From e2a0cddd9fc80d5dc629d1194f61dbc216fbcc2d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:26:04 +0000 Subject: [PATCH 1/6] Initial plan From 3a2e2398edf68780bc4b698648af4656d02b06a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:30:20 +0000 Subject: [PATCH 2/6] Add comprehensive use cases and examples to documentation Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com> --- README.md | 342 +++++++++++++++++++++++++++++++++-- packages/fints-cli/README.md | 110 +++++++++++ packages/fints/README.md | 154 +++++++++++++++- 3 files changed, 584 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index c93064e..c0a363d 100644 --- a/README.md +++ b/README.md @@ -55,35 +55,269 @@ yarn lint ## 🚀 Quick Start +### Minimal Configuration + ```typescript import { PinTanClient } from "fints-lib"; +// Create a client with minimal required configuration const client = new PinTanClient({ - url: "https://example.com/fints", - name: "username", - pin: "12345", - blz: "12345678", + url: "https://banking.example.com/fints", // Your bank's FinTS URL + name: "username", // Your banking username + pin: "12345", // Your banking PIN + blz: "12345678", // Bank code (BLZ/Bankleitzahl) }); -// List accounts +// List all accounts const accounts = await client.accounts(); console.log(accounts); +``` + +### CLI Quick Start + +```bash +# Install globally +npm install -g fints-lib-cli + +# List your accounts +fints-lib list-accounts \ + --url https://banking.example.com/fints \ + -n username \ + -p 12345 \ + -b 12345678 +``` + +## 📖 Common Use Cases + +### 1. Check Account Balance + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +// Get all accounts +const accounts = await client.accounts(); + +// Check balance for first account +const balance = await client.balance(accounts[0]); +console.log(`Account: ${accounts[0].iban}`); +console.log(`Balance: ${balance.value.value} ${balance.value.currency}`); +``` + +**CLI Example:** +```bash +fints-lib get-balance \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + -i DE89370400440532013000 +``` + +### 2. Fetch Recent Transactions + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); + +// Fetch last 30 days of transactions +const startDate = new Date(); +startDate.setDate(startDate.getDate() - 30); +const endDate = new Date(); -// Fetch statements -const startDate = new Date("2024-01-01"); -const endDate = new Date("2024-12-31"); const statements = await client.statements(accounts[0], startDate, endDate); -console.log(statements); + +// Process transactions +statements.forEach(statement => { + console.log(`Date: ${statement.date}`); + statement.transactions.forEach(transaction => { + console.log(` ${transaction.descriptionStructured?.bookingText || 'Transaction'}`); + console.log(` Amount: ${transaction.amount} ${transaction.currency}`); + console.log(` Purpose: ${transaction.purpose || 'N/A'}`); + }); +}); ``` -For CLI usage: +**CLI Example:** +```bash +# Fetch transactions for the last 30 days +fints-lib fetch-transactions \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + -i DE89370400440532013000 \ + -s 2024-11-01 -e 2024-12-01 \ + --json > transactions.json +``` + +### 3. SEPA Credit Transfer (Send Money) + +```typescript +import { PinTanClient, TanRequiredError } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); +const myAccount = accounts[0]; + +// Prepare transfer +const transfer = { + debtorName: "John Doe", + creditor: { + name: "Recipient Name", + iban: "DE44500105175407324931", + bic: "INGDDEFFXXX", // Optional for transfers within SEPA + }, + amount: 50.00, + remittanceInformation: "Payment for invoice #12345", +}; + +try { + // Initiate transfer + const result = await client.creditTransfer(myAccount, transfer); + console.log("Transfer successful:", result.taskId); +} catch (error) { + if (error instanceof TanRequiredError) { + // TAN is required - get TAN from user + const tan = "123456"; // Get from user input or TAN app + + const result = await client.completeCreditTransfer( + error.dialog, + error.transactionReference, + tan, + error.creditTransferSubmission + ); + console.log("Transfer completed:", result.taskId); + } else { + throw error; + } +} +``` + +**CLI Example:** +```bash +# Transfer money (will prompt for TAN if required) +fints-lib submit-credit-transfer \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + --account-iban DE89370400440532013000 \ + --debtor-name "John Doe" \ + --creditor-name "Recipient Name" \ + --creditor-iban DE44500105175407324931 \ + --amount 50.00 \ + --remittance "Payment for invoice #12345" +``` + +### 4. SEPA Direct Debit (Collect Money) + +```typescript +import { PinTanClient, TanRequiredError } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); +const myAccount = accounts[0]; + +// Prepare direct debit +const debit = { + creditorName: "My Company GmbH", + creditorId: "DE98ZZZ09999999999", // Your SEPA creditor ID + debtor: { + name: "Customer Name", + iban: "DE02120300000000202051", + }, + amount: 99.99, + mandateId: "MANDATE-2024-001", + mandateSignatureDate: new Date("2024-01-15"), + requestedCollectionDate: new Date("2024-12-15"), + remittanceInformation: "Monthly subscription fee", +}; + +try { + const result = await client.directDebit(myAccount, debit); + console.log("Direct debit submitted:", result.taskId); +} catch (error) { + if (error instanceof TanRequiredError) { + const tan = "123456"; // Get from user + + const result = await client.completeDirectDebit( + error.dialog, + error.transactionReference, + tan, + error.directDebitSubmission + ); + console.log("Direct debit completed:", result.taskId); + } else { + throw error; + } +} +``` +**CLI Example:** ```bash -# List accounts -fints-lib list-accounts --url https://example.com/fints -n username -p 12345 -b 12345678 +fints-lib submit-direct-debit \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + --account-iban DE89370400440532013000 \ + --creditor-name "My Company GmbH" \ + --creditor-id DE98ZZZ09999999999 \ + --debtor-name "Customer Name" \ + --debtor-iban DE02120300000000202051 \ + --amount 99.99 \ + --mandate-id MANDATE-2024-001 \ + --mandate-date 2024-01-15 \ + --collection-date 2024-12-15 \ + --remittance "Monthly subscription fee" +``` -# Fetch transactions -fints-lib fetch-transactions --url https://example.com/fints -n username -p 12345 -b 12345678 -i DE111234567800000001 -s 2024-01-01 -e 2024-12-31 +### 5. List Multiple Accounts and Their Balances + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +// Get all accounts with balances +const accounts = await client.accounts(); + +for (const account of accounts) { + console.log(`\n${account.accountName || 'Account'} (${account.iban})`); + console.log(` Type: ${account.accountType || 'N/A'}`); + + try { + const balance = await client.balance(account); + console.log(` Balance: ${balance.value.value} ${balance.value.currency}`); + console.log(` Available: ${balance.availableBalance?.value || 'N/A'}`); + } catch (error) { + console.log(` Balance: Unable to fetch`); + } +} ``` > Before using any FinTS library you have to register your application with Die Deutsche Kreditwirtschaft in order to get your registration number. Note that this process can take several weeks. First you receive your registration number after a couple days, but then you have to wait anywhere between 0 and 8+ weeks for the registration to reach your bank's server. If you have multiple banks, it probably reaches them at different times. @@ -135,6 +369,86 @@ const badClient = new PinTanClient({ If you discover a security vulnerability, please report it privately via GitHub's "Security" tab instead of opening a public issue. +## 💡 Tips and Troubleshooting + +### Finding Your Bank's FinTS URL + +You can find your bank's FinTS endpoint URL in this community database: +- [FinTS Institute Database](https://github.com/jhermsmeier/fints-institute-db) + +### Common Issues + +**Authentication Errors:** +- Verify your username, PIN, and BLZ are correct +- Some banks require you to enable FinTS/HBCI access in your online banking settings +- Check if your bank requires registration (see registration note below) + +**TAN Requirements:** +- Many operations (transfers, direct debits) require TAN authentication +- Use try-catch with `TanRequiredError` to handle TAN challenges properly +- Some banks require TAN even for login - handle with `completeLogin()` + +**Timeout Issues:** +- Increase the timeout value in client configuration: + ```typescript + const client = new PinTanClient({ + // ... other config + timeout: 60000, // 60 seconds + maxRetries: 5, + }); + ``` + +**Date Range Queries:** +- Not all banks support all date ranges - some limit how far back you can query +- Use shorter date ranges if you experience timeouts or errors + +### Best Practices + +1. **Always use environment variables for credentials:** + ```typescript + const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, + }); + ``` + +2. **Enable debug mode during development:** + ```typescript + const client = new PinTanClient({ + // ... credentials + debug: process.env.NODE_ENV === 'development', + }); + ``` + +3. **Handle errors gracefully:** + ```typescript + import { FinTSError, TanRequiredError, PinError } from "fints-lib"; + + try { + const accounts = await client.accounts(); + } catch (error) { + if (error instanceof TanRequiredError) { + // Handle TAN requirement + } else if (error instanceof PinError) { + // Handle PIN error + } else if (error instanceof FinTSError) { + console.error(`FinTS Error [${error.code}]: ${error.message}`); + } + } + ``` + +4. **Close dialogs when done:** + ```typescript + const dialog = await client.startDialog(); + try { + // ... perform operations + } finally { + await dialog.end(); + } + ``` + ## Mentions FinTS is a complex and old format and this library wouldn't have been possible without the great work of: diff --git a/packages/fints-cli/README.md b/packages/fints-cli/README.md index f2efe65..02b14f9 100644 --- a/packages/fints-cli/README.md +++ b/packages/fints-cli/README.md @@ -215,6 +215,116 @@ fints-lib submit-direct-debit --url https://example.com/fints --name username -- --mandate-date 2022-01-10 --collection-date 2022-01-15 --remittance "Invoice 0815" ``` +## Practical CLI Examples + +### Using Environment Variables + +To avoid typing credentials repeatedly, create a shell script or use environment variables: + +```bash +#!/bin/bash +# save as fints-env.sh + +export FINTS_URL="https://banking.example.com/fints" +export FINTS_USER="myusername" +export FINTS_PIN="mypin" +export FINTS_BLZ="12345678" + +# Then use in commands: +# source fints-env.sh +# fints-lib list-accounts --url $FINTS_URL -n $FINTS_USER -p $FINTS_PIN -b $FINTS_BLZ +``` + +### Quick Account Overview + +```bash +# Get account list in JSON format for processing +fints-lib list-accounts \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + --json | jq '.' + +# Check balance for a specific account +fints-lib get-balance \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + -i DE89370400440532013000 \ + --json | jq '.value' +``` + +### Export Transactions to File + +```bash +# Fetch and save transactions as JSON +fints-lib fetch-transactions \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + -i DE89370400440532013000 \ + -s 2024-01-01 -e 2024-12-31 \ + --json > transactions-2024.json + +# Or save verbose output to text file +fints-lib fetch-transactions \ + --url https://banking.example.com/fints \ + -n username -p 12345 -b 12345678 \ + -i DE89370400440532013000 \ + -s 2024-01-01 -e 2024-12-31 \ + --verbose > transactions-2024.txt +``` + +### Monthly Statement Automation + +```bash +#!/bin/bash +# monthly-statement.sh - Fetch last month's transactions + +# Calculate date range for last month +START_DATE=$(date -d "last month" +%Y-%m-01) +END_DATE=$(date -d "-1 day $(date +%Y-%m-01)" +%Y-%m-%d) + +# Fetch transactions +fints-lib fetch-transactions \ + --url "$FINTS_URL" \ + -n "$FINTS_USER" \ + -p "$FINTS_PIN" \ + -b "$FINTS_BLZ" \ + -i "$ACCOUNT_IBAN" \ + -s "$START_DATE" \ + -e "$END_DATE" \ + --json > "statement-$(date -d 'last month' +%Y-%m).json" + +echo "Statement saved for $(date -d 'last month' +%B %Y)" +``` + +### Check Multiple Accounts + +```bash +#!/bin/bash +# check-all-accounts.sh + +ACCOUNTS=("DE89370400440532013000" "DE89370400440532013001") + +for IBAN in "${ACCOUNTS[@]}"; do + echo "Checking account: $IBAN" + fints-lib get-balance \ + --url "$FINTS_URL" \ + -n "$FINTS_USER" \ + -p "$FINTS_PIN" \ + -b "$FINTS_BLZ" \ + -i "$IBAN" \ + --json | jq -r '" Balance: \(.value.value) \(.value.currency)"' + echo "" +done +``` + +## Tips + +- Use `--json` flag for machine-readable output that can be processed with tools like `jq` +- Use `--verbose` flag to see detailed information during development +- Use `--debug` flag to troubleshoot connection issues +- Store credentials in environment variables or a secure credential manager +- Use the [FinTS Institute Database](https://github.com/jhermsmeier/fints-institute-db) to find your bank's URL + ## Resources - [Database of banks with their URLs](https://github.com/jhermsmeier/fints-institute-db) diff --git a/packages/fints/README.md b/packages/fints/README.md index 2e4bb17..caedb41 100644 --- a/packages/fints/README.md +++ b/packages/fints/README.md @@ -15,26 +15,56 @@ npm install fints-lib yarn add fints-lib ``` -## Example +## Quick Start Examples + +### Basic Account Information ```typescript import { PinTanClient } from "fints-lib"; -const startDate = new Date("2018-08-10T12:00:00Z"); -const endDate = new Date("2018-10-10T12:00:00Z"); +// Initialize client with minimal configuration +const client = new PinTanClient({ + url: "https://banking.example.com/fints", + name: "username", + pin: "12345", + blz: "12345678", +}); + +// Fetch all accounts +const accounts = await client.accounts(); +console.log(accounts); // List of all accounts + +// Get balance for first account +const balance = await client.balance(accounts[0]); +console.log(`Balance: ${balance.value.value} ${balance.value.currency}`); +``` + +### Fetching Transactions + +```typescript +import { PinTanClient } from "fints-lib"; const client = new PinTanClient({ - url: "https://example.com/fints", + url: "https://banking.example.com/fints", name: "username", - pin: 12345, - blz: 12345678, + pin: "12345", + blz: "12345678", }); const accounts = await client.accounts(); -console.info(accounts); // List of all accounts. +// Fetch transactions for a date range +const startDate = new Date("2024-01-01"); +const endDate = new Date("2024-12-31"); const statements = await client.statements(accounts[0], startDate, endDate); -console.info(statements); // List of all statements with transactions in specified date range. + +// Process transactions +statements.forEach(statement => { + console.log(`Statement from ${statement.date}`); + statement.transactions.forEach(tx => { + console.log(` ${tx.descriptionStructured?.bookingText}: ${tx.amount} ${tx.currency}`); + }); +}); ``` @@ -164,6 +194,114 @@ const formatted = formatErrorCode("9942", "Custom message"); // Output: "[9942] PIN falsch - Custom message" ``` +## Common Use Cases + +### Check Account Balance + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); + +// Get balance for a specific account +const balance = await client.balance(accounts[0]); +console.log(`Current Balance: ${balance.value.value} ${balance.value.currency}`); +console.log(`Available: ${balance.availableBalance?.value || 'N/A'}`); +``` + +### Fetch Recent Transactions + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); + +// Get transactions from the last 30 days +const endDate = new Date(); +const startDate = new Date(); +startDate.setDate(startDate.getDate() - 30); + +const statements = await client.statements(accounts[0], startDate, endDate); + +statements.forEach(statement => { + console.log(`\nStatement: ${statement.date}`); + statement.transactions.forEach(tx => { + const booking = tx.descriptionStructured?.bookingText || 'Transaction'; + const purpose = tx.purpose || ''; + console.log(` ${booking}: ${tx.amount} ${tx.currency}`); + if (purpose) console.log(` Purpose: ${purpose}`); + }); +}); +``` + +### List All Accounts with Details + +```typescript +import { PinTanClient } from "fints-lib"; + +const client = new PinTanClient({ + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, +}); + +const accounts = await client.accounts(); + +console.log(`Found ${accounts.length} account(s):\n`); + +for (const account of accounts) { + console.log(`Account: ${account.accountName || 'Unnamed'}`); + console.log(` IBAN: ${account.iban}`); + console.log(` Type: ${account.accountType || 'N/A'}`); + console.log(` Number: ${account.accountNumber || 'N/A'}`); + + try { + const balance = await client.balance(account); + console.log(` Balance: ${balance.value.value} ${balance.value.currency}`); + } catch (error) { + console.log(` Balance: Unable to retrieve`); + } + console.log(); +} +``` + +### Working with Environment Variables (Recommended) + +```typescript +import { PinTanClient } from "fints-lib"; + +// Load credentials from environment variables +const client = new PinTanClient({ + url: process.env.FINTS_URL!, + name: process.env.FINTS_USERNAME!, + pin: process.env.FINTS_PIN!, + blz: process.env.FINTS_BLZ!, + debug: process.env.NODE_ENV === "development", +}); + +// Example .env file: +// FINTS_URL=https://banking.example.com/fints +// FINTS_USERNAME=myusername +// FINTS_PIN=mypin +// FINTS_BLZ=12345678 +// NODE_ENV=development +``` + ## Missing From 921c72a9d7d3b84d9bf744584fd2c9256d1d717c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:33:57 +0000 Subject: [PATCH 3/6] Fix documentation formatting and improve clarity based on code review Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com> --- README.md | 12 ++++++------ packages/fints-cli/README.md | 3 +++ packages/fints/README.md | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c0a363d..bbf4841 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ console.log(`Account: ${accounts[0].iban}`); console.log(`Balance: ${balance.value.value} ${balance.value.currency}`); ``` -**CLI Example:** +**CLI Example** ```bash fints-lib get-balance \ --url https://banking.example.com/fints \ @@ -150,14 +150,14 @@ statements.forEach(statement => { }); ``` -**CLI Example:** +**CLI Example** ```bash -# Fetch transactions for the last 30 days +# Fetch transactions for a date range fints-lib fetch-transactions \ --url https://banking.example.com/fints \ -n username -p 12345 -b 12345678 \ -i DE89370400440532013000 \ - -s 2024-11-01 -e 2024-12-01 \ + -s 2024-01-01 -e 2024-12-31 \ --json > transactions.json ``` @@ -210,7 +210,7 @@ try { } ``` -**CLI Example:** +**CLI Example** ```bash # Transfer money (will prompt for TAN if required) fints-lib submit-credit-transfer \ @@ -274,7 +274,7 @@ try { } ``` -**CLI Example:** +**CLI Example** ```bash fints-lib submit-direct-debit \ --url https://banking.example.com/fints \ diff --git a/packages/fints-cli/README.md b/packages/fints-cli/README.md index 02b14f9..f5a22a8 100644 --- a/packages/fints-cli/README.md +++ b/packages/fints-cli/README.md @@ -277,6 +277,9 @@ fints-lib fetch-transactions \ ```bash #!/bin/bash # monthly-statement.sh - Fetch last month's transactions +# Note: This script uses GNU date syntax. On macOS, install GNU coreutils: +# brew install coreutils +# and use 'gdate' instead of 'date' # Calculate date range for last month START_DATE=$(date -d "last month" +%Y-%m-01) diff --git a/packages/fints/README.md b/packages/fints/README.md index caedb41..9a847f6 100644 --- a/packages/fints/README.md +++ b/packages/fints/README.md @@ -285,7 +285,7 @@ for (const account of accounts) { ```typescript import { PinTanClient } from "fints-lib"; -// Load credentials from environment variables +// Create client using environment variables for credentials const client = new PinTanClient({ url: process.env.FINTS_URL!, name: process.env.FINTS_USERNAME!, From 6d95ecda575c4f2ee39a112d30152fcf08fa899e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:35:00 +0000 Subject: [PATCH 4/6] Add cross-platform date command examples for macOS and Linux Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com> --- packages/fints-cli/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/fints-cli/README.md b/packages/fints-cli/README.md index f5a22a8..8924059 100644 --- a/packages/fints-cli/README.md +++ b/packages/fints-cli/README.md @@ -277,14 +277,17 @@ fints-lib fetch-transactions \ ```bash #!/bin/bash # monthly-statement.sh - Fetch last month's transactions -# Note: This script uses GNU date syntax. On macOS, install GNU coreutils: -# brew install coreutils -# and use 'gdate' instead of 'date' # Calculate date range for last month +# For Linux (GNU date): START_DATE=$(date -d "last month" +%Y-%m-01) END_DATE=$(date -d "-1 day $(date +%Y-%m-01)" +%Y-%m-%d) +# For macOS (BSD date), use: +# START_DATE=$(date -v-1m +%Y-%m-01) +# END_DATE=$(date -v-1d -v1d +%Y-%m-%d) +# Or install GNU coreutils (brew install coreutils) and use 'gdate' + # Fetch transactions fints-lib fetch-transactions \ --url "$FINTS_URL" \ @@ -294,9 +297,9 @@ fints-lib fetch-transactions \ -i "$ACCOUNT_IBAN" \ -s "$START_DATE" \ -e "$END_DATE" \ - --json > "statement-$(date -d 'last month' +%Y-%m).json" + --json > "statement-$(date +%Y-%m).json" -echo "Statement saved for $(date -d 'last month' +%B %Y)" +echo "Statement saved for period: $START_DATE to $END_DATE" ``` ### Check Multiple Accounts From 651a89fe6ad2af5bd7bf28b9d2f1d1e421062634 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:37:00 +0000 Subject: [PATCH 5/6] Fix macOS date command and add environment variable validation Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com> --- packages/fints-cli/README.md | 2 +- packages/fints/README.md | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/fints-cli/README.md b/packages/fints-cli/README.md index 8924059..0324bd0 100644 --- a/packages/fints-cli/README.md +++ b/packages/fints-cli/README.md @@ -285,7 +285,7 @@ END_DATE=$(date -d "-1 day $(date +%Y-%m-01)" +%Y-%m-%d) # For macOS (BSD date), use: # START_DATE=$(date -v-1m +%Y-%m-01) -# END_DATE=$(date -v-1d -v1d +%Y-%m-%d) +# END_DATE=$(date -v1d -v-1m -v-1d +%Y-%m-%d) # Or install GNU coreutils (brew install coreutils) and use 'gdate' # Fetch transactions diff --git a/packages/fints/README.md b/packages/fints/README.md index 9a847f6..d055f7b 100644 --- a/packages/fints/README.md +++ b/packages/fints/README.md @@ -286,11 +286,17 @@ for (const account of accounts) { import { PinTanClient } from "fints-lib"; // Create client using environment variables for credentials +// Ensure environment variables are set before running +if (!process.env.FINTS_URL || !process.env.FINTS_USERNAME || + !process.env.FINTS_PIN || !process.env.FINTS_BLZ) { + throw new Error("Required environment variables are not set"); +} + const client = new PinTanClient({ - url: process.env.FINTS_URL!, - name: process.env.FINTS_USERNAME!, - pin: process.env.FINTS_PIN!, - blz: process.env.FINTS_BLZ!, + url: process.env.FINTS_URL, + name: process.env.FINTS_USERNAME, + pin: process.env.FINTS_PIN, + blz: process.env.FINTS_BLZ, debug: process.env.NODE_ENV === "development", }); From 1fa4c2fe5891bd44a1c0c7eb97273b210212f1d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 28 Dec 2025 23:38:40 +0000 Subject: [PATCH 6/6] Fix date arithmetic and simplify macOS date commands Co-authored-by: larsdecker <1968186+larsdecker@users.noreply.github.com> --- README.md | 3 +-- packages/fints-cli/README.md | 8 ++++---- packages/fints/README.md | 3 +-- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bbf4841..f8d9924 100644 --- a/README.md +++ b/README.md @@ -133,9 +133,8 @@ const client = new PinTanClient({ const accounts = await client.accounts(); // Fetch last 30 days of transactions -const startDate = new Date(); -startDate.setDate(startDate.getDate() - 30); const endDate = new Date(); +const startDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000); const statements = await client.statements(accounts[0], startDate, endDate); diff --git a/packages/fints-cli/README.md b/packages/fints-cli/README.md index 0324bd0..a91d86c 100644 --- a/packages/fints-cli/README.md +++ b/packages/fints-cli/README.md @@ -283,10 +283,10 @@ fints-lib fetch-transactions \ START_DATE=$(date -d "last month" +%Y-%m-01) END_DATE=$(date -d "-1 day $(date +%Y-%m-01)" +%Y-%m-%d) -# For macOS (BSD date), use: -# START_DATE=$(date -v-1m +%Y-%m-01) -# END_DATE=$(date -v1d -v-1m -v-1d +%Y-%m-%d) -# Or install GNU coreutils (brew install coreutils) and use 'gdate' +# For macOS (BSD date), install GNU coreutils and use 'gdate': +# brew install coreutils +# START_DATE=$(gdate -d "last month" +%Y-%m-01) +# END_DATE=$(gdate -d "-1 day $(gdate +%Y-%m-01)" +%Y-%m-%d) # Fetch transactions fints-lib fetch-transactions \ diff --git a/packages/fints/README.md b/packages/fints/README.md index d055f7b..d9d7021 100644 --- a/packages/fints/README.md +++ b/packages/fints/README.md @@ -232,8 +232,7 @@ const accounts = await client.accounts(); // Get transactions from the last 30 days const endDate = new Date(); -const startDate = new Date(); -startDate.setDate(startDate.getDate() - 30); +const startDate = new Date(endDate.getTime() - 30 * 24 * 60 * 60 * 1000); const statements = await client.statements(accounts[0], startDate, endDate);