@aderis-erp/cli 1.0.15 → 1.1.0

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 (182) 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 +54 -78
  4. package/dist/commands/account-transaction-allocations.d.ts +0 -1
  5. package/dist/commands/account-transaction-allocations.js +51 -75
  6. package/dist/commands/account-transactions.d.ts +0 -1
  7. package/dist/commands/account-transactions.js +80 -94
  8. package/dist/commands/accounts.d.ts +0 -1
  9. package/dist/commands/accounts.js +59 -83
  10. package/dist/commands/agent-platform.d.ts +0 -1
  11. package/dist/commands/agent-platform.js +58 -82
  12. package/dist/commands/agent-runs.d.ts +39 -0
  13. package/dist/commands/agent-runs.js +1155 -0
  14. package/dist/commands/analytics.d.ts +0 -1
  15. package/dist/commands/analytics.js +52 -76
  16. package/dist/commands/{text-templates.d.ts → api-keys.d.ts} +1 -2
  17. package/dist/commands/api-keys.js +1150 -0
  18. package/dist/commands/async-jobs.d.ts +39 -0
  19. package/dist/commands/async-jobs.js +1158 -0
  20. package/dist/commands/audit-log.d.ts +0 -1
  21. package/dist/commands/audit-log.js +51 -75
  22. package/dist/commands/auth/login.d.ts +9 -0
  23. package/dist/commands/auth/login.js +73 -20
  24. package/dist/commands/auth/logout.d.ts +4 -0
  25. package/dist/commands/auth/logout.js +4 -0
  26. package/dist/commands/auth/status.js +26 -17
  27. package/dist/commands/auth/tenant.js +3 -6
  28. package/dist/commands/auth.d.ts +0 -1
  29. package/dist/commands/auth.js +5 -34
  30. package/dist/commands/bank-accounts.d.ts +0 -1
  31. package/dist/commands/bank-accounts.js +68 -91
  32. package/dist/commands/bank-integrations.d.ts +1 -1
  33. package/dist/commands/bank-integrations.js +71 -92
  34. package/dist/commands/business-partners.d.ts +1 -1
  35. package/dist/commands/business-partners.js +84 -100
  36. package/dist/commands/chat.d.ts +0 -1
  37. package/dist/commands/chat.js +57 -80
  38. package/dist/commands/config/add.d.ts +3 -0
  39. package/dist/commands/config/add.js +34 -16
  40. package/dist/commands/config/current.js +3 -0
  41. package/dist/commands/config/list.js +3 -0
  42. package/dist/commands/credit-card-accounts.d.ts +1 -1
  43. package/dist/commands/credit-card-accounts.js +72 -90
  44. package/dist/commands/delivery-notes.d.ts +0 -1
  45. package/dist/commands/delivery-notes.js +83 -105
  46. package/dist/commands/dunning-configs.d.ts +0 -1
  47. package/dist/commands/dunning-configs.js +54 -78
  48. package/dist/commands/dunning-reminders.d.ts +0 -1
  49. package/dist/commands/dunning-reminders.js +57 -81
  50. package/dist/commands/dunning-runs.d.ts +0 -1
  51. package/dist/commands/dunning-runs.js +50 -74
  52. package/dist/commands/email-transactions.d.ts +0 -1
  53. package/dist/commands/email-transactions.js +52 -76
  54. package/dist/commands/employees.d.ts +0 -1
  55. package/dist/commands/employees.js +81 -105
  56. package/dist/commands/entity-configurations.d.ts +0 -1
  57. package/dist/commands/entity-configurations.js +52 -76
  58. package/dist/commands/event-processor-mappings.d.ts +0 -1
  59. package/dist/commands/event-processor-mappings.js +54 -78
  60. package/dist/commands/files.d.ts +0 -1
  61. package/dist/commands/files.js +61 -85
  62. package/dist/commands/health.d.ts +0 -1
  63. package/dist/commands/health.js +54 -78
  64. package/dist/commands/imports.d.ts +39 -0
  65. package/dist/commands/imports.js +1151 -0
  66. package/dist/commands/inbox.d.ts +0 -1
  67. package/dist/commands/inbox.js +57 -80
  68. package/dist/commands/integration-identities.d.ts +40 -0
  69. package/dist/commands/integration-identities.js +1151 -0
  70. package/dist/commands/integrations.d.ts +0 -1
  71. package/dist/commands/integrations.js +52 -76
  72. package/dist/commands/item-categories.d.ts +0 -1
  73. package/dist/commands/item-categories.js +54 -78
  74. package/dist/commands/items.d.ts +0 -1
  75. package/dist/commands/items.js +54 -78
  76. package/dist/commands/journal-lines.d.ts +0 -1
  77. package/dist/commands/journal-lines.js +50 -74
  78. package/dist/commands/journals.d.ts +1 -1
  79. package/dist/commands/journals.js +75 -96
  80. package/dist/commands/ledgers.d.ts +3 -2
  81. package/dist/commands/ledgers.js +100 -95
  82. package/dist/commands/my-account.d.ts +39 -0
  83. package/dist/commands/my-account.js +1160 -0
  84. package/dist/commands/office-locations.d.ts +0 -1
  85. package/dist/commands/office-locations.js +54 -78
  86. package/dist/commands/payment-methods.d.ts +0 -1
  87. package/dist/commands/payment-methods.js +59 -83
  88. package/dist/commands/payment-runs.d.ts +0 -1
  89. package/dist/commands/payment-runs.js +66 -90
  90. package/dist/commands/payment-terms.d.ts +0 -1
  91. package/dist/commands/payment-terms.js +55 -79
  92. package/dist/commands/payments.d.ts +0 -1
  93. package/dist/commands/payments.js +56 -80
  94. package/dist/commands/payroll-runs.d.ts +43 -0
  95. package/dist/commands/payroll-runs.js +1188 -0
  96. package/dist/commands/permissions.d.ts +39 -0
  97. package/dist/commands/permissions.js +1146 -0
  98. package/dist/commands/price-lists.d.ts +0 -1
  99. package/dist/commands/price-lists.js +59 -83
  100. package/dist/commands/processor-mappings.d.ts +0 -1
  101. package/dist/commands/processor-mappings.js +53 -77
  102. package/dist/commands/processors.d.ts +0 -1
  103. package/dist/commands/processors.js +60 -85
  104. package/dist/commands/purchase-order-types.d.ts +0 -1
  105. package/dist/commands/purchase-order-types.js +54 -78
  106. package/dist/commands/purchase-orders.d.ts +0 -1
  107. package/dist/commands/purchase-orders.js +74 -97
  108. package/dist/commands/reports.d.ts +0 -1
  109. package/dist/commands/reports.js +54 -78
  110. package/dist/commands/roles.d.ts +39 -0
  111. package/dist/commands/{text-templates.js → roles.js} +64 -90
  112. package/dist/commands/salary-types.d.ts +0 -1
  113. package/dist/commands/salary-types.js +54 -78
  114. package/dist/commands/sales-invoices.d.ts +0 -1
  115. package/dist/commands/sales-invoices.js +90 -110
  116. package/dist/commands/sales-orders.d.ts +0 -1
  117. package/dist/commands/sales-orders.js +83 -105
  118. package/dist/commands/saved-views.d.ts +0 -1
  119. package/dist/commands/saved-views.js +52 -76
  120. package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
  121. package/dist/commands/scheduled-processor-mappings.js +54 -78
  122. package/dist/commands/schedules.d.ts +0 -1
  123. package/dist/commands/schedules.js +58 -82
  124. package/dist/commands/switch.js +4 -4
  125. package/dist/commands/tag-configurations.d.ts +0 -1
  126. package/dist/commands/tag-configurations.js +56 -79
  127. package/dist/commands/tags.d.ts +0 -1
  128. package/dist/commands/tags.js +54 -78
  129. package/dist/commands/tax-codes.d.ts +0 -1
  130. package/dist/commands/tax-codes.js +57 -81
  131. package/dist/commands/tax-matrix.d.ts +0 -1
  132. package/dist/commands/tax-matrix.js +54 -78
  133. package/dist/commands/templates.d.ts +39 -0
  134. package/dist/commands/templates.js +1157 -0
  135. package/dist/commands/tenants.d.ts +0 -1
  136. package/dist/commands/tenants.js +58 -81
  137. package/dist/commands/tools.d.ts +0 -1
  138. package/dist/commands/tools.js +51 -75
  139. package/dist/commands/users.d.ts +42 -0
  140. package/dist/commands/users.js +1174 -0
  141. package/dist/commands/vat-declarations.d.ts +3 -1
  142. package/dist/commands/vat-declarations.js +78 -93
  143. package/dist/commands/vendor-invoices.d.ts +0 -1
  144. package/dist/commands/vendor-invoices.js +87 -110
  145. package/dist/commands/webhooks.d.ts +0 -1
  146. package/dist/commands/webhooks.js +56 -80
  147. package/dist/commands/workflows.d.ts +0 -1
  148. package/dist/commands/workflows.js +52 -76
  149. package/dist/lib/api-client.d.ts +6 -0
  150. package/dist/lib/api-client.js +16 -6
  151. package/dist/lib/auth/constants.d.ts +11 -0
  152. package/dist/lib/auth/constants.js +11 -0
  153. package/dist/lib/auth/errors.d.ts +17 -0
  154. package/dist/lib/auth/errors.js +22 -0
  155. package/dist/lib/auth/flow.d.ts +27 -0
  156. package/dist/lib/auth/flow.js +163 -0
  157. package/dist/lib/auth/guards.d.ts +5 -0
  158. package/dist/lib/auth/guards.js +14 -0
  159. package/dist/lib/auth/http.d.ts +16 -0
  160. package/dist/lib/auth/http.js +49 -0
  161. package/dist/lib/auth/index.d.ts +49 -0
  162. package/dist/lib/auth/index.js +228 -0
  163. package/dist/lib/auth/jwks.d.ts +19 -0
  164. package/dist/lib/auth/jwks.js +112 -0
  165. package/dist/lib/auth/keycloak-provider.d.ts +91 -0
  166. package/dist/lib/auth/keycloak-provider.js +244 -0
  167. package/dist/lib/auth/pages.d.ts +25 -0
  168. package/dist/lib/auth/pages.js +123 -0
  169. package/dist/lib/auth/pkce.d.ts +11 -0
  170. package/dist/lib/auth/pkce.js +17 -0
  171. package/dist/lib/auth/tokens.d.ts +59 -0
  172. package/dist/lib/auth/tokens.js +105 -0
  173. package/dist/lib/auth/types.d.ts +61 -0
  174. package/dist/lib/auth/types.js +1 -0
  175. package/dist/lib/auth/validated-url.d.ts +6 -0
  176. package/dist/lib/auth/validated-url.js +53 -0
  177. package/dist/lib/config.d.ts +13 -3
  178. package/dist/lib/config.js +24 -19
  179. package/oclif.manifest.json +2447 -641
  180. package/package.json +5 -4
  181. package/dist/lib/auth.d.ts +0 -43
  182. package/dist/lib/auth.js +0 -610
@@ -1,35 +1,37 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
2
+ import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
3
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", "files"];
9
- const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "post", "approve", "cancel", "reverse", "get-deferrals", "create-deferrals", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["list", "create", "stats", "get", "update", "delete", "post", "approve", "cancel", "reverse", "update-lines", "get-deferrals", "create-deferrals", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
- 'list': { method: 'GET', path: '/v1/journals', summary: 'List all journals', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/journals', summary: 'Create a new journal (with embedded lines)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lines', 'notes'] },
13
- 'get': { method: 'GET', path: '/v1/journals/{id}', summary: 'Get a journal by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'update': { method: 'PATCH', path: '/v1/journals/{id}', summary: 'Update a journal (with embedded lines upsert)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lines'] },
15
- 'delete': { method: 'DELETE', path: '/v1/journals/{id}', summary: 'Delete a journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
- 'post': { method: 'POST', path: '/v1/journals/{id}/post', summary: 'Post journal (finalize)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
- 'approve': { method: 'POST', path: '/v1/journals/{id}/approve', summary: 'Approve a journal (transitions DRAFT to APPROVED)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
18
- 'cancel': { method: 'POST', path: '/v1/journals/{id}/cancel', summary: 'Cancel a journal', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
- 'reverse': { method: 'POST', path: '/v1/journals/{id}/reverse', summary: 'Reverse a posted journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
- 'get-deferrals': { method: 'GET', path: '/v1/journals/{id}/deferrals', summary: 'List the deferral schedules of a journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
21
- 'create-deferrals': { method: 'POST', path: '/v1/journals/{id}/deferrals', summary: 'Create deferral schedules for one line of a journal (manual trigger)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['periods'] },
22
- 'list-notes': { method: 'GET', path: '/v1/journals/{journalId}/notes', summary: 'Get all notes for a journal', pathParams: ['journalId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
- 'create-notes': { method: 'POST', path: '/v1/journals/{journalId}/notes', summary: 'Create a note for a journal', pathParams: ['journalId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
24
- 'get-notes': { method: 'GET', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Get a specific note for a journal', pathParams: ['journalId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
- 'update-notes': { method: 'PATCH', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Update a note for a journal', pathParams: ['journalId', 'noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
- 'delete-notes': { method: 'DELETE', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Delete a note from a journal', pathParams: ['journalId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
- 'list-files': { method: 'GET', path: '/v1/journals/{parentId}/files', summary: 'List file attachments for a journal', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
- 'create-files': { method: 'POST', path: '/v1/journals/{parentId}/files', summary: 'Upload a file attachment to a journal', pathParams: ['parentId'], hasBody: false, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
29
- 'get-files': { method: 'GET', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Get a file attachment for a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
30
- 'update-files': { method: 'PATCH', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a journal', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
31
- 'delete-files': { method: 'DELETE', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
32
- 'files-download': { method: 'GET', path: '/v1/journals/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
11
+ 'list': { method: 'GET', path: '/v1/journals', summary: 'List all journals', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
12
+ 'create': { method: 'POST', path: '/v1/journals', summary: 'Create a new journal (with embedded lines)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['lines', 'files', 'notes'] },
13
+ 'stats': { method: 'GET', path: '/v1/journals/stats', summary: 'Journal counts and debit totals per date range', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
14
+ 'get': { method: 'GET', path: '/v1/journals/{id}', summary: 'Get a journal by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
15
+ 'update': { method: 'PATCH', path: '/v1/journals/{id}', summary: 'Update a journal (with embedded lines upsert)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['lines'] },
16
+ 'delete': { method: 'DELETE', path: '/v1/journals/{id}', summary: 'Delete a journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
17
+ 'post': { method: 'POST', path: '/v1/journals/{id}/post', summary: 'Post journal (finalize)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
18
+ 'approve': { method: 'POST', path: '/v1/journals/{id}/approve', summary: 'Approve a journal (transitions DRAFT to APPROVED)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
19
+ 'cancel': { method: 'POST', path: '/v1/journals/{id}/cancel', summary: 'Cancel a journal', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
20
+ 'reverse': { method: 'POST', path: '/v1/journals/{id}/reverse', summary: 'Reverse a posted journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
21
+ 'update-lines': { method: 'PATCH', path: '/v1/journals/{id}/lines/{lineId}', summary: 'Update a single journal line in place', pathParams: ['id', 'lineId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['tagIds', 'tagCodes'] },
22
+ 'get-deferrals': { method: 'GET', path: '/v1/journals/{id}/deferrals', summary: 'List the deferral schedules of a journal', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
23
+ 'create-deferrals': { method: 'POST', path: '/v1/journals/{id}/deferrals', summary: 'Create deferral schedules for one line of a journal (manual trigger)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['periods'] },
24
+ 'list-notes': { method: 'GET', path: '/v1/journals/{journalId}/notes', summary: 'Get all notes for a journal', pathParams: ['journalId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
25
+ 'create-notes': { method: 'POST', path: '/v1/journals/{journalId}/notes', summary: 'Create a note for a journal', pathParams: ['journalId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
26
+ 'get-notes': { method: 'GET', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Get a specific note for a journal', pathParams: ['journalId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
27
+ 'update-notes': { method: 'PATCH', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Update a note for a journal', pathParams: ['journalId', 'noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
28
+ 'delete-notes': { method: 'DELETE', path: '/v1/journals/{journalId}/notes/{noteId}', summary: 'Delete a note from a journal', pathParams: ['journalId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
29
+ 'list-files': { method: 'GET', path: '/v1/journals/{parentId}/files', summary: 'List file attachments for a journal', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
30
+ 'create-files': { method: 'POST', path: '/v1/journals/{parentId}/files', summary: 'Upload a file attachment to a journal', pathParams: ['parentId'], hasBody: false, isMultipart: true, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
31
+ 'get-files': { method: 'GET', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Get a file attachment for a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
32
+ 'update-files': { method: 'PATCH', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a journal', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
33
+ 'delete-files': { method: 'DELETE', path: '/v1/journals/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
34
+ 'files-download': { method: 'GET', path: '/v1/journals/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a journal', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: true, hasBinaryVariant: false, bodyArrayFields: [] },
33
35
  };
34
36
  export default class Journals extends Command {
35
37
  static description = 'Manage journals';
@@ -53,6 +55,7 @@ export default class Journals extends Command {
53
55
  data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
54
56
  file: Flags.string({ char: 'f', description: 'Read request body from file' }),
55
57
  set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
58
+ 'line-id': Flags.string({ description: 'Path param: lineId' }),
56
59
  'note-id': Flags.string({ description: 'Path param: noteId' }),
57
60
  'file-id': Flags.string({ description: 'Path param: fileId' }),
58
61
  page: Flags.string({ description: 'Page number' }),
@@ -62,7 +65,7 @@ export default class Journals extends Command {
62
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
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
68
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
66
69
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
67
70
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
68
71
  };
@@ -134,6 +137,8 @@ export default class Journals extends Command {
134
137
  queryParams.search = flags.search;
135
138
  if (flags['sort-by'])
136
139
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
140
+ if (flags.fields)
141
+ queryParams.fields = flags.fields;
137
142
  if (flags.query) {
138
143
  try {
139
144
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -281,10 +286,11 @@ export default class Journals extends Command {
281
286
  process.stderr.write('\n');
282
287
  }
283
288
  try {
284
- // Binary response: download to file
289
+ // Binary response: to -f / --file, or to stdout when it is redirected.
285
290
  if (endpoint.isBinaryResponse) {
286
- if (!flags.file) {
287
- this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx).`);
291
+ const toStdout = !flags.file;
292
+ if (toStdout && process.stdout.isTTY) {
293
+ this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx), or redirect stdout to a file.`);
288
294
  }
289
295
  const binResponse = await apiRequest(endpoint.method, apiPath, {
290
296
  params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
@@ -292,24 +298,55 @@ export default class Journals extends Command {
292
298
  contextName: flags.context,
293
299
  binary: true,
294
300
  });
295
- const fsModule = await import('node:fs');
296
301
  const binData = binResponse.data;
297
302
  const buffer = Buffer.isBuffer(binData)
298
303
  ? binData
299
304
  : Buffer.from(binData);
305
+ if (toStdout) {
306
+ // Nothing else may reach stdout here — it is the file.
307
+ process.stdout.write(buffer);
308
+ return;
309
+ }
310
+ const fsModule = await import('node:fs');
300
311
  fsModule.writeFileSync(flags.file, buffer);
301
312
  this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
302
313
  return;
303
314
  }
304
- const response = await apiRequest(endpoint.method, apiPath, {
305
- params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
306
- data,
307
- contextName: flags.context,
308
- acceptAny: true,
309
- });
315
+ let response;
316
+ if (endpoint.hasBinaryVariant) {
317
+ // This route answers JSON or a file depending on the request body, so the
318
+ // bytes are read first and the response's own content-type decides. Asking
319
+ // for text here would corrupt an xlsx/pdf before anything could inspect it.
320
+ const raw = await apiRequest(endpoint.method, apiPath, {
321
+ params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
322
+ data,
323
+ contextName: flags.context,
324
+ binary: true,
325
+ });
326
+ const rawType = String(raw.headers['content-type'] || '').toLowerCase();
327
+ const rawData = raw.data;
328
+ const buffer = Buffer.isBuffer(rawData) ? rawData : Buffer.from(rawData);
329
+ if (!isTextualMediaType(rawType)) {
330
+ if (process.stdout.isTTY) {
331
+ this.error(`The API returned ${rawType || 'binary data'}. Redirect stdout to a file, e.g. ... > report.xlsx`);
332
+ }
333
+ // Nothing else may reach stdout here — it is the file.
334
+ process.stdout.write(buffer);
335
+ return;
336
+ }
337
+ response = { data: buffer.toString('utf8'), headers: raw.headers, status: raw.status };
338
+ }
339
+ else {
340
+ response = await apiRequest(endpoint.method, apiPath, {
341
+ params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
342
+ data,
343
+ contextName: flags.context,
344
+ acceptAny: true,
345
+ });
346
+ }
310
347
  // Check content-type for non-JSON responses (XML, text, etc.)
311
348
  const contentType = (response.headers['content-type'] || '').toLowerCase();
312
- if (contentType.includes('xml') || contentType.includes('text/')) {
349
+ if (isTextualMediaType(contentType) && !contentType.startsWith('application/json')) {
313
350
  // Output raw content for XML/text responses (CSV, plain, HTML, etc.)
314
351
  this.log(String(response.data));
315
352
  return;
@@ -336,11 +373,6 @@ export default class Journals extends Command {
336
373
  output = obj[arrayKeys[0]];
337
374
  }
338
375
  }
339
- // Filter fields if --fields flag is provided
340
- if (flags.fields) {
341
- const fieldList = flags.fields.split(',').map(f => f.trim());
342
- output = this.filterFields(output, fieldList);
343
- }
344
376
  // Sanitize output if requested
345
377
  if (flags.sanitize) {
346
378
  output = this.sanitizeOutput(output);
@@ -595,6 +627,8 @@ export default class Journals extends Command {
595
627
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
596
628
  if (flags.include)
597
629
  baseParams.include = flags.include;
630
+ if (flags.fields)
631
+ baseParams.fields = flags.fields;
598
632
  if (flags.query) {
599
633
  try {
600
634
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -649,12 +683,7 @@ export default class Journals extends Command {
649
683
  }
650
684
  }
651
685
  process.stderr.write(' done\n');
652
- // Filter fields if specified
653
686
  let output = allItems;
654
- if (flags.fields) {
655
- const fieldList = flags.fields.split(',').map(f => f.trim());
656
- output = this.filterFields(allItems, fieldList);
657
- }
658
687
  // Sanitize output if requested
659
688
  if (flags.sanitize) {
660
689
  output = this.sanitizeOutput(output);
@@ -983,56 +1012,6 @@ export default class Journals extends Command {
983
1012
  return `\$${op}`;
984
1013
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
985
1014
  }
986
- filterFields(data, fields) {
987
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
988
- const pick = (obj, keys) => {
989
- // Group keys by their first segment so sibling sub-paths
990
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
991
- // and don't clobber each other on merge.
992
- const directKeys = new Set();
993
- const nestedKeys = new Map();
994
- for (const key of keys) {
995
- if (key.split('.').some(isUnsafeKey))
996
- continue;
997
- if (key.includes('.')) {
998
- const [first, ...rest] = key.split('.');
999
- if (isUnsafeKey(first))
1000
- continue;
1001
- const list = nestedKeys.get(first);
1002
- if (list) {
1003
- list.push(rest.join('.'));
1004
- }
1005
- else {
1006
- nestedKeys.set(first, [rest.join('.')]);
1007
- }
1008
- }
1009
- else {
1010
- directKeys.add(key);
1011
- }
1012
- }
1013
- const result = {};
1014
- for (const key of directKeys) {
1015
- if (key in obj)
1016
- result[key] = obj[key];
1017
- }
1018
- for (const [first, restKeys] of nestedKeys) {
1019
- const val = obj[first];
1020
- if (!val || typeof val !== 'object')
1021
- continue;
1022
- if (Array.isArray(val)) {
1023
- result[first] = val.map(item => pick(item, restKeys));
1024
- }
1025
- else {
1026
- result[first] = pick(val, restKeys);
1027
- }
1028
- }
1029
- return result;
1030
- };
1031
- if (Array.isArray(data)) {
1032
- return data.map(item => pick(item, fields));
1033
- }
1034
- return pick(data, fields);
1035
- }
1036
1015
  sanitizeOutput(data) {
1037
1016
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1038
1017
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -14,8 +14,10 @@ export default class Ledgers extends Command {
14
14
  data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
15
  file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
16
  set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
- 'note-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
17
  id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ 'accrual-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ 'finding-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ 'note-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
21
  page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
22
  limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
23
  include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -33,7 +35,6 @@ export default class Ledgers extends Command {
33
35
  private runCamt053Import;
34
36
  private runNestedImport;
35
37
  private parseFilterValue;
36
- private filterFields;
37
38
  private sanitizeOutput;
38
39
  private getColumns;
39
40
  private getValue;