@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 { Args, Command, Flags } from '@oclif/core';
2
2
  import { ApiError, apiRequest } from '../lib/api-client.js';
3
- import { getContext, getCurrentContext } from '../lib/config.js';
3
+ import { getContext, getCurrentContext, 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 = false;
@@ -40,7 +40,12 @@ export default class Auth extends Command {
40
40
  static description = 'Manage auth';
41
41
  static examples = [];
42
42
  static flags = {
43
- context: Flags.string({ char: 'c', description: 'Context to use' }),
43
+ context: Flags.string({
44
+ aliases: ['config'],
45
+ char: 'c',
46
+ description: 'Context to use for this command, overriding the current context (alias: --config)',
47
+ env: 'ADERIS_CONTEXT',
48
+ }),
44
49
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
45
50
  data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
46
51
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -96,9 +101,11 @@ export default class Auth extends Command {
96
101
  this.error(`Unknown action: ${args.action}. Available: ${SUBCOMMANDS.join(', ')}`);
97
102
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
98
103
  if (!context)
99
- this.error('No context configured. Run: aderis auth login --new');
100
- if (!context.tokens)
101
- this.error('Not logged in. Run: aderis auth login');
104
+ this.error(flags.context
105
+ ? `Context "${flags.context}" not found. List contexts with: aderis config list`
106
+ : 'No context configured. Run: aderis auth login --new');
107
+ if (!hasCredentials(context))
108
+ this.error(missingCredentialsMessage(context));
102
109
  let apiPath = endpoint.path;
103
110
  for (const param of endpoint.pathParams) {
104
111
  let value;
@@ -359,9 +366,11 @@ export default class Auth extends Command {
359
366
  async runCamt053Import(flags) {
360
367
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
361
368
  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');
369
+ this.error(flags.context
370
+ ? `Context "${flags.context}" not found. List contexts with: aderis config list`
371
+ : 'No context configured. Run: aderis auth login --new');
372
+ if (!hasCredentials(context))
373
+ this.error(missingCredentialsMessage(context));
365
374
  if (!flags.file) {
366
375
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
367
376
  }
@@ -446,9 +455,11 @@ export default class Auth extends Command {
446
455
  async runExport(flags) {
447
456
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
448
457
  if (!context)
449
- this.error('No context configured. Run: aderis auth login --new');
450
- if (!context.tokens)
451
- this.error('Not logged in. Run: aderis auth login');
458
+ this.error(flags.context
459
+ ? `Context "${flags.context}" not found. List contexts with: aderis config list`
460
+ : 'No context configured. Run: aderis auth login --new');
461
+ if (!hasCredentials(context))
462
+ this.error(missingCredentialsMessage(context));
452
463
  const listEndpoint = ENDPOINTS.list;
453
464
  if (!listEndpoint)
454
465
  this.error('Export requires a list endpoint');
@@ -522,9 +533,11 @@ export default class Auth extends Command {
522
533
  async runImport(flags) {
523
534
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
524
535
  if (!context)
525
- this.error('No context configured. Run: aderis auth login --new');
526
- if (!context.tokens)
527
- this.error('Not logged in. Run: aderis auth login');
536
+ this.error(flags.context
537
+ ? `Context "${flags.context}" not found. List contexts with: aderis config list`
538
+ : 'No context configured. Run: aderis auth login --new');
539
+ if (!hasCredentials(context))
540
+ this.error(missingCredentialsMessage(context));
528
541
  // Get data from file, --data, or --set flags
529
542
  let items = [];
530
543
  if (flags.file) {
@@ -676,9 +689,11 @@ export default class Auth extends Command {
676
689
  }
677
690
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
678
691
  if (!context)
679
- this.error('No context configured. Run: aderis auth login --new');
680
- if (!context.tokens)
681
- this.error('Not logged in. Run: aderis auth login');
692
+ this.error(flags.context
693
+ ? `Context "${flags.context}" not found. List contexts with: aderis config list`
694
+ : 'No context configured. Run: aderis auth login --new');
695
+ if (!hasCredentials(context))
696
+ this.error(missingCredentialsMessage(context));
682
697
  // Get data from file, --data, or --set flags
683
698
  let items = [];
684
699
  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;
@@ -41,7 +41,7 @@ export default class BankAccounts extends Command {
41
41
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
42
42
  };
43
43
  static flags = {
44
- 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)' }),
45
45
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
46
46
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
47
47
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -54,7 +54,7 @@ export default class BankAccounts extends Command {
54
54
  limit: Flags.string({ description: 'Items per page' }),
55
55
  include: Flags.string({ description: 'Relations to include' }),
56
56
  search: Flags.string({ description: 'Search term' }),
57
- '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.' }),
58
58
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
59
59
  query: Flags.string({ description: 'Additional query params as JSON' }),
60
60
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -115,9 +115,9 @@ export default class BankAccounts extends Command {
115
115
  }
116
116
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
117
117
  if (!context)
118
- this.error('No context configured. Run: aderis auth login --new');
119
- if (!context.tokens)
120
- 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));
121
121
  const queryParams = {};
122
122
  if (flags.page)
123
123
  queryParams.page = flags.page;
@@ -128,7 +128,7 @@ export default class BankAccounts extends Command {
128
128
  if (flags.search)
129
129
  queryParams.search = flags.search;
130
130
  if (flags['sort-by'])
131
- queryParams.sortBy = flags['sort-by'];
131
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
132
132
  if (flags.query) {
133
133
  try {
134
134
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -360,9 +360,9 @@ export default class BankAccounts extends Command {
360
360
  async runImport(flags) {
361
361
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
362
362
  if (!context)
363
- this.error('No context configured. Run: aderis auth login --new');
364
- if (!context.tokens)
365
- 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));
366
366
  // Get data from file, --data, or --set flags
367
367
  let items = [];
368
368
  if (flags.file) {
@@ -572,9 +572,9 @@ export default class BankAccounts extends Command {
572
572
  async runExport(flags) {
573
573
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
574
574
  if (!context)
575
- this.error('No context configured. Run: aderis auth login --new');
576
- if (!context.tokens)
577
- 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));
578
578
  const listEndpoint = ENDPOINTS['list'];
579
579
  if (!listEndpoint)
580
580
  this.error('Export requires a list endpoint');
@@ -587,7 +587,7 @@ export default class BankAccounts extends Command {
587
587
  if (flags.search)
588
588
  baseParams.search = flags.search;
589
589
  if (flags['sort-by'])
590
- baseParams.sortBy = flags['sort-by'];
590
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
591
591
  if (flags.include)
592
592
  baseParams.include = flags.include;
593
593
  if (flags.query) {
@@ -666,9 +666,9 @@ export default class BankAccounts extends Command {
666
666
  async runCamt053Import(flags) {
667
667
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
668
668
  if (!context)
669
- this.error('No context configured. Run: aderis auth login --new');
670
- if (!context.tokens)
671
- 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));
672
672
  if (!flags.file) {
673
673
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
674
674
  }
@@ -756,9 +756,9 @@ export default class BankAccounts extends Command {
756
756
  }
757
757
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
758
758
  if (!context)
759
- this.error('No context configured. Run: aderis auth login --new');
760
- if (!context.tokens)
761
- 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));
762
762
  // Get data from file, --data, or --set flags
763
763
  let items = [];
764
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;
@@ -42,7 +42,7 @@ export default class BankIntegrations extends Command {
42
42
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
43
43
  };
44
44
  static flags = {
45
- context: Flags.string({ char: 'c', description: 'Context to use' }),
45
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
46
46
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
47
47
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
48
48
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -55,7 +55,7 @@ export default class BankIntegrations extends Command {
55
55
  limit: Flags.string({ description: 'Items per page' }),
56
56
  include: Flags.string({ description: 'Relations to include' }),
57
57
  search: Flags.string({ description: 'Search term' }),
58
- 'sort-by': Flags.string({ description: 'Sort field' }),
58
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
59
59
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
60
60
  query: Flags.string({ description: 'Additional query params as JSON' }),
61
61
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -116,9 +116,9 @@ export default class BankIntegrations extends Command {
116
116
  }
117
117
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
118
118
  if (!context)
119
- this.error('No context configured. Run: aderis auth login --new');
120
- if (!context.tokens)
121
- this.error('Not logged in. Run: aderis auth login');
119
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
120
+ if (!hasCredentials(context))
121
+ this.error(missingCredentialsMessage(context));
122
122
  const queryParams = {};
123
123
  if (flags.page)
124
124
  queryParams.page = flags.page;
@@ -129,7 +129,7 @@ export default class BankIntegrations extends Command {
129
129
  if (flags.search)
130
130
  queryParams.search = flags.search;
131
131
  if (flags['sort-by'])
132
- queryParams.sortBy = flags['sort-by'];
132
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
133
133
  if (flags.query) {
134
134
  try {
135
135
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -361,9 +361,9 @@ export default class BankIntegrations extends Command {
361
361
  async runImport(flags) {
362
362
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
363
363
  if (!context)
364
- this.error('No context configured. Run: aderis auth login --new');
365
- if (!context.tokens)
366
- this.error('Not logged in. Run: aderis auth login');
364
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
365
+ if (!hasCredentials(context))
366
+ this.error(missingCredentialsMessage(context));
367
367
  // Get data from file, --data, or --set flags
368
368
  let items = [];
369
369
  if (flags.file) {
@@ -573,9 +573,9 @@ export default class BankIntegrations extends Command {
573
573
  async runExport(flags) {
574
574
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
575
575
  if (!context)
576
- this.error('No context configured. Run: aderis auth login --new');
577
- if (!context.tokens)
578
- this.error('Not logged in. Run: aderis auth login');
576
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
577
+ if (!hasCredentials(context))
578
+ this.error(missingCredentialsMessage(context));
579
579
  const listEndpoint = ENDPOINTS['list'];
580
580
  if (!listEndpoint)
581
581
  this.error('Export requires a list endpoint');
@@ -588,7 +588,7 @@ export default class BankIntegrations extends Command {
588
588
  if (flags.search)
589
589
  baseParams.search = flags.search;
590
590
  if (flags['sort-by'])
591
- baseParams.sortBy = flags['sort-by'];
591
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
592
592
  if (flags.include)
593
593
  baseParams.include = flags.include;
594
594
  if (flags.query) {
@@ -667,9 +667,9 @@ export default class BankIntegrations extends Command {
667
667
  async runCamt053Import(flags) {
668
668
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
669
669
  if (!context)
670
- this.error('No context configured. Run: aderis auth login --new');
671
- if (!context.tokens)
672
- this.error('Not logged in. Run: aderis auth login');
670
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
671
+ if (!hasCredentials(context))
672
+ this.error(missingCredentialsMessage(context));
673
673
  if (!flags.file) {
674
674
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
675
675
  }
@@ -757,9 +757,9 @@ export default class BankIntegrations extends Command {
757
757
  }
758
758
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
759
759
  if (!context)
760
- this.error('No context configured. Run: aderis auth login --new');
761
- if (!context.tokens)
762
- this.error('Not logged in. Run: aderis auth login');
760
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
761
+ if (!hasCredentials(context))
762
+ this.error(missingCredentialsMessage(context));
763
763
  // Get data from file, --data, or --set flags
764
764
  let items = [];
765
765
  if (flags.file) {
@@ -1,29 +1,32 @@
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", "contacts", "contacts-notes"];
9
- const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "merge", "activate", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-contacts", "create-contacts", "get-contacts", "update-contacts", "delete-contacts", "list-contacts-notes", "create-contacts-notes", "get-contacts-notes", "update-contacts-notes", "delete-contacts-notes"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "merge", "activate", "get-favicon", "update-favicon", "trigger-favicon-backfill", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-contacts", "create-contacts", "get-contacts", "update-contacts", "delete-contacts", "list-contacts-notes", "create-contacts-notes", "get-contacts-notes", "update-contacts-notes", "delete-contacts-notes"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/business-partners', summary: 'Get all business partners with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/business-partners', summary: 'Create a new business partner', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['invoiceEmailCc', 'salesOrderRecipientCc', 'salesOrderRecipientBcc', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'contacts', 'tagIds', 'salesEarlyPaymentDiscounts', 'purchaseEarlyPaymentDiscounts', 'notes'] },
12
+ 'create': { method: 'POST', path: '/v1/business-partners', summary: 'Create a new business partner', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderRecipientCc', 'salesOrderRecipientBcc', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'deliveryNoteRecipientCc', 'deliveryNoteRecipientBcc', 'contacts', 'tagIds', 'tagCodes', 'salesEarlyPaymentDiscounts', 'purchaseEarlyPaymentDiscounts', 'notes'] },
13
13
  'get': { method: 'GET', path: '/v1/business-partners/{id}', summary: 'Get a business partner by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'update': { method: 'PATCH', path: '/v1/business-partners/{id}', summary: 'Update a business partner', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['invoiceEmailCc', 'salesOrderRecipientCc', 'salesOrderRecipientBcc', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'contacts', 'tagIds', 'salesEarlyPaymentDiscounts', 'purchaseEarlyPaymentDiscounts', 'notes'] },
14
+ 'update': { method: 'PATCH', path: '/v1/business-partners/{id}', summary: 'Update a business partner', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderRecipientCc', 'salesOrderRecipientBcc', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'deliveryNoteRecipientCc', 'deliveryNoteRecipientBcc', 'contacts', 'tagIds', 'tagCodes', 'salesEarlyPaymentDiscounts', 'purchaseEarlyPaymentDiscounts', 'notes'] },
15
15
  'delete': { method: 'DELETE', path: '/v1/business-partners/{id}', summary: 'Delete a business partner', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
16
  'merge': { method: 'POST', path: '/v1/business-partners/{id}/merge', summary: 'Merge a business partner into another', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
17
  'activate': { method: 'POST', path: '/v1/business-partners/{id}/activate', summary: 'Activate a business partner', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
18
+ 'get-favicon': { method: 'GET', path: '/v1/business-partners/{id}/favicon', summary: 'Download a business partner\'s stored favicon', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
+ 'update-favicon': { method: 'PUT', path: '/v1/business-partners/{id}/favicon', summary: 'Manually upload a business partner\'s favicon', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
+ 'trigger-favicon-backfill': { method: 'POST', path: '/v1/business-partners/favicon-backfill', summary: 'Fetch favicons for every business partner in this tenant that has none yet', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
18
21
  'list-notes': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/notes', summary: 'Get all notes for a business partner', pathParams: ['businessPartnerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
22
  'create-notes': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/notes', summary: 'Create a note for a business partner', pathParams: ['businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
23
  'get-notes': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/notes/{noteId}', summary: 'Get a specific note for a business partner', pathParams: ['businessPartnerId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
21
24
  'update-notes': { method: 'PATCH', path: '/v1/business-partners/{businessPartnerId}/notes/{noteId}', summary: 'Update a note for a business partner', pathParams: ['businessPartnerId', 'noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
22
25
  'delete-notes': { method: 'DELETE', path: '/v1/business-partners/{businessPartnerId}/notes/{noteId}', summary: 'Delete a note from a business partner', pathParams: ['businessPartnerId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
26
  'list-contacts': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/contacts', summary: 'Get all contacts for a business partner with pagination', pathParams: ['businessPartnerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
24
- 'create-contacts': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/contacts', summary: 'Create a new contact for a business partner', pathParams: ['businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['notes'] },
27
+ 'create-contacts': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/contacts', summary: 'Create a new contact for a business partner', pathParams: ['businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'tagCodes', 'notes'] },
25
28
  'get-contacts': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/contacts/{id}', summary: 'Get a contact by ID', pathParams: ['id', 'businessPartnerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
- 'update-contacts': { method: 'PATCH', path: '/v1/business-partners/{businessPartnerId}/contacts/{id}', summary: 'Update a contact', pathParams: ['id', 'businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['notes'] },
29
+ 'update-contacts': { method: 'PATCH', path: '/v1/business-partners/{businessPartnerId}/contacts/{id}', summary: 'Update a contact', pathParams: ['id', 'businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'tagCodes', 'notes'] },
27
30
  'delete-contacts': { method: 'DELETE', path: '/v1/business-partners/{businessPartnerId}/contacts/{id}', summary: 'Delete a contact', pathParams: ['id', 'businessPartnerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
31
  'list-contacts-notes': { method: 'GET', path: '/v1/business-partners/contacts/{contactId}/notes', summary: 'Get all notes for a contact', pathParams: ['contactId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
29
32
  'create-contacts-notes': { method: 'POST', path: '/v1/business-partners/contacts/{contactId}/notes', summary: 'Create a note for a contact', pathParams: ['contactId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -46,7 +49,7 @@ export default class BusinessPartners extends Command {
46
49
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
47
50
  };
48
51
  static flags = {
49
- context: Flags.string({ char: 'c', description: 'Context to use' }),
52
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
50
53
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
51
54
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
52
55
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -59,7 +62,7 @@ export default class BusinessPartners extends Command {
59
62
  limit: Flags.string({ description: 'Items per page' }),
60
63
  include: Flags.string({ description: 'Relations to include' }),
61
64
  search: Flags.string({ description: 'Search term' }),
62
- 'sort-by': Flags.string({ description: 'Sort field' }),
65
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
63
66
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
64
67
  query: Flags.string({ description: 'Additional query params as JSON' }),
65
68
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -120,9 +123,9 @@ export default class BusinessPartners extends Command {
120
123
  }
121
124
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
122
125
  if (!context)
123
- this.error('No context configured. Run: aderis auth login --new');
124
- if (!context.tokens)
125
- this.error('Not logged in. Run: aderis auth login');
126
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
127
+ if (!hasCredentials(context))
128
+ this.error(missingCredentialsMessage(context));
126
129
  const queryParams = {};
127
130
  if (flags.page)
128
131
  queryParams.page = flags.page;
@@ -133,7 +136,7 @@ export default class BusinessPartners extends Command {
133
136
  if (flags.search)
134
137
  queryParams.search = flags.search;
135
138
  if (flags['sort-by'])
136
- queryParams.sortBy = flags['sort-by'];
139
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
137
140
  if (flags.query) {
138
141
  try {
139
142
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -365,9 +368,9 @@ export default class BusinessPartners extends Command {
365
368
  async runImport(flags) {
366
369
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
367
370
  if (!context)
368
- this.error('No context configured. Run: aderis auth login --new');
369
- if (!context.tokens)
370
- this.error('Not logged in. Run: aderis auth login');
371
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
372
+ if (!hasCredentials(context))
373
+ this.error(missingCredentialsMessage(context));
371
374
  // Get data from file, --data, or --set flags
372
375
  let items = [];
373
376
  if (flags.file) {
@@ -577,9 +580,9 @@ export default class BusinessPartners extends Command {
577
580
  async runExport(flags) {
578
581
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
579
582
  if (!context)
580
- this.error('No context configured. Run: aderis auth login --new');
581
- if (!context.tokens)
582
- this.error('Not logged in. Run: aderis auth login');
583
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
584
+ if (!hasCredentials(context))
585
+ this.error(missingCredentialsMessage(context));
583
586
  const listEndpoint = ENDPOINTS['list'];
584
587
  if (!listEndpoint)
585
588
  this.error('Export requires a list endpoint');
@@ -592,7 +595,7 @@ export default class BusinessPartners extends Command {
592
595
  if (flags.search)
593
596
  baseParams.search = flags.search;
594
597
  if (flags['sort-by'])
595
- baseParams.sortBy = flags['sort-by'];
598
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
596
599
  if (flags.include)
597
600
  baseParams.include = flags.include;
598
601
  if (flags.query) {
@@ -671,9 +674,9 @@ export default class BusinessPartners extends Command {
671
674
  async runCamt053Import(flags) {
672
675
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
673
676
  if (!context)
674
- this.error('No context configured. Run: aderis auth login --new');
675
- if (!context.tokens)
676
- this.error('Not logged in. Run: aderis auth login');
677
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
678
+ if (!hasCredentials(context))
679
+ this.error(missingCredentialsMessage(context));
677
680
  if (!flags.file) {
678
681
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
679
682
  }
@@ -761,9 +764,9 @@ export default class BusinessPartners extends Command {
761
764
  }
762
765
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
763
766
  if (!context)
764
- this.error('No context configured. Run: aderis auth login --new');
765
- if (!context.tokens)
766
- this.error('Not logged in. Run: aderis auth login');
767
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
768
+ if (!hasCredentials(context))
769
+ this.error(missingCredentialsMessage(context));
767
770
  // Get data from file, --data, or --set flags
768
771
  let items = [];
769
772
  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 = false;
@@ -28,7 +28,7 @@ export default class Chat extends Command {
28
28
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
29
29
  };
30
30
  static flags = {
31
- context: Flags.string({ char: 'c', description: 'Context to use' }),
31
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
32
32
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
33
33
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
34
34
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -39,7 +39,7 @@ export default class Chat extends Command {
39
39
  limit: Flags.string({ description: 'Items per page' }),
40
40
  include: Flags.string({ description: 'Relations to include' }),
41
41
  search: Flags.string({ description: 'Search term' }),
42
- 'sort-by': Flags.string({ description: 'Sort field' }),
42
+ 'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
43
43
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
44
44
  query: Flags.string({ description: 'Additional query params as JSON' }),
45
45
  fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
@@ -100,9 +100,9 @@ export default class Chat extends Command {
100
100
  }
101
101
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
102
102
  if (!context)
103
- this.error('No context configured. Run: aderis auth login --new');
104
- if (!context.tokens)
105
- this.error('Not logged in. Run: aderis auth login');
103
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
104
+ if (!hasCredentials(context))
105
+ this.error(missingCredentialsMessage(context));
106
106
  const queryParams = {};
107
107
  if (flags.page)
108
108
  queryParams.page = flags.page;
@@ -113,7 +113,7 @@ export default class Chat extends Command {
113
113
  if (flags.search)
114
114
  queryParams.search = flags.search;
115
115
  if (flags['sort-by'])
116
- queryParams.sortBy = flags['sort-by'];
116
+ queryParams.sortBy = normalizeSortBy(flags['sort-by']);
117
117
  if (flags.query) {
118
118
  try {
119
119
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -345,9 +345,9 @@ export default class Chat extends Command {
345
345
  async runImport(flags) {
346
346
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
347
347
  if (!context)
348
- this.error('No context configured. Run: aderis auth login --new');
349
- if (!context.tokens)
350
- this.error('Not logged in. Run: aderis auth login');
348
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
349
+ if (!hasCredentials(context))
350
+ this.error(missingCredentialsMessage(context));
351
351
  // Get data from file, --data, or --set flags
352
352
  let items = [];
353
353
  if (flags.file) {
@@ -557,9 +557,9 @@ export default class Chat extends Command {
557
557
  async runExport(flags) {
558
558
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
559
559
  if (!context)
560
- this.error('No context configured. Run: aderis auth login --new');
561
- if (!context.tokens)
562
- this.error('Not logged in. Run: aderis auth login');
560
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
561
+ if (!hasCredentials(context))
562
+ this.error(missingCredentialsMessage(context));
563
563
  const listEndpoint = ENDPOINTS['list'];
564
564
  if (!listEndpoint)
565
565
  this.error('Export requires a list endpoint');
@@ -572,7 +572,7 @@ export default class Chat extends Command {
572
572
  if (flags.search)
573
573
  baseParams.search = flags.search;
574
574
  if (flags['sort-by'])
575
- baseParams.sortBy = flags['sort-by'];
575
+ baseParams.sortBy = normalizeSortBy(flags['sort-by']);
576
576
  if (flags.include)
577
577
  baseParams.include = flags.include;
578
578
  if (flags.query) {
@@ -651,9 +651,9 @@ export default class Chat extends Command {
651
651
  async runCamt053Import(flags) {
652
652
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
653
653
  if (!context)
654
- this.error('No context configured. Run: aderis auth login --new');
655
- if (!context.tokens)
656
- this.error('Not logged in. Run: aderis auth login');
654
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
655
+ if (!hasCredentials(context))
656
+ this.error(missingCredentialsMessage(context));
657
657
  if (!flags.file) {
658
658
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
659
659
  }
@@ -741,9 +741,9 @@ export default class Chat extends Command {
741
741
  }
742
742
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
743
743
  if (!context)
744
- this.error('No context configured. Run: aderis auth login --new');
745
- if (!context.tokens)
746
- this.error('Not logged in. Run: aderis auth login');
744
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
745
+ if (!hasCredentials(context))
746
+ this.error(missingCredentialsMessage(context));
747
747
  // Get data from file, --data, or --set flags
748
748
  let items = [];
749
749
  if (flags.file) {
@@ -3,6 +3,8 @@ export default class ConfigAdd extends Command {
3
3
  static description: string;
4
4
  static examples: string[];
5
5
  static flags: {
6
+ 'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ 'auth-type': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
8
  'client-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
9
  'client-secret': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
10
  environment: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -10,4 +12,11 @@ export default class ConfigAdd extends Command {
10
12
  name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
13
  };
12
14
  run(): Promise<void>;
15
+ /**
16
+ * Decide the auth type from flags, falling back to a prompt only when the
17
+ * invocation leaves it genuinely open. `--client-id`/`--client-secret` imply
18
+ * OAuth, and a non-TTY stdin means we must not block on a prompt — both keep
19
+ * scripted `config add` calls working exactly as before API-key support.
20
+ */
21
+ private resolveAuthType;
13
22
  }