@aderis-erp/cli 1.0.15 → 1.0.17
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/README.md +30 -8
- package/dist/commands/access-groups.d.ts +0 -1
- package/dist/commands/access-groups.js +5 -61
- package/dist/commands/account-transaction-allocations.d.ts +0 -1
- package/dist/commands/account-transaction-allocations.js +5 -61
- package/dist/commands/account-transactions.d.ts +0 -1
- package/dist/commands/account-transactions.js +9 -63
- package/dist/commands/accounts.d.ts +0 -1
- package/dist/commands/accounts.js +5 -61
- package/dist/commands/agent-platform.d.ts +0 -1
- package/dist/commands/agent-platform.js +5 -61
- package/dist/commands/analytics.d.ts +0 -1
- package/dist/commands/analytics.js +5 -61
- package/dist/commands/api-keys.d.ts +39 -0
- package/dist/commands/api-keys.js +1117 -0
- package/dist/commands/audit-log.d.ts +0 -1
- package/dist/commands/audit-log.js +5 -61
- package/dist/commands/auth/login.d.ts +9 -0
- package/dist/commands/auth/login.js +73 -20
- package/dist/commands/auth/logout.d.ts +4 -0
- package/dist/commands/auth/logout.js +4 -0
- package/dist/commands/auth/status.js +26 -17
- package/dist/commands/auth/tenant.js +3 -6
- package/dist/commands/auth.d.ts +0 -1
- package/dist/commands/auth.js +5 -34
- package/dist/commands/bank-accounts.d.ts +0 -1
- package/dist/commands/bank-accounts.js +5 -61
- package/dist/commands/bank-integrations.d.ts +0 -1
- package/dist/commands/bank-integrations.js +5 -61
- package/dist/commands/business-partners.d.ts +1 -1
- package/dist/commands/business-partners.js +14 -63
- package/dist/commands/chat.d.ts +0 -1
- package/dist/commands/chat.js +5 -61
- package/dist/commands/config/add.d.ts +3 -0
- package/dist/commands/config/add.js +34 -16
- package/dist/commands/config/current.js +3 -0
- package/dist/commands/config/list.js +3 -0
- package/dist/commands/credit-card-accounts.d.ts +0 -1
- package/dist/commands/credit-card-accounts.js +5 -61
- package/dist/commands/delivery-notes.d.ts +0 -1
- package/dist/commands/delivery-notes.js +7 -63
- package/dist/commands/dunning-configs.d.ts +0 -1
- package/dist/commands/dunning-configs.js +5 -61
- package/dist/commands/dunning-reminders.d.ts +0 -1
- package/dist/commands/dunning-reminders.js +5 -61
- package/dist/commands/dunning-runs.d.ts +0 -1
- package/dist/commands/dunning-runs.js +5 -61
- package/dist/commands/email-transactions.d.ts +0 -1
- package/dist/commands/email-transactions.js +5 -61
- package/dist/commands/employees.d.ts +0 -1
- package/dist/commands/employees.js +5 -61
- package/dist/commands/entity-configurations.d.ts +0 -1
- package/dist/commands/entity-configurations.js +5 -61
- package/dist/commands/event-processor-mappings.d.ts +0 -1
- package/dist/commands/event-processor-mappings.js +5 -61
- package/dist/commands/files.d.ts +0 -1
- package/dist/commands/files.js +5 -61
- package/dist/commands/health.d.ts +0 -1
- package/dist/commands/health.js +5 -61
- package/dist/commands/inbox.d.ts +0 -1
- package/dist/commands/inbox.js +5 -61
- package/dist/commands/integrations.d.ts +0 -1
- package/dist/commands/integrations.js +5 -61
- package/dist/commands/item-categories.d.ts +0 -1
- package/dist/commands/item-categories.js +5 -61
- package/dist/commands/items.d.ts +0 -1
- package/dist/commands/items.js +5 -61
- package/dist/commands/journal-lines.d.ts +0 -1
- package/dist/commands/journal-lines.js +5 -61
- package/dist/commands/journals.d.ts +1 -1
- package/dist/commands/journals.js +9 -62
- package/dist/commands/ledgers.d.ts +0 -1
- package/dist/commands/ledgers.js +5 -61
- package/dist/commands/nango-integrations.d.ts +39 -0
- package/dist/commands/nango-integrations.js +1115 -0
- package/dist/commands/office-locations.d.ts +0 -1
- package/dist/commands/office-locations.js +5 -61
- package/dist/commands/payment-methods.d.ts +0 -1
- package/dist/commands/payment-methods.js +5 -61
- package/dist/commands/payment-runs.d.ts +0 -1
- package/dist/commands/payment-runs.js +5 -61
- package/dist/commands/payment-terms.d.ts +0 -1
- package/dist/commands/payment-terms.js +5 -61
- package/dist/commands/payments.d.ts +0 -1
- package/dist/commands/payments.js +5 -61
- package/dist/commands/price-lists.d.ts +0 -1
- package/dist/commands/price-lists.js +5 -61
- package/dist/commands/processor-mappings.d.ts +0 -1
- package/dist/commands/processor-mappings.js +5 -61
- package/dist/commands/processors.d.ts +0 -1
- package/dist/commands/processors.js +5 -61
- package/dist/commands/purchase-order-types.d.ts +0 -1
- package/dist/commands/purchase-order-types.js +5 -61
- package/dist/commands/purchase-orders.d.ts +0 -1
- package/dist/commands/purchase-orders.js +7 -63
- package/dist/commands/reports.d.ts +0 -1
- package/dist/commands/reports.js +6 -62
- package/dist/commands/salary-types.d.ts +0 -1
- package/dist/commands/salary-types.js +5 -61
- package/dist/commands/sales-invoices.d.ts +0 -1
- package/dist/commands/sales-invoices.js +12 -65
- package/dist/commands/sales-orders.d.ts +0 -1
- package/dist/commands/sales-orders.js +7 -63
- package/dist/commands/saved-views.d.ts +0 -1
- package/dist/commands/saved-views.js +5 -61
- package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
- package/dist/commands/scheduled-processor-mappings.js +5 -61
- package/dist/commands/schedules.d.ts +0 -1
- package/dist/commands/schedules.js +5 -61
- package/dist/commands/switch.js +4 -4
- package/dist/commands/tag-configurations.d.ts +0 -1
- package/dist/commands/tag-configurations.js +9 -64
- package/dist/commands/tags.d.ts +0 -1
- package/dist/commands/tags.js +5 -61
- package/dist/commands/tax-codes.d.ts +0 -1
- package/dist/commands/tax-codes.js +5 -61
- package/dist/commands/tax-matrix.d.ts +0 -1
- package/dist/commands/tax-matrix.js +5 -61
- package/dist/commands/tenants.d.ts +0 -1
- package/dist/commands/tenants.js +7 -62
- package/dist/commands/text-templates.d.ts +0 -1
- package/dist/commands/text-templates.js +5 -61
- package/dist/commands/tools.d.ts +0 -1
- package/dist/commands/tools.js +5 -61
- package/dist/commands/vat-declarations.d.ts +1 -1
- package/dist/commands/vat-declarations.js +11 -62
- package/dist/commands/vendor-invoices.d.ts +0 -1
- package/dist/commands/vendor-invoices.js +10 -65
- package/dist/commands/webhooks.d.ts +0 -1
- package/dist/commands/webhooks.js +5 -61
- package/dist/commands/workflows.d.ts +0 -1
- package/dist/commands/workflows.js +5 -61
- package/dist/lib/api-client.js +3 -6
- package/dist/lib/auth/constants.d.ts +11 -0
- package/dist/lib/auth/constants.js +11 -0
- package/dist/lib/auth/errors.d.ts +17 -0
- package/dist/lib/auth/errors.js +22 -0
- package/dist/lib/auth/flow.d.ts +27 -0
- package/dist/lib/auth/flow.js +163 -0
- package/dist/lib/auth/guards.d.ts +5 -0
- package/dist/lib/auth/guards.js +14 -0
- package/dist/lib/auth/http.d.ts +16 -0
- package/dist/lib/auth/http.js +49 -0
- package/dist/lib/auth/index.d.ts +49 -0
- package/dist/lib/auth/index.js +217 -0
- package/dist/lib/auth/keycloak-provider.d.ts +75 -0
- package/dist/lib/auth/keycloak-provider.js +215 -0
- package/dist/lib/auth/pages.d.ts +25 -0
- package/dist/lib/auth/pages.js +123 -0
- package/dist/lib/auth/pkce.d.ts +11 -0
- package/dist/lib/auth/pkce.js +17 -0
- package/dist/lib/auth/tokens.d.ts +54 -0
- package/dist/lib/auth/tokens.js +104 -0
- package/dist/lib/auth/types.d.ts +57 -0
- package/dist/lib/auth/types.js +1 -0
- package/dist/lib/auth/validated-url.d.ts +6 -0
- package/dist/lib/auth/validated-url.js +53 -0
- package/dist/lib/config.d.ts +13 -3
- package/dist/lib/config.js +24 -19
- package/oclif.manifest.json +440 -71
- package/package.json +2 -1
- package/dist/lib/auth.d.ts +0 -43
- package/dist/lib/auth.js +0 -610
|
@@ -43,7 +43,7 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
43
43
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
44
44
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
45
45
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
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
48
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
49
|
};
|
|
@@ -115,6 +115,8 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
115
115
|
queryParams.search = flags.search;
|
|
116
116
|
if (flags['sort-by'])
|
|
117
117
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
118
|
+
if (flags.fields)
|
|
119
|
+
queryParams.fields = flags.fields;
|
|
118
120
|
if (flags.query) {
|
|
119
121
|
try {
|
|
120
122
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -317,11 +319,6 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
317
319
|
output = obj[arrayKeys[0]];
|
|
318
320
|
}
|
|
319
321
|
}
|
|
320
|
-
// Filter fields if --fields flag is provided
|
|
321
|
-
if (flags.fields) {
|
|
322
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
323
|
-
output = this.filterFields(output, fieldList);
|
|
324
|
-
}
|
|
325
322
|
// Sanitize output if requested
|
|
326
323
|
if (flags.sanitize) {
|
|
327
324
|
output = this.sanitizeOutput(output);
|
|
@@ -576,6 +573,8 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
576
573
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
577
574
|
if (flags.include)
|
|
578
575
|
baseParams.include = flags.include;
|
|
576
|
+
if (flags.fields)
|
|
577
|
+
baseParams.fields = flags.fields;
|
|
579
578
|
if (flags.query) {
|
|
580
579
|
try {
|
|
581
580
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -630,12 +629,7 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
630
629
|
}
|
|
631
630
|
}
|
|
632
631
|
process.stderr.write(' done\n');
|
|
633
|
-
// Filter fields if specified
|
|
634
632
|
let output = allItems;
|
|
635
|
-
if (flags.fields) {
|
|
636
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
637
|
-
output = this.filterFields(allItems, fieldList);
|
|
638
|
-
}
|
|
639
633
|
// Sanitize output if requested
|
|
640
634
|
if (flags.sanitize) {
|
|
641
635
|
output = this.sanitizeOutput(output);
|
|
@@ -964,56 +958,6 @@ export default class ScheduledProcessorMappings extends Command {
|
|
|
964
958
|
return `\$${op}`;
|
|
965
959
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
966
960
|
}
|
|
967
|
-
filterFields(data, fields) {
|
|
968
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
969
|
-
const pick = (obj, keys) => {
|
|
970
|
-
// Group keys by their first segment so sibling sub-paths
|
|
971
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
972
|
-
// and don't clobber each other on merge.
|
|
973
|
-
const directKeys = new Set();
|
|
974
|
-
const nestedKeys = new Map();
|
|
975
|
-
for (const key of keys) {
|
|
976
|
-
if (key.split('.').some(isUnsafeKey))
|
|
977
|
-
continue;
|
|
978
|
-
if (key.includes('.')) {
|
|
979
|
-
const [first, ...rest] = key.split('.');
|
|
980
|
-
if (isUnsafeKey(first))
|
|
981
|
-
continue;
|
|
982
|
-
const list = nestedKeys.get(first);
|
|
983
|
-
if (list) {
|
|
984
|
-
list.push(rest.join('.'));
|
|
985
|
-
}
|
|
986
|
-
else {
|
|
987
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
directKeys.add(key);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
const result = {};
|
|
995
|
-
for (const key of directKeys) {
|
|
996
|
-
if (key in obj)
|
|
997
|
-
result[key] = obj[key];
|
|
998
|
-
}
|
|
999
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1000
|
-
const val = obj[first];
|
|
1001
|
-
if (!val || typeof val !== 'object')
|
|
1002
|
-
continue;
|
|
1003
|
-
if (Array.isArray(val)) {
|
|
1004
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
result[first] = pick(val, restKeys);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
return result;
|
|
1011
|
-
};
|
|
1012
|
-
if (Array.isArray(data)) {
|
|
1013
|
-
return data.map(item => pick(item, fields));
|
|
1014
|
-
}
|
|
1015
|
-
return pick(data, fields);
|
|
1016
|
-
}
|
|
1017
961
|
sanitizeOutput(data) {
|
|
1018
962
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1019
963
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -47,7 +47,7 @@ export default class Schedules extends Command {
|
|
|
47
47
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
48
48
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
49
49
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
50
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
50
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
51
51
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
52
52
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
53
53
|
};
|
|
@@ -119,6 +119,8 @@ export default class Schedules extends Command {
|
|
|
119
119
|
queryParams.search = flags.search;
|
|
120
120
|
if (flags['sort-by'])
|
|
121
121
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
122
|
+
if (flags.fields)
|
|
123
|
+
queryParams.fields = flags.fields;
|
|
122
124
|
if (flags.query) {
|
|
123
125
|
try {
|
|
124
126
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -321,11 +323,6 @@ export default class Schedules extends Command {
|
|
|
321
323
|
output = obj[arrayKeys[0]];
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
|
-
// Filter fields if --fields flag is provided
|
|
325
|
-
if (flags.fields) {
|
|
326
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
327
|
-
output = this.filterFields(output, fieldList);
|
|
328
|
-
}
|
|
329
326
|
// Sanitize output if requested
|
|
330
327
|
if (flags.sanitize) {
|
|
331
328
|
output = this.sanitizeOutput(output);
|
|
@@ -580,6 +577,8 @@ export default class Schedules extends Command {
|
|
|
580
577
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
581
578
|
if (flags.include)
|
|
582
579
|
baseParams.include = flags.include;
|
|
580
|
+
if (flags.fields)
|
|
581
|
+
baseParams.fields = flags.fields;
|
|
583
582
|
if (flags.query) {
|
|
584
583
|
try {
|
|
585
584
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -634,12 +633,7 @@ export default class Schedules extends Command {
|
|
|
634
633
|
}
|
|
635
634
|
}
|
|
636
635
|
process.stderr.write(' done\n');
|
|
637
|
-
// Filter fields if specified
|
|
638
636
|
let output = allItems;
|
|
639
|
-
if (flags.fields) {
|
|
640
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
641
|
-
output = this.filterFields(allItems, fieldList);
|
|
642
|
-
}
|
|
643
637
|
// Sanitize output if requested
|
|
644
638
|
if (flags.sanitize) {
|
|
645
639
|
output = this.sanitizeOutput(output);
|
|
@@ -968,56 +962,6 @@ export default class Schedules extends Command {
|
|
|
968
962
|
return `\$${op}`;
|
|
969
963
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
970
964
|
}
|
|
971
|
-
filterFields(data, fields) {
|
|
972
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
973
|
-
const pick = (obj, keys) => {
|
|
974
|
-
// Group keys by their first segment so sibling sub-paths
|
|
975
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
976
|
-
// and don't clobber each other on merge.
|
|
977
|
-
const directKeys = new Set();
|
|
978
|
-
const nestedKeys = new Map();
|
|
979
|
-
for (const key of keys) {
|
|
980
|
-
if (key.split('.').some(isUnsafeKey))
|
|
981
|
-
continue;
|
|
982
|
-
if (key.includes('.')) {
|
|
983
|
-
const [first, ...rest] = key.split('.');
|
|
984
|
-
if (isUnsafeKey(first))
|
|
985
|
-
continue;
|
|
986
|
-
const list = nestedKeys.get(first);
|
|
987
|
-
if (list) {
|
|
988
|
-
list.push(rest.join('.'));
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
else {
|
|
995
|
-
directKeys.add(key);
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
const result = {};
|
|
999
|
-
for (const key of directKeys) {
|
|
1000
|
-
if (key in obj)
|
|
1001
|
-
result[key] = obj[key];
|
|
1002
|
-
}
|
|
1003
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1004
|
-
const val = obj[first];
|
|
1005
|
-
if (!val || typeof val !== 'object')
|
|
1006
|
-
continue;
|
|
1007
|
-
if (Array.isArray(val)) {
|
|
1008
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1009
|
-
}
|
|
1010
|
-
else {
|
|
1011
|
-
result[first] = pick(val, restKeys);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
return result;
|
|
1015
|
-
};
|
|
1016
|
-
if (Array.isArray(data)) {
|
|
1017
|
-
return data.map(item => pick(item, fields));
|
|
1018
|
-
}
|
|
1019
|
-
return pick(data, fields);
|
|
1020
|
-
}
|
|
1021
965
|
sanitizeOutput(data) {
|
|
1022
966
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1023
967
|
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/switch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { confirm, select } from '@inquirer/prompts';
|
|
2
2
|
import { Command } from '@oclif/core';
|
|
3
|
-
import { loginAndSwitchTenant } from '../lib/auth.js';
|
|
3
|
+
import { loginAndSwitchTenant, tenantLabel } from '../lib/auth/index.js';
|
|
4
4
|
import { getAuthType, getContext, getCurrentContext, hasCredentials, listContexts, setCurrentContext, } from '../lib/config.js';
|
|
5
5
|
export default class Switch extends Command {
|
|
6
6
|
static description = 'Switch context and tenant interactively';
|
|
@@ -62,8 +62,8 @@ export default class Switch extends Command {
|
|
|
62
62
|
if (!shouldLogin)
|
|
63
63
|
return;
|
|
64
64
|
// If we have a cached tenant list from a previous session, let the user pick
|
|
65
|
-
// tenant FIRST. Then run the combined login + tenant-switch flow which
|
|
66
|
-
// a single browser tab
|
|
65
|
+
// tenant FIRST. Then run the combined login + tenant-switch flow, which
|
|
66
|
+
// uses a single browser tab.
|
|
67
67
|
const ctx = getContext(selectedContext);
|
|
68
68
|
const cached = ctx?.cachedTenants ?? [];
|
|
69
69
|
if (cached.length > 1) {
|
|
@@ -76,7 +76,7 @@ export default class Switch extends Command {
|
|
|
76
76
|
});
|
|
77
77
|
const selectedTenant = await select({
|
|
78
78
|
choices: sorted.map((t) => ({
|
|
79
|
-
name: t.tenantId === ctx?.tenant_id ? `${t
|
|
79
|
+
name: t.tenantId === ctx?.tenant_id ? `${tenantLabel(t)} (previous)` : tenantLabel(t),
|
|
80
80
|
value: t.tenantId,
|
|
81
81
|
})),
|
|
82
82
|
message: 'Select a tenant:',
|
|
@@ -6,13 +6,14 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "journal-coverage"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/tag-configurations', summary: 'Get all tag configurations with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/tag-configurations', summary: 'Create a new tag configuration', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'tagIds', 'tagCodes'] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tag-configurations', summary: 'Create a new tag configuration', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'accountTypes', 'tagIds', 'tagCodes'] },
|
|
13
13
|
'get': { method: 'GET', path: '/v1/tag-configurations/{id}', summary: 'Get a tag configuration by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/tag-configurations/{id}', summary: 'Update a tag configuration', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'tagIds', 'tagCodes'] },
|
|
14
|
+
'update': { method: 'PATCH', path: '/v1/tag-configurations/{id}', summary: 'Update a tag configuration', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'accountTypes', 'tagIds', 'tagCodes'] },
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/tag-configurations/{id}', summary: 'Delete a tag configuration', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
|
+
'journal-coverage': { method: 'GET', path: '/v1/tag-configurations/{id}/journal-coverage', summary: 'How much of the journal-line amount in scope carries one of this configuration\'s tags', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
17
|
};
|
|
17
18
|
export default class TagConfigurations extends Command {
|
|
18
19
|
static description = 'Manage tag configurations';
|
|
@@ -43,7 +44,7 @@ export default class TagConfigurations extends Command {
|
|
|
43
44
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
44
45
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
45
46
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
47
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
47
48
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
48
49
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
50
|
};
|
|
@@ -115,6 +116,8 @@ export default class TagConfigurations extends Command {
|
|
|
115
116
|
queryParams.search = flags.search;
|
|
116
117
|
if (flags['sort-by'])
|
|
117
118
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
119
|
+
if (flags.fields)
|
|
120
|
+
queryParams.fields = flags.fields;
|
|
118
121
|
if (flags.query) {
|
|
119
122
|
try {
|
|
120
123
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -317,11 +320,6 @@ export default class TagConfigurations extends Command {
|
|
|
317
320
|
output = obj[arrayKeys[0]];
|
|
318
321
|
}
|
|
319
322
|
}
|
|
320
|
-
// Filter fields if --fields flag is provided
|
|
321
|
-
if (flags.fields) {
|
|
322
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
323
|
-
output = this.filterFields(output, fieldList);
|
|
324
|
-
}
|
|
325
323
|
// Sanitize output if requested
|
|
326
324
|
if (flags.sanitize) {
|
|
327
325
|
output = this.sanitizeOutput(output);
|
|
@@ -576,6 +574,8 @@ export default class TagConfigurations extends Command {
|
|
|
576
574
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
577
575
|
if (flags.include)
|
|
578
576
|
baseParams.include = flags.include;
|
|
577
|
+
if (flags.fields)
|
|
578
|
+
baseParams.fields = flags.fields;
|
|
579
579
|
if (flags.query) {
|
|
580
580
|
try {
|
|
581
581
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -630,12 +630,7 @@ export default class TagConfigurations extends Command {
|
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
632
|
process.stderr.write(' done\n');
|
|
633
|
-
// Filter fields if specified
|
|
634
633
|
let output = allItems;
|
|
635
|
-
if (flags.fields) {
|
|
636
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
637
|
-
output = this.filterFields(allItems, fieldList);
|
|
638
|
-
}
|
|
639
634
|
// Sanitize output if requested
|
|
640
635
|
if (flags.sanitize) {
|
|
641
636
|
output = this.sanitizeOutput(output);
|
|
@@ -964,56 +959,6 @@ export default class TagConfigurations extends Command {
|
|
|
964
959
|
return `\$${op}`;
|
|
965
960
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
966
961
|
}
|
|
967
|
-
filterFields(data, fields) {
|
|
968
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
969
|
-
const pick = (obj, keys) => {
|
|
970
|
-
// Group keys by their first segment so sibling sub-paths
|
|
971
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
972
|
-
// and don't clobber each other on merge.
|
|
973
|
-
const directKeys = new Set();
|
|
974
|
-
const nestedKeys = new Map();
|
|
975
|
-
for (const key of keys) {
|
|
976
|
-
if (key.split('.').some(isUnsafeKey))
|
|
977
|
-
continue;
|
|
978
|
-
if (key.includes('.')) {
|
|
979
|
-
const [first, ...rest] = key.split('.');
|
|
980
|
-
if (isUnsafeKey(first))
|
|
981
|
-
continue;
|
|
982
|
-
const list = nestedKeys.get(first);
|
|
983
|
-
if (list) {
|
|
984
|
-
list.push(rest.join('.'));
|
|
985
|
-
}
|
|
986
|
-
else {
|
|
987
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
directKeys.add(key);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
const result = {};
|
|
995
|
-
for (const key of directKeys) {
|
|
996
|
-
if (key in obj)
|
|
997
|
-
result[key] = obj[key];
|
|
998
|
-
}
|
|
999
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1000
|
-
const val = obj[first];
|
|
1001
|
-
if (!val || typeof val !== 'object')
|
|
1002
|
-
continue;
|
|
1003
|
-
if (Array.isArray(val)) {
|
|
1004
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
result[first] = pick(val, restKeys);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
return result;
|
|
1011
|
-
};
|
|
1012
|
-
if (Array.isArray(data)) {
|
|
1013
|
-
return data.map(item => pick(item, fields));
|
|
1014
|
-
}
|
|
1015
|
-
return pick(data, fields);
|
|
1016
|
-
}
|
|
1017
962
|
sanitizeOutput(data) {
|
|
1018
963
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1019
964
|
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/tags.d.ts
CHANGED
package/dist/commands/tags.js
CHANGED
|
@@ -43,7 +43,7 @@ export default class Tags extends Command {
|
|
|
43
43
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
44
44
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
45
45
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
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
48
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
49
|
};
|
|
@@ -115,6 +115,8 @@ export default class Tags extends Command {
|
|
|
115
115
|
queryParams.search = flags.search;
|
|
116
116
|
if (flags['sort-by'])
|
|
117
117
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
118
|
+
if (flags.fields)
|
|
119
|
+
queryParams.fields = flags.fields;
|
|
118
120
|
if (flags.query) {
|
|
119
121
|
try {
|
|
120
122
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -317,11 +319,6 @@ export default class Tags extends Command {
|
|
|
317
319
|
output = obj[arrayKeys[0]];
|
|
318
320
|
}
|
|
319
321
|
}
|
|
320
|
-
// Filter fields if --fields flag is provided
|
|
321
|
-
if (flags.fields) {
|
|
322
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
323
|
-
output = this.filterFields(output, fieldList);
|
|
324
|
-
}
|
|
325
322
|
// Sanitize output if requested
|
|
326
323
|
if (flags.sanitize) {
|
|
327
324
|
output = this.sanitizeOutput(output);
|
|
@@ -576,6 +573,8 @@ export default class Tags extends Command {
|
|
|
576
573
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
577
574
|
if (flags.include)
|
|
578
575
|
baseParams.include = flags.include;
|
|
576
|
+
if (flags.fields)
|
|
577
|
+
baseParams.fields = flags.fields;
|
|
579
578
|
if (flags.query) {
|
|
580
579
|
try {
|
|
581
580
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -630,12 +629,7 @@ export default class Tags extends Command {
|
|
|
630
629
|
}
|
|
631
630
|
}
|
|
632
631
|
process.stderr.write(' done\n');
|
|
633
|
-
// Filter fields if specified
|
|
634
632
|
let output = allItems;
|
|
635
|
-
if (flags.fields) {
|
|
636
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
637
|
-
output = this.filterFields(allItems, fieldList);
|
|
638
|
-
}
|
|
639
633
|
// Sanitize output if requested
|
|
640
634
|
if (flags.sanitize) {
|
|
641
635
|
output = this.sanitizeOutput(output);
|
|
@@ -964,56 +958,6 @@ export default class Tags extends Command {
|
|
|
964
958
|
return `\$${op}`;
|
|
965
959
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
966
960
|
}
|
|
967
|
-
filterFields(data, fields) {
|
|
968
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
969
|
-
const pick = (obj, keys) => {
|
|
970
|
-
// Group keys by their first segment so sibling sub-paths
|
|
971
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
972
|
-
// and don't clobber each other on merge.
|
|
973
|
-
const directKeys = new Set();
|
|
974
|
-
const nestedKeys = new Map();
|
|
975
|
-
for (const key of keys) {
|
|
976
|
-
if (key.split('.').some(isUnsafeKey))
|
|
977
|
-
continue;
|
|
978
|
-
if (key.includes('.')) {
|
|
979
|
-
const [first, ...rest] = key.split('.');
|
|
980
|
-
if (isUnsafeKey(first))
|
|
981
|
-
continue;
|
|
982
|
-
const list = nestedKeys.get(first);
|
|
983
|
-
if (list) {
|
|
984
|
-
list.push(rest.join('.'));
|
|
985
|
-
}
|
|
986
|
-
else {
|
|
987
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
directKeys.add(key);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
const result = {};
|
|
995
|
-
for (const key of directKeys) {
|
|
996
|
-
if (key in obj)
|
|
997
|
-
result[key] = obj[key];
|
|
998
|
-
}
|
|
999
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1000
|
-
const val = obj[first];
|
|
1001
|
-
if (!val || typeof val !== 'object')
|
|
1002
|
-
continue;
|
|
1003
|
-
if (Array.isArray(val)) {
|
|
1004
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
result[first] = pick(val, restKeys);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
return result;
|
|
1011
|
-
};
|
|
1012
|
-
if (Array.isArray(data)) {
|
|
1013
|
-
return data.map(item => pick(item, fields));
|
|
1014
|
-
}
|
|
1015
|
-
return pick(data, fields);
|
|
1016
|
-
}
|
|
1017
961
|
sanitizeOutput(data) {
|
|
1018
962
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1019
963
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -46,7 +46,7 @@ export default class TaxCodes extends Command {
|
|
|
46
46
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
47
47
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
48
48
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
49
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
49
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
50
50
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
51
51
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
52
52
|
};
|
|
@@ -118,6 +118,8 @@ export default class TaxCodes extends Command {
|
|
|
118
118
|
queryParams.search = flags.search;
|
|
119
119
|
if (flags['sort-by'])
|
|
120
120
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
121
|
+
if (flags.fields)
|
|
122
|
+
queryParams.fields = flags.fields;
|
|
121
123
|
if (flags.query) {
|
|
122
124
|
try {
|
|
123
125
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -320,11 +322,6 @@ export default class TaxCodes extends Command {
|
|
|
320
322
|
output = obj[arrayKeys[0]];
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
|
-
// Filter fields if --fields flag is provided
|
|
324
|
-
if (flags.fields) {
|
|
325
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
326
|
-
output = this.filterFields(output, fieldList);
|
|
327
|
-
}
|
|
328
325
|
// Sanitize output if requested
|
|
329
326
|
if (flags.sanitize) {
|
|
330
327
|
output = this.sanitizeOutput(output);
|
|
@@ -579,6 +576,8 @@ export default class TaxCodes extends Command {
|
|
|
579
576
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
580
577
|
if (flags.include)
|
|
581
578
|
baseParams.include = flags.include;
|
|
579
|
+
if (flags.fields)
|
|
580
|
+
baseParams.fields = flags.fields;
|
|
582
581
|
if (flags.query) {
|
|
583
582
|
try {
|
|
584
583
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -633,12 +632,7 @@ export default class TaxCodes extends Command {
|
|
|
633
632
|
}
|
|
634
633
|
}
|
|
635
634
|
process.stderr.write(' done\n');
|
|
636
|
-
// Filter fields if specified
|
|
637
635
|
let output = allItems;
|
|
638
|
-
if (flags.fields) {
|
|
639
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
640
|
-
output = this.filterFields(allItems, fieldList);
|
|
641
|
-
}
|
|
642
636
|
// Sanitize output if requested
|
|
643
637
|
if (flags.sanitize) {
|
|
644
638
|
output = this.sanitizeOutput(output);
|
|
@@ -967,56 +961,6 @@ export default class TaxCodes extends Command {
|
|
|
967
961
|
return `\$${op}`;
|
|
968
962
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
969
963
|
}
|
|
970
|
-
filterFields(data, fields) {
|
|
971
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
972
|
-
const pick = (obj, keys) => {
|
|
973
|
-
// Group keys by their first segment so sibling sub-paths
|
|
974
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
975
|
-
// and don't clobber each other on merge.
|
|
976
|
-
const directKeys = new Set();
|
|
977
|
-
const nestedKeys = new Map();
|
|
978
|
-
for (const key of keys) {
|
|
979
|
-
if (key.split('.').some(isUnsafeKey))
|
|
980
|
-
continue;
|
|
981
|
-
if (key.includes('.')) {
|
|
982
|
-
const [first, ...rest] = key.split('.');
|
|
983
|
-
if (isUnsafeKey(first))
|
|
984
|
-
continue;
|
|
985
|
-
const list = nestedKeys.get(first);
|
|
986
|
-
if (list) {
|
|
987
|
-
list.push(rest.join('.'));
|
|
988
|
-
}
|
|
989
|
-
else {
|
|
990
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
else {
|
|
994
|
-
directKeys.add(key);
|
|
995
|
-
}
|
|
996
|
-
}
|
|
997
|
-
const result = {};
|
|
998
|
-
for (const key of directKeys) {
|
|
999
|
-
if (key in obj)
|
|
1000
|
-
result[key] = obj[key];
|
|
1001
|
-
}
|
|
1002
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1003
|
-
const val = obj[first];
|
|
1004
|
-
if (!val || typeof val !== 'object')
|
|
1005
|
-
continue;
|
|
1006
|
-
if (Array.isArray(val)) {
|
|
1007
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1008
|
-
}
|
|
1009
|
-
else {
|
|
1010
|
-
result[first] = pick(val, restKeys);
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
return result;
|
|
1014
|
-
};
|
|
1015
|
-
if (Array.isArray(data)) {
|
|
1016
|
-
return data.map(item => pick(item, fields));
|
|
1017
|
-
}
|
|
1018
|
-
return pick(data, fields);
|
|
1019
|
-
}
|
|
1020
964
|
sanitizeOutput(data) {
|
|
1021
965
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1022
966
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|