@carthooks/arcubase-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/arcubase-admin.mjs +9875 -0
- package/bundle/arcubase.mjs +9875 -0
- package/dist/bin/arcubase-admin.d.ts +2 -0
- package/dist/bin/arcubase-admin.d.ts.map +1 -0
- package/dist/bin/arcubase-admin.js +22 -0
- package/dist/bin/arcubase.d.ts +2 -0
- package/dist/bin/arcubase.d.ts.map +1 -0
- package/dist/bin/arcubase.js +22 -0
- package/dist/generated/command_registry.generated.d.ts +3072 -0
- package/dist/generated/command_registry.generated.d.ts.map +1 -0
- package/dist/generated/command_registry.generated.js +4587 -0
- package/dist/generated/type_index.generated.d.ts +496 -0
- package/dist/generated/type_index.generated.d.ts.map +1 -0
- package/dist/generated/type_index.generated.js +502 -0
- package/dist/generated/zod_registry.generated.d.ts +356 -0
- package/dist/generated/zod_registry.generated.d.ts.map +1 -0
- package/dist/generated/zod_registry.generated.js +483 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/runtime/argv.d.ts +8 -0
- package/dist/runtime/argv.d.ts.map +1 -0
- package/dist/runtime/argv.js +31 -0
- package/dist/runtime/body_loader.d.ts +3 -0
- package/dist/runtime/body_loader.d.ts.map +1 -0
- package/dist/runtime/body_loader.js +26 -0
- package/dist/runtime/command_registry.d.ts +9 -0
- package/dist/runtime/command_registry.d.ts.map +1 -0
- package/dist/runtime/command_registry.js +14 -0
- package/dist/runtime/env.d.ts +14 -0
- package/dist/runtime/env.d.ts.map +1 -0
- package/dist/runtime/env.js +42 -0
- package/dist/runtime/errors.d.ts +23 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/errors.js +18 -0
- package/dist/runtime/execute.d.ts +17 -0
- package/dist/runtime/execute.d.ts.map +1 -0
- package/dist/runtime/execute.js +183 -0
- package/dist/runtime/http.d.ts +4 -0
- package/dist/runtime/http.d.ts.map +1 -0
- package/dist/runtime/http.js +21 -0
- package/dist/runtime/output.d.ts +2 -0
- package/dist/runtime/output.d.ts.map +1 -0
- package/dist/runtime/output.js +3 -0
- package/dist/runtime/paths.d.ts +4 -0
- package/dist/runtime/paths.d.ts.map +1 -0
- package/dist/runtime/paths.js +8 -0
- package/dist/runtime/zod_registry.d.ts +10 -0
- package/dist/runtime/zod_registry.d.ts.map +1 -0
- package/dist/runtime/zod_registry.js +50 -0
- package/dist/tests/bootstrap.test.d.ts +2 -0
- package/dist/tests/bootstrap.test.d.ts.map +1 -0
- package/dist/tests/bootstrap.test.js +59 -0
- package/dist/tests/command_registry.test.d.ts +2 -0
- package/dist/tests/command_registry.test.d.ts.map +1 -0
- package/dist/tests/command_registry.test.js +22 -0
- package/dist/tests/execute_validation.test.d.ts +2 -0
- package/dist/tests/execute_validation.test.d.ts.map +1 -0
- package/dist/tests/execute_validation.test.js +41 -0
- package/dist/tests/help.test.d.ts +2 -0
- package/dist/tests/help.test.d.ts.map +1 -0
- package/dist/tests/help.test.js +22 -0
- package/dist/tests/zod_registry.test.d.ts +2 -0
- package/dist/tests/zod_registry.test.d.ts.map +1 -0
- package/dist/tests/zod_registry.test.js +26 -0
- package/package.json +46 -0
- package/sdk-dist/api/admin/app-entity-share.ts +52 -0
- package/sdk-dist/api/admin/app.ts +187 -0
- package/sdk-dist/api/admin/automate-rule.ts +59 -0
- package/sdk-dist/api/admin/business-hooks.ts +17 -0
- package/sdk-dist/api/admin/config.ts +12 -0
- package/sdk-dist/api/admin/dashboard.ts +88 -0
- package/sdk-dist/api/admin/dataset.ts +133 -0
- package/sdk-dist/api/admin/departments.ts +223 -0
- package/sdk-dist/api/admin/developer.ts +126 -0
- package/sdk-dist/api/admin/entity-tags.ts +71 -0
- package/sdk-dist/api/admin/entity.ts +188 -0
- package/sdk-dist/api/admin/extension.ts +19 -0
- package/sdk-dist/api/admin/index.ts +21 -0
- package/sdk-dist/api/admin/ingress.ts +117 -0
- package/sdk-dist/api/admin/integration.ts +64 -0
- package/sdk-dist/api/admin/kiosk-flow.ts +67 -0
- package/sdk-dist/api/admin/print-template-background.ts +43 -0
- package/sdk-dist/api/admin/print-templates.ts +60 -0
- package/sdk-dist/api/admin/tenant.ts +231 -0
- package/sdk-dist/api/admin/workflow.ts +51 -0
- package/sdk-dist/api/kiosk/index.ts +4 -0
- package/sdk-dist/api/kiosk/starter.ts +34 -0
- package/sdk-dist/api/kiosk/ui.ts +79 -0
- package/sdk-dist/api/open/api.ts +11 -0
- package/sdk-dist/api/open/index.ts +3 -0
- package/sdk-dist/api/shared-link/form.ts +103 -0
- package/sdk-dist/api/shared-link/index.ts +3 -0
- package/sdk-dist/api/user/common.ts +159 -0
- package/sdk-dist/api/user/context.ts +10 -0
- package/sdk-dist/api/user/copilot.ts +20 -0
- package/sdk-dist/api/user/dashboard.ts +43 -0
- package/sdk-dist/api/user/entity.ts +213 -0
- package/sdk-dist/api/user/flow.ts +20 -0
- package/sdk-dist/api/user/global-action.ts +128 -0
- package/sdk-dist/api/user/index.ts +12 -0
- package/sdk-dist/api/user/kiosk.ts +12 -0
- package/sdk-dist/api/user/profile.ts +57 -0
- package/sdk-dist/api/user/workflow.ts +186 -0
- package/sdk-dist/generated/command_registry.generated.ts +4603 -0
- package/sdk-dist/generated/type_index.generated.ts +503 -0
- package/sdk-dist/generated/zod_registry.generated.ts +713 -0
- package/sdk-dist/types/app-user.ts +0 -0
- package/sdk-dist/types/app.ts +182 -0
- package/sdk-dist/types/auth.ts +174 -0
- package/sdk-dist/types/automate-rule.ts +100 -0
- package/sdk-dist/types/business-hooks.ts +37 -0
- package/sdk-dist/types/common.ts +676 -0
- package/sdk-dist/types/copilot.ts +34 -0
- package/sdk-dist/types/dashboard.ts +122 -0
- package/sdk-dist/types/dataset.ts +168 -0
- package/sdk-dist/types/departments.ts +351 -0
- package/sdk-dist/types/developer.ts +190 -0
- package/sdk-dist/types/entity.ts +400 -0
- package/sdk-dist/types/extension.ts +15 -0
- package/sdk-dist/types/global-action.ts +206 -0
- package/sdk-dist/types/index.ts +26 -0
- package/sdk-dist/types/ingress.ts +173 -0
- package/sdk-dist/types/kiosk-starter.ts +46 -0
- package/sdk-dist/types/kiosk-ui.ts +94 -0
- package/sdk-dist/types/oauth-authorize.ts +52 -0
- package/sdk-dist/types/oauth.ts +33 -0
- package/sdk-dist/types/openapi.ts +24 -0
- package/sdk-dist/types/platform-setup.ts +26 -0
- package/sdk-dist/types/shared-link.ts +41 -0
- package/sdk-dist/types/tenant.ts +340 -0
- package/sdk-dist/types/upload.ts +0 -0
- package/sdk-dist/types/user-action.ts +871 -0
- package/sdk-dist/types/user-flow.ts +90 -0
- package/sdk-dist/types/widgets.ts +115 -0
- package/sdk-dist/types/workflow.ts +162 -0
- package/src/bin/arcubase-admin.ts +23 -0
- package/src/bin/arcubase.ts +23 -0
- package/src/generated/command_registry.generated.ts +4603 -0
- package/src/generated/type_index.generated.ts +503 -0
- package/src/generated/zod_registry.generated.ts +713 -0
- package/src/index.ts +4 -0
- package/src/runtime/argv.ts +39 -0
- package/src/runtime/body_loader.ts +26 -0
- package/src/runtime/command_registry.ts +22 -0
- package/src/runtime/env.ts +60 -0
- package/src/runtime/errors.ts +41 -0
- package/src/runtime/execute.ts +206 -0
- package/src/runtime/http.ts +23 -0
- package/src/runtime/output.ts +3 -0
- package/src/runtime/paths.ts +8 -0
- package/src/runtime/zod_registry.ts +53 -0
- package/src/tests/bootstrap.test.ts +67 -0
- package/src/tests/command_registry.test.ts +27 -0
- package/src/tests/execute_validation.test.ts +50 -0
- package/src/tests/help.test.ts +25 -0
- package/src/tests/zod_registry.test.ts +33 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body_loader.d.ts","sourceRoot":"","sources":["../../src/runtime/body_loader.ts"],"names":[],"mappings":"AAWA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,GAAG,SAAS,CAI9F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAQ3G"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { CLIError } from './errors.js';
|
|
3
|
+
function parseJSONFile(filePath, label) {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
throw new CLIError('INVALID_JSON_FILE', `${label} file is invalid: ${filePath}`, 2);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function loadBodyFromFlags(flags) {
|
|
12
|
+
const bodyFile = typeof flags['body-file'] === 'string' ? flags['body-file'] : undefined;
|
|
13
|
+
if (!bodyFile)
|
|
14
|
+
return undefined;
|
|
15
|
+
return parseJSONFile(bodyFile, 'body');
|
|
16
|
+
}
|
|
17
|
+
export function loadQueryFromFlags(flags) {
|
|
18
|
+
const queryFile = typeof flags['query-file'] === 'string' ? flags['query-file'] : undefined;
|
|
19
|
+
if (!queryFile)
|
|
20
|
+
return undefined;
|
|
21
|
+
const parsed = parseJSONFile(queryFile, 'query');
|
|
22
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
23
|
+
throw new CLIError('INVALID_QUERY_FILE', 'query file must contain a JSON object', 2);
|
|
24
|
+
}
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { adminCommands, userCommands } from '../generated/command_registry.generated.js';
|
|
2
|
+
export { adminCommands, userCommands };
|
|
3
|
+
export type CommandScope = 'admin' | 'user';
|
|
4
|
+
export type CommandDef = (typeof adminCommands)[number] | (typeof userCommands)[number];
|
|
5
|
+
export declare function listCommands(scope: CommandScope): readonly CommandDef[];
|
|
6
|
+
export declare function findCommand(scope: CommandScope, moduleName: string, commandName: string): CommandDef | null;
|
|
7
|
+
export declare function listModules(scope: CommandScope): string[];
|
|
8
|
+
export declare function listModuleCommands(scope: CommandScope, moduleName: string): readonly CommandDef[];
|
|
9
|
+
//# sourceMappingURL=command_registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/command_registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAA;AAExF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,CAAA;AAEtC,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,CAAA;AAC3C,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvF,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,UAAU,EAAE,CAEvE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAE3G;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,UAAU,EAAE,CAEjG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { adminCommands, userCommands } from '../generated/command_registry.generated.js';
|
|
2
|
+
export { adminCommands, userCommands };
|
|
3
|
+
export function listCommands(scope) {
|
|
4
|
+
return scope === 'admin' ? adminCommands : userCommands;
|
|
5
|
+
}
|
|
6
|
+
export function findCommand(scope, moduleName, commandName) {
|
|
7
|
+
return listCommands(scope).find((item) => item.commandPath[0] === moduleName && item.commandPath[1] === commandName) ?? null;
|
|
8
|
+
}
|
|
9
|
+
export function listModules(scope) {
|
|
10
|
+
return [...new Set(listCommands(scope).map((item) => item.commandPath[0]))].sort();
|
|
11
|
+
}
|
|
12
|
+
export function listModuleCommands(scope, moduleName) {
|
|
13
|
+
return listCommands(scope).filter((item) => item.commandPath[0] === moduleName);
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type RuntimeEnv = {
|
|
2
|
+
ARCUBASE_BASE_URL: string;
|
|
3
|
+
ARCUBASE_TENANT_ID: string;
|
|
4
|
+
ARCUBASE_ACCESS_TOKEN: string;
|
|
5
|
+
ARCUBASE_TRACE_ID?: string;
|
|
6
|
+
ARCUBASE_SUBJECT_TYPE?: string;
|
|
7
|
+
ARCUBASE_SUBJECT_ID?: string;
|
|
8
|
+
ARCUBASE_TOKEN_EXPIRES_AT?: string;
|
|
9
|
+
};
|
|
10
|
+
export type RuntimeEnvScope = 'admin' | 'user';
|
|
11
|
+
type EnvInput = Record<string, string | undefined>;
|
|
12
|
+
export declare function loadRuntimeEnv(scope: RuntimeEnvScope, env?: EnvInput): RuntimeEnv;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/runtime/env.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,yBAAyB,CAAC,EAAE,MAAM,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAA;AAE9C,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAqClD,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,GAAE,QAAsB,GAAG,UAAU,CAU9F"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const PREFIX_BY_SCOPE = {
|
|
2
|
+
admin: 'ARCUBASE_ADMIN_',
|
|
3
|
+
user: 'ARCUBASE_USER_',
|
|
4
|
+
};
|
|
5
|
+
function envValue(env, scope, key) {
|
|
6
|
+
const direct = env[key];
|
|
7
|
+
if (direct && direct.trim() !== '') {
|
|
8
|
+
return direct.trim();
|
|
9
|
+
}
|
|
10
|
+
const suffix = String(key).replace(/^ARCUBASE_/, '');
|
|
11
|
+
const scopedKey = `${PREFIX_BY_SCOPE[scope]}${suffix}`;
|
|
12
|
+
const scopedValue = env[scopedKey];
|
|
13
|
+
if (!scopedValue || scopedValue.trim() === '') {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return scopedValue.trim();
|
|
17
|
+
}
|
|
18
|
+
function requiredValue(env, scope, key) {
|
|
19
|
+
const value = envValue(env, scope, key);
|
|
20
|
+
if (!value || value.trim() === '') {
|
|
21
|
+
throw new Error(`${key} is required`);
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function optionalValue(env, scope, key) {
|
|
26
|
+
const value = envValue(env, scope, key);
|
|
27
|
+
if (!value || value.trim() === '') {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
export function loadRuntimeEnv(scope, env = process.env) {
|
|
33
|
+
return {
|
|
34
|
+
ARCUBASE_BASE_URL: requiredValue(env, scope, 'ARCUBASE_BASE_URL'),
|
|
35
|
+
ARCUBASE_TENANT_ID: requiredValue(env, scope, 'ARCUBASE_TENANT_ID'),
|
|
36
|
+
ARCUBASE_ACCESS_TOKEN: requiredValue(env, scope, 'ARCUBASE_ACCESS_TOKEN'),
|
|
37
|
+
ARCUBASE_TRACE_ID: optionalValue(env, scope, 'ARCUBASE_TRACE_ID'),
|
|
38
|
+
ARCUBASE_SUBJECT_TYPE: optionalValue(env, scope, 'ARCUBASE_SUBJECT_TYPE'),
|
|
39
|
+
ARCUBASE_SUBJECT_ID: optionalValue(env, scope, 'ARCUBASE_SUBJECT_ID'),
|
|
40
|
+
ARCUBASE_TOKEN_EXPIRES_AT: optionalValue(env, scope, 'ARCUBASE_TOKEN_EXPIRES_AT')
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type CLIValidationIssue = {
|
|
2
|
+
path: string;
|
|
3
|
+
message: string;
|
|
4
|
+
};
|
|
5
|
+
export type CLITSTypeHint = {
|
|
6
|
+
symbol: string;
|
|
7
|
+
file: string;
|
|
8
|
+
};
|
|
9
|
+
export type CLIErrorDetails = {
|
|
10
|
+
operation?: string;
|
|
11
|
+
requestType?: string;
|
|
12
|
+
issues?: CLIValidationIssue[];
|
|
13
|
+
tsHints?: CLITSTypeHint[];
|
|
14
|
+
reason?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare class CLIError extends Error {
|
|
17
|
+
readonly code: string;
|
|
18
|
+
readonly exitCode: number;
|
|
19
|
+
readonly details?: CLIErrorDetails;
|
|
20
|
+
constructor(code: string, message: string, exitCode?: number, details?: CLIErrorDetails);
|
|
21
|
+
toJSON(): Record<string, unknown>;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/runtime/errors.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,MAAM,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC7B,OAAO,CAAC,EAAE,aAAa,EAAE,CAAA;IACzB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAA;gBAEtB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAI,EAAE,OAAO,CAAC,EAAE,eAAe;IAQlF,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASlC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export class CLIError extends Error {
|
|
2
|
+
constructor(code, message, exitCode = 1, details) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'CLIError';
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.exitCode = exitCode;
|
|
7
|
+
this.details = details;
|
|
8
|
+
}
|
|
9
|
+
toJSON() {
|
|
10
|
+
return {
|
|
11
|
+
error: {
|
|
12
|
+
code: this.code,
|
|
13
|
+
message: this.message,
|
|
14
|
+
...(this.details ? this.details : {}),
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type RuntimeEnv } from './env.js';
|
|
2
|
+
import { type CommandScope } from './command_registry.js';
|
|
3
|
+
export type CommandExecutionSummary = {
|
|
4
|
+
scope: CommandScope;
|
|
5
|
+
commandPath: readonly [string, string];
|
|
6
|
+
method: string;
|
|
7
|
+
endpoint: string;
|
|
8
|
+
requestType: string | null;
|
|
9
|
+
pathFlags: readonly string[];
|
|
10
|
+
scalarFlags: readonly string[];
|
|
11
|
+
};
|
|
12
|
+
export declare function renderRootHelp(scope: CommandScope): string;
|
|
13
|
+
export declare function renderModuleHelp(scope: CommandScope, moduleName: string): string;
|
|
14
|
+
export declare function renderCommandHelp(scope: CommandScope, moduleName: string, commandName: string): string;
|
|
15
|
+
export declare function summarizeCommand(scope: CommandScope, moduleName: string, commandName: string): CommandExecutionSummary;
|
|
16
|
+
export declare function executeCLI(scope: CommandScope, argv: string[], env?: RuntimeEnv, fetchImpl?: typeof fetch): Promise<any>;
|
|
17
|
+
//# sourceMappingURL=execute.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/runtime/execute.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAG1D,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAIvG,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,YAAY,CAAA;IACnB,WAAW,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAC/B,CAAA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAQ1D;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAWhF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAatG;AA8CD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,uBAAuB,CActH;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,UAAkC,EAAE,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,GAAG,CAAC,CAyF5J"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { parseCLIArgs, hasFlag, flagValue } from './argv.js';
|
|
2
|
+
import { loadRuntimeEnv } from './env.js';
|
|
3
|
+
import { CLIError } from './errors.js';
|
|
4
|
+
import { buildRequestHeaders, buildURL } from './http.js';
|
|
5
|
+
import { listModules, listModuleCommands, findCommand } from './command_registry.js';
|
|
6
|
+
import { loadBodyFromFlags, loadQueryFromFlags } from './body_loader.js';
|
|
7
|
+
import { getBodySchema, getTypeHints, getUnsupportedBodySchemaReason } from './zod_registry.js';
|
|
8
|
+
export function renderRootHelp(scope) {
|
|
9
|
+
const binary = scope === 'admin' ? 'arcubase-admin' : 'arcubase';
|
|
10
|
+
return [
|
|
11
|
+
`${binary} <module> <command> [flags]`,
|
|
12
|
+
'',
|
|
13
|
+
'modules:',
|
|
14
|
+
...listModules(scope).map((item) => ` - ${item}`),
|
|
15
|
+
].join('\n');
|
|
16
|
+
}
|
|
17
|
+
export function renderModuleHelp(scope, moduleName) {
|
|
18
|
+
const items = listModuleCommands(scope, moduleName);
|
|
19
|
+
if (items.length === 0) {
|
|
20
|
+
throw new CLIError('UNKNOWN_MODULE', `unknown module: ${moduleName}`, 2);
|
|
21
|
+
}
|
|
22
|
+
return [
|
|
23
|
+
`${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${moduleName} <command> [flags]`,
|
|
24
|
+
'',
|
|
25
|
+
'commands:',
|
|
26
|
+
...items.map((item) => ` - ${item.commandPath[1]}`),
|
|
27
|
+
].join('\n');
|
|
28
|
+
}
|
|
29
|
+
export function renderCommandHelp(scope, moduleName, commandName) {
|
|
30
|
+
const command = findCommand(scope, moduleName, commandName);
|
|
31
|
+
if (!command) {
|
|
32
|
+
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName} ${commandName}`, 2);
|
|
33
|
+
}
|
|
34
|
+
return [
|
|
35
|
+
`${scope === 'admin' ? 'arcubase-admin' : 'arcubase'} ${moduleName} ${commandName}`,
|
|
36
|
+
`method: ${command.method}`,
|
|
37
|
+
`endpoint: ${command.endpoint}`,
|
|
38
|
+
command.requestType ? `body: ${command.requestType} via --body-file` : 'body: none',
|
|
39
|
+
command.endpointParams.length ? `path flags: ${command.endpointParams.map((item) => `--${item.replace(/_/g, '-')}`).join(', ')}` : 'path flags: none',
|
|
40
|
+
command.scalarParams.length ? `scalar flags: ${command.scalarParams.map((item) => `--${item.name.replace(/([A-Z])/g, '-$1').toLowerCase()}`).join(', ')}` : 'scalar flags: none',
|
|
41
|
+
].join('\n');
|
|
42
|
+
}
|
|
43
|
+
function coerceScalar(value, typeText) {
|
|
44
|
+
const normalized = typeText.trim();
|
|
45
|
+
if (normalized === 'number' || normalized === 'string | number') {
|
|
46
|
+
const parsed = Number(value);
|
|
47
|
+
if (Number.isNaN(parsed)) {
|
|
48
|
+
throw new CLIError('INVALID_FLAG_VALUE', `expected number, got ${value}`, 2);
|
|
49
|
+
}
|
|
50
|
+
return parsed;
|
|
51
|
+
}
|
|
52
|
+
if (normalized === 'boolean') {
|
|
53
|
+
if (value === 'true')
|
|
54
|
+
return true;
|
|
55
|
+
if (value === 'false')
|
|
56
|
+
return false;
|
|
57
|
+
throw new CLIError('INVALID_FLAG_VALUE', `expected boolean, got ${value}`, 2);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function resolveEndpoint(endpoint, flags) {
|
|
62
|
+
let resolved = endpoint;
|
|
63
|
+
for (const placeholder of [...endpoint.matchAll(/:([A-Za-z0-9_]+)/g)].map((match) => match[1])) {
|
|
64
|
+
const flagName = placeholder.replace(/_/g, '-');
|
|
65
|
+
const value = flagValue(flags, flagName);
|
|
66
|
+
if (!value) {
|
|
67
|
+
throw new CLIError('MISSING_PATH_FLAG', `missing required flag --${flagName}`, 2);
|
|
68
|
+
}
|
|
69
|
+
resolved = resolved.replace(`:${placeholder}`, encodeURIComponent(value));
|
|
70
|
+
}
|
|
71
|
+
return resolved;
|
|
72
|
+
}
|
|
73
|
+
function buildScalarQuery(command, flags) {
|
|
74
|
+
if (!command) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const out = {};
|
|
78
|
+
for (const scalar of command.scalarParams) {
|
|
79
|
+
const flagName = scalar.name.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
80
|
+
const value = flagValue(flags, flagName);
|
|
81
|
+
if (value === undefined)
|
|
82
|
+
continue;
|
|
83
|
+
out[scalar.name] = coerceScalar(value, scalar.type);
|
|
84
|
+
}
|
|
85
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
86
|
+
}
|
|
87
|
+
export function summarizeCommand(scope, moduleName, commandName) {
|
|
88
|
+
const command = findCommand(scope, moduleName, commandName);
|
|
89
|
+
if (!command) {
|
|
90
|
+
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName} ${commandName}`, 2);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
scope,
|
|
94
|
+
commandPath: command.commandPath,
|
|
95
|
+
method: command.method,
|
|
96
|
+
endpoint: command.endpoint,
|
|
97
|
+
requestType: command.requestType,
|
|
98
|
+
pathFlags: command.endpointParams,
|
|
99
|
+
scalarFlags: command.scalarParams.map((item) => item.name.replace(/([A-Z])/g, '-$1').toLowerCase()),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export async function executeCLI(scope, argv, env = loadRuntimeEnv(scope), fetchImpl = fetch) {
|
|
103
|
+
const parsed = parseCLIArgs(argv);
|
|
104
|
+
if (parsed.commandTokens.length === 0) {
|
|
105
|
+
return { kind: 'help', text: renderRootHelp(scope) };
|
|
106
|
+
}
|
|
107
|
+
const [moduleName, commandName] = parsed.commandTokens;
|
|
108
|
+
if (!moduleName) {
|
|
109
|
+
return { kind: 'help', text: renderRootHelp(scope) };
|
|
110
|
+
}
|
|
111
|
+
if (!commandName) {
|
|
112
|
+
return { kind: 'help', text: renderModuleHelp(scope, moduleName) };
|
|
113
|
+
}
|
|
114
|
+
if (hasFlag(parsed.flags, 'help')) {
|
|
115
|
+
return { kind: 'help', text: renderCommandHelp(scope, moduleName, commandName) };
|
|
116
|
+
}
|
|
117
|
+
const command = findCommand(scope, moduleName, commandName);
|
|
118
|
+
if (!command) {
|
|
119
|
+
throw new CLIError('UNKNOWN_COMMAND', `unknown command: ${moduleName} ${commandName}`, 2);
|
|
120
|
+
}
|
|
121
|
+
const endpoint = resolveEndpoint(command.endpoint, parsed.flags);
|
|
122
|
+
const scalarQuery = buildScalarQuery(command, parsed.flags);
|
|
123
|
+
const fileQuery = loadQueryFromFlags(parsed.flags);
|
|
124
|
+
const query = { ...(scalarQuery ?? {}), ...(fileQuery ?? {}) };
|
|
125
|
+
const body = loadBodyFromFlags(parsed.flags);
|
|
126
|
+
if (command.requestType) {
|
|
127
|
+
if (body === undefined) {
|
|
128
|
+
throw new CLIError('MISSING_BODY_FILE', `command requires --body-file for ${command.requestType}`, 2);
|
|
129
|
+
}
|
|
130
|
+
const schema = getBodySchema(command.requestType);
|
|
131
|
+
if (schema) {
|
|
132
|
+
const parsedBody = schema.safeParse(body);
|
|
133
|
+
if (!parsedBody.success) {
|
|
134
|
+
throw new CLIError('BODY_VALIDATION_FAILED', parsedBody.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('; '), 2, {
|
|
135
|
+
operation: `${scope}.${command.module}.${command.functionName}`,
|
|
136
|
+
requestType: command.requestType,
|
|
137
|
+
issues: parsedBody.error.issues.map((issue) => ({
|
|
138
|
+
path: issue.path.length > 0 ? `body.${issue.path.join('.')}` : 'body',
|
|
139
|
+
message: issue.message,
|
|
140
|
+
})),
|
|
141
|
+
tsHints: getTypeHints(command.requestType),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const unsupportedReason = getUnsupportedBodySchemaReason(command.requestType);
|
|
147
|
+
if (unsupportedReason) {
|
|
148
|
+
throw new CLIError('UNSUPPORTED_BODY_SCHEMA', `${command.requestType}: ${unsupportedReason}`, 2, {
|
|
149
|
+
operation: `${scope}.${command.module}.${command.functionName}`,
|
|
150
|
+
requestType: command.requestType,
|
|
151
|
+
reason: unsupportedReason,
|
|
152
|
+
tsHints: getTypeHints(command.requestType),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const headers = buildRequestHeaders(env);
|
|
158
|
+
const response = await fetchImpl(buildURL(env.ARCUBASE_BASE_URL, endpoint, Object.keys(query).length > 0 ? query : undefined), {
|
|
159
|
+
method: command.method,
|
|
160
|
+
headers: {
|
|
161
|
+
...headers,
|
|
162
|
+
'Content-Type': 'application/json',
|
|
163
|
+
},
|
|
164
|
+
body: body === undefined || command.method === 'GET' ? undefined : JSON.stringify(body),
|
|
165
|
+
});
|
|
166
|
+
const raw = await response.text();
|
|
167
|
+
let parsedResponse = raw;
|
|
168
|
+
try {
|
|
169
|
+
parsedResponse = raw ? JSON.parse(raw) : null;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
// keep raw text
|
|
173
|
+
}
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
throw new CLIError('UPSTREAM_REQUEST_FAILED', typeof parsedResponse === 'string' ? parsedResponse : JSON.stringify(parsedResponse), 1);
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
kind: 'result',
|
|
179
|
+
commandPath: command.commandPath,
|
|
180
|
+
status: response.status,
|
|
181
|
+
data: parsedResponse,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { RuntimeEnv } from './env.js';
|
|
2
|
+
export declare function buildRequestHeaders(env: Pick<RuntimeEnv, 'ARCUBASE_ACCESS_TOKEN' | 'ARCUBASE_TENANT_ID' | 'ARCUBASE_TRACE_ID'>): Record<string, string>;
|
|
3
|
+
export declare function buildURL(baseURL: string, endpoint: string, query?: Record<string, any>): string;
|
|
4
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/runtime/http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,EAAE,uBAAuB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASvJ;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAS/F"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function buildRequestHeaders(env) {
|
|
2
|
+
const headers = {
|
|
3
|
+
Authorization: `Bearer ${env.ARCUBASE_ACCESS_TOKEN}`,
|
|
4
|
+
'X-Tenant-Id': env.ARCUBASE_TENANT_ID
|
|
5
|
+
};
|
|
6
|
+
if (env.ARCUBASE_TRACE_ID) {
|
|
7
|
+
headers['X-Trace-Id'] = env.ARCUBASE_TRACE_ID;
|
|
8
|
+
}
|
|
9
|
+
return headers;
|
|
10
|
+
}
|
|
11
|
+
export function buildURL(baseURL, endpoint, query) {
|
|
12
|
+
const url = new URL(endpoint, baseURL.endsWith('/') ? baseURL : `${baseURL}/`);
|
|
13
|
+
if (query) {
|
|
14
|
+
for (const [key, value] of Object.entries(query)) {
|
|
15
|
+
if (value === undefined || value === null)
|
|
16
|
+
continue;
|
|
17
|
+
url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return url.toString();
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/runtime/output.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE9C"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const DEFAULT_ARCUBASE_CLI_ROOT = "/opt/arcubase-cli";
|
|
2
|
+
export declare const DEFAULT_ARCUBASE_SDK_ROOT = "/opt/arcubase-sdk";
|
|
3
|
+
export declare function resolveArcubaseSDKRoot(env?: Record<string, string | undefined>): string;
|
|
4
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/runtime/paths.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,sBAAsB,CAAA;AAC5D,eAAO,MAAM,yBAAyB,sBAAsB,CAAA;AAE5D,wBAAgB,sBAAsB,CAAC,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,MAAM,CAIpG"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const DEFAULT_ARCUBASE_CLI_ROOT = '/opt/arcubase-cli';
|
|
2
|
+
export const DEFAULT_ARCUBASE_SDK_ROOT = '/opt/arcubase-sdk';
|
|
3
|
+
export function resolveArcubaseSDKRoot(env = process.env) {
|
|
4
|
+
const value = env.ARCUBASE_SDK_ROOT?.trim();
|
|
5
|
+
if (value)
|
|
6
|
+
return value;
|
|
7
|
+
return DEFAULT_ARCUBASE_SDK_ROOT;
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ZodTypeAny } from 'zod';
|
|
2
|
+
export declare function getBodySchema(typeName: string): ZodTypeAny | null;
|
|
3
|
+
export declare function getUnsupportedBodySchemaReason(typeName: string): string | null;
|
|
4
|
+
export declare function requireBodySchema(typeName: string): ZodTypeAny;
|
|
5
|
+
export type RuntimeTypeHint = {
|
|
6
|
+
symbol: string;
|
|
7
|
+
file: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function getTypeHints(typeName: string): RuntimeTypeHint[];
|
|
10
|
+
//# sourceMappingURL=zod_registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod_registry.d.ts","sourceRoot":"","sources":["../../src/runtime/zod_registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAIrC,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAIjE;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9E;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAQ9D;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAqBhE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { bodySchemas, unsupportedBodySchemas } from '../generated/zod_registry.generated.js';
|
|
2
|
+
import { typeIndex } from '../generated/type_index.generated.js';
|
|
3
|
+
export function getBodySchema(typeName) {
|
|
4
|
+
const name = String(typeName || '').trim();
|
|
5
|
+
if (!name)
|
|
6
|
+
return null;
|
|
7
|
+
return bodySchemas[name] ?? null;
|
|
8
|
+
}
|
|
9
|
+
export function getUnsupportedBodySchemaReason(typeName) {
|
|
10
|
+
const name = String(typeName || '').trim();
|
|
11
|
+
if (!name)
|
|
12
|
+
return null;
|
|
13
|
+
return unsupportedBodySchemas[name] ?? null;
|
|
14
|
+
}
|
|
15
|
+
export function requireBodySchema(typeName) {
|
|
16
|
+
const schema = getBodySchema(typeName);
|
|
17
|
+
if (schema)
|
|
18
|
+
return schema;
|
|
19
|
+
const reason = getUnsupportedBodySchemaReason(typeName);
|
|
20
|
+
if (reason) {
|
|
21
|
+
throw new Error(`runtime validation for ${typeName} is not supported: ${reason}`);
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`runtime validation schema not found for ${typeName}`);
|
|
24
|
+
}
|
|
25
|
+
export function getTypeHints(typeName) {
|
|
26
|
+
const name = String(typeName || '').trim();
|
|
27
|
+
if (!name)
|
|
28
|
+
return [];
|
|
29
|
+
const entry = typeIndex[name];
|
|
30
|
+
if (!entry?.file)
|
|
31
|
+
return [];
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
const out = [];
|
|
34
|
+
const append = (symbol, file) => {
|
|
35
|
+
symbol = String(symbol || '').trim();
|
|
36
|
+
file = String(file || '').trim();
|
|
37
|
+
if (!symbol || !file)
|
|
38
|
+
return;
|
|
39
|
+
const key = `${symbol}@@${file}`;
|
|
40
|
+
if (seen.has(key))
|
|
41
|
+
return;
|
|
42
|
+
seen.add(key);
|
|
43
|
+
out.push({ symbol, file });
|
|
44
|
+
};
|
|
45
|
+
append(name, entry.file);
|
|
46
|
+
for (const dep of entry.dependencies ?? []) {
|
|
47
|
+
append(dep.symbol, dep.file);
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.test.d.ts","sourceRoot":"","sources":["../../src/tests/bootstrap.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { loadRuntimeEnv } from '../runtime/env.js';
|
|
4
|
+
test('loadRuntimeEnv requires base url, tenant id and access token', () => {
|
|
5
|
+
assert.throws(() => loadRuntimeEnv('admin', {}), /ARCUBASE_BASE_URL is required/);
|
|
6
|
+
});
|
|
7
|
+
test('loadRuntimeEnv returns normalized runtime env', () => {
|
|
8
|
+
const env = loadRuntimeEnv('admin', {
|
|
9
|
+
ARCUBASE_BASE_URL: ' http://example.com ',
|
|
10
|
+
ARCUBASE_TENANT_ID: ' tenant-1 ',
|
|
11
|
+
ARCUBASE_ACCESS_TOKEN: ' token-1 ',
|
|
12
|
+
ARCUBASE_TRACE_ID: ' trace-1 '
|
|
13
|
+
});
|
|
14
|
+
assert.deepEqual(env, {
|
|
15
|
+
ARCUBASE_BASE_URL: 'http://example.com',
|
|
16
|
+
ARCUBASE_TENANT_ID: 'tenant-1',
|
|
17
|
+
ARCUBASE_ACCESS_TOKEN: 'token-1',
|
|
18
|
+
ARCUBASE_TRACE_ID: 'trace-1',
|
|
19
|
+
ARCUBASE_SUBJECT_TYPE: undefined,
|
|
20
|
+
ARCUBASE_SUBJECT_ID: undefined,
|
|
21
|
+
ARCUBASE_TOKEN_EXPIRES_AT: undefined
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
test('loadRuntimeEnv accepts admin-prefixed runtime env', () => {
|
|
25
|
+
const env = loadRuntimeEnv('admin', {
|
|
26
|
+
ARCUBASE_ADMIN_BASE_URL: ' https://admin.example.com ',
|
|
27
|
+
ARCUBASE_ADMIN_TENANT_ID: ' tenant-admin ',
|
|
28
|
+
ARCUBASE_ADMIN_ACCESS_TOKEN: ' token-admin ',
|
|
29
|
+
ARCUBASE_ADMIN_SUBJECT_TYPE: ' system_admin ',
|
|
30
|
+
ARCUBASE_ADMIN_SUBJECT_ID: ' user-admin ',
|
|
31
|
+
});
|
|
32
|
+
assert.deepEqual(env, {
|
|
33
|
+
ARCUBASE_BASE_URL: 'https://admin.example.com',
|
|
34
|
+
ARCUBASE_TENANT_ID: 'tenant-admin',
|
|
35
|
+
ARCUBASE_ACCESS_TOKEN: 'token-admin',
|
|
36
|
+
ARCUBASE_TRACE_ID: undefined,
|
|
37
|
+
ARCUBASE_SUBJECT_TYPE: 'system_admin',
|
|
38
|
+
ARCUBASE_SUBJECT_ID: 'user-admin',
|
|
39
|
+
ARCUBASE_TOKEN_EXPIRES_AT: undefined
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
test('loadRuntimeEnv accepts user-prefixed runtime env', () => {
|
|
43
|
+
const env = loadRuntimeEnv('user', {
|
|
44
|
+
ARCUBASE_USER_BASE_URL: ' https://user.example.com ',
|
|
45
|
+
ARCUBASE_USER_TENANT_ID: ' tenant-user ',
|
|
46
|
+
ARCUBASE_USER_ACCESS_TOKEN: ' token-user ',
|
|
47
|
+
ARCUBASE_USER_SUBJECT_TYPE: ' service_account ',
|
|
48
|
+
ARCUBASE_USER_SUBJECT_ID: ' sa-user ',
|
|
49
|
+
});
|
|
50
|
+
assert.deepEqual(env, {
|
|
51
|
+
ARCUBASE_BASE_URL: 'https://user.example.com',
|
|
52
|
+
ARCUBASE_TENANT_ID: 'tenant-user',
|
|
53
|
+
ARCUBASE_ACCESS_TOKEN: 'token-user',
|
|
54
|
+
ARCUBASE_TRACE_ID: undefined,
|
|
55
|
+
ARCUBASE_SUBJECT_TYPE: 'service_account',
|
|
56
|
+
ARCUBASE_SUBJECT_ID: 'sa-user',
|
|
57
|
+
ARCUBASE_TOKEN_EXPIRES_AT: undefined
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command_registry.test.d.ts","sourceRoot":"","sources":["../../src/tests/command_registry.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { adminCommands, userCommands } from '../generated/command_registry.generated.js';
|
|
4
|
+
test('admin app create-entity command exists', () => {
|
|
5
|
+
assert.ok(adminCommands.some((c) => c.commandPath.join(' ') === 'app create-entity'));
|
|
6
|
+
});
|
|
7
|
+
test('user workflow query-entity command exists', () => {
|
|
8
|
+
assert.ok(userCommands.some((c) => c.commandPath.join(' ') === 'workflow query-entity'));
|
|
9
|
+
});
|
|
10
|
+
test('inline request type keeps full object text instead of truncated brace', () => {
|
|
11
|
+
const command = adminCommands.find((c) => c.commandPath.join(' ') === 'dashboard clone-dashboard');
|
|
12
|
+
assert.ok(command);
|
|
13
|
+
const typed = command;
|
|
14
|
+
assert.match(String(typed.requestType), /^\{\s*name:\s*string\s*\}$/);
|
|
15
|
+
});
|
|
16
|
+
test('tag commands no longer emit truncated inline request type', () => {
|
|
17
|
+
const command = adminCommands.find((c) => c.commandPath.join(' ') === 'entity-tags batch-add-entity-tags');
|
|
18
|
+
assert.ok(command);
|
|
19
|
+
const typed = command;
|
|
20
|
+
assert.match(String(typed.requestType), /^\{\s*policy_id:\s*string.*selection:\s*any.*tag_names:\s*string\[\]\s*\}$/);
|
|
21
|
+
assert.equal(typed.scalarParams.length, 0);
|
|
22
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute_validation.test.d.ts","sourceRoot":"","sources":["../../src/tests/execute_validation.test.ts"],"names":[],"mappings":""}
|