@aderis-erp/cli 1.0.17 → 1.1.1
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/dist/commands/access-groups.js +49 -17
- package/dist/commands/account-transaction-allocations.js +46 -14
- package/dist/commands/account-transactions.js +75 -35
- package/dist/commands/accounts.js +54 -22
- package/dist/commands/agent-platform.js +53 -21
- package/dist/commands/{nango-integrations.d.ts → agent-runs.d.ts} +1 -1
- package/dist/commands/agent-runs.js +1155 -0
- package/dist/commands/analytics.js +47 -15
- package/dist/commands/api-keys.js +49 -16
- package/dist/commands/{text-templates.d.ts → async-jobs.d.ts} +1 -1
- package/dist/commands/async-jobs.js +1158 -0
- package/dist/commands/audit-log.js +46 -14
- package/dist/commands/bank-accounts.js +63 -30
- package/dist/commands/bank-integrations.d.ts +1 -0
- package/dist/commands/bank-integrations.js +66 -31
- package/dist/commands/business-partners.js +77 -44
- package/dist/commands/chat.js +52 -19
- package/dist/commands/credit-card-accounts.d.ts +1 -0
- package/dist/commands/credit-card-accounts.js +67 -29
- package/dist/commands/delivery-notes.js +78 -44
- package/dist/commands/dunning-configs.js +49 -17
- package/dist/commands/dunning-reminders.js +52 -20
- package/dist/commands/dunning-runs.js +45 -13
- package/dist/commands/email-transactions.js +47 -15
- package/dist/commands/employees.js +76 -44
- package/dist/commands/entity-configurations.js +47 -15
- package/dist/commands/event-processor-mappings.js +49 -17
- package/dist/commands/files.js +56 -24
- package/dist/commands/health.js +49 -17
- package/dist/commands/{tag-configurations.d.ts → imports.d.ts} +1 -1
- package/dist/commands/{tag-configurations.js → imports.js} +59 -31
- package/dist/commands/inbox.js +52 -19
- package/dist/commands/integration-identities.d.ts +40 -0
- package/dist/commands/integration-identities.js +1151 -0
- package/dist/commands/integrations.js +47 -15
- package/dist/commands/item-categories.js +49 -17
- package/dist/commands/items.js +49 -17
- package/dist/commands/journal-lines.js +45 -13
- package/dist/commands/journals.js +68 -36
- package/dist/commands/ledgers.d.ts +3 -1
- package/dist/commands/ledgers.js +96 -34
- package/dist/commands/my-account.d.ts +39 -0
- package/dist/commands/my-account.js +1160 -0
- package/dist/commands/office-locations.js +49 -17
- package/dist/commands/payment-methods.js +54 -22
- package/dist/commands/payment-runs.js +61 -29
- package/dist/commands/payment-terms.js +50 -18
- package/dist/commands/payments.js +51 -19
- package/dist/commands/payroll-runs.d.ts +43 -0
- package/dist/commands/payroll-runs.js +1188 -0
- package/dist/commands/permissions.d.ts +39 -0
- package/dist/commands/{text-templates.js → permissions.js} +54 -30
- package/dist/commands/price-lists.js +54 -22
- package/dist/commands/processor-mappings.js +48 -16
- package/dist/commands/processors.js +55 -24
- package/dist/commands/purchase-order-types.js +49 -17
- package/dist/commands/purchase-orders.js +69 -36
- package/dist/commands/reports.js +49 -17
- package/dist/commands/roles.d.ts +39 -0
- package/dist/commands/{nango-integrations.js → roles.js} +63 -26
- package/dist/commands/salary-types.js +49 -17
- package/dist/commands/sales-invoices.js +84 -51
- package/dist/commands/sales-orders.js +78 -44
- package/dist/commands/saved-views.js +47 -15
- package/dist/commands/scheduled-processor-mappings.js +49 -17
- package/dist/commands/schedules.js +53 -21
- package/dist/commands/support/end.d.ts +9 -0
- package/dist/commands/support/end.js +29 -0
- package/dist/commands/support/start.d.ts +14 -0
- package/dist/commands/support/start.js +50 -0
- package/dist/commands/support/status.d.ts +10 -0
- package/dist/commands/support/status.js +45 -0
- package/dist/commands/support/tenants.d.ts +10 -0
- package/dist/commands/support/tenants.js +39 -0
- package/dist/commands/tags.js +51 -18
- package/dist/commands/tax-codes.js +52 -20
- package/dist/commands/tax-matrix.js +49 -17
- package/dist/commands/templates.d.ts +39 -0
- package/dist/commands/templates.js +1157 -0
- package/dist/commands/tenants.js +52 -20
- package/dist/commands/tools.js +46 -14
- package/dist/commands/users.d.ts +42 -0
- package/dist/commands/users.js +1174 -0
- package/dist/commands/vat-declarations.d.ts +2 -0
- package/dist/commands/vat-declarations.js +72 -36
- package/dist/commands/vendor-invoices.js +81 -49
- package/dist/commands/webhooks.js +51 -19
- package/dist/commands/workflows.js +47 -15
- package/dist/lib/api-client.d.ts +6 -0
- package/dist/lib/api-client.js +13 -0
- package/dist/lib/auth/constants.d.ts +12 -0
- package/dist/lib/auth/constants.js +12 -0
- package/dist/lib/auth/index.d.ts +11 -1
- package/dist/lib/auth/index.js +105 -6
- package/dist/lib/auth/jwks.d.ts +19 -0
- package/dist/lib/auth/jwks.js +112 -0
- package/dist/lib/auth/keycloak-provider.d.ts +45 -7
- package/dist/lib/auth/keycloak-provider.js +161 -27
- package/dist/lib/auth/tokens.d.ts +8 -3
- package/dist/lib/auth/tokens.js +8 -7
- package/dist/lib/auth/types.d.ts +5 -1
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.js +10 -0
- package/oclif.manifest.json +2182 -744
- package/package.json +7 -4
package/dist/commands/tags.js
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
-
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
2
|
+
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "journal-coverage"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'list': { method: 'GET', path: '/v1/tags', summary: 'Get all tags with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
12
|
-
'create': { method: 'POST', path: '/v1/tags', summary: 'Create a new tag', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
13
|
-
'get': { method: 'GET', path: '/v1/tags/{id}', summary: 'Get a tag by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/tags/{id}', summary: 'Update a tag', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
15
|
-
'delete': { method: 'DELETE', path: '/v1/tags/{id}', summary: 'Delete a tag', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/tags', summary: 'Get all tags with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tags', summary: 'Create a new tag', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['rules'] },
|
|
13
|
+
'get': { method: 'GET', path: '/v1/tags/{id}', summary: 'Get a tag by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
14
|
+
'update': { method: 'PATCH', path: '/v1/tags/{id}', summary: 'Update a tag', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['rules'] },
|
|
15
|
+
'delete': { method: 'DELETE', path: '/v1/tags/{id}', summary: 'Delete a tag', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
+
'journal-coverage': { method: 'GET', path: '/v1/tags/{id}/journal-coverage', summary: 'How much of the journal-line amount in scope carries one of the tags below this tag', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
17
|
};
|
|
17
18
|
export default class Tags extends Command {
|
|
18
19
|
static description = 'Manage tags';
|
|
@@ -264,10 +265,11 @@ export default class Tags extends Command {
|
|
|
264
265
|
process.stderr.write('\n');
|
|
265
266
|
}
|
|
266
267
|
try {
|
|
267
|
-
// Binary response:
|
|
268
|
+
// Binary response: to -f / --file, or to stdout when it is redirected.
|
|
268
269
|
if (endpoint.isBinaryResponse) {
|
|
269
|
-
|
|
270
|
-
|
|
270
|
+
const toStdout = !flags.file;
|
|
271
|
+
if (toStdout && process.stdout.isTTY) {
|
|
272
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx), or redirect stdout to a file.`);
|
|
271
273
|
}
|
|
272
274
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
273
275
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
@@ -275,24 +277,55 @@ export default class Tags extends Command {
|
|
|
275
277
|
contextName: flags.context,
|
|
276
278
|
binary: true,
|
|
277
279
|
});
|
|
278
|
-
const fsModule = await import('node:fs');
|
|
279
280
|
const binData = binResponse.data;
|
|
280
281
|
const buffer = Buffer.isBuffer(binData)
|
|
281
282
|
? binData
|
|
282
283
|
: Buffer.from(binData);
|
|
284
|
+
if (toStdout) {
|
|
285
|
+
// Nothing else may reach stdout here — it is the file.
|
|
286
|
+
process.stdout.write(buffer);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const fsModule = await import('node:fs');
|
|
283
290
|
fsModule.writeFileSync(flags.file, buffer);
|
|
284
291
|
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
285
292
|
return;
|
|
286
293
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
294
|
+
let response;
|
|
295
|
+
if (endpoint.hasBinaryVariant) {
|
|
296
|
+
// This route answers JSON or a file depending on the request body, so the
|
|
297
|
+
// bytes are read first and the response's own content-type decides. Asking
|
|
298
|
+
// for text here would corrupt an xlsx/pdf before anything could inspect it.
|
|
299
|
+
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
300
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
301
|
+
data,
|
|
302
|
+
contextName: flags.context,
|
|
303
|
+
binary: true,
|
|
304
|
+
});
|
|
305
|
+
const rawType = String(raw.headers['content-type'] || '').toLowerCase();
|
|
306
|
+
const rawData = raw.data;
|
|
307
|
+
const buffer = Buffer.isBuffer(rawData) ? rawData : Buffer.from(rawData);
|
|
308
|
+
if (!isTextualMediaType(rawType)) {
|
|
309
|
+
if (process.stdout.isTTY) {
|
|
310
|
+
this.error(`The API returned ${rawType || 'binary data'}. Redirect stdout to a file, e.g. ... > report.xlsx`);
|
|
311
|
+
}
|
|
312
|
+
// Nothing else may reach stdout here — it is the file.
|
|
313
|
+
process.stdout.write(buffer);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
response = { data: buffer.toString('utf8'), headers: raw.headers, status: raw.status };
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
response = await apiRequest(endpoint.method, apiPath, {
|
|
320
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
321
|
+
data,
|
|
322
|
+
contextName: flags.context,
|
|
323
|
+
acceptAny: true,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
293
326
|
// Check content-type for non-JSON responses (XML, text, etc.)
|
|
294
327
|
const contentType = (response.headers['content-type'] || '').toLowerCase();
|
|
295
|
-
if (contentType
|
|
328
|
+
if (isTextualMediaType(contentType) && !contentType.startsWith('application/json')) {
|
|
296
329
|
// Output raw content for XML/text responses (CSV, plain, HTML, etc.)
|
|
297
330
|
this.log(String(response.data));
|
|
298
331
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
-
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
2
|
+
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
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;
|
|
@@ -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, 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: ['directions'] },
|
|
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: ['directions'] },
|
|
18
|
-
'delete': { method: 'DELETE', path: '/v1/tax/tax-codes/{id}', summary: 'Delete a tax code', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/tax/tax-codes', summary: 'Get all tax codes with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
12
|
+
'create': { method: 'POST', path: '/v1/tax/tax-codes', summary: 'Create a new tax code', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['directions'] },
|
|
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, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: false, bodyArrayFields: ['directions'] },
|
|
18
|
+
'delete': { method: 'DELETE', path: '/v1/tax/tax-codes/{id}', summary: 'Delete a tax code', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
19
19
|
};
|
|
20
20
|
export default class TaxCodes extends Command {
|
|
21
21
|
static description = 'Manage tax codes';
|
|
@@ -267,10 +267,11 @@ export default class TaxCodes extends Command {
|
|
|
267
267
|
process.stderr.write('\n');
|
|
268
268
|
}
|
|
269
269
|
try {
|
|
270
|
-
// Binary response:
|
|
270
|
+
// Binary response: to -f / --file, or to stdout when it is redirected.
|
|
271
271
|
if (endpoint.isBinaryResponse) {
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
const toStdout = !flags.file;
|
|
273
|
+
if (toStdout && process.stdout.isTTY) {
|
|
274
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx), or redirect stdout to a file.`);
|
|
274
275
|
}
|
|
275
276
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
276
277
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
@@ -278,24 +279,55 @@ export default class TaxCodes extends Command {
|
|
|
278
279
|
contextName: flags.context,
|
|
279
280
|
binary: true,
|
|
280
281
|
});
|
|
281
|
-
const fsModule = await import('node:fs');
|
|
282
282
|
const binData = binResponse.data;
|
|
283
283
|
const buffer = Buffer.isBuffer(binData)
|
|
284
284
|
? binData
|
|
285
285
|
: Buffer.from(binData);
|
|
286
|
+
if (toStdout) {
|
|
287
|
+
// Nothing else may reach stdout here — it is the file.
|
|
288
|
+
process.stdout.write(buffer);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const fsModule = await import('node:fs');
|
|
286
292
|
fsModule.writeFileSync(flags.file, buffer);
|
|
287
293
|
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
288
294
|
return;
|
|
289
295
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
+
let response;
|
|
297
|
+
if (endpoint.hasBinaryVariant) {
|
|
298
|
+
// This route answers JSON or a file depending on the request body, so the
|
|
299
|
+
// bytes are read first and the response's own content-type decides. Asking
|
|
300
|
+
// for text here would corrupt an xlsx/pdf before anything could inspect it.
|
|
301
|
+
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
302
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
303
|
+
data,
|
|
304
|
+
contextName: flags.context,
|
|
305
|
+
binary: true,
|
|
306
|
+
});
|
|
307
|
+
const rawType = String(raw.headers['content-type'] || '').toLowerCase();
|
|
308
|
+
const rawData = raw.data;
|
|
309
|
+
const buffer = Buffer.isBuffer(rawData) ? rawData : Buffer.from(rawData);
|
|
310
|
+
if (!isTextualMediaType(rawType)) {
|
|
311
|
+
if (process.stdout.isTTY) {
|
|
312
|
+
this.error(`The API returned ${rawType || 'binary data'}. Redirect stdout to a file, e.g. ... > report.xlsx`);
|
|
313
|
+
}
|
|
314
|
+
// Nothing else may reach stdout here — it is the file.
|
|
315
|
+
process.stdout.write(buffer);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
response = { data: buffer.toString('utf8'), headers: raw.headers, status: raw.status };
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
response = await apiRequest(endpoint.method, apiPath, {
|
|
322
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
323
|
+
data,
|
|
324
|
+
contextName: flags.context,
|
|
325
|
+
acceptAny: true,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
296
328
|
// Check content-type for non-JSON responses (XML, text, etc.)
|
|
297
329
|
const contentType = (response.headers['content-type'] || '').toLowerCase();
|
|
298
|
-
if (contentType
|
|
330
|
+
if (isTextualMediaType(contentType) && !contentType.startsWith('application/json')) {
|
|
299
331
|
// Output raw content for XML/text responses (CSV, plain, HTML, etc.)
|
|
300
332
|
this.log(String(response.data));
|
|
301
333
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
-
import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
|
|
2
|
+
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
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;
|
|
@@ -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, 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: [] },
|
|
11
|
+
'list': { method: 'GET', path: '/v1/tax/tax-matrix', summary: 'Get all tax matrix mappings with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: 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, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
16
|
};
|
|
17
17
|
export default class TaxMatrix extends Command {
|
|
18
18
|
static description = 'Manage tax matrix';
|
|
@@ -264,10 +264,11 @@ export default class TaxMatrix extends Command {
|
|
|
264
264
|
process.stderr.write('\n');
|
|
265
265
|
}
|
|
266
266
|
try {
|
|
267
|
-
// Binary response:
|
|
267
|
+
// Binary response: to -f / --file, or to stdout when it is redirected.
|
|
268
268
|
if (endpoint.isBinaryResponse) {
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
const toStdout = !flags.file;
|
|
270
|
+
if (toStdout && process.stdout.isTTY) {
|
|
271
|
+
this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx), or redirect stdout to a file.`);
|
|
271
272
|
}
|
|
272
273
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
273
274
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
@@ -275,24 +276,55 @@ export default class TaxMatrix extends Command {
|
|
|
275
276
|
contextName: flags.context,
|
|
276
277
|
binary: true,
|
|
277
278
|
});
|
|
278
|
-
const fsModule = await import('node:fs');
|
|
279
279
|
const binData = binResponse.data;
|
|
280
280
|
const buffer = Buffer.isBuffer(binData)
|
|
281
281
|
? binData
|
|
282
282
|
: Buffer.from(binData);
|
|
283
|
+
if (toStdout) {
|
|
284
|
+
// Nothing else may reach stdout here — it is the file.
|
|
285
|
+
process.stdout.write(buffer);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const fsModule = await import('node:fs');
|
|
283
289
|
fsModule.writeFileSync(flags.file, buffer);
|
|
284
290
|
this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
|
|
285
291
|
return;
|
|
286
292
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
let response;
|
|
294
|
+
if (endpoint.hasBinaryVariant) {
|
|
295
|
+
// This route answers JSON or a file depending on the request body, so the
|
|
296
|
+
// bytes are read first and the response's own content-type decides. Asking
|
|
297
|
+
// for text here would corrupt an xlsx/pdf before anything could inspect it.
|
|
298
|
+
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
299
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
300
|
+
data,
|
|
301
|
+
contextName: flags.context,
|
|
302
|
+
binary: true,
|
|
303
|
+
});
|
|
304
|
+
const rawType = String(raw.headers['content-type'] || '').toLowerCase();
|
|
305
|
+
const rawData = raw.data;
|
|
306
|
+
const buffer = Buffer.isBuffer(rawData) ? rawData : Buffer.from(rawData);
|
|
307
|
+
if (!isTextualMediaType(rawType)) {
|
|
308
|
+
if (process.stdout.isTTY) {
|
|
309
|
+
this.error(`The API returned ${rawType || 'binary data'}. Redirect stdout to a file, e.g. ... > report.xlsx`);
|
|
310
|
+
}
|
|
311
|
+
// Nothing else may reach stdout here — it is the file.
|
|
312
|
+
process.stdout.write(buffer);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
response = { data: buffer.toString('utf8'), headers: raw.headers, status: raw.status };
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
response = await apiRequest(endpoint.method, apiPath, {
|
|
319
|
+
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
320
|
+
data,
|
|
321
|
+
contextName: flags.context,
|
|
322
|
+
acceptAny: true,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
293
325
|
// Check content-type for non-JSON responses (XML, text, etc.)
|
|
294
326
|
const contentType = (response.headers['content-type'] || '').toLowerCase();
|
|
295
|
-
if (contentType
|
|
327
|
+
if (isTextualMediaType(contentType) && !contentType.startsWith('application/json')) {
|
|
296
328
|
// Output raw content for XML/text responses (CSV, plain, HTML, etc.)
|
|
297
329
|
this.log(String(response.data));
|
|
298
330
|
return;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Templates 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 sanitizeOutput;
|
|
35
|
+
private getColumns;
|
|
36
|
+
private getValue;
|
|
37
|
+
private printTable;
|
|
38
|
+
private printCsv;
|
|
39
|
+
}
|