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