@aderis-erp/cli 1.0.14 → 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 (167) 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 +22 -78
  4. package/dist/commands/account-transaction-allocations.d.ts +0 -1
  5. package/dist/commands/account-transaction-allocations.js +22 -78
  6. package/dist/commands/account-transactions.d.ts +0 -1
  7. package/dist/commands/account-transactions.js +28 -82
  8. package/dist/commands/accounts.d.ts +0 -1
  9. package/dist/commands/accounts.js +24 -80
  10. package/dist/commands/agent-platform.d.ts +0 -1
  11. package/dist/commands/agent-platform.js +24 -79
  12. package/dist/commands/analytics.d.ts +39 -0
  13. package/dist/commands/analytics.js +1113 -0
  14. package/dist/commands/{documents.d.ts → api-keys.d.ts} +1 -2
  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 +22 -78
  18. package/dist/commands/auth/login.d.ts +9 -0
  19. package/dist/commands/auth/login.js +83 -21
  20. package/dist/commands/auth/logout.d.ts +6 -0
  21. package/dist/commands/auth/logout.js +23 -6
  22. package/dist/commands/auth/status.js +46 -23
  23. package/dist/commands/auth/tenant.js +15 -9
  24. package/dist/commands/auth.d.ts +0 -1
  25. package/dist/commands/auth.js +37 -51
  26. package/dist/commands/bank-accounts.d.ts +0 -1
  27. package/dist/commands/bank-accounts.js +22 -78
  28. package/dist/commands/bank-integrations.d.ts +0 -1
  29. package/dist/commands/bank-integrations.js +22 -78
  30. package/dist/commands/business-partners.d.ts +1 -1
  31. package/dist/commands/business-partners.js +38 -84
  32. package/dist/commands/chat.d.ts +0 -1
  33. package/dist/commands/chat.js +22 -78
  34. package/dist/commands/config/add.d.ts +12 -0
  35. package/dist/commands/config/add.js +97 -17
  36. package/dist/commands/config/current.js +12 -4
  37. package/dist/commands/config/list.js +12 -4
  38. package/dist/commands/config/set-api-key.d.ts +10 -0
  39. package/dist/commands/config/set-api-key.js +49 -0
  40. package/dist/commands/config/use.js +3 -4
  41. package/dist/commands/credit-card-accounts.d.ts +0 -1
  42. package/dist/commands/credit-card-accounts.js +22 -78
  43. package/dist/commands/delivery-notes.d.ts +0 -1
  44. package/dist/commands/delivery-notes.js +29 -84
  45. package/dist/commands/dunning-configs.d.ts +0 -1
  46. package/dist/commands/dunning-configs.js +22 -78
  47. package/dist/commands/dunning-reminders.d.ts +0 -1
  48. package/dist/commands/dunning-reminders.js +22 -78
  49. package/dist/commands/dunning-runs.d.ts +0 -1
  50. package/dist/commands/dunning-runs.js +22 -78
  51. package/dist/commands/email-transactions.d.ts +0 -1
  52. package/dist/commands/email-transactions.js +22 -78
  53. package/dist/commands/employees.d.ts +0 -1
  54. package/dist/commands/employees.js +24 -80
  55. package/dist/commands/entity-configurations.d.ts +0 -1
  56. package/dist/commands/entity-configurations.js +22 -78
  57. package/dist/commands/event-processor-mappings.d.ts +0 -1
  58. package/dist/commands/event-processor-mappings.js +22 -78
  59. package/dist/commands/{files-internal.d.ts → files.d.ts} +1 -2
  60. package/dist/commands/{files-internal.js → files.js} +40 -90
  61. package/dist/commands/health.d.ts +0 -1
  62. package/dist/commands/health.js +22 -78
  63. package/dist/commands/inbox.d.ts +0 -1
  64. package/dist/commands/inbox.js +22 -78
  65. package/dist/commands/integrations.d.ts +0 -1
  66. package/dist/commands/integrations.js +22 -78
  67. package/dist/commands/item-categories.d.ts +0 -1
  68. package/dist/commands/item-categories.js +22 -78
  69. package/dist/commands/items.d.ts +0 -1
  70. package/dist/commands/items.js +24 -80
  71. package/dist/commands/journal-lines.d.ts +0 -1
  72. package/dist/commands/journal-lines.js +22 -78
  73. package/dist/commands/journals.d.ts +1 -1
  74. package/dist/commands/journals.js +29 -81
  75. package/dist/commands/ledgers.d.ts +0 -1
  76. package/dist/commands/ledgers.js +26 -79
  77. package/dist/commands/nango-integrations.d.ts +39 -0
  78. package/dist/commands/nango-integrations.js +1115 -0
  79. package/dist/commands/office-locations.d.ts +0 -1
  80. package/dist/commands/office-locations.js +22 -78
  81. package/dist/commands/payment-methods.d.ts +0 -1
  82. package/dist/commands/payment-methods.js +22 -78
  83. package/dist/commands/payment-runs.d.ts +0 -1
  84. package/dist/commands/payment-runs.js +24 -79
  85. package/dist/commands/payment-terms.d.ts +0 -1
  86. package/dist/commands/payment-terms.js +22 -78
  87. package/dist/commands/payments.d.ts +0 -1
  88. package/dist/commands/payments.js +22 -78
  89. package/dist/commands/price-lists.d.ts +0 -1
  90. package/dist/commands/price-lists.js +22 -78
  91. package/dist/commands/processor-mappings.d.ts +0 -1
  92. package/dist/commands/processor-mappings.js +22 -78
  93. package/dist/commands/processors.d.ts +0 -1
  94. package/dist/commands/processors.js +22 -78
  95. package/dist/commands/purchase-order-types.d.ts +0 -1
  96. package/dist/commands/purchase-order-types.js +22 -78
  97. package/dist/commands/purchase-orders.d.ts +1 -1
  98. package/dist/commands/purchase-orders.js +35 -84
  99. package/dist/commands/reports.d.ts +0 -1
  100. package/dist/commands/reports.js +23 -79
  101. package/dist/commands/salary-types.d.ts +0 -1
  102. package/dist/commands/salary-types.js +22 -78
  103. package/dist/commands/sales-invoices.d.ts +0 -1
  104. package/dist/commands/sales-invoices.js +38 -89
  105. package/dist/commands/sales-orders.d.ts +0 -1
  106. package/dist/commands/sales-orders.js +26 -82
  107. package/dist/commands/saved-views.d.ts +0 -1
  108. package/dist/commands/saved-views.js +22 -78
  109. package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
  110. package/dist/commands/scheduled-processor-mappings.js +22 -78
  111. package/dist/commands/schedules.d.ts +0 -1
  112. package/dist/commands/schedules.js +22 -78
  113. package/dist/commands/switch.js +14 -7
  114. package/dist/commands/tag-configurations.d.ts +39 -0
  115. package/dist/commands/{documents.js → tag-configurations.js} +40 -96
  116. package/dist/commands/tags.d.ts +0 -1
  117. package/dist/commands/tags.js +22 -78
  118. package/dist/commands/tax-codes.d.ts +0 -1
  119. package/dist/commands/tax-codes.js +22 -78
  120. package/dist/commands/tax-matrix.d.ts +0 -1
  121. package/dist/commands/tax-matrix.js +22 -78
  122. package/dist/commands/tenants.d.ts +0 -1
  123. package/dist/commands/tenants.js +24 -79
  124. package/dist/commands/text-templates.d.ts +0 -1
  125. package/dist/commands/text-templates.js +22 -78
  126. package/dist/commands/tools.d.ts +0 -1
  127. package/dist/commands/tools.js +22 -78
  128. package/dist/commands/vat-declarations.d.ts +1 -1
  129. package/dist/commands/vat-declarations.js +28 -79
  130. package/dist/commands/vendor-invoices.d.ts +0 -1
  131. package/dist/commands/vendor-invoices.js +31 -86
  132. package/dist/commands/webhooks.d.ts +0 -1
  133. package/dist/commands/webhooks.js +22 -78
  134. package/dist/commands/workflows.d.ts +0 -1
  135. package/dist/commands/workflows.js +22 -78
  136. package/dist/lib/api-client.js +8 -6
  137. package/dist/lib/auth/constants.d.ts +11 -0
  138. package/dist/lib/auth/constants.js +11 -0
  139. package/dist/lib/auth/errors.d.ts +17 -0
  140. package/dist/lib/auth/errors.js +22 -0
  141. package/dist/lib/auth/flow.d.ts +27 -0
  142. package/dist/lib/auth/flow.js +163 -0
  143. package/dist/lib/auth/guards.d.ts +5 -0
  144. package/dist/lib/auth/guards.js +14 -0
  145. package/dist/lib/auth/http.d.ts +16 -0
  146. package/dist/lib/auth/http.js +49 -0
  147. package/dist/lib/auth/index.d.ts +49 -0
  148. package/dist/lib/auth/index.js +217 -0
  149. package/dist/lib/auth/keycloak-provider.d.ts +75 -0
  150. package/dist/lib/auth/keycloak-provider.js +215 -0
  151. package/dist/lib/auth/pages.d.ts +25 -0
  152. package/dist/lib/auth/pages.js +123 -0
  153. package/dist/lib/auth/pkce.d.ts +11 -0
  154. package/dist/lib/auth/pkce.js +17 -0
  155. package/dist/lib/auth/tokens.d.ts +54 -0
  156. package/dist/lib/auth/tokens.js +104 -0
  157. package/dist/lib/auth/types.d.ts +57 -0
  158. package/dist/lib/auth/types.js +1 -0
  159. package/dist/lib/auth/validated-url.d.ts +6 -0
  160. package/dist/lib/auth/validated-url.js +53 -0
  161. package/dist/lib/base-api-command.js +6 -4
  162. package/dist/lib/config.d.ts +44 -4
  163. package/dist/lib/config.js +55 -19
  164. package/oclif.manifest.json +1181 -330
  165. package/package.json +3 -2
  166. package/dist/lib/auth.d.ts +0 -35
  167. package/dist/lib/auth.js +0 -566
@@ -1,5 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
- import { getCurrentContext } from '../../lib/config.js';
2
+ import { keycloakBaseUrlOf } from '../../lib/auth/index.js';
3
+ import { getAuthType, getCurrentContext, hasCredentials } from '../../lib/config.js';
3
4
  export default class ConfigCurrent extends Command {
4
5
  static description = 'Show the current context';
5
6
  static examples = ['<%= config.bin %> config current', '<%= config.bin %> config current --json'];
@@ -24,20 +25,27 @@ export default class ConfigCurrent extends Command {
24
25
  }
25
26
  if (flags.json) {
26
27
  this.log(JSON.stringify({
27
- authenticated: Boolean(context.tokens),
28
+ auth_type: getAuthType(context),
29
+ authenticated: hasCredentials(context),
28
30
  client_id: context.client_id,
29
31
  environment: context.environment,
32
+ keycloak_base_url: getAuthType(context) === 'oauth2' ? keycloakBaseUrlOf(context) : undefined,
30
33
  name: context.name,
31
34
  tenant_id: context.tenant_id,
32
35
  }, null, 2));
33
36
  return;
34
37
  }
38
+ const authType = getAuthType(context);
35
39
  this.log(`Current context: ${context.name}`);
36
40
  this.log(`Environment: ${context.environment}`);
37
- this.log(`Client ID: ${context.client_id}`);
41
+ this.log(`Auth: ${authType === 'api_key' ? 'API key (x-api-key)' : 'oauth2'}`);
42
+ if (authType === 'oauth2') {
43
+ this.log(`Keycloak URL: ${keycloakBaseUrlOf(context)}`);
44
+ this.log(`Client ID: ${context.client_id ?? 'N/A'}`);
45
+ }
38
46
  if (context.tenant_id) {
39
47
  this.log(`Tenant ID: ${context.tenant_id}`);
40
48
  }
41
- this.log(`Authenticated: ${context.tokens ? 'Yes' : 'No'}`);
49
+ this.log(`Authenticated: ${hasCredentials(context) ? 'Yes' : 'No'}`);
42
50
  }
43
51
  }
@@ -1,5 +1,6 @@
1
1
  import { Command, Flags } from '@oclif/core';
2
- import { getCurrentContext, listContexts } from '../../lib/config.js';
2
+ import { keycloakBaseUrlOf } from '../../lib/auth/index.js';
3
+ import { getAuthType, getCurrentContext, hasCredentials, listContexts } from '../../lib/config.js';
3
4
  export default class ConfigList extends Command {
4
5
  static description = 'List all configured contexts';
5
6
  static examples = ['<%= config.bin %> config list', '<%= config.bin %> config list --json'];
@@ -16,9 +17,11 @@ export default class ConfigList extends Command {
16
17
  if (flags.json) {
17
18
  this.log(JSON.stringify({
18
19
  contexts: contexts.map((c) => ({
19
- authenticated: Boolean(c.tokens),
20
+ auth_type: getAuthType(c),
21
+ authenticated: hasCredentials(c),
20
22
  client_id: c.client_id,
21
23
  environment: c.environment,
24
+ keycloak_base_url: getAuthType(c) === 'oauth2' ? keycloakBaseUrlOf(c) : undefined,
22
25
  name: c.name,
23
26
  tenant_id: c.tenant_id,
24
27
  })),
@@ -35,10 +38,15 @@ export default class ConfigList extends Command {
35
38
  for (const ctx of contexts) {
36
39
  const isCurrent = current?.name === ctx.name;
37
40
  const marker = isCurrent ? '*' : ' ';
38
- const auth = ctx.tokens ? '✓' : '✗';
41
+ const auth = hasCredentials(ctx) ? '✓' : '✗';
42
+ const authType = getAuthType(ctx);
39
43
  this.log(`${marker} ${ctx.name}`);
40
44
  this.log(` Environment: ${ctx.environment}`);
41
- this.log(` Client ID: ${ctx.client_id}`);
45
+ this.log(` Auth: ${authType === 'api_key' ? 'API key (x-api-key)' : 'oauth2'}`);
46
+ if (authType === 'oauth2') {
47
+ this.log(` Keycloak URL: ${keycloakBaseUrlOf(ctx)}`);
48
+ this.log(` Client ID: ${ctx.client_id ?? 'N/A'}`);
49
+ }
42
50
  this.log(` Authenticated: ${auth}`);
43
51
  if (ctx.tenant_id) {
44
52
  this.log(` Tenant ID: ${ctx.tenant_id}`);
@@ -0,0 +1,10 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class ConfigSetApiKey extends Command {
3
+ static description: string;
4
+ static examples: string[];
5
+ static flags: {
6
+ 'api-key': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
+ context: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
+ };
9
+ run(): Promise<void>;
10
+ }
@@ -0,0 +1,49 @@
1
+ import { password } from '@inquirer/prompts';
2
+ import { Command, Flags } from '@oclif/core';
3
+ import { getAuthType, getContext, getCurrentContext, maskApiKey, saveApiKey } from '../../lib/config.js';
4
+ export default class ConfigSetApiKey extends Command {
5
+ static description = 'Set or rotate the API key for a context (switches it to api-key auth)';
6
+ static examples = [
7
+ '<%= config.bin %> config set-api-key',
8
+ '<%= config.bin %> config set-api-key --context ci',
9
+ '<%= config.bin %> config set-api-key --context ci --api-key <key>',
10
+ ];
11
+ static flags = {
12
+ 'api-key': Flags.string({
13
+ description: 'The API key. Prompted for (hidden) if omitted.',
14
+ }),
15
+ context: Flags.string({
16
+ aliases: ['config'],
17
+ char: 'c',
18
+ description: 'Context to update, overriding the current context (alias: --config)',
19
+ env: 'ADERIS_CONTEXT',
20
+ }),
21
+ };
22
+ async run() {
23
+ const { flags } = await this.parse(ConfigSetApiKey);
24
+ const contextName = flags.context ?? getCurrentContext()?.name;
25
+ if (!contextName) {
26
+ this.error('No context configured. Run: aderis config add');
27
+ }
28
+ const context = getContext(contextName);
29
+ if (!context) {
30
+ this.error(`Context "${contextName}" not found.`);
31
+ }
32
+ const apiKey = flags['api-key'] ??
33
+ (await password({
34
+ mask: true,
35
+ message: `API key for "${contextName}":`,
36
+ validate: (value) => (value.trim() ? true : 'API key is required'),
37
+ }));
38
+ if (!apiKey.trim()) {
39
+ this.error('API key is required');
40
+ }
41
+ const wasOAuth = getAuthType(context) === 'oauth2';
42
+ saveApiKey(contextName, apiKey.trim());
43
+ this.log(`API key set for context "${contextName}" (${maskApiKey(apiKey.trim())})`);
44
+ if (wasOAuth) {
45
+ this.log('Auth method switched from oauth2 to api-key; requests now send the x-api-key header.');
46
+ this.log(`Any stored OAuth tokens are kept but unused. Remove them with: aderis auth logout --context ${contextName}`);
47
+ }
48
+ }
49
+ }
@@ -1,6 +1,6 @@
1
1
  import { select } from '@inquirer/prompts';
2
2
  import { Args, Command } from '@oclif/core';
3
- import { getContext, listContexts, setCurrentContext } from '../../lib/config.js';
3
+ import { getContext, hasCredentials, listContexts, missingCredentialsMessage, setCurrentContext, } from '../../lib/config.js';
4
4
  export default class ConfigUse extends Command {
5
5
  static args = {
6
6
  name: Args.string({
@@ -32,9 +32,8 @@ export default class ConfigUse extends Command {
32
32
  }
33
33
  setCurrentContext(contextName);
34
34
  this.log(`Switched to context "${contextName}" (${context.environment})`);
35
- if (!context.tokens) {
36
- this.log(`\nNote: You are not logged in to this context.`);
37
- this.log(`Run: aderis auth login`);
35
+ if (!hasCredentials(context)) {
36
+ this.log(`\nNote: ${missingCredentialsMessage(context)}`);
38
37
  }
39
38
  }
40
39
  }
@@ -33,7 +33,6 @@ export default class CreditCardAccounts extends Command {
33
33
  private runCamt053Import;
34
34
  private runNestedImport;
35
35
  private parseFilterValue;
36
- private filterFields;
37
36
  private sanitizeOutput;
38
37
  private getColumns;
39
38
  private getValue;
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
@@ -39,7 +39,7 @@ export default class CreditCardAccounts extends Command {
39
39
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
40
40
  };
41
41
  static flags = {
42
- context: Flags.string({ char: 'c', description: 'Context to use' }),
42
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
43
43
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
44
44
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
45
45
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -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
  };
@@ -113,9 +113,9 @@ export default class CreditCardAccounts extends Command {
113
113
  }
114
114
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
115
115
  if (!context)
116
- this.error('No context configured. Run: aderis auth login --new');
117
- if (!context.tokens)
118
- this.error('Not logged in. Run: aderis auth login');
116
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
117
+ if (!hasCredentials(context))
118
+ this.error(missingCredentialsMessage(context));
119
119
  const queryParams = {};
120
120
  if (flags.page)
121
121
  queryParams.page = flags.page;
@@ -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);
@@ -358,9 +355,9 @@ export default class CreditCardAccounts extends Command {
358
355
  async runImport(flags) {
359
356
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
360
357
  if (!context)
361
- this.error('No context configured. Run: aderis auth login --new');
362
- if (!context.tokens)
363
- this.error('Not logged in. Run: aderis auth login');
358
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
359
+ if (!hasCredentials(context))
360
+ this.error(missingCredentialsMessage(context));
364
361
  // Get data from file, --data, or --set flags
365
362
  let items = [];
366
363
  if (flags.file) {
@@ -570,9 +567,9 @@ export default class CreditCardAccounts extends Command {
570
567
  async runExport(flags) {
571
568
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
572
569
  if (!context)
573
- this.error('No context configured. Run: aderis auth login --new');
574
- if (!context.tokens)
575
- this.error('Not logged in. Run: aderis auth login');
570
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
571
+ if (!hasCredentials(context))
572
+ this.error(missingCredentialsMessage(context));
576
573
  const listEndpoint = ENDPOINTS['list'];
577
574
  if (!listEndpoint)
578
575
  this.error('Export requires a list endpoint');
@@ -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);
@@ -664,9 +658,9 @@ export default class CreditCardAccounts extends Command {
664
658
  async runCamt053Import(flags) {
665
659
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
666
660
  if (!context)
667
- this.error('No context configured. Run: aderis auth login --new');
668
- if (!context.tokens)
669
- this.error('Not logged in. Run: aderis auth login');
661
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
662
+ if (!hasCredentials(context))
663
+ this.error(missingCredentialsMessage(context));
670
664
  if (!flags.file) {
671
665
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
672
666
  }
@@ -754,9 +748,9 @@ export default class CreditCardAccounts extends Command {
754
748
  }
755
749
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
756
750
  if (!context)
757
- this.error('No context configured. Run: aderis auth login --new');
758
- if (!context.tokens)
759
- this.error('Not logged in. Run: aderis auth login');
751
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
752
+ if (!hasCredentials(context))
753
+ this.error(missingCredentialsMessage(context));
760
754
  // Get data from file, --data, or --set flags
761
755
  let items = [];
762
756
  if (flags.file) {
@@ -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;
@@ -1,31 +1,32 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
7
7
  const HAS_CAMT053 = false;
8
8
  const NESTED_IMPORTS = ["line-items", "notes", "files"];
9
- const SUBCOMMANDS = [...["list", "create", "create-from-orders", "create-from-invoice", "create-invoice", "get", "update", "delete", "pdf", "submit", "approve", "cancel", "deliver", "ship", "send", "create-line-items", "update-line-items-reorder", "update-line-items", "delete-line-items", "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", "create-from-orders", "create-from-invoice", "create-invoice", "get", "update", "delete", "pdf", "submit", "approve", "cancel", "replace", "deliver", "ship", "send", "create-line-items", "update-line-items-reorder", "update-line-items", "delete-line-items", "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
11
  'list': { method: 'GET', path: '/v1/delivery-notes', summary: 'Get all delivery notes with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/delivery-notes', summary: 'Create a new delivery note', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['files', 'notes', 'tagIds', 'lineItems'] },
12
+ 'create': { method: 'POST', path: '/v1/delivery-notes', summary: 'Create a new delivery note', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['files', 'notes', 'tagIds', 'tagCodes', 'lineItems'] },
13
13
  'create-from-orders': { method: 'POST', path: '/v1/delivery-notes/create-from-orders', summary: 'Create a DRAFT delivery note from several sales orders', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['salesOrderIds'] },
14
14
  'create-from-invoice': { method: 'POST', path: '/v1/delivery-notes/create-from-invoice', summary: 'Create a DRAFT delivery note from a sales invoice', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
15
15
  'create-invoice': { method: 'POST', path: '/v1/delivery-notes/create-invoice', summary: 'Create ONE draft sales invoice from several delivery notes (same customer)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['deliveryNoteIds'] },
16
16
  'get': { method: 'GET', path: '/v1/delivery-notes/{id}', summary: 'Get a delivery note by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
- 'update': { method: 'PATCH', path: '/v1/delivery-notes/{id}', summary: 'Update a delivery note', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['files', 'notes', 'tagIds', 'removeFileIds'] },
17
+ 'update': { method: 'PATCH', path: '/v1/delivery-notes/{id}', summary: 'Update a delivery note', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['files', 'notes', 'tagIds', 'tagCodes', 'removeFileIds'] },
18
18
  'delete': { method: 'DELETE', path: '/v1/delivery-notes/{id}', summary: 'Delete a delivery note', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
19
  'pdf': { method: 'GET', path: '/v1/delivery-notes/{id}/pdf', summary: 'Render a delivery note PDF using the configured PDF processor', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
20
  'submit': { method: 'POST', path: '/v1/delivery-notes/{id}/submit', summary: 'Submit a delivery note for approval (DRAFT → PENDING_APPROVAL)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
21
21
  'approve': { method: 'POST', path: '/v1/delivery-notes/{id}/approve', summary: 'Approve a delivery note (DRAFT or PENDING_APPROVAL → APPROVED)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
22
- 'cancel': { method: 'POST', path: '/v1/delivery-notes/{id}/cancel', summary: 'Cancel a delivery note (DRAFT / PENDING_APPROVAL / APPROVED → CANCELLED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
22
+ 'cancel': { method: 'POST', path: '/v1/delivery-notes/{id}/cancel', summary: 'Cancel a delivery note (DRAFT / PENDING_APPROVAL / APPROVED / SHIPPED / DELIVERED → CANCELLED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
+ 'replace': { method: 'POST', path: '/v1/delivery-notes/{id}/replace', summary: 'Replace a delivery note (APPROVED / SHIPPED / DELIVERED / CANCELLED → REPLACED)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
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: [] },
24
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'] },
25
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'] },
26
- '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'] },
27
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'] },
28
- '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'] },
29
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: [] },
30
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: [] },
31
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: [] },
@@ -54,7 +55,7 @@ export default class DeliveryNotes extends Command {
54
55
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
55
56
  };
56
57
  static flags = {
57
- context: Flags.string({ char: 'c', description: 'Context to use' }),
58
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
58
59
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
59
60
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
60
61
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -71,7 +72,7 @@ export default class DeliveryNotes extends Command {
71
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.' }),
72
73
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
73
74
  query: Flags.string({ description: 'Additional query params as JSON' }),
74
- 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)' }),
75
76
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
76
77
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
77
78
  };
@@ -129,9 +130,9 @@ export default class DeliveryNotes extends Command {
129
130
  }
130
131
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
131
132
  if (!context)
132
- this.error('No context configured. Run: aderis auth login --new');
133
- if (!context.tokens)
134
- this.error('Not logged in. Run: aderis auth login');
133
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
134
+ if (!hasCredentials(context))
135
+ this.error(missingCredentialsMessage(context));
135
136
  const queryParams = {};
136
137
  if (flags.page)
137
138
  queryParams.page = flags.page;
@@ -143,6 +144,8 @@ export default class DeliveryNotes extends Command {
143
144
  queryParams.search = flags.search;
144
145
  if (flags['sort-by'])
145
146
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
147
+ if (flags.fields)
148
+ queryParams.fields = flags.fields;
146
149
  if (flags.query) {
147
150
  try {
148
151
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -345,11 +348,6 @@ export default class DeliveryNotes extends Command {
345
348
  output = obj[arrayKeys[0]];
346
349
  }
347
350
  }
348
- // Filter fields if --fields flag is provided
349
- if (flags.fields) {
350
- const fieldList = flags.fields.split(',').map(f => f.trim());
351
- output = this.filterFields(output, fieldList);
352
- }
353
351
  // Sanitize output if requested
354
352
  if (flags.sanitize) {
355
353
  output = this.sanitizeOutput(output);
@@ -374,9 +372,9 @@ export default class DeliveryNotes extends Command {
374
372
  async runImport(flags) {
375
373
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
376
374
  if (!context)
377
- this.error('No context configured. Run: aderis auth login --new');
378
- if (!context.tokens)
379
- this.error('Not logged in. Run: aderis auth login');
375
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
376
+ if (!hasCredentials(context))
377
+ this.error(missingCredentialsMessage(context));
380
378
  // Get data from file, --data, or --set flags
381
379
  let items = [];
382
380
  if (flags.file) {
@@ -586,9 +584,9 @@ export default class DeliveryNotes extends Command {
586
584
  async runExport(flags) {
587
585
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
588
586
  if (!context)
589
- this.error('No context configured. Run: aderis auth login --new');
590
- if (!context.tokens)
591
- this.error('Not logged in. Run: aderis auth login');
587
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
588
+ if (!hasCredentials(context))
589
+ this.error(missingCredentialsMessage(context));
592
590
  const listEndpoint = ENDPOINTS['list'];
593
591
  if (!listEndpoint)
594
592
  this.error('Export requires a list endpoint');
@@ -604,6 +602,8 @@ export default class DeliveryNotes extends Command {
604
602
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
605
603
  if (flags.include)
606
604
  baseParams.include = flags.include;
605
+ if (flags.fields)
606
+ baseParams.fields = flags.fields;
607
607
  if (flags.query) {
608
608
  try {
609
609
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -658,12 +658,7 @@ export default class DeliveryNotes extends Command {
658
658
  }
659
659
  }
660
660
  process.stderr.write(' done\n');
661
- // Filter fields if specified
662
661
  let output = allItems;
663
- if (flags.fields) {
664
- const fieldList = flags.fields.split(',').map(f => f.trim());
665
- output = this.filterFields(allItems, fieldList);
666
- }
667
662
  // Sanitize output if requested
668
663
  if (flags.sanitize) {
669
664
  output = this.sanitizeOutput(output);
@@ -680,9 +675,9 @@ export default class DeliveryNotes extends Command {
680
675
  async runCamt053Import(flags) {
681
676
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
682
677
  if (!context)
683
- this.error('No context configured. Run: aderis auth login --new');
684
- if (!context.tokens)
685
- this.error('Not logged in. Run: aderis auth login');
678
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
679
+ if (!hasCredentials(context))
680
+ this.error(missingCredentialsMessage(context));
686
681
  if (!flags.file) {
687
682
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
688
683
  }
@@ -770,9 +765,9 @@ export default class DeliveryNotes extends Command {
770
765
  }
771
766
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
772
767
  if (!context)
773
- this.error('No context configured. Run: aderis auth login --new');
774
- if (!context.tokens)
775
- this.error('Not logged in. Run: aderis auth login');
768
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
769
+ if (!hasCredentials(context))
770
+ this.error(missingCredentialsMessage(context));
776
771
  // Get data from file, --data, or --set flags
777
772
  let items = [];
778
773
  if (flags.file) {
@@ -992,56 +987,6 @@ export default class DeliveryNotes extends Command {
992
987
  return `\$${op}`;
993
988
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
994
989
  }
995
- filterFields(data, fields) {
996
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
997
- const pick = (obj, keys) => {
998
- // Group keys by their first segment so sibling sub-paths
999
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
1000
- // and don't clobber each other on merge.
1001
- const directKeys = new Set();
1002
- const nestedKeys = new Map();
1003
- for (const key of keys) {
1004
- if (key.split('.').some(isUnsafeKey))
1005
- continue;
1006
- if (key.includes('.')) {
1007
- const [first, ...rest] = key.split('.');
1008
- if (isUnsafeKey(first))
1009
- continue;
1010
- const list = nestedKeys.get(first);
1011
- if (list) {
1012
- list.push(rest.join('.'));
1013
- }
1014
- else {
1015
- nestedKeys.set(first, [rest.join('.')]);
1016
- }
1017
- }
1018
- else {
1019
- directKeys.add(key);
1020
- }
1021
- }
1022
- const result = {};
1023
- for (const key of directKeys) {
1024
- if (key in obj)
1025
- result[key] = obj[key];
1026
- }
1027
- for (const [first, restKeys] of nestedKeys) {
1028
- const val = obj[first];
1029
- if (!val || typeof val !== 'object')
1030
- continue;
1031
- if (Array.isArray(val)) {
1032
- result[first] = val.map(item => pick(item, restKeys));
1033
- }
1034
- else {
1035
- result[first] = pick(val, restKeys);
1036
- }
1037
- }
1038
- return result;
1039
- };
1040
- if (Array.isArray(data)) {
1041
- return data.map(item => pick(item, fields));
1042
- }
1043
- return pick(data, fields);
1044
- }
1045
990
  sanitizeOutput(data) {
1046
991
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1047
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;