@aderis-erp/cli 1.0.1 → 1.0.3
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.
- package/README.md +1 -1
- package/dist/commands/access-groups.js +36 -22
- package/dist/commands/account-transactions.js +30 -18
- package/dist/commands/accounts.js +30 -18
- package/dist/commands/agent-runs.js +33 -21
- package/dist/commands/{processing-logs.d.ts → async-endpoints-internal.d.ts} +2 -2
- package/dist/commands/{processing-logs.js → async-endpoints-internal.js} +39 -28
- package/dist/commands/audit-log.js +30 -18
- package/dist/commands/auth/tenant.d.ts +1 -0
- package/dist/commands/auth/tenant.js +23 -7
- package/dist/commands/bank-accounts.js +30 -18
- package/dist/commands/bank-integrations.d.ts +2 -0
- package/dist/commands/bank-integrations.js +41 -19
- package/dist/commands/business-partners---contacts.js +30 -18
- package/dist/commands/business-partners.js +30 -18
- package/dist/commands/credit-card-accounts.js +30 -18
- package/dist/commands/documents.js +36 -22
- package/dist/commands/dunning-configs.js +30 -18
- package/dist/commands/dunning-reminders.js +30 -18
- package/dist/commands/dunning-runs.js +30 -18
- package/dist/commands/employees.js +30 -18
- package/dist/commands/event-processor-mappings.js +30 -18
- package/dist/commands/files-internal.js +30 -18
- package/dist/commands/health.js +30 -18
- package/dist/commands/inbox.js +34 -20
- package/dist/commands/integrations.js +30 -18
- package/dist/commands/item-categories.js +30 -18
- package/dist/commands/items.js +30 -18
- package/dist/commands/journal-lines.js +30 -18
- package/dist/commands/journals.js +30 -18
- package/dist/commands/ledgers.js +30 -18
- package/dist/commands/office-locations.js +30 -18
- package/dist/commands/payment-method-ledger-mappings.js +30 -18
- package/dist/commands/payment-methods.js +30 -18
- package/dist/commands/payment-runs.js +30 -18
- package/dist/commands/payment-terms.js +30 -18
- package/dist/commands/price-lists.js +30 -18
- package/dist/commands/processor-mappings.js +30 -18
- package/dist/commands/processors.js +31 -19
- package/dist/commands/reconciliation.js +30 -18
- package/dist/commands/reports.js +30 -18
- package/dist/commands/salary-types.js +30 -18
- package/dist/commands/sales-invoices.js +32 -19
- package/dist/commands/sales-orders.js +33 -19
- package/dist/commands/switch.d.ts +1 -0
- package/dist/commands/switch.js +58 -3
- package/dist/commands/tags.js +30 -18
- package/dist/commands/tax-codes.js +30 -18
- package/dist/commands/tax-matrix.js +30 -18
- package/dist/commands/tenants.js +30 -18
- package/dist/commands/text-templates.js +30 -18
- package/dist/commands/tools.js +30 -18
- package/dist/commands/vendor-invoices.js +33 -19
- package/dist/commands/webhooks.js +30 -18
- package/dist/commands/workflows.js +30 -18
- package/dist/index 2.js +1 -0
- package/dist/index.d 2.ts +1 -0
- package/dist/lib/auth.d.ts +16 -1
- package/dist/lib/auth.js +167 -50
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +6 -0
- package/oclif.manifest.json +65 -385
- package/package.json +2 -2
- package/dist/commands/account-statement-runs.d.ts +0 -40
- package/dist/commands/account-statement-runs.js +0 -1004
- package/dist/commands/bank-statements.d.ts +0 -40
- package/dist/commands/bank-statements.js +0 -998
package/README.md
CHANGED
|
@@ -3,24 +3,26 @@ import { apiRequest, ApiError } from '../lib/api-client.js';
|
|
|
3
3
|
import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
|
-
const HAS_EXPORT =
|
|
6
|
+
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "get", "update", "delete"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'
|
|
11
|
+
'list': { method: 'GET', path: '/v1/access-groups', summary: 'List access groups (paginated)', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/access-groups', summary: 'Create a new access group', pathParams: [], hasBody: true, isMultipart: false },
|
|
13
|
-
'get
|
|
13
|
+
'get': { method: 'GET', path: '/v1/access-groups/{id}', summary: 'Get a single access group by ID', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
14
14
|
'update': { method: 'PATCH', path: '/v1/access-groups/{id}', summary: 'Update an existing access group', pathParams: ['id'], hasBody: true, isMultipart: false },
|
|
15
15
|
'delete': { method: 'DELETE', path: '/v1/access-groups/{id}', summary: 'Delete an access group', pathParams: ['id'], hasBody: false, isMultipart: false },
|
|
16
16
|
};
|
|
17
17
|
export default class AccessGroups extends Command {
|
|
18
18
|
static description = 'Manage access groups';
|
|
19
19
|
static examples = [
|
|
20
|
+
'<%= config.bin %> access-groups list',
|
|
20
21
|
'<%= config.bin %> access-groups get <id>',
|
|
21
22
|
'<%= config.bin %> access-groups create --data \'{...}\'',
|
|
22
23
|
'<%= config.bin %> access-groups update <id> --set field=value',
|
|
23
24
|
'<%= config.bin %> access-groups import --file data.json',
|
|
25
|
+
'<%= config.bin %> access-groups export --csv > access-groups.csv',
|
|
24
26
|
];
|
|
25
27
|
static args = {
|
|
26
28
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
|
@@ -817,32 +819,44 @@ export default class AccessGroups extends Command {
|
|
|
817
819
|
filterFields(data, fields) {
|
|
818
820
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
819
821
|
const pick = (obj, keys) => {
|
|
820
|
-
|
|
822
|
+
// Group keys by their first segment so sibling sub-paths
|
|
823
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
824
|
+
// and don't clobber each other on merge.
|
|
825
|
+
const directKeys = new Set();
|
|
826
|
+
const nestedKeys = new Map();
|
|
821
827
|
for (const key of keys) {
|
|
822
828
|
if (key.split('.').some(isUnsafeKey))
|
|
823
829
|
continue;
|
|
824
830
|
if (key.includes('.')) {
|
|
825
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
826
831
|
const [first, ...rest] = key.split('.');
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
833
|
-
result[first] = val.map((item, i) => ({
|
|
834
|
-
...(existing[i] || {}),
|
|
835
|
-
...pick(item, [restKey]),
|
|
836
|
-
}));
|
|
837
|
-
}
|
|
838
|
-
else {
|
|
839
|
-
const nested = pick(val, [restKey]);
|
|
840
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
841
|
-
}
|
|
832
|
+
if (isUnsafeKey(first))
|
|
833
|
+
continue;
|
|
834
|
+
const list = nestedKeys.get(first);
|
|
835
|
+
if (list) {
|
|
836
|
+
list.push(rest.join('.'));
|
|
842
837
|
}
|
|
838
|
+
else {
|
|
839
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
directKeys.add(key);
|
|
843
844
|
}
|
|
844
|
-
|
|
845
|
+
}
|
|
846
|
+
const result = {};
|
|
847
|
+
for (const key of directKeys) {
|
|
848
|
+
if (key in obj)
|
|
845
849
|
result[key] = obj[key];
|
|
850
|
+
}
|
|
851
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
852
|
+
const val = obj[first];
|
|
853
|
+
if (!val || typeof val !== 'object')
|
|
854
|
+
continue;
|
|
855
|
+
if (Array.isArray(val)) {
|
|
856
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
857
|
+
}
|
|
858
|
+
else {
|
|
859
|
+
result[first] = pick(val, restKeys);
|
|
846
860
|
}
|
|
847
861
|
}
|
|
848
862
|
return result;
|
|
@@ -833,32 +833,44 @@ export default class AccountTransactions extends Command {
|
|
|
833
833
|
filterFields(data, fields) {
|
|
834
834
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
835
835
|
const pick = (obj, keys) => {
|
|
836
|
-
|
|
836
|
+
// Group keys by their first segment so sibling sub-paths
|
|
837
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
838
|
+
// and don't clobber each other on merge.
|
|
839
|
+
const directKeys = new Set();
|
|
840
|
+
const nestedKeys = new Map();
|
|
837
841
|
for (const key of keys) {
|
|
838
842
|
if (key.split('.').some(isUnsafeKey))
|
|
839
843
|
continue;
|
|
840
844
|
if (key.includes('.')) {
|
|
841
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
842
845
|
const [first, ...rest] = key.split('.');
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
849
|
-
result[first] = val.map((item, i) => ({
|
|
850
|
-
...(existing[i] || {}),
|
|
851
|
-
...pick(item, [restKey]),
|
|
852
|
-
}));
|
|
853
|
-
}
|
|
854
|
-
else {
|
|
855
|
-
const nested = pick(val, [restKey]);
|
|
856
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
857
|
-
}
|
|
846
|
+
if (isUnsafeKey(first))
|
|
847
|
+
continue;
|
|
848
|
+
const list = nestedKeys.get(first);
|
|
849
|
+
if (list) {
|
|
850
|
+
list.push(rest.join('.'));
|
|
858
851
|
}
|
|
852
|
+
else {
|
|
853
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
directKeys.add(key);
|
|
859
858
|
}
|
|
860
|
-
|
|
859
|
+
}
|
|
860
|
+
const result = {};
|
|
861
|
+
for (const key of directKeys) {
|
|
862
|
+
if (key in obj)
|
|
861
863
|
result[key] = obj[key];
|
|
864
|
+
}
|
|
865
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
866
|
+
const val = obj[first];
|
|
867
|
+
if (!val || typeof val !== 'object')
|
|
868
|
+
continue;
|
|
869
|
+
if (Array.isArray(val)) {
|
|
870
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
result[first] = pick(val, restKeys);
|
|
862
874
|
}
|
|
863
875
|
}
|
|
864
876
|
return result;
|
|
@@ -825,32 +825,44 @@ export default class Accounts extends Command {
|
|
|
825
825
|
filterFields(data, fields) {
|
|
826
826
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
827
827
|
const pick = (obj, keys) => {
|
|
828
|
-
|
|
828
|
+
// Group keys by their first segment so sibling sub-paths
|
|
829
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
830
|
+
// and don't clobber each other on merge.
|
|
831
|
+
const directKeys = new Set();
|
|
832
|
+
const nestedKeys = new Map();
|
|
829
833
|
for (const key of keys) {
|
|
830
834
|
if (key.split('.').some(isUnsafeKey))
|
|
831
835
|
continue;
|
|
832
836
|
if (key.includes('.')) {
|
|
833
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
834
837
|
const [first, ...rest] = key.split('.');
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
841
|
-
result[first] = val.map((item, i) => ({
|
|
842
|
-
...(existing[i] || {}),
|
|
843
|
-
...pick(item, [restKey]),
|
|
844
|
-
}));
|
|
845
|
-
}
|
|
846
|
-
else {
|
|
847
|
-
const nested = pick(val, [restKey]);
|
|
848
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
849
|
-
}
|
|
838
|
+
if (isUnsafeKey(first))
|
|
839
|
+
continue;
|
|
840
|
+
const list = nestedKeys.get(first);
|
|
841
|
+
if (list) {
|
|
842
|
+
list.push(rest.join('.'));
|
|
850
843
|
}
|
|
844
|
+
else {
|
|
845
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
directKeys.add(key);
|
|
851
850
|
}
|
|
852
|
-
|
|
851
|
+
}
|
|
852
|
+
const result = {};
|
|
853
|
+
for (const key of directKeys) {
|
|
854
|
+
if (key in obj)
|
|
853
855
|
result[key] = obj[key];
|
|
856
|
+
}
|
|
857
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
858
|
+
const val = obj[first];
|
|
859
|
+
if (!val || typeof val !== 'object')
|
|
860
|
+
continue;
|
|
861
|
+
if (Array.isArray(val)) {
|
|
862
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
863
|
+
}
|
|
864
|
+
else {
|
|
865
|
+
result[first] = pick(val, restKeys);
|
|
854
866
|
}
|
|
855
867
|
}
|
|
856
868
|
return result;
|
|
@@ -8,9 +8,9 @@ const HAS_CAMT053 = false;
|
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
9
|
const SUBCOMMANDS = [...["list", "get", "retry"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'list': { method: 'GET', path: '/v1/agent-runs', summary: 'List agent runs for the current tenant
|
|
12
|
-
'get': { method: 'GET', path: '/v1/agent-runs/{runId}', summary: 'Get an agent-run detail by id
|
|
13
|
-
'retry': { method: 'POST', path: '/v1/agent-runs/{runId}/retry', summary: 'Retry an agent run from NEEDS_REVIEW with a reviewer instruction
|
|
11
|
+
'list': { method: 'GET', path: '/v1/agent-runs', summary: 'List agent runs for the current tenant', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
+
'get': { method: 'GET', path: '/v1/agent-runs/{runId}', summary: 'Get an agent-run detail by id', pathParams: ['runId'], hasBody: false, isMultipart: false },
|
|
13
|
+
'retry': { method: 'POST', path: '/v1/agent-runs/{runId}/retry', summary: 'Retry an agent run from NEEDS_REVIEW with a reviewer instruction', pathParams: ['runId'], hasBody: true, isMultipart: false },
|
|
14
14
|
};
|
|
15
15
|
export default class AgentRuns extends Command {
|
|
16
16
|
static description = 'Manage agent runs';
|
|
@@ -814,32 +814,44 @@ export default class AgentRuns extends Command {
|
|
|
814
814
|
filterFields(data, fields) {
|
|
815
815
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
816
816
|
const pick = (obj, keys) => {
|
|
817
|
-
|
|
817
|
+
// Group keys by their first segment so sibling sub-paths
|
|
818
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
819
|
+
// and don't clobber each other on merge.
|
|
820
|
+
const directKeys = new Set();
|
|
821
|
+
const nestedKeys = new Map();
|
|
818
822
|
for (const key of keys) {
|
|
819
823
|
if (key.split('.').some(isUnsafeKey))
|
|
820
824
|
continue;
|
|
821
825
|
if (key.includes('.')) {
|
|
822
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
823
826
|
const [first, ...rest] = key.split('.');
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
830
|
-
result[first] = val.map((item, i) => ({
|
|
831
|
-
...(existing[i] || {}),
|
|
832
|
-
...pick(item, [restKey]),
|
|
833
|
-
}));
|
|
834
|
-
}
|
|
835
|
-
else {
|
|
836
|
-
const nested = pick(val, [restKey]);
|
|
837
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
838
|
-
}
|
|
827
|
+
if (isUnsafeKey(first))
|
|
828
|
+
continue;
|
|
829
|
+
const list = nestedKeys.get(first);
|
|
830
|
+
if (list) {
|
|
831
|
+
list.push(rest.join('.'));
|
|
839
832
|
}
|
|
833
|
+
else {
|
|
834
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
else {
|
|
838
|
+
directKeys.add(key);
|
|
840
839
|
}
|
|
841
|
-
|
|
840
|
+
}
|
|
841
|
+
const result = {};
|
|
842
|
+
for (const key of directKeys) {
|
|
843
|
+
if (key in obj)
|
|
842
844
|
result[key] = obj[key];
|
|
845
|
+
}
|
|
846
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
847
|
+
const val = obj[first];
|
|
848
|
+
if (!val || typeof val !== 'object')
|
|
849
|
+
continue;
|
|
850
|
+
if (Array.isArray(val)) {
|
|
851
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
852
|
+
}
|
|
853
|
+
else {
|
|
854
|
+
result[first] = pick(val, restKeys);
|
|
843
855
|
}
|
|
844
856
|
}
|
|
845
857
|
return result;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
export default class
|
|
2
|
+
export default class AsyncEndpointsInternal extends Command {
|
|
3
3
|
static description: string;
|
|
4
|
-
static examples:
|
|
4
|
+
static examples: never[];
|
|
5
5
|
static args: {
|
|
6
6
|
action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
7
|
id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
@@ -6,15 +6,14 @@ const HAS_IMPORT = false;
|
|
|
6
6
|
const HAS_EXPORT = false;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
9
|
+
const SUBCOMMANDS = [...["webhook-events", "processor-jobs"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'
|
|
11
|
+
'webhook-events': { method: 'POST', path: '/v1/pubsub/webhook-events', summary: '[INTERNAL] Async push endpoint for webhook event delivery', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
|
+
'processor-jobs': { method: 'POST', path: '/v1/pubsub/processor-jobs', summary: '[INTERNAL] Async push endpoint for processor-job.v1 envelopes', pathParams: [], hasBody: false, isMultipart: false },
|
|
12
13
|
};
|
|
13
|
-
export default class
|
|
14
|
-
static description = 'Manage
|
|
15
|
-
static examples = [
|
|
16
|
-
'<%= config.bin %> processing-logs get <id>',
|
|
17
|
-
];
|
|
14
|
+
export default class AsyncEndpointsInternal extends Command {
|
|
15
|
+
static description = 'Manage async endpoints internal';
|
|
16
|
+
static examples = [];
|
|
18
17
|
static args = {
|
|
19
18
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
|
20
19
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
@@ -39,7 +38,7 @@ export default class ProcessingLogs extends Command {
|
|
|
39
38
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
40
39
|
};
|
|
41
40
|
async run() {
|
|
42
|
-
const { args, flags } = await this.parse(
|
|
41
|
+
const { args, flags } = await this.parse(AsyncEndpointsInternal);
|
|
43
42
|
// Handle import action specially
|
|
44
43
|
if (args.action === 'import') {
|
|
45
44
|
if (!HAS_IMPORT)
|
|
@@ -85,7 +84,7 @@ export default class ProcessingLogs extends Command {
|
|
|
85
84
|
// First path param always comes from positional argument
|
|
86
85
|
value = args.id;
|
|
87
86
|
if (!value)
|
|
88
|
-
this.error('Missing required argument: id. Usage: aderis
|
|
87
|
+
this.error('Missing required argument: id. Usage: aderis async-endpoints-internal <action> <id>');
|
|
89
88
|
}
|
|
90
89
|
else {
|
|
91
90
|
const flagName = param.replace(/\./g, '-').replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
@@ -648,7 +647,7 @@ export default class ProcessingLogs extends Command {
|
|
|
648
647
|
}
|
|
649
648
|
async runNestedImport(suffix, parentId, flags) {
|
|
650
649
|
if (!parentId) {
|
|
651
|
-
this.error(`Missing required argument: id. Usage: aderis
|
|
650
|
+
this.error(`Missing required argument: id. Usage: aderis async-endpoints-internal import-${suffix} <parent-id> --file data.json`);
|
|
652
651
|
}
|
|
653
652
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
654
653
|
if (!context)
|
|
@@ -810,32 +809,44 @@ export default class ProcessingLogs extends Command {
|
|
|
810
809
|
filterFields(data, fields) {
|
|
811
810
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
812
811
|
const pick = (obj, keys) => {
|
|
813
|
-
|
|
812
|
+
// Group keys by their first segment so sibling sub-paths
|
|
813
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
814
|
+
// and don't clobber each other on merge.
|
|
815
|
+
const directKeys = new Set();
|
|
816
|
+
const nestedKeys = new Map();
|
|
814
817
|
for (const key of keys) {
|
|
815
818
|
if (key.split('.').some(isUnsafeKey))
|
|
816
819
|
continue;
|
|
817
820
|
if (key.includes('.')) {
|
|
818
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
819
821
|
const [first, ...rest] = key.split('.');
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
826
|
-
result[first] = val.map((item, i) => ({
|
|
827
|
-
...(existing[i] || {}),
|
|
828
|
-
...pick(item, [restKey]),
|
|
829
|
-
}));
|
|
830
|
-
}
|
|
831
|
-
else {
|
|
832
|
-
const nested = pick(val, [restKey]);
|
|
833
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
834
|
-
}
|
|
822
|
+
if (isUnsafeKey(first))
|
|
823
|
+
continue;
|
|
824
|
+
const list = nestedKeys.get(first);
|
|
825
|
+
if (list) {
|
|
826
|
+
list.push(rest.join('.'));
|
|
835
827
|
}
|
|
828
|
+
else {
|
|
829
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
directKeys.add(key);
|
|
836
834
|
}
|
|
837
|
-
|
|
835
|
+
}
|
|
836
|
+
const result = {};
|
|
837
|
+
for (const key of directKeys) {
|
|
838
|
+
if (key in obj)
|
|
838
839
|
result[key] = obj[key];
|
|
840
|
+
}
|
|
841
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
842
|
+
const val = obj[first];
|
|
843
|
+
if (!val || typeof val !== 'object')
|
|
844
|
+
continue;
|
|
845
|
+
if (Array.isArray(val)) {
|
|
846
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
result[first] = pick(val, restKeys);
|
|
839
850
|
}
|
|
840
851
|
}
|
|
841
852
|
return result;
|
|
@@ -813,32 +813,44 @@ export default class AuditLog extends Command {
|
|
|
813
813
|
filterFields(data, fields) {
|
|
814
814
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
815
815
|
const pick = (obj, keys) => {
|
|
816
|
-
|
|
816
|
+
// Group keys by their first segment so sibling sub-paths
|
|
817
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
818
|
+
// and don't clobber each other on merge.
|
|
819
|
+
const directKeys = new Set();
|
|
820
|
+
const nestedKeys = new Map();
|
|
817
821
|
for (const key of keys) {
|
|
818
822
|
if (key.split('.').some(isUnsafeKey))
|
|
819
823
|
continue;
|
|
820
824
|
if (key.includes('.')) {
|
|
821
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
822
825
|
const [first, ...rest] = key.split('.');
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
829
|
-
result[first] = val.map((item, i) => ({
|
|
830
|
-
...(existing[i] || {}),
|
|
831
|
-
...pick(item, [restKey]),
|
|
832
|
-
}));
|
|
833
|
-
}
|
|
834
|
-
else {
|
|
835
|
-
const nested = pick(val, [restKey]);
|
|
836
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
837
|
-
}
|
|
826
|
+
if (isUnsafeKey(first))
|
|
827
|
+
continue;
|
|
828
|
+
const list = nestedKeys.get(first);
|
|
829
|
+
if (list) {
|
|
830
|
+
list.push(rest.join('.'));
|
|
838
831
|
}
|
|
832
|
+
else {
|
|
833
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
else {
|
|
837
|
+
directKeys.add(key);
|
|
839
838
|
}
|
|
840
|
-
|
|
839
|
+
}
|
|
840
|
+
const result = {};
|
|
841
|
+
for (const key of directKeys) {
|
|
842
|
+
if (key in obj)
|
|
841
843
|
result[key] = obj[key];
|
|
844
|
+
}
|
|
845
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
846
|
+
const val = obj[first];
|
|
847
|
+
if (!val || typeof val !== 'object')
|
|
848
|
+
continue;
|
|
849
|
+
if (Array.isArray(val)) {
|
|
850
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
result[first] = pick(val, restKeys);
|
|
842
854
|
}
|
|
843
855
|
}
|
|
844
856
|
return result;
|
|
@@ -74,10 +74,10 @@ export default class AuthTenant extends Command {
|
|
|
74
74
|
const tenant = tenants[0];
|
|
75
75
|
this.log(`Only one tenant available: ${tenant.name}`);
|
|
76
76
|
if (tenant.tenantId === current?.tenantId) {
|
|
77
|
-
this.log(
|
|
77
|
+
this.log(`Already using this tenant (${tenant.name}, ${tenant.tenantId})`);
|
|
78
78
|
}
|
|
79
79
|
else {
|
|
80
|
-
await this.switchTenant(contextName, tenant.tenantId);
|
|
80
|
+
await this.switchTenant(contextName, tenant.tenantId, tenant.name);
|
|
81
81
|
}
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
@@ -106,11 +106,13 @@ export default class AuthTenant extends Command {
|
|
|
106
106
|
choices,
|
|
107
107
|
message: 'Select a tenant:',
|
|
108
108
|
});
|
|
109
|
+
const selectedTenantName = tenants.find((t) => t.tenantId === selectedTenant)?.name;
|
|
109
110
|
if (selectedTenant === current?.tenantId) {
|
|
110
|
-
|
|
111
|
+
const label = selectedTenantName ? `${selectedTenantName}, ${selectedTenant}` : selectedTenant;
|
|
112
|
+
this.log(`Already using this tenant (${label})`);
|
|
111
113
|
return;
|
|
112
114
|
}
|
|
113
|
-
await this.switchTenant(contextName, selectedTenant);
|
|
115
|
+
await this.switchTenant(contextName, selectedTenant, selectedTenantName);
|
|
114
116
|
}
|
|
115
117
|
async listTenants(contextName, asJson) {
|
|
116
118
|
const tenants = await listTenants(contextName);
|
|
@@ -152,11 +154,14 @@ export default class AuthTenant extends Command {
|
|
|
152
154
|
this.log(`Tenant ID: ${current.tenantId}`);
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
|
-
async switchTenant(contextName, tenantId) {
|
|
156
|
-
|
|
157
|
+
async switchTenant(contextName, tenantId, tenantName) {
|
|
158
|
+
const requested = tenantName ? `${tenantName} (${tenantId})` : tenantId;
|
|
159
|
+
this.log(`Switching to tenant ${requested}...`);
|
|
157
160
|
try {
|
|
158
161
|
const tokens = await switchTenant(contextName, tenantId);
|
|
159
|
-
this.
|
|
162
|
+
const resolvedName = tenantName ?? (await this.resolveTenantName(contextName, tokens.tenant_id));
|
|
163
|
+
const display = resolvedName ? `${resolvedName} (${tokens.tenant_id})` : tokens.tenant_id;
|
|
164
|
+
this.log(`Successfully switched to tenant ${display}`);
|
|
160
165
|
}
|
|
161
166
|
catch (error) {
|
|
162
167
|
if (error instanceof Error) {
|
|
@@ -165,4 +170,15 @@ export default class AuthTenant extends Command {
|
|
|
165
170
|
throw error;
|
|
166
171
|
}
|
|
167
172
|
}
|
|
173
|
+
async resolveTenantName(contextName, tenantId) {
|
|
174
|
+
if (!tenantId)
|
|
175
|
+
return undefined;
|
|
176
|
+
try {
|
|
177
|
+
const tenants = await listTenants(contextName);
|
|
178
|
+
return tenants.find((t) => t.tenantId === tenantId)?.name;
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
168
184
|
}
|
|
@@ -833,32 +833,44 @@ export default class BankAccounts extends Command {
|
|
|
833
833
|
filterFields(data, fields) {
|
|
834
834
|
const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
|
|
835
835
|
const pick = (obj, keys) => {
|
|
836
|
-
|
|
836
|
+
// Group keys by their first segment so sibling sub-paths
|
|
837
|
+
// (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
|
|
838
|
+
// and don't clobber each other on merge.
|
|
839
|
+
const directKeys = new Set();
|
|
840
|
+
const nestedKeys = new Map();
|
|
837
841
|
for (const key of keys) {
|
|
838
842
|
if (key.split('.').some(isUnsafeKey))
|
|
839
843
|
continue;
|
|
840
844
|
if (key.includes('.')) {
|
|
841
|
-
// Handle nested fields like 'customer.name' or 'allocations.salesInvoiceId'
|
|
842
845
|
const [first, ...rest] = key.split('.');
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
const existing = Array.isArray(result[first]) ? result[first] : [];
|
|
849
|
-
result[first] = val.map((item, i) => ({
|
|
850
|
-
...(existing[i] || {}),
|
|
851
|
-
...pick(item, [restKey]),
|
|
852
|
-
}));
|
|
853
|
-
}
|
|
854
|
-
else {
|
|
855
|
-
const nested = pick(val, [restKey]);
|
|
856
|
-
result[first] = { ...(result[first] || {}), ...nested };
|
|
857
|
-
}
|
|
846
|
+
if (isUnsafeKey(first))
|
|
847
|
+
continue;
|
|
848
|
+
const list = nestedKeys.get(first);
|
|
849
|
+
if (list) {
|
|
850
|
+
list.push(rest.join('.'));
|
|
858
851
|
}
|
|
852
|
+
else {
|
|
853
|
+
nestedKeys.set(first, [rest.join('.')]);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
else {
|
|
857
|
+
directKeys.add(key);
|
|
859
858
|
}
|
|
860
|
-
|
|
859
|
+
}
|
|
860
|
+
const result = {};
|
|
861
|
+
for (const key of directKeys) {
|
|
862
|
+
if (key in obj)
|
|
861
863
|
result[key] = obj[key];
|
|
864
|
+
}
|
|
865
|
+
for (const [first, restKeys] of nestedKeys) {
|
|
866
|
+
const val = obj[first];
|
|
867
|
+
if (!val || typeof val !== 'object')
|
|
868
|
+
continue;
|
|
869
|
+
if (Array.isArray(val)) {
|
|
870
|
+
result[first] = val.map(item => pick(item, restKeys));
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
result[first] = pick(val, restKeys);
|
|
862
874
|
}
|
|
863
875
|
}
|
|
864
876
|
return result;
|
|
@@ -14,6 +14,8 @@ export default class BankIntegrations 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
|
+
'import-run-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'statement-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
19
|
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
20
|
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
21
|
include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|