feat(transactions): add full pagination support with older_id and custom count parameters
This commit is contained in:
12
changelog.md
12
changelog.md
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## 2025-07-25 - 4.1.0 - feat(transactions)
|
||||
Enhanced transaction pagination support with full control over historical data retrieval
|
||||
|
||||
- Added full `IBunqPaginationOptions` support to `getTransactions()` method
|
||||
- Now supports `older_id` for paginating backwards through historical transactions
|
||||
- Supports custom `count` parameter (defaults to 200)
|
||||
- Maintains backward compatibility - passing a number is still treated as `newer_id`
|
||||
- Only includes pagination parameters that are explicitly set (not false/undefined)
|
||||
- Added `example.pagination.ts` demonstrating various pagination patterns
|
||||
|
||||
This enhancement allows banking applications to properly fetch and paginate through historical transaction data using both `newer_id` and `older_id` parameters.
|
||||
|
||||
## 2025-07-25 - 4.0.0 - BREAKING CHANGE(core)
|
||||
Complete stateless architecture - consumers now have full control over session persistence
|
||||
|
||||
|
128
example.pagination.ts
Normal file
128
example.pagination.ts
Normal file
@@ -0,0 +1,128 @@
|
||||
import { BunqAccount, IBunqPaginationOptions } from './ts/index.js';
|
||||
|
||||
// Example demonstrating the enhanced pagination support in getTransactions
|
||||
|
||||
async function demonstratePagination() {
|
||||
const bunq = new BunqAccount({
|
||||
apiKey: 'your-api-key',
|
||||
deviceName: 'Pagination Demo',
|
||||
environment: 'PRODUCTION',
|
||||
});
|
||||
|
||||
// Initialize and get session
|
||||
const sessionData = await bunq.init();
|
||||
|
||||
// Get accounts
|
||||
const { accounts } = await bunq.getAccounts();
|
||||
const account = accounts[0];
|
||||
|
||||
// Example 1: Get most recent transactions (default behavior)
|
||||
const recentTransactions = await account.getTransactions();
|
||||
console.log(`Got ${recentTransactions.length} recent transactions`);
|
||||
|
||||
// Example 2: Get transactions with custom count
|
||||
const smallBatch = await account.getTransactions({ count: 10 });
|
||||
console.log(`Got ${smallBatch.length} transactions with custom count`);
|
||||
|
||||
// Example 3: Get older transactions using older_id
|
||||
if (recentTransactions.length > 0) {
|
||||
const oldestTransaction = recentTransactions[recentTransactions.length - 1];
|
||||
const olderTransactions = await account.getTransactions({
|
||||
count: 50,
|
||||
older_id: oldestTransaction.id
|
||||
});
|
||||
console.log(`Got ${olderTransactions.length} older transactions`);
|
||||
}
|
||||
|
||||
// Example 4: Get newer transactions using newer_id
|
||||
if (recentTransactions.length > 0) {
|
||||
const newestTransaction = recentTransactions[0];
|
||||
const newerTransactions = await account.getTransactions({
|
||||
count: 20,
|
||||
newer_id: newestTransaction.id
|
||||
});
|
||||
console.log(`Got ${newerTransactions.length} newer transactions`);
|
||||
}
|
||||
|
||||
// Example 5: Backward compatibility - using number as newer_id
|
||||
const backwardCompatible = await account.getTransactions(12345);
|
||||
console.log(`Backward compatible call returned ${backwardCompatible.length} transactions`);
|
||||
|
||||
// Example 6: Paginating through all historical transactions
|
||||
async function getAllTransactions(account: any): Promise<any[]> {
|
||||
const allTransactions: any[] = [];
|
||||
let lastTransactionId: number | false = false;
|
||||
let hasMore = true;
|
||||
|
||||
while (hasMore) {
|
||||
const options: IBunqPaginationOptions = {
|
||||
count: 200,
|
||||
older_id: lastTransactionId
|
||||
};
|
||||
|
||||
const batch = await account.getTransactions(options);
|
||||
|
||||
if (batch.length === 0) {
|
||||
hasMore = false;
|
||||
} else {
|
||||
allTransactions.push(...batch);
|
||||
lastTransactionId = batch[batch.length - 1].id;
|
||||
console.log(`Fetched ${batch.length} transactions, total: ${allTransactions.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
return allTransactions;
|
||||
}
|
||||
|
||||
// Example 7: Getting transactions between two dates
|
||||
async function getTransactionsBetweenDates(
|
||||
account: any,
|
||||
startDate: Date,
|
||||
endDate: Date
|
||||
): Promise<any[]> {
|
||||
const transactions: any[] = [];
|
||||
let olderId: number | false = false;
|
||||
let keepFetching = true;
|
||||
|
||||
while (keepFetching) {
|
||||
const batch = await account.getTransactions({
|
||||
count: 200,
|
||||
older_id: olderId
|
||||
});
|
||||
|
||||
if (batch.length === 0) {
|
||||
keepFetching = false;
|
||||
break;
|
||||
}
|
||||
|
||||
for (const transaction of batch) {
|
||||
const transactionDate = new Date(transaction.created);
|
||||
|
||||
if (transactionDate >= startDate && transactionDate <= endDate) {
|
||||
transactions.push(transaction);
|
||||
} else if (transactionDate < startDate) {
|
||||
// We've gone past our date range
|
||||
keepFetching = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
olderId = batch[batch.length - 1].id;
|
||||
}
|
||||
|
||||
return transactions;
|
||||
}
|
||||
|
||||
// Usage
|
||||
const lastMonth = new Date();
|
||||
lastMonth.setMonth(lastMonth.getMonth() - 1);
|
||||
const transactionsLastMonth = await getTransactionsBetweenDates(
|
||||
account,
|
||||
lastMonth,
|
||||
new Date()
|
||||
);
|
||||
console.log(`Found ${transactionsLastMonth.length} transactions in the last month`);
|
||||
}
|
||||
|
||||
// Run the demo
|
||||
demonstratePagination().catch(console.error);
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@apiclient.xyz/bunq",
|
||||
"version": "4.0.1",
|
||||
"version": "4.1.0",
|
||||
"private": false,
|
||||
"description": "A full-featured TypeScript/JavaScript client for the bunq API",
|
||||
"type": "module",
|
||||
|
@@ -111,18 +111,41 @@ export class BunqMonetaryAccount {
|
||||
|
||||
/**
|
||||
* gets all transactions on this account
|
||||
* @param options - Pagination options or a number for backward compatibility (treated as newer_id)
|
||||
*/
|
||||
public async getTransactions(startingIdArg: number | false = false): Promise<BunqTransaction[]> {
|
||||
const paginationOptions: IBunqPaginationOptions = {
|
||||
count: 200,
|
||||
newer_id: startingIdArg,
|
||||
public async getTransactions(options?: IBunqPaginationOptions | number | false): Promise<BunqTransaction[]> {
|
||||
let paginationOptions: IBunqPaginationOptions = {};
|
||||
|
||||
// Backward compatibility: if a number or false is passed, treat it as newer_id
|
||||
if (typeof options === 'number' || options === false) {
|
||||
paginationOptions.newer_id = options;
|
||||
} else if (options) {
|
||||
paginationOptions = { ...options };
|
||||
}
|
||||
|
||||
// Set default count if not specified
|
||||
if (!paginationOptions.count) {
|
||||
paginationOptions.count = 200;
|
||||
}
|
||||
|
||||
// Build clean pagination object - only include properties that are not false/undefined
|
||||
const cleanPaginationOptions: IBunqPaginationOptions = {
|
||||
count: paginationOptions.count,
|
||||
};
|
||||
|
||||
if (paginationOptions.newer_id !== undefined && paginationOptions.newer_id !== false) {
|
||||
cleanPaginationOptions.newer_id = paginationOptions.newer_id;
|
||||
}
|
||||
|
||||
if (paginationOptions.older_id !== undefined && paginationOptions.older_id !== false) {
|
||||
cleanPaginationOptions.older_id = paginationOptions.older_id;
|
||||
}
|
||||
|
||||
await this.bunqAccountRef.apiContext.ensureValidSession();
|
||||
|
||||
const response = await this.bunqAccountRef.getHttpClient().list(
|
||||
`/v1/user/${this.bunqAccountRef.userId}/monetary-account/${this.id}/payment`,
|
||||
paginationOptions
|
||||
cleanPaginationOptions
|
||||
);
|
||||
|
||||
const transactionsArray: BunqTransaction[] = [];
|
||||
|
Reference in New Issue
Block a user