@aderis-erp/cli 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/access-groups.d.ts +8 -0
- package/dist/commands/access-groups.js +56 -8
- package/dist/commands/account-transaction-allocations.d.ts +8 -0
- package/dist/commands/account-transaction-allocations.js +52 -5
- package/dist/commands/account-transactions.d.ts +8 -0
- package/dist/commands/account-transactions.js +55 -7
- package/dist/commands/accounts.d.ts +8 -0
- package/dist/commands/accounts.js +52 -5
- package/dist/commands/agent-platform.d.ts +8 -0
- package/dist/commands/agent-platform.js +52 -5
- package/dist/commands/agent-runs.d.ts +8 -0
- package/dist/commands/agent-runs.js +52 -5
- package/dist/commands/analytics.d.ts +8 -0
- package/dist/commands/analytics.js +52 -5
- package/dist/commands/api-keys.d.ts +8 -0
- package/dist/commands/api-keys.js +52 -5
- package/dist/commands/async-jobs.d.ts +8 -0
- package/dist/commands/async-jobs.js +52 -5
- package/dist/commands/audit-log.d.ts +8 -0
- package/dist/commands/audit-log.js +52 -5
- package/dist/commands/bank-accounts.d.ts +8 -0
- package/dist/commands/bank-accounts.js +52 -5
- package/dist/commands/bank-integrations.d.ts +8 -0
- package/dist/commands/bank-integrations.js +52 -5
- package/dist/commands/business-partners.d.ts +9 -0
- package/dist/commands/business-partners.js +66 -9
- package/dist/commands/chat.d.ts +8 -0
- package/dist/commands/chat.js +52 -5
- package/dist/commands/credit-card-accounts.d.ts +8 -0
- package/dist/commands/credit-card-accounts.js +52 -5
- package/dist/commands/delivery-notes.d.ts +8 -0
- package/dist/commands/delivery-notes.js +52 -5
- package/dist/commands/dunning-configs.d.ts +8 -0
- package/dist/commands/dunning-configs.js +52 -5
- package/dist/commands/dunning-reminders.d.ts +8 -0
- package/dist/commands/dunning-reminders.js +52 -5
- package/dist/commands/dunning-runs.d.ts +8 -0
- package/dist/commands/dunning-runs.js +52 -5
- package/dist/commands/email-transactions.d.ts +8 -0
- package/dist/commands/email-transactions.js +52 -5
- package/dist/commands/employees.d.ts +8 -0
- package/dist/commands/employees.js +52 -5
- package/dist/commands/entity-configurations.d.ts +8 -0
- package/dist/commands/entity-configurations.js +52 -5
- package/dist/commands/event-processor-mappings.d.ts +8 -0
- package/dist/commands/event-processor-mappings.js +52 -5
- package/dist/commands/files.d.ts +8 -0
- package/dist/commands/files.js +53 -6
- package/dist/commands/health.d.ts +8 -0
- package/dist/commands/health.js +52 -5
- package/dist/commands/imports.d.ts +8 -0
- package/dist/commands/imports.js +53 -8
- package/dist/commands/inbox.d.ts +8 -0
- package/dist/commands/inbox.js +53 -7
- package/dist/commands/integration-identities.d.ts +8 -0
- package/dist/commands/integration-identities.js +52 -5
- package/dist/commands/integrations.d.ts +8 -0
- package/dist/commands/integrations.js +52 -5
- package/dist/commands/item-categories.d.ts +8 -0
- package/dist/commands/item-categories.js +52 -5
- package/dist/commands/items.d.ts +8 -0
- package/dist/commands/items.js +52 -5
- package/dist/commands/journal-lines.d.ts +8 -0
- package/dist/commands/journal-lines.js +52 -5
- package/dist/commands/journals.d.ts +8 -0
- package/dist/commands/journals.js +52 -5
- package/dist/commands/ledgers.d.ts +8 -0
- package/dist/commands/ledgers.js +57 -9
- package/dist/commands/my-account.d.ts +8 -0
- package/dist/commands/my-account.js +52 -5
- package/dist/commands/office-locations.d.ts +8 -0
- package/dist/commands/office-locations.js +52 -5
- package/dist/commands/payment-methods.d.ts +8 -0
- package/dist/commands/payment-methods.js +52 -5
- package/dist/commands/payment-runs.d.ts +8 -0
- package/dist/commands/payment-runs.js +54 -6
- package/dist/commands/payment-terms.d.ts +8 -0
- package/dist/commands/payment-terms.js +52 -5
- package/dist/commands/payments.d.ts +8 -0
- package/dist/commands/payments.js +52 -5
- package/dist/commands/payroll-runs.d.ts +8 -0
- package/dist/commands/payroll-runs.js +52 -5
- package/dist/commands/permissions.d.ts +8 -0
- package/dist/commands/permissions.js +52 -5
- package/dist/commands/price-lists.d.ts +8 -0
- package/dist/commands/price-lists.js +52 -5
- package/dist/commands/processor-mappings.d.ts +8 -0
- package/dist/commands/processor-mappings.js +52 -5
- package/dist/commands/processors.d.ts +8 -0
- package/dist/commands/processors.js +52 -5
- package/dist/commands/purchase-order-types.d.ts +8 -0
- package/dist/commands/purchase-order-types.js +52 -5
- package/dist/commands/purchase-orders.d.ts +8 -0
- package/dist/commands/purchase-orders.js +52 -5
- package/dist/commands/reports.d.ts +8 -0
- package/dist/commands/reports.js +52 -5
- package/dist/commands/roles.d.ts +8 -0
- package/dist/commands/roles.js +52 -5
- package/dist/commands/salary-types.d.ts +8 -0
- package/dist/commands/salary-types.js +52 -5
- package/dist/commands/sales-invoices.d.ts +10 -0
- package/dist/commands/sales-invoices.js +62 -6
- package/dist/commands/sales-orders.d.ts +8 -0
- package/dist/commands/sales-orders.js +52 -5
- package/dist/commands/saved-views.d.ts +8 -0
- package/dist/commands/saved-views.js +52 -5
- package/dist/commands/scheduled-processor-mappings.d.ts +8 -0
- package/dist/commands/scheduled-processor-mappings.js +52 -5
- package/dist/commands/schedules.d.ts +8 -0
- package/dist/commands/schedules.js +52 -5
- package/dist/commands/support/end.d.ts +9 -0
- package/dist/commands/support/end.js +29 -0
- package/dist/commands/support/start.d.ts +14 -0
- package/dist/commands/support/start.js +50 -0
- package/dist/commands/support/status.d.ts +10 -0
- package/dist/commands/support/status.js +45 -0
- package/dist/commands/support/tenants.d.ts +10 -0
- package/dist/commands/support/tenants.js +39 -0
- package/dist/commands/tags.d.ts +8 -0
- package/dist/commands/tags.js +56 -8
- package/dist/commands/tax-codes.d.ts +8 -0
- package/dist/commands/tax-codes.js +52 -5
- package/dist/commands/tax-matrix.d.ts +8 -0
- package/dist/commands/tax-matrix.js +52 -5
- package/dist/commands/templates.d.ts +8 -0
- package/dist/commands/templates.js +52 -5
- package/dist/commands/tenants.d.ts +8 -0
- package/dist/commands/tenants.js +52 -5
- package/dist/commands/tools.d.ts +8 -0
- package/dist/commands/tools.js +52 -5
- package/dist/commands/users.d.ts +8 -0
- package/dist/commands/users.js +52 -5
- package/dist/commands/vat-declarations.d.ts +8 -0
- package/dist/commands/vat-declarations.js +52 -5
- package/dist/commands/vendor-invoices.d.ts +9 -0
- package/dist/commands/vendor-invoices.js +60 -8
- package/dist/commands/webhooks.d.ts +8 -0
- package/dist/commands/webhooks.js +52 -5
- package/dist/commands/workflows.d.ts +8 -0
- package/dist/commands/workflows.js +52 -5
- package/dist/lib/auth/constants.d.ts +12 -0
- package/dist/lib/auth/constants.js +12 -0
- package/dist/lib/auth/index.d.ts +11 -1
- package/dist/lib/auth/index.js +90 -2
- package/dist/lib/auth/keycloak-provider.d.ts +22 -0
- package/dist/lib/auth/keycloak-provider.js +108 -3
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.js +10 -0
- package/oclif.manifest.json +640 -216
- package/package.json +4 -1
- package/dist/commands/tag-configurations.d.ts +0 -39
- package/dist/commands/tag-configurations.js +0 -1155
package/dist/commands/tags.js
CHANGED
|
@@ -6,13 +6,14 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "journal-coverage"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/tags', summary: 'Get all tags with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/tags', summary: 'Create a new tag', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tags', summary: 'Create a new tag', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['rules'] },
|
|
13
13
|
'get': { method: 'GET', path: '/v1/tags/{id}', summary: 'Get a tag by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/tags/{id}', summary: 'Update a tag', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
14
|
+
'update': { method: 'PATCH', path: '/v1/tags/{id}', summary: 'Update a tag', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['rules'] },
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/tags/{id}', summary: 'Delete a tag', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
+
'journal-coverage': { method: 'GET', path: '/v1/tags/{id}/journal-coverage', summary: 'How much of the journal-line amount in scope carries one of the tags below this tag', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
17
|
};
|
|
17
18
|
export default class Tags extends Command {
|
|
18
19
|
static description = 'Manage tags';
|
|
@@ -45,6 +46,7 @@ export default class Tags extends Command {
|
|
|
45
46
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
47
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
47
48
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
49
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
48
50
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
51
|
};
|
|
50
52
|
async run() {
|
|
@@ -337,9 +339,15 @@ export default class Tags extends Command {
|
|
|
337
339
|
}
|
|
338
340
|
catch { /* keep as string */ }
|
|
339
341
|
}
|
|
340
|
-
//
|
|
342
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
343
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
344
|
+
// dropping it silently let a script read one page as the whole result
|
|
345
|
+
// (AderisERP/product#61).
|
|
346
|
+
let envelope;
|
|
341
347
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
342
|
-
|
|
348
|
+
const page = output;
|
|
349
|
+
envelope = page;
|
|
350
|
+
output = page.data;
|
|
343
351
|
}
|
|
344
352
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
345
353
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -356,12 +364,24 @@ export default class Tags extends Command {
|
|
|
356
364
|
output = this.sanitizeOutput(output);
|
|
357
365
|
}
|
|
358
366
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
359
|
-
if (
|
|
367
|
+
if (envelope)
|
|
368
|
+
this.warnShortPage(envelope, flags.limit);
|
|
369
|
+
if (flags.csv || flags.output === 'csv') {
|
|
360
370
|
this.printCsv(output, fieldList);
|
|
361
|
-
|
|
371
|
+
}
|
|
372
|
+
else if (flags.table || flags.output === 'table') {
|
|
362
373
|
this.printTable(output, fieldList);
|
|
363
|
-
|
|
374
|
+
if (envelope)
|
|
375
|
+
this.printPageSummary(envelope);
|
|
376
|
+
}
|
|
377
|
+
else if (envelope && flags.meta) {
|
|
378
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
379
|
+
// a bare array so existing scripts are unaffected.
|
|
380
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
381
|
+
}
|
|
382
|
+
else {
|
|
364
383
|
this.log(JSON.stringify(output, null, 2));
|
|
384
|
+
}
|
|
365
385
|
}
|
|
366
386
|
catch (error) {
|
|
367
387
|
if (error instanceof ApiError) {
|
|
@@ -990,6 +1010,34 @@ export default class Tags extends Command {
|
|
|
990
1010
|
return `\$${op}`;
|
|
991
1011
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
992
1012
|
}
|
|
1013
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1014
|
+
printPageSummary(envelope) {
|
|
1015
|
+
const meta = envelope.meta;
|
|
1016
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1017
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1018
|
+
this.log(`
|
|
1019
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1020
|
+
}
|
|
1021
|
+
for (const total of envelope.totals ?? []) {
|
|
1022
|
+
const { currency, ...sums } = total;
|
|
1023
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1024
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1029
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1030
|
+
*/
|
|
1031
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1032
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1033
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1034
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1035
|
+
return;
|
|
1036
|
+
const pages = envelope.meta?.totalPages;
|
|
1037
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1038
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1039
|
+
`);
|
|
1040
|
+
}
|
|
993
1041
|
sanitizeOutput(data) {
|
|
994
1042
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
995
1043
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -23,6 +23,7 @@ export default class TaxCodes extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class TaxCodes extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|
|
@@ -48,6 +48,7 @@ export default class TaxCodes extends Command {
|
|
|
48
48
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
49
49
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
50
50
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
51
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
51
52
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
52
53
|
};
|
|
53
54
|
async run() {
|
|
@@ -340,9 +341,15 @@ export default class TaxCodes extends Command {
|
|
|
340
341
|
}
|
|
341
342
|
catch { /* keep as string */ }
|
|
342
343
|
}
|
|
343
|
-
//
|
|
344
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
345
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
346
|
+
// dropping it silently let a script read one page as the whole result
|
|
347
|
+
// (AderisERP/product#61).
|
|
348
|
+
let envelope;
|
|
344
349
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
345
|
-
|
|
350
|
+
const page = output;
|
|
351
|
+
envelope = page;
|
|
352
|
+
output = page.data;
|
|
346
353
|
}
|
|
347
354
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
348
355
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -359,12 +366,24 @@ export default class TaxCodes extends Command {
|
|
|
359
366
|
output = this.sanitizeOutput(output);
|
|
360
367
|
}
|
|
361
368
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
362
|
-
if (
|
|
369
|
+
if (envelope)
|
|
370
|
+
this.warnShortPage(envelope, flags.limit);
|
|
371
|
+
if (flags.csv || flags.output === 'csv') {
|
|
363
372
|
this.printCsv(output, fieldList);
|
|
364
|
-
|
|
373
|
+
}
|
|
374
|
+
else if (flags.table || flags.output === 'table') {
|
|
365
375
|
this.printTable(output, fieldList);
|
|
366
|
-
|
|
376
|
+
if (envelope)
|
|
377
|
+
this.printPageSummary(envelope);
|
|
378
|
+
}
|
|
379
|
+
else if (envelope && flags.meta) {
|
|
380
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
381
|
+
// a bare array so existing scripts are unaffected.
|
|
382
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
367
385
|
this.log(JSON.stringify(output, null, 2));
|
|
386
|
+
}
|
|
368
387
|
}
|
|
369
388
|
catch (error) {
|
|
370
389
|
if (error instanceof ApiError) {
|
|
@@ -993,6 +1012,34 @@ export default class TaxCodes extends Command {
|
|
|
993
1012
|
return `\$${op}`;
|
|
994
1013
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
995
1014
|
}
|
|
1015
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1016
|
+
printPageSummary(envelope) {
|
|
1017
|
+
const meta = envelope.meta;
|
|
1018
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1019
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1020
|
+
this.log(`
|
|
1021
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1022
|
+
}
|
|
1023
|
+
for (const total of envelope.totals ?? []) {
|
|
1024
|
+
const { currency, ...sums } = total;
|
|
1025
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1026
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1031
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1032
|
+
*/
|
|
1033
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1034
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1035
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1036
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1037
|
+
return;
|
|
1038
|
+
const pages = envelope.meta?.totalPages;
|
|
1039
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1040
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1041
|
+
`);
|
|
1042
|
+
}
|
|
996
1043
|
sanitizeOutput(data) {
|
|
997
1044
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
998
1045
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -23,6 +23,7 @@ export default class TaxMatrix extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class TaxMatrix extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|
|
@@ -45,6 +45,7 @@ export default class TaxMatrix extends Command {
|
|
|
45
45
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
46
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
47
47
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
48
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
48
49
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
50
|
};
|
|
50
51
|
async run() {
|
|
@@ -337,9 +338,15 @@ export default class TaxMatrix extends Command {
|
|
|
337
338
|
}
|
|
338
339
|
catch { /* keep as string */ }
|
|
339
340
|
}
|
|
340
|
-
//
|
|
341
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
342
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
343
|
+
// dropping it silently let a script read one page as the whole result
|
|
344
|
+
// (AderisERP/product#61).
|
|
345
|
+
let envelope;
|
|
341
346
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
342
|
-
|
|
347
|
+
const page = output;
|
|
348
|
+
envelope = page;
|
|
349
|
+
output = page.data;
|
|
343
350
|
}
|
|
344
351
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
345
352
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -356,12 +363,24 @@ export default class TaxMatrix extends Command {
|
|
|
356
363
|
output = this.sanitizeOutput(output);
|
|
357
364
|
}
|
|
358
365
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
359
|
-
if (
|
|
366
|
+
if (envelope)
|
|
367
|
+
this.warnShortPage(envelope, flags.limit);
|
|
368
|
+
if (flags.csv || flags.output === 'csv') {
|
|
360
369
|
this.printCsv(output, fieldList);
|
|
361
|
-
|
|
370
|
+
}
|
|
371
|
+
else if (flags.table || flags.output === 'table') {
|
|
362
372
|
this.printTable(output, fieldList);
|
|
363
|
-
|
|
373
|
+
if (envelope)
|
|
374
|
+
this.printPageSummary(envelope);
|
|
375
|
+
}
|
|
376
|
+
else if (envelope && flags.meta) {
|
|
377
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
378
|
+
// a bare array so existing scripts are unaffected.
|
|
379
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
364
382
|
this.log(JSON.stringify(output, null, 2));
|
|
383
|
+
}
|
|
365
384
|
}
|
|
366
385
|
catch (error) {
|
|
367
386
|
if (error instanceof ApiError) {
|
|
@@ -990,6 +1009,34 @@ export default class TaxMatrix extends Command {
|
|
|
990
1009
|
return `\$${op}`;
|
|
991
1010
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
992
1011
|
}
|
|
1012
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1013
|
+
printPageSummary(envelope) {
|
|
1014
|
+
const meta = envelope.meta;
|
|
1015
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1016
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1017
|
+
this.log(`
|
|
1018
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1019
|
+
}
|
|
1020
|
+
for (const total of envelope.totals ?? []) {
|
|
1021
|
+
const { currency, ...sums } = total;
|
|
1022
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1023
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1028
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1029
|
+
*/
|
|
1030
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1031
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1032
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1033
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1034
|
+
return;
|
|
1035
|
+
const pages = envelope.meta?.totalPages;
|
|
1036
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1037
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1038
|
+
`);
|
|
1039
|
+
}
|
|
993
1040
|
sanitizeOutput(data) {
|
|
994
1041
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
995
1042
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -23,6 +23,7 @@ export default class Templates extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class Templates extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|
|
@@ -48,6 +48,7 @@ export default class Templates extends Command {
|
|
|
48
48
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
49
49
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
50
50
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
51
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
51
52
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
52
53
|
};
|
|
53
54
|
async run() {
|
|
@@ -340,9 +341,15 @@ export default class Templates extends Command {
|
|
|
340
341
|
}
|
|
341
342
|
catch { /* keep as string */ }
|
|
342
343
|
}
|
|
343
|
-
//
|
|
344
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
345
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
346
|
+
// dropping it silently let a script read one page as the whole result
|
|
347
|
+
// (AderisERP/product#61).
|
|
348
|
+
let envelope;
|
|
344
349
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
345
|
-
|
|
350
|
+
const page = output;
|
|
351
|
+
envelope = page;
|
|
352
|
+
output = page.data;
|
|
346
353
|
}
|
|
347
354
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
348
355
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -359,12 +366,24 @@ export default class Templates extends Command {
|
|
|
359
366
|
output = this.sanitizeOutput(output);
|
|
360
367
|
}
|
|
361
368
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
362
|
-
if (
|
|
369
|
+
if (envelope)
|
|
370
|
+
this.warnShortPage(envelope, flags.limit);
|
|
371
|
+
if (flags.csv || flags.output === 'csv') {
|
|
363
372
|
this.printCsv(output, fieldList);
|
|
364
|
-
|
|
373
|
+
}
|
|
374
|
+
else if (flags.table || flags.output === 'table') {
|
|
365
375
|
this.printTable(output, fieldList);
|
|
366
|
-
|
|
376
|
+
if (envelope)
|
|
377
|
+
this.printPageSummary(envelope);
|
|
378
|
+
}
|
|
379
|
+
else if (envelope && flags.meta) {
|
|
380
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
381
|
+
// a bare array so existing scripts are unaffected.
|
|
382
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
367
385
|
this.log(JSON.stringify(output, null, 2));
|
|
386
|
+
}
|
|
368
387
|
}
|
|
369
388
|
catch (error) {
|
|
370
389
|
if (error instanceof ApiError) {
|
|
@@ -993,6 +1012,34 @@ export default class Templates extends Command {
|
|
|
993
1012
|
return `\$${op}`;
|
|
994
1013
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
995
1014
|
}
|
|
1015
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1016
|
+
printPageSummary(envelope) {
|
|
1017
|
+
const meta = envelope.meta;
|
|
1018
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1019
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1020
|
+
this.log(`
|
|
1021
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1022
|
+
}
|
|
1023
|
+
for (const total of envelope.totals ?? []) {
|
|
1024
|
+
const { currency, ...sums } = total;
|
|
1025
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1026
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1031
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1032
|
+
*/
|
|
1033
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1034
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1035
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1036
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1037
|
+
return;
|
|
1038
|
+
const pages = envelope.meta?.totalPages;
|
|
1039
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1040
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1041
|
+
`);
|
|
1042
|
+
}
|
|
996
1043
|
sanitizeOutput(data) {
|
|
997
1044
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
998
1045
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -23,6 +23,7 @@ export default class Tenants extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class Tenants extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|
package/dist/commands/tenants.js
CHANGED
|
@@ -48,6 +48,7 @@ export default class Tenants extends Command {
|
|
|
48
48
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
49
49
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
50
50
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
51
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
51
52
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
52
53
|
};
|
|
53
54
|
async run() {
|
|
@@ -340,9 +341,15 @@ export default class Tenants extends Command {
|
|
|
340
341
|
}
|
|
341
342
|
catch { /* keep as string */ }
|
|
342
343
|
}
|
|
343
|
-
//
|
|
344
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
345
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
346
|
+
// dropping it silently let a script read one page as the whole result
|
|
347
|
+
// (AderisERP/product#61).
|
|
348
|
+
let envelope;
|
|
344
349
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
345
|
-
|
|
350
|
+
const page = output;
|
|
351
|
+
envelope = page;
|
|
352
|
+
output = page.data;
|
|
346
353
|
}
|
|
347
354
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
348
355
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -359,12 +366,24 @@ export default class Tenants extends Command {
|
|
|
359
366
|
output = this.sanitizeOutput(output);
|
|
360
367
|
}
|
|
361
368
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
362
|
-
if (
|
|
369
|
+
if (envelope)
|
|
370
|
+
this.warnShortPage(envelope, flags.limit);
|
|
371
|
+
if (flags.csv || flags.output === 'csv') {
|
|
363
372
|
this.printCsv(output, fieldList);
|
|
364
|
-
|
|
373
|
+
}
|
|
374
|
+
else if (flags.table || flags.output === 'table') {
|
|
365
375
|
this.printTable(output, fieldList);
|
|
366
|
-
|
|
376
|
+
if (envelope)
|
|
377
|
+
this.printPageSummary(envelope);
|
|
378
|
+
}
|
|
379
|
+
else if (envelope && flags.meta) {
|
|
380
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
381
|
+
// a bare array so existing scripts are unaffected.
|
|
382
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
367
385
|
this.log(JSON.stringify(output, null, 2));
|
|
386
|
+
}
|
|
368
387
|
}
|
|
369
388
|
catch (error) {
|
|
370
389
|
if (error instanceof ApiError) {
|
|
@@ -993,6 +1012,34 @@ export default class Tenants extends Command {
|
|
|
993
1012
|
return `\$${op}`;
|
|
994
1013
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
995
1014
|
}
|
|
1015
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1016
|
+
printPageSummary(envelope) {
|
|
1017
|
+
const meta = envelope.meta;
|
|
1018
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1019
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1020
|
+
this.log(`
|
|
1021
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1022
|
+
}
|
|
1023
|
+
for (const total of envelope.totals ?? []) {
|
|
1024
|
+
const { currency, ...sums } = total;
|
|
1025
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1026
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
1030
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1031
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1032
|
+
*/
|
|
1033
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1034
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1035
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1036
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1037
|
+
return;
|
|
1038
|
+
const pages = envelope.meta?.totalPages;
|
|
1039
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1040
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1041
|
+
`);
|
|
1042
|
+
}
|
|
996
1043
|
sanitizeOutput(data) {
|
|
997
1044
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
998
1045
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
package/dist/commands/tools.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export default class Tools extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class Tools extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|