@aderis-erp/cli 1.0.14 → 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 +22 -78
- package/dist/commands/account-transaction-allocations.d.ts +0 -1
- package/dist/commands/account-transaction-allocations.js +22 -78
- package/dist/commands/account-transactions.d.ts +0 -1
- package/dist/commands/account-transactions.js +28 -82
- package/dist/commands/accounts.d.ts +0 -1
- package/dist/commands/accounts.js +24 -80
- package/dist/commands/agent-platform.d.ts +0 -1
- package/dist/commands/agent-platform.js +24 -79
- package/dist/commands/analytics.d.ts +39 -0
- package/dist/commands/analytics.js +1113 -0
- package/dist/commands/{documents.d.ts → api-keys.d.ts} +1 -2
- package/dist/commands/api-keys.js +1117 -0
- package/dist/commands/audit-log.d.ts +0 -1
- package/dist/commands/audit-log.js +22 -78
- package/dist/commands/auth/login.d.ts +9 -0
- package/dist/commands/auth/login.js +83 -21
- package/dist/commands/auth/logout.d.ts +6 -0
- package/dist/commands/auth/logout.js +23 -6
- package/dist/commands/auth/status.js +46 -23
- package/dist/commands/auth/tenant.js +15 -9
- package/dist/commands/auth.d.ts +0 -1
- package/dist/commands/auth.js +37 -51
- package/dist/commands/bank-accounts.d.ts +0 -1
- package/dist/commands/bank-accounts.js +22 -78
- package/dist/commands/bank-integrations.d.ts +0 -1
- package/dist/commands/bank-integrations.js +22 -78
- package/dist/commands/business-partners.d.ts +1 -1
- package/dist/commands/business-partners.js +38 -84
- package/dist/commands/chat.d.ts +0 -1
- package/dist/commands/chat.js +22 -78
- package/dist/commands/config/add.d.ts +12 -0
- package/dist/commands/config/add.js +97 -17
- package/dist/commands/config/current.js +12 -4
- package/dist/commands/config/list.js +12 -4
- package/dist/commands/config/set-api-key.d.ts +10 -0
- package/dist/commands/config/set-api-key.js +49 -0
- package/dist/commands/config/use.js +3 -4
- package/dist/commands/credit-card-accounts.d.ts +0 -1
- package/dist/commands/credit-card-accounts.js +22 -78
- package/dist/commands/delivery-notes.d.ts +0 -1
- package/dist/commands/delivery-notes.js +29 -84
- package/dist/commands/dunning-configs.d.ts +0 -1
- package/dist/commands/dunning-configs.js +22 -78
- package/dist/commands/dunning-reminders.d.ts +0 -1
- package/dist/commands/dunning-reminders.js +22 -78
- package/dist/commands/dunning-runs.d.ts +0 -1
- package/dist/commands/dunning-runs.js +22 -78
- package/dist/commands/email-transactions.d.ts +0 -1
- package/dist/commands/email-transactions.js +22 -78
- package/dist/commands/employees.d.ts +0 -1
- package/dist/commands/employees.js +24 -80
- package/dist/commands/entity-configurations.d.ts +0 -1
- package/dist/commands/entity-configurations.js +22 -78
- package/dist/commands/event-processor-mappings.d.ts +0 -1
- package/dist/commands/event-processor-mappings.js +22 -78
- package/dist/commands/{files-internal.d.ts → files.d.ts} +1 -2
- package/dist/commands/{files-internal.js → files.js} +40 -90
- package/dist/commands/health.d.ts +0 -1
- package/dist/commands/health.js +22 -78
- package/dist/commands/inbox.d.ts +0 -1
- package/dist/commands/inbox.js +22 -78
- package/dist/commands/integrations.d.ts +0 -1
- package/dist/commands/integrations.js +22 -78
- package/dist/commands/item-categories.d.ts +0 -1
- package/dist/commands/item-categories.js +22 -78
- package/dist/commands/items.d.ts +0 -1
- package/dist/commands/items.js +24 -80
- package/dist/commands/journal-lines.d.ts +0 -1
- package/dist/commands/journal-lines.js +22 -78
- package/dist/commands/journals.d.ts +1 -1
- package/dist/commands/journals.js +29 -81
- package/dist/commands/ledgers.d.ts +0 -1
- package/dist/commands/ledgers.js +26 -79
- 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 +22 -78
- package/dist/commands/payment-methods.d.ts +0 -1
- package/dist/commands/payment-methods.js +22 -78
- package/dist/commands/payment-runs.d.ts +0 -1
- package/dist/commands/payment-runs.js +24 -79
- package/dist/commands/payment-terms.d.ts +0 -1
- package/dist/commands/payment-terms.js +22 -78
- package/dist/commands/payments.d.ts +0 -1
- package/dist/commands/payments.js +22 -78
- package/dist/commands/price-lists.d.ts +0 -1
- package/dist/commands/price-lists.js +22 -78
- package/dist/commands/processor-mappings.d.ts +0 -1
- package/dist/commands/processor-mappings.js +22 -78
- package/dist/commands/processors.d.ts +0 -1
- package/dist/commands/processors.js +22 -78
- package/dist/commands/purchase-order-types.d.ts +0 -1
- package/dist/commands/purchase-order-types.js +22 -78
- package/dist/commands/purchase-orders.d.ts +1 -1
- package/dist/commands/purchase-orders.js +35 -84
- package/dist/commands/reports.d.ts +0 -1
- package/dist/commands/reports.js +23 -79
- package/dist/commands/salary-types.d.ts +0 -1
- package/dist/commands/salary-types.js +22 -78
- package/dist/commands/sales-invoices.d.ts +0 -1
- package/dist/commands/sales-invoices.js +38 -89
- package/dist/commands/sales-orders.d.ts +0 -1
- package/dist/commands/sales-orders.js +26 -82
- package/dist/commands/saved-views.d.ts +0 -1
- package/dist/commands/saved-views.js +22 -78
- package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
- package/dist/commands/scheduled-processor-mappings.js +22 -78
- package/dist/commands/schedules.d.ts +0 -1
- package/dist/commands/schedules.js +22 -78
- package/dist/commands/switch.js +14 -7
- package/dist/commands/tag-configurations.d.ts +39 -0
- package/dist/commands/{documents.js → tag-configurations.js} +40 -96
- package/dist/commands/tags.d.ts +0 -1
- package/dist/commands/tags.js +22 -78
- package/dist/commands/tax-codes.d.ts +0 -1
- package/dist/commands/tax-codes.js +22 -78
- package/dist/commands/tax-matrix.d.ts +0 -1
- package/dist/commands/tax-matrix.js +22 -78
- package/dist/commands/tenants.d.ts +0 -1
- package/dist/commands/tenants.js +24 -79
- package/dist/commands/text-templates.d.ts +0 -1
- package/dist/commands/text-templates.js +22 -78
- package/dist/commands/tools.d.ts +0 -1
- package/dist/commands/tools.js +22 -78
- package/dist/commands/vat-declarations.d.ts +1 -1
- package/dist/commands/vat-declarations.js +28 -79
- package/dist/commands/vendor-invoices.d.ts +0 -1
- package/dist/commands/vendor-invoices.js +31 -86
- package/dist/commands/webhooks.d.ts +0 -1
- package/dist/commands/webhooks.js +22 -78
- package/dist/commands/workflows.d.ts +0 -1
- package/dist/commands/workflows.js +22 -78
- package/dist/lib/api-client.js +8 -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/base-api-command.js +6 -4
- package/dist/lib/config.d.ts +44 -4
- package/dist/lib/config.js +55 -19
- package/oclif.manifest.json +1181 -330
- package/package.json +3 -2
- package/dist/lib/auth.d.ts +0 -35
- package/dist/lib/auth.js +0 -566
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
3
|
-
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
3
|
+
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
6
|
const HAS_EXPORT = true;
|
|
@@ -32,7 +32,7 @@ export default class TaxCodes extends Command {
|
|
|
32
32
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
33
33
|
};
|
|
34
34
|
static flags = {
|
|
35
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
35
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
36
36
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
37
37
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
38
38
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -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
|
};
|
|
@@ -104,9 +104,9 @@ export default class TaxCodes extends Command {
|
|
|
104
104
|
}
|
|
105
105
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
106
106
|
if (!context)
|
|
107
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
108
|
-
if (!context
|
|
109
|
-
this.error(
|
|
107
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
108
|
+
if (!hasCredentials(context))
|
|
109
|
+
this.error(missingCredentialsMessage(context));
|
|
110
110
|
const queryParams = {};
|
|
111
111
|
if (flags.page)
|
|
112
112
|
queryParams.page = flags.page;
|
|
@@ -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);
|
|
@@ -349,9 +346,9 @@ export default class TaxCodes extends Command {
|
|
|
349
346
|
async runImport(flags) {
|
|
350
347
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
351
348
|
if (!context)
|
|
352
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
353
|
-
if (!context
|
|
354
|
-
this.error(
|
|
349
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
350
|
+
if (!hasCredentials(context))
|
|
351
|
+
this.error(missingCredentialsMessage(context));
|
|
355
352
|
// Get data from file, --data, or --set flags
|
|
356
353
|
let items = [];
|
|
357
354
|
if (flags.file) {
|
|
@@ -561,9 +558,9 @@ export default class TaxCodes extends Command {
|
|
|
561
558
|
async runExport(flags) {
|
|
562
559
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
563
560
|
if (!context)
|
|
564
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
565
|
-
if (!context
|
|
566
|
-
this.error(
|
|
561
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
562
|
+
if (!hasCredentials(context))
|
|
563
|
+
this.error(missingCredentialsMessage(context));
|
|
567
564
|
const listEndpoint = ENDPOINTS['list'];
|
|
568
565
|
if (!listEndpoint)
|
|
569
566
|
this.error('Export requires a list endpoint');
|
|
@@ -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);
|
|
@@ -655,9 +649,9 @@ export default class TaxCodes extends Command {
|
|
|
655
649
|
async runCamt053Import(flags) {
|
|
656
650
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
657
651
|
if (!context)
|
|
658
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
659
|
-
if (!context
|
|
660
|
-
this.error(
|
|
652
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
653
|
+
if (!hasCredentials(context))
|
|
654
|
+
this.error(missingCredentialsMessage(context));
|
|
661
655
|
if (!flags.file) {
|
|
662
656
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
663
657
|
}
|
|
@@ -745,9 +739,9 @@ export default class TaxCodes extends Command {
|
|
|
745
739
|
}
|
|
746
740
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
747
741
|
if (!context)
|
|
748
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
749
|
-
if (!context
|
|
750
|
-
this.error(
|
|
742
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
743
|
+
if (!hasCredentials(context))
|
|
744
|
+
this.error(missingCredentialsMessage(context));
|
|
751
745
|
// Get data from file, --data, or --set flags
|
|
752
746
|
let items = [];
|
|
753
747
|
if (flags.file) {
|
|
@@ -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;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
3
|
-
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
3
|
+
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
6
|
const HAS_EXPORT = true;
|
|
@@ -29,7 +29,7 @@ export default class TaxMatrix extends Command {
|
|
|
29
29
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
30
30
|
};
|
|
31
31
|
static flags = {
|
|
32
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
32
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
33
33
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
34
34
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
35
35
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -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
|
};
|
|
@@ -101,9 +101,9 @@ export default class TaxMatrix extends Command {
|
|
|
101
101
|
}
|
|
102
102
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
103
103
|
if (!context)
|
|
104
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
105
|
-
if (!context
|
|
106
|
-
this.error(
|
|
104
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
105
|
+
if (!hasCredentials(context))
|
|
106
|
+
this.error(missingCredentialsMessage(context));
|
|
107
107
|
const queryParams = {};
|
|
108
108
|
if (flags.page)
|
|
109
109
|
queryParams.page = flags.page;
|
|
@@ -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);
|
|
@@ -346,9 +343,9 @@ export default class TaxMatrix extends Command {
|
|
|
346
343
|
async runImport(flags) {
|
|
347
344
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
348
345
|
if (!context)
|
|
349
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
350
|
-
if (!context
|
|
351
|
-
this.error(
|
|
346
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
347
|
+
if (!hasCredentials(context))
|
|
348
|
+
this.error(missingCredentialsMessage(context));
|
|
352
349
|
// Get data from file, --data, or --set flags
|
|
353
350
|
let items = [];
|
|
354
351
|
if (flags.file) {
|
|
@@ -558,9 +555,9 @@ export default class TaxMatrix extends Command {
|
|
|
558
555
|
async runExport(flags) {
|
|
559
556
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
560
557
|
if (!context)
|
|
561
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
562
|
-
if (!context
|
|
563
|
-
this.error(
|
|
558
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
559
|
+
if (!hasCredentials(context))
|
|
560
|
+
this.error(missingCredentialsMessage(context));
|
|
564
561
|
const listEndpoint = ENDPOINTS['list'];
|
|
565
562
|
if (!listEndpoint)
|
|
566
563
|
this.error('Export requires a list endpoint');
|
|
@@ -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);
|
|
@@ -652,9 +646,9 @@ export default class TaxMatrix extends Command {
|
|
|
652
646
|
async runCamt053Import(flags) {
|
|
653
647
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
654
648
|
if (!context)
|
|
655
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
656
|
-
if (!context
|
|
657
|
-
this.error(
|
|
649
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
650
|
+
if (!hasCredentials(context))
|
|
651
|
+
this.error(missingCredentialsMessage(context));
|
|
658
652
|
if (!flags.file) {
|
|
659
653
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
660
654
|
}
|
|
@@ -742,9 +736,9 @@ export default class TaxMatrix extends Command {
|
|
|
742
736
|
}
|
|
743
737
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
744
738
|
if (!context)
|
|
745
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
746
|
-
if (!context
|
|
747
|
-
this.error(
|
|
739
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
740
|
+
if (!hasCredentials(context))
|
|
741
|
+
this.error(missingCredentialsMessage(context));
|
|
748
742
|
// Get data from file, --data, or --set flags
|
|
749
743
|
let items = [];
|
|
750
744
|
if (flags.file) {
|
|
@@ -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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
3
|
-
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
3
|
+
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
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';
|
|
@@ -31,7 +32,7 @@ export default class Tenants extends Command {
|
|
|
31
32
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
32
33
|
};
|
|
33
34
|
static flags = {
|
|
34
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
35
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
35
36
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
36
37
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
37
38
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -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
|
};
|
|
@@ -103,9 +104,9 @@ export default class Tenants extends Command {
|
|
|
103
104
|
}
|
|
104
105
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
105
106
|
if (!context)
|
|
106
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
107
|
-
if (!context
|
|
108
|
-
this.error(
|
|
107
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
108
|
+
if (!hasCredentials(context))
|
|
109
|
+
this.error(missingCredentialsMessage(context));
|
|
109
110
|
const queryParams = {};
|
|
110
111
|
if (flags.page)
|
|
111
112
|
queryParams.page = flags.page;
|
|
@@ -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);
|
|
@@ -348,9 +346,9 @@ export default class Tenants extends Command {
|
|
|
348
346
|
async runImport(flags) {
|
|
349
347
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
350
348
|
if (!context)
|
|
351
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
352
|
-
if (!context
|
|
353
|
-
this.error(
|
|
349
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
350
|
+
if (!hasCredentials(context))
|
|
351
|
+
this.error(missingCredentialsMessage(context));
|
|
354
352
|
// Get data from file, --data, or --set flags
|
|
355
353
|
let items = [];
|
|
356
354
|
if (flags.file) {
|
|
@@ -560,9 +558,9 @@ export default class Tenants extends Command {
|
|
|
560
558
|
async runExport(flags) {
|
|
561
559
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
562
560
|
if (!context)
|
|
563
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
564
|
-
if (!context
|
|
565
|
-
this.error(
|
|
561
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
562
|
+
if (!hasCredentials(context))
|
|
563
|
+
this.error(missingCredentialsMessage(context));
|
|
566
564
|
const listEndpoint = ENDPOINTS['list'];
|
|
567
565
|
if (!listEndpoint)
|
|
568
566
|
this.error('Export requires a list endpoint');
|
|
@@ -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);
|
|
@@ -654,9 +649,9 @@ export default class Tenants extends Command {
|
|
|
654
649
|
async runCamt053Import(flags) {
|
|
655
650
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
656
651
|
if (!context)
|
|
657
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
658
|
-
if (!context
|
|
659
|
-
this.error(
|
|
652
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
653
|
+
if (!hasCredentials(context))
|
|
654
|
+
this.error(missingCredentialsMessage(context));
|
|
660
655
|
if (!flags.file) {
|
|
661
656
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
662
657
|
}
|
|
@@ -744,9 +739,9 @@ export default class Tenants extends Command {
|
|
|
744
739
|
}
|
|
745
740
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
746
741
|
if (!context)
|
|
747
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
748
|
-
if (!context
|
|
749
|
-
this.error(
|
|
742
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
743
|
+
if (!hasCredentials(context))
|
|
744
|
+
this.error(missingCredentialsMessage(context));
|
|
750
745
|
// Get data from file, --data, or --set flags
|
|
751
746
|
let items = [];
|
|
752
747
|
if (flags.file) {
|
|
@@ -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;
|