@aderis-erp/cli 1.1.0 → 1.1.1

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.
@@ -1,8 +1,8 @@
1
1
  import { URL } from 'node:url';
2
- import { REDIRECT_URI } from './constants.js';
2
+ import { FORM_POST_HEADERS, REDIRECT_URI, SUPPORT_CLIENT_ID, SUPPORT_SESSION_GRANT_TYPE } from './constants.js';
3
3
  import { AuthError } from './errors.js';
4
4
  import { requireClientId } from './guards.js';
5
- import { authHttp, toAuthError } from './http.js';
5
+ import { authHttp, httpStatusOf, toAuthError } from './http.js';
6
6
  import { verifyToken } from './jwks.js';
7
7
  import { exchangeAuthorizationCode, redeemRefreshToken, tenantIdOf, tenantsOf, toTokenData, } from './tokens.js';
8
8
  import { buildValidatedUrl } from './validated-url.js';
@@ -84,14 +84,25 @@ function validateDiscovery(url, data) {
84
84
  throw new AuthError(`Keycloak discovery document at ${url} advertises a ${field} outside the allowed hosts: ${value}`);
85
85
  }
86
86
  };
87
- // `end_session_endpoint` is unused: logout is local-only.
88
87
  return {
89
88
  authorization_endpoint: requireEndpoint('authorization_endpoint'),
89
+ end_session_endpoint: requireEndpoint('end_session_endpoint'),
90
90
  issuer: requireString('issuer'),
91
91
  jwks_uri: requireEndpoint('jwks_uri'),
92
92
  token_endpoint: requireEndpoint('token_endpoint'),
93
93
  };
94
94
  }
95
+ /** `{id, name}` entries from the realm's support-tenant list; an entry without a usable id is dropped. */
96
+ function parseSupportTenants(body) {
97
+ if (!Array.isArray(body))
98
+ return [];
99
+ return body.flatMap((entry) => {
100
+ const { id, name } = (entry ?? {});
101
+ if (typeof id !== 'string' || !id)
102
+ return [];
103
+ return [{ name: typeof name === 'string' && name ? name : id, tenantId: id }];
104
+ });
105
+ }
95
106
  /**
96
107
  * Authorization Code + PKCE S256 with `state` and `nonce` against the public
97
108
  * `aderis-cli-login` client, endpoints from OIDC discovery. Tenants come from
@@ -131,6 +142,23 @@ export class KeycloakProvider {
131
142
  this.discoveryCache.set(key, pending);
132
143
  return pending;
133
144
  }
145
+ /**
146
+ * Ends exactly the support session. The operator's own login is a different
147
+ * Keycloak session and is left running.
148
+ */
149
+ async endSupportSession(context, refreshToken) {
150
+ const discovery = await this.discover(context);
151
+ const params = new URLSearchParams({ client_id: SUPPORT_CLIENT_ID, refresh_token: refreshToken });
152
+ try {
153
+ await authHttp.post(discovery.end_session_endpoint, params.toString(), { headers: FORM_POST_HEADERS });
154
+ }
155
+ catch (error) {
156
+ // A session Keycloak has already forgotten is the state we wanted.
157
+ const status = httpStatusOf(error);
158
+ if (status !== 400 && status !== 401 && status !== 404)
159
+ throw toAuthError(error, 'Support session logout');
160
+ }
161
+ }
134
162
  async exchangeCode(context, { code, codeVerifier, nonce }) {
135
163
  const discovery = await this.discover(context);
136
164
  const response = await exchangeAuthorizationCode(discovery.token_endpoint, context, { code, codeVerifier });
@@ -138,6 +166,28 @@ export class KeycloakProvider {
138
166
  const claims = await this.verifyAccessToken(discovery, response.access_token);
139
167
  return this.requireTenant(toTokenData(response, claims), claims);
140
168
  }
169
+ /**
170
+ * Customers this operator may act for. Served by the realm's tenant-claims
171
+ * mapper against the operator's own Bearer, so Keycloak — not the CLI —
172
+ * decides who is an operator and which customers they may pick.
173
+ */
174
+ async listSupportTenants(context, operatorAccessToken) {
175
+ const discovery = await this.discover(context);
176
+ const url = buildValidatedUrl(new URL(discovery.issuer).origin, `${new URL(discovery.issuer).pathname}/aderis-tenant-claims/me/support/tenants`);
177
+ let response;
178
+ try {
179
+ response = await authHttp.get(url, {
180
+ headers: { Accept: 'application/json', Authorization: `Bearer ${operatorAccessToken}` },
181
+ });
182
+ }
183
+ catch (error) {
184
+ if (httpStatusOf(error) === 403) {
185
+ throw new AuthError('Your account is not an Aderis Support operator, so it cannot act for a customer.');
186
+ }
187
+ throw toAuthError(error, 'Support tenant list');
188
+ }
189
+ return parseSupportTenants(response.data);
190
+ }
141
191
  /** The access token's `availableTenants` claim lists every tenant the user may act in, read once its signature checks out. */
142
192
  async listTenants(context, accessToken) {
143
193
  const decoded = await this.readClaims(context, accessToken);
@@ -168,6 +218,61 @@ export class KeycloakProvider {
168
218
  refresh(context, refreshToken) {
169
219
  return this.redeem(context, refreshToken);
170
220
  }
221
+ /** Refreshes a support session. No tenant is named: the session never moves customer. */
222
+ async refreshSupportSession(context, refreshToken) {
223
+ const discovery = await this.discover(context);
224
+ const params = new URLSearchParams({
225
+ client_id: SUPPORT_CLIENT_ID,
226
+ grant_type: 'refresh_token',
227
+ refresh_token: refreshToken,
228
+ });
229
+ let response;
230
+ try {
231
+ response = await authHttp.post(discovery.token_endpoint, params.toString(), {
232
+ headers: FORM_POST_HEADERS,
233
+ });
234
+ }
235
+ catch (error) {
236
+ const status = httpStatusOf(error);
237
+ if (status === 400 || status === 401) {
238
+ throw new AuthError('The support session has ended. Start a new one with: aderis support start <tenant-id>', {
239
+ status,
240
+ });
241
+ }
242
+ throw toAuthError(error, 'Support session refresh');
243
+ }
244
+ const claims = await this.verifyAccessToken(discovery, response.data.access_token);
245
+ return toTokenData(response.data, claims);
246
+ }
247
+ /**
248
+ * Starts a support session for `tenantId`, authorised by the operator's own
249
+ * access token. The returned tokens belong to the shared support account and
250
+ * name the operator in `impersonatorId`; they are a second login, so the
251
+ * operator's own tokens stay valid and untouched.
252
+ */
253
+ async startSupportSession(context, operatorAccessToken, tenantId) {
254
+ const discovery = await this.discover(context);
255
+ const params = new URLSearchParams({
256
+ client_id: SUPPORT_CLIENT_ID,
257
+ grant_type: SUPPORT_SESSION_GRANT_TYPE,
258
+ tenant_id: tenantId,
259
+ });
260
+ let response;
261
+ try {
262
+ response = await authHttp.post(discovery.token_endpoint, params.toString(), {
263
+ headers: { ...FORM_POST_HEADERS, Authorization: `Bearer ${operatorAccessToken}` },
264
+ });
265
+ }
266
+ catch (error) {
267
+ const status = httpStatusOf(error);
268
+ if (status === 400 || status === 401 || status === 403) {
269
+ throw new AuthError(`Keycloak refused a support session for tenant ${tenantId}. Check that your account is a support operator and that the customer is one you may act for.`, { status });
270
+ }
271
+ throw toAuthError(error, 'Support session');
272
+ }
273
+ const claims = await this.verifyAccessToken(discovery, response.data.access_token);
274
+ return toTokenData(response.data, claims);
275
+ }
171
276
  /**
172
277
  * One refresh-token grant with the `tenant_id` form field, read by the
173
278
  * realm's tenant-claims mapper: the minted token's `tenantId` becomes this
@@ -26,6 +26,18 @@ export interface CachedTenant {
26
26
  name: string;
27
27
  tenantId: string;
28
28
  }
29
+ /**
30
+ * A running "act as Aderis Support" session, held beside the operator's own
31
+ * login rather than replacing it: ending it returns to the operator without a
32
+ * new browser login, exactly as the web app does.
33
+ */
34
+ export interface SupportSession {
35
+ /** The operator's Keycloak `sub`; a session started by someone else is not reused. */
36
+ operator_sub: string;
37
+ tenant_id: string;
38
+ tenant_name: string;
39
+ tokens: TokenData;
40
+ }
29
41
  export interface Context {
30
42
  api_key?: string;
31
43
  auth_type?: AuthType;
@@ -41,6 +53,8 @@ export interface Context {
41
53
  */
42
54
  keycloak_base_url?: string;
43
55
  name: string;
56
+ /** Set while acting as Aderis Support; the operator's own tokens stay in `tokens`. */
57
+ support?: SupportSession;
44
58
  tenant_id?: string;
45
59
  tokens?: TokenData;
46
60
  }
@@ -63,6 +77,10 @@ export declare function saveCachedTenants(contextName: string, tenants: CachedTe
63
77
  export declare function getCachedTenants(contextName: string): CachedTenant[] | undefined;
64
78
  export declare function getTokens(contextName: string): null | TokenData;
65
79
  export declare function clearTokens(contextName: string): void;
80
+ export declare function saveSupportSession(contextName: string, support: SupportSession): void;
81
+ export declare function clearSupportSession(contextName: string): void;
82
+ /** The running support session of a context, if any. */
83
+ export declare function getSupportSession(context: Context): SupportSession | undefined;
66
84
  export declare function saveApiKey(contextName: string, apiKey: string): void;
67
85
  export declare function clearApiKey(contextName: string): void;
68
86
  /**
@@ -128,6 +128,16 @@ export function getTokens(contextName) {
128
128
  export function clearTokens(contextName) {
129
129
  updateContext(contextName, { tokens: undefined });
130
130
  }
131
+ export function saveSupportSession(contextName, support) {
132
+ updateContext(contextName, { support });
133
+ }
134
+ export function clearSupportSession(contextName) {
135
+ updateContext(contextName, { support: undefined });
136
+ }
137
+ /** The running support session of a context, if any. */
138
+ export function getSupportSession(context) {
139
+ return context.support;
140
+ }
131
141
  export function saveApiKey(contextName, apiKey) {
132
142
  updateContext(contextName, { api_key: apiKey, auth_type: 'api_key' });
133
143
  }
@@ -5879,7 +5879,7 @@
5879
5879
  "aliases": [],
5880
5880
  "args": {
5881
5881
  "action": {
5882
- "description": "Action: list, create, get, update, delete, list-month-end-closings, create-month-end-closings, get-month-end-closings, update-month-end-closings, delete-month-end-closings, month-end-closings-complete, create-month-end-closings-provisional-booking, delete-month-end-closings-provisional-booking, month-end-closings-reopen, list-month-end-closings-accruals, create-month-end-closings-accruals, update-month-end-closings-accruals, delete-month-end-closings-accruals, month-end-closings-accruals-accept, month-end-closings-accruals-dismiss, list-month-end-closings-accrual-accounts, list-month-end-closings-findings, update-month-end-closings-findings, list-month-end-closings-notes, create-month-end-closings-notes, get-month-end-closings-notes, update-month-end-closings-notes, delete-month-end-closings-notes, update-month-end-closings-agent-results, month-end-closings-agent-run, get-fx-rate, replace-fx-rate-providers, list-notes, create-notes, get-notes, update-notes, delete-notes, list-closings, create-closings, get-closings, update-closings, closings-close, closings-reopen, list-posting-runs, create-posting-runs, posting-runs, import, export, import-month-end-closings, import-month-end-closings-accruals, import-month-end-closings-notes, import-notes, import-closings",
5882
+ "description": "Action: list, create, get, update, delete, list-month-end-closings, create-month-end-closings, get-month-end-closings, update-month-end-closings, delete-month-end-closings, month-end-closings-complete, create-month-end-closings-provisional-booking, delete-month-end-closings-provisional-booking, month-end-closings-reopen, list-month-end-closings-accruals, create-month-end-closings-accruals, update-month-end-closings-accruals, delete-month-end-closings-accruals, month-end-closings-accruals-accept, month-end-closings-accruals-dismiss, list-month-end-closings-accrual-accounts, list-month-end-closings-findings, update-month-end-closings-findings, list-month-end-closings-notes, create-month-end-closings-notes, get-month-end-closings-notes, update-month-end-closings-notes, delete-month-end-closings-notes, update-month-end-closings-agent-results, month-end-closings-agent-run, get-fx-rate, replace-fx-rate-providers, replace-closing-fx-rate-providers, list-notes, create-notes, get-notes, update-notes, delete-notes, list-closings, create-closings, get-closings, update-closings, closings-close, closings-reopen, list-posting-runs, create-posting-runs, posting-runs, import, export, import-month-end-closings, import-month-end-closings-accruals, import-month-end-closings-notes, import-notes, import-closings",
5883
5883
  "name": "action",
5884
5884
  "required": true
5885
5885
  },
@@ -9761,181 +9761,11 @@
9761
9761
  "switch.js"
9762
9762
  ]
9763
9763
  },
9764
- "tag-configurations": {
9765
- "aliases": [],
9766
- "args": {
9767
- "action": {
9768
- "description": "Action: list, create, get, update, delete, journal-coverage, import, export",
9769
- "name": "action",
9770
- "required": true
9771
- },
9772
- "id": {
9773
- "description": "Resource ID (for get, update, delete operations)",
9774
- "name": "id",
9775
- "required": false
9776
- }
9777
- },
9778
- "description": "Manage tag configurations",
9779
- "examples": [
9780
- "<%= config.bin %> tag-configurations list",
9781
- "<%= config.bin %> tag-configurations get <id>",
9782
- "<%= config.bin %> tag-configurations create --data '{...}'",
9783
- "<%= config.bin %> tag-configurations update <id> --set field=value",
9784
- "<%= config.bin %> tag-configurations import --file data.json",
9785
- "<%= config.bin %> tag-configurations export --csv > tag-configurations.csv"
9786
- ],
9787
- "flags": {
9788
- "context": {
9789
- "aliases": [
9790
- "config"
9791
- ],
9792
- "char": "c",
9793
- "description": "Context to use for this command, overriding the current context (alias: --config)",
9794
- "env": "ADERIS_CONTEXT",
9795
- "name": "context",
9796
- "hasDynamicHelp": false,
9797
- "multiple": false,
9798
- "type": "option"
9799
- },
9800
- "output": {
9801
- "char": "o",
9802
- "description": "Output format (default: table for import, json for other commands)",
9803
- "name": "output",
9804
- "hasDynamicHelp": false,
9805
- "multiple": false,
9806
- "options": [
9807
- "json",
9808
- "table",
9809
- "csv"
9810
- ],
9811
- "type": "option"
9812
- },
9813
- "table": {
9814
- "char": "t",
9815
- "description": "Output as table (shortcut for --output table)",
9816
- "name": "table",
9817
- "allowNo": false,
9818
- "type": "boolean"
9819
- },
9820
- "csv": {
9821
- "description": "Output as CSV (shortcut for --output csv)",
9822
- "name": "csv",
9823
- "allowNo": false,
9824
- "type": "boolean"
9825
- },
9826
- "data": {
9827
- "char": "d",
9828
- "description": "JSON data for request body",
9829
- "name": "data",
9830
- "hasDynamicHelp": false,
9831
- "multiple": false,
9832
- "type": "option"
9833
- },
9834
- "file": {
9835
- "char": "f",
9836
- "description": "Read request body from file",
9837
- "name": "file",
9838
- "hasDynamicHelp": false,
9839
- "multiple": false,
9840
- "type": "option"
9841
- },
9842
- "set": {
9843
- "char": "s",
9844
- "description": "Set individual field (e.g. --set firstName=John)",
9845
- "name": "set",
9846
- "hasDynamicHelp": false,
9847
- "multiple": true,
9848
- "type": "option"
9849
- },
9850
- "page": {
9851
- "description": "Page number",
9852
- "name": "page",
9853
- "hasDynamicHelp": false,
9854
- "multiple": false,
9855
- "type": "option"
9856
- },
9857
- "limit": {
9858
- "description": "Items per page",
9859
- "name": "limit",
9860
- "hasDynamicHelp": false,
9861
- "multiple": false,
9862
- "type": "option"
9863
- },
9864
- "include": {
9865
- "description": "Relations to include",
9866
- "name": "include",
9867
- "hasDynamicHelp": false,
9868
- "multiple": false,
9869
- "type": "option"
9870
- },
9871
- "search": {
9872
- "description": "Search term",
9873
- "name": "search",
9874
- "hasDynamicHelp": false,
9875
- "multiple": false,
9876
- "type": "option"
9877
- },
9878
- "sort-by": {
9879
- "description": "Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.",
9880
- "name": "sort-by",
9881
- "hasDynamicHelp": false,
9882
- "multiple": false,
9883
- "type": "option"
9884
- },
9885
- "filter": {
9886
- "description": "Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:",
9887
- "name": "filter",
9888
- "hasDynamicHelp": false,
9889
- "multiple": true,
9890
- "type": "option"
9891
- },
9892
- "query": {
9893
- "description": "Additional query params as JSON",
9894
- "name": "query",
9895
- "hasDynamicHelp": false,
9896
- "multiple": false,
9897
- "type": "option"
9898
- },
9899
- "fields": {
9900
- "description": "Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)",
9901
- "name": "fields",
9902
- "hasDynamicHelp": false,
9903
- "multiple": false,
9904
- "type": "option"
9905
- },
9906
- "sanitize": {
9907
- "description": "Remove null values, audit fields, and duplicate UUIDs from output",
9908
- "name": "sanitize",
9909
- "allowNo": false,
9910
- "type": "boolean"
9911
- },
9912
- "show-http-request": {
9913
- "description": "Show HTTP request details (method, URL, body)",
9914
- "name": "show-http-request",
9915
- "allowNo": false,
9916
- "type": "boolean"
9917
- }
9918
- },
9919
- "hasDynamicHelp": false,
9920
- "hiddenAliases": [],
9921
- "id": "tag-configurations",
9922
- "pluginAlias": "@aderis-erp/cli",
9923
- "pluginName": "@aderis-erp/cli",
9924
- "pluginType": "core",
9925
- "strict": true,
9926
- "enableJsonFlag": false,
9927
- "isESM": true,
9928
- "relativePath": [
9929
- "dist",
9930
- "commands",
9931
- "tag-configurations.js"
9932
- ]
9933
- },
9934
9764
  "tags": {
9935
9765
  "aliases": [],
9936
9766
  "args": {
9937
9767
  "action": {
9938
- "description": "Action: list, create, get, update, delete, import, export",
9768
+ "description": "Action: list, create, get, update, delete, journal-coverage, import, export",
9939
9769
  "name": "action",
9940
9770
  "required": true
9941
9771
  },
@@ -12425,7 +12255,178 @@
12425
12255
  "config",
12426
12256
  "use.js"
12427
12257
  ]
12258
+ },
12259
+ "support:end": {
12260
+ "aliases": [],
12261
+ "args": {},
12262
+ "description": "Stop acting as Aderis Support and return to your own account",
12263
+ "examples": [
12264
+ "<%= config.bin %> support end",
12265
+ "<%= config.bin %> support end --context prod"
12266
+ ],
12267
+ "flags": {
12268
+ "context": {
12269
+ "aliases": [
12270
+ "config"
12271
+ ],
12272
+ "char": "c",
12273
+ "description": "Context to use, overriding the current context (alias: --config)",
12274
+ "env": "ADERIS_CONTEXT",
12275
+ "name": "context",
12276
+ "hasDynamicHelp": false,
12277
+ "multiple": false,
12278
+ "type": "option"
12279
+ }
12280
+ },
12281
+ "hasDynamicHelp": false,
12282
+ "hiddenAliases": [],
12283
+ "id": "support:end",
12284
+ "pluginAlias": "@aderis-erp/cli",
12285
+ "pluginName": "@aderis-erp/cli",
12286
+ "pluginType": "core",
12287
+ "strict": true,
12288
+ "enableJsonFlag": false,
12289
+ "isESM": true,
12290
+ "relativePath": [
12291
+ "dist",
12292
+ "commands",
12293
+ "support",
12294
+ "end.js"
12295
+ ]
12296
+ },
12297
+ "support:start": {
12298
+ "aliases": [],
12299
+ "args": {
12300
+ "tenantId": {
12301
+ "description": "Customer to act for; prompted for if omitted",
12302
+ "name": "tenantId",
12303
+ "required": false
12304
+ }
12305
+ },
12306
+ "description": "Act as Aderis Support in a customer tenant",
12307
+ "examples": [
12308
+ "<%= config.bin %> support start",
12309
+ "<%= config.bin %> support start 11839c8b-7ec3-4cc1-9dae-396ced09b928",
12310
+ "<%= config.bin %> support start <tenant-id> --context prod"
12311
+ ],
12312
+ "flags": {
12313
+ "context": {
12314
+ "aliases": [
12315
+ "config"
12316
+ ],
12317
+ "char": "c",
12318
+ "description": "Context to use, overriding the current context (alias: --config)",
12319
+ "env": "ADERIS_CONTEXT",
12320
+ "name": "context",
12321
+ "hasDynamicHelp": false,
12322
+ "multiple": false,
12323
+ "type": "option"
12324
+ }
12325
+ },
12326
+ "hasDynamicHelp": false,
12327
+ "hiddenAliases": [],
12328
+ "id": "support:start",
12329
+ "pluginAlias": "@aderis-erp/cli",
12330
+ "pluginName": "@aderis-erp/cli",
12331
+ "pluginType": "core",
12332
+ "strict": true,
12333
+ "enableJsonFlag": false,
12334
+ "isESM": true,
12335
+ "relativePath": [
12336
+ "dist",
12337
+ "commands",
12338
+ "support",
12339
+ "start.js"
12340
+ ]
12341
+ },
12342
+ "support:status": {
12343
+ "aliases": [],
12344
+ "args": {},
12345
+ "description": "Show whether this context is acting as Aderis Support",
12346
+ "examples": [
12347
+ "<%= config.bin %> support status",
12348
+ "<%= config.bin %> support status --context prod"
12349
+ ],
12350
+ "flags": {
12351
+ "context": {
12352
+ "aliases": [
12353
+ "config"
12354
+ ],
12355
+ "char": "c",
12356
+ "description": "Context to check, overriding the current context (alias: --config)",
12357
+ "env": "ADERIS_CONTEXT",
12358
+ "name": "context",
12359
+ "hasDynamicHelp": false,
12360
+ "multiple": false,
12361
+ "type": "option"
12362
+ },
12363
+ "json": {
12364
+ "description": "Output as JSON",
12365
+ "name": "json",
12366
+ "allowNo": false,
12367
+ "type": "boolean"
12368
+ }
12369
+ },
12370
+ "hasDynamicHelp": false,
12371
+ "hiddenAliases": [],
12372
+ "id": "support:status",
12373
+ "pluginAlias": "@aderis-erp/cli",
12374
+ "pluginName": "@aderis-erp/cli",
12375
+ "pluginType": "core",
12376
+ "strict": true,
12377
+ "enableJsonFlag": false,
12378
+ "isESM": true,
12379
+ "relativePath": [
12380
+ "dist",
12381
+ "commands",
12382
+ "support",
12383
+ "status.js"
12384
+ ]
12385
+ },
12386
+ "support:tenants": {
12387
+ "aliases": [],
12388
+ "args": {},
12389
+ "description": "List the customers you may act for as Aderis Support",
12390
+ "examples": [
12391
+ "<%= config.bin %> support tenants",
12392
+ "<%= config.bin %> support tenants --context prod --json"
12393
+ ],
12394
+ "flags": {
12395
+ "context": {
12396
+ "aliases": [
12397
+ "config"
12398
+ ],
12399
+ "char": "c",
12400
+ "description": "Context to use, overriding the current context (alias: --config)",
12401
+ "env": "ADERIS_CONTEXT",
12402
+ "name": "context",
12403
+ "hasDynamicHelp": false,
12404
+ "multiple": false,
12405
+ "type": "option"
12406
+ },
12407
+ "json": {
12408
+ "description": "Output as JSON",
12409
+ "name": "json",
12410
+ "allowNo": false,
12411
+ "type": "boolean"
12412
+ }
12413
+ },
12414
+ "hasDynamicHelp": false,
12415
+ "hiddenAliases": [],
12416
+ "id": "support:tenants",
12417
+ "pluginAlias": "@aderis-erp/cli",
12418
+ "pluginName": "@aderis-erp/cli",
12419
+ "pluginType": "core",
12420
+ "strict": true,
12421
+ "enableJsonFlag": false,
12422
+ "isESM": true,
12423
+ "relativePath": [
12424
+ "dist",
12425
+ "commands",
12426
+ "support",
12427
+ "tenants.js"
12428
+ ]
12428
12429
  }
12429
12430
  },
12430
- "version": "1.1.0"
12431
+ "version": "1.1.1"
12431
12432
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@aderis-erp/cli",
3
3
  "description": "Aderis Live Finance Platform CLI - Manage your Aderis account from the command line",
4
- "version": "1.1.0",
4
+ "version": "1.1.1",
5
5
  "author": "Aderis AG",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -77,6 +77,9 @@
77
77
  },
78
78
  "config": {
79
79
  "description": "Configuration management - contexts, environments, and settings"
80
+ },
81
+ "support": {
82
+ "description": "Act as Aderis Support in a customer tenant (impersonation)"
80
83
  }
81
84
  }
82
85
  },
@@ -1,39 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class TagConfigurations extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
- id: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- context: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- table: import("@oclif/core/interfaces").BooleanFlag<boolean>;
13
- csv: import("@oclif/core/interfaces").BooleanFlag<boolean>;
14
- data: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
15
- file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
- set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
- page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
- limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
- include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
- search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
- 'sort-by': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
22
- filter: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
23
- query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
24
- fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
25
- sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
26
- 'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
27
- };
28
- run(): Promise<void>;
29
- private runImport;
30
- private runExport;
31
- private runCamt053Import;
32
- private runNestedImport;
33
- private parseFilterValue;
34
- private sanitizeOutput;
35
- private getColumns;
36
- private getValue;
37
- private printTable;
38
- private printCsv;
39
- }