@aderis-erp/cli 1.0.1 → 1.0.2
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 +1 -1
- package/dist/commands/{access-groups.js → access-groups 2.js } +6 -4
- package/dist/commands/bank-integrations.d.ts +2 -0
- package/dist/commands/bank-integrations.js +11 -1
- package/dist/commands/documents.js +6 -4
- package/dist/commands/inbox.js +1 -1
- package/dist/commands/processing-logs.js +3 -2
- package/dist/commands/{audit-log.d.ts → pubsub.d.ts} +2 -2
- package/dist/commands/{audit-log.js → pubsub.js} +10 -14
- package/dist/commands/sales-invoices.js +2 -1
- package/dist/commands/sales-orders.js +2 -1
- package/dist/lib/auth.js +16 -7
- package/oclif.manifest.json +660 -2403
- package/package.json +1 -1
- package/dist/commands/access-groups.d.ts +0 -39
- package/dist/commands/account-statement-runs.d.ts +0 -40
- package/dist/commands/account-statement-runs.js +0 -1004
- package/dist/commands/account-transactions.d.ts +0 -41
- package/dist/commands/account-transactions.js +0 -1020
- package/dist/commands/accounts.d.ts +0 -40
- package/dist/commands/accounts.js +0 -1012
- package/dist/commands/agent-runs.d.ts +0 -39
- package/dist/commands/agent-runs.js +0 -1001
- package/dist/commands/auth/login.d.ts +0 -14
- package/dist/commands/auth/login.js +0 -116
- package/dist/commands/auth/logout.d.ts +0 -10
- package/dist/commands/auth/logout.js +0 -58
- package/dist/commands/auth/status.d.ts +0 -12
- package/dist/commands/auth/status.js +0 -101
- package/dist/commands/auth/tenant.d.ts +0 -18
- package/dist/commands/auth/tenant.js +0 -168
- package/dist/commands/auth.d.ts +0 -37
- package/dist/commands/auth.js +0 -871
- package/dist/commands/bank-accounts.d.ts +0 -41
- package/dist/commands/bank-accounts.js +0 -1020
- package/dist/commands/bank-statements.d.ts +0 -40
- package/dist/commands/bank-statements.js +0 -998
- package/dist/commands/config/add.d.ts +0 -13
- package/dist/commands/config/add.js +0 -120
- package/dist/commands/config/current.d.ts +0 -9
- package/dist/commands/config/current.js +0 -43
- package/dist/commands/config/delete.d.ts +0 -12
- package/dist/commands/config/delete.js +0 -67
- package/dist/commands/config/list.d.ts +0 -9
- package/dist/commands/config/list.js +0 -50
- package/dist/commands/config/use.d.ts +0 -9
- package/dist/commands/config/use.js +0 -40
- package/dist/commands/salary-types.js +0 -1006
package/README.md
CHANGED
|
@@ -3,24 +3,26 @@ import { apiRequest, ApiError } from '../lib/api-client.js';
|
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
|
-
const HAS_EXPORT =
|
|
6
|
+
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
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
|
-
'
|
|
11
|
+
'list': { method: 'GET', path: '/v1/access-groups', summary: 'List access groups (paginated)', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/access-groups', summary: 'Create a new access group', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'get
|
|
13
|
+
'get': { method: 'GET', path: '/v1/access-groups/{id}', summary: 'Get a single access group by ID', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
14
14
|
'update': { method: 'PATCH', path: '/v1/access-groups/{id}', summary: 'Update an existing access group', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/access-groups/{id}', summary: 'Delete an access group', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
16
16
|
};
|
|
17
17
|
export default class AccessGroups extends Command {
|
|
18
18
|
static description = 'Manage access groups';
|
|
19
19
|
static examples = [
|
|
20
|
+
'<%= config.bin %> access-groups list',
|
|
20
21
|
'<%= config.bin %> access-groups get <id>',
|
|
21
22
|
'<%= config.bin %> access-groups create --data \'{...}\'',
|
|
22
23
|
'<%= config.bin %> access-groups update <id> --set field=value',
|
|
23
24
|
'<%= config.bin %> access-groups import --file data.json',
|
|
25
|
+
'<%= config.bin %> access-groups export --csv > access-groups.csv',
|
|
24
26
|
];
|
|
25
27
|
static args = {
|
|
26
28
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
|
@@ -14,6 +14,8 @@ export default class BankIntegrations extends Command {
|
|
|
14
14
|
data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
15
|
file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
16
|
set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
'import-run-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'statement-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
19
|
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
20
|
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
21
|
include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -6,7 +6,7 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["initiate", "providers-supported", "providers-consent-status", "delete-providers-consent", "list", "create", "get", "update", "delete", "log"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["initiate", "providers-supported", "providers-consent-status", "delete-providers-consent", "list", "create", "get", "update", "delete", "log", "list-account-statement-runs", "trigger-account-statement-runs", "get-account-statement-runs", "account-statement-runs-files", "trigger-account-statement-runs-reimport", "list-statements", "statements", "download-statements-xml"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'initiate': { method: 'POST', path: '/v1/bank-integrations/initiate', summary: 'Initiate the OAuth/auth flow for a bank integration', pathParams: [], hasBody: true, isMultipart: false },
|
|
12
12
|
'providers-supported': { method: 'GET', path: '/v1/bank-integrations/providers/supported', summary: 'List supported bLink providers', pathParams: [], hasBody: false, isMultipart: false },
|
|
@@ -18,6 +18,14 @@ const ENDPOINTS = {
|
|
|
18
18
|
'update': { method: 'PATCH', path: '/v1/bank-integrations/{id}', summary: 'Update the display name of a BankIntegration', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
19
19
|
'delete': { method: 'DELETE', path: '/v1/bank-integrations/{id}', summary: 'Delete a BankIntegration', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
20
20
|
'log': { method: 'GET', path: '/v1/bank-integrations/{id}/log', summary: 'Get activity log for a bank integration', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
21
|
+
'list-account-statement-runs': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/account-statement-runs', summary: 'List bank statement import runs', pathParams: ['bankIntegrationId'], hasBody: false, isMultipart: false },
|
|
22
|
+
'trigger-account-statement-runs': { method: 'POST', path: '/v1/bank-integrations/{bankIntegrationId}/account-statement-runs', summary: 'Trigger a bank statement import', pathParams: ['bankIntegrationId'], hasBody: true, isMultipart: false },
|
|
23
|
+
'get-account-statement-runs': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/account-statement-runs/{importRunId}', summary: 'Get import run details', pathParams: ['bankIntegrationId', 'importRunId'], hasBody: false, isMultipart: false },
|
|
24
|
+
'account-statement-runs-files': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/account-statement-runs/{importRunId}/files', summary: 'Get files for an import run', pathParams: ['bankIntegrationId', 'importRunId'], hasBody: false, isMultipart: false },
|
|
25
|
+
'trigger-account-statement-runs-reimport': { method: 'POST', path: '/v1/bank-integrations/{bankIntegrationId}/account-statement-runs/{importRunId}/reimport', summary: 'Trigger reimport of an existing account statement import run', pathParams: ['bankIntegrationId', 'importRunId'], hasBody: true, isMultipart: false },
|
|
26
|
+
'list-statements': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/statements', summary: 'List CAMT.053 statements for a bank integration', pathParams: ['bankIntegrationId'], hasBody: false, isMultipart: false },
|
|
27
|
+
'statements': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/statements/{statementId}', summary: 'Get CAMT.053 statement detail', pathParams: ['bankIntegrationId', 'statementId'], hasBody: false, isMultipart: false },
|
|
28
|
+
'download-statements-xml': { method: 'GET', path: '/v1/bank-integrations/{bankIntegrationId}/statements/{statementId}/xml', summary: 'Get raw CAMT.053 XML for a statement', pathParams: ['bankIntegrationId', 'statementId'], hasBody: false, isMultipart: false },
|
|
21
29
|
};
|
|
22
30
|
export default class BankIntegrations extends Command {
|
|
23
31
|
static description = 'Manage bank integrations';
|
|
@@ -41,6 +49,8 @@ export default class BankIntegrations extends Command {
|
|
|
41
49
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
42
50
|
file: Flags.string({ char: 'f', description: 'Read request body from file' }),
|
|
43
51
|
set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
|
|
52
|
+
'import-run-id': Flags.string({ description: 'Path param: importRunId' }),
|
|
53
|
+
'statement-id': Flags.string({ description: 'Path param: statementId' }),
|
|
44
54
|
page: Flags.string({ description: 'Page number' }),
|
|
45
55
|
limit: Flags.string({ description: 'Items per page' }),
|
|
46
56
|
include: Flags.string({ description: 'Relations to include' }),
|
|
@@ -3,14 +3,14 @@ import { apiRequest, ApiError } from '../lib/api-client.js';
|
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
|
-
const HAS_EXPORT =
|
|
6
|
+
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "reclassify"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'
|
|
11
|
+
'list': { method: 'GET', path: '/v1/documents', summary: 'List documents (paginated)', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/documents', summary: 'Create a new document (letterbox)', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'get
|
|
13
|
+
'get': { method: 'GET', path: '/v1/documents/{id}', summary: 'Get document detail with files, audit log, and notes placeholder', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
14
14
|
'update': { method: 'PATCH', path: '/v1/documents/{id}', summary: 'Patch an existing document', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/documents/{id}', summary: 'Soft-delete (discard) a document', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
16
16
|
'reclassify': { method: 'POST', path: '/v1/documents/{id}/reclassify', summary: 'Reclassify a document to a new type', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
@@ -18,10 +18,12 @@ const ENDPOINTS = {
|
|
|
18
18
|
export default class Documents extends Command {
|
|
19
19
|
static description = 'Manage documents';
|
|
20
20
|
static examples = [
|
|
21
|
+
'<%= config.bin %> documents list',
|
|
21
22
|
'<%= config.bin %> documents get <id>',
|
|
22
23
|
'<%= config.bin %> documents create --data \'{...}\'',
|
|
23
24
|
'<%= config.bin %> documents update <id> --set field=value',
|
|
24
25
|
'<%= config.bin %> documents import --file data.json',
|
|
26
|
+
'<%= config.bin %> documents export --csv > documents.csv',
|
|
25
27
|
];
|
|
26
28
|
static args = {
|
|
27
29
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
package/dist/commands/inbox.js
CHANGED
|
@@ -8,7 +8,7 @@ const HAS_CAMT053 = false;
|
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
9
|
const SUBCOMMANDS = [...["upload", "email-webhook", "document-types"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'upload': { method: 'POST', path: '/v1/inbox/upload', summary: 'Upload document(s) to inbox for processing', pathParams: [], hasBody: false, isMultipart:
|
|
11
|
+
'upload': { method: 'POST', path: '/v1/inbox/upload', summary: 'Upload document(s) to inbox for processing', pathParams: [], hasBody: false, isMultipart: true },
|
|
12
12
|
'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 },
|
|
13
13
|
'document-types': { method: 'GET', path: '/v1/inbox/document-types', summary: 'Get available document types and per-parent allowed types', pathParams: [], hasBody: false, isMultipart: false },
|
|
14
14
|
};
|
|
@@ -6,9 +6,10 @@ const HAS_IMPORT = false;
|
|
|
6
6
|
const HAS_EXPORT = false;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["get"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["get", "get-processingId"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'get': { method: 'GET', path: '/v1/processing-logs
|
|
11
|
+
'get': { method: 'GET', path: '/v1/processing-logs', summary: 'List recent inbox processing logs (newest first)', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
+
'get-processingId': { method: 'GET', path: '/v1/processing-logs/{processingId}', summary: 'Get a processing run by its processing identifier', pathParams: ['processingId'], hasBody: false, isMultipart: false },
|
|
12
13
|
};
|
|
13
14
|
export default class ProcessingLogs extends Command {
|
|
14
15
|
static description = 'Manage processing logs';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
export default class
|
|
2
|
+
export default class Pubsub extends Command {
|
|
3
3
|
static description: string;
|
|
4
|
-
static examples:
|
|
4
|
+
static examples: never[];
|
|
5
5
|
static args: {
|
|
6
6
|
action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
7
|
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
@@ -3,21 +3,17 @@ import { apiRequest, ApiError } from '../lib/api-client.js';
|
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = false;
|
|
6
|
-
const HAS_EXPORT =
|
|
6
|
+
const HAS_EXPORT = false;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
9
|
+
const SUBCOMMANDS = [...["webhook-events", "processor-jobs"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'find-workflow': { method: 'GET', path: '/v1/audit-log/workflow/{workflowId}', summary: 'Get audit log entries for a specific workflow', pathParams: ['workflowId'], hasBody: false, isMultipart: false },
|
|
11
|
+
'webhook-events': { method: 'POST', path: '/v1/pubsub/webhook-events', summary: 'GCP Pub/Sub push endpoint for webhook event delivery', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
+
'processor-jobs': { method: 'POST', path: '/v1/pubsub/processor-jobs', summary: 'GCP Pub/Sub push endpoint for processor-job.v1 envelopes (PDF rendering)', pathParams: [], hasBody: false, isMultipart: false },
|
|
14
13
|
};
|
|
15
|
-
export default class
|
|
16
|
-
static description = 'Manage
|
|
17
|
-
static examples = [
|
|
18
|
-
'<%= config.bin %> audit-log list',
|
|
19
|
-
'<%= config.bin %> audit-log export --csv > audit-log.csv',
|
|
20
|
-
];
|
|
14
|
+
export default class Pubsub extends Command {
|
|
15
|
+
static description = 'Manage pubsub';
|
|
16
|
+
static examples = [];
|
|
21
17
|
static args = {
|
|
22
18
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
|
23
19
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
@@ -42,7 +38,7 @@ export default class AuditLog extends Command {
|
|
|
42
38
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
43
39
|
};
|
|
44
40
|
async run() {
|
|
45
|
-
const { args, flags } = await this.parse(
|
|
41
|
+
const { args, flags } = await this.parse(Pubsub);
|
|
46
42
|
// Handle import action specially
|
|
47
43
|
if (args.action === 'import') {
|
|
48
44
|
if (!HAS_IMPORT)
|
|
@@ -88,7 +84,7 @@ export default class AuditLog extends Command {
|
|
|
88
84
|
// First path param always comes from positional argument
|
|
89
85
|
value = args.id;
|
|
90
86
|
if (!value)
|
|
91
|
-
this.error('Missing required argument: id. Usage: aderis
|
|
87
|
+
this.error('Missing required argument: id. Usage: aderis pubsub <action> <id>');
|
|
92
88
|
}
|
|
93
89
|
else {
|
|
94
90
|
const flagName = param.replace(/\./g, '-').replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
@@ -651,7 +647,7 @@ export default class AuditLog extends Command {
|
|
|
651
647
|
}
|
|
652
648
|
async runNestedImport(suffix, parentId, flags) {
|
|
653
649
|
if (!parentId) {
|
|
654
|
-
this.error(`Missing required argument: id. Usage: aderis
|
|
650
|
+
this.error(`Missing required argument: id. Usage: aderis pubsub import-${suffix} <parent-id> --file data.json`);
|
|
655
651
|
}
|
|
656
652
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
657
653
|
if (!context)
|
|
@@ -6,7 +6,7 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = ["line-items", "notes", "files"];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "create-migrated-invoice", "pdf", "get", "update", "delete", "approve", "validate", "request-approval", "send", "send-resend", "cancel", "copy", "replace", "create-line-items", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "create-migrated-invoice", "pdf", "get", "update", "delete", "approve", "validate", "request-approval", "send", "send-resend", "cancel", "copy", "replace", "create-line-items", "update-line-items-reorder", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/sales-invoices', summary: 'Get all sales invoices with pagination', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/sales-invoices', summary: 'Create a new sales invoice', pathParams: [], hasBody: true, isMultipart: false },
|
|
@@ -24,6 +24,7 @@ const ENDPOINTS = {
|
|
|
24
24
|
'copy': { method: 'POST', path: '/v1/sales-invoices/{id}/copy', summary: 'Create a copy of a cancelled invoice', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
25
25
|
'replace': { method: 'POST', path: '/v1/sales-invoices/{id}/replace', summary: 'Replace invoice with corrected version (creates new CORRECTED_INVOICE)', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
26
26
|
'create-line-items': { method: 'POST', path: '/v1/sales-invoices/{invoiceId}/line-items', summary: 'Add a line item to a sales invoice', pathParams: ['invoiceId'], hasBody: true, isMultipart: false },
|
|
27
|
+
'update-line-items-reorder': { method: 'PATCH', path: '/v1/sales-invoices/{invoiceId}/line-items/reorder', summary: 'Bulk reorder line items (drag-and-drop)', pathParams: ['invoiceId'], hasBody: true, isMultipart: false },
|
|
27
28
|
'update-line-items': { method: 'PATCH', path: '/v1/sales-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Update a line item on a sales invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: true, isMultipart: false },
|
|
28
29
|
'delete-line-items': { method: 'DELETE', path: '/v1/sales-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Remove a line item from a sales invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: false, isMultipart: false },
|
|
29
30
|
'list-notes': { method: 'GET', path: '/v1/sales-invoices/{salesInvoiceId}/notes', summary: 'Get all notes for a sales invoice', pathParams: ['salesInvoiceId'], hasBody: false, isMultipart: false },
|
|
@@ -6,7 +6,7 @@ const HAS_IMPORT = true;
|
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = ["line-items", "notes", "files"];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "submit", "approve", "accept", "terminate", "cancel", "replace", "create-invoice", "create-line-items", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "submit", "approve", "accept", "terminate", "cancel", "replace", "create-invoice", "create-line-items", "update-line-items-reorder", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/sales-orders', summary: 'Get all sales orders with pagination', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/sales-orders', summary: 'Create a new sales order', pathParams: [], hasBody: true, isMultipart: false },
|
|
@@ -21,6 +21,7 @@ const ENDPOINTS = {
|
|
|
21
21
|
'replace': { method: 'POST', path: '/v1/sales-orders/{id}/replace', summary: 'Replace order with corrected version (APPROVED → creates new DRAFT)', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
22
22
|
'create-invoice': { method: 'POST', path: '/v1/sales-orders/{id}/create-invoice', summary: 'Create invoice from sales order (ACCEPTED → creates DRAFT invoice)', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
23
23
|
'create-line-items': { method: 'POST', path: '/v1/sales-orders/{orderId}/line-items', summary: 'Add a line item to a sales order', pathParams: ['orderId'], hasBody: true, isMultipart: false },
|
|
24
|
+
'update-line-items-reorder': { method: 'PATCH', path: '/v1/sales-orders/{orderId}/line-items/reorder', summary: 'Bulk reorder line items (drag-and-drop)', pathParams: ['orderId'], hasBody: true, isMultipart: false },
|
|
24
25
|
'update-line-items': { method: 'PATCH', path: '/v1/sales-orders/{orderId}/line-items/{lineItemId}', summary: 'Update a line item on a sales order', pathParams: ['orderId', 'lineItemId'], hasBody: true, isMultipart: false },
|
|
25
26
|
'delete-line-items': { method: 'DELETE', path: '/v1/sales-orders/{orderId}/line-items/{lineItemId}', summary: 'Remove a line item from a sales order', pathParams: ['orderId', 'lineItemId'], hasBody: false, isMultipart: false },
|
|
26
27
|
'list-notes': { method: 'GET', path: '/v1/sales-orders/{salesOrderId}/notes', summary: 'Get all notes for a sales order', pathParams: ['salesOrderId'], hasBody: false, isMultipart: false },
|
package/dist/lib/auth.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as http from 'node:http';
|
|
|
5
5
|
import { URL, URLSearchParams } from 'node:url';
|
|
6
6
|
import open from 'open';
|
|
7
7
|
import { getBaseUrls, getContext, saveTokens } from './config.js';
|
|
8
|
-
function buildValidatedUrl(baseUrl) {
|
|
8
|
+
function buildValidatedUrl(baseUrl, path) {
|
|
9
9
|
try {
|
|
10
10
|
// Minimal path validation
|
|
11
11
|
if (baseUrl.includes('/../') || /\/%2e%2e\//i.test(baseUrl)) {
|
|
@@ -24,6 +24,15 @@ function buildValidatedUrl(baseUrl) {
|
|
|
24
24
|
if (!['http:', 'https:'].includes(url.protocol)) {
|
|
25
25
|
throw new Error('Invalid protocol');
|
|
26
26
|
}
|
|
27
|
+
// Add path if provided
|
|
28
|
+
if (path) {
|
|
29
|
+
if (path.includes('/../') || /\/%2e%2e\//i.test(path)) {
|
|
30
|
+
throw new Error('Invalid path');
|
|
31
|
+
}
|
|
32
|
+
// Ensure path starts with / and append to pathname
|
|
33
|
+
const cleanPath = path.startsWith('/') ? path : '/' + path;
|
|
34
|
+
url.pathname = url.pathname.replace(/\/$/, '') + cleanPath;
|
|
35
|
+
}
|
|
27
36
|
return url.href;
|
|
28
37
|
}
|
|
29
38
|
catch {
|
|
@@ -234,7 +243,7 @@ async function exchangeCodeForTokens(context, code, codeVerifier) {
|
|
|
234
243
|
if (context.client_secret) {
|
|
235
244
|
params.set('client_secret', context.client_secret);
|
|
236
245
|
}
|
|
237
|
-
const response = await axios.post(buildValidatedUrl(
|
|
246
|
+
const response = await axios.post(buildValidatedUrl(authUrl, '/oauth/token'), params.toString(), {
|
|
238
247
|
headers: {
|
|
239
248
|
Accept: 'application/json',
|
|
240
249
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -267,7 +276,7 @@ export async function refreshTokens(contextName) {
|
|
|
267
276
|
}
|
|
268
277
|
let response;
|
|
269
278
|
try {
|
|
270
|
-
response = await axios.post(buildValidatedUrl(
|
|
279
|
+
response = await axios.post(buildValidatedUrl(authUrl, '/oauth/token'), params.toString(), {
|
|
271
280
|
headers: {
|
|
272
281
|
Accept: 'application/json',
|
|
273
282
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
@@ -316,7 +325,7 @@ export async function testAuth(contextName) {
|
|
|
316
325
|
}
|
|
317
326
|
const token = await getValidToken(contextName);
|
|
318
327
|
const { api: apiUrl } = getBaseUrls(context.environment);
|
|
319
|
-
const response = await axios.get(buildValidatedUrl(
|
|
328
|
+
const response = await axios.get(buildValidatedUrl(apiUrl, '/v1/auth/me'), {
|
|
320
329
|
headers: {
|
|
321
330
|
Accept: 'application/json',
|
|
322
331
|
Authorization: `Bearer ${token}`,
|
|
@@ -334,7 +343,7 @@ export async function listTenants(contextName) {
|
|
|
334
343
|
let response;
|
|
335
344
|
try {
|
|
336
345
|
// Frontegg endpoint to list user's tenants
|
|
337
|
-
response = await axios.get(buildValidatedUrl(
|
|
346
|
+
response = await axios.get(buildValidatedUrl(authUrl, '/identity/resources/users/v2/me/tenants'), {
|
|
338
347
|
headers: {
|
|
339
348
|
Accept: 'application/json',
|
|
340
349
|
Authorization: `Bearer ${token}`,
|
|
@@ -393,7 +402,7 @@ export async function switchTenant(contextName, tenantId) {
|
|
|
393
402
|
const token = await getValidToken(contextName);
|
|
394
403
|
try {
|
|
395
404
|
// Step 1: PUT to switch the user's active tenant
|
|
396
|
-
await axios.put(buildValidatedUrl(
|
|
405
|
+
await axios.put(buildValidatedUrl(authUrl, '/identity/resources/users/v1/tenant'), { tenantId }, {
|
|
397
406
|
headers: {
|
|
398
407
|
Accept: 'application/json',
|
|
399
408
|
Authorization: `Bearer ${token}`,
|
|
@@ -401,7 +410,7 @@ export async function switchTenant(contextName, tenantId) {
|
|
|
401
410
|
},
|
|
402
411
|
});
|
|
403
412
|
// Step 2: Refresh tokens to get new tokens for the switched tenant
|
|
404
|
-
const response = await axios.post(buildValidatedUrl(
|
|
413
|
+
const response = await axios.post(buildValidatedUrl(authUrl, '/oauth/token'), new URLSearchParams({
|
|
405
414
|
client_id: context.client_id,
|
|
406
415
|
grant_type: 'refresh_token',
|
|
407
416
|
refresh_token: context.tokens.refresh_token,
|