@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
@@ -55,7 +55,7 @@ export default class CreditCardAccounts extends Command {
55
55
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
56
56
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
57
57
  query: Flags.string({ description: 'Additional query params as JSON' }),
58
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
58
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
59
59
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
60
60
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
61
61
  };
@@ -127,6 +127,8 @@ export default class CreditCardAccounts extends Command {
127
127
  queryParams.search = flags.search;
128
128
  if (flags['sort-by'])
129
129
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
130
+ if (flags.fields)
131
+ queryParams.fields = flags.fields;
130
132
  if (flags.query) {
131
133
  try {
132
134
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -329,11 +331,6 @@ export default class CreditCardAccounts extends Command {
329
331
  output = obj[arrayKeys[0]];
330
332
  }
331
333
  }
332
- // Filter fields if --fields flag is provided
333
- if (flags.fields) {
334
- const fieldList = flags.fields.split(',').map(f => f.trim());
335
- output = this.filterFields(output, fieldList);
336
- }
337
334
  // Sanitize output if requested
338
335
  if (flags.sanitize) {
339
336
  output = this.sanitizeOutput(output);
@@ -588,6 +585,8 @@ export default class CreditCardAccounts extends Command {
588
585
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
589
586
  if (flags.include)
590
587
  baseParams.include = flags.include;
588
+ if (flags.fields)
589
+ baseParams.fields = flags.fields;
591
590
  if (flags.query) {
592
591
  try {
593
592
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -642,12 +641,7 @@ export default class CreditCardAccounts extends Command {
642
641
  }
643
642
  }
644
643
  process.stderr.write(' done\n');
645
- // Filter fields if specified
646
644
  let output = allItems;
647
- if (flags.fields) {
648
- const fieldList = flags.fields.split(',').map(f => f.trim());
649
- output = this.filterFields(allItems, fieldList);
650
- }
651
645
  // Sanitize output if requested
652
646
  if (flags.sanitize) {
653
647
  output = this.sanitizeOutput(output);
@@ -976,56 +970,6 @@ export default class CreditCardAccounts extends Command {
976
970
  return `\$${op}`;
977
971
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
978
972
  }
979
- filterFields(data, fields) {
980
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
981
- const pick = (obj, keys) => {
982
- // Group keys by their first segment so sibling sub-paths
983
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
984
- // and don't clobber each other on merge.
985
- const directKeys = new Set();
986
- const nestedKeys = new Map();
987
- for (const key of keys) {
988
- if (key.split('.').some(isUnsafeKey))
989
- continue;
990
- if (key.includes('.')) {
991
- const [first, ...rest] = key.split('.');
992
- if (isUnsafeKey(first))
993
- continue;
994
- const list = nestedKeys.get(first);
995
- if (list) {
996
- list.push(rest.join('.'));
997
- }
998
- else {
999
- nestedKeys.set(first, [rest.join('.')]);
1000
- }
1001
- }
1002
- else {
1003
- directKeys.add(key);
1004
- }
1005
- }
1006
- const result = {};
1007
- for (const key of directKeys) {
1008
- if (key in obj)
1009
- result[key] = obj[key];
1010
- }
1011
- for (const [first, restKeys] of nestedKeys) {
1012
- const val = obj[first];
1013
- if (!val || typeof val !== 'object')
1014
- continue;
1015
- if (Array.isArray(val)) {
1016
- result[first] = val.map(item => pick(item, restKeys));
1017
- }
1018
- else {
1019
- result[first] = pick(val, restKeys);
1020
- }
1021
- }
1022
- return result;
1023
- };
1024
- if (Array.isArray(data)) {
1025
- return data.map(item => pick(item, fields));
1026
- }
1027
- return pick(data, fields);
1028
- }
1029
973
  sanitizeOutput(data) {
1030
974
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1031
975
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -34,7 +34,6 @@ export default class DeliveryNotes extends Command {
34
34
  private runCamt053Import;
35
35
  private runNestedImport;
36
36
  private parseFilterValue;
37
- private filterFields;
38
37
  private sanitizeOutput;
39
38
  private getColumns;
40
39
  private getValue;
@@ -24,9 +24,9 @@ const ENDPOINTS = {
24
24
  'deliver': { method: 'POST', path: '/v1/delivery-notes/{id}/deliver', summary: 'Mark a delivery note as delivered (SHIPPED → DELIVERED)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
25
  'ship': { method: 'POST', path: '/v1/delivery-notes/{id}/ship', summary: 'Ship a delivery note (APPROVED → SHIPPED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lineItems'] },
26
26
  'send': { method: 'POST', path: '/v1/delivery-notes/{id}/send', summary: 'Send a delivery note to its recipient by email', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['emailCc', 'emailBcc'] },
27
- 'create-line-items': { method: 'POST', path: '/v1/delivery-notes/{noteId}/line-items', summary: 'Add a line item to a delivery note', pathParams: ['noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderLineItems'] },
27
+ 'create-line-items': { method: 'POST', path: '/v1/delivery-notes/{noteId}/line-items', summary: 'Add a line item to a delivery note', pathParams: ['noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderLineItems', 'tagIds', 'tagCodes'] },
28
28
  'update-line-items-reorder': { method: 'PATCH', path: '/v1/delivery-notes/{noteId}/line-items/reorder', summary: 'Bulk reorder line items (drag-and-drop)', pathParams: ['noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['items'] },
29
- 'update-line-items': { method: 'PATCH', path: '/v1/delivery-notes/{noteId}/line-items/{lineItemId}', summary: 'Update a line item on a delivery note', pathParams: ['noteId', 'lineItemId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderLineItems'] },
29
+ 'update-line-items': { method: 'PATCH', path: '/v1/delivery-notes/{noteId}/line-items/{lineItemId}', summary: 'Update a line item on a delivery note', pathParams: ['noteId', 'lineItemId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderLineItems', 'tagIds', 'tagCodes'] },
30
30
  'delete-line-items': { method: 'DELETE', path: '/v1/delivery-notes/{noteId}/line-items/{lineItemId}', summary: 'Remove a line item from a delivery note', pathParams: ['noteId', 'lineItemId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
31
31
  'list-notes': { method: 'GET', path: '/v1/delivery-notes/{deliveryNoteId}/notes', summary: 'Get all notes for a delivery note', pathParams: ['deliveryNoteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
32
32
  'create-notes': { method: 'POST', path: '/v1/delivery-notes/{deliveryNoteId}/notes', summary: 'Create a note for a delivery note', pathParams: ['deliveryNoteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -72,7 +72,7 @@ export default class DeliveryNotes extends Command {
72
72
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
73
73
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
74
74
  query: Flags.string({ description: 'Additional query params as JSON' }),
75
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
75
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
76
76
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
77
77
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
78
78
  };
@@ -144,6 +144,8 @@ export default class DeliveryNotes extends Command {
144
144
  queryParams.search = flags.search;
145
145
  if (flags['sort-by'])
146
146
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
147
+ if (flags.fields)
148
+ queryParams.fields = flags.fields;
147
149
  if (flags.query) {
148
150
  try {
149
151
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -346,11 +348,6 @@ export default class DeliveryNotes extends Command {
346
348
  output = obj[arrayKeys[0]];
347
349
  }
348
350
  }
349
- // Filter fields if --fields flag is provided
350
- if (flags.fields) {
351
- const fieldList = flags.fields.split(',').map(f => f.trim());
352
- output = this.filterFields(output, fieldList);
353
- }
354
351
  // Sanitize output if requested
355
352
  if (flags.sanitize) {
356
353
  output = this.sanitizeOutput(output);
@@ -605,6 +602,8 @@ export default class DeliveryNotes extends Command {
605
602
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
606
603
  if (flags.include)
607
604
  baseParams.include = flags.include;
605
+ if (flags.fields)
606
+ baseParams.fields = flags.fields;
608
607
  if (flags.query) {
609
608
  try {
610
609
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -659,12 +658,7 @@ export default class DeliveryNotes extends Command {
659
658
  }
660
659
  }
661
660
  process.stderr.write(' done\n');
662
- // Filter fields if specified
663
661
  let output = allItems;
664
- if (flags.fields) {
665
- const fieldList = flags.fields.split(',').map(f => f.trim());
666
- output = this.filterFields(allItems, fieldList);
667
- }
668
662
  // Sanitize output if requested
669
663
  if (flags.sanitize) {
670
664
  output = this.sanitizeOutput(output);
@@ -993,56 +987,6 @@ export default class DeliveryNotes extends Command {
993
987
  return `\$${op}`;
994
988
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
995
989
  }
996
- filterFields(data, fields) {
997
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
998
- const pick = (obj, keys) => {
999
- // Group keys by their first segment so sibling sub-paths
1000
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
1001
- // and don't clobber each other on merge.
1002
- const directKeys = new Set();
1003
- const nestedKeys = new Map();
1004
- for (const key of keys) {
1005
- if (key.split('.').some(isUnsafeKey))
1006
- continue;
1007
- if (key.includes('.')) {
1008
- const [first, ...rest] = key.split('.');
1009
- if (isUnsafeKey(first))
1010
- continue;
1011
- const list = nestedKeys.get(first);
1012
- if (list) {
1013
- list.push(rest.join('.'));
1014
- }
1015
- else {
1016
- nestedKeys.set(first, [rest.join('.')]);
1017
- }
1018
- }
1019
- else {
1020
- directKeys.add(key);
1021
- }
1022
- }
1023
- const result = {};
1024
- for (const key of directKeys) {
1025
- if (key in obj)
1026
- result[key] = obj[key];
1027
- }
1028
- for (const [first, restKeys] of nestedKeys) {
1029
- const val = obj[first];
1030
- if (!val || typeof val !== 'object')
1031
- continue;
1032
- if (Array.isArray(val)) {
1033
- result[first] = val.map(item => pick(item, restKeys));
1034
- }
1035
- else {
1036
- result[first] = pick(val, restKeys);
1037
- }
1038
- }
1039
- return result;
1040
- };
1041
- if (Array.isArray(data)) {
1042
- return data.map(item => pick(item, fields));
1043
- }
1044
- return pick(data, fields);
1045
- }
1046
990
  sanitizeOutput(data) {
1047
991
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1048
992
  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 DunningConfigs 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 DunningConfigs 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 DunningConfigs 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 DunningConfigs 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 DunningConfigs 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 DunningConfigs 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 DunningConfigs 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 DunningReminders 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;
@@ -44,7 +44,7 @@ export default class DunningReminders extends Command {
44
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
- 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)' }),
48
48
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
49
49
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
50
50
  };
@@ -116,6 +116,8 @@ export default class DunningReminders extends Command {
116
116
  queryParams.search = flags.search;
117
117
  if (flags['sort-by'])
118
118
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
119
+ if (flags.fields)
120
+ queryParams.fields = flags.fields;
119
121
  if (flags.query) {
120
122
  try {
121
123
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -318,11 +320,6 @@ export default class DunningReminders extends Command {
318
320
  output = obj[arrayKeys[0]];
319
321
  }
320
322
  }
321
- // Filter fields if --fields flag is provided
322
- if (flags.fields) {
323
- const fieldList = flags.fields.split(',').map(f => f.trim());
324
- output = this.filterFields(output, fieldList);
325
- }
326
323
  // Sanitize output if requested
327
324
  if (flags.sanitize) {
328
325
  output = this.sanitizeOutput(output);
@@ -577,6 +574,8 @@ export default class DunningReminders extends Command {
577
574
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
578
575
  if (flags.include)
579
576
  baseParams.include = flags.include;
577
+ if (flags.fields)
578
+ baseParams.fields = flags.fields;
580
579
  if (flags.query) {
581
580
  try {
582
581
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -631,12 +630,7 @@ export default class DunningReminders extends Command {
631
630
  }
632
631
  }
633
632
  process.stderr.write(' done\n');
634
- // Filter fields if specified
635
633
  let output = allItems;
636
- if (flags.fields) {
637
- const fieldList = flags.fields.split(',').map(f => f.trim());
638
- output = this.filterFields(allItems, fieldList);
639
- }
640
634
  // Sanitize output if requested
641
635
  if (flags.sanitize) {
642
636
  output = this.sanitizeOutput(output);
@@ -965,56 +959,6 @@ export default class DunningReminders extends Command {
965
959
  return `\$${op}`;
966
960
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
967
961
  }
968
- filterFields(data, fields) {
969
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
970
- const pick = (obj, keys) => {
971
- // Group keys by their first segment so sibling sub-paths
972
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
973
- // and don't clobber each other on merge.
974
- const directKeys = new Set();
975
- const nestedKeys = new Map();
976
- for (const key of keys) {
977
- if (key.split('.').some(isUnsafeKey))
978
- continue;
979
- if (key.includes('.')) {
980
- const [first, ...rest] = key.split('.');
981
- if (isUnsafeKey(first))
982
- continue;
983
- const list = nestedKeys.get(first);
984
- if (list) {
985
- list.push(rest.join('.'));
986
- }
987
- else {
988
- nestedKeys.set(first, [rest.join('.')]);
989
- }
990
- }
991
- else {
992
- directKeys.add(key);
993
- }
994
- }
995
- const result = {};
996
- for (const key of directKeys) {
997
- if (key in obj)
998
- result[key] = obj[key];
999
- }
1000
- for (const [first, restKeys] of nestedKeys) {
1001
- const val = obj[first];
1002
- if (!val || typeof val !== 'object')
1003
- continue;
1004
- if (Array.isArray(val)) {
1005
- result[first] = val.map(item => pick(item, restKeys));
1006
- }
1007
- else {
1008
- result[first] = pick(val, restKeys);
1009
- }
1010
- }
1011
- return result;
1012
- };
1013
- if (Array.isArray(data)) {
1014
- return data.map(item => pick(item, fields));
1015
- }
1016
- return pick(data, fields);
1017
- }
1018
962
  sanitizeOutput(data) {
1019
963
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1020
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 DunningRuns 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;
@@ -32,7 +32,7 @@ export default class DunningRuns extends Command {
32
32
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
33
33
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
34
34
  query: Flags.string({ description: 'Additional query params as JSON' }),
35
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
35
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
36
36
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
37
37
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
38
38
  };
@@ -104,6 +104,8 @@ export default class DunningRuns extends Command {
104
104
  queryParams.search = flags.search;
105
105
  if (flags['sort-by'])
106
106
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
107
+ if (flags.fields)
108
+ queryParams.fields = flags.fields;
107
109
  if (flags.query) {
108
110
  try {
109
111
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -306,11 +308,6 @@ export default class DunningRuns extends Command {
306
308
  output = obj[arrayKeys[0]];
307
309
  }
308
310
  }
309
- // Filter fields if --fields flag is provided
310
- if (flags.fields) {
311
- const fieldList = flags.fields.split(',').map(f => f.trim());
312
- output = this.filterFields(output, fieldList);
313
- }
314
311
  // Sanitize output if requested
315
312
  if (flags.sanitize) {
316
313
  output = this.sanitizeOutput(output);
@@ -565,6 +562,8 @@ export default class DunningRuns extends Command {
565
562
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
566
563
  if (flags.include)
567
564
  baseParams.include = flags.include;
565
+ if (flags.fields)
566
+ baseParams.fields = flags.fields;
568
567
  if (flags.query) {
569
568
  try {
570
569
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -619,12 +618,7 @@ export default class DunningRuns extends Command {
619
618
  }
620
619
  }
621
620
  process.stderr.write(' done\n');
622
- // Filter fields if specified
623
621
  let output = allItems;
624
- if (flags.fields) {
625
- const fieldList = flags.fields.split(',').map(f => f.trim());
626
- output = this.filterFields(allItems, fieldList);
627
- }
628
622
  // Sanitize output if requested
629
623
  if (flags.sanitize) {
630
624
  output = this.sanitizeOutput(output);
@@ -953,56 +947,6 @@ export default class DunningRuns extends Command {
953
947
  return `\$${op}`;
954
948
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
955
949
  }
956
- filterFields(data, fields) {
957
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
958
- const pick = (obj, keys) => {
959
- // Group keys by their first segment so sibling sub-paths
960
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
961
- // and don't clobber each other on merge.
962
- const directKeys = new Set();
963
- const nestedKeys = new Map();
964
- for (const key of keys) {
965
- if (key.split('.').some(isUnsafeKey))
966
- continue;
967
- if (key.includes('.')) {
968
- const [first, ...rest] = key.split('.');
969
- if (isUnsafeKey(first))
970
- continue;
971
- const list = nestedKeys.get(first);
972
- if (list) {
973
- list.push(rest.join('.'));
974
- }
975
- else {
976
- nestedKeys.set(first, [rest.join('.')]);
977
- }
978
- }
979
- else {
980
- directKeys.add(key);
981
- }
982
- }
983
- const result = {};
984
- for (const key of directKeys) {
985
- if (key in obj)
986
- result[key] = obj[key];
987
- }
988
- for (const [first, restKeys] of nestedKeys) {
989
- const val = obj[first];
990
- if (!val || typeof val !== 'object')
991
- continue;
992
- if (Array.isArray(val)) {
993
- result[first] = val.map(item => pick(item, restKeys));
994
- }
995
- else {
996
- result[first] = pick(val, restKeys);
997
- }
998
- }
999
- return result;
1000
- };
1001
- if (Array.isArray(data)) {
1002
- return data.map(item => pick(item, fields));
1003
- }
1004
- return pick(data, fields);
1005
- }
1006
950
  sanitizeOutput(data) {
1007
951
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1008
952
  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 EmailTransactions 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;