@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;
|
|
@@ -29,7 +29,7 @@ export default class OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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 OfficeLocations 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;
|
|
@@ -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;
|
|
@@ -34,7 +34,7 @@ export default class PaymentMethods extends Command {
|
|
|
34
34
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
35
35
|
};
|
|
36
36
|
static flags = {
|
|
37
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
37
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
38
38
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
39
39
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
40
40
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -49,7 +49,7 @@ export default class PaymentMethods extends Command {
|
|
|
49
49
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
50
50
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
51
51
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
52
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
52
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
53
53
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
54
54
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
55
55
|
};
|
|
@@ -107,9 +107,9 @@ export default class PaymentMethods extends Command {
|
|
|
107
107
|
}
|
|
108
108
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
109
109
|
if (!context)
|
|
110
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
111
|
-
if (!context
|
|
112
|
-
this.error(
|
|
110
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
111
|
+
if (!hasCredentials(context))
|
|
112
|
+
this.error(missingCredentialsMessage(context));
|
|
113
113
|
const queryParams = {};
|
|
114
114
|
if (flags.page)
|
|
115
115
|
queryParams.page = flags.page;
|
|
@@ -121,6 +121,8 @@ export default class PaymentMethods extends Command {
|
|
|
121
121
|
queryParams.search = flags.search;
|
|
122
122
|
if (flags['sort-by'])
|
|
123
123
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
124
|
+
if (flags.fields)
|
|
125
|
+
queryParams.fields = flags.fields;
|
|
124
126
|
if (flags.query) {
|
|
125
127
|
try {
|
|
126
128
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -323,11 +325,6 @@ export default class PaymentMethods extends Command {
|
|
|
323
325
|
output = obj[arrayKeys[0]];
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
|
-
// Filter fields if --fields flag is provided
|
|
327
|
-
if (flags.fields) {
|
|
328
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
329
|
-
output = this.filterFields(output, fieldList);
|
|
330
|
-
}
|
|
331
328
|
// Sanitize output if requested
|
|
332
329
|
if (flags.sanitize) {
|
|
333
330
|
output = this.sanitizeOutput(output);
|
|
@@ -352,9 +349,9 @@ export default class PaymentMethods extends Command {
|
|
|
352
349
|
async runImport(flags) {
|
|
353
350
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
354
351
|
if (!context)
|
|
355
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
356
|
-
if (!context
|
|
357
|
-
this.error(
|
|
352
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
353
|
+
if (!hasCredentials(context))
|
|
354
|
+
this.error(missingCredentialsMessage(context));
|
|
358
355
|
// Get data from file, --data, or --set flags
|
|
359
356
|
let items = [];
|
|
360
357
|
if (flags.file) {
|
|
@@ -564,9 +561,9 @@ export default class PaymentMethods extends Command {
|
|
|
564
561
|
async runExport(flags) {
|
|
565
562
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
566
563
|
if (!context)
|
|
567
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
568
|
-
if (!context
|
|
569
|
-
this.error(
|
|
564
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
565
|
+
if (!hasCredentials(context))
|
|
566
|
+
this.error(missingCredentialsMessage(context));
|
|
570
567
|
const listEndpoint = ENDPOINTS['list'];
|
|
571
568
|
if (!listEndpoint)
|
|
572
569
|
this.error('Export requires a list endpoint');
|
|
@@ -582,6 +579,8 @@ export default class PaymentMethods extends Command {
|
|
|
582
579
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
583
580
|
if (flags.include)
|
|
584
581
|
baseParams.include = flags.include;
|
|
582
|
+
if (flags.fields)
|
|
583
|
+
baseParams.fields = flags.fields;
|
|
585
584
|
if (flags.query) {
|
|
586
585
|
try {
|
|
587
586
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -636,12 +635,7 @@ export default class PaymentMethods extends Command {
|
|
|
636
635
|
}
|
|
637
636
|
}
|
|
638
637
|
process.stderr.write(' done\n');
|
|
639
|
-
// Filter fields if specified
|
|
640
638
|
let output = allItems;
|
|
641
|
-
if (flags.fields) {
|
|
642
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
643
|
-
output = this.filterFields(allItems, fieldList);
|
|
644
|
-
}
|
|
645
639
|
// Sanitize output if requested
|
|
646
640
|
if (flags.sanitize) {
|
|
647
641
|
output = this.sanitizeOutput(output);
|
|
@@ -658,9 +652,9 @@ export default class PaymentMethods extends Command {
|
|
|
658
652
|
async runCamt053Import(flags) {
|
|
659
653
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
660
654
|
if (!context)
|
|
661
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
662
|
-
if (!context
|
|
663
|
-
this.error(
|
|
655
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
656
|
+
if (!hasCredentials(context))
|
|
657
|
+
this.error(missingCredentialsMessage(context));
|
|
664
658
|
if (!flags.file) {
|
|
665
659
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
666
660
|
}
|
|
@@ -748,9 +742,9 @@ export default class PaymentMethods extends Command {
|
|
|
748
742
|
}
|
|
749
743
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
750
744
|
if (!context)
|
|
751
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
752
|
-
if (!context
|
|
753
|
-
this.error(
|
|
745
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
746
|
+
if (!hasCredentials(context))
|
|
747
|
+
this.error(missingCredentialsMessage(context));
|
|
754
748
|
// Get data from file, --data, or --set flags
|
|
755
749
|
let items = [];
|
|
756
750
|
if (flags.file) {
|
|
@@ -970,56 +964,6 @@ export default class PaymentMethods extends Command {
|
|
|
970
964
|
return `\$${op}`;
|
|
971
965
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
972
966
|
}
|
|
973
|
-
filterFields(data, fields) {
|
|
974
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
975
|
-
const pick = (obj, keys) => {
|
|
976
|
-
// Group keys by their first segment so sibling sub-paths
|
|
977
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
978
|
-
// and don't clobber each other on merge.
|
|
979
|
-
const directKeys = new Set();
|
|
980
|
-
const nestedKeys = new Map();
|
|
981
|
-
for (const key of keys) {
|
|
982
|
-
if (key.split('.').some(isUnsafeKey))
|
|
983
|
-
continue;
|
|
984
|
-
if (key.includes('.')) {
|
|
985
|
-
const [first, ...rest] = key.split('.');
|
|
986
|
-
if (isUnsafeKey(first))
|
|
987
|
-
continue;
|
|
988
|
-
const list = nestedKeys.get(first);
|
|
989
|
-
if (list) {
|
|
990
|
-
list.push(rest.join('.'));
|
|
991
|
-
}
|
|
992
|
-
else {
|
|
993
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
994
|
-
}
|
|
995
|
-
}
|
|
996
|
-
else {
|
|
997
|
-
directKeys.add(key);
|
|
998
|
-
}
|
|
999
|
-
}
|
|
1000
|
-
const result = {};
|
|
1001
|
-
for (const key of directKeys) {
|
|
1002
|
-
if (key in obj)
|
|
1003
|
-
result[key] = obj[key];
|
|
1004
|
-
}
|
|
1005
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1006
|
-
const val = obj[first];
|
|
1007
|
-
if (!val || typeof val !== 'object')
|
|
1008
|
-
continue;
|
|
1009
|
-
if (Array.isArray(val)) {
|
|
1010
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1011
|
-
}
|
|
1012
|
-
else {
|
|
1013
|
-
result[first] = pick(val, restKeys);
|
|
1014
|
-
}
|
|
1015
|
-
}
|
|
1016
|
-
return result;
|
|
1017
|
-
};
|
|
1018
|
-
if (Array.isArray(data)) {
|
|
1019
|
-
return data.map(item => pick(item, fields));
|
|
1020
|
-
}
|
|
1021
|
-
return pick(data, fields);
|
|
1022
|
-
}
|
|
1023
967
|
sanitizeOutput(data) {
|
|
1024
968
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1025
969
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -1,14 +1,15 @@
|
|
|
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 = [...["open-submissions", "list", "create", "preview", "schedule", "status", "get", "update", "delete", "create-payments", "delete-payments", "send", "painfile", "sync-status", "sync-status-xml", "sync-all"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["open-submissions", "eligible-payments", "list", "create", "preview", "schedule", "status", "get", "update", "delete", "create-payments", "delete-payments", "send", "painfile", "sync-status", "sync-status-xml", "sync-all"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'open-submissions': { method: 'GET', path: '/v1/payment-runs/bank-accounts/{bankAccountId}/open-submissions', summary: 'Get open submission IDs for a bank account', pathParams: ['bankAccountId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
+
'eligible-payments': { method: 'GET', path: '/v1/payment-runs/eligible-payments/{bankAccountId}', summary: 'Show what a payment run from this bank account would pay', pathParams: ['bankAccountId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
13
|
'list': { method: 'GET', path: '/v1/payment-runs', summary: 'List all payment runs with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
13
14
|
'create': { method: 'POST', path: '/v1/payment-runs', summary: 'Create a DRAFT payment run from payment IDs', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['paymentIds'] },
|
|
14
15
|
'preview': { method: 'POST', path: '/v1/payment-runs/preview/{bankAccountId}', summary: 'Preview eligible and filtered invoices for a payment run', pathParams: ['bankAccountId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['invoiceIds'] },
|
|
@@ -40,7 +41,7 @@ export default class PaymentRuns extends Command {
|
|
|
40
41
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
41
42
|
};
|
|
42
43
|
static flags = {
|
|
43
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
44
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
44
45
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
45
46
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
46
47
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -56,7 +57,7 @@ export default class PaymentRuns extends Command {
|
|
|
56
57
|
'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
|
|
57
58
|
filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
|
|
58
59
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
59
|
-
fields: Flags.string({ description: 'Comma-separated list of fields to
|
|
60
|
+
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
60
61
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
61
62
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
62
63
|
};
|
|
@@ -114,9 +115,9 @@ export default class PaymentRuns extends Command {
|
|
|
114
115
|
}
|
|
115
116
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
116
117
|
if (!context)
|
|
117
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
118
|
-
if (!context
|
|
119
|
-
this.error(
|
|
118
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
119
|
+
if (!hasCredentials(context))
|
|
120
|
+
this.error(missingCredentialsMessage(context));
|
|
120
121
|
const queryParams = {};
|
|
121
122
|
if (flags.page)
|
|
122
123
|
queryParams.page = flags.page;
|
|
@@ -128,6 +129,8 @@ export default class PaymentRuns extends Command {
|
|
|
128
129
|
queryParams.search = flags.search;
|
|
129
130
|
if (flags['sort-by'])
|
|
130
131
|
queryParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
132
|
+
if (flags.fields)
|
|
133
|
+
queryParams.fields = flags.fields;
|
|
131
134
|
if (flags.query) {
|
|
132
135
|
try {
|
|
133
136
|
Object.assign(queryParams, JSON.parse(flags.query));
|
|
@@ -330,11 +333,6 @@ export default class PaymentRuns extends Command {
|
|
|
330
333
|
output = obj[arrayKeys[0]];
|
|
331
334
|
}
|
|
332
335
|
}
|
|
333
|
-
// Filter fields if --fields flag is provided
|
|
334
|
-
if (flags.fields) {
|
|
335
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
336
|
-
output = this.filterFields(output, fieldList);
|
|
337
|
-
}
|
|
338
336
|
// Sanitize output if requested
|
|
339
337
|
if (flags.sanitize) {
|
|
340
338
|
output = this.sanitizeOutput(output);
|
|
@@ -359,9 +357,9 @@ export default class PaymentRuns extends Command {
|
|
|
359
357
|
async runImport(flags) {
|
|
360
358
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
361
359
|
if (!context)
|
|
362
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
363
|
-
if (!context
|
|
364
|
-
this.error(
|
|
360
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
361
|
+
if (!hasCredentials(context))
|
|
362
|
+
this.error(missingCredentialsMessage(context));
|
|
365
363
|
// Get data from file, --data, or --set flags
|
|
366
364
|
let items = [];
|
|
367
365
|
if (flags.file) {
|
|
@@ -571,9 +569,9 @@ export default class PaymentRuns extends Command {
|
|
|
571
569
|
async runExport(flags) {
|
|
572
570
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
573
571
|
if (!context)
|
|
574
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
575
|
-
if (!context
|
|
576
|
-
this.error(
|
|
572
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
573
|
+
if (!hasCredentials(context))
|
|
574
|
+
this.error(missingCredentialsMessage(context));
|
|
577
575
|
const listEndpoint = ENDPOINTS['list'];
|
|
578
576
|
if (!listEndpoint)
|
|
579
577
|
this.error('Export requires a list endpoint');
|
|
@@ -589,6 +587,8 @@ export default class PaymentRuns extends Command {
|
|
|
589
587
|
baseParams.sortBy = normalizeSortBy(flags['sort-by']);
|
|
590
588
|
if (flags.include)
|
|
591
589
|
baseParams.include = flags.include;
|
|
590
|
+
if (flags.fields)
|
|
591
|
+
baseParams.fields = flags.fields;
|
|
592
592
|
if (flags.query) {
|
|
593
593
|
try {
|
|
594
594
|
Object.assign(baseParams, JSON.parse(flags.query));
|
|
@@ -643,12 +643,7 @@ export default class PaymentRuns extends Command {
|
|
|
643
643
|
}
|
|
644
644
|
}
|
|
645
645
|
process.stderr.write(' done\n');
|
|
646
|
-
// Filter fields if specified
|
|
647
646
|
let output = allItems;
|
|
648
|
-
if (flags.fields) {
|
|
649
|
-
const fieldList = flags.fields.split(',').map(f => f.trim());
|
|
650
|
-
output = this.filterFields(allItems, fieldList);
|
|
651
|
-
}
|
|
652
647
|
// Sanitize output if requested
|
|
653
648
|
if (flags.sanitize) {
|
|
654
649
|
output = this.sanitizeOutput(output);
|
|
@@ -665,9 +660,9 @@ export default class PaymentRuns extends Command {
|
|
|
665
660
|
async runCamt053Import(flags) {
|
|
666
661
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
667
662
|
if (!context)
|
|
668
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
669
|
-
if (!context
|
|
670
|
-
this.error(
|
|
663
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
664
|
+
if (!hasCredentials(context))
|
|
665
|
+
this.error(missingCredentialsMessage(context));
|
|
671
666
|
if (!flags.file) {
|
|
672
667
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
673
668
|
}
|
|
@@ -755,9 +750,9 @@ export default class PaymentRuns extends Command {
|
|
|
755
750
|
}
|
|
756
751
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
757
752
|
if (!context)
|
|
758
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
759
|
-
if (!context
|
|
760
|
-
this.error(
|
|
753
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
754
|
+
if (!hasCredentials(context))
|
|
755
|
+
this.error(missingCredentialsMessage(context));
|
|
761
756
|
// Get data from file, --data, or --set flags
|
|
762
757
|
let items = [];
|
|
763
758
|
if (flags.file) {
|
|
@@ -977,56 +972,6 @@ export default class PaymentRuns extends Command {
|
|
|
977
972
|
return `\$${op}`;
|
|
978
973
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
979
974
|
}
|
|
980
|
-
filterFields(data, fields) {
|
|
981
|
-
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
982
|
-
const pick = (obj, keys) => {
|
|
983
|
-
// Group keys by their first segment so sibling sub-paths
|
|
984
|
-
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
985
|
-
// and don't clobber each other on merge.
|
|
986
|
-
const directKeys = new Set();
|
|
987
|
-
const nestedKeys = new Map();
|
|
988
|
-
for (const key of keys) {
|
|
989
|
-
if (key.split('.').some(isUnsafeKey))
|
|
990
|
-
continue;
|
|
991
|
-
if (key.includes('.')) {
|
|
992
|
-
const [first, ...rest] = key.split('.');
|
|
993
|
-
if (isUnsafeKey(first))
|
|
994
|
-
continue;
|
|
995
|
-
const list = nestedKeys.get(first);
|
|
996
|
-
if (list) {
|
|
997
|
-
list.push(rest.join('.'));
|
|
998
|
-
}
|
|
999
|
-
else {
|
|
1000
|
-
nestedKeys.set(first, [rest.join('.')]);
|
|
1001
|
-
}
|
|
1002
|
-
}
|
|
1003
|
-
else {
|
|
1004
|
-
directKeys.add(key);
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
const result = {};
|
|
1008
|
-
for (const key of directKeys) {
|
|
1009
|
-
if (key in obj)
|
|
1010
|
-
result[key] = obj[key];
|
|
1011
|
-
}
|
|
1012
|
-
for (const [first, restKeys] of nestedKeys) {
|
|
1013
|
-
const val = obj[first];
|
|
1014
|
-
if (!val || typeof val !== 'object')
|
|
1015
|
-
continue;
|
|
1016
|
-
if (Array.isArray(val)) {
|
|
1017
|
-
result[first] = val.map(item => pick(item, restKeys));
|
|
1018
|
-
}
|
|
1019
|
-
else {
|
|
1020
|
-
result[first] = pick(val, restKeys);
|
|
1021
|
-
}
|
|
1022
|
-
}
|
|
1023
|
-
return result;
|
|
1024
|
-
};
|
|
1025
|
-
if (Array.isArray(data)) {
|
|
1026
|
-
return data.map(item => pick(item, fields));
|
|
1027
|
-
}
|
|
1028
|
-
return pick(data, fields);
|
|
1029
|
-
}
|
|
1030
975
|
sanitizeOutput(data) {
|
|
1031
976
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1032
977
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|