@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
|
@@ -8,14 +8,14 @@ const HAS_CAMT053 = false;
|
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
9
|
const SUBCOMMANDS = [...["list", "create", "tax-codes-standard-rate", "get-by-country-rate", "get-by-code-at-date", "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/tax/tax-codes', summary: 'Get all tax codes with pagination', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/tax/tax-codes', summary: 'Create a new tax code', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'tax-codes-standard-rate': { method: 'GET', path: '/v1/tax/tax-codes/standard-rate', summary: 'Get the standard-rate tax code for a country at a specific date', pathParams: [], hasBody: false, isMultipart: false },
|
|
14
|
-
'get-by-country-rate': { method: 'GET', path: '/v1/tax/tax-codes/by-country-rate', summary: 'Get tax code by country and rate at a specific date', pathParams: [], hasBody: false, isMultipart: false },
|
|
15
|
-
'get-by-code-at-date': { method: 'GET', path: '/v1/tax/tax-codes/by-code-at-date', summary: 'Get tax code by code at a specific date', pathParams: [], hasBody: false, isMultipart: false },
|
|
16
|
-
'get': { method: 'GET', path: '/v1/tax/tax-codes/{id}', summary: 'Get a tax code by ID', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
17
|
-
'update': { method: 'PATCH', path: '/v1/tax/tax-codes/{id}', summary: 'Update a tax code', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
18
|
-
'delete': { method: 'DELETE', path: '/v1/tax/tax-codes/{id}', summary: 'Delete a tax code', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/tax/tax-codes', summary: 'Get all tax codes with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tax/tax-codes', summary: 'Create a new tax code', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
13
|
+
'tax-codes-standard-rate': { method: 'GET', path: '/v1/tax/tax-codes/standard-rate', summary: 'Get the standard-rate tax code for a country at a specific date', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
14
|
+
'get-by-country-rate': { method: 'GET', path: '/v1/tax/tax-codes/by-country-rate', summary: 'Get tax code by country and rate at a specific date', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
15
|
+
'get-by-code-at-date': { method: 'GET', path: '/v1/tax/tax-codes/by-code-at-date', summary: 'Get tax code by code at a specific date', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
|
+
'get': { method: 'GET', path: '/v1/tax/tax-codes/{id}', summary: 'Get a tax code by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
17
|
+
'update': { method: 'PATCH', path: '/v1/tax/tax-codes/{id}', summary: 'Update a tax code', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
18
|
+
'delete': { method: 'DELETE', path: '/v1/tax/tax-codes/{id}', summary: 'Delete a tax code', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
19
19
|
};
|
|
20
20
|
export default class TaxCodes extends Command {
|
|
21
21
|
static description = 'Manage tax codes';
|
|
@@ -133,15 +133,7 @@ export default class TaxCodes extends Command {
|
|
|
133
133
|
if (eqIndex === -1)
|
|
134
134
|
this.error(`Invalid --filter format: ${f}. Use: --filter key=value`);
|
|
135
135
|
const key = f.slice(0, eqIndex);
|
|
136
|
-
|
|
137
|
-
// Check for operator prefix (with or without $)
|
|
138
|
-
const opMatch = value.match(/^\$?(eq|ne|in|like|gt|gte|lt|lte|null):/);
|
|
139
|
-
if (opMatch) {
|
|
140
|
-
value = `\$${opMatch[1]}:${value.slice(opMatch[0].length)}`;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
value = `\$eq:${value}`;
|
|
144
|
-
}
|
|
136
|
+
const value = this.parseFilterValue(f.slice(eqIndex + 1));
|
|
145
137
|
const filterKey = `filter.${key}`;
|
|
146
138
|
if (filterKey in queryParams) {
|
|
147
139
|
// Multiple filters on same field: collect as array
|
|
@@ -174,7 +166,9 @@ export default class TaxCodes extends Command {
|
|
|
174
166
|
data = form;
|
|
175
167
|
}
|
|
176
168
|
else if (endpoint.hasBody) {
|
|
177
|
-
|
|
169
|
+
// For binary-response endpoints, --file is the output path, not a JSON
|
|
170
|
+
// input file — skip the read-as-body branch.
|
|
171
|
+
if (flags.file && !endpoint.isBinaryResponse) {
|
|
178
172
|
const fsModule = await import('node:fs');
|
|
179
173
|
try {
|
|
180
174
|
data = JSON.parse(fsModule.readFileSync(flags.file, 'utf-8'));
|
|
@@ -196,6 +190,7 @@ export default class TaxCodes extends Command {
|
|
|
196
190
|
if (!data)
|
|
197
191
|
data = {};
|
|
198
192
|
const body = data;
|
|
193
|
+
const arrayFields = new Set(endpoint.bodyArrayFields);
|
|
199
194
|
for (const pair of flags.set) {
|
|
200
195
|
const eqIndex = pair.indexOf('=');
|
|
201
196
|
if (eqIndex === -1)
|
|
@@ -207,6 +202,19 @@ export default class TaxCodes extends Command {
|
|
|
207
202
|
value = JSON.parse(value);
|
|
208
203
|
}
|
|
209
204
|
catch { /* keep as string */ }
|
|
205
|
+
// For top-level keys typed as array in the API schema, split bare
|
|
206
|
+
// comma-separated input (e.g. "1171,1170" -> ["1171","1170"]) and
|
|
207
|
+
// wrap a lone scalar in a single-element array. Skips when --set
|
|
208
|
+
// already provided a JSON array.
|
|
209
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
210
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
211
|
+
if (typeof value === 'string') {
|
|
212
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
213
|
+
}
|
|
214
|
+
else if (value !== undefined && value !== null) {
|
|
215
|
+
value = [value];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
210
218
|
// Support nested keys like "address.city"
|
|
211
219
|
const keys = key.split('.');
|
|
212
220
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
@@ -257,6 +265,26 @@ export default class TaxCodes extends Command {
|
|
|
257
265
|
process.stderr.write('\n');
|
|
258
266
|
}
|
|
259
267
|
try {
|
|
268
|
+
// Binary response: download to file
|
|
269
|
+
if (endpoint.isBinaryResponse) {
|
|
270
|
+
if (!flags.file) {
|
|
271
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx).`);
|
|
272
|
+
}
|
|
273
|
+
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
274
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
275
|
+
data,
|
|
276
|
+
contextName: flags.context,
|
|
277
|
+
binary: true,
|
|
278
|
+
});
|
|
279
|
+
const fsModule = await import('node:fs');
|
|
280
|
+
const binData = binResponse.data;
|
|
281
|
+
const buffer = Buffer.isBuffer(binData)
|
|
282
|
+
? binData
|
|
283
|
+
: Buffer.from(binData);
|
|
284
|
+
fsModule.writeFileSync(flags.file, buffer);
|
|
285
|
+
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
260
288
|
const response = await apiRequest(endpoint.method, apiPath, {
|
|
261
289
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
262
290
|
data,
|
|
@@ -347,6 +375,7 @@ export default class TaxCodes extends Command {
|
|
|
347
375
|
}
|
|
348
376
|
else if (flags.set && flags.set.length > 0) {
|
|
349
377
|
const item = {};
|
|
378
|
+
const arrayFields = new Set(ENDPOINTS['create']?.bodyArrayFields ?? []);
|
|
350
379
|
for (const pair of flags.set) {
|
|
351
380
|
const eqIndex = pair.indexOf('=');
|
|
352
381
|
if (eqIndex === -1)
|
|
@@ -357,6 +386,15 @@ export default class TaxCodes extends Command {
|
|
|
357
386
|
value = JSON.parse(value);
|
|
358
387
|
}
|
|
359
388
|
catch { /* keep as string */ }
|
|
389
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
390
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
391
|
+
if (typeof value === 'string') {
|
|
392
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
393
|
+
}
|
|
394
|
+
else if (value !== undefined && value !== null) {
|
|
395
|
+
value = [value];
|
|
396
|
+
}
|
|
397
|
+
}
|
|
360
398
|
const keys = key.split('.');
|
|
361
399
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
362
400
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -506,14 +544,7 @@ export default class TaxCodes extends Command {
|
|
|
506
544
|
if (eqIndex === -1)
|
|
507
545
|
this.error(`Invalid --filter format: ${f}. Use: --filter key=value`);
|
|
508
546
|
const key = f.slice(0, eqIndex);
|
|
509
|
-
|
|
510
|
-
const opMatch = value.match(/^\$?(eq|ne|in|like|gt|gte|lt|lte|null):/);
|
|
511
|
-
if (opMatch) {
|
|
512
|
-
value = `\$${opMatch[1]}:${value.slice(opMatch[0].length)}`;
|
|
513
|
-
}
|
|
514
|
-
else {
|
|
515
|
-
value = `\$eq:${value}`;
|
|
516
|
-
}
|
|
547
|
+
const value = this.parseFilterValue(f.slice(eqIndex + 1));
|
|
517
548
|
const filterKey = `filter.${key}`;
|
|
518
549
|
if (filterKey in baseParams) {
|
|
519
550
|
const existing = baseParams[filterKey];
|
|
@@ -690,6 +721,7 @@ export default class TaxCodes extends Command {
|
|
|
690
721
|
}
|
|
691
722
|
else if (flags.set && flags.set.length > 0) {
|
|
692
723
|
const item = {};
|
|
724
|
+
const arrayFields = new Set(ENDPOINTS[`create-${suffix}`]?.bodyArrayFields ?? []);
|
|
693
725
|
for (const pair of flags.set) {
|
|
694
726
|
const eqIndex = pair.indexOf('=');
|
|
695
727
|
if (eqIndex === -1)
|
|
@@ -700,6 +732,15 @@ export default class TaxCodes extends Command {
|
|
|
700
732
|
value = JSON.parse(value);
|
|
701
733
|
}
|
|
702
734
|
catch { /* keep as string */ }
|
|
735
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
736
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
737
|
+
if (typeof value === 'string') {
|
|
738
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
739
|
+
}
|
|
740
|
+
else if (value !== undefined && value !== null) {
|
|
741
|
+
value = [value];
|
|
742
|
+
}
|
|
743
|
+
}
|
|
703
744
|
const keys = key.split('.');
|
|
704
745
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
705
746
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -819,35 +860,62 @@ export default class TaxCodes extends Command {
|
|
|
819
860
|
this.log('');
|
|
820
861
|
this.log(`Summary: ${created} created, ${updated} updated, ${errors.length} failed`);
|
|
821
862
|
}
|
|
863
|
+
parseFilterValue(value) {
|
|
864
|
+
// Recognises the nestjs-paginate operator set (with or without the leading $)
|
|
865
|
+
// and recursively unwraps chained operators like 'not:null' -> '$not:$null'
|
|
866
|
+
// or 'not:like:John' -> '$not:$like:John'. Falls back to '$eq:<value>' when
|
|
867
|
+
// no operator prefix is present.
|
|
868
|
+
const opRe = /^\$?(and|or|not|eq|gt|gte|in|null|lt|lte|btw|ne|ilike|like|sw|contains)(?::|$)/;
|
|
869
|
+
const m = value.match(opRe);
|
|
870
|
+
if (!m)
|
|
871
|
+
return `\$eq:${value}`;
|
|
872
|
+
const op = m[1];
|
|
873
|
+
const rest = value.slice(m[0].length);
|
|
874
|
+
if (rest === '')
|
|
875
|
+
return `\$${op}`;
|
|
876
|
+
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
877
|
+
}
|
|
822
878
|
filterFields(data, fields) {
|
|
823
879
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
824
880
|
const pick = (obj, keys) => {
|
|
825
|
-
|
|
881
|
+
// Group keys by their first segment so sibling sub-paths
|
|
882
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
883
|
+
// and don't clobber each other on merge.
|
|
884
|
+
const directKeys = new Set();
|
|
885
|
+
const nestedKeys = new Map();
|
|
826
886
|
for (const key of keys) {
|
|
827
887
|
if (key.split('.').some(isUnsafeKey))
|
|
828
888
|
continue;
|
|
829
889
|
if (key.includes('.')) {
|
|
830
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
831
890
|
const [first, ...rest] = key.split('.');
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
...pick(item, [restKey]),
|
|
841
|
-
}));
|
|
842
|
-
}
|
|
843
|
-
else {
|
|
844
|
-
const nested = pick(val, [restKey]);
|
|
845
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
846
|
-
}
|
|
891
|
+
if (isUnsafeKey(first))
|
|
892
|
+
continue;
|
|
893
|
+
const list = nestedKeys.get(first);
|
|
894
|
+
if (list) {
|
|
895
|
+
list.push(rest.join('.'));
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
847
899
|
}
|
|
848
900
|
}
|
|
849
|
-
else
|
|
901
|
+
else {
|
|
902
|
+
directKeys.add(key);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
const result = {};
|
|
906
|
+
for (const key of directKeys) {
|
|
907
|
+
if (key in obj)
|
|
850
908
|
result[key] = obj[key];
|
|
909
|
+
}
|
|
910
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
911
|
+
const val = obj[first];
|
|
912
|
+
if (!val || typeof val !== 'object')
|
|
913
|
+
continue;
|
|
914
|
+
if (Array.isArray(val)) {
|
|
915
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
result[first] = pick(val, restKeys);
|
|
851
919
|
}
|
|
852
920
|
}
|
|
853
921
|
return result;
|
|
@@ -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/tax/tax-matrix', summary: 'Get all tax matrix mappings with pagination', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/tax/tax-matrix', summary: 'Create a new tax matrix mapping', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'get': { method: 'GET', path: '/v1/tax/tax-matrix/{id}', summary: 'Get a tax matrix mapping by ID', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/tax/tax-matrix/{id}', summary: 'Update a tax matrix mapping', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
15
|
-
'delete': { method: 'DELETE', path: '/v1/tax/tax-matrix/{id}', summary: 'Delete a tax matrix mapping', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/tax/tax-matrix', summary: 'Get all tax matrix mappings with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tax/tax-matrix', summary: 'Create a new tax matrix mapping', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
13
|
+
'get': { method: 'GET', path: '/v1/tax/tax-matrix/{id}', summary: 'Get a tax matrix mapping by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
14
|
+
'update': { method: 'PATCH', path: '/v1/tax/tax-matrix/{id}', summary: 'Update a tax matrix mapping', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
15
|
+
'delete': { method: 'DELETE', path: '/v1/tax/tax-matrix/{id}', summary: 'Delete a tax matrix mapping', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
16
|
};
|
|
17
17
|
export default class TaxMatrix extends Command {
|
|
18
18
|
static description = 'Manage tax matrix';
|
|
@@ -130,15 +130,7 @@ export default class TaxMatrix 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
|
|
@@ -171,7 +163,9 @@ export default class TaxMatrix extends Command {
|
|
|
171
163
|
data = form;
|
|
172
164
|
}
|
|
173
165
|
else if (endpoint.hasBody) {
|
|
174
|
-
|
|
166
|
+
// For binary-response endpoints, --file is the output path, not a JSON
|
|
167
|
+
// input file — skip the read-as-body branch.
|
|
168
|
+
if (flags.file && !endpoint.isBinaryResponse) {
|
|
175
169
|
const fsModule = await import('node:fs');
|
|
176
170
|
try {
|
|
177
171
|
data = JSON.parse(fsModule.readFileSync(flags.file, 'utf-8'));
|
|
@@ -193,6 +187,7 @@ export default class TaxMatrix extends Command {
|
|
|
193
187
|
if (!data)
|
|
194
188
|
data = {};
|
|
195
189
|
const body = data;
|
|
190
|
+
const arrayFields = new Set(endpoint.bodyArrayFields);
|
|
196
191
|
for (const pair of flags.set) {
|
|
197
192
|
const eqIndex = pair.indexOf('=');
|
|
198
193
|
if (eqIndex === -1)
|
|
@@ -204,6 +199,19 @@ export default class TaxMatrix extends Command {
|
|
|
204
199
|
value = JSON.parse(value);
|
|
205
200
|
}
|
|
206
201
|
catch { /* keep as string */ }
|
|
202
|
+
// For top-level keys typed as array in the API schema, split bare
|
|
203
|
+
// comma-separated input (e.g. "1171,1170" -> ["1171","1170"]) and
|
|
204
|
+
// wrap a lone scalar in a single-element array. Skips when --set
|
|
205
|
+
// already provided a JSON array.
|
|
206
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
207
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
208
|
+
if (typeof value === 'string') {
|
|
209
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
210
|
+
}
|
|
211
|
+
else if (value !== undefined && value !== null) {
|
|
212
|
+
value = [value];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
207
215
|
// Support nested keys like "address.city"
|
|
208
216
|
const keys = key.split('.');
|
|
209
217
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
@@ -254,6 +262,26 @@ export default class TaxMatrix extends Command {
|
|
|
254
262
|
process.stderr.write('\n');
|
|
255
263
|
}
|
|
256
264
|
try {
|
|
265
|
+
// Binary response: download to file
|
|
266
|
+
if (endpoint.isBinaryResponse) {
|
|
267
|
+
if (!flags.file) {
|
|
268
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx).`);
|
|
269
|
+
}
|
|
270
|
+
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
271
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
272
|
+
data,
|
|
273
|
+
contextName: flags.context,
|
|
274
|
+
binary: true,
|
|
275
|
+
});
|
|
276
|
+
const fsModule = await import('node:fs');
|
|
277
|
+
const binData = binResponse.data;
|
|
278
|
+
const buffer = Buffer.isBuffer(binData)
|
|
279
|
+
? binData
|
|
280
|
+
: Buffer.from(binData);
|
|
281
|
+
fsModule.writeFileSync(flags.file, buffer);
|
|
282
|
+
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
257
285
|
const response = await apiRequest(endpoint.method, apiPath, {
|
|
258
286
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
259
287
|
data,
|
|
@@ -344,6 +372,7 @@ export default class TaxMatrix extends Command {
|
|
|
344
372
|
}
|
|
345
373
|
else if (flags.set && flags.set.length > 0) {
|
|
346
374
|
const item = {};
|
|
375
|
+
const arrayFields = new Set(ENDPOINTS['create']?.bodyArrayFields ?? []);
|
|
347
376
|
for (const pair of flags.set) {
|
|
348
377
|
const eqIndex = pair.indexOf('=');
|
|
349
378
|
if (eqIndex === -1)
|
|
@@ -354,6 +383,15 @@ export default class TaxMatrix extends Command {
|
|
|
354
383
|
value = JSON.parse(value);
|
|
355
384
|
}
|
|
356
385
|
catch { /* keep as string */ }
|
|
386
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
387
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
388
|
+
if (typeof value === 'string') {
|
|
389
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
390
|
+
}
|
|
391
|
+
else if (value !== undefined && value !== null) {
|
|
392
|
+
value = [value];
|
|
393
|
+
}
|
|
394
|
+
}
|
|
357
395
|
const keys = key.split('.');
|
|
358
396
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
359
397
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -503,14 +541,7 @@ export default class TaxMatrix extends Command {
|
|
|
503
541
|
if (eqIndex === -1)
|
|
504
542
|
this.error(`Invalid --filter format: ${f}. Use: --filter key=value`);
|
|
505
543
|
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
|
-
}
|
|
544
|
+
const value = this.parseFilterValue(f.slice(eqIndex + 1));
|
|
514
545
|
const filterKey = `filter.${key}`;
|
|
515
546
|
if (filterKey in baseParams) {
|
|
516
547
|
const existing = baseParams[filterKey];
|
|
@@ -687,6 +718,7 @@ export default class TaxMatrix extends Command {
|
|
|
687
718
|
}
|
|
688
719
|
else if (flags.set && flags.set.length > 0) {
|
|
689
720
|
const item = {};
|
|
721
|
+
const arrayFields = new Set(ENDPOINTS[`create-${suffix}`]?.bodyArrayFields ?? []);
|
|
690
722
|
for (const pair of flags.set) {
|
|
691
723
|
const eqIndex = pair.indexOf('=');
|
|
692
724
|
if (eqIndex === -1)
|
|
@@ -697,6 +729,15 @@ export default class TaxMatrix extends Command {
|
|
|
697
729
|
value = JSON.parse(value);
|
|
698
730
|
}
|
|
699
731
|
catch { /* keep as string */ }
|
|
732
|
+
const isArrayField = !key.includes('.') && arrayFields.has(key);
|
|
733
|
+
if (isArrayField && !Array.isArray(value)) {
|
|
734
|
+
if (typeof value === 'string') {
|
|
735
|
+
value = value.split(',').map(v => v.trim()).filter(v => v.length > 0);
|
|
736
|
+
}
|
|
737
|
+
else if (value !== undefined && value !== null) {
|
|
738
|
+
value = [value];
|
|
739
|
+
}
|
|
740
|
+
}
|
|
700
741
|
const keys = key.split('.');
|
|
701
742
|
if (keys.some(k => k === '__proto__' || k === 'constructor' || k === 'prototype')) {
|
|
702
743
|
this.error(`Invalid --set key: ${key}`);
|
|
@@ -816,35 +857,62 @@ export default class TaxMatrix extends Command {
|
|
|
816
857
|
this.log('');
|
|
817
858
|
this.log(`Summary: ${created} created, ${updated} updated, ${errors.length} failed`);
|
|
818
859
|
}
|
|
860
|
+
parseFilterValue(value) {
|
|
861
|
+
// Recognises the nestjs-paginate operator set (with or without the leading $)
|
|
862
|
+
// and recursively unwraps chained operators like 'not:null' -> '$not:$null'
|
|
863
|
+
// or 'not:like:John' -> '$not:$like:John'. Falls back to '$eq:<value>' when
|
|
864
|
+
// no operator prefix is present.
|
|
865
|
+
const opRe = /^\$?(and|or|not|eq|gt|gte|in|null|lt|lte|btw|ne|ilike|like|sw|contains)(?::|$)/;
|
|
866
|
+
const m = value.match(opRe);
|
|
867
|
+
if (!m)
|
|
868
|
+
return `\$eq:${value}`;
|
|
869
|
+
const op = m[1];
|
|
870
|
+
const rest = value.slice(m[0].length);
|
|
871
|
+
if (rest === '')
|
|
872
|
+
return `\$${op}`;
|
|
873
|
+
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
874
|
+
}
|
|
819
875
|
filterFields(data, fields) {
|
|
820
876
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
821
877
|
const pick = (obj, keys) => {
|
|
822
|
-
|
|
878
|
+
// Group keys by their first segment so sibling sub-paths
|
|
879
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
880
|
+
// and don't clobber each other on merge.
|
|
881
|
+
const directKeys = new Set();
|
|
882
|
+
const nestedKeys = new Map();
|
|
823
883
|
for (const key of keys) {
|
|
824
884
|
if (key.split('.').some(isUnsafeKey))
|
|
825
885
|
continue;
|
|
826
886
|
if (key.includes('.')) {
|
|
827
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
828
887
|
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
|
-
}
|
|
888
|
+
if (isUnsafeKey(first))
|
|
889
|
+
continue;
|
|
890
|
+
const list = nestedKeys.get(first);
|
|
891
|
+
if (list) {
|
|
892
|
+
list.push(rest.join('.'));
|
|
893
|
+
}
|
|
894
|
+
else {
|
|
895
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
844
896
|
}
|
|
845
897
|
}
|
|
846
|
-
else
|
|
898
|
+
else {
|
|
899
|
+
directKeys.add(key);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
const result = {};
|
|
903
|
+
for (const key of directKeys) {
|
|
904
|
+
if (key in obj)
|
|
847
905
|
result[key] = obj[key];
|
|
906
|
+
}
|
|
907
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
908
|
+
const val = obj[first];
|
|
909
|
+
if (!val || typeof val !== 'object')
|
|
910
|
+
continue;
|
|
911
|
+
if (Array.isArray(val)) {
|
|
912
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
913
|
+
}
|
|
914
|
+
else {
|
|
915
|
+
result[first] = pick(val, restKeys);
|
|
848
916
|
}
|
|
849
917
|
}
|
|
850
918
|
return result;
|