@aderis-erp/cli 1.0.14 → 1.0.15
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/dist/commands/access-groups.js +17 -17
- package/dist/commands/account-transaction-allocations.js +17 -17
- package/dist/commands/account-transactions.js +19 -19
- package/dist/commands/accounts.js +19 -19
- package/dist/commands/agent-platform.js +19 -18
- package/dist/commands/analytics.d.ts +40 -0
- package/dist/commands/{documents.js → analytics.js} +29 -39
- package/dist/commands/audit-log.js +17 -17
- package/dist/commands/auth/login.js +11 -2
- package/dist/commands/auth/logout.d.ts +2 -0
- package/dist/commands/auth/logout.js +19 -6
- package/dist/commands/auth/status.js +26 -12
- package/dist/commands/auth/tenant.js +12 -3
- package/dist/commands/auth.js +32 -17
- package/dist/commands/bank-accounts.js +17 -17
- package/dist/commands/bank-integrations.js +17 -17
- package/dist/commands/business-partners.js +25 -22
- package/dist/commands/chat.js +17 -17
- package/dist/commands/config/add.d.ts +9 -0
- package/dist/commands/config/add.js +64 -2
- package/dist/commands/config/current.js +9 -4
- package/dist/commands/config/list.js +9 -4
- package/dist/commands/config/set-api-key.d.ts +10 -0
- package/dist/commands/config/set-api-key.js +49 -0
- package/dist/commands/config/use.js +3 -4
- package/dist/commands/credit-card-accounts.js +17 -17
- package/dist/commands/delivery-notes.js +22 -21
- package/dist/commands/dunning-configs.js +17 -17
- package/dist/commands/dunning-reminders.js +17 -17
- package/dist/commands/dunning-runs.js +17 -17
- package/dist/commands/email-transactions.js +17 -17
- package/dist/commands/employees.js +19 -19
- package/dist/commands/entity-configurations.js +17 -17
- package/dist/commands/event-processor-mappings.js +17 -17
- package/dist/commands/{documents.d.ts → files.d.ts} +1 -1
- package/dist/commands/{files-internal.js → files.js} +35 -29
- package/dist/commands/health.js +17 -17
- package/dist/commands/inbox.js +17 -17
- package/dist/commands/integrations.js +17 -17
- package/dist/commands/item-categories.js +17 -17
- package/dist/commands/items.js +19 -19
- package/dist/commands/journal-lines.js +17 -17
- package/dist/commands/journals.js +21 -20
- package/dist/commands/ledgers.js +21 -18
- package/dist/commands/office-locations.js +17 -17
- package/dist/commands/payment-methods.js +17 -17
- package/dist/commands/payment-runs.js +19 -18
- package/dist/commands/payment-terms.js +17 -17
- package/dist/commands/payments.js +17 -17
- package/dist/commands/price-lists.js +17 -17
- package/dist/commands/processor-mappings.js +17 -17
- package/dist/commands/processors.js +17 -17
- package/dist/commands/purchase-order-types.js +17 -17
- package/dist/commands/purchase-orders.d.ts +1 -0
- package/dist/commands/purchase-orders.js +28 -21
- package/dist/commands/reports.js +17 -17
- package/dist/commands/salary-types.js +17 -17
- package/dist/commands/sales-invoices.js +27 -25
- package/dist/commands/sales-orders.js +19 -19
- package/dist/commands/saved-views.js +17 -17
- package/dist/commands/scheduled-processor-mappings.js +17 -17
- package/dist/commands/schedules.js +17 -17
- package/dist/commands/switch.js +10 -3
- package/dist/commands/{files-internal.d.ts → tag-configurations.d.ts} +1 -1
- package/dist/commands/tag-configurations.js +1178 -0
- package/dist/commands/tags.js +17 -17
- package/dist/commands/tax-codes.js +17 -17
- package/dist/commands/tax-matrix.js +17 -17
- package/dist/commands/tenants.js +17 -17
- package/dist/commands/text-templates.js +17 -17
- package/dist/commands/tools.js +17 -17
- package/dist/commands/vat-declarations.js +17 -17
- package/dist/commands/vendor-invoices.js +21 -21
- package/dist/commands/webhooks.js +17 -17
- package/dist/commands/workflows.js +17 -17
- package/dist/lib/api-client.js +11 -6
- package/dist/lib/auth.d.ts +8 -0
- package/dist/lib/auth.js +51 -7
- package/dist/lib/base-api-command.js +6 -4
- package/dist/lib/config.d.ts +31 -1
- package/dist/lib/config.js +31 -0
- package/oclif.manifest.json +729 -247
- package/package.json +2 -2
|
@@ -1,36 +1,26 @@
|
|
|
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
|
-
const HAS_IMPORT =
|
|
6
|
-
const HAS_EXPORT =
|
|
5
|
+
const HAS_IMPORT = false;
|
|
6
|
+
const HAS_EXPORT = false;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
8
|
const NESTED_IMPORTS = [];
|
|
9
|
-
const SUBCOMMANDS = [...["
|
|
9
|
+
const SUBCOMMANDS = [...["query", "views", "views-name"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'update': { method: 'PATCH', path: '/v1/documents/{id}', summary: 'Patch an existing document', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['references', 'tags', 'files'] },
|
|
15
|
-
'delete': { method: 'DELETE', path: '/v1/documents/{id}', summary: 'Soft-delete (discard) a document', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
16
|
-
'reclassify': { method: 'POST', path: '/v1/documents/{id}/reclassify', summary: 'Reclassify a document to a new type', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
11
|
+
'query': { method: 'POST', path: '/v1/analytics/query', summary: 'Run a structured aggregate query over a reporting view', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['measures', 'dimensions', 'filters', 'order'] },
|
|
12
|
+
'views': { method: 'GET', path: '/v1/analytics/views', summary: 'List the analytics views for discovery', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
13
|
+
'views-name': { method: 'GET', path: '/v1/analytics/views/{name}', summary: 'Describe one analytics view with full metadata', pathParams: ['name'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
|
|
17
14
|
};
|
|
18
|
-
export default class
|
|
19
|
-
static description = 'Manage
|
|
20
|
-
static examples = [
|
|
21
|
-
'<%= config.bin %> documents list',
|
|
22
|
-
'<%= config.bin %> documents get <id>',
|
|
23
|
-
'<%= config.bin %> documents create --data \'{...}\'',
|
|
24
|
-
'<%= config.bin %> documents update <id> --set field=value',
|
|
25
|
-
'<%= config.bin %> documents import --file data.json',
|
|
26
|
-
'<%= config.bin %> documents export --csv > documents.csv',
|
|
27
|
-
];
|
|
15
|
+
export default class Analytics extends Command {
|
|
16
|
+
static description = 'Manage analytics';
|
|
17
|
+
static examples = [];
|
|
28
18
|
static args = {
|
|
29
19
|
action: Args.string({ description: 'Action: ' + SUBCOMMANDS.join(', '), required: true }),
|
|
30
20
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
31
21
|
};
|
|
32
22
|
static flags = {
|
|
33
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
23
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
34
24
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
35
25
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
36
26
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -49,7 +39,7 @@ export default class Documents extends Command {
|
|
|
49
39
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
50
40
|
};
|
|
51
41
|
async run() {
|
|
52
|
-
const { args, flags } = await this.parse(
|
|
42
|
+
const { args, flags } = await this.parse(Analytics);
|
|
53
43
|
// Handle import action specially
|
|
54
44
|
if (args.action === 'import') {
|
|
55
45
|
if (!HAS_IMPORT)
|
|
@@ -90,7 +80,7 @@ export default class Documents extends Command {
|
|
|
90
80
|
// First path param always comes from positional argument
|
|
91
81
|
value = args.id;
|
|
92
82
|
if (!value)
|
|
93
|
-
this.error('Missing required argument: id. Usage: aderis
|
|
83
|
+
this.error('Missing required argument: id. Usage: aderis analytics <action> <id>');
|
|
94
84
|
}
|
|
95
85
|
else {
|
|
96
86
|
const flagName = param.replace(/\./g, '-').replace(/([A-Z])/g, '-$1').toLowerCase().replace(/^-/, '');
|
|
@@ -102,9 +92,9 @@ export default class Documents extends Command {
|
|
|
102
92
|
}
|
|
103
93
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
104
94
|
if (!context)
|
|
105
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
106
|
-
if (!context
|
|
107
|
-
this.error(
|
|
95
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
96
|
+
if (!hasCredentials(context))
|
|
97
|
+
this.error(missingCredentialsMessage(context));
|
|
108
98
|
const queryParams = {};
|
|
109
99
|
if (flags.page)
|
|
110
100
|
queryParams.page = flags.page;
|
|
@@ -347,9 +337,9 @@ export default class Documents extends Command {
|
|
|
347
337
|
async runImport(flags) {
|
|
348
338
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
349
339
|
if (!context)
|
|
350
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
351
|
-
if (!context
|
|
352
|
-
this.error(
|
|
340
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
341
|
+
if (!hasCredentials(context))
|
|
342
|
+
this.error(missingCredentialsMessage(context));
|
|
353
343
|
// Get data from file, --data, or --set flags
|
|
354
344
|
let items = [];
|
|
355
345
|
if (flags.file) {
|
|
@@ -559,9 +549,9 @@ export default class Documents extends Command {
|
|
|
559
549
|
async runExport(flags) {
|
|
560
550
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
561
551
|
if (!context)
|
|
562
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
563
|
-
if (!context
|
|
564
|
-
this.error(
|
|
552
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
553
|
+
if (!hasCredentials(context))
|
|
554
|
+
this.error(missingCredentialsMessage(context));
|
|
565
555
|
const listEndpoint = ENDPOINTS['list'];
|
|
566
556
|
if (!listEndpoint)
|
|
567
557
|
this.error('Export requires a list endpoint');
|
|
@@ -653,9 +643,9 @@ export default class Documents extends Command {
|
|
|
653
643
|
async runCamt053Import(flags) {
|
|
654
644
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
655
645
|
if (!context)
|
|
656
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
657
|
-
if (!context
|
|
658
|
-
this.error(
|
|
646
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
647
|
+
if (!hasCredentials(context))
|
|
648
|
+
this.error(missingCredentialsMessage(context));
|
|
659
649
|
if (!flags.file) {
|
|
660
650
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
661
651
|
}
|
|
@@ -739,13 +729,13 @@ export default class Documents extends Command {
|
|
|
739
729
|
}
|
|
740
730
|
async runNestedImport(suffix, parentId, flags) {
|
|
741
731
|
if (!parentId) {
|
|
742
|
-
this.error(`Missing required argument: id. Usage: aderis
|
|
732
|
+
this.error(`Missing required argument: id. Usage: aderis analytics import-${suffix} <parent-id> --file data.json`);
|
|
743
733
|
}
|
|
744
734
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
745
735
|
if (!context)
|
|
746
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
747
|
-
if (!context
|
|
748
|
-
this.error(
|
|
736
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
737
|
+
if (!hasCredentials(context))
|
|
738
|
+
this.error(missingCredentialsMessage(context));
|
|
749
739
|
// Get data from file, --data, or --set flags
|
|
750
740
|
let items = [];
|
|
751
741
|
if (flags.file) {
|
|
@@ -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 = false;
|
|
6
6
|
const HAS_EXPORT = true;
|
|
@@ -23,7 +23,7 @@ export default class AuditLog extends Command {
|
|
|
23
23
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
24
24
|
};
|
|
25
25
|
static flags = {
|
|
26
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
26
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
27
27
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
28
28
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
29
29
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -95,9 +95,9 @@ export default class AuditLog extends Command {
|
|
|
95
95
|
}
|
|
96
96
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
97
97
|
if (!context)
|
|
98
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
99
|
-
if (!context
|
|
100
|
-
this.error(
|
|
98
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
99
|
+
if (!hasCredentials(context))
|
|
100
|
+
this.error(missingCredentialsMessage(context));
|
|
101
101
|
const queryParams = {};
|
|
102
102
|
if (flags.page)
|
|
103
103
|
queryParams.page = flags.page;
|
|
@@ -340,9 +340,9 @@ export default class AuditLog extends Command {
|
|
|
340
340
|
async runImport(flags) {
|
|
341
341
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
342
342
|
if (!context)
|
|
343
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
344
|
-
if (!context
|
|
345
|
-
this.error(
|
|
343
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
344
|
+
if (!hasCredentials(context))
|
|
345
|
+
this.error(missingCredentialsMessage(context));
|
|
346
346
|
// Get data from file, --data, or --set flags
|
|
347
347
|
let items = [];
|
|
348
348
|
if (flags.file) {
|
|
@@ -552,9 +552,9 @@ export default class AuditLog extends Command {
|
|
|
552
552
|
async runExport(flags) {
|
|
553
553
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
554
554
|
if (!context)
|
|
555
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
556
|
-
if (!context
|
|
557
|
-
this.error(
|
|
555
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
556
|
+
if (!hasCredentials(context))
|
|
557
|
+
this.error(missingCredentialsMessage(context));
|
|
558
558
|
const listEndpoint = ENDPOINTS['list'];
|
|
559
559
|
if (!listEndpoint)
|
|
560
560
|
this.error('Export requires a list endpoint');
|
|
@@ -646,9 +646,9 @@ export default class AuditLog extends Command {
|
|
|
646
646
|
async runCamt053Import(flags) {
|
|
647
647
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
648
648
|
if (!context)
|
|
649
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
650
|
-
if (!context
|
|
651
|
-
this.error(
|
|
649
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
650
|
+
if (!hasCredentials(context))
|
|
651
|
+
this.error(missingCredentialsMessage(context));
|
|
652
652
|
if (!flags.file) {
|
|
653
653
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
654
654
|
}
|
|
@@ -736,9 +736,9 @@ export default class AuditLog extends Command {
|
|
|
736
736
|
}
|
|
737
737
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
738
738
|
if (!context)
|
|
739
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
740
|
-
if (!context
|
|
741
|
-
this.error(
|
|
739
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
740
|
+
if (!hasCredentials(context))
|
|
741
|
+
this.error(missingCredentialsMessage(context));
|
|
742
742
|
// Get data from file, --data, or --set flags
|
|
743
743
|
let items = [];
|
|
744
744
|
if (flags.file) {
|
|
@@ -2,7 +2,7 @@ import { input, select } from '@inquirer/prompts';
|
|
|
2
2
|
import { Command, Flags } from '@oclif/core';
|
|
3
3
|
import ora from 'ora';
|
|
4
4
|
import { login, testAuth } from '../../lib/auth.js';
|
|
5
|
-
import { addContext, DEFAULT_CLIENT_IDS, getContext, getCurrentContext, } from '../../lib/config.js';
|
|
5
|
+
import { addContext, DEFAULT_CLIENT_IDS, getAuthType, getContext, getCurrentContext, } from '../../lib/config.js';
|
|
6
6
|
export default class AuthLogin extends Command {
|
|
7
7
|
static description = 'Login to an Aderis environment using OAuth';
|
|
8
8
|
static examples = [
|
|
@@ -15,8 +15,10 @@ export default class AuthLogin extends Command {
|
|
|
15
15
|
description: 'OAuth client ID (uses default if not specified)',
|
|
16
16
|
}),
|
|
17
17
|
context: Flags.string({
|
|
18
|
+
aliases: ['config'],
|
|
18
19
|
char: 'c',
|
|
19
|
-
description: 'Context to login with
|
|
20
|
+
description: 'Context to login with, overriding the current context (alias: --config)',
|
|
21
|
+
env: 'ADERIS_CONTEXT',
|
|
20
22
|
}),
|
|
21
23
|
environment: Flags.string({
|
|
22
24
|
char: 'e',
|
|
@@ -51,6 +53,12 @@ export default class AuthLogin extends Command {
|
|
|
51
53
|
context = await this.createNewContext(flags);
|
|
52
54
|
}
|
|
53
55
|
}
|
|
56
|
+
// API-key contexts have no browser flow; sending them through OAuth would
|
|
57
|
+
// fail deeper in with a less useful error.
|
|
58
|
+
if (getAuthType(context) === 'api_key') {
|
|
59
|
+
this.error(`Context "${context.name}" authenticates with an API key, so there is nothing to log in to.\n` +
|
|
60
|
+
`Set or rotate the key with: aderis config set-api-key --context ${context.name}`);
|
|
61
|
+
}
|
|
54
62
|
const spinner = ora(`Logging in to ${context.name} (${context.environment})...`).start();
|
|
55
63
|
try {
|
|
56
64
|
spinner.text = 'Waiting for browser authentication...';
|
|
@@ -104,6 +112,7 @@ export default class AuthLogin extends Command {
|
|
|
104
112
|
this.error(`No default client ID configured for ${environment} environment. Please provide --client-id`);
|
|
105
113
|
}
|
|
106
114
|
const context = {
|
|
115
|
+
auth_type: 'oauth2',
|
|
107
116
|
client_id: clientId,
|
|
108
117
|
environment,
|
|
109
118
|
name: contextName,
|
|
@@ -7,4 +7,6 @@ export default class AuthLogout extends Command {
|
|
|
7
7
|
context: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
8
8
|
};
|
|
9
9
|
run(): Promise<void>;
|
|
10
|
+
/** Drop whichever credential the context holds — OAuth tokens or an API key. */
|
|
11
|
+
private clearCredentials;
|
|
10
12
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import { clearTokens, getContext, getCurrentContext } from '../../lib/config.js';
|
|
2
|
+
import { clearApiKey, clearTokens, getAuthType, getContext, getCurrentContext, hasCredentials, } from '../../lib/config.js';
|
|
3
3
|
export default class AuthLogout extends Command {
|
|
4
4
|
static description = 'Logout from the current or specified context';
|
|
5
5
|
static examples = [
|
|
@@ -14,8 +14,10 @@ export default class AuthLogout extends Command {
|
|
|
14
14
|
description: 'Logout from all contexts',
|
|
15
15
|
}),
|
|
16
16
|
context: Flags.string({
|
|
17
|
+
aliases: ['config'],
|
|
17
18
|
char: 'c',
|
|
18
|
-
description: '
|
|
19
|
+
description: 'Context to logout from, overriding the current context (alias: --config)',
|
|
20
|
+
env: 'ADERIS_CONTEXT',
|
|
19
21
|
}),
|
|
20
22
|
};
|
|
21
23
|
async run() {
|
|
@@ -24,8 +26,8 @@ export default class AuthLogout extends Command {
|
|
|
24
26
|
if (flags.all) {
|
|
25
27
|
const contexts = listContexts();
|
|
26
28
|
for (const ctx of contexts) {
|
|
27
|
-
if (ctx
|
|
28
|
-
|
|
29
|
+
if (hasCredentials(ctx)) {
|
|
30
|
+
this.clearCredentials(ctx.name);
|
|
29
31
|
this.log(`Logged out from ${ctx.name}`);
|
|
30
32
|
}
|
|
31
33
|
}
|
|
@@ -48,11 +50,22 @@ export default class AuthLogout extends Command {
|
|
|
48
50
|
contextName = current.name;
|
|
49
51
|
}
|
|
50
52
|
const context = getContext(contextName);
|
|
51
|
-
if (!context
|
|
53
|
+
if (!context || !hasCredentials(context)) {
|
|
52
54
|
this.log(`Already logged out from ${contextName}`);
|
|
53
55
|
return;
|
|
54
56
|
}
|
|
57
|
+
this.clearCredentials(contextName);
|
|
58
|
+
this.log(getAuthType(context) === 'api_key'
|
|
59
|
+
? `Removed API key from ${contextName}`
|
|
60
|
+
: `Successfully logged out from ${contextName}`);
|
|
61
|
+
}
|
|
62
|
+
/** Drop whichever credential the context holds — OAuth tokens or an API key. */
|
|
63
|
+
clearCredentials(contextName) {
|
|
64
|
+
const context = getContext(contextName);
|
|
65
|
+
if (context && getAuthType(context) === 'api_key') {
|
|
66
|
+
clearApiKey(contextName);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
55
69
|
clearTokens(contextName);
|
|
56
|
-
this.log(`Successfully logged out from ${contextName}`);
|
|
57
70
|
}
|
|
58
71
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { testAuth } from '../../lib/auth.js';
|
|
3
|
-
import { getContext, getCurrentContext, listContexts } from '../../lib/config.js';
|
|
3
|
+
import { getAuthType, getContext, getCurrentContext, hasCredentials, listContexts, maskApiKey, missingCredentialsMessage, } from '../../lib/config.js';
|
|
4
4
|
export default class AuthStatus extends Command {
|
|
5
5
|
static description = 'Show authentication status for contexts';
|
|
6
6
|
static examples = [
|
|
@@ -15,8 +15,10 @@ export default class AuthStatus extends Command {
|
|
|
15
15
|
description: 'Show status for all contexts',
|
|
16
16
|
}),
|
|
17
17
|
context: Flags.string({
|
|
18
|
+
aliases: ['config'],
|
|
18
19
|
char: 'c',
|
|
19
|
-
description: '
|
|
20
|
+
description: 'Context to check, overriding the current context (alias: --config)',
|
|
21
|
+
env: 'ADERIS_CONTEXT',
|
|
20
22
|
}),
|
|
21
23
|
};
|
|
22
24
|
async run() {
|
|
@@ -56,7 +58,10 @@ export default class AuthStatus extends Command {
|
|
|
56
58
|
for (const ctx of contexts) {
|
|
57
59
|
const isCurrent = current?.name === ctx.name;
|
|
58
60
|
const prefix = isCurrent ? '* ' : ' ';
|
|
59
|
-
const
|
|
61
|
+
const isApiKey = getAuthType(ctx) === 'api_key';
|
|
62
|
+
const status = hasCredentials(ctx)
|
|
63
|
+
? (isApiKey ? '✓ api key set' : '✓ logged in')
|
|
64
|
+
: (isApiKey ? '✗ no api key' : '✗ not logged in');
|
|
60
65
|
this.log(`${prefix}${ctx.name} (${ctx.environment}) - ${status}`);
|
|
61
66
|
}
|
|
62
67
|
this.log('\n* = current context');
|
|
@@ -68,19 +73,28 @@ export default class AuthStatus extends Command {
|
|
|
68
73
|
this.error(`Context "${name}" not found.`);
|
|
69
74
|
}
|
|
70
75
|
const isCurrent = current?.name === name;
|
|
76
|
+
const authType = getAuthType(context);
|
|
71
77
|
this.log(`Context: ${context.name}${isCurrent ? ' (current)' : ''}`);
|
|
72
78
|
this.log(`Environment: ${context.environment}`);
|
|
73
|
-
this.log(`
|
|
74
|
-
if (
|
|
75
|
-
this.log(`
|
|
76
|
-
|
|
79
|
+
this.log(`Auth: ${authType === 'api_key' ? 'API key (x-api-key)' : 'oauth2'}`);
|
|
80
|
+
if (authType === 'oauth2') {
|
|
81
|
+
this.log(`Client ID: ${context.client_id ?? 'N/A'}`);
|
|
82
|
+
}
|
|
83
|
+
if (!hasCredentials(context)) {
|
|
84
|
+
this.log(`Status: ${authType === 'api_key' ? 'No API key set' : 'Not logged in'}`);
|
|
85
|
+
this.log(`\n${missingCredentialsMessage(context)}`);
|
|
77
86
|
return;
|
|
78
87
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
this.log(`
|
|
88
|
+
if (authType === 'api_key') {
|
|
89
|
+
this.log(`API key: ${maskApiKey(context.api_key)}`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.log(`Tenant ID: ${context.tenant_id || 'N/A'}`);
|
|
93
|
+
if (context.tokens?.expires_at) {
|
|
94
|
+
const expiresAt = new Date(context.tokens.expires_at);
|
|
95
|
+
const isExpired = expiresAt < new Date();
|
|
96
|
+
this.log(`Token expires: ${expiresAt.toLocaleString()}${isExpired ? ' (EXPIRED)' : ''}`);
|
|
97
|
+
}
|
|
84
98
|
}
|
|
85
99
|
if (detailed) {
|
|
86
100
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { select } from '@inquirer/prompts';
|
|
2
2
|
import { Args, Command, Flags } from '@oclif/core';
|
|
3
3
|
import { getCurrentTenant, listTenants, switchTenant } from '../../lib/auth.js';
|
|
4
|
-
import { getContext, getCurrentContext } from '../../lib/config.js';
|
|
4
|
+
import { getAuthType, getContext, getCurrentContext } from '../../lib/config.js';
|
|
5
5
|
export default class AuthTenant extends Command {
|
|
6
6
|
static args = {
|
|
7
7
|
action: Args.string({
|
|
@@ -23,8 +23,10 @@ export default class AuthTenant extends Command {
|
|
|
23
23
|
];
|
|
24
24
|
static flags = {
|
|
25
25
|
context: Flags.string({
|
|
26
|
+
aliases: ['config'],
|
|
26
27
|
char: 'c',
|
|
27
|
-
description: 'Context to use',
|
|
28
|
+
description: 'Context to use, overriding the current context (alias: --config)',
|
|
29
|
+
env: 'ADERIS_CONTEXT',
|
|
28
30
|
}),
|
|
29
31
|
json: Flags.boolean({
|
|
30
32
|
default: false,
|
|
@@ -38,7 +40,14 @@ export default class AuthTenant extends Command {
|
|
|
38
40
|
this.error('No context configured. Run: aderis auth login --new');
|
|
39
41
|
}
|
|
40
42
|
const context = getContext(contextName);
|
|
41
|
-
if (!context
|
|
43
|
+
if (!context) {
|
|
44
|
+
this.error(`Context "${contextName}" not found.`);
|
|
45
|
+
}
|
|
46
|
+
// API keys are issued per tenant, so there is nothing to list or switch.
|
|
47
|
+
if (getAuthType(context) === 'api_key') {
|
|
48
|
+
this.error(`Context "${contextName}" authenticates with an API key, which is already scoped to a single tenant. Tenant switching requires OAuth login.`);
|
|
49
|
+
}
|
|
50
|
+
if (!context.tokens) {
|
|
42
51
|
this.error('Not logged in. Run: aderis auth login');
|
|
43
52
|
}
|
|
44
53
|
const action = args.action || 'interactive';
|
package/dist/commands/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { ApiError, apiRequest } from '../lib/api-client.js';
|
|
3
|
-
import { getContext, getCurrentContext } from '../lib/config.js';
|
|
3
|
+
import { getContext, getCurrentContext, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
|
|
4
4
|
// Add 'import' action if both create and update exist
|
|
5
5
|
const HAS_IMPORT = false;
|
|
6
6
|
const HAS_EXPORT = false;
|
|
@@ -40,7 +40,12 @@ export default class Auth extends Command {
|
|
|
40
40
|
static description = 'Manage auth';
|
|
41
41
|
static examples = [];
|
|
42
42
|
static flags = {
|
|
43
|
-
context: Flags.string({
|
|
43
|
+
context: Flags.string({
|
|
44
|
+
aliases: ['config'],
|
|
45
|
+
char: 'c',
|
|
46
|
+
description: 'Context to use for this command, overriding the current context (alias: --config)',
|
|
47
|
+
env: 'ADERIS_CONTEXT',
|
|
48
|
+
}),
|
|
44
49
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
45
50
|
data: Flags.string({ char: 'd', description: 'JSON data for request body' }),
|
|
46
51
|
fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
|
|
@@ -96,9 +101,11 @@ export default class Auth extends Command {
|
|
|
96
101
|
this.error(`Unknown action: ${args.action}. Available: ${SUBCOMMANDS.join(', ')}`);
|
|
97
102
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
98
103
|
if (!context)
|
|
99
|
-
this.error(
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
this.error(flags.context
|
|
105
|
+
? `Context "${flags.context}" not found. List contexts with: aderis config list`
|
|
106
|
+
: 'No context configured. Run: aderis auth login --new');
|
|
107
|
+
if (!hasCredentials(context))
|
|
108
|
+
this.error(missingCredentialsMessage(context));
|
|
102
109
|
let apiPath = endpoint.path;
|
|
103
110
|
for (const param of endpoint.pathParams) {
|
|
104
111
|
let value;
|
|
@@ -359,9 +366,11 @@ export default class Auth extends Command {
|
|
|
359
366
|
async runCamt053Import(flags) {
|
|
360
367
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
361
368
|
if (!context)
|
|
362
|
-
this.error(
|
|
363
|
-
|
|
364
|
-
|
|
369
|
+
this.error(flags.context
|
|
370
|
+
? `Context "${flags.context}" not found. List contexts with: aderis config list`
|
|
371
|
+
: 'No context configured. Run: aderis auth login --new');
|
|
372
|
+
if (!hasCredentials(context))
|
|
373
|
+
this.error(missingCredentialsMessage(context));
|
|
365
374
|
if (!flags.file) {
|
|
366
375
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
367
376
|
}
|
|
@@ -446,9 +455,11 @@ export default class Auth extends Command {
|
|
|
446
455
|
async runExport(flags) {
|
|
447
456
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
448
457
|
if (!context)
|
|
449
|
-
this.error(
|
|
450
|
-
|
|
451
|
-
|
|
458
|
+
this.error(flags.context
|
|
459
|
+
? `Context "${flags.context}" not found. List contexts with: aderis config list`
|
|
460
|
+
: 'No context configured. Run: aderis auth login --new');
|
|
461
|
+
if (!hasCredentials(context))
|
|
462
|
+
this.error(missingCredentialsMessage(context));
|
|
452
463
|
const listEndpoint = ENDPOINTS.list;
|
|
453
464
|
if (!listEndpoint)
|
|
454
465
|
this.error('Export requires a list endpoint');
|
|
@@ -522,9 +533,11 @@ export default class Auth extends Command {
|
|
|
522
533
|
async runImport(flags) {
|
|
523
534
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
524
535
|
if (!context)
|
|
525
|
-
this.error(
|
|
526
|
-
|
|
527
|
-
|
|
536
|
+
this.error(flags.context
|
|
537
|
+
? `Context "${flags.context}" not found. List contexts with: aderis config list`
|
|
538
|
+
: 'No context configured. Run: aderis auth login --new');
|
|
539
|
+
if (!hasCredentials(context))
|
|
540
|
+
this.error(missingCredentialsMessage(context));
|
|
528
541
|
// Get data from file, --data, or --set flags
|
|
529
542
|
let items = [];
|
|
530
543
|
if (flags.file) {
|
|
@@ -676,9 +689,11 @@ export default class Auth extends Command {
|
|
|
676
689
|
}
|
|
677
690
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
678
691
|
if (!context)
|
|
679
|
-
this.error(
|
|
680
|
-
|
|
681
|
-
|
|
692
|
+
this.error(flags.context
|
|
693
|
+
? `Context "${flags.context}" not found. List contexts with: aderis config list`
|
|
694
|
+
: 'No context configured. Run: aderis auth login --new');
|
|
695
|
+
if (!hasCredentials(context))
|
|
696
|
+
this.error(missingCredentialsMessage(context));
|
|
682
697
|
// Get data from file, --data, or --set flags
|
|
683
698
|
let items = [];
|
|
684
699
|
if (flags.file) {
|
|
@@ -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;
|
|
@@ -41,7 +41,7 @@ export default class BankAccounts extends Command {
|
|
|
41
41
|
id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
|
|
42
42
|
};
|
|
43
43
|
static flags = {
|
|
44
|
-
context: Flags.string({ char: 'c', description: 'Context to use' }),
|
|
44
|
+
context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
|
|
45
45
|
output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
|
|
46
46
|
table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
|
|
47
47
|
csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
|
|
@@ -115,9 +115,9 @@ export default class BankAccounts extends Command {
|
|
|
115
115
|
}
|
|
116
116
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
117
117
|
if (!context)
|
|
118
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
119
|
-
if (!context
|
|
120
|
-
this.error(
|
|
118
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
119
|
+
if (!hasCredentials(context))
|
|
120
|
+
this.error(missingCredentialsMessage(context));
|
|
121
121
|
const queryParams = {};
|
|
122
122
|
if (flags.page)
|
|
123
123
|
queryParams.page = flags.page;
|
|
@@ -360,9 +360,9 @@ export default class BankAccounts extends Command {
|
|
|
360
360
|
async runImport(flags) {
|
|
361
361
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
362
362
|
if (!context)
|
|
363
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
364
|
-
if (!context
|
|
365
|
-
this.error(
|
|
363
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
364
|
+
if (!hasCredentials(context))
|
|
365
|
+
this.error(missingCredentialsMessage(context));
|
|
366
366
|
// Get data from file, --data, or --set flags
|
|
367
367
|
let items = [];
|
|
368
368
|
if (flags.file) {
|
|
@@ -572,9 +572,9 @@ export default class BankAccounts extends Command {
|
|
|
572
572
|
async runExport(flags) {
|
|
573
573
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
574
574
|
if (!context)
|
|
575
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
576
|
-
if (!context
|
|
577
|
-
this.error(
|
|
575
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
576
|
+
if (!hasCredentials(context))
|
|
577
|
+
this.error(missingCredentialsMessage(context));
|
|
578
578
|
const listEndpoint = ENDPOINTS['list'];
|
|
579
579
|
if (!listEndpoint)
|
|
580
580
|
this.error('Export requires a list endpoint');
|
|
@@ -666,9 +666,9 @@ export default class BankAccounts extends Command {
|
|
|
666
666
|
async runCamt053Import(flags) {
|
|
667
667
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
668
668
|
if (!context)
|
|
669
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
670
|
-
if (!context
|
|
671
|
-
this.error(
|
|
669
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
670
|
+
if (!hasCredentials(context))
|
|
671
|
+
this.error(missingCredentialsMessage(context));
|
|
672
672
|
if (!flags.file) {
|
|
673
673
|
this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
|
|
674
674
|
}
|
|
@@ -756,9 +756,9 @@ export default class BankAccounts extends Command {
|
|
|
756
756
|
}
|
|
757
757
|
const context = flags.context ? getContext(flags.context) : getCurrentContext();
|
|
758
758
|
if (!context)
|
|
759
|
-
this.error('No context configured. Run: aderis auth login --new');
|
|
760
|
-
if (!context
|
|
761
|
-
this.error(
|
|
759
|
+
this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
|
|
760
|
+
if (!hasCredentials(context))
|
|
761
|
+
this.error(missingCredentialsMessage(context));
|
|
762
762
|
// Get data from file, --data, or --set flags
|
|
763
763
|
let items = [];
|
|
764
764
|
if (flags.file) {
|