@aderis-erp/cli 1.0.2 → 1.0.4
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 +6 -0
- package/dist/commands/access-groups 3.d.ts +40 -0
- package/dist/commands/{access-groups 2.js → access-groups 3.js } +106 -40
- package/dist/commands/access-groups.d.ts +40 -0
- package/dist/commands/access-groups.js +1074 -0
- package/dist/commands/account-transactions.d.ts +42 -0
- package/dist/commands/account-transactions.js +1088 -0
- package/dist/commands/accounts 2.d.ts +41 -0
- package/dist/commands/accounts 2.js +1078 -0
- package/dist/commands/accounts.d.ts +41 -0
- package/dist/commands/accounts.js +1080 -0
- package/dist/commands/agent-runs.d.ts +40 -0
- package/dist/commands/agent-runs.js +1071 -0
- package/dist/commands/async-endpoints-internal 3.d.ts +40 -0
- package/dist/commands/{processing-logs.js → async-endpoints-internal 3.js } +110 -46
- package/dist/commands/async-endpoints-internal.d.ts +40 -0
- package/dist/commands/async-endpoints-internal.js +1064 -0
- package/dist/commands/audit-log 3.d.ts +40 -0
- package/dist/commands/audit-log 3.js +1066 -0
- package/dist/commands/audit-log.d.ts +40 -0
- package/dist/commands/audit-log.js +1068 -0
- package/dist/commands/auth/login.d.ts +14 -0
- package/dist/commands/auth/login.js +116 -0
- package/dist/commands/auth/logout.d.ts +10 -0
- package/dist/commands/auth/logout.js +58 -0
- package/dist/commands/auth/status.d.ts +12 -0
- package/dist/commands/auth/status.js +101 -0
- package/dist/commands/auth/tenant.d.ts +19 -0
- package/dist/commands/auth/tenant.js +184 -0
- package/dist/commands/auth.d.ts +37 -0
- package/dist/commands/auth.js +871 -0
- package/dist/commands/bank-accounts.d.ts +42 -0
- package/dist/commands/bank-accounts.js +1088 -0
- package/dist/commands/bank-integrations.d.ts +1 -0
- package/dist/commands/bank-integrations.js +122 -54
- package/dist/commands/business-partners 3.d.ts +41 -0
- package/dist/commands/business-partners 3.js +1078 -0
- package/dist/commands/business-partners---contacts 3.d.ts +42 -0
- package/dist/commands/business-partners---contacts 3.js +1072 -0
- package/dist/commands/business-partners---contacts.d.ts +1 -0
- package/dist/commands/business-partners---contacts.js +114 -46
- package/dist/commands/business-partners.d.ts +1 -0
- package/dist/commands/business-partners.js +114 -46
- package/dist/commands/config/add.d.ts +13 -0
- package/dist/commands/config/add.js +120 -0
- package/dist/commands/config/current.d.ts +9 -0
- package/dist/commands/config/current.js +43 -0
- package/dist/commands/config/delete.d.ts +12 -0
- package/dist/commands/config/delete.js +67 -0
- package/dist/commands/config/list.d.ts +9 -0
- package/dist/commands/config/list.js +50 -0
- package/dist/commands/config/use.d.ts +9 -0
- package/dist/commands/config/use.js +40 -0
- package/dist/commands/credit-card-accounts 3.d.ts +42 -0
- package/dist/commands/credit-card-accounts 3.js +1084 -0
- package/dist/commands/credit-card-accounts.d.ts +1 -0
- package/dist/commands/credit-card-accounts.js +119 -51
- package/dist/commands/documents.d.ts +1 -0
- package/dist/commands/documents.js +110 -42
- package/dist/commands/dunning-configs 3.d.ts +40 -0
- package/dist/commands/dunning-configs 3.js +1072 -0
- package/dist/commands/dunning-configs.d.ts +1 -0
- package/dist/commands/dunning-configs.js +109 -41
- package/dist/commands/dunning-reminders.d.ts +1 -0
- package/dist/commands/dunning-reminders.js +112 -44
- package/dist/commands/dunning-runs 3.d.ts +40 -0
- package/dist/commands/{pubsub.js → dunning-runs 3.js } +108 -43
- package/dist/commands/dunning-runs.d.ts +1 -0
- package/dist/commands/dunning-runs.js +105 -37
- package/dist/commands/employees.d.ts +1 -0
- package/dist/commands/employees.js +136 -68
- package/dist/commands/event-processor-mappings 3.d.ts +40 -0
- package/dist/commands/event-processor-mappings 3.js +1071 -0
- package/dist/commands/event-processor-mappings.d.ts +1 -0
- package/dist/commands/event-processor-mappings.js +109 -41
- package/dist/commands/files-internal 3.d.ts +40 -0
- package/dist/commands/files-internal 3.js +1073 -0
- package/dist/commands/files-internal.d.ts +1 -0
- package/dist/commands/files-internal.js +113 -45
- package/dist/commands/health 3.d.ts +40 -0
- package/dist/commands/health 3.js +1067 -0
- package/dist/commands/health.d.ts +1 -0
- package/dist/commands/health.js +109 -41
- package/dist/commands/{pubsub.d.ts → inbox 3.d.ts } +2 -1
- package/dist/commands/inbox 3.js +1065 -0
- package/dist/commands/inbox.d.ts +1 -0
- package/dist/commands/inbox.js +110 -40
- package/dist/commands/integrations 3.d.ts +41 -0
- package/dist/commands/integrations 3.js +1067 -0
- package/dist/commands/integrations.d.ts +1 -0
- package/dist/commands/integrations.js +107 -39
- package/dist/commands/item-categories 3.d.ts +40 -0
- package/dist/commands/item-categories 3.js +1072 -0
- package/dist/commands/item-categories.d.ts +1 -0
- package/dist/commands/item-categories.js +109 -41
- package/dist/commands/items 3.d.ts +40 -0
- package/dist/commands/items 3.js +1072 -0
- package/dist/commands/items.d.ts +1 -0
- package/dist/commands/items.js +109 -41
- package/dist/commands/journal-lines.d.ts +1 -0
- package/dist/commands/journal-lines.js +105 -37
- package/dist/commands/journals 3.d.ts +42 -0
- package/dist/commands/journals 3.js +1088 -0
- package/dist/commands/journals.d.ts +1 -0
- package/dist/commands/journals.js +123 -55
- package/dist/commands/ledgers.d.ts +1 -0
- package/dist/commands/ledgers.js +120 -52
- package/dist/commands/office-locations 3.d.ts +40 -0
- package/dist/commands/office-locations 3.js +1072 -0
- package/dist/commands/office-locations.d.ts +1 -0
- package/dist/commands/office-locations.js +109 -41
- package/dist/commands/payment-method-ledger-mappings 3.d.ts +41 -0
- package/dist/commands/payment-method-ledger-mappings 3.js +1066 -0
- package/dist/commands/payment-method-ledger-mappings.d.ts +1 -0
- package/dist/commands/payment-method-ledger-mappings.js +109 -41
- package/dist/commands/payment-methods 3.d.ts +40 -0
- package/dist/commands/payment-methods 3.js +1072 -0
- package/dist/commands/payment-methods.d.ts +1 -0
- package/dist/commands/payment-methods.js +109 -41
- package/dist/commands/payment-runs 3.d.ts +42 -0
- package/dist/commands/payment-runs 3.js +1087 -0
- package/dist/commands/payment-runs.d.ts +1 -0
- package/dist/commands/payment-runs.js +122 -54
- package/dist/commands/payment-terms 3.d.ts +40 -0
- package/dist/commands/payment-terms 3.js +1073 -0
- package/dist/commands/payment-terms.d.ts +1 -0
- package/dist/commands/payment-terms.js +110 -42
- package/dist/commands/price-lists 3.d.ts +41 -0
- package/dist/commands/price-lists 3.js +1078 -0
- package/dist/commands/price-lists.d.ts +1 -0
- package/dist/commands/price-lists.js +114 -46
- package/dist/commands/processor-mappings 2.d.ts +40 -0
- package/dist/commands/processor-mappings 2.js +1070 -0
- package/dist/commands/processor-mappings.d.ts +1 -0
- package/dist/commands/processor-mappings.js +108 -40
- package/dist/commands/processors.d.ts +1 -0
- package/dist/commands/processors.js +113 -45
- package/dist/commands/reconciliation 3.d.ts +40 -0
- package/dist/commands/reconciliation 3.js +1069 -0
- package/dist/commands/reconciliation.d.ts +1 -0
- package/dist/commands/reconciliation.js +110 -42
- package/dist/commands/reports.d.ts +1 -0
- package/dist/commands/reports.js +110 -39
- package/dist/commands/salary-types 3.d.ts +40 -0
- package/dist/commands/salary-types 3.js +1072 -0
- package/dist/commands/salary-types.d.ts +1 -0
- package/dist/commands/salary-types.js +1074 -0
- package/dist/commands/sales-invoices 3.d.ts +43 -0
- package/dist/commands/sales-invoices 3.js +1100 -0
- package/dist/commands/sales-invoices.d.ts +1 -0
- package/dist/commands/sales-invoices.js +134 -66
- package/dist/commands/sales-orders 3.d.ts +43 -0
- package/dist/commands/sales-orders 3.js +1098 -0
- package/dist/commands/sales-orders.d.ts +1 -0
- package/dist/commands/sales-orders.js +133 -64
- package/dist/commands/switch.d.ts +1 -0
- package/dist/commands/switch.js +58 -3
- package/dist/commands/{processing-logs.d.ts → tags 3.d.ts } +2 -1
- package/dist/commands/tags 3.js +1072 -0
- package/dist/commands/tags.d.ts +1 -0
- package/dist/commands/tags.js +109 -41
- package/dist/commands/tax-codes 3.d.ts +40 -0
- package/dist/commands/tax-codes 3.js +1075 -0
- package/dist/commands/tax-codes.d.ts +1 -0
- package/dist/commands/tax-codes.js +112 -44
- package/dist/commands/tax-matrix.d.ts +1 -0
- package/dist/commands/tax-matrix.js +109 -41
- package/dist/commands/tenants.d.ts +1 -0
- package/dist/commands/tenants.js +109 -41
- package/dist/commands/text-templates 3.d.ts +40 -0
- package/dist/commands/text-templates 3.js +1072 -0
- package/dist/commands/text-templates.d.ts +1 -0
- package/dist/commands/text-templates.js +109 -41
- package/dist/commands/tools.d.ts +1 -0
- package/dist/commands/tools.js +106 -38
- package/dist/commands/vendor-invoices.d.ts +1 -0
- package/dist/commands/vendor-invoices.js +139 -69
- package/dist/commands/webhooks 3.d.ts +40 -0
- package/dist/commands/webhooks 3.js +1074 -0
- package/dist/commands/webhooks.d.ts +1 -0
- package/dist/commands/webhooks.js +111 -43
- package/dist/commands/workflows.d.ts +1 -0
- package/dist/commands/workflows.js +107 -39
- package/dist/lib/api-client.d.ts +5 -1
- package/dist/lib/api-client.js +19 -5
- package/dist/lib/auth.d.ts +16 -1
- package/dist/lib/auth.js +170 -45
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +7 -1
- package/oclif.manifest.json +7464 -653
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class AccessGroups extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
context: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
table: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
'sort-by': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
filter: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
+
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
|
+
};
|
|
28
|
+
run(): Promise<void>;
|
|
29
|
+
private runImport;
|
|
30
|
+
private runExport;
|
|
31
|
+
private runCamt053Import;
|
|
32
|
+
private runNestedImport;
|
|
33
|
+
private parseFilterValue;
|
|
34
|
+
private filterFields;
|
|
35
|
+
private sanitizeOutput;
|
|
36
|
+
private getColumns;
|
|
37
|
+
private getValue;
|
|
38
|
+
private printTable;
|
|
39
|
+
private printCsv;
|
|
40
|
+
}
|
|
@@ -8,11 +8,11 @@ const HAS_CAMT053 = false;
|
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
9
|
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'list': { method: 'GET', path: '/v1/access-groups', summary: 'List access groups (paginated)', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/access-groups', summary: 'Create a new access group', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'get': { method: 'GET', path: '/v1/access-groups/{id}', summary: 'Get a single access group by ID', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/access-groups/{id}', summary: 'Update an existing access group', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
15
|
-
'delete': { method: 'DELETE', path: '/v1/access-groups/{id}', summary: 'Delete an access group', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/access-groups', summary: 'List access groups (paginated)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/access-groups', summary: 'Create a new access group', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['types', 'employeeIds'] },
|
|
13
|
+
'get': { method: 'GET', path: '/v1/access-groups/{id}', summary: 'Get a single access group by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
14
|
+
'update': { method: 'PATCH', path: '/v1/access-groups/{id}', summary: 'Update an existing access group', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['types', 'employeeIds'] },
|
|
15
|
+
'delete': { method: 'DELETE', path: '/v1/access-groups/{id}', summary: 'Delete an access group', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
16
|
};
|
|
17
17
|
export default class AccessGroups extends Command {
|
|
18
18
|
static description = 'Manage access groups';
|
|
@@ -130,15 +130,7 @@ export default class AccessGroups extends Command {
|
|
|
130
130
|
if (eqIndex === -1)
|
|
131
131
|
this.error(`Invalid --filter format: ${f}. Use: --filter key=value`);
|
|
132
132
|
const key = f.slice(0, eqIndex);
|
|
133
|
-
|
|
134
|
-
// Check for operator prefix (with or without $)
|
|
135
|
-
const opMatch = value.match(/^\$?(eq|ne|in|like|gt|gte|lt|lte|null):/);
|
|
136
|
-
if (opMatch) {
|
|
137
|
-
value = `\$${opMatch[1]}:${value.slice(opMatch[0].length)}`;
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
value = `\$eq:${value}`;
|
|
141
|
-
}
|
|
133
|
+
const value = this.parseFilterValue(f.slice(eqIndex + 1));
|
|
142
134
|
const filterKey = `filter.${key}`;
|
|
143
135
|
if (filterKey in queryParams) {
|
|
144
136
|
// Multiple filters on same field: collect as array
|
|
@@ -193,6 +185,7 @@ export default class AccessGroups extends Command {
|
|
|
193
185
|
if (!data)
|
|
194
186
|
data = {};
|
|
195
187
|
const body = data;
|
|
188
|
+
const arrayFields = new Set(endpoint.bodyArrayFields);
|
|
196
189
|
for (const pair of flags.set) {
|
|
197
190
|
const eqIndex = pair.indexOf('=');
|
|
198
191
|
if (eqIndex === -1)
|
|
@@ -204,6 +197,19 @@ export default class AccessGroups extends Command {
|
|
|
204
197
|
value = JSON.parse(value);
|
|
205
198
|
}
|
|
206
199
|
catch { /* keep as string */ }
|
|
200
|
+
// For top-level keys typed as array in the API schema, split bare
|
|
201
|
+
// comma-separated input (e.g. "1171,1170" -> ["1171","1170"]) and
|
|
202
|
+
// wrap a lone scalar in a single-element array. Skips when --set
|
|
203
|
+
// already provided a JSON array.
|
|
204
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
205
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
206
|
+
if (typeof value === 'string') {
|
|
207
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
208
|
+
}
|
|
209
|
+
else if (value !== undefined && value !== null) {
|
|
210
|
+
value = [value];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
207
213
|
// Support nested keys like "address.city"
|
|
208
214
|
const keys = key.split('.');
|
|
209
215
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
@@ -254,6 +260,26 @@ export default class AccessGroups extends Command {
|
|
|
254
260
|
process.stderr.write('\n');
|
|
255
261
|
}
|
|
256
262
|
try {
|
|
263
|
+
// Binary response: download to file
|
|
264
|
+
if (endpoint.isBinaryResponse) {
|
|
265
|
+
if (!flags.file) {
|
|
266
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx).`);
|
|
267
|
+
}
|
|
268
|
+
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
269
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
270
|
+
data,
|
|
271
|
+
contextName: flags.context,
|
|
272
|
+
binary: true,
|
|
273
|
+
});
|
|
274
|
+
const fsModule = await import('node:fs');
|
|
275
|
+
const binData = binResponse.data;
|
|
276
|
+
const buffer = Buffer.isBuffer(binData)
|
|
277
|
+
? binData
|
|
278
|
+
: Buffer.from(binData);
|
|
279
|
+
fsModule.writeFileSync(flags.file, buffer);
|
|
280
|
+
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
257
283
|
const response = await apiRequest(endpoint.method, apiPath, {
|
|
258
284
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
259
285
|
data,
|
|
@@ -344,6 +370,7 @@ export default class AccessGroups extends Command {
|
|
|
344
370
|
}
|
|
345
371
|
else if (flags.set && flags.set.length > 0) {
|
|
346
372
|
const item = {};
|
|
373
|
+
const arrayFields = new Set(ENDPOINTS['create']?.bodyArrayFields ?? []);
|
|
347
374
|
for (const pair of flags.set) {
|
|
348
375
|
const eqIndex = pair.indexOf('=');
|
|
349
376
|
if (eqIndex === -1)
|
|
@@ -354,6 +381,15 @@ export default class AccessGroups extends Command {
|
|
|
354
381
|
value = JSON.parse(value);
|
|
355
382
|
}
|
|
356
383
|
catch { /* keep as string */ }
|
|
384
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
385
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
386
|
+
if (typeof value === 'string') {
|
|
387
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
388
|
+
}
|
|
389
|
+
else if (value !== undefined && value !== null) {
|
|
390
|
+
value = [value];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
357
393
|
const keys = key.split('.');
|
|
358
394
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
359
395
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -503,14 +539,7 @@ export default class AccessGroups extends Command {
|
|
|
503
539
|
if (eqIndex === -1)
|
|
504
540
|
this.error(`Invalid --filter format: ${f}. Use: --filter key=value`);
|
|
505
541
|
const key = f.slice(0, eqIndex);
|
|
506
|
-
|
|
507
|
-
const opMatch = value.match(/^\$?(eq|ne|in|like|gt|gte|lt|lte|null):/);
|
|
508
|
-
if (opMatch) {
|
|
509
|
-
value = `\$${opMatch[1]}:${value.slice(opMatch[0].length)}`;
|
|
510
|
-
}
|
|
511
|
-
else {
|
|
512
|
-
value = `\$eq:${value}`;
|
|
513
|
-
}
|
|
542
|
+
const value = this.parseFilterValue(f.slice(eqIndex + 1));
|
|
514
543
|
const filterKey = `filter.${key}`;
|
|
515
544
|
if (filterKey in baseParams) {
|
|
516
545
|
const existing = baseParams[filterKey];
|
|
@@ -687,6 +716,7 @@ export default class AccessGroups extends Command {
|
|
|
687
716
|
}
|
|
688
717
|
else if (flags.set && flags.set.length > 0) {
|
|
689
718
|
const item = {};
|
|
719
|
+
const arrayFields = new Set(ENDPOINTS[`create-${suffix}`]?.bodyArrayFields ?? []);
|
|
690
720
|
for (const pair of flags.set) {
|
|
691
721
|
const eqIndex = pair.indexOf('=');
|
|
692
722
|
if (eqIndex === -1)
|
|
@@ -697,6 +727,15 @@ export default class AccessGroups extends Command {
|
|
|
697
727
|
value = JSON.parse(value);
|
|
698
728
|
}
|
|
699
729
|
catch { /* keep as string */ }
|
|
730
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
731
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
732
|
+
if (typeof value === 'string') {
|
|
733
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
734
|
+
}
|
|
735
|
+
else if (value !== undefined && value !== null) {
|
|
736
|
+
value = [value];
|
|
737
|
+
}
|
|
738
|
+
}
|
|
700
739
|
const keys = key.split('.');
|
|
701
740
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
702
741
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -816,35 +855,62 @@ export default class AccessGroups extends Command {
|
|
|
816
855
|
this.log('');
|
|
817
856
|
this.log(`Summary: ${created} created, ${updated} updated, ${errors.length} failed`);
|
|
818
857
|
}
|
|
858
|
+
parseFilterValue(value) {
|
|
859
|
+
// Recognises the nestjs-paginate operator set (with or without the leading $)
|
|
860
|
+
// and recursively unwraps chained operators like 'not:null' -> '$not:$null'
|
|
861
|
+
// or 'not:like:John' -> '$not:$like:John'. Falls back to '$eq:<value>' when
|
|
862
|
+
// no operator prefix is present.
|
|
863
|
+
const opRe = /^\$?(and|or|not|eq|gt|gte|in|null|lt|lte|btw|ne|ilike|like|sw|contains)(?::|$)/;
|
|
864
|
+
const m = value.match(opRe);
|
|
865
|
+
if (!m)
|
|
866
|
+
return `\$eq:${value}`;
|
|
867
|
+
const op = m[1];
|
|
868
|
+
const rest = value.slice(m[0].length);
|
|
869
|
+
if (rest === '')
|
|
870
|
+
return `\$${op}`;
|
|
871
|
+
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
872
|
+
}
|
|
819
873
|
filterFields(data, fields) {
|
|
820
874
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
821
875
|
const pick = (obj, keys) => {
|
|
822
|
-
|
|
876
|
+
// Group keys by their first segment so sibling sub-paths
|
|
877
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
878
|
+
// and don't clobber each other on merge.
|
|
879
|
+
const directKeys = new Set();
|
|
880
|
+
const nestedKeys = new Map();
|
|
823
881
|
for (const key of keys) {
|
|
824
882
|
if (key.split('.').some(isUnsafeKey))
|
|
825
883
|
continue;
|
|
826
884
|
if (key.includes('.')) {
|
|
827
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
828
885
|
const [first, ...rest] = key.split('.');
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
...pick(item, [restKey]),
|
|
838
|
-
}));
|
|
839
|
-
}
|
|
840
|
-
else {
|
|
841
|
-
const nested = pick(val, [restKey]);
|
|
842
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
843
|
-
}
|
|
886
|
+
if (isUnsafeKey(first))
|
|
887
|
+
continue;
|
|
888
|
+
const list = nestedKeys.get(first);
|
|
889
|
+
if (list) {
|
|
890
|
+
list.push(rest.join('.'));
|
|
891
|
+
}
|
|
892
|
+
else {
|
|
893
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
844
894
|
}
|
|
845
895
|
}
|
|
846
|
-
else
|
|
896
|
+
else {
|
|
897
|
+
directKeys.add(key);
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
const result = {};
|
|
901
|
+
for (const key of directKeys) {
|
|
902
|
+
if (key in obj)
|
|
847
903
|
result[key] = obj[key];
|
|
904
|
+
}
|
|
905
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
906
|
+
const val = obj[first];
|
|
907
|
+
if (!val || typeof val !== 'object')
|
|
908
|
+
continue;
|
|
909
|
+
if (Array.isArray(val)) {
|
|
910
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
911
|
+
}
|
|
912
|
+
else {
|
|
913
|
+
result[first] = pick(val, restKeys);
|
|
848
914
|
}
|
|
849
915
|
}
|
|
850
916
|
return result;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class AccessGroups extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static args: {
|
|
6
|
+
action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
|
+
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
|
+
};
|
|
9
|
+
static flags: {
|
|
10
|
+
context: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
|
+
output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
table: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
'sort-by': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
filter: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
+
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
|
+
};
|
|
28
|
+
run(): Promise<void>;
|
|
29
|
+
private runImport;
|
|
30
|
+
private runExport;
|
|
31
|
+
private runCamt053Import;
|
|
32
|
+
private runNestedImport;
|
|
33
|
+
private parseFilterValue;
|
|
34
|
+
private filterFields;
|
|
35
|
+
private sanitizeOutput;
|
|
36
|
+
private getColumns;
|
|
37
|
+
private getValue;
|
|
38
|
+
private printTable;
|
|
39
|
+
private printCsv;
|
|
40
|
+
}
|