@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,12 +1,12 @@
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;
7
7
  const HAS_CAMT053 = false;
8
8
  const NESTED_IMPORTS = ["notes", "closings"];
9
- const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-closings", "create-closings", "get-closings", "update-closings", "closings-close", "closings-reopen"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-closings", "create-closings", "get-closings", "update-closings", "closings-close", "closings-reopen", "list-posting-runs", "create-posting-runs", "posting-runs"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/ledgers', summary: 'List all ledgers', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
12
  'create': { method: 'POST', path: '/v1/ledgers', summary: 'Create a new ledger', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['notes'] },
@@ -24,6 +24,9 @@ const ENDPOINTS = {
24
24
  'update-closings': { method: 'PATCH', path: '/v1/ledgers/{ledgerId}/closings/{id}', summary: 'Update closing description', pathParams: ['ledgerId', 'id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
25
  'closings-close': { method: 'POST', path: '/v1/ledgers/{ledgerId}/closings/{id}/close', summary: 'Transition closing to CLOSED. Computes netPnl from POSTED journals. Valid from DRAFT or REOPENED.', pathParams: ['ledgerId', 'id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
26
  'closings-reopen': { method: 'POST', path: '/v1/ledgers/{ledgerId}/closings/{id}/reopen', summary: 'Transition closing to REOPENED. netPnl snapshot is preserved. Valid from CLOSED only.', pathParams: ['ledgerId', 'id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
+ 'list-posting-runs': { method: 'GET', path: '/v1/ledgers/{ledgerId}/posting-runs', summary: 'List posting runs for a ledger', pathParams: ['ledgerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
+ 'create-posting-runs': { method: 'POST', path: '/v1/ledgers/{ledgerId}/posting-runs', summary: 'Post every APPROVED journal in a date range', pathParams: ['ledgerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
29
+ 'posting-runs': { method: 'GET', path: '/v1/ledgers/{ledgerId}/posting-runs/{id}', summary: 'Get a posting run by ID', pathParams: ['ledgerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
30
  };
28
31
  export default class Ledgers extends Command {
29
32
  static description = 'Manage ledgers';
@@ -40,7 +43,7 @@ export default class Ledgers extends Command {
40
43
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
41
44
  };
42
45
  static flags = {
43
- 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)' }),
44
47
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
45
48
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
46
49
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -53,7 +56,7 @@ export default class Ledgers extends Command {
53
56
  limit: Flags.string({ description: 'Items per page' }),
54
57
  include: Flags.string({ description: 'Relations to include' }),
55
58
  search: Flags.string({ description: 'Search term' }),
56
- '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.' }),
57
60
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
58
61
  query: Flags.string({ description: 'Additional query params as JSON' }),
59
62
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -114,9 +117,9 @@ export default class Ledgers extends Command {
114
117
  }
115
118
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
116
119
  if (!context)
117
- this.error('No context configured. Run: aderis auth login --new');
118
- if (!context.tokens)
119
- 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));
120
123
  const queryParams = {};
121
124
  if (flags.page)
122
125
  queryParams.page = flags.page;
@@ -127,7 +130,7 @@ export default class Ledgers extends Command {
127
130
  if (flags.search)
128
131
  queryParams.search = flags.search;
129
132
  if (flags['sort-by'])
130
- queryParams.sortBy = flags['sort-by'];
133
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
131
134
  if (flags.query) {
132
135
  try {
133
136
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -359,9 +362,9 @@ export default class Ledgers extends Command {
359
362
  async runImport(flags) {
360
363
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
361
364
  if (!context)
362
- this.error('No context configured. Run: aderis auth login --new');
363
- if (!context.tokens)
364
- 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));
365
368
  // Get data from file, --data, or --set flags
366
369
  let items = [];
367
370
  if (flags.file) {
@@ -571,9 +574,9 @@ export default class Ledgers extends Command {
571
574
  async runExport(flags) {
572
575
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
573
576
  if (!context)
574
- this.error('No context configured. Run: aderis auth login --new');
575
- if (!context.tokens)
576
- 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));
577
580
  const listEndpoint = ENDPOINTS['list'];
578
581
  if (!listEndpoint)
579
582
  this.error('Export requires a list endpoint');
@@ -586,7 +589,7 @@ export default class Ledgers extends Command {
586
589
  if (flags.search)
587
590
  baseParams.search = flags.search;
588
591
  if (flags['sort-by'])
589
- baseParams.sortBy = flags['sort-by'];
592
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
590
593
  if (flags.include)
591
594
  baseParams.include = flags.include;
592
595
  if (flags.query) {
@@ -665,9 +668,9 @@ export default class Ledgers extends Command {
665
668
  async runCamt053Import(flags) {
666
669
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
667
670
  if (!context)
668
- this.error('No context configured. Run: aderis auth login --new');
669
- if (!context.tokens)
670
- 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));
671
674
  if (!flags.file) {
672
675
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
673
676
  }
@@ -755,9 +758,9 @@ export default class Ledgers extends Command {
755
758
  }
756
759
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
757
760
  if (!context)
758
- this.error('No context configured. Run: aderis auth login --new');
759
- if (!context.tokens)
760
- 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));
761
764
  // Get data from file, --data, or --set flags
762
765
  let items = [];
763
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;
@@ -29,7 +29,7 @@ export default class OfficeLocations extends Command {
29
29
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
30
30
  };
31
31
  static flags = {
32
- context: Flags.string({ char: 'c', description: 'Context to use' }),
32
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
33
33
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
34
34
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
35
35
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -40,7 +40,7 @@ export default class OfficeLocations extends Command {
40
40
  limit: Flags.string({ description: 'Items per page' }),
41
41
  include: Flags.string({ description: 'Relations to include' }),
42
42
  search: Flags.string({ description: 'Search term' }),
43
- 'sort-by': Flags.string({ description: 'Sort field' }),
43
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
44
44
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
45
45
  query: Flags.string({ description: 'Additional query params as JSON' }),
46
46
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -101,9 +101,9 @@ export default class OfficeLocations extends Command {
101
101
  }
102
102
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
103
103
  if (!context)
104
- this.error('No context configured. Run: aderis auth login --new');
105
- if (!context.tokens)
106
- this.error('Not logged in. Run: aderis auth login');
104
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
105
+ if (!hasCredentials(context))
106
+ this.error(missingCredentialsMessage(context));
107
107
  const queryParams = {};
108
108
  if (flags.page)
109
109
  queryParams.page = flags.page;
@@ -114,7 +114,7 @@ export default class OfficeLocations extends Command {
114
114
  if (flags.search)
115
115
  queryParams.search = flags.search;
116
116
  if (flags['sort-by'])
117
- queryParams.sortBy = flags['sort-by'];
117
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
118
118
  if (flags.query) {
119
119
  try {
120
120
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -346,9 +346,9 @@ export default class OfficeLocations extends Command {
346
346
  async runImport(flags) {
347
347
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
348
348
  if (!context)
349
- this.error('No context configured. Run: aderis auth login --new');
350
- if (!context.tokens)
351
- this.error('Not logged in. Run: aderis auth login');
349
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
350
+ if (!hasCredentials(context))
351
+ this.error(missingCredentialsMessage(context));
352
352
  // Get data from file, --data, or --set flags
353
353
  let items = [];
354
354
  if (flags.file) {
@@ -558,9 +558,9 @@ export default class OfficeLocations extends Command {
558
558
  async runExport(flags) {
559
559
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
560
560
  if (!context)
561
- this.error('No context configured. Run: aderis auth login --new');
562
- if (!context.tokens)
563
- this.error('Not logged in. Run: aderis auth login');
561
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
562
+ if (!hasCredentials(context))
563
+ this.error(missingCredentialsMessage(context));
564
564
  const listEndpoint = ENDPOINTS['list'];
565
565
  if (!listEndpoint)
566
566
  this.error('Export requires a list endpoint');
@@ -573,7 +573,7 @@ export default class OfficeLocations extends Command {
573
573
  if (flags.search)
574
574
  baseParams.search = flags.search;
575
575
  if (flags['sort-by'])
576
- baseParams.sortBy = flags['sort-by'];
576
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
577
577
  if (flags.include)
578
578
  baseParams.include = flags.include;
579
579
  if (flags.query) {
@@ -652,9 +652,9 @@ export default class OfficeLocations extends Command {
652
652
  async runCamt053Import(flags) {
653
653
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
654
654
  if (!context)
655
- this.error('No context configured. Run: aderis auth login --new');
656
- if (!context.tokens)
657
- this.error('Not logged in. Run: aderis auth login');
655
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
656
+ if (!hasCredentials(context))
657
+ this.error(missingCredentialsMessage(context));
658
658
  if (!flags.file) {
659
659
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
660
660
  }
@@ -742,9 +742,9 @@ export default class OfficeLocations extends Command {
742
742
  }
743
743
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
744
744
  if (!context)
745
- this.error('No context configured. Run: aderis auth login --new');
746
- if (!context.tokens)
747
- this.error('Not logged in. Run: aderis auth login');
745
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
746
+ if (!hasCredentials(context))
747
+ this.error(missingCredentialsMessage(context));
748
748
  // Get data from file, --data, or --set flags
749
749
  let items = [];
750
750
  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;
@@ -34,7 +34,7 @@ export default class PaymentMethods extends Command {
34
34
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
35
35
  };
36
36
  static flags = {
37
- context: Flags.string({ char: 'c', description: 'Context to use' }),
37
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
38
38
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
39
39
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
40
40
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -46,7 +46,7 @@ export default class PaymentMethods extends Command {
46
46
  limit: Flags.string({ description: 'Items per page' }),
47
47
  include: Flags.string({ description: 'Relations to include' }),
48
48
  search: Flags.string({ description: 'Search term' }),
49
- 'sort-by': Flags.string({ description: 'Sort field' }),
49
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
50
50
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
51
51
  query: Flags.string({ description: 'Additional query params as JSON' }),
52
52
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -107,9 +107,9 @@ export default class PaymentMethods extends Command {
107
107
  }
108
108
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
109
109
  if (!context)
110
- this.error('No context configured. Run: aderis auth login --new');
111
- if (!context.tokens)
112
- this.error('Not logged in. Run: aderis auth login');
110
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
111
+ if (!hasCredentials(context))
112
+ this.error(missingCredentialsMessage(context));
113
113
  const queryParams = {};
114
114
  if (flags.page)
115
115
  queryParams.page = flags.page;
@@ -120,7 +120,7 @@ export default class PaymentMethods extends Command {
120
120
  if (flags.search)
121
121
  queryParams.search = flags.search;
122
122
  if (flags['sort-by'])
123
- queryParams.sortBy = flags['sort-by'];
123
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
124
124
  if (flags.query) {
125
125
  try {
126
126
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -352,9 +352,9 @@ export default class PaymentMethods extends Command {
352
352
  async runImport(flags) {
353
353
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
354
354
  if (!context)
355
- this.error('No context configured. Run: aderis auth login --new');
356
- if (!context.tokens)
357
- this.error('Not logged in. Run: aderis auth login');
355
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
356
+ if (!hasCredentials(context))
357
+ this.error(missingCredentialsMessage(context));
358
358
  // Get data from file, --data, or --set flags
359
359
  let items = [];
360
360
  if (flags.file) {
@@ -564,9 +564,9 @@ export default class PaymentMethods extends Command {
564
564
  async runExport(flags) {
565
565
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
566
566
  if (!context)
567
- this.error('No context configured. Run: aderis auth login --new');
568
- if (!context.tokens)
569
- this.error('Not logged in. Run: aderis auth login');
567
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
568
+ if (!hasCredentials(context))
569
+ this.error(missingCredentialsMessage(context));
570
570
  const listEndpoint = ENDPOINTS['list'];
571
571
  if (!listEndpoint)
572
572
  this.error('Export requires a list endpoint');
@@ -579,7 +579,7 @@ export default class PaymentMethods extends Command {
579
579
  if (flags.search)
580
580
  baseParams.search = flags.search;
581
581
  if (flags['sort-by'])
582
- baseParams.sortBy = flags['sort-by'];
582
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
583
583
  if (flags.include)
584
584
  baseParams.include = flags.include;
585
585
  if (flags.query) {
@@ -658,9 +658,9 @@ export default class PaymentMethods extends Command {
658
658
  async runCamt053Import(flags) {
659
659
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
660
660
  if (!context)
661
- this.error('No context configured. Run: aderis auth login --new');
662
- if (!context.tokens)
663
- this.error('Not logged in. Run: aderis auth login');
661
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
662
+ if (!hasCredentials(context))
663
+ this.error(missingCredentialsMessage(context));
664
664
  if (!flags.file) {
665
665
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
666
666
  }
@@ -748,9 +748,9 @@ export default class PaymentMethods extends Command {
748
748
  }
749
749
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
750
750
  if (!context)
751
- this.error('No context configured. Run: aderis auth login --new');
752
- if (!context.tokens)
753
- this.error('Not logged in. Run: aderis auth login');
751
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
752
+ if (!hasCredentials(context))
753
+ this.error(missingCredentialsMessage(context));
754
754
  // Get data from file, --data, or --set flags
755
755
  let items = [];
756
756
  if (flags.file) {
@@ -1,14 +1,15 @@
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;
7
7
  const HAS_CAMT053 = false;
8
8
  const NESTED_IMPORTS = [];
9
- const SUBCOMMANDS = [...["open-submissions", "list", "create", "preview", "schedule", "status", "get", "update", "delete", "create-payments", "delete-payments", "send", "painfile", "sync-status", "sync-status-xml", "sync-all"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["open-submissions", "eligible-payments", "list", "create", "preview", "schedule", "status", "get", "update", "delete", "create-payments", "delete-payments", "send", "painfile", "sync-status", "sync-status-xml", "sync-all"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'open-submissions': { method: 'GET', path: '/v1/payment-runs/bank-accounts/{bankAccountId}/open-submissions', summary: 'Get open submission IDs for a bank account', pathParams: ['bankAccountId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
+ 'eligible-payments': { method: 'GET', path: '/v1/payment-runs/eligible-payments/{bankAccountId}', summary: 'Show what a payment run from this bank account would pay', pathParams: ['bankAccountId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
13
  'list': { method: 'GET', path: '/v1/payment-runs', summary: 'List all payment runs with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
13
14
  'create': { method: 'POST', path: '/v1/payment-runs', summary: 'Create a DRAFT payment run from payment IDs', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['paymentIds'] },
14
15
  'preview': { method: 'POST', path: '/v1/payment-runs/preview/{bankAccountId}', summary: 'Preview eligible and filtered invoices for a payment run', pathParams: ['bankAccountId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['invoiceIds'] },
@@ -40,7 +41,7 @@ export default class PaymentRuns extends Command {
40
41
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
41
42
  };
42
43
  static flags = {
43
- context: Flags.string({ char: 'c', description: 'Context to use' }),
44
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
44
45
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
45
46
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
46
47
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -53,7 +54,7 @@ export default class PaymentRuns extends Command {
53
54
  limit: Flags.string({ description: 'Items per page' }),
54
55
  include: Flags.string({ description: 'Relations to include' }),
55
56
  search: Flags.string({ description: 'Search term' }),
56
- 'sort-by': Flags.string({ description: 'Sort field' }),
57
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
57
58
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
58
59
  query: Flags.string({ description: 'Additional query params as JSON' }),
59
60
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -114,9 +115,9 @@ export default class PaymentRuns extends Command {
114
115
  }
115
116
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
116
117
  if (!context)
117
- this.error('No context configured. Run: aderis auth login --new');
118
- if (!context.tokens)
119
- this.error('Not logged in. Run: aderis auth login');
118
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
119
+ if (!hasCredentials(context))
120
+ this.error(missingCredentialsMessage(context));
120
121
  const queryParams = {};
121
122
  if (flags.page)
122
123
  queryParams.page = flags.page;
@@ -127,7 +128,7 @@ export default class PaymentRuns extends Command {
127
128
  if (flags.search)
128
129
  queryParams.search = flags.search;
129
130
  if (flags['sort-by'])
130
- queryParams.sortBy = flags['sort-by'];
131
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
131
132
  if (flags.query) {
132
133
  try {
133
134
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -359,9 +360,9 @@ export default class PaymentRuns extends Command {
359
360
  async runImport(flags) {
360
361
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
361
362
  if (!context)
362
- this.error('No context configured. Run: aderis auth login --new');
363
- if (!context.tokens)
364
- this.error('Not logged in. Run: aderis auth login');
363
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
364
+ if (!hasCredentials(context))
365
+ this.error(missingCredentialsMessage(context));
365
366
  // Get data from file, --data, or --set flags
366
367
  let items = [];
367
368
  if (flags.file) {
@@ -571,9 +572,9 @@ export default class PaymentRuns extends Command {
571
572
  async runExport(flags) {
572
573
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
573
574
  if (!context)
574
- this.error('No context configured. Run: aderis auth login --new');
575
- if (!context.tokens)
576
- this.error('Not logged in. Run: aderis auth login');
575
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
576
+ if (!hasCredentials(context))
577
+ this.error(missingCredentialsMessage(context));
577
578
  const listEndpoint = ENDPOINTS['list'];
578
579
  if (!listEndpoint)
579
580
  this.error('Export requires a list endpoint');
@@ -586,7 +587,7 @@ export default class PaymentRuns extends Command {
586
587
  if (flags.search)
587
588
  baseParams.search = flags.search;
588
589
  if (flags['sort-by'])
589
- baseParams.sortBy = flags['sort-by'];
590
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
590
591
  if (flags.include)
591
592
  baseParams.include = flags.include;
592
593
  if (flags.query) {
@@ -665,9 +666,9 @@ export default class PaymentRuns extends Command {
665
666
  async runCamt053Import(flags) {
666
667
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
667
668
  if (!context)
668
- this.error('No context configured. Run: aderis auth login --new');
669
- if (!context.tokens)
670
- this.error('Not logged in. Run: aderis auth login');
669
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
670
+ if (!hasCredentials(context))
671
+ this.error(missingCredentialsMessage(context));
671
672
  if (!flags.file) {
672
673
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
673
674
  }
@@ -755,9 +756,9 @@ export default class PaymentRuns extends Command {
755
756
  }
756
757
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
757
758
  if (!context)
758
- this.error('No context configured. Run: aderis auth login --new');
759
- if (!context.tokens)
760
- this.error('Not logged in. Run: aderis auth login');
759
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
760
+ if (!hasCredentials(context))
761
+ this.error(missingCredentialsMessage(context));
761
762
  // Get data from file, --data, or --set flags
762
763
  let items = [];
763
764
  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;
@@ -30,7 +30,7 @@ export default class PaymentTerms extends Command {
30
30
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
31
31
  };
32
32
  static flags = {
33
- context: Flags.string({ char: 'c', description: 'Context to use' }),
33
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
34
34
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
35
35
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
36
36
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -41,7 +41,7 @@ export default class PaymentTerms extends Command {
41
41
  limit: Flags.string({ description: 'Items per page' }),
42
42
  include: Flags.string({ description: 'Relations to include' }),
43
43
  search: Flags.string({ description: 'Search term' }),
44
- 'sort-by': Flags.string({ description: 'Sort field' }),
44
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
45
45
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
46
46
  query: Flags.string({ description: 'Additional query params as JSON' }),
47
47
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -102,9 +102,9 @@ export default class PaymentTerms extends Command {
102
102
  }
103
103
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
104
104
  if (!context)
105
- this.error('No context configured. Run: aderis auth login --new');
106
- if (!context.tokens)
107
- this.error('Not logged in. Run: aderis auth login');
105
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
106
+ if (!hasCredentials(context))
107
+ this.error(missingCredentialsMessage(context));
108
108
  const queryParams = {};
109
109
  if (flags.page)
110
110
  queryParams.page = flags.page;
@@ -115,7 +115,7 @@ export default class PaymentTerms extends Command {
115
115
  if (flags.search)
116
116
  queryParams.search = flags.search;
117
117
  if (flags['sort-by'])
118
- queryParams.sortBy = flags['sort-by'];
118
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
119
119
  if (flags.query) {
120
120
  try {
121
121
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -347,9 +347,9 @@ export default class PaymentTerms extends Command {
347
347
  async runImport(flags) {
348
348
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
349
349
  if (!context)
350
- this.error('No context configured. Run: aderis auth login --new');
351
- if (!context.tokens)
352
- this.error('Not logged in. Run: aderis auth login');
350
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
351
+ if (!hasCredentials(context))
352
+ this.error(missingCredentialsMessage(context));
353
353
  // Get data from file, --data, or --set flags
354
354
  let items = [];
355
355
  if (flags.file) {
@@ -559,9 +559,9 @@ export default class PaymentTerms extends Command {
559
559
  async runExport(flags) {
560
560
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
561
561
  if (!context)
562
- this.error('No context configured. Run: aderis auth login --new');
563
- if (!context.tokens)
564
- this.error('Not logged in. Run: aderis auth login');
562
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
563
+ if (!hasCredentials(context))
564
+ this.error(missingCredentialsMessage(context));
565
565
  const listEndpoint = ENDPOINTS['list'];
566
566
  if (!listEndpoint)
567
567
  this.error('Export requires a list endpoint');
@@ -574,7 +574,7 @@ export default class PaymentTerms extends Command {
574
574
  if (flags.search)
575
575
  baseParams.search = flags.search;
576
576
  if (flags['sort-by'])
577
- baseParams.sortBy = flags['sort-by'];
577
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
578
578
  if (flags.include)
579
579
  baseParams.include = flags.include;
580
580
  if (flags.query) {
@@ -653,9 +653,9 @@ export default class PaymentTerms extends Command {
653
653
  async runCamt053Import(flags) {
654
654
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
655
655
  if (!context)
656
- this.error('No context configured. Run: aderis auth login --new');
657
- if (!context.tokens)
658
- this.error('Not logged in. Run: aderis auth login');
656
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
657
+ if (!hasCredentials(context))
658
+ this.error(missingCredentialsMessage(context));
659
659
  if (!flags.file) {
660
660
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
661
661
  }
@@ -743,9 +743,9 @@ export default class PaymentTerms extends Command {
743
743
  }
744
744
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
745
745
  if (!context)
746
- this.error('No context configured. Run: aderis auth login --new');
747
- if (!context.tokens)
748
- this.error('Not logged in. Run: aderis auth login');
746
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
747
+ if (!hasCredentials(context))
748
+ this.error(missingCredentialsMessage(context));
749
749
  // Get data from file, --data, or --set flags
750
750
  let items = [];
751
751
  if (flags.file) {