@aderis-erp/cli 1.0.15 → 1.0.17

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 (163) hide show
  1. package/README.md +30 -8
  2. package/dist/commands/access-groups.d.ts +0 -1
  3. package/dist/commands/access-groups.js +5 -61
  4. package/dist/commands/account-transaction-allocations.d.ts +0 -1
  5. package/dist/commands/account-transaction-allocations.js +5 -61
  6. package/dist/commands/account-transactions.d.ts +0 -1
  7. package/dist/commands/account-transactions.js +9 -63
  8. package/dist/commands/accounts.d.ts +0 -1
  9. package/dist/commands/accounts.js +5 -61
  10. package/dist/commands/agent-platform.d.ts +0 -1
  11. package/dist/commands/agent-platform.js +5 -61
  12. package/dist/commands/analytics.d.ts +0 -1
  13. package/dist/commands/analytics.js +5 -61
  14. package/dist/commands/api-keys.d.ts +39 -0
  15. package/dist/commands/api-keys.js +1117 -0
  16. package/dist/commands/audit-log.d.ts +0 -1
  17. package/dist/commands/audit-log.js +5 -61
  18. package/dist/commands/auth/login.d.ts +9 -0
  19. package/dist/commands/auth/login.js +73 -20
  20. package/dist/commands/auth/logout.d.ts +4 -0
  21. package/dist/commands/auth/logout.js +4 -0
  22. package/dist/commands/auth/status.js +26 -17
  23. package/dist/commands/auth/tenant.js +3 -6
  24. package/dist/commands/auth.d.ts +0 -1
  25. package/dist/commands/auth.js +5 -34
  26. package/dist/commands/bank-accounts.d.ts +0 -1
  27. package/dist/commands/bank-accounts.js +5 -61
  28. package/dist/commands/bank-integrations.d.ts +0 -1
  29. package/dist/commands/bank-integrations.js +5 -61
  30. package/dist/commands/business-partners.d.ts +1 -1
  31. package/dist/commands/business-partners.js +14 -63
  32. package/dist/commands/chat.d.ts +0 -1
  33. package/dist/commands/chat.js +5 -61
  34. package/dist/commands/config/add.d.ts +3 -0
  35. package/dist/commands/config/add.js +34 -16
  36. package/dist/commands/config/current.js +3 -0
  37. package/dist/commands/config/list.js +3 -0
  38. package/dist/commands/credit-card-accounts.d.ts +0 -1
  39. package/dist/commands/credit-card-accounts.js +5 -61
  40. package/dist/commands/delivery-notes.d.ts +0 -1
  41. package/dist/commands/delivery-notes.js +7 -63
  42. package/dist/commands/dunning-configs.d.ts +0 -1
  43. package/dist/commands/dunning-configs.js +5 -61
  44. package/dist/commands/dunning-reminders.d.ts +0 -1
  45. package/dist/commands/dunning-reminders.js +5 -61
  46. package/dist/commands/dunning-runs.d.ts +0 -1
  47. package/dist/commands/dunning-runs.js +5 -61
  48. package/dist/commands/email-transactions.d.ts +0 -1
  49. package/dist/commands/email-transactions.js +5 -61
  50. package/dist/commands/employees.d.ts +0 -1
  51. package/dist/commands/employees.js +5 -61
  52. package/dist/commands/entity-configurations.d.ts +0 -1
  53. package/dist/commands/entity-configurations.js +5 -61
  54. package/dist/commands/event-processor-mappings.d.ts +0 -1
  55. package/dist/commands/event-processor-mappings.js +5 -61
  56. package/dist/commands/files.d.ts +0 -1
  57. package/dist/commands/files.js +5 -61
  58. package/dist/commands/health.d.ts +0 -1
  59. package/dist/commands/health.js +5 -61
  60. package/dist/commands/inbox.d.ts +0 -1
  61. package/dist/commands/inbox.js +5 -61
  62. package/dist/commands/integrations.d.ts +0 -1
  63. package/dist/commands/integrations.js +5 -61
  64. package/dist/commands/item-categories.d.ts +0 -1
  65. package/dist/commands/item-categories.js +5 -61
  66. package/dist/commands/items.d.ts +0 -1
  67. package/dist/commands/items.js +5 -61
  68. package/dist/commands/journal-lines.d.ts +0 -1
  69. package/dist/commands/journal-lines.js +5 -61
  70. package/dist/commands/journals.d.ts +1 -1
  71. package/dist/commands/journals.js +9 -62
  72. package/dist/commands/ledgers.d.ts +0 -1
  73. package/dist/commands/ledgers.js +5 -61
  74. package/dist/commands/nango-integrations.d.ts +39 -0
  75. package/dist/commands/nango-integrations.js +1115 -0
  76. package/dist/commands/office-locations.d.ts +0 -1
  77. package/dist/commands/office-locations.js +5 -61
  78. package/dist/commands/payment-methods.d.ts +0 -1
  79. package/dist/commands/payment-methods.js +5 -61
  80. package/dist/commands/payment-runs.d.ts +0 -1
  81. package/dist/commands/payment-runs.js +5 -61
  82. package/dist/commands/payment-terms.d.ts +0 -1
  83. package/dist/commands/payment-terms.js +5 -61
  84. package/dist/commands/payments.d.ts +0 -1
  85. package/dist/commands/payments.js +5 -61
  86. package/dist/commands/price-lists.d.ts +0 -1
  87. package/dist/commands/price-lists.js +5 -61
  88. package/dist/commands/processor-mappings.d.ts +0 -1
  89. package/dist/commands/processor-mappings.js +5 -61
  90. package/dist/commands/processors.d.ts +0 -1
  91. package/dist/commands/processors.js +5 -61
  92. package/dist/commands/purchase-order-types.d.ts +0 -1
  93. package/dist/commands/purchase-order-types.js +5 -61
  94. package/dist/commands/purchase-orders.d.ts +0 -1
  95. package/dist/commands/purchase-orders.js +7 -63
  96. package/dist/commands/reports.d.ts +0 -1
  97. package/dist/commands/reports.js +6 -62
  98. package/dist/commands/salary-types.d.ts +0 -1
  99. package/dist/commands/salary-types.js +5 -61
  100. package/dist/commands/sales-invoices.d.ts +0 -1
  101. package/dist/commands/sales-invoices.js +12 -65
  102. package/dist/commands/sales-orders.d.ts +0 -1
  103. package/dist/commands/sales-orders.js +7 -63
  104. package/dist/commands/saved-views.d.ts +0 -1
  105. package/dist/commands/saved-views.js +5 -61
  106. package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
  107. package/dist/commands/scheduled-processor-mappings.js +5 -61
  108. package/dist/commands/schedules.d.ts +0 -1
  109. package/dist/commands/schedules.js +5 -61
  110. package/dist/commands/switch.js +4 -4
  111. package/dist/commands/tag-configurations.d.ts +0 -1
  112. package/dist/commands/tag-configurations.js +9 -64
  113. package/dist/commands/tags.d.ts +0 -1
  114. package/dist/commands/tags.js +5 -61
  115. package/dist/commands/tax-codes.d.ts +0 -1
  116. package/dist/commands/tax-codes.js +5 -61
  117. package/dist/commands/tax-matrix.d.ts +0 -1
  118. package/dist/commands/tax-matrix.js +5 -61
  119. package/dist/commands/tenants.d.ts +0 -1
  120. package/dist/commands/tenants.js +7 -62
  121. package/dist/commands/text-templates.d.ts +0 -1
  122. package/dist/commands/text-templates.js +5 -61
  123. package/dist/commands/tools.d.ts +0 -1
  124. package/dist/commands/tools.js +5 -61
  125. package/dist/commands/vat-declarations.d.ts +1 -1
  126. package/dist/commands/vat-declarations.js +11 -62
  127. package/dist/commands/vendor-invoices.d.ts +0 -1
  128. package/dist/commands/vendor-invoices.js +10 -65
  129. package/dist/commands/webhooks.d.ts +0 -1
  130. package/dist/commands/webhooks.js +5 -61
  131. package/dist/commands/workflows.d.ts +0 -1
  132. package/dist/commands/workflows.js +5 -61
  133. package/dist/lib/api-client.js +3 -6
  134. package/dist/lib/auth/constants.d.ts +11 -0
  135. package/dist/lib/auth/constants.js +11 -0
  136. package/dist/lib/auth/errors.d.ts +17 -0
  137. package/dist/lib/auth/errors.js +22 -0
  138. package/dist/lib/auth/flow.d.ts +27 -0
  139. package/dist/lib/auth/flow.js +163 -0
  140. package/dist/lib/auth/guards.d.ts +5 -0
  141. package/dist/lib/auth/guards.js +14 -0
  142. package/dist/lib/auth/http.d.ts +16 -0
  143. package/dist/lib/auth/http.js +49 -0
  144. package/dist/lib/auth/index.d.ts +49 -0
  145. package/dist/lib/auth/index.js +217 -0
  146. package/dist/lib/auth/keycloak-provider.d.ts +75 -0
  147. package/dist/lib/auth/keycloak-provider.js +215 -0
  148. package/dist/lib/auth/pages.d.ts +25 -0
  149. package/dist/lib/auth/pages.js +123 -0
  150. package/dist/lib/auth/pkce.d.ts +11 -0
  151. package/dist/lib/auth/pkce.js +17 -0
  152. package/dist/lib/auth/tokens.d.ts +54 -0
  153. package/dist/lib/auth/tokens.js +104 -0
  154. package/dist/lib/auth/types.d.ts +57 -0
  155. package/dist/lib/auth/types.js +1 -0
  156. package/dist/lib/auth/validated-url.d.ts +6 -0
  157. package/dist/lib/auth/validated-url.js +53 -0
  158. package/dist/lib/config.d.ts +13 -3
  159. package/dist/lib/config.js +24 -19
  160. package/oclif.manifest.json +440 -71
  161. package/package.json +2 -1
  162. package/dist/lib/auth.d.ts +0 -43
  163. package/dist/lib/auth.js +0 -610
@@ -31,7 +31,6 @@ export default class ScheduledProcessorMappings extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;
@@ -43,7 +43,7 @@ export default class ScheduledProcessorMappings extends Command {
43
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
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
46
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
47
47
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
48
48
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
49
49
  };
@@ -115,6 +115,8 @@ export default class ScheduledProcessorMappings extends Command {
115
115
  queryParams.search = flags.search;
116
116
  if (flags['sort-by'])
117
117
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
118
+ if (flags.fields)
119
+ queryParams.fields = flags.fields;
118
120
  if (flags.query) {
119
121
  try {
120
122
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -317,11 +319,6 @@ export default class ScheduledProcessorMappings extends Command {
317
319
  output = obj[arrayKeys[0]];
318
320
  }
319
321
  }
320
- // Filter fields if --fields flag is provided
321
- if (flags.fields) {
322
- const fieldList = flags.fields.split(',').map(f => f.trim());
323
- output = this.filterFields(output, fieldList);
324
- }
325
322
  // Sanitize output if requested
326
323
  if (flags.sanitize) {
327
324
  output = this.sanitizeOutput(output);
@@ -576,6 +573,8 @@ export default class ScheduledProcessorMappings extends Command {
576
573
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
577
574
  if (flags.include)
578
575
  baseParams.include = flags.include;
576
+ if (flags.fields)
577
+ baseParams.fields = flags.fields;
579
578
  if (flags.query) {
580
579
  try {
581
580
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -630,12 +629,7 @@ export default class ScheduledProcessorMappings extends Command {
630
629
  }
631
630
  }
632
631
  process.stderr.write(' done\n');
633
- // Filter fields if specified
634
632
  let output = allItems;
635
- if (flags.fields) {
636
- const fieldList = flags.fields.split(',').map(f => f.trim());
637
- output = this.filterFields(allItems, fieldList);
638
- }
639
633
  // Sanitize output if requested
640
634
  if (flags.sanitize) {
641
635
  output = this.sanitizeOutput(output);
@@ -964,56 +958,6 @@ export default class ScheduledProcessorMappings extends Command {
964
958
  return `\$${op}`;
965
959
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
966
960
  }
967
- filterFields(data, fields) {
968
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
969
- const pick = (obj, keys) => {
970
- // Group keys by their first segment so sibling sub-paths
971
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
972
- // and don't clobber each other on merge.
973
- const directKeys = new Set();
974
- const nestedKeys = new Map();
975
- for (const key of keys) {
976
- if (key.split('.').some(isUnsafeKey))
977
- continue;
978
- if (key.includes('.')) {
979
- const [first, ...rest] = key.split('.');
980
- if (isUnsafeKey(first))
981
- continue;
982
- const list = nestedKeys.get(first);
983
- if (list) {
984
- list.push(rest.join('.'));
985
- }
986
- else {
987
- nestedKeys.set(first, [rest.join('.')]);
988
- }
989
- }
990
- else {
991
- directKeys.add(key);
992
- }
993
- }
994
- const result = {};
995
- for (const key of directKeys) {
996
- if (key in obj)
997
- result[key] = obj[key];
998
- }
999
- for (const [first, restKeys] of nestedKeys) {
1000
- const val = obj[first];
1001
- if (!val || typeof val !== 'object')
1002
- continue;
1003
- if (Array.isArray(val)) {
1004
- result[first] = val.map(item => pick(item, restKeys));
1005
- }
1006
- else {
1007
- result[first] = pick(val, restKeys);
1008
- }
1009
- }
1010
- return result;
1011
- };
1012
- if (Array.isArray(data)) {
1013
- return data.map(item => pick(item, fields));
1014
- }
1015
- return pick(data, fields);
1016
- }
1017
961
  sanitizeOutput(data) {
1018
962
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1019
963
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -31,7 +31,6 @@ export default class Schedules extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;
@@ -47,7 +47,7 @@ export default class Schedules extends Command {
47
47
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
48
48
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
49
49
  query: Flags.string({ description: 'Additional query params as JSON' }),
50
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
50
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
51
51
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
52
52
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
53
53
  };
@@ -119,6 +119,8 @@ export default class Schedules extends Command {
119
119
  queryParams.search = flags.search;
120
120
  if (flags['sort-by'])
121
121
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
122
+ if (flags.fields)
123
+ queryParams.fields = flags.fields;
122
124
  if (flags.query) {
123
125
  try {
124
126
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -321,11 +323,6 @@ export default class Schedules extends Command {
321
323
  output = obj[arrayKeys[0]];
322
324
  }
323
325
  }
324
- // Filter fields if --fields flag is provided
325
- if (flags.fields) {
326
- const fieldList = flags.fields.split(',').map(f => f.trim());
327
- output = this.filterFields(output, fieldList);
328
- }
329
326
  // Sanitize output if requested
330
327
  if (flags.sanitize) {
331
328
  output = this.sanitizeOutput(output);
@@ -580,6 +577,8 @@ export default class Schedules extends Command {
580
577
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
581
578
  if (flags.include)
582
579
  baseParams.include = flags.include;
580
+ if (flags.fields)
581
+ baseParams.fields = flags.fields;
583
582
  if (flags.query) {
584
583
  try {
585
584
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -634,12 +633,7 @@ export default class Schedules extends Command {
634
633
  }
635
634
  }
636
635
  process.stderr.write(' done\n');
637
- // Filter fields if specified
638
636
  let output = allItems;
639
- if (flags.fields) {
640
- const fieldList = flags.fields.split(',').map(f => f.trim());
641
- output = this.filterFields(allItems, fieldList);
642
- }
643
637
  // Sanitize output if requested
644
638
  if (flags.sanitize) {
645
639
  output = this.sanitizeOutput(output);
@@ -968,56 +962,6 @@ export default class Schedules extends Command {
968
962
  return `\$${op}`;
969
963
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
970
964
  }
971
- filterFields(data, fields) {
972
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
973
- const pick = (obj, keys) => {
974
- // Group keys by their first segment so sibling sub-paths
975
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
976
- // and don't clobber each other on merge.
977
- const directKeys = new Set();
978
- const nestedKeys = new Map();
979
- for (const key of keys) {
980
- if (key.split('.').some(isUnsafeKey))
981
- continue;
982
- if (key.includes('.')) {
983
- const [first, ...rest] = key.split('.');
984
- if (isUnsafeKey(first))
985
- continue;
986
- const list = nestedKeys.get(first);
987
- if (list) {
988
- list.push(rest.join('.'));
989
- }
990
- else {
991
- nestedKeys.set(first, [rest.join('.')]);
992
- }
993
- }
994
- else {
995
- directKeys.add(key);
996
- }
997
- }
998
- const result = {};
999
- for (const key of directKeys) {
1000
- if (key in obj)
1001
- result[key] = obj[key];
1002
- }
1003
- for (const [first, restKeys] of nestedKeys) {
1004
- const val = obj[first];
1005
- if (!val || typeof val !== 'object')
1006
- continue;
1007
- if (Array.isArray(val)) {
1008
- result[first] = val.map(item => pick(item, restKeys));
1009
- }
1010
- else {
1011
- result[first] = pick(val, restKeys);
1012
- }
1013
- }
1014
- return result;
1015
- };
1016
- if (Array.isArray(data)) {
1017
- return data.map(item => pick(item, fields));
1018
- }
1019
- return pick(data, fields);
1020
- }
1021
965
  sanitizeOutput(data) {
1022
966
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1023
967
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -1,6 +1,6 @@
1
1
  import { confirm, select } from '@inquirer/prompts';
2
2
  import { Command } from '@oclif/core';
3
- import { loginAndSwitchTenant } from '../lib/auth.js';
3
+ import { loginAndSwitchTenant, tenantLabel } from '../lib/auth/index.js';
4
4
  import { getAuthType, getContext, getCurrentContext, hasCredentials, listContexts, setCurrentContext, } from '../lib/config.js';
5
5
  export default class Switch extends Command {
6
6
  static description = 'Switch context and tenant interactively';
@@ -62,8 +62,8 @@ export default class Switch extends Command {
62
62
  if (!shouldLogin)
63
63
  return;
64
64
  // If we have a cached tenant list from a previous session, let the user pick
65
- // tenant FIRST. Then run the combined login + tenant-switch flow which uses
66
- // a single browser tab (chained PKCE rounds with a meta-refresh redirect).
65
+ // tenant FIRST. Then run the combined login + tenant-switch flow, which
66
+ // uses a single browser tab.
67
67
  const ctx = getContext(selectedContext);
68
68
  const cached = ctx?.cachedTenants ?? [];
69
69
  if (cached.length > 1) {
@@ -76,7 +76,7 @@ export default class Switch extends Command {
76
76
  });
77
77
  const selectedTenant = await select({
78
78
  choices: sorted.map((t) => ({
79
- name: t.tenantId === ctx?.tenant_id ? `${t.name} (previous)` : t.name,
79
+ name: t.tenantId === ctx?.tenant_id ? `${tenantLabel(t)} (previous)` : tenantLabel(t),
80
80
  value: t.tenantId,
81
81
  })),
82
82
  message: 'Select a tenant:',
@@ -31,7 +31,6 @@ export default class TagConfigurations extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;
@@ -6,13 +6,14 @@ const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
7
7
  const HAS_CAMT053 = false;
8
8
  const NESTED_IMPORTS = [];
9
- const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "journal-coverage"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/tag-configurations', summary: 'Get all tag configurations with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/tag-configurations', summary: 'Create a new tag configuration', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'tagIds', 'tagCodes'] },
12
+ 'create': { method: 'POST', path: '/v1/tag-configurations', summary: 'Create a new tag configuration', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'accountTypes', 'tagIds', 'tagCodes'] },
13
13
  'get': { method: 'GET', path: '/v1/tag-configurations/{id}', summary: 'Get a tag configuration by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'update': { method: 'PATCH', path: '/v1/tag-configurations/{id}', summary: 'Update a tag configuration', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'tagIds', 'tagCodes'] },
14
+ 'update': { method: 'PATCH', path: '/v1/tag-configurations/{id}', summary: 'Update a tag configuration', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['resourceTypes', 'accountTypes', 'tagIds', 'tagCodes'] },
15
15
  'delete': { method: 'DELETE', path: '/v1/tag-configurations/{id}', summary: 'Delete a tag configuration', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
+ 'journal-coverage': { method: 'GET', path: '/v1/tag-configurations/{id}/journal-coverage', summary: 'How much of the journal-line amount in scope carries one of this configuration\'s tags', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
17
  };
17
18
  export default class TagConfigurations extends Command {
18
19
  static description = 'Manage tag configurations';
@@ -43,7 +44,7 @@ export default class TagConfigurations extends Command {
43
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.' }),
44
45
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
45
46
  query: Flags.string({ description: 'Additional query params as JSON' }),
46
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
47
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
47
48
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
48
49
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
49
50
  };
@@ -115,6 +116,8 @@ export default class TagConfigurations extends Command {
115
116
  queryParams.search = flags.search;
116
117
  if (flags['sort-by'])
117
118
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
119
+ if (flags.fields)
120
+ queryParams.fields = flags.fields;
118
121
  if (flags.query) {
119
122
  try {
120
123
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -317,11 +320,6 @@ export default class TagConfigurations extends Command {
317
320
  output = obj[arrayKeys[0]];
318
321
  }
319
322
  }
320
- // Filter fields if --fields flag is provided
321
- if (flags.fields) {
322
- const fieldList = flags.fields.split(',').map(f => f.trim());
323
- output = this.filterFields(output, fieldList);
324
- }
325
323
  // Sanitize output if requested
326
324
  if (flags.sanitize) {
327
325
  output = this.sanitizeOutput(output);
@@ -576,6 +574,8 @@ export default class TagConfigurations extends Command {
576
574
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
577
575
  if (flags.include)
578
576
  baseParams.include = flags.include;
577
+ if (flags.fields)
578
+ baseParams.fields = flags.fields;
579
579
  if (flags.query) {
580
580
  try {
581
581
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -630,12 +630,7 @@ export default class TagConfigurations extends Command {
630
630
  }
631
631
  }
632
632
  process.stderr.write(' done\n');
633
- // Filter fields if specified
634
633
  let output = allItems;
635
- if (flags.fields) {
636
- const fieldList = flags.fields.split(',').map(f => f.trim());
637
- output = this.filterFields(allItems, fieldList);
638
- }
639
634
  // Sanitize output if requested
640
635
  if (flags.sanitize) {
641
636
  output = this.sanitizeOutput(output);
@@ -964,56 +959,6 @@ export default class TagConfigurations extends Command {
964
959
  return `\$${op}`;
965
960
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
966
961
  }
967
- filterFields(data, fields) {
968
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
969
- const pick = (obj, keys) => {
970
- // Group keys by their first segment so sibling sub-paths
971
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
972
- // and don't clobber each other on merge.
973
- const directKeys = new Set();
974
- const nestedKeys = new Map();
975
- for (const key of keys) {
976
- if (key.split('.').some(isUnsafeKey))
977
- continue;
978
- if (key.includes('.')) {
979
- const [first, ...rest] = key.split('.');
980
- if (isUnsafeKey(first))
981
- continue;
982
- const list = nestedKeys.get(first);
983
- if (list) {
984
- list.push(rest.join('.'));
985
- }
986
- else {
987
- nestedKeys.set(first, [rest.join('.')]);
988
- }
989
- }
990
- else {
991
- directKeys.add(key);
992
- }
993
- }
994
- const result = {};
995
- for (const key of directKeys) {
996
- if (key in obj)
997
- result[key] = obj[key];
998
- }
999
- for (const [first, restKeys] of nestedKeys) {
1000
- const val = obj[first];
1001
- if (!val || typeof val !== 'object')
1002
- continue;
1003
- if (Array.isArray(val)) {
1004
- result[first] = val.map(item => pick(item, restKeys));
1005
- }
1006
- else {
1007
- result[first] = pick(val, restKeys);
1008
- }
1009
- }
1010
- return result;
1011
- };
1012
- if (Array.isArray(data)) {
1013
- return data.map(item => pick(item, fields));
1014
- }
1015
- return pick(data, fields);
1016
- }
1017
962
  sanitizeOutput(data) {
1018
963
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1019
964
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -31,7 +31,6 @@ export default class Tags extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;
@@ -43,7 +43,7 @@ export default class Tags extends Command {
43
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
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
46
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
47
47
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
48
48
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
49
49
  };
@@ -115,6 +115,8 @@ export default class Tags extends Command {
115
115
  queryParams.search = flags.search;
116
116
  if (flags['sort-by'])
117
117
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
118
+ if (flags.fields)
119
+ queryParams.fields = flags.fields;
118
120
  if (flags.query) {
119
121
  try {
120
122
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -317,11 +319,6 @@ export default class Tags extends Command {
317
319
  output = obj[arrayKeys[0]];
318
320
  }
319
321
  }
320
- // Filter fields if --fields flag is provided
321
- if (flags.fields) {
322
- const fieldList = flags.fields.split(',').map(f => f.trim());
323
- output = this.filterFields(output, fieldList);
324
- }
325
322
  // Sanitize output if requested
326
323
  if (flags.sanitize) {
327
324
  output = this.sanitizeOutput(output);
@@ -576,6 +573,8 @@ export default class Tags extends Command {
576
573
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
577
574
  if (flags.include)
578
575
  baseParams.include = flags.include;
576
+ if (flags.fields)
577
+ baseParams.fields = flags.fields;
579
578
  if (flags.query) {
580
579
  try {
581
580
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -630,12 +629,7 @@ export default class Tags extends Command {
630
629
  }
631
630
  }
632
631
  process.stderr.write(' done\n');
633
- // Filter fields if specified
634
632
  let output = allItems;
635
- if (flags.fields) {
636
- const fieldList = flags.fields.split(',').map(f => f.trim());
637
- output = this.filterFields(allItems, fieldList);
638
- }
639
633
  // Sanitize output if requested
640
634
  if (flags.sanitize) {
641
635
  output = this.sanitizeOutput(output);
@@ -964,56 +958,6 @@ export default class Tags extends Command {
964
958
  return `\$${op}`;
965
959
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
966
960
  }
967
- filterFields(data, fields) {
968
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
969
- const pick = (obj, keys) => {
970
- // Group keys by their first segment so sibling sub-paths
971
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
972
- // and don't clobber each other on merge.
973
- const directKeys = new Set();
974
- const nestedKeys = new Map();
975
- for (const key of keys) {
976
- if (key.split('.').some(isUnsafeKey))
977
- continue;
978
- if (key.includes('.')) {
979
- const [first, ...rest] = key.split('.');
980
- if (isUnsafeKey(first))
981
- continue;
982
- const list = nestedKeys.get(first);
983
- if (list) {
984
- list.push(rest.join('.'));
985
- }
986
- else {
987
- nestedKeys.set(first, [rest.join('.')]);
988
- }
989
- }
990
- else {
991
- directKeys.add(key);
992
- }
993
- }
994
- const result = {};
995
- for (const key of directKeys) {
996
- if (key in obj)
997
- result[key] = obj[key];
998
- }
999
- for (const [first, restKeys] of nestedKeys) {
1000
- const val = obj[first];
1001
- if (!val || typeof val !== 'object')
1002
- continue;
1003
- if (Array.isArray(val)) {
1004
- result[first] = val.map(item => pick(item, restKeys));
1005
- }
1006
- else {
1007
- result[first] = pick(val, restKeys);
1008
- }
1009
- }
1010
- return result;
1011
- };
1012
- if (Array.isArray(data)) {
1013
- return data.map(item => pick(item, fields));
1014
- }
1015
- return pick(data, fields);
1016
- }
1017
961
  sanitizeOutput(data) {
1018
962
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1019
963
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -31,7 +31,6 @@ export default class TaxCodes extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;
@@ -46,7 +46,7 @@ export default class TaxCodes extends Command {
46
46
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
47
47
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
48
48
  query: Flags.string({ description: 'Additional query params as JSON' }),
49
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
49
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
50
50
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
51
51
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
52
52
  };
@@ -118,6 +118,8 @@ export default class TaxCodes extends Command {
118
118
  queryParams.search = flags.search;
119
119
  if (flags['sort-by'])
120
120
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
121
+ if (flags.fields)
122
+ queryParams.fields = flags.fields;
121
123
  if (flags.query) {
122
124
  try {
123
125
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -320,11 +322,6 @@ export default class TaxCodes extends Command {
320
322
  output = obj[arrayKeys[0]];
321
323
  }
322
324
  }
323
- // Filter fields if --fields flag is provided
324
- if (flags.fields) {
325
- const fieldList = flags.fields.split(',').map(f => f.trim());
326
- output = this.filterFields(output, fieldList);
327
- }
328
325
  // Sanitize output if requested
329
326
  if (flags.sanitize) {
330
327
  output = this.sanitizeOutput(output);
@@ -579,6 +576,8 @@ export default class TaxCodes extends Command {
579
576
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
580
577
  if (flags.include)
581
578
  baseParams.include = flags.include;
579
+ if (flags.fields)
580
+ baseParams.fields = flags.fields;
582
581
  if (flags.query) {
583
582
  try {
584
583
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -633,12 +632,7 @@ export default class TaxCodes extends Command {
633
632
  }
634
633
  }
635
634
  process.stderr.write(' done\n');
636
- // Filter fields if specified
637
635
  let output = allItems;
638
- if (flags.fields) {
639
- const fieldList = flags.fields.split(',').map(f => f.trim());
640
- output = this.filterFields(allItems, fieldList);
641
- }
642
636
  // Sanitize output if requested
643
637
  if (flags.sanitize) {
644
638
  output = this.sanitizeOutput(output);
@@ -967,56 +961,6 @@ export default class TaxCodes extends Command {
967
961
  return `\$${op}`;
968
962
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
969
963
  }
970
- filterFields(data, fields) {
971
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
972
- const pick = (obj, keys) => {
973
- // Group keys by their first segment so sibling sub-paths
974
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
975
- // and don't clobber each other on merge.
976
- const directKeys = new Set();
977
- const nestedKeys = new Map();
978
- for (const key of keys) {
979
- if (key.split('.').some(isUnsafeKey))
980
- continue;
981
- if (key.includes('.')) {
982
- const [first, ...rest] = key.split('.');
983
- if (isUnsafeKey(first))
984
- continue;
985
- const list = nestedKeys.get(first);
986
- if (list) {
987
- list.push(rest.join('.'));
988
- }
989
- else {
990
- nestedKeys.set(first, [rest.join('.')]);
991
- }
992
- }
993
- else {
994
- directKeys.add(key);
995
- }
996
- }
997
- const result = {};
998
- for (const key of directKeys) {
999
- if (key in obj)
1000
- result[key] = obj[key];
1001
- }
1002
- for (const [first, restKeys] of nestedKeys) {
1003
- const val = obj[first];
1004
- if (!val || typeof val !== 'object')
1005
- continue;
1006
- if (Array.isArray(val)) {
1007
- result[first] = val.map(item => pick(item, restKeys));
1008
- }
1009
- else {
1010
- result[first] = pick(val, restKeys);
1011
- }
1012
- }
1013
- return result;
1014
- };
1015
- if (Array.isArray(data)) {
1016
- return data.map(item => pick(item, fields));
1017
- }
1018
- return pick(data, fields);
1019
- }
1020
964
  sanitizeOutput(data) {
1021
965
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1022
966
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -31,7 +31,6 @@ export default class TaxMatrix extends Command {
31
31
  private runCamt053Import;
32
32
  private runNestedImport;
33
33
  private parseFilterValue;
34
- private filterFields;
35
34
  private sanitizeOutput;
36
35
  private getColumns;
37
36
  private getValue;