@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 TaxMatrix 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 TaxMatrix 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 TaxMatrix 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 TaxMatrix 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 TaxMatrix 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 TaxMatrix 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;
|
package/dist/commands/tenants.js
CHANGED
|
@@ -6,7 +6,7 @@ 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", "logo", "icon"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "logo", "icon", "update-identity-provider"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/tenants', summary: 'Get all tenants with pagination (admin only)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/tenants', summary: 'Create a new tenant (admin only)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['supportedLocales', 'allowedSenders', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'salesOrderRecipientCc', 'salesOrderRecipientBcc', 'deliveryNoteRecipientCc', 'deliveryNoteRecipientBcc'] },
|
|
@@ -15,6 +15,7 @@ const ENDPOINTS = {
|
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/tenants/{id}', summary: 'Delete a tenant (admin only)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
16
|
'logo': { method: 'POST', path: '/v1/tenants/{id}/logo', summary: 'Upload the tenant logo to the public bucket and set logoUrl (own tenant or admin)', pathParams: ['id'], hasBody: false, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
|
|
17
17
|
'icon': { method: 'POST', path: '/v1/tenants/{id}/icon', summary: 'Upload the tenant icon to the public bucket and set iconUrl (own tenant or admin)', pathParams: ['id'], hasBody: false, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
|
|
18
|
+
'update-identity-provider': { method: 'PUT', path: '/v1/tenants/{id}/identity-provider', summary: 'Synchronize a tenant with the identity provider (admin only)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
18
19
|
};
|
|
19
20
|
export default class Tenants extends Command {
|
|
20
21
|
static description = 'Manage tenants';
|
|
@@ -45,7 +46,7 @@ export default class Tenants extends Command {
|
|
|
45
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.' }),
|
|
46
47
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
47
48
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
48
|
-
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)' }),
|
|
49
50
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
50
51
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
51
52
|
};
|
|
@@ -117,6 +118,8 @@ export default class Tenants extends Command {
|
|
|
117
118
|
queryParams.search = flags.search;
|
|
118
119
|
if (flags['sort-by'])
|
|
119
120
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
121
|
+
if (flags.fields)
|
|
122
|
+
queryParams.fields = flags.fields;
|
|
120
123
|
if (flags.query) {
|
|
121
124
|
try {
|
|
122
125
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -319,11 +322,6 @@ export default class Tenants extends Command {
|
|
|
319
322
|
output = obj[arrayKeys[0]];
|
|
320
323
|
}
|
|
321
324
|
}
|
|
322
|
-
// Filter fields if --fields flag is provided
|
|
323
|
-
if (flags.fields) {
|
|
324
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
325
|
-
output = this.filterFields(output, fieldList);
|
|
326
|
-
}
|
|
327
325
|
// Sanitize output if requested
|
|
328
326
|
if (flags.sanitize) {
|
|
329
327
|
output = this.sanitizeOutput(output);
|
|
@@ -578,6 +576,8 @@ export default class Tenants extends Command {
|
|
|
578
576
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
579
577
|
if (flags.include)
|
|
580
578
|
baseParams.include = flags.include;
|
|
579
|
+
if (flags.fields)
|
|
580
|
+
baseParams.fields = flags.fields;
|
|
581
581
|
if (flags.query) {
|
|
582
582
|
try {
|
|
583
583
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -632,12 +632,7 @@ export default class Tenants extends Command {
|
|
|
632
632
|
}
|
|
633
633
|
}
|
|
634
634
|
process.stderr.write(' done\n');
|
|
635
|
-
// Filter fields if specified
|
|
636
635
|
let output = allItems;
|
|
637
|
-
if (flags.fields) {
|
|
638
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
639
|
-
output = this.filterFields(allItems, fieldList);
|
|
640
|
-
}
|
|
641
636
|
// Sanitize output if requested
|
|
642
637
|
if (flags.sanitize) {
|
|
643
638
|
output = this.sanitizeOutput(output);
|
|
@@ -966,56 +961,6 @@ export default class Tenants extends Command {
|
|
|
966
961
|
return `\$${op}`;
|
|
967
962
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
968
963
|
}
|
|
969
|
-
filterFields(data, fields) {
|
|
970
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
971
|
-
const pick = (obj, keys) => {
|
|
972
|
-
// Group keys by their first segment so sibling sub-paths
|
|
973
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
974
|
-
// and don't clobber each other on merge.
|
|
975
|
-
const directKeys = new Set();
|
|
976
|
-
const nestedKeys = new Map();
|
|
977
|
-
for (const key of keys) {
|
|
978
|
-
if (key.split('.').some(isUnsafeKey))
|
|
979
|
-
continue;
|
|
980
|
-
if (key.includes('.')) {
|
|
981
|
-
const [first, ...rest] = key.split('.');
|
|
982
|
-
if (isUnsafeKey(first))
|
|
983
|
-
continue;
|
|
984
|
-
const list = nestedKeys.get(first);
|
|
985
|
-
if (list) {
|
|
986
|
-
list.push(rest.join('.'));
|
|
987
|
-
}
|
|
988
|
-
else {
|
|
989
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
directKeys.add(key);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
const result = {};
|
|
997
|
-
for (const key of directKeys) {
|
|
998
|
-
if (key in obj)
|
|
999
|
-
result[key] = obj[key];
|
|
1000
|
-
}
|
|
1001
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1002
|
-
const val = obj[first];
|
|
1003
|
-
if (!val || typeof val !== 'object')
|
|
1004
|
-
continue;
|
|
1005
|
-
if (Array.isArray(val)) {
|
|
1006
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1007
|
-
}
|
|
1008
|
-
else {
|
|
1009
|
-
result[first] = pick(val, restKeys);
|
|
1010
|
-
}
|
|
1011
|
-
}
|
|
1012
|
-
return result;
|
|
1013
|
-
};
|
|
1014
|
-
if (Array.isArray(data)) {
|
|
1015
|
-
return data.map(item => pick(item, fields));
|
|
1016
|
-
}
|
|
1017
|
-
return pick(data, fields);
|
|
1018
|
-
}
|
|
1019
964
|
sanitizeOutput(data) {
|
|
1020
965
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1021
966
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -43,7 +43,7 @@ export default class TextTemplates 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 TextTemplates 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 TextTemplates 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 TextTemplates 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 TextTemplates 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 TextTemplates 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;
|
package/dist/commands/tools.d.ts
CHANGED
package/dist/commands/tools.js
CHANGED
|
@@ -36,7 +36,7 @@ export default class Tools extends Command {
|
|
|
36
36
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
37
37
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
38
38
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
39
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
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
41
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
42
42
|
};
|
|
@@ -108,6 +108,8 @@ export default class Tools extends Command {
|
|
|
108
108
|
queryParams.search = flags.search;
|
|
109
109
|
if (flags['sort-by'])
|
|
110
110
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
111
|
+
if (flags.fields)
|
|
112
|
+
queryParams.fields = flags.fields;
|
|
111
113
|
if (flags.query) {
|
|
112
114
|
try {
|
|
113
115
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -310,11 +312,6 @@ export default class Tools extends Command {
|
|
|
310
312
|
output = obj[arrayKeys[0]];
|
|
311
313
|
}
|
|
312
314
|
}
|
|
313
|
-
// Filter fields if --fields flag is provided
|
|
314
|
-
if (flags.fields) {
|
|
315
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
316
|
-
output = this.filterFields(output, fieldList);
|
|
317
|
-
}
|
|
318
315
|
// Sanitize output if requested
|
|
319
316
|
if (flags.sanitize) {
|
|
320
317
|
output = this.sanitizeOutput(output);
|
|
@@ -569,6 +566,8 @@ export default class Tools extends Command {
|
|
|
569
566
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
570
567
|
if (flags.include)
|
|
571
568
|
baseParams.include = flags.include;
|
|
569
|
+
if (flags.fields)
|
|
570
|
+
baseParams.fields = flags.fields;
|
|
572
571
|
if (flags.query) {
|
|
573
572
|
try {
|
|
574
573
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -623,12 +622,7 @@ export default class Tools extends Command {
|
|
|
623
622
|
}
|
|
624
623
|
}
|
|
625
624
|
process.stderr.write(' done\n');
|
|
626
|
-
// Filter fields if specified
|
|
627
625
|
let output = allItems;
|
|
628
|
-
if (flags.fields) {
|
|
629
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
630
|
-
output = this.filterFields(allItems, fieldList);
|
|
631
|
-
}
|
|
632
626
|
// Sanitize output if requested
|
|
633
627
|
if (flags.sanitize) {
|
|
634
628
|
output = this.sanitizeOutput(output);
|
|
@@ -957,56 +951,6 @@ export default class Tools extends Command {
|
|
|
957
951
|
return `\$${op}`;
|
|
958
952
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
959
953
|
}
|
|
960
|
-
filterFields(data, fields) {
|
|
961
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
962
|
-
const pick = (obj, keys) => {
|
|
963
|
-
// Group keys by their first segment so sibling sub-paths
|
|
964
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
965
|
-
// and don't clobber each other on merge.
|
|
966
|
-
const directKeys = new Set();
|
|
967
|
-
const nestedKeys = new Map();
|
|
968
|
-
for (const key of keys) {
|
|
969
|
-
if (key.split('.').some(isUnsafeKey))
|
|
970
|
-
continue;
|
|
971
|
-
if (key.includes('.')) {
|
|
972
|
-
const [first, ...rest] = key.split('.');
|
|
973
|
-
if (isUnsafeKey(first))
|
|
974
|
-
continue;
|
|
975
|
-
const list = nestedKeys.get(first);
|
|
976
|
-
if (list) {
|
|
977
|
-
list.push(rest.join('.'));
|
|
978
|
-
}
|
|
979
|
-
else {
|
|
980
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
else {
|
|
984
|
-
directKeys.add(key);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
const result = {};
|
|
988
|
-
for (const key of directKeys) {
|
|
989
|
-
if (key in obj)
|
|
990
|
-
result[key] = obj[key];
|
|
991
|
-
}
|
|
992
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
993
|
-
const val = obj[first];
|
|
994
|
-
if (!val || typeof val !== 'object')
|
|
995
|
-
continue;
|
|
996
|
-
if (Array.isArray(val)) {
|
|
997
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
998
|
-
}
|
|
999
|
-
else {
|
|
1000
|
-
result[first] = pick(val, restKeys);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
return result;
|
|
1004
|
-
};
|
|
1005
|
-
if (Array.isArray(data)) {
|
|
1006
|
-
return data.map(item => pick(item, fields));
|
|
1007
|
-
}
|
|
1008
|
-
return pick(data, fields);
|
|
1009
|
-
}
|
|
1010
954
|
sanitizeOutput(data) {
|
|
1011
955
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1012
956
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -15,6 +15,7 @@ export default class VatDeclarations extends Command {
|
|
|
15
15
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
17
|
'field-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'notice-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
19
|
'file-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
20
|
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
21
|
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -33,7 +34,6 @@ export default class VatDeclarations extends Command {
|
|
|
33
34
|
private runCamt053Import;
|
|
34
35
|
private runNestedImport;
|
|
35
36
|
private parseFilterValue;
|
|
36
|
-
private filterFields;
|
|
37
37
|
private sanitizeOutput;
|
|
38
38
|
private getColumns;
|
|
39
39
|
private getValue;
|
|
@@ -6,7 +6,7 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = ["files"];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "preview", "get", "update", "delete", "regenerate", "replace", "fields-contributions", "fields-contributions-export", "approve", "mark-as-filed", "xml", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "preview", "get", "update", "delete", "regenerate", "replace", "fields-contributions", "fields-contributions-export", "approve", "notices-dismiss", "notices-restore", "mark-as-filed", "xml", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download", "list-payments", "create-payments"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/vat-declarations', summary: 'List VAT reports (paginated)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/vat-declarations', summary: 'Create a VAT declaration report (always async-accepted)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
@@ -19,6 +19,8 @@ const ENDPOINTS = {
|
|
|
19
19
|
'fields-contributions': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions', summary: 'Drill into the contributions for a single Ziffer', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
20
20
|
'fields-contributions-export': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions/export', summary: 'Export the drill-down result set as an Excel workbook', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: true, bodyArrayFields: [] },
|
|
21
21
|
'approve': { method: 'POST', path: '/v1/vat-declarations/{id}/approve', summary: 'Approve a VAT report and produce the eCH-0217 XML submission file.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
22
|
+
'notices-dismiss': { method: 'POST', path: '/v1/vat-declarations/{id}/notices/{noticeId}/dismiss', summary: 'Dismiss a generation notice with a mandatory reason.', pathParams: ['id', 'noticeId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
23
|
+
'notices-restore': { method: 'POST', path: '/v1/vat-declarations/{id}/notices/{noticeId}/restore', summary: 'Restore a previously dismissed generation notice.', pathParams: ['id', 'noticeId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
22
24
|
'mark-as-filed': { method: 'POST', path: '/v1/vat-declarations/{id}/mark-as-filed', summary: 'Mark a FINALIZED VAT declaration as filed.', pathParams: ['id'], hasBody: true, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
|
|
23
25
|
'xml': { method: 'GET', path: '/v1/vat-declarations/{id}/xml', summary: 'Download the eCH-0217 XML submission file for a FINALIZED or FILED VAT report.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: true, bodyArrayFields: [] },
|
|
24
26
|
'list-files': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files', summary: 'List file attachments for a VAT declaration', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
@@ -27,6 +29,8 @@ const ENDPOINTS = {
|
|
|
27
29
|
'update-files': { method: 'PATCH', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
28
30
|
'delete-files': { method: 'DELETE', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
29
31
|
'files-download': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
32
|
+
'list-payments': { method: 'GET', path: '/v1/vat-declarations/{vatDeclarationId}/payments', summary: 'Get all payments for a VAT declaration', pathParams: ['vatDeclarationId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
33
|
+
'create-payments': { method: 'POST', path: '/v1/vat-declarations/{vatDeclarationId}/payments', summary: 'Create the payment for a filed VAT declaration', pathParams: ['vatDeclarationId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
30
34
|
};
|
|
31
35
|
export default class VatDeclarations extends Command {
|
|
32
36
|
static description = 'Manage vat declarations';
|
|
@@ -51,6 +55,7 @@ export default class VatDeclarations extends Command {
|
|
|
51
55
|
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
52
56
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
53
57
|
'field-id': Flags.string({ description: 'Path param: fieldId' }),
|
|
58
|
+
'notice-id': Flags.string({ description: 'Path param: noticeId' }),
|
|
54
59
|
'file-id': Flags.string({ description: 'Path param: fileId' }),
|
|
55
60
|
page: Flags.string({ description: 'Page number' }),
|
|
56
61
|
limit: Flags.string({ description: 'Items per page' }),
|
|
@@ -59,7 +64,7 @@ export default class VatDeclarations extends Command {
|
|
|
59
64
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
60
65
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
61
66
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
62
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
67
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
63
68
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
64
69
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
65
70
|
};
|
|
@@ -131,6 +136,8 @@ export default class VatDeclarations extends Command {
|
|
|
131
136
|
queryParams.search = flags.search;
|
|
132
137
|
if (flags['sort-by'])
|
|
133
138
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
139
|
+
if (flags.fields)
|
|
140
|
+
queryParams.fields = flags.fields;
|
|
134
141
|
if (flags.query) {
|
|
135
142
|
try {
|
|
136
143
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -333,11 +340,6 @@ export default class VatDeclarations extends Command {
|
|
|
333
340
|
output = obj[arrayKeys[0]];
|
|
334
341
|
}
|
|
335
342
|
}
|
|
336
|
-
// Filter fields if --fields flag is provided
|
|
337
|
-
if (flags.fields) {
|
|
338
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
339
|
-
output = this.filterFields(output, fieldList);
|
|
340
|
-
}
|
|
341
343
|
// Sanitize output if requested
|
|
342
344
|
if (flags.sanitize) {
|
|
343
345
|
output = this.sanitizeOutput(output);
|
|
@@ -592,6 +594,8 @@ export default class VatDeclarations extends Command {
|
|
|
592
594
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
593
595
|
if (flags.include)
|
|
594
596
|
baseParams.include = flags.include;
|
|
597
|
+
if (flags.fields)
|
|
598
|
+
baseParams.fields = flags.fields;
|
|
595
599
|
if (flags.query) {
|
|
596
600
|
try {
|
|
597
601
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -646,12 +650,7 @@ export default class VatDeclarations extends Command {
|
|
|
646
650
|
}
|
|
647
651
|
}
|
|
648
652
|
process.stderr.write(' done\n');
|
|
649
|
-
// Filter fields if specified
|
|
650
653
|
let output = allItems;
|
|
651
|
-
if (flags.fields) {
|
|
652
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
653
|
-
output = this.filterFields(allItems, fieldList);
|
|
654
|
-
}
|
|
655
654
|
// Sanitize output if requested
|
|
656
655
|
if (flags.sanitize) {
|
|
657
656
|
output = this.sanitizeOutput(output);
|
|
@@ -980,56 +979,6 @@ export default class VatDeclarations extends Command {
|
|
|
980
979
|
return `\$${op}`;
|
|
981
980
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
982
981
|
}
|
|
983
|
-
filterFields(data, fields) {
|
|
984
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
985
|
-
const pick = (obj, keys) => {
|
|
986
|
-
// Group keys by their first segment so sibling sub-paths
|
|
987
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
988
|
-
// and don't clobber each other on merge.
|
|
989
|
-
const directKeys = new Set();
|
|
990
|
-
const nestedKeys = new Map();
|
|
991
|
-
for (const key of keys) {
|
|
992
|
-
if (key.split('.').some(isUnsafeKey))
|
|
993
|
-
continue;
|
|
994
|
-
if (key.includes('.')) {
|
|
995
|
-
const [first, ...rest] = key.split('.');
|
|
996
|
-
if (isUnsafeKey(first))
|
|
997
|
-
continue;
|
|
998
|
-
const list = nestedKeys.get(first);
|
|
999
|
-
if (list) {
|
|
1000
|
-
list.push(rest.join('.'));
|
|
1001
|
-
}
|
|
1002
|
-
else {
|
|
1003
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
1007
|
-
directKeys.add(key);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
const result = {};
|
|
1011
|
-
for (const key of directKeys) {
|
|
1012
|
-
if (key in obj)
|
|
1013
|
-
result[key] = obj[key];
|
|
1014
|
-
}
|
|
1015
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1016
|
-
const val = obj[first];
|
|
1017
|
-
if (!val || typeof val !== 'object')
|
|
1018
|
-
continue;
|
|
1019
|
-
if (Array.isArray(val)) {
|
|
1020
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1021
|
-
}
|
|
1022
|
-
else {
|
|
1023
|
-
result[first] = pick(val, restKeys);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
return result;
|
|
1027
|
-
};
|
|
1028
|
-
if (Array.isArray(data)) {
|
|
1029
|
-
return data.map(item => pick(item, fields));
|
|
1030
|
-
}
|
|
1031
|
-
return pick(data, fields);
|
|
1032
|
-
}
|
|
1033
982
|
sanitizeOutput(data) {
|
|
1034
983
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1035
984
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|