@aderis-erp/cli 1.0.13 → 1.0.15

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.
Files changed (86) hide show
  1. package/dist/commands/access-groups.js +21 -21
  2. package/dist/commands/account-transaction-allocations.js +21 -21
  3. package/dist/commands/account-transactions.js +23 -23
  4. package/dist/commands/accounts.js +23 -23
  5. package/dist/commands/agent-platform.js +23 -22
  6. package/dist/commands/analytics.d.ts +40 -0
  7. package/dist/commands/{documents.js → analytics.js} +33 -43
  8. package/dist/commands/audit-log.js +24 -24
  9. package/dist/commands/auth/login.js +11 -2
  10. package/dist/commands/auth/logout.d.ts +2 -0
  11. package/dist/commands/auth/logout.js +19 -6
  12. package/dist/commands/auth/status.js +26 -12
  13. package/dist/commands/auth/tenant.js +12 -3
  14. package/dist/commands/auth.js +32 -17
  15. package/dist/commands/bank-accounts.js +21 -21
  16. package/dist/commands/bank-integrations.js +21 -21
  17. package/dist/commands/business-partners.js +29 -26
  18. package/dist/commands/chat.js +21 -21
  19. package/dist/commands/config/add.d.ts +9 -0
  20. package/dist/commands/config/add.js +64 -2
  21. package/dist/commands/config/current.js +9 -4
  22. package/dist/commands/config/list.js +9 -4
  23. package/dist/commands/config/set-api-key.d.ts +10 -0
  24. package/dist/commands/config/set-api-key.js +49 -0
  25. package/dist/commands/config/use.js +3 -4
  26. package/dist/commands/credit-card-accounts.js +21 -21
  27. package/dist/commands/delivery-notes.js +28 -25
  28. package/dist/commands/dunning-configs.js +21 -21
  29. package/dist/commands/dunning-reminders.js +21 -21
  30. package/dist/commands/dunning-runs.js +21 -21
  31. package/dist/commands/email-transactions.js +21 -21
  32. package/dist/commands/employees.js +23 -23
  33. package/dist/commands/entity-configurations.js +21 -21
  34. package/dist/commands/event-processor-mappings.js +21 -21
  35. package/dist/commands/{documents.d.ts → files.d.ts} +1 -1
  36. package/dist/commands/{files-internal.js → files.js} +39 -33
  37. package/dist/commands/health.js +21 -21
  38. package/dist/commands/inbox.d.ts +1 -0
  39. package/dist/commands/inbox.js +25 -23
  40. package/dist/commands/integrations.js +21 -21
  41. package/dist/commands/item-categories.js +21 -21
  42. package/dist/commands/items.js +23 -23
  43. package/dist/commands/journal-lines.js +21 -21
  44. package/dist/commands/journals.js +27 -24
  45. package/dist/commands/ledgers.js +25 -22
  46. package/dist/commands/office-locations.js +21 -21
  47. package/dist/commands/payment-methods.js +21 -21
  48. package/dist/commands/payment-runs.js +23 -22
  49. package/dist/commands/payment-terms.js +21 -21
  50. package/dist/commands/payments.js +21 -21
  51. package/dist/commands/price-lists.js +21 -21
  52. package/dist/commands/processor-mappings.js +21 -21
  53. package/dist/commands/processors.js +21 -21
  54. package/dist/commands/purchase-order-types.js +21 -21
  55. package/dist/commands/purchase-orders.d.ts +1 -0
  56. package/dist/commands/purchase-orders.js +32 -25
  57. package/dist/commands/reports.js +21 -21
  58. package/dist/commands/salary-types.js +21 -21
  59. package/dist/commands/sales-invoices.js +33 -31
  60. package/dist/commands/sales-orders.js +23 -23
  61. package/dist/commands/saved-views.js +21 -21
  62. package/dist/commands/scheduled-processor-mappings.d.ts +40 -0
  63. package/dist/commands/scheduled-processor-mappings.js +1178 -0
  64. package/dist/commands/schedules.js +21 -21
  65. package/dist/commands/switch.js +10 -3
  66. package/dist/commands/{files-internal.d.ts → tag-configurations.d.ts} +1 -1
  67. package/dist/commands/tag-configurations.js +1178 -0
  68. package/dist/commands/tags.js +21 -21
  69. package/dist/commands/tax-codes.js +21 -21
  70. package/dist/commands/tax-matrix.js +21 -21
  71. package/dist/commands/tenants.js +23 -23
  72. package/dist/commands/text-templates.js +21 -21
  73. package/dist/commands/tools.js +21 -21
  74. package/dist/commands/vat-declarations.js +21 -21
  75. package/dist/commands/vendor-invoices.js +25 -25
  76. package/dist/commands/webhooks.js +21 -21
  77. package/dist/commands/workflows.js +21 -21
  78. package/dist/lib/api-client.d.ts +8 -0
  79. package/dist/lib/api-client.js +31 -6
  80. package/dist/lib/auth.d.ts +8 -0
  81. package/dist/lib/auth.js +51 -7
  82. package/dist/lib/base-api-command.js +6 -4
  83. package/dist/lib/config.d.ts +31 -1
  84. package/dist/lib/config.js +31 -0
  85. package/oclif.manifest.json +1099 -443
  86. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
2
+ import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
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 = false;
6
6
  const HAS_EXPORT = true;
@@ -22,7 +22,7 @@ export default class Tools extends Command {
22
22
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
23
23
  };
24
24
  static flags = {
25
- context: Flags.string({ char: 'c', description: 'Context to use' }),
25
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
26
26
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
27
27
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
28
28
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -33,7 +33,7 @@ export default class Tools extends Command {
33
33
  limit: Flags.string({ description: 'Items per page' }),
34
34
  include: Flags.string({ description: 'Relations to include' }),
35
35
  search: Flags.string({ description: 'Search term' }),
36
- 'sort-by': Flags.string({ description: 'Sort field' }),
36
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
37
37
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
38
38
  query: Flags.string({ description: 'Additional query params as JSON' }),
39
39
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -94,9 +94,9 @@ export default class Tools extends Command {
94
94
  }
95
95
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
96
96
  if (!context)
97
- this.error('No context configured. Run: aderis auth login --new');
98
- if (!context.tokens)
99
- this.error('Not logged in. Run: aderis auth login');
97
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
98
+ if (!hasCredentials(context))
99
+ this.error(missingCredentialsMessage(context));
100
100
  const queryParams = {};
101
101
  if (flags.page)
102
102
  queryParams.page = flags.page;
@@ -107,7 +107,7 @@ export default class Tools extends Command {
107
107
  if (flags.search)
108
108
  queryParams.search = flags.search;
109
109
  if (flags['sort-by'])
110
- queryParams.sortBy = flags['sort-by'];
110
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
111
111
  if (flags.query) {
112
112
  try {
113
113
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -339,9 +339,9 @@ export default class Tools extends Command {
339
339
  async runImport(flags) {
340
340
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
341
341
  if (!context)
342
- this.error('No context configured. Run: aderis auth login --new');
343
- if (!context.tokens)
344
- this.error('Not logged in. Run: aderis auth login');
342
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
343
+ if (!hasCredentials(context))
344
+ this.error(missingCredentialsMessage(context));
345
345
  // Get data from file, --data, or --set flags
346
346
  let items = [];
347
347
  if (flags.file) {
@@ -551,9 +551,9 @@ export default class Tools extends Command {
551
551
  async runExport(flags) {
552
552
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
553
553
  if (!context)
554
- this.error('No context configured. Run: aderis auth login --new');
555
- if (!context.tokens)
556
- this.error('Not logged in. Run: aderis auth login');
554
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
555
+ if (!hasCredentials(context))
556
+ this.error(missingCredentialsMessage(context));
557
557
  const listEndpoint = ENDPOINTS['list'];
558
558
  if (!listEndpoint)
559
559
  this.error('Export requires a list endpoint');
@@ -566,7 +566,7 @@ export default class Tools extends Command {
566
566
  if (flags.search)
567
567
  baseParams.search = flags.search;
568
568
  if (flags['sort-by'])
569
- baseParams.sortBy = flags['sort-by'];
569
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
570
570
  if (flags.include)
571
571
  baseParams.include = flags.include;
572
572
  if (flags.query) {
@@ -645,9 +645,9 @@ export default class Tools extends Command {
645
645
  async runCamt053Import(flags) {
646
646
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
647
647
  if (!context)
648
- this.error('No context configured. Run: aderis auth login --new');
649
- if (!context.tokens)
650
- this.error('Not logged in. Run: aderis auth login');
648
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
649
+ if (!hasCredentials(context))
650
+ this.error(missingCredentialsMessage(context));
651
651
  if (!flags.file) {
652
652
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
653
653
  }
@@ -735,9 +735,9 @@ export default class Tools extends Command {
735
735
  }
736
736
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
737
737
  if (!context)
738
- this.error('No context configured. Run: aderis auth login --new');
739
- if (!context.tokens)
740
- this.error('Not logged in. Run: aderis auth login');
738
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
739
+ if (!hasCredentials(context))
740
+ this.error(missingCredentialsMessage(context));
741
741
  // Get data from file, --data, or --set flags
742
742
  let items = [];
743
743
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
2
+ import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
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;
@@ -43,7 +43,7 @@ export default class VatDeclarations extends Command {
43
43
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
44
44
  };
45
45
  static flags = {
46
- context: Flags.string({ char: 'c', description: 'Context to use' }),
46
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
47
47
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
48
48
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
49
49
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -56,7 +56,7 @@ export default class VatDeclarations extends Command {
56
56
  limit: Flags.string({ description: 'Items per page' }),
57
57
  include: Flags.string({ description: 'Relations to include' }),
58
58
  search: Flags.string({ description: 'Search term' }),
59
- 'sort-by': Flags.string({ description: 'Sort field' }),
59
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
60
60
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
61
61
  query: Flags.string({ description: 'Additional query params as JSON' }),
62
62
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -117,9 +117,9 @@ export default class VatDeclarations extends Command {
117
117
  }
118
118
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
119
119
  if (!context)
120
- this.error('No context configured. Run: aderis auth login --new');
121
- if (!context.tokens)
122
- this.error('Not logged in. Run: aderis auth login');
120
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
121
+ if (!hasCredentials(context))
122
+ this.error(missingCredentialsMessage(context));
123
123
  const queryParams = {};
124
124
  if (flags.page)
125
125
  queryParams.page = flags.page;
@@ -130,7 +130,7 @@ export default class VatDeclarations extends Command {
130
130
  if (flags.search)
131
131
  queryParams.search = flags.search;
132
132
  if (flags['sort-by'])
133
- queryParams.sortBy = flags['sort-by'];
133
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
134
134
  if (flags.query) {
135
135
  try {
136
136
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -362,9 +362,9 @@ export default class VatDeclarations extends Command {
362
362
  async runImport(flags) {
363
363
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
364
364
  if (!context)
365
- this.error('No context configured. Run: aderis auth login --new');
366
- if (!context.tokens)
367
- this.error('Not logged in. Run: aderis auth login');
365
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
366
+ if (!hasCredentials(context))
367
+ this.error(missingCredentialsMessage(context));
368
368
  // Get data from file, --data, or --set flags
369
369
  let items = [];
370
370
  if (flags.file) {
@@ -574,9 +574,9 @@ export default class VatDeclarations extends Command {
574
574
  async runExport(flags) {
575
575
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
576
576
  if (!context)
577
- this.error('No context configured. Run: aderis auth login --new');
578
- if (!context.tokens)
579
- this.error('Not logged in. Run: aderis auth login');
577
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
578
+ if (!hasCredentials(context))
579
+ this.error(missingCredentialsMessage(context));
580
580
  const listEndpoint = ENDPOINTS['list'];
581
581
  if (!listEndpoint)
582
582
  this.error('Export requires a list endpoint');
@@ -589,7 +589,7 @@ export default class VatDeclarations extends Command {
589
589
  if (flags.search)
590
590
  baseParams.search = flags.search;
591
591
  if (flags['sort-by'])
592
- baseParams.sortBy = flags['sort-by'];
592
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
593
593
  if (flags.include)
594
594
  baseParams.include = flags.include;
595
595
  if (flags.query) {
@@ -668,9 +668,9 @@ export default class VatDeclarations extends Command {
668
668
  async runCamt053Import(flags) {
669
669
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
670
670
  if (!context)
671
- this.error('No context configured. Run: aderis auth login --new');
672
- if (!context.tokens)
673
- this.error('Not logged in. Run: aderis auth login');
671
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
672
+ if (!hasCredentials(context))
673
+ this.error(missingCredentialsMessage(context));
674
674
  if (!flags.file) {
675
675
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
676
676
  }
@@ -758,9 +758,9 @@ export default class VatDeclarations extends Command {
758
758
  }
759
759
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
760
760
  if (!context)
761
- this.error('No context configured. Run: aderis auth login --new');
762
- if (!context.tokens)
763
- this.error('Not logged in. Run: aderis auth login');
761
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
762
+ if (!hasCredentials(context))
763
+ this.error(missingCredentialsMessage(context));
764
764
  // Get data from file, --data, or --set flags
765
765
  let items = [];
766
766
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
2
+ import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
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;
@@ -9,12 +9,12 @@ const NESTED_IMPORTS = ["line-items", "notes", "files", "payments"];
9
9
  const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "submit", "approve", "decline", "book", "rebuild-journal", "cancel", "confirm-cancellation", "change-vendor", "recalculate-payment-status", "validate", "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", "list-payments", "create-payments", "get-payments", "update-payments", "delete-payments", "payments-approve", "payments-cancel"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/vendor-invoices', summary: 'Get all vendor invoices with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/vendor-invoices', summary: 'Create a new vendor invoice', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'payments'] },
12
+ 'create': { method: 'POST', path: '/v1/vendor-invoices', summary: 'Create a new vendor invoice', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'tagCodes', 'payments'] },
13
13
  'get': { method: 'GET', path: '/v1/vendor-invoices/{id}', summary: 'Get a vendor invoice by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'update': { method: 'PATCH', path: '/v1/vendor-invoices/{id}', summary: 'Update a vendor invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'removeFileIds'] },
14
+ 'update': { method: 'PATCH', path: '/v1/vendor-invoices/{id}', summary: 'Update a vendor invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'tagCodes', 'removeFileIds'] },
15
15
  'delete': { method: 'DELETE', path: '/v1/vendor-invoices/{id}', summary: 'Delete a vendor invoice', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
16
  'submit': { method: 'POST', path: '/v1/vendor-invoices/{id}/submit', summary: 'Submit a vendor invoice for approval (transitions DRAFT to PENDING_APPROVAL)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
- 'approve': { method: 'POST', path: '/v1/vendor-invoices/{id}/approve', summary: 'Approve a vendor invoice (transitions DRAFT/PENDING_APPROVAL to APPROVED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'removeFileIds'] },
17
+ 'approve': { method: 'POST', path: '/v1/vendor-invoices/{id}/approve', summary: 'Approve a vendor invoice (transitions DRAFT/PENDING_APPROVAL to APPROVED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'tagCodes', 'removeFileIds'] },
18
18
  'decline': { method: 'POST', path: '/v1/vendor-invoices/{id}/decline', summary: 'Decline a vendor invoice (transitions PENDING_APPROVAL to DECLINED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
19
  'book': { method: 'POST', path: '/v1/vendor-invoices/{id}/book', summary: 'Manually book a vendor invoice (dispatch to ledger-booking-agent)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
20
  'rebuild-journal': { method: 'POST', path: '/v1/vendor-invoices/{id}/rebuild-journal', summary: 'Rebuild a vendor invoice booking journal (dispatch to ledger-booking-agent)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -22,7 +22,7 @@ const ENDPOINTS = {
22
22
  'confirm-cancellation': { method: 'POST', path: '/v1/vendor-invoices/{id}/confirm-cancellation', summary: 'Confirm bank cancellation for a vendor invoice (PENDING_CANCELLATION to CANCELLED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
23
  'change-vendor': { method: 'POST', path: '/v1/vendor-invoices/{id}/change-vendor', summary: 'Change the vendor on a vendor invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
24
24
  'recalculate-payment-status': { method: 'POST', path: '/v1/vendor-invoices/{id}/recalculate-payment-status', summary: 'Recalculate a vendor invoice\'s open amount and payment status', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
- 'validate': { method: 'POST', path: '/v1/vendor-invoices/{id}/validate', summary: 'Validate a vendor invoice update without persisting changes', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'removeFileIds'] },
25
+ 'validate': { method: 'POST', path: '/v1/vendor-invoices/{id}/validate', summary: 'Validate a vendor invoice update without persisting changes', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'totalAmountByTaxRate', 'files', 'notes', 'lineItems', 'tagIds', 'tagCodes', 'removeFileIds'] },
26
26
  'create-line-items': { method: 'POST', path: '/v1/vendor-invoices/{invoiceId}/line-items', summary: 'Add a line item to a vendor invoice', pathParams: ['invoiceId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
27
  'update-line-items': { method: 'PATCH', path: '/v1/vendor-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Update a line item on a vendor invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
28
  'delete-line-items': { method: 'DELETE', path: '/v1/vendor-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Remove a line item from a vendor invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -60,7 +60,7 @@ export default class VendorInvoices extends Command {
60
60
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
61
61
  };
62
62
  static flags = {
63
- context: Flags.string({ char: 'c', description: 'Context to use' }),
63
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
64
64
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
65
65
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
66
66
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -75,7 +75,7 @@ export default class VendorInvoices extends Command {
75
75
  limit: Flags.string({ description: 'Items per page' }),
76
76
  include: Flags.string({ description: 'Relations to include' }),
77
77
  search: Flags.string({ description: 'Search term' }),
78
- 'sort-by': Flags.string({ description: 'Sort field' }),
78
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
79
79
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
80
80
  query: Flags.string({ description: 'Additional query params as JSON' }),
81
81
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -136,9 +136,9 @@ export default class VendorInvoices extends Command {
136
136
  }
137
137
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
138
138
  if (!context)
139
- this.error('No context configured. Run: aderis auth login --new');
140
- if (!context.tokens)
141
- this.error('Not logged in. Run: aderis auth login');
139
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
140
+ if (!hasCredentials(context))
141
+ this.error(missingCredentialsMessage(context));
142
142
  const queryParams = {};
143
143
  if (flags.page)
144
144
  queryParams.page = flags.page;
@@ -149,7 +149,7 @@ export default class VendorInvoices extends Command {
149
149
  if (flags.search)
150
150
  queryParams.search = flags.search;
151
151
  if (flags['sort-by'])
152
- queryParams.sortBy = flags['sort-by'];
152
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
153
153
  if (flags.query) {
154
154
  try {
155
155
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -381,9 +381,9 @@ export default class VendorInvoices extends Command {
381
381
  async runImport(flags) {
382
382
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
383
383
  if (!context)
384
- this.error('No context configured. Run: aderis auth login --new');
385
- if (!context.tokens)
386
- this.error('Not logged in. Run: aderis auth login');
384
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
385
+ if (!hasCredentials(context))
386
+ this.error(missingCredentialsMessage(context));
387
387
  // Get data from file, --data, or --set flags
388
388
  let items = [];
389
389
  if (flags.file) {
@@ -593,9 +593,9 @@ export default class VendorInvoices extends Command {
593
593
  async runExport(flags) {
594
594
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
595
595
  if (!context)
596
- this.error('No context configured. Run: aderis auth login --new');
597
- if (!context.tokens)
598
- this.error('Not logged in. Run: aderis auth login');
596
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
597
+ if (!hasCredentials(context))
598
+ this.error(missingCredentialsMessage(context));
599
599
  const listEndpoint = ENDPOINTS['list'];
600
600
  if (!listEndpoint)
601
601
  this.error('Export requires a list endpoint');
@@ -608,7 +608,7 @@ export default class VendorInvoices extends Command {
608
608
  if (flags.search)
609
609
  baseParams.search = flags.search;
610
610
  if (flags['sort-by'])
611
- baseParams.sortBy = flags['sort-by'];
611
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
612
612
  if (flags.include)
613
613
  baseParams.include = flags.include;
614
614
  if (flags.query) {
@@ -687,9 +687,9 @@ export default class VendorInvoices extends Command {
687
687
  async runCamt053Import(flags) {
688
688
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
689
689
  if (!context)
690
- this.error('No context configured. Run: aderis auth login --new');
691
- if (!context.tokens)
692
- this.error('Not logged in. Run: aderis auth login');
690
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
691
+ if (!hasCredentials(context))
692
+ this.error(missingCredentialsMessage(context));
693
693
  if (!flags.file) {
694
694
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
695
695
  }
@@ -777,9 +777,9 @@ export default class VendorInvoices extends Command {
777
777
  }
778
778
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
779
779
  if (!context)
780
- this.error('No context configured. Run: aderis auth login --new');
781
- if (!context.tokens)
782
- this.error('Not logged in. Run: aderis auth login');
780
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
781
+ if (!hasCredentials(context))
782
+ this.error(missingCredentialsMessage(context));
783
783
  // Get data from file, --data, or --set flags
784
784
  let items = [];
785
785
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
2
+ import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
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;
@@ -31,7 +31,7 @@ export default class Webhooks extends Command {
31
31
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
32
32
  };
33
33
  static flags = {
34
- context: Flags.string({ char: 'c', description: 'Context to use' }),
34
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
35
35
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
36
36
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
37
37
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -42,7 +42,7 @@ export default class Webhooks extends Command {
42
42
  limit: Flags.string({ description: 'Items per page' }),
43
43
  include: Flags.string({ description: 'Relations to include' }),
44
44
  search: Flags.string({ description: 'Search term' }),
45
- 'sort-by': Flags.string({ description: 'Sort field' }),
45
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
46
46
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
47
47
  query: Flags.string({ description: 'Additional query params as JSON' }),
48
48
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -103,9 +103,9 @@ export default class Webhooks extends Command {
103
103
  }
104
104
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
105
105
  if (!context)
106
- this.error('No context configured. Run: aderis auth login --new');
107
- if (!context.tokens)
108
- this.error('Not logged in. Run: aderis auth login');
106
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
107
+ if (!hasCredentials(context))
108
+ this.error(missingCredentialsMessage(context));
109
109
  const queryParams = {};
110
110
  if (flags.page)
111
111
  queryParams.page = flags.page;
@@ -116,7 +116,7 @@ export default class Webhooks extends Command {
116
116
  if (flags.search)
117
117
  queryParams.search = flags.search;
118
118
  if (flags['sort-by'])
119
- queryParams.sortBy = flags['sort-by'];
119
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
120
120
  if (flags.query) {
121
121
  try {
122
122
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -348,9 +348,9 @@ export default class Webhooks extends Command {
348
348
  async runImport(flags) {
349
349
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
350
350
  if (!context)
351
- this.error('No context configured. Run: aderis auth login --new');
352
- if (!context.tokens)
353
- this.error('Not logged in. Run: aderis auth login');
351
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
352
+ if (!hasCredentials(context))
353
+ this.error(missingCredentialsMessage(context));
354
354
  // Get data from file, --data, or --set flags
355
355
  let items = [];
356
356
  if (flags.file) {
@@ -560,9 +560,9 @@ export default class Webhooks extends Command {
560
560
  async runExport(flags) {
561
561
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
562
562
  if (!context)
563
- this.error('No context configured. Run: aderis auth login --new');
564
- if (!context.tokens)
565
- this.error('Not logged in. Run: aderis auth login');
563
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
564
+ if (!hasCredentials(context))
565
+ this.error(missingCredentialsMessage(context));
566
566
  const listEndpoint = ENDPOINTS['list'];
567
567
  if (!listEndpoint)
568
568
  this.error('Export requires a list endpoint');
@@ -575,7 +575,7 @@ export default class Webhooks extends Command {
575
575
  if (flags.search)
576
576
  baseParams.search = flags.search;
577
577
  if (flags['sort-by'])
578
- baseParams.sortBy = flags['sort-by'];
578
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
579
579
  if (flags.include)
580
580
  baseParams.include = flags.include;
581
581
  if (flags.query) {
@@ -654,9 +654,9 @@ export default class Webhooks extends Command {
654
654
  async runCamt053Import(flags) {
655
655
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
656
656
  if (!context)
657
- this.error('No context configured. Run: aderis auth login --new');
658
- if (!context.tokens)
659
- this.error('Not logged in. Run: aderis auth login');
657
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
658
+ if (!hasCredentials(context))
659
+ this.error(missingCredentialsMessage(context));
660
660
  if (!flags.file) {
661
661
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
662
662
  }
@@ -744,9 +744,9 @@ export default class Webhooks extends Command {
744
744
  }
745
745
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
746
746
  if (!context)
747
- this.error('No context configured. Run: aderis auth login --new');
748
- if (!context.tokens)
749
- this.error('Not logged in. Run: aderis auth login');
747
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
748
+ if (!hasCredentials(context))
749
+ this.error(missingCredentialsMessage(context));
750
750
  // Get data from file, --data, or --set flags
751
751
  let items = [];
752
752
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
2
+ import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
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 = false;
6
6
  const HAS_EXPORT = true;
@@ -23,7 +23,7 @@ export default class Workflows extends Command {
23
23
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
24
24
  };
25
25
  static flags = {
26
- context: Flags.string({ char: 'c', description: 'Context to use' }),
26
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
27
27
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
28
28
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
29
29
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -34,7 +34,7 @@ export default class Workflows extends Command {
34
34
  limit: Flags.string({ description: 'Items per page' }),
35
35
  include: Flags.string({ description: 'Relations to include' }),
36
36
  search: Flags.string({ description: 'Search term' }),
37
- 'sort-by': Flags.string({ description: 'Sort field' }),
37
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
38
38
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
39
39
  query: Flags.string({ description: 'Additional query params as JSON' }),
40
40
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -95,9 +95,9 @@ export default class Workflows extends Command {
95
95
  }
96
96
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
97
97
  if (!context)
98
- this.error('No context configured. Run: aderis auth login --new');
99
- if (!context.tokens)
100
- this.error('Not logged in. Run: aderis auth login');
98
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
99
+ if (!hasCredentials(context))
100
+ this.error(missingCredentialsMessage(context));
101
101
  const queryParams = {};
102
102
  if (flags.page)
103
103
  queryParams.page = flags.page;
@@ -108,7 +108,7 @@ export default class Workflows extends Command {
108
108
  if (flags.search)
109
109
  queryParams.search = flags.search;
110
110
  if (flags['sort-by'])
111
- queryParams.sortBy = flags['sort-by'];
111
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
112
112
  if (flags.query) {
113
113
  try {
114
114
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -340,9 +340,9 @@ export default class Workflows extends Command {
340
340
  async runImport(flags) {
341
341
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
342
342
  if (!context)
343
- this.error('No context configured. Run: aderis auth login --new');
344
- if (!context.tokens)
345
- this.error('Not logged in. Run: aderis auth login');
343
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
344
+ if (!hasCredentials(context))
345
+ this.error(missingCredentialsMessage(context));
346
346
  // Get data from file, --data, or --set flags
347
347
  let items = [];
348
348
  if (flags.file) {
@@ -552,9 +552,9 @@ export default class Workflows extends Command {
552
552
  async runExport(flags) {
553
553
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
554
554
  if (!context)
555
- this.error('No context configured. Run: aderis auth login --new');
556
- if (!context.tokens)
557
- this.error('Not logged in. Run: aderis auth login');
555
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
556
+ if (!hasCredentials(context))
557
+ this.error(missingCredentialsMessage(context));
558
558
  const listEndpoint = ENDPOINTS['list'];
559
559
  if (!listEndpoint)
560
560
  this.error('Export requires a list endpoint');
@@ -567,7 +567,7 @@ export default class Workflows extends Command {
567
567
  if (flags.search)
568
568
  baseParams.search = flags.search;
569
569
  if (flags['sort-by'])
570
- baseParams.sortBy = flags['sort-by'];
570
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
571
571
  if (flags.include)
572
572
  baseParams.include = flags.include;
573
573
  if (flags.query) {
@@ -646,9 +646,9 @@ export default class Workflows extends Command {
646
646
  async runCamt053Import(flags) {
647
647
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
648
648
  if (!context)
649
- this.error('No context configured. Run: aderis auth login --new');
650
- if (!context.tokens)
651
- this.error('Not logged in. Run: aderis auth login');
649
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
650
+ if (!hasCredentials(context))
651
+ this.error(missingCredentialsMessage(context));
652
652
  if (!flags.file) {
653
653
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
654
654
  }
@@ -736,9 +736,9 @@ export default class Workflows extends Command {
736
736
  }
737
737
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
738
738
  if (!context)
739
- this.error('No context configured. Run: aderis auth login --new');
740
- if (!context.tokens)
741
- this.error('Not logged in. Run: aderis auth login');
739
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
740
+ if (!hasCredentials(context))
741
+ this.error(missingCredentialsMessage(context));
742
742
  // Get data from file, --data, or --set flags
743
743
  let items = [];
744
744
  if (flags.file) {
@@ -20,6 +20,14 @@ export interface PaginatedResponse<T> {
20
20
  totalPages: number;
21
21
  };
22
22
  }
23
+ /**
24
+ * Normalize a --sort-by value: comma-separated fields, each optionally suffixed
25
+ * with `:ASC` or `:DESC`. Fields without an explicit direction default to DESC
26
+ * when the leaf name ends in `At`, `Date`, or `Time` (dates read newest-first);
27
+ * everything else defaults to ASC. Returned as an array so axios expands it
28
+ * into repeated `sortBy=a:ASC&sortBy=b:DESC` params.
29
+ */
30
+ export declare function normalizeSortBy(input: string): string[];
23
31
  export declare class ApiError extends Error {
24
32
  status: number;
25
33
  data?: unknown | undefined;