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