@aderis-erp/cli 1.1.1 → 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 +54 -6
- 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 +64 -7
- 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 +52 -5
- 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 +52 -5
- 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/tags.d.ts +8 -0
- package/dist/commands/tags.js +52 -5
- 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/oclif.manifest.json +433 -10
- package/package.json +1 -1
|
@@ -46,6 +46,7 @@ export default class AgentRuns extends Command {
|
|
|
46
46
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
47
47
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
48
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' }),
|
|
49
50
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
50
51
|
};
|
|
51
52
|
async run() {
|
|
@@ -338,9 +339,15 @@ export default class AgentRuns extends Command {
|
|
|
338
339
|
}
|
|
339
340
|
catch { /* keep as string */ }
|
|
340
341
|
}
|
|
341
|
-
//
|
|
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;
|
|
342
347
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
343
|
-
|
|
348
|
+
const page = output;
|
|
349
|
+
envelope = page;
|
|
350
|
+
output = page.data;
|
|
344
351
|
}
|
|
345
352
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
346
353
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -357,12 +364,24 @@ export default class AgentRuns extends Command {
|
|
|
357
364
|
output = this.sanitizeOutput(output);
|
|
358
365
|
}
|
|
359
366
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
360
|
-
if (
|
|
367
|
+
if (envelope)
|
|
368
|
+
this.warnShortPage(envelope, flags.limit);
|
|
369
|
+
if (flags.csv || flags.output === 'csv') {
|
|
361
370
|
this.printCsv(output, fieldList);
|
|
362
|
-
|
|
371
|
+
}
|
|
372
|
+
else if (flags.table || flags.output === 'table') {
|
|
363
373
|
this.printTable(output, fieldList);
|
|
364
|
-
|
|
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 {
|
|
365
383
|
this.log(JSON.stringify(output, null, 2));
|
|
384
|
+
}
|
|
366
385
|
}
|
|
367
386
|
catch (error) {
|
|
368
387
|
if (error instanceof ApiError) {
|
|
@@ -991,6 +1010,34 @@ export default class AgentRuns extends Command {
|
|
|
991
1010
|
return `\$${op}`;
|
|
992
1011
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
993
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
|
+
}
|
|
994
1041
|
sanitizeOutput(data) {
|
|
995
1042
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
996
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 Analytics 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 Analytics 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;
|
|
@@ -36,6 +36,7 @@ export default class Analytics extends Command {
|
|
|
36
36
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
37
37
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
38
38
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
39
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
39
40
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
40
41
|
};
|
|
41
42
|
async run() {
|
|
@@ -328,9 +329,15 @@ export default class Analytics extends Command {
|
|
|
328
329
|
}
|
|
329
330
|
catch { /* keep as string */ }
|
|
330
331
|
}
|
|
331
|
-
//
|
|
332
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
333
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
334
|
+
// dropping it silently let a script read one page as the whole result
|
|
335
|
+
// (AderisERP/product#61).
|
|
336
|
+
let envelope;
|
|
332
337
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
333
|
-
|
|
338
|
+
const page = output;
|
|
339
|
+
envelope = page;
|
|
340
|
+
output = page.data;
|
|
334
341
|
}
|
|
335
342
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
336
343
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -347,12 +354,24 @@ export default class Analytics extends Command {
|
|
|
347
354
|
output = this.sanitizeOutput(output);
|
|
348
355
|
}
|
|
349
356
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
350
|
-
if (
|
|
357
|
+
if (envelope)
|
|
358
|
+
this.warnShortPage(envelope, flags.limit);
|
|
359
|
+
if (flags.csv || flags.output === 'csv') {
|
|
351
360
|
this.printCsv(output, fieldList);
|
|
352
|
-
|
|
361
|
+
}
|
|
362
|
+
else if (flags.table || flags.output === 'table') {
|
|
353
363
|
this.printTable(output, fieldList);
|
|
354
|
-
|
|
364
|
+
if (envelope)
|
|
365
|
+
this.printPageSummary(envelope);
|
|
366
|
+
}
|
|
367
|
+
else if (envelope && flags.meta) {
|
|
368
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
369
|
+
// a bare array so existing scripts are unaffected.
|
|
370
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
355
373
|
this.log(JSON.stringify(output, null, 2));
|
|
374
|
+
}
|
|
356
375
|
}
|
|
357
376
|
catch (error) {
|
|
358
377
|
if (error instanceof ApiError) {
|
|
@@ -981,6 +1000,34 @@ export default class Analytics extends Command {
|
|
|
981
1000
|
return `\$${op}`;
|
|
982
1001
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
983
1002
|
}
|
|
1003
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1004
|
+
printPageSummary(envelope) {
|
|
1005
|
+
const meta = envelope.meta;
|
|
1006
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1007
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1008
|
+
this.log(`
|
|
1009
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1010
|
+
}
|
|
1011
|
+
for (const total of envelope.totals ?? []) {
|
|
1012
|
+
const { currency, ...sums } = total;
|
|
1013
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1014
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
/**
|
|
1018
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1019
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1020
|
+
*/
|
|
1021
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1022
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1023
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1024
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1025
|
+
return;
|
|
1026
|
+
const pages = envelope.meta?.totalPages;
|
|
1027
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1028
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1029
|
+
`);
|
|
1030
|
+
}
|
|
984
1031
|
sanitizeOutput(data) {
|
|
985
1032
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
986
1033
|
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 ApiKeys 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 ApiKeys 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;
|
|
@@ -41,6 +41,7 @@ export default class ApiKeys extends Command {
|
|
|
41
41
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
42
42
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
43
43
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
44
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
44
45
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
45
46
|
};
|
|
46
47
|
async run() {
|
|
@@ -333,9 +334,15 @@ export default class ApiKeys extends Command {
|
|
|
333
334
|
}
|
|
334
335
|
catch { /* keep as string */ }
|
|
335
336
|
}
|
|
336
|
-
//
|
|
337
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
338
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
339
|
+
// dropping it silently let a script read one page as the whole result
|
|
340
|
+
// (AderisERP/product#61).
|
|
341
|
+
let envelope;
|
|
337
342
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
338
|
-
|
|
343
|
+
const page = output;
|
|
344
|
+
envelope = page;
|
|
345
|
+
output = page.data;
|
|
339
346
|
}
|
|
340
347
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
341
348
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -352,12 +359,24 @@ export default class ApiKeys extends Command {
|
|
|
352
359
|
output = this.sanitizeOutput(output);
|
|
353
360
|
}
|
|
354
361
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
355
|
-
if (
|
|
362
|
+
if (envelope)
|
|
363
|
+
this.warnShortPage(envelope, flags.limit);
|
|
364
|
+
if (flags.csv || flags.output === 'csv') {
|
|
356
365
|
this.printCsv(output, fieldList);
|
|
357
|
-
|
|
366
|
+
}
|
|
367
|
+
else if (flags.table || flags.output === 'table') {
|
|
358
368
|
this.printTable(output, fieldList);
|
|
359
|
-
|
|
369
|
+
if (envelope)
|
|
370
|
+
this.printPageSummary(envelope);
|
|
371
|
+
}
|
|
372
|
+
else if (envelope && flags.meta) {
|
|
373
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
374
|
+
// a bare array so existing scripts are unaffected.
|
|
375
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
360
378
|
this.log(JSON.stringify(output, null, 2));
|
|
379
|
+
}
|
|
361
380
|
}
|
|
362
381
|
catch (error) {
|
|
363
382
|
if (error instanceof ApiError) {
|
|
@@ -986,6 +1005,34 @@ export default class ApiKeys extends Command {
|
|
|
986
1005
|
return `\$${op}`;
|
|
987
1006
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
988
1007
|
}
|
|
1008
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1009
|
+
printPageSummary(envelope) {
|
|
1010
|
+
const meta = envelope.meta;
|
|
1011
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1012
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1013
|
+
this.log(`
|
|
1014
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1015
|
+
}
|
|
1016
|
+
for (const total of envelope.totals ?? []) {
|
|
1017
|
+
const { currency, ...sums } = total;
|
|
1018
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1019
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1024
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1025
|
+
*/
|
|
1026
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1027
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1028
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1029
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1030
|
+
return;
|
|
1031
|
+
const pages = envelope.meta?.totalPages;
|
|
1032
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1033
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1034
|
+
`);
|
|
1035
|
+
}
|
|
989
1036
|
sanitizeOutput(data) {
|
|
990
1037
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
991
1038
|
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 AsyncJobs 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 AsyncJobs 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;
|
|
@@ -49,6 +49,7 @@ export default class AsyncJobs extends Command {
|
|
|
49
49
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
50
50
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
51
51
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
52
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
52
53
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
53
54
|
};
|
|
54
55
|
async run() {
|
|
@@ -341,9 +342,15 @@ export default class AsyncJobs extends Command {
|
|
|
341
342
|
}
|
|
342
343
|
catch { /* keep as string */ }
|
|
343
344
|
}
|
|
344
|
-
//
|
|
345
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
346
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
347
|
+
// dropping it silently let a script read one page as the whole result
|
|
348
|
+
// (AderisERP/product#61).
|
|
349
|
+
let envelope;
|
|
345
350
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
346
|
-
|
|
351
|
+
const page = output;
|
|
352
|
+
envelope = page;
|
|
353
|
+
output = page.data;
|
|
347
354
|
}
|
|
348
355
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
349
356
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -360,12 +367,24 @@ export default class AsyncJobs extends Command {
|
|
|
360
367
|
output = this.sanitizeOutput(output);
|
|
361
368
|
}
|
|
362
369
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
363
|
-
if (
|
|
370
|
+
if (envelope)
|
|
371
|
+
this.warnShortPage(envelope, flags.limit);
|
|
372
|
+
if (flags.csv || flags.output === 'csv') {
|
|
364
373
|
this.printCsv(output, fieldList);
|
|
365
|
-
|
|
374
|
+
}
|
|
375
|
+
else if (flags.table || flags.output === 'table') {
|
|
366
376
|
this.printTable(output, fieldList);
|
|
367
|
-
|
|
377
|
+
if (envelope)
|
|
378
|
+
this.printPageSummary(envelope);
|
|
379
|
+
}
|
|
380
|
+
else if (envelope && flags.meta) {
|
|
381
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
382
|
+
// a bare array so existing scripts are unaffected.
|
|
383
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
368
386
|
this.log(JSON.stringify(output, null, 2));
|
|
387
|
+
}
|
|
369
388
|
}
|
|
370
389
|
catch (error) {
|
|
371
390
|
if (error instanceof ApiError) {
|
|
@@ -994,6 +1013,34 @@ export default class AsyncJobs extends Command {
|
|
|
994
1013
|
return `\$${op}`;
|
|
995
1014
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
996
1015
|
}
|
|
1016
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1017
|
+
printPageSummary(envelope) {
|
|
1018
|
+
const meta = envelope.meta;
|
|
1019
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1020
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1021
|
+
this.log(`
|
|
1022
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1023
|
+
}
|
|
1024
|
+
for (const total of envelope.totals ?? []) {
|
|
1025
|
+
const { currency, ...sums } = total;
|
|
1026
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1027
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1032
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1033
|
+
*/
|
|
1034
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1035
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1036
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1037
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1038
|
+
return;
|
|
1039
|
+
const pages = envelope.meta?.totalPages;
|
|
1040
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1041
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1042
|
+
`);
|
|
1043
|
+
}
|
|
997
1044
|
sanitizeOutput(data) {
|
|
998
1045
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
999
1046
|
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 AuditLog 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 AuditLog 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;
|
|
@@ -39,6 +39,7 @@ export default class AuditLog extends Command {
|
|
|
39
39
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
40
40
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
41
41
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
42
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
42
43
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
43
44
|
};
|
|
44
45
|
async run() {
|
|
@@ -331,9 +332,15 @@ export default class AuditLog extends Command {
|
|
|
331
332
|
}
|
|
332
333
|
catch { /* keep as string */ }
|
|
333
334
|
}
|
|
334
|
-
//
|
|
335
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
336
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
337
|
+
// dropping it silently let a script read one page as the whole result
|
|
338
|
+
// (AderisERP/product#61).
|
|
339
|
+
let envelope;
|
|
335
340
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
336
|
-
|
|
341
|
+
const page = output;
|
|
342
|
+
envelope = page;
|
|
343
|
+
output = page.data;
|
|
337
344
|
}
|
|
338
345
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
339
346
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -350,12 +357,24 @@ export default class AuditLog extends Command {
|
|
|
350
357
|
output = this.sanitizeOutput(output);
|
|
351
358
|
}
|
|
352
359
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
353
|
-
if (
|
|
360
|
+
if (envelope)
|
|
361
|
+
this.warnShortPage(envelope, flags.limit);
|
|
362
|
+
if (flags.csv || flags.output === 'csv') {
|
|
354
363
|
this.printCsv(output, fieldList);
|
|
355
|
-
|
|
364
|
+
}
|
|
365
|
+
else if (flags.table || flags.output === 'table') {
|
|
356
366
|
this.printTable(output, fieldList);
|
|
357
|
-
|
|
367
|
+
if (envelope)
|
|
368
|
+
this.printPageSummary(envelope);
|
|
369
|
+
}
|
|
370
|
+
else if (envelope && flags.meta) {
|
|
371
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
372
|
+
// a bare array so existing scripts are unaffected.
|
|
373
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
358
376
|
this.log(JSON.stringify(output, null, 2));
|
|
377
|
+
}
|
|
359
378
|
}
|
|
360
379
|
catch (error) {
|
|
361
380
|
if (error instanceof ApiError) {
|
|
@@ -984,6 +1003,34 @@ export default class AuditLog extends Command {
|
|
|
984
1003
|
return `\$${op}`;
|
|
985
1004
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
986
1005
|
}
|
|
1006
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1007
|
+
printPageSummary(envelope) {
|
|
1008
|
+
const meta = envelope.meta;
|
|
1009
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1010
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1011
|
+
this.log(`
|
|
1012
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1013
|
+
}
|
|
1014
|
+
for (const total of envelope.totals ?? []) {
|
|
1015
|
+
const { currency, ...sums } = total;
|
|
1016
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1017
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1022
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1023
|
+
*/
|
|
1024
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1025
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1026
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1027
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1028
|
+
return;
|
|
1029
|
+
const pages = envelope.meta?.totalPages;
|
|
1030
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1031
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1032
|
+
`);
|
|
1033
|
+
}
|
|
987
1034
|
sanitizeOutput(data) {
|
|
988
1035
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
989
1036
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -25,6 +25,7 @@ export default class BankAccounts extends Command {
|
|
|
25
25
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
26
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
28
29
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
30
|
};
|
|
30
31
|
run(): Promise<void>;
|
|
@@ -33,6 +34,13 @@ export default class BankAccounts extends Command {
|
|
|
33
34
|
private runCamt053Import;
|
|
34
35
|
private runNestedImport;
|
|
35
36
|
private parseFilterValue;
|
|
37
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
38
|
+
private printPageSummary;
|
|
39
|
+
/**
|
|
40
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
41
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
42
|
+
*/
|
|
43
|
+
private warnShortPage;
|
|
36
44
|
private sanitizeOutput;
|
|
37
45
|
private getColumns;
|
|
38
46
|
private getValue;
|
|
@@ -60,6 +60,7 @@ export default class BankAccounts extends Command {
|
|
|
60
60
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
61
61
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
62
62
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
63
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
63
64
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
64
65
|
};
|
|
65
66
|
async run() {
|
|
@@ -352,9 +353,15 @@ export default class BankAccounts extends Command {
|
|
|
352
353
|
}
|
|
353
354
|
catch { /* keep as string */ }
|
|
354
355
|
}
|
|
355
|
-
//
|
|
356
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
357
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
358
|
+
// dropping it silently let a script read one page as the whole result
|
|
359
|
+
// (AderisERP/product#61).
|
|
360
|
+
let envelope;
|
|
356
361
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
357
|
-
|
|
362
|
+
const page = output;
|
|
363
|
+
envelope = page;
|
|
364
|
+
output = page.data;
|
|
358
365
|
}
|
|
359
366
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
360
367
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -371,12 +378,24 @@ export default class BankAccounts extends Command {
|
|
|
371
378
|
output = this.sanitizeOutput(output);
|
|
372
379
|
}
|
|
373
380
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
374
|
-
if (
|
|
381
|
+
if (envelope)
|
|
382
|
+
this.warnShortPage(envelope, flags.limit);
|
|
383
|
+
if (flags.csv || flags.output === 'csv') {
|
|
375
384
|
this.printCsv(output, fieldList);
|
|
376
|
-
|
|
385
|
+
}
|
|
386
|
+
else if (flags.table || flags.output === 'table') {
|
|
377
387
|
this.printTable(output, fieldList);
|
|
378
|
-
|
|
388
|
+
if (envelope)
|
|
389
|
+
this.printPageSummary(envelope);
|
|
390
|
+
}
|
|
391
|
+
else if (envelope && flags.meta) {
|
|
392
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
393
|
+
// a bare array so existing scripts are unaffected.
|
|
394
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
379
397
|
this.log(JSON.stringify(output, null, 2));
|
|
398
|
+
}
|
|
380
399
|
}
|
|
381
400
|
catch (error) {
|
|
382
401
|
if (error instanceof ApiError) {
|
|
@@ -1005,6 +1024,34 @@ export default class BankAccounts extends Command {
|
|
|
1005
1024
|
return `\$${op}`;
|
|
1006
1025
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
1007
1026
|
}
|
|
1027
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1028
|
+
printPageSummary(envelope) {
|
|
1029
|
+
const meta = envelope.meta;
|
|
1030
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1031
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1032
|
+
this.log(`
|
|
1033
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1034
|
+
}
|
|
1035
|
+
for (const total of envelope.totals ?? []) {
|
|
1036
|
+
const { currency, ...sums } = total;
|
|
1037
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1038
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1043
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1044
|
+
*/
|
|
1045
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1046
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1047
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1048
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1049
|
+
return;
|
|
1050
|
+
const pages = envelope.meta?.totalPages;
|
|
1051
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1052
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1053
|
+
`);
|
|
1054
|
+
}
|
|
1008
1055
|
sanitizeOutput(data) {
|
|
1009
1056
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1010
1057
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|