@aderis-erp/cli 1.1.4 → 1.1.5
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 +42 -8
- package/dist/commands/account-transaction-allocations.js +38 -4
- package/dist/commands/account-transactions.d.ts +2 -0
- package/dist/commands/account-transactions.js +68 -32
- package/dist/commands/accounts.js +46 -12
- package/dist/commands/agent-platform.js +37 -3
- package/dist/commands/agent-runs.js +49 -15
- package/dist/commands/analytics.js +39 -5
- package/dist/commands/api-clients.js +47 -13
- package/dist/commands/api-keys.js +40 -6
- package/dist/commands/async-jobs.js +45 -11
- package/dist/commands/audit-log.js +38 -4
- package/dist/commands/bank-accounts.js +54 -20
- package/dist/commands/bank-integrations.js +56 -22
- package/dist/commands/business-partners.js +77 -43
- package/dist/commands/chat.js +43 -9
- package/dist/commands/credit-card-accounts.js +57 -23
- package/dist/commands/currencies.js +37 -3
- package/dist/commands/custody-accounts.js +41 -7
- package/dist/commands/dashboards.js +52 -18
- package/dist/commands/delivery-notes.js +69 -35
- package/dist/commands/document-checksums.d.ts +1 -0
- package/dist/commands/document-checksums.js +38 -3
- package/dist/commands/dunning-configs.js +41 -7
- package/dist/commands/dunning-reminders.js +44 -10
- package/dist/commands/dunning-runs.js +37 -3
- package/dist/commands/email-transactions.js +39 -5
- package/dist/commands/employees.js +77 -43
- package/dist/commands/entity-configurations.js +39 -5
- package/dist/commands/event-mapping-rules.js +37 -3
- package/dist/commands/event-processor-mappings.js +41 -7
- package/dist/commands/files.js +48 -14
- package/dist/commands/financial-instrument-transactions.d.ts +56 -0
- package/dist/commands/financial-instrument-transactions.js +1369 -0
- package/dist/commands/financial-instrument-types.js +41 -7
- package/dist/commands/financial-instruments.js +41 -7
- package/dist/commands/health.js +41 -7
- package/dist/commands/imports.js +39 -5
- package/dist/commands/inbox.js +42 -8
- package/dist/commands/integrations.js +39 -5
- package/dist/commands/item-categories.js +41 -7
- package/dist/commands/items.js +42 -8
- package/dist/commands/journal-lines.js +37 -3
- package/dist/commands/journals.js +61 -27
- package/dist/commands/kpis.js +44 -10
- package/dist/commands/ledgers.js +83 -49
- package/dist/commands/my-account.js +54 -20
- package/dist/commands/notifications.js +37 -3
- package/dist/commands/office-locations.js +41 -7
- package/dist/commands/payment-methods.js +46 -12
- package/dist/commands/payment-runs.js +54 -20
- package/dist/commands/payment-terms.js +42 -8
- package/dist/commands/payments.js +43 -9
- package/dist/commands/payroll-runs.js +71 -37
- package/dist/commands/permissions.js +37 -3
- package/dist/commands/price-lists.js +48 -14
- package/dist/commands/processor-mappings.js +40 -6
- package/dist/commands/processors.js +46 -12
- package/dist/commands/purchase-order-types.js +41 -7
- package/dist/commands/purchase-orders.js +60 -26
- package/dist/commands/reports.js +43 -8
- package/dist/commands/roles.js +40 -6
- package/dist/commands/salary-types.js +41 -7
- package/dist/commands/sales-invoices.js +85 -51
- package/dist/commands/sales-orders.js +69 -35
- package/dist/commands/saved-views.js +39 -5
- package/dist/commands/scheduled-processor-mappings.js +41 -7
- package/dist/commands/schedules.js +45 -11
- package/dist/commands/settings.js +38 -4
- package/dist/commands/tags.js +42 -8
- package/dist/commands/tax-codes.js +44 -10
- package/dist/commands/tax-matrix.js +41 -7
- package/dist/commands/templates.js +49 -15
- package/dist/commands/tenants.js +44 -10
- package/dist/commands/tools.js +38 -4
- package/dist/commands/users.js +58 -24
- package/dist/commands/vat-declarations.js +61 -27
- package/dist/commands/vendor-invoices.js +81 -47
- package/dist/commands/webhooks.js +43 -9
- package/dist/commands/work-summary.js +37 -3
- package/dist/lib/paths.d.ts +8 -0
- package/dist/lib/paths.js +16 -0
- package/dist/lib/production-guard.js +2 -0
- package/oclif.manifest.json +199 -2
- package/package.json +9 -3
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
|
+
import { resolveUserPath } from '../lib/paths.js';
|
|
4
5
|
// 'upsert' loops create/update from the CLI, one request per record. It exists
|
|
5
6
|
// only where the API has no import endpoint of its own; those keep the name
|
|
6
7
|
// 'import' and are listed in SERVER_IMPORTS.
|
|
@@ -11,11 +12,11 @@ const SERVER_IMPORTS = [];
|
|
|
11
12
|
const NESTED_UPSERTS = [];
|
|
12
13
|
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_UPSERT ? ['upsert'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_UPSERTS.map(n => `upsert-${n}`)];
|
|
13
14
|
const ENDPOINTS = {
|
|
14
|
-
'list': { method: 'GET', path: '/v1/financial-instrument-types', summary: 'List financial instrument types', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
-
'create': { method: 'POST', path: '/v1/financial-instrument-types', summary: 'Create a financial instrument type', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['ledgerSettings'] },
|
|
16
|
-
'get': { method: 'GET', path: '/v1/financial-instrument-types/{id}', summary: 'Read a financial instrument type', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
17
|
-
'update': { method: 'PATCH', path: '/v1/financial-instrument-types/{id}', summary: 'Update a financial instrument type', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['ledgerSettings'] },
|
|
18
|
-
'delete': { method: 'DELETE', path: '/v1/financial-instrument-types/{id}', summary: 'Delete a financial instrument type', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
+
'list': { method: 'GET', path: '/v1/financial-instrument-types', summary: 'List financial instrument types', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
16
|
+
'create': { method: 'POST', path: '/v1/financial-instrument-types', summary: 'Create a financial instrument type', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['ledgerSettings'], bodyMediaType: '', specParams: [] },
|
|
17
|
+
'get': { method: 'GET', path: '/v1/financial-instrument-types/{id}', summary: 'Read a financial instrument type', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
18
|
+
'update': { method: 'PATCH', path: '/v1/financial-instrument-types/{id}', summary: 'Update a financial instrument type', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['ledgerSettings'], bodyMediaType: '', specParams: [] },
|
|
19
|
+
'delete': { method: 'DELETE', path: '/v1/financial-instrument-types/{id}', summary: 'Delete a financial instrument type', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
20
|
};
|
|
20
21
|
export default class FinancialInstrumentTypes extends Command {
|
|
21
22
|
static description = 'Manage financial instrument types';
|
|
@@ -37,7 +38,7 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
37
38
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
38
39
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
39
40
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
40
|
-
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
41
|
+
file: Flags.string({ char: 'f', description: 'Read request body from file', parse: async (input) => resolveUserPath(input) }),
|
|
41
42
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
42
43
|
page: Flags.string({ description: 'Page number' }),
|
|
43
44
|
limit: Flags.string({ description: 'Items per page' }),
|
|
@@ -168,6 +169,17 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
}
|
|
172
|
+
// Flags generated from this endpoint's own parameters. Raw-body endpoints
|
|
173
|
+
// have them: their body is not JSON, so --set cannot carry a value there.
|
|
174
|
+
for (const param of endpoint.specParams) {
|
|
175
|
+
const value = flags[param.flag];
|
|
176
|
+
if (value === undefined || value === '') {
|
|
177
|
+
if (param.required)
|
|
178
|
+
this.error(`Missing required flag: --${param.flag}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
queryParams[param.name] = value;
|
|
182
|
+
}
|
|
171
183
|
let data;
|
|
172
184
|
if (endpoint.isMultipart) {
|
|
173
185
|
if (!flags.file)
|
|
@@ -188,6 +200,25 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
188
200
|
}
|
|
189
201
|
data = form;
|
|
190
202
|
}
|
|
203
|
+
else if (endpoint.bodyMediaType) {
|
|
204
|
+
// The body is not JSON (today only application/x-ndjson): it is sent
|
|
205
|
+
// verbatim, under the content type the endpoint asks for.
|
|
206
|
+
if (flags.file) {
|
|
207
|
+
const fsModule = await import('node:fs');
|
|
208
|
+
try {
|
|
209
|
+
data = fsModule.readFileSync(flags.file, 'utf-8');
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
this.error(`Failed to read file: ${flags.file}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else if (flags.data) {
|
|
216
|
+
data = flags.data;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.error(`This endpoint takes its body as ${endpoint.bodyMediaType}. Pass the file with -f / --file, or the text with --data.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
191
222
|
else if (endpoint.hasBody) {
|
|
192
223
|
// For binary-response endpoints, --file is the output path, not a JSON
|
|
193
224
|
// input file — skip the read-as-body branch.
|
|
@@ -283,7 +314,7 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
283
314
|
process.stderr.write(`Body: [multipart/form-data file upload]\n`);
|
|
284
315
|
}
|
|
285
316
|
else if (data) {
|
|
286
|
-
process.stderr.write(`Body: ${JSON.stringify(data, null, 2)}\n`);
|
|
317
|
+
process.stderr.write(`Body: ${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}\n`);
|
|
287
318
|
}
|
|
288
319
|
process.stderr.write('\n');
|
|
289
320
|
}
|
|
@@ -297,6 +328,7 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
297
328
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
298
329
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
299
330
|
data,
|
|
331
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
300
332
|
contextName: flags.context,
|
|
301
333
|
binary: true,
|
|
302
334
|
});
|
|
@@ -322,6 +354,7 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
322
354
|
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
323
355
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
324
356
|
data,
|
|
357
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
325
358
|
contextName: flags.context,
|
|
326
359
|
binary: true,
|
|
327
360
|
});
|
|
@@ -342,6 +375,7 @@ export default class FinancialInstrumentTypes extends Command {
|
|
|
342
375
|
response = await apiRequest(endpoint.method, apiPath, {
|
|
343
376
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
344
377
|
data,
|
|
378
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
345
379
|
contextName: flags.context,
|
|
346
380
|
acceptAny: true,
|
|
347
381
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
|
+
import { resolveUserPath } from '../lib/paths.js';
|
|
4
5
|
// 'upsert' loops create/update from the CLI, one request per record. It exists
|
|
5
6
|
// only where the API has no import endpoint of its own; those keep the name
|
|
6
7
|
// 'import' and are listed in SERVER_IMPORTS.
|
|
@@ -11,11 +12,11 @@ const SERVER_IMPORTS = [];
|
|
|
11
12
|
const NESTED_UPSERTS = [];
|
|
12
13
|
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_UPSERT ? ['upsert'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_UPSERTS.map(n => `upsert-${n}`)];
|
|
13
14
|
const ENDPOINTS = {
|
|
14
|
-
'list': { method: 'GET', path: '/v1/financial-instruments', summary: 'List financial instruments', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
-
'create': { method: 'POST', path: '/v1/financial-instruments', summary: 'Create a financial instrument', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
-
'get': { method: 'GET', path: '/v1/financial-instruments/{id}', summary: 'Read a financial instrument', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
17
|
-
'update': { method: 'PATCH', path: '/v1/financial-instruments/{id}', summary: 'Update a financial instrument', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
18
|
-
'delete': { method: 'DELETE', path: '/v1/financial-instruments/{id}', summary: 'Delete a financial instrument', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
+
'list': { method: 'GET', path: '/v1/financial-instruments', summary: 'List financial instruments', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
16
|
+
'create': { method: 'POST', path: '/v1/financial-instruments', summary: 'Create a financial instrument', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
17
|
+
'get': { method: 'GET', path: '/v1/financial-instruments/{id}', summary: 'Read a financial instrument', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
18
|
+
'update': { method: 'PATCH', path: '/v1/financial-instruments/{id}', summary: 'Update a financial instrument', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
|
+
'delete': { method: 'DELETE', path: '/v1/financial-instruments/{id}', summary: 'Delete a financial instrument', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
20
|
};
|
|
20
21
|
export default class FinancialInstruments extends Command {
|
|
21
22
|
static description = 'Manage financial instruments';
|
|
@@ -37,7 +38,7 @@ export default class FinancialInstruments extends Command {
|
|
|
37
38
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
38
39
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
39
40
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
40
|
-
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
41
|
+
file: Flags.string({ char: 'f', description: 'Read request body from file', parse: async (input) => resolveUserPath(input) }),
|
|
41
42
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
42
43
|
page: Flags.string({ description: 'Page number' }),
|
|
43
44
|
limit: Flags.string({ description: 'Items per page' }),
|
|
@@ -168,6 +169,17 @@ export default class FinancialInstruments extends Command {
|
|
|
168
169
|
}
|
|
169
170
|
}
|
|
170
171
|
}
|
|
172
|
+
// Flags generated from this endpoint's own parameters. Raw-body endpoints
|
|
173
|
+
// have them: their body is not JSON, so --set cannot carry a value there.
|
|
174
|
+
for (const param of endpoint.specParams) {
|
|
175
|
+
const value = flags[param.flag];
|
|
176
|
+
if (value === undefined || value === '') {
|
|
177
|
+
if (param.required)
|
|
178
|
+
this.error(`Missing required flag: --${param.flag}`);
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
queryParams[param.name] = value;
|
|
182
|
+
}
|
|
171
183
|
let data;
|
|
172
184
|
if (endpoint.isMultipart) {
|
|
173
185
|
if (!flags.file)
|
|
@@ -188,6 +200,25 @@ export default class FinancialInstruments extends Command {
|
|
|
188
200
|
}
|
|
189
201
|
data = form;
|
|
190
202
|
}
|
|
203
|
+
else if (endpoint.bodyMediaType) {
|
|
204
|
+
// The body is not JSON (today only application/x-ndjson): it is sent
|
|
205
|
+
// verbatim, under the content type the endpoint asks for.
|
|
206
|
+
if (flags.file) {
|
|
207
|
+
const fsModule = await import('node:fs');
|
|
208
|
+
try {
|
|
209
|
+
data = fsModule.readFileSync(flags.file, 'utf-8');
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
this.error(`Failed to read file: ${flags.file}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else if (flags.data) {
|
|
216
|
+
data = flags.data;
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.error(`This endpoint takes its body as ${endpoint.bodyMediaType}. Pass the file with -f / --file, or the text with --data.`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
191
222
|
else if (endpoint.hasBody) {
|
|
192
223
|
// For binary-response endpoints, --file is the output path, not a JSON
|
|
193
224
|
// input file — skip the read-as-body branch.
|
|
@@ -283,7 +314,7 @@ export default class FinancialInstruments extends Command {
|
|
|
283
314
|
process.stderr.write(`Body: [multipart/form-data file upload]\n`);
|
|
284
315
|
}
|
|
285
316
|
else if (data) {
|
|
286
|
-
process.stderr.write(`Body: ${JSON.stringify(data, null, 2)}\n`);
|
|
317
|
+
process.stderr.write(`Body: ${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}\n`);
|
|
287
318
|
}
|
|
288
319
|
process.stderr.write('\n');
|
|
289
320
|
}
|
|
@@ -297,6 +328,7 @@ export default class FinancialInstruments extends Command {
|
|
|
297
328
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
298
329
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
299
330
|
data,
|
|
331
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
300
332
|
contextName: flags.context,
|
|
301
333
|
binary: true,
|
|
302
334
|
});
|
|
@@ -322,6 +354,7 @@ export default class FinancialInstruments extends Command {
|
|
|
322
354
|
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
323
355
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
324
356
|
data,
|
|
357
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
325
358
|
contextName: flags.context,
|
|
326
359
|
binary: true,
|
|
327
360
|
});
|
|
@@ -342,6 +375,7 @@ export default class FinancialInstruments extends Command {
|
|
|
342
375
|
response = await apiRequest(endpoint.method, apiPath, {
|
|
343
376
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
344
377
|
data,
|
|
378
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
345
379
|
contextName: flags.context,
|
|
346
380
|
acceptAny: true,
|
|
347
381
|
});
|
package/dist/commands/health.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
|
+
import { resolveUserPath } from '../lib/paths.js';
|
|
4
5
|
// 'upsert' loops create/update from the CLI, one request per record. It exists
|
|
5
6
|
// only where the API has no import endpoint of its own; those keep the name
|
|
6
7
|
// 'import' and are listed in SERVER_IMPORTS.
|
|
@@ -11,11 +12,11 @@ const SERVER_IMPORTS = [];
|
|
|
11
12
|
const NESTED_UPSERTS = [];
|
|
12
13
|
const SUBCOMMANDS = [...["get", "get-all", "ready", "get-3", "v1"], ...(HAS_UPSERT ? ['upsert'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_UPSERTS.map(n => `upsert-${n}`)];
|
|
13
14
|
const ENDPOINTS = {
|
|
14
|
-
'get': { method: 'GET', path: '/', summary: 'GET /', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
-
'get-all': { method: 'GET', path: '/health', summary: 'GET /health', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
-
'ready': { method: 'GET', path: '/ready', summary: 'GET /ready', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
17
|
-
'get-3': { method: 'GET', path: '/v1/status', summary: 'GET /v1/status', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
18
|
-
'v1': { method: 'GET', path: '/v1', summary: 'GET /v1', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
+
'get': { method: 'GET', path: '/', summary: 'GET /', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
16
|
+
'get-all': { method: 'GET', path: '/health', summary: 'GET /health', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
17
|
+
'ready': { method: 'GET', path: '/ready', summary: 'GET /ready', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
18
|
+
'get-3': { method: 'GET', path: '/v1/status', summary: 'GET /v1/status', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
|
+
'v1': { method: 'GET', path: '/v1', summary: 'GET /v1', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
20
|
};
|
|
20
21
|
export default class Health extends Command {
|
|
21
22
|
static description = 'Manage health';
|
|
@@ -32,7 +33,7 @@ export default class Health extends Command {
|
|
|
32
33
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
33
34
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
34
35
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
35
|
-
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
36
|
+
file: Flags.string({ char: 'f', description: 'Read request body from file', parse: async (input) => resolveUserPath(input) }),
|
|
36
37
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
37
38
|
page: Flags.string({ description: 'Page number' }),
|
|
38
39
|
limit: Flags.string({ description: 'Items per page' }),
|
|
@@ -163,6 +164,17 @@ export default class Health extends Command {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
}
|
|
167
|
+
// Flags generated from this endpoint's own parameters. Raw-body endpoints
|
|
168
|
+
// have them: their body is not JSON, so --set cannot carry a value there.
|
|
169
|
+
for (const param of endpoint.specParams) {
|
|
170
|
+
const value = flags[param.flag];
|
|
171
|
+
if (value === undefined || value === '') {
|
|
172
|
+
if (param.required)
|
|
173
|
+
this.error(`Missing required flag: --${param.flag}`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
queryParams[param.name] = value;
|
|
177
|
+
}
|
|
166
178
|
let data;
|
|
167
179
|
if (endpoint.isMultipart) {
|
|
168
180
|
if (!flags.file)
|
|
@@ -183,6 +195,25 @@ export default class Health extends Command {
|
|
|
183
195
|
}
|
|
184
196
|
data = form;
|
|
185
197
|
}
|
|
198
|
+
else if (endpoint.bodyMediaType) {
|
|
199
|
+
// The body is not JSON (today only application/x-ndjson): it is sent
|
|
200
|
+
// verbatim, under the content type the endpoint asks for.
|
|
201
|
+
if (flags.file) {
|
|
202
|
+
const fsModule = await import('node:fs');
|
|
203
|
+
try {
|
|
204
|
+
data = fsModule.readFileSync(flags.file, 'utf-8');
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
this.error(`Failed to read file: ${flags.file}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (flags.data) {
|
|
211
|
+
data = flags.data;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this.error(`This endpoint takes its body as ${endpoint.bodyMediaType}. Pass the file with -f / --file, or the text with --data.`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
186
217
|
else if (endpoint.hasBody) {
|
|
187
218
|
// For binary-response endpoints, --file is the output path, not a JSON
|
|
188
219
|
// input file — skip the read-as-body branch.
|
|
@@ -278,7 +309,7 @@ export default class Health extends Command {
|
|
|
278
309
|
process.stderr.write(`Body: [multipart/form-data file upload]\n`);
|
|
279
310
|
}
|
|
280
311
|
else if (data) {
|
|
281
|
-
process.stderr.write(`Body: ${JSON.stringify(data, null, 2)}\n`);
|
|
312
|
+
process.stderr.write(`Body: ${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}\n`);
|
|
282
313
|
}
|
|
283
314
|
process.stderr.write('\n');
|
|
284
315
|
}
|
|
@@ -292,6 +323,7 @@ export default class Health extends Command {
|
|
|
292
323
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
293
324
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
294
325
|
data,
|
|
326
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
295
327
|
contextName: flags.context,
|
|
296
328
|
binary: true,
|
|
297
329
|
});
|
|
@@ -317,6 +349,7 @@ export default class Health extends Command {
|
|
|
317
349
|
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
318
350
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
319
351
|
data,
|
|
352
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
320
353
|
contextName: flags.context,
|
|
321
354
|
binary: true,
|
|
322
355
|
});
|
|
@@ -337,6 +370,7 @@ export default class Health extends Command {
|
|
|
337
370
|
response = await apiRequest(endpoint.method, apiPath, {
|
|
338
371
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
339
372
|
data,
|
|
373
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
340
374
|
contextName: flags.context,
|
|
341
375
|
acceptAny: true,
|
|
342
376
|
});
|
package/dist/commands/imports.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
|
+
import { resolveUserPath } from '../lib/paths.js';
|
|
4
5
|
// 'upsert' loops create/update from the CLI, one request per record. It exists
|
|
5
6
|
// only where the API has no import endpoint of its own; those keep the name
|
|
6
7
|
// 'import' and are listed in SERVER_IMPORTS.
|
|
@@ -11,9 +12,9 @@ const SERVER_IMPORTS = [];
|
|
|
11
12
|
const NESTED_UPSERTS = [];
|
|
12
13
|
const SUBCOMMANDS = [...["list", "get", "delete"], ...(HAS_UPSERT ? ['upsert'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_UPSERTS.map(n => `upsert-${n}`)];
|
|
13
14
|
const ENDPOINTS = {
|
|
14
|
-
'list': { method: 'GET', path: '/v1/imports', summary: 'List the tenant\'s import runs', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
-
'get': { method: 'GET', path: '/v1/imports/{id}', summary: 'Read one import run back', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
-
'delete': { method: 'DELETE', path: '/v1/imports/{id}', summary: 'Throw one import run away', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
+
'list': { method: 'GET', path: '/v1/imports', summary: 'List the tenant\'s import runs', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
16
|
+
'get': { method: 'GET', path: '/v1/imports/{id}', summary: 'Read one import run back', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
17
|
+
'delete': { method: 'DELETE', path: '/v1/imports/{id}', summary: 'Throw one import run away', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
17
18
|
};
|
|
18
19
|
export default class Imports extends Command {
|
|
19
20
|
static description = 'Manage imports';
|
|
@@ -32,7 +33,7 @@ export default class Imports extends Command {
|
|
|
32
33
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
33
34
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
34
35
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
35
|
-
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
36
|
+
file: Flags.string({ char: 'f', description: 'Read request body from file', parse: async (input) => resolveUserPath(input) }),
|
|
36
37
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
37
38
|
page: Flags.string({ description: 'Page number' }),
|
|
38
39
|
limit: Flags.string({ description: 'Items per page' }),
|
|
@@ -163,6 +164,17 @@ export default class Imports extends Command {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
}
|
|
167
|
+
// Flags generated from this endpoint's own parameters. Raw-body endpoints
|
|
168
|
+
// have them: their body is not JSON, so --set cannot carry a value there.
|
|
169
|
+
for (const param of endpoint.specParams) {
|
|
170
|
+
const value = flags[param.flag];
|
|
171
|
+
if (value === undefined || value === '') {
|
|
172
|
+
if (param.required)
|
|
173
|
+
this.error(`Missing required flag: --${param.flag}`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
queryParams[param.name] = value;
|
|
177
|
+
}
|
|
166
178
|
let data;
|
|
167
179
|
if (endpoint.isMultipart) {
|
|
168
180
|
if (!flags.file)
|
|
@@ -183,6 +195,25 @@ export default class Imports extends Command {
|
|
|
183
195
|
}
|
|
184
196
|
data = form;
|
|
185
197
|
}
|
|
198
|
+
else if (endpoint.bodyMediaType) {
|
|
199
|
+
// The body is not JSON (today only application/x-ndjson): it is sent
|
|
200
|
+
// verbatim, under the content type the endpoint asks for.
|
|
201
|
+
if (flags.file) {
|
|
202
|
+
const fsModule = await import('node:fs');
|
|
203
|
+
try {
|
|
204
|
+
data = fsModule.readFileSync(flags.file, 'utf-8');
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
this.error(`Failed to read file: ${flags.file}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (flags.data) {
|
|
211
|
+
data = flags.data;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this.error(`This endpoint takes its body as ${endpoint.bodyMediaType}. Pass the file with -f / --file, or the text with --data.`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
186
217
|
else if (endpoint.hasBody) {
|
|
187
218
|
// For binary-response endpoints, --file is the output path, not a JSON
|
|
188
219
|
// input file — skip the read-as-body branch.
|
|
@@ -278,7 +309,7 @@ export default class Imports extends Command {
|
|
|
278
309
|
process.stderr.write(`Body: [multipart/form-data file upload]\n`);
|
|
279
310
|
}
|
|
280
311
|
else if (data) {
|
|
281
|
-
process.stderr.write(`Body: ${JSON.stringify(data, null, 2)}\n`);
|
|
312
|
+
process.stderr.write(`Body: ${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}\n`);
|
|
282
313
|
}
|
|
283
314
|
process.stderr.write('\n');
|
|
284
315
|
}
|
|
@@ -292,6 +323,7 @@ export default class Imports extends Command {
|
|
|
292
323
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
293
324
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
294
325
|
data,
|
|
326
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
295
327
|
contextName: flags.context,
|
|
296
328
|
binary: true,
|
|
297
329
|
});
|
|
@@ -317,6 +349,7 @@ export default class Imports extends Command {
|
|
|
317
349
|
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
318
350
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
319
351
|
data,
|
|
352
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
320
353
|
contextName: flags.context,
|
|
321
354
|
binary: true,
|
|
322
355
|
});
|
|
@@ -337,6 +370,7 @@ export default class Imports extends Command {
|
|
|
337
370
|
response = await apiRequest(endpoint.method, apiPath, {
|
|
338
371
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
339
372
|
data,
|
|
373
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
340
374
|
contextName: flags.context,
|
|
341
375
|
acceptAny: true,
|
|
342
376
|
});
|
package/dist/commands/inbox.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command, Args, Flags } from '@oclif/core';
|
|
2
2
|
import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
|
+
import { resolveUserPath } from '../lib/paths.js';
|
|
4
5
|
// 'upsert' loops create/update from the CLI, one request per record. It exists
|
|
5
6
|
// only where the API has no import endpoint of its own; those keep the name
|
|
6
7
|
// 'import' and are listed in SERVER_IMPORTS.
|
|
@@ -11,12 +12,12 @@ const SERVER_IMPORTS = [];
|
|
|
11
12
|
const NESTED_UPSERTS = [];
|
|
12
13
|
const SUBCOMMANDS = [...["create-upload", "email-webhook", "document-types", "uploads-files-content", "list-processing-logs", "processing-logs"], ...(HAS_UPSERT ? ['upsert'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_UPSERTS.map(n => `upsert-${n}`)];
|
|
13
14
|
const ENDPOINTS = {
|
|
14
|
-
'create-upload': { method: 'POST', path: '/v1/inbox/upload', summary: 'Upload document(s) to inbox for processing', pathParams: [], hasBody: false, isMultipart: true, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
-
'email-webhook': { method: 'POST', path: '/v1/inbox/email-webhook/{secret}', summary: 'Email webhook for document ingestion (SendGrid inbound-parse)', pathParams: ['secret'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
16
|
-
'document-types': { method: 'GET', path: '/v1/inbox/document-types', summary: 'Get available document types and per-parent allowed types', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
17
|
-
'uploads-files-content': { method: 'GET', path: '/v1/inbox/uploads/{processingId}/files/{fileId}/content', summary: 'Stream the original bytes of an uploaded inbox file', pathParams: ['fileId', 'processingId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
18
|
-
'list-processing-logs': { method: 'GET', path: '/v1/inbox/processing-logs', summary: 'List recent inbox processing logs (newest first)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
19
|
-
'processing-logs': { method: 'GET', path: '/v1/inbox/processing-logs/{processingId}', summary: 'Get a processing run by its processing identifier', pathParams: ['processingId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
15
|
+
'create-upload': { method: 'POST', path: '/v1/inbox/upload', summary: 'Upload document(s) to inbox for processing', pathParams: [], hasBody: false, isMultipart: true, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
16
|
+
'email-webhook': { method: 'POST', path: '/v1/inbox/email-webhook/{secret}', summary: 'Email webhook for document ingestion (SendGrid inbound-parse)', pathParams: ['secret'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
17
|
+
'document-types': { method: 'GET', path: '/v1/inbox/document-types', summary: 'Get available document types and per-parent allowed types', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
18
|
+
'uploads-files-content': { method: 'GET', path: '/v1/inbox/uploads/{processingId}/files/{fileId}/content', summary: 'Stream the original bytes of an uploaded inbox file', pathParams: ['fileId', 'processingId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
19
|
+
'list-processing-logs': { method: 'GET', path: '/v1/inbox/processing-logs', summary: 'List recent inbox processing logs (newest first)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
20
|
+
'processing-logs': { method: 'GET', path: '/v1/inbox/processing-logs/{processingId}', summary: 'Get a processing run by its processing identifier', pathParams: ['processingId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [], bodyMediaType: '', specParams: [] },
|
|
20
21
|
};
|
|
21
22
|
export default class Inbox extends Command {
|
|
22
23
|
static description = 'Manage inbox';
|
|
@@ -31,7 +32,7 @@ export default class Inbox extends Command {
|
|
|
31
32
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
32
33
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
33
34
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
34
|
-
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
35
|
+
file: Flags.string({ char: 'f', description: 'Read request body from file', parse: async (input) => resolveUserPath(input) }),
|
|
35
36
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
36
37
|
'processing-id': Flags.string({ description: 'Path param: processingId' }),
|
|
37
38
|
page: Flags.string({ description: 'Page number' }),
|
|
@@ -163,6 +164,17 @@ export default class Inbox extends Command {
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
}
|
|
167
|
+
// Flags generated from this endpoint's own parameters. Raw-body endpoints
|
|
168
|
+
// have them: their body is not JSON, so --set cannot carry a value there.
|
|
169
|
+
for (const param of endpoint.specParams) {
|
|
170
|
+
const value = flags[param.flag];
|
|
171
|
+
if (value === undefined || value === '') {
|
|
172
|
+
if (param.required)
|
|
173
|
+
this.error(`Missing required flag: --${param.flag}`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
queryParams[param.name] = value;
|
|
177
|
+
}
|
|
166
178
|
let data;
|
|
167
179
|
if (endpoint.isMultipart) {
|
|
168
180
|
if (!flags.file)
|
|
@@ -183,6 +195,25 @@ export default class Inbox extends Command {
|
|
|
183
195
|
}
|
|
184
196
|
data = form;
|
|
185
197
|
}
|
|
198
|
+
else if (endpoint.bodyMediaType) {
|
|
199
|
+
// The body is not JSON (today only application/x-ndjson): it is sent
|
|
200
|
+
// verbatim, under the content type the endpoint asks for.
|
|
201
|
+
if (flags.file) {
|
|
202
|
+
const fsModule = await import('node:fs');
|
|
203
|
+
try {
|
|
204
|
+
data = fsModule.readFileSync(flags.file, 'utf-8');
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
this.error(`Failed to read file: ${flags.file}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else if (flags.data) {
|
|
211
|
+
data = flags.data;
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
this.error(`This endpoint takes its body as ${endpoint.bodyMediaType}. Pass the file with -f / --file, or the text with --data.`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
186
217
|
else if (endpoint.hasBody) {
|
|
187
218
|
// For binary-response endpoints, --file is the output path, not a JSON
|
|
188
219
|
// input file — skip the read-as-body branch.
|
|
@@ -278,7 +309,7 @@ export default class Inbox extends Command {
|
|
|
278
309
|
process.stderr.write(`Body: [multipart/form-data file upload]\n`);
|
|
279
310
|
}
|
|
280
311
|
else if (data) {
|
|
281
|
-
process.stderr.write(`Body: ${JSON.stringify(data, null, 2)}\n`);
|
|
312
|
+
process.stderr.write(`Body: ${typeof data === 'string' ? data : JSON.stringify(data, null, 2)}\n`);
|
|
282
313
|
}
|
|
283
314
|
process.stderr.write('\n');
|
|
284
315
|
}
|
|
@@ -292,6 +323,7 @@ export default class Inbox extends Command {
|
|
|
292
323
|
const binResponse = await apiRequest(endpoint.method, apiPath, {
|
|
293
324
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
294
325
|
data,
|
|
326
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
295
327
|
contextName: flags.context,
|
|
296
328
|
binary: true,
|
|
297
329
|
});
|
|
@@ -317,6 +349,7 @@ export default class Inbox extends Command {
|
|
|
317
349
|
const raw = await apiRequest(endpoint.method, apiPath, {
|
|
318
350
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
319
351
|
data,
|
|
352
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
320
353
|
contextName: flags.context,
|
|
321
354
|
binary: true,
|
|
322
355
|
});
|
|
@@ -337,6 +370,7 @@ export default class Inbox extends Command {
|
|
|
337
370
|
response = await apiRequest(endpoint.method, apiPath, {
|
|
338
371
|
params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
|
|
339
372
|
data,
|
|
373
|
+
contentType: endpoint.bodyMediaType || undefined,
|
|
340
374
|
contextName: flags.context,
|
|
341
375
|
acceptAny: true,
|
|
342
376
|
});
|