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