@astrale-os/cli 1.0.0-beta.2 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/astrale.js +501 -396
- package/dist/public/connect-core.js +49 -12
- package/dist/public/keys/index.js +1 -1
- package/dist/public/paths/index.js +1 -1
- package/dist/types/lib/admin-target.d.ts +6 -2
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/update.d.ts +101 -0
- package/package.json +4 -4
- package/src/admin/__tests__/binding.test.ts +38 -0
- package/src/admin/binding.ts +9 -159
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/idp.test.ts +9 -4
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/idp.ts +5 -2
- package/viewer/dist/main.js +1 -1
|
@@ -47129,7 +47129,7 @@ function nonEmptyText(input, label) {
|
|
|
47129
47129
|
}
|
|
47130
47130
|
// node_modules/.pnpm/@astrale-os+kernel-protocol@0.5.0-beta.3_msgpackr@1.12.1_typescript@6.0.3/node_modules/@astrale-os/kernel-protocol/dist/routes/reservation.js
|
|
47131
47131
|
var STATIC_RESERVED_PATHS = new Set([PATH]);
|
|
47132
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
47132
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/auth/exchange.js
|
|
47133
47133
|
var paths2 = exports_issuer2.paths;
|
|
47134
47134
|
var acceptConfiguration2 = exports_issuer2.acceptConfiguration;
|
|
47135
47135
|
var MEDIA_TYPE5 = exports_issuer2.exchange.MEDIA_TYPE;
|
|
@@ -52063,7 +52063,7 @@ var log = {
|
|
|
52063
52063
|
};
|
|
52064
52064
|
var IS_CI = !!(process.env.CI || process.env.CONTINUOUS_INTEGRATION || process.env.NO_SPINNER);
|
|
52065
52065
|
|
|
52066
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52066
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/capability/define.js
|
|
52067
52067
|
var operations = new WeakSet;
|
|
52068
52068
|
var definitions = new WeakSet;
|
|
52069
52069
|
var providers = new WeakMap;
|
|
@@ -52192,7 +52192,7 @@ function isObject4(input) {
|
|
|
52192
52192
|
return input !== null && typeof input === "object";
|
|
52193
52193
|
}
|
|
52194
52194
|
|
|
52195
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52195
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/capability/client.js
|
|
52196
52196
|
function captureCapabilityRequirements(requirements) {
|
|
52197
52197
|
const source2 = acceptMap(requirements, "Capability requirements");
|
|
52198
52198
|
const names = ownStringKeys2(source2, "Capability requirements");
|
|
@@ -52223,22 +52223,22 @@ function ownDataValue2(input, key, label) {
|
|
|
52223
52223
|
return descriptor.value;
|
|
52224
52224
|
}
|
|
52225
52225
|
|
|
52226
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52226
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/view/admission.js
|
|
52227
52227
|
var admittedFrontendArtifacts = new WeakSet;
|
|
52228
52228
|
function isCapturedFrontendArtifact(input) {
|
|
52229
52229
|
return admittedFrontendArtifacts.has(input);
|
|
52230
52230
|
}
|
|
52231
52231
|
|
|
52232
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52232
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/workflow/binding.js
|
|
52233
52233
|
function isWorkflowBinding(input) {
|
|
52234
52234
|
return input !== null && typeof input === "object" && input.kind === "workflow" && typeof input.workflow?.run === "function";
|
|
52235
52235
|
}
|
|
52236
52236
|
function isTriggeredHandler(input) {
|
|
52237
52237
|
return input !== null && typeof input === "object" && input.kind === "handler" && typeof input.handler === "function";
|
|
52238
52238
|
}
|
|
52239
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52239
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/workflow/runner.js
|
|
52240
52240
|
var DIRECT_ACTIVATION = Object.freeze({ kind: "direct" });
|
|
52241
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52241
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/domain/handlers.js
|
|
52242
52242
|
function acceptDomainHandlers(domain3, input) {
|
|
52243
52243
|
const registry2 = record4(input, "handlers");
|
|
52244
52244
|
exactKeys2(registry2, ["functions", "classes", "interfaces"], "handlers");
|
|
@@ -52320,7 +52320,7 @@ function compareText3(left, right) {
|
|
|
52320
52320
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
52321
52321
|
}
|
|
52322
52322
|
|
|
52323
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52323
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/domain/requirements.js
|
|
52324
52324
|
var ClassOperationOrder2 = Object.freeze([
|
|
52325
52325
|
"create",
|
|
52326
52326
|
"read",
|
|
@@ -52405,7 +52405,7 @@ function compare7(left, right) {
|
|
|
52405
52405
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
52406
52406
|
}
|
|
52407
52407
|
|
|
52408
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
52408
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/domain/define.js
|
|
52409
52409
|
function defineDomain(input) {
|
|
52410
52410
|
const config2 = record5(input, "defineDomain input");
|
|
52411
52411
|
const hasCapabilities = Object.hasOwn(config2, "capabilities");
|
|
@@ -52615,6 +52615,7 @@ var IdpSessionSchema = exports_external2.object({
|
|
|
52615
52615
|
}).passthrough();
|
|
52616
52616
|
var BUILTIN_WORKOS_IDP_NAME = "workos";
|
|
52617
52617
|
var DEFAULT_WORKOS_API_HOST = "https://api.workos.com";
|
|
52618
|
+
var DEFAULT_WORKOS_CLIENT_ID = "client_01KC29HET5F3QAQ8GNTPZ7F320";
|
|
52618
52619
|
var WORKOS_CLIENT_ID_ENV_NAMES = ["WORKOS_CLIENT_ID", "VITE_WORKOS_CLIENT_ID"];
|
|
52619
52620
|
function idpDir(name) {
|
|
52620
52621
|
return paths3.idpDir(name);
|
|
@@ -52747,7 +52748,7 @@ function builtinIdpConfig(name, clientIdOverride, env2 = process.env) {
|
|
|
52747
52748
|
};
|
|
52748
52749
|
}
|
|
52749
52750
|
function workosClientIdFromEnv(env2 = process.env) {
|
|
52750
|
-
return WORKOS_CLIENT_ID_ENV_NAMES.map((name) => env2[name]?.trim()).find((value) => typeof value === "string" && value.length > 0);
|
|
52751
|
+
return WORKOS_CLIENT_ID_ENV_NAMES.map((name) => env2[name]?.trim()).find((value) => typeof value === "string" && value.length > 0) ?? DEFAULT_WORKOS_CLIENT_ID;
|
|
52751
52752
|
}
|
|
52752
52753
|
async function postForm(url3, params) {
|
|
52753
52754
|
const response2 = await fetch(url3, {
|
|
@@ -53261,10 +53262,46 @@ function isRegionRoutedInstanceRoot(url3) {
|
|
|
53261
53262
|
const labels = url3.hostname.toLowerCase().split(".");
|
|
53262
53263
|
return (labels.length === 4 || labels.length === 5) && /^[a-z]{2}(?:-[a-z0-9]+)*$/u.test(labels[1] ?? "") && labels.at(-2) === "astrale" && labels.at(-1) === "ai";
|
|
53263
53264
|
}
|
|
53265
|
+
// src/lib/update.ts
|
|
53266
|
+
var DEFAULT_REPO = "astrale-os/cli";
|
|
53267
|
+
var DEFAULT_UPDATE_CHANNEL = "beta";
|
|
53268
|
+
var InstallMetadataSchema = exports_external2.object({
|
|
53269
|
+
method: exports_external2.literal("script"),
|
|
53270
|
+
channel: exports_external2.string().min(1).default(DEFAULT_UPDATE_CHANNEL),
|
|
53271
|
+
version: exports_external2.string().min(1).optional(),
|
|
53272
|
+
repo: exports_external2.string().min(1).default(DEFAULT_REPO),
|
|
53273
|
+
bin: exports_external2.string().min(1),
|
|
53274
|
+
installedAt: exports_external2.string().optional()
|
|
53275
|
+
});
|
|
53276
|
+
var ManifestAssetSchema = exports_external2.object({
|
|
53277
|
+
name: exports_external2.string().min(1),
|
|
53278
|
+
sha256: exports_external2.string().regex(/^[a-fA-F0-9]{64}$/).optional()
|
|
53279
|
+
});
|
|
53280
|
+
var UpdateManifestSchema = exports_external2.object({
|
|
53281
|
+
version: exports_external2.string().min(1),
|
|
53282
|
+
binaryVersion: exports_external2.string().min(1).optional(),
|
|
53283
|
+
channel: exports_external2.string().min(1),
|
|
53284
|
+
repo: exports_external2.string().min(1).optional(),
|
|
53285
|
+
assets: exports_external2.record(exports_external2.string(), exports_external2.union([
|
|
53286
|
+
ManifestAssetSchema,
|
|
53287
|
+
exports_external2.string().min(1).transform((name) => ({ name }))
|
|
53288
|
+
]))
|
|
53289
|
+
});
|
|
53290
|
+
|
|
53264
53291
|
// src/lib/admin-target.ts
|
|
53265
53292
|
var DEFAULT_ADMIN_TARGET_NAME = "admin";
|
|
53266
|
-
|
|
53267
|
-
|
|
53293
|
+
function defaultAdminTargetForChannel(channel) {
|
|
53294
|
+
return channel === "stable" ? {
|
|
53295
|
+
url: "https://admin.eu.astrale.ai/api",
|
|
53296
|
+
domainIssuer: "https://admin.astrale.ai"
|
|
53297
|
+
} : {
|
|
53298
|
+
url: "https://admin.eu.beta.astrale.ai/api",
|
|
53299
|
+
domainIssuer: "https://admin.beta.astrale.ai"
|
|
53300
|
+
};
|
|
53301
|
+
}
|
|
53302
|
+
var DEFAULT_ADMIN_TARGET = defaultAdminTargetForChannel(DEFAULT_UPDATE_CHANNEL);
|
|
53303
|
+
var DEFAULT_ADMIN_TARGET_URL = DEFAULT_ADMIN_TARGET.url;
|
|
53304
|
+
var DEFAULT_ADMIN_DOMAIN_ISSUER = DEFAULT_ADMIN_TARGET.domainIssuer;
|
|
53268
53305
|
var DEFAULT_ADMIN_TARGET_CONFIG = {
|
|
53269
53306
|
name: DEFAULT_ADMIN_TARGET_NAME,
|
|
53270
53307
|
url: DEFAULT_ADMIN_TARGET_URL,
|
|
@@ -40188,7 +40188,7 @@ function nonEmptyText(input, label) {
|
|
|
40188
40188
|
}
|
|
40189
40189
|
// node_modules/.pnpm/@astrale-os+kernel-protocol@0.5.0-beta.3_msgpackr@1.12.1_typescript@6.0.3/node_modules/@astrale-os/kernel-protocol/dist/routes/reservation.js
|
|
40190
40190
|
var STATIC_RESERVED_PATHS = new Set([PATH]);
|
|
40191
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
40191
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/auth/exchange.js
|
|
40192
40192
|
var paths2 = exports_issuer2.paths;
|
|
40193
40193
|
var acceptConfiguration2 = exports_issuer2.acceptConfiguration;
|
|
40194
40194
|
var MEDIA_TYPE5 = exports_issuer2.exchange.MEDIA_TYPE;
|
|
@@ -38780,7 +38780,7 @@ function nonEmptyText(input, label) {
|
|
|
38780
38780
|
}
|
|
38781
38781
|
// node_modules/.pnpm/@astrale-os+kernel-protocol@0.5.0-beta.3_msgpackr@1.12.1_typescript@6.0.3/node_modules/@astrale-os/kernel-protocol/dist/routes/reservation.js
|
|
38782
38782
|
var STATIC_RESERVED_PATHS = new Set([PATH]);
|
|
38783
|
-
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.
|
|
38783
|
+
// node_modules/.pnpm/@astrale-os+sdk@0.5.0-beta.9_@astrale-os+ox@0.1.3_oxfmt@0.52.0_oxlint@1.79.0__msgpackr@1.12.1_oxlint@1.79.0/node_modules/@astrale-os/sdk/dist/auth/exchange.js
|
|
38784
38784
|
var paths2 = exports_issuer2.paths;
|
|
38785
38785
|
var acceptConfiguration2 = exports_issuer2.acceptConfiguration;
|
|
38786
38786
|
var MEDIA_TYPE5 = exports_issuer2.exchange.MEDIA_TYPE;
|
|
@@ -2,8 +2,12 @@ import { z } from 'zod';
|
|
|
2
2
|
import type { AstraleConfig } from './config';
|
|
3
3
|
import type { InstanceStore } from './instance';
|
|
4
4
|
export declare const DEFAULT_ADMIN_TARGET_NAME = "admin";
|
|
5
|
-
export declare
|
|
6
|
-
|
|
5
|
+
export declare function defaultAdminTargetForChannel(channel: string): {
|
|
6
|
+
readonly url: string;
|
|
7
|
+
readonly domainIssuer: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const DEFAULT_ADMIN_TARGET_URL: string;
|
|
10
|
+
export declare const DEFAULT_ADMIN_DOMAIN_ISSUER: string;
|
|
7
11
|
export declare const DEFAULT_ADMIN_TARGET_CONFIG: {
|
|
8
12
|
name: string;
|
|
9
13
|
url: string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ChildProcess, type StdioOptions } from 'node:child_process';
|
|
2
|
+
export type RunResult = {
|
|
3
|
+
/** Exit code, or -1 when the process was killed by a signal. */
|
|
4
|
+
code: number;
|
|
5
|
+
stdout: string;
|
|
6
|
+
stderr: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Spawn a child process and capture stdout/stderr as UTF-8 text.
|
|
10
|
+
*
|
|
11
|
+
* Uses `node:child_process` rather than `Bun.spawn` so the exact same code runs
|
|
12
|
+
* under both the Bun-compiled standalone binary (Linux/macOS) and the Node/npm
|
|
13
|
+
* build (Windows and any Node user). The promise rejects only when the process
|
|
14
|
+
* fails to spawn (e.g. ENOENT); a non-zero exit resolves with that `code` so
|
|
15
|
+
* callers can branch on it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function run(file: string, args?: string[], opts?: {
|
|
18
|
+
cwd?: string;
|
|
19
|
+
}): Promise<RunResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Spawn a child process with inherited stdio so its output streams live to the
|
|
22
|
+
* user's terminal. Used for hand-held installs (npm / npx) where progress
|
|
23
|
+
* matters and the output is for the human, not for parsing. Resolves with the
|
|
24
|
+
* exit code; rejects only when the process fails to spawn (e.g. ENOENT).
|
|
25
|
+
*/
|
|
26
|
+
export declare function runInherit(file: string, args?: string[], opts?: {
|
|
27
|
+
cwd?: string;
|
|
28
|
+
}): Promise<number>;
|
|
29
|
+
/**
|
|
30
|
+
* Spawn a LONG-LIVED child and return the handle immediately so the caller can
|
|
31
|
+
* supervise it (wait for exit, forward signals, tear down siblings). Unlike
|
|
32
|
+
* run()/runInherit() — which resolve only once the child closes — this is for
|
|
33
|
+
* servers the command keeps attached to (e.g. `astrale studio`'s Bun server and
|
|
34
|
+
* Vite dev process). Same node:child_process basis (cross-runtime) and bare
|
|
35
|
+
* PATH-name lookup convention. Default stdio streams stdout/stderr live but
|
|
36
|
+
* ignores stdin, so two supervised children never contend for the TTY.
|
|
37
|
+
*/
|
|
38
|
+
export declare function spawnHandle(file: string, args?: string[], opts?: {
|
|
39
|
+
cwd?: string;
|
|
40
|
+
env?: NodeJS.ProcessEnv;
|
|
41
|
+
stdio?: StdioOptions;
|
|
42
|
+
detached?: boolean;
|
|
43
|
+
}): ChildProcess;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const DEFAULT_UPDATE_CHANNEL = "beta";
|
|
3
|
+
export declare const InstallMetadataSchema: z.ZodObject<{
|
|
4
|
+
method: z.ZodLiteral<"script">;
|
|
5
|
+
channel: z.ZodDefault<z.ZodString>;
|
|
6
|
+
version: z.ZodOptional<z.ZodString>;
|
|
7
|
+
repo: z.ZodDefault<z.ZodString>;
|
|
8
|
+
bin: z.ZodString;
|
|
9
|
+
installedAt: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
method: "script";
|
|
12
|
+
channel: string;
|
|
13
|
+
version?: string | undefined;
|
|
14
|
+
repo: string;
|
|
15
|
+
bin: string;
|
|
16
|
+
installedAt?: string | undefined;
|
|
17
|
+
}, {
|
|
18
|
+
method: "script";
|
|
19
|
+
channel?: string | undefined;
|
|
20
|
+
version?: string | undefined;
|
|
21
|
+
repo?: string | undefined;
|
|
22
|
+
bin: string;
|
|
23
|
+
installedAt?: string | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
export type InstallMetadata = z.infer<typeof InstallMetadataSchema>;
|
|
26
|
+
export declare const UpdateManifestSchema: z.ZodObject<{
|
|
27
|
+
version: z.ZodString;
|
|
28
|
+
binaryVersion: z.ZodOptional<z.ZodString>;
|
|
29
|
+
channel: z.ZodString;
|
|
30
|
+
repo: z.ZodOptional<z.ZodString>;
|
|
31
|
+
assets: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
sha256: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, "strip", z.ZodTypeAny, {
|
|
35
|
+
name: string;
|
|
36
|
+
sha256?: string | undefined;
|
|
37
|
+
}, {
|
|
38
|
+
name: string;
|
|
39
|
+
sha256?: string | undefined;
|
|
40
|
+
}>, z.ZodEffects<z.ZodString, {
|
|
41
|
+
name: string;
|
|
42
|
+
}, string>]>>;
|
|
43
|
+
}, "strip", z.ZodTypeAny, {
|
|
44
|
+
version: string;
|
|
45
|
+
binaryVersion?: string | undefined;
|
|
46
|
+
channel: string;
|
|
47
|
+
repo?: string | undefined;
|
|
48
|
+
assets: Record<string, {
|
|
49
|
+
name: string;
|
|
50
|
+
sha256?: string | undefined;
|
|
51
|
+
} | {
|
|
52
|
+
name: string;
|
|
53
|
+
}>;
|
|
54
|
+
}, {
|
|
55
|
+
version: string;
|
|
56
|
+
binaryVersion?: string | undefined;
|
|
57
|
+
channel: string;
|
|
58
|
+
repo?: string | undefined;
|
|
59
|
+
assets: Record<string, string | {
|
|
60
|
+
name: string;
|
|
61
|
+
sha256?: string | undefined;
|
|
62
|
+
}>;
|
|
63
|
+
}>;
|
|
64
|
+
export type UpdateManifest = z.infer<typeof UpdateManifestSchema>;
|
|
65
|
+
export type Platform = {
|
|
66
|
+
os: 'darwin' | 'linux';
|
|
67
|
+
arch: 'arm64' | 'x64';
|
|
68
|
+
};
|
|
69
|
+
export type UpdateRequest = {
|
|
70
|
+
check?: boolean;
|
|
71
|
+
channel?: string;
|
|
72
|
+
version?: string;
|
|
73
|
+
currentVersion: string;
|
|
74
|
+
platform?: Platform;
|
|
75
|
+
installPath?: string;
|
|
76
|
+
};
|
|
77
|
+
export type UpdateResult = {
|
|
78
|
+
status: 'up-to-date';
|
|
79
|
+
currentVersion: string;
|
|
80
|
+
latestVersion: string;
|
|
81
|
+
channel: string;
|
|
82
|
+
} | {
|
|
83
|
+
status: 'available';
|
|
84
|
+
currentVersion: string;
|
|
85
|
+
latestVersion: string;
|
|
86
|
+
channel: string;
|
|
87
|
+
} | {
|
|
88
|
+
status: 'updated';
|
|
89
|
+
previousVersion: string;
|
|
90
|
+
currentVersion: string;
|
|
91
|
+
channel: string;
|
|
92
|
+
bin: string;
|
|
93
|
+
};
|
|
94
|
+
export declare function detectPlatform(): Platform;
|
|
95
|
+
export declare function platformKey(platform: Platform): string;
|
|
96
|
+
export declare function readInstallMetadata(path?: string): Promise<InstallMetadata>;
|
|
97
|
+
export declare function writeInstallMetadata(meta: InstallMetadata, path?: string): Promise<void>;
|
|
98
|
+
export declare function releaseBase(meta: InstallMetadata, req: Pick<UpdateRequest, 'channel' | 'version'>): string;
|
|
99
|
+
export declare function fetchManifest(base: string): Promise<UpdateManifest>;
|
|
100
|
+
export declare function shouldUpdate(currentVersion: string, manifestVersion: string): boolean;
|
|
101
|
+
export declare function updateAstrale(req: UpdateRequest): Promise<UpdateResult>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrale-os/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "Astrale CLI — connect to existing Astrale kernels",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"devDependencies": {
|
|
65
65
|
"@astrale-os/kernel-client": ">=0.6.0-beta.4 <1.0.0",
|
|
66
66
|
"@astrale-os/kernel-protocol": ">=0.5.0-beta.3 <1.0.0",
|
|
67
|
-
"@astrale-os/ox": ">=0.1.
|
|
68
|
-
"@astrale-os/sdk": ">=0.5.0-beta.
|
|
67
|
+
"@astrale-os/ox": ">=0.1.3 <1.0.0",
|
|
68
|
+
"@astrale-os/sdk": ">=0.5.0-beta.9 <1.0.0",
|
|
69
69
|
"@astrale-os/shell": ">=0.3.8-beta.2 <1.0.0",
|
|
70
70
|
"@astrale/commitlint-config": "npm:@jsr/astrale__commitlint-config@~2.0.1",
|
|
71
71
|
"@commitlint/cli": "~20.3.1",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"scripts": {
|
|
103
103
|
"preinstall": "node .check-workspace.cjs",
|
|
104
104
|
"build": "bun scripts/build.ts",
|
|
105
|
-
"package:check": "pnpm run typecheck && pnpm run test && pnpm run build && node scripts/verify-public-exports.mjs && node scripts/verify-
|
|
105
|
+
"package:check": "pnpm run typecheck && pnpm run test && pnpm run build && node scripts/verify-public-exports.mjs && node scripts/verify-public-dependency-boundary.mjs",
|
|
106
106
|
"typecheck": "tsgo --noEmit && tsgo --noEmit -p tsconfig.tests.json && tsgo --noEmit -p viewer && tsgo --noEmit -p studio",
|
|
107
107
|
"lint": "oxlint .",
|
|
108
108
|
"lint:fix": "oxlint --fix .",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ClientSession } from '@astrale-os/kernel-client/session'
|
|
2
|
+
|
|
3
|
+
import { defineDomain } from '@astrale-os/sdk'
|
|
4
|
+
import { issuer } from '@astrale-os/sdk/auth'
|
|
5
|
+
import { createDeployment } from '@astrale-os/sdk/deployment'
|
|
6
|
+
import { defineSchema } from '@astrale-os/sdk/schema/v1'
|
|
7
|
+
import { expect, mock, test } from 'bun:test'
|
|
8
|
+
|
|
9
|
+
import { bindAdmin } from '../binding'
|
|
10
|
+
|
|
11
|
+
const schema = defineSchema('admin.astrale.ai', {})
|
|
12
|
+
const deployment = createDeployment({
|
|
13
|
+
definition: defineDomain({
|
|
14
|
+
schema,
|
|
15
|
+
handlers: { functions: {}, classes: {}, interfaces: {} },
|
|
16
|
+
}),
|
|
17
|
+
issuer: issuer.accept('https://admin.beta.astrale.ai'),
|
|
18
|
+
bundleHref: 'https://admin.beta.astrale.ai/domain.bundle.json',
|
|
19
|
+
bindings: { callables: [] },
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
test('binds the installed Admin Domain instead of the source Kernel publication', async () => {
|
|
23
|
+
const installed = mock(async () => ({
|
|
24
|
+
state: 'ready' as const,
|
|
25
|
+
target: 'sha256:admin-target' as const,
|
|
26
|
+
source: { kind: 'remote' as const, publication: deployment.publication },
|
|
27
|
+
bundle: deployment.bundle,
|
|
28
|
+
readiness: 'sha256:admin-readiness' as const,
|
|
29
|
+
capabilities: { requested: [], materialized: [] },
|
|
30
|
+
}))
|
|
31
|
+
const session = { installed } as unknown as ClientSession
|
|
32
|
+
|
|
33
|
+
const binding = await bindAdmin(session)
|
|
34
|
+
|
|
35
|
+
expect(installed).toHaveBeenCalledWith('admin.astrale.ai')
|
|
36
|
+
expect(binding.$.origin).toBe('admin.astrale.ai')
|
|
37
|
+
expect(String(binding.$.publication?.identity.issuer)).toBe('https://admin.beta.astrale.ai')
|
|
38
|
+
})
|
package/src/admin/binding.ts
CHANGED
|
@@ -1,168 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
ClientSession,
|
|
4
|
-
SessionRequestOptions,
|
|
5
|
-
SessionSnapshot,
|
|
6
|
-
} from '@astrale-os/kernel-client/session'
|
|
7
|
-
import type {
|
|
8
|
-
Definition,
|
|
9
|
-
Domain as RichDomain,
|
|
10
|
-
InstanceMethod,
|
|
11
|
-
StaticMethod,
|
|
12
|
-
} from '@astrale-os/sdk/domain'
|
|
13
|
-
import type { PathLike } from '@astrale-os/sdk/graph/path'
|
|
14
|
-
import type { Key } from '@astrale-os/sdk/schema'
|
|
1
|
+
import type { DomainBinding } from '@astrale-os/kernel-client/domain'
|
|
2
|
+
import type { ClientSession } from '@astrale-os/kernel-client/session'
|
|
15
3
|
|
|
16
|
-
import {
|
|
17
|
-
import * as sessionModule from '@astrale-os/kernel-client/session'
|
|
18
|
-
import { Domain } from '@astrale-os/sdk/domain'
|
|
19
|
-
import { Path } from '@astrale-os/sdk/graph/path'
|
|
4
|
+
import { bind } from '@astrale-os/kernel-client/domain'
|
|
20
5
|
|
|
21
6
|
const ADMIN_ORIGIN = 'admin.astrale.ai'
|
|
22
7
|
|
|
23
|
-
type
|
|
24
|
-
| (Definition<'function'> & { readonly path: NonNullable<Definition<'function'>['path']> })
|
|
25
|
-
| StaticMethod
|
|
26
|
-
| InstanceMethod
|
|
8
|
+
export type AdminBinding = DomainBinding
|
|
27
9
|
|
|
28
|
-
|
|
29
|
-
readonly installation: unknown
|
|
30
|
-
readonly publication: SessionSnapshot['publication']
|
|
31
|
-
invoke(
|
|
32
|
-
callable: DynamicCallable,
|
|
33
|
-
receiverOrInput: PathLike | Input,
|
|
34
|
-
inputOrOptions?: Input | SessionRequestOptions,
|
|
35
|
-
options?: SessionRequestOptions,
|
|
36
|
-
): Promise<unknown>
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export type AdminBinding = RichDomain & {
|
|
40
|
-
readonly $: RichDomain['$'] & AdminBindingOperations
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface CompatibleCallableReference {
|
|
44
|
-
readonly origin: typeof ADMIN_ORIGIN
|
|
45
|
-
readonly revision: SessionSnapshot['publication']['schema']['revision']
|
|
46
|
-
readonly callable: Key.Callable
|
|
47
|
-
readonly target: PathLike
|
|
48
|
-
readonly outputMode: DynamicCallable['definition']['output']['mode']
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
interface CompatibleSession {
|
|
52
|
-
readonly installation?: (origin: typeof ADMIN_ORIGIN) => Promise<unknown>
|
|
53
|
-
readonly installed?: (origin: typeof ADMIN_ORIGIN) => Promise<unknown>
|
|
54
|
-
readonly invoke?: (
|
|
55
|
-
reference: CompatibleCallableReference,
|
|
56
|
-
input: Input,
|
|
57
|
-
options?: SessionRequestOptions,
|
|
58
|
-
) => Promise<unknown>
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
type LegacyDispatchBound = (
|
|
62
|
-
session: ClientSession,
|
|
63
|
-
request: ReturnType<typeof call>,
|
|
64
|
-
expected: {
|
|
65
|
-
readonly schema: { readonly revision: CompatibleCallableReference['revision'] }
|
|
66
|
-
readonly publication: {
|
|
67
|
-
readonly origin: SessionSnapshot['publication']['origin']
|
|
68
|
-
readonly identity: SessionSnapshot['publication']['identity']
|
|
69
|
-
readonly revision: CompatibleCallableReference['revision']
|
|
70
|
-
readonly etag: SessionSnapshot['publication']['etag']
|
|
71
|
-
}
|
|
72
|
-
},
|
|
73
|
-
options?: SessionRequestOptions,
|
|
74
|
-
) => Promise<Result>
|
|
75
|
-
|
|
76
|
-
/** Bind the Admin revision advertised by this exact Session snapshot. */
|
|
10
|
+
/** Bind the exact Admin revision installed on this source Kernel. */
|
|
77
11
|
export async function bindAdmin(session: ClientSession): Promise<AdminBinding> {
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
snapshot.bundle.root.origin !== ADMIN_ORIGIN
|
|
82
|
-
) {
|
|
12
|
+
const installed = await session.installed(ADMIN_ORIGIN)
|
|
13
|
+
const binding = bind(session, installed)
|
|
14
|
+
if (binding.$.publication?.origin !== ADMIN_ORIGIN || binding.$.origin !== ADMIN_ORIGIN) {
|
|
83
15
|
throw new TypeError('Configured Admin target does not serve the Admin Domain.')
|
|
84
16
|
}
|
|
85
|
-
|
|
86
|
-
const resolveInstallation = compatible.installation ?? compatible.installed
|
|
87
|
-
if (resolveInstallation === undefined) {
|
|
88
|
-
throw new TypeError('Client Session cannot resolve an installed Admin Domain.')
|
|
89
|
-
}
|
|
90
|
-
const installation = await resolveInstallation.call(session, ADMIN_ORIGIN)
|
|
91
|
-
const domain = Domain.fromSchema(snapshot.bundle.root)
|
|
92
|
-
const invoke = ((
|
|
93
|
-
callable: DynamicCallable,
|
|
94
|
-
receiverOrInput: PathLike | Input,
|
|
95
|
-
inputOrOptions?: Input | SessionRequestOptions,
|
|
96
|
-
options?: SessionRequestOptions,
|
|
97
|
-
) => {
|
|
98
|
-
const target =
|
|
99
|
-
'on' in callable ? callable.on(Path.from(receiverOrInput as PathLike)) : callable.path
|
|
100
|
-
const reference: CompatibleCallableReference = Object.freeze({
|
|
101
|
-
origin: ADMIN_ORIGIN,
|
|
102
|
-
revision: snapshot.publication.schema.revision,
|
|
103
|
-
callable: callable.key as Key.Callable,
|
|
104
|
-
target,
|
|
105
|
-
outputMode: callable.definition.output.mode,
|
|
106
|
-
})
|
|
107
|
-
return invokeCompatible(
|
|
108
|
-
session,
|
|
109
|
-
snapshot,
|
|
110
|
-
reference,
|
|
111
|
-
('on' in callable ? inputOrOptions : receiverOrInput) as Input,
|
|
112
|
-
('on' in callable ? options : inputOrOptions) as SessionRequestOptions | undefined,
|
|
113
|
-
)
|
|
114
|
-
}) as AdminBindingOperations['invoke']
|
|
115
|
-
|
|
116
|
-
return Object.freeze({
|
|
117
|
-
...domain,
|
|
118
|
-
$: Object.freeze({
|
|
119
|
-
...domain.$,
|
|
120
|
-
installation,
|
|
121
|
-
publication: snapshot.publication,
|
|
122
|
-
invoke,
|
|
123
|
-
}),
|
|
124
|
-
}) as AdminBinding
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function invokeCompatible(
|
|
128
|
-
session: ClientSession,
|
|
129
|
-
snapshot: SessionSnapshot,
|
|
130
|
-
reference: CompatibleCallableReference,
|
|
131
|
-
input: Input,
|
|
132
|
-
options: SessionRequestOptions | undefined,
|
|
133
|
-
): Promise<unknown> {
|
|
134
|
-
const current = session as unknown as CompatibleSession
|
|
135
|
-
if (current.invoke !== undefined) return current.invoke(reference, input, options)
|
|
136
|
-
|
|
137
|
-
const dispatchBound = (sessionModule as unknown as { dispatchBound?: LegacyDispatchBound })
|
|
138
|
-
.dispatchBound
|
|
139
|
-
if (dispatchBound === undefined) {
|
|
140
|
-
throw new TypeError('Client Session cannot invoke an exact Admin publication.')
|
|
141
|
-
}
|
|
142
|
-
const result = await dispatchBound(
|
|
143
|
-
session,
|
|
144
|
-
call(reference.target, input),
|
|
145
|
-
{
|
|
146
|
-
schema: { revision: reference.revision },
|
|
147
|
-
publication: {
|
|
148
|
-
origin: snapshot.publication.origin,
|
|
149
|
-
identity: snapshot.publication.identity,
|
|
150
|
-
revision: snapshot.publication.schema.revision,
|
|
151
|
-
etag: snapshot.publication.etag,
|
|
152
|
-
},
|
|
153
|
-
},
|
|
154
|
-
options,
|
|
155
|
-
)
|
|
156
|
-
return requireOutput(reference.outputMode, result)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function requireOutput(
|
|
160
|
-
expected: CompatibleCallableReference['outputMode'],
|
|
161
|
-
result: Result,
|
|
162
|
-
): unknown {
|
|
163
|
-
if (result.kind !== expected) {
|
|
164
|
-
if (result.kind === 'stream') void result.stream.cancel(`Admin callable declared ${expected}.`)
|
|
165
|
-
throw new TypeError(`Admin callable declared ${expected} output but returned ${result.kind}.`)
|
|
166
|
-
}
|
|
167
|
-
return result.kind === 'stream' ? result.stream : result.value
|
|
17
|
+
return binding
|
|
168
18
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
DEFAULT_ADMIN_TARGET_NAME,
|
|
7
7
|
DEFAULT_ADMIN_DOMAIN_ISSUER,
|
|
8
8
|
DEFAULT_ADMIN_TARGET_URL,
|
|
9
|
+
defaultAdminTargetForChannel,
|
|
9
10
|
resolveAdminTargetFromStore,
|
|
10
11
|
} from '../admin-target'
|
|
11
12
|
import { DEFAULT_CONFIG, type AstraleConfig } from '../config'
|
|
@@ -32,6 +33,17 @@ const instances: InstanceStore = {
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
describe('resolveAdminTargetFromStore', () => {
|
|
36
|
+
test('derives hosted Admin defaults from the release channel', () => {
|
|
37
|
+
expect(defaultAdminTargetForChannel('beta')).toEqual({
|
|
38
|
+
url: 'https://admin.eu.beta.astrale.ai/api',
|
|
39
|
+
domainIssuer: 'https://admin.beta.astrale.ai',
|
|
40
|
+
})
|
|
41
|
+
expect(defaultAdminTargetForChannel('stable')).toEqual({
|
|
42
|
+
url: 'https://admin.eu.astrale.ai/api',
|
|
43
|
+
domainIssuer: 'https://admin.astrale.ai',
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
35
47
|
test('uses hosted admin default without active instance coupling', () => {
|
|
36
48
|
expect(resolveAdminTargetFromStore({}, DEFAULT_CONFIG, instances)).toEqual({
|
|
37
49
|
name: DEFAULT_ADMIN_TARGET_NAME,
|
|
@@ -63,8 +63,11 @@ describe('IdP schemas and token helpers', () => {
|
|
|
63
63
|
expect(config?.client.token_request_format).toBe('json')
|
|
64
64
|
})
|
|
65
65
|
|
|
66
|
-
test('
|
|
67
|
-
|
|
66
|
+
test('builds the built-in WorkOS IdP with the public client id by default', () => {
|
|
67
|
+
const config = builtinIdpConfig('workos', undefined, {})
|
|
68
|
+
|
|
69
|
+
expect(config?.entry.builtIn).toBe(true)
|
|
70
|
+
expect(config?.client.client_id).toBe('client_01KC29HET5F3QAQ8GNTPZ7F320')
|
|
68
71
|
})
|
|
69
72
|
|
|
70
73
|
test('reads WorkOS client id from WORKOS_CLIENT_ID before VITE_WORKOS_CLIENT_ID', () => {
|
|
@@ -75,8 +78,10 @@ describe('IdP schemas and token helpers', () => {
|
|
|
75
78
|
}),
|
|
76
79
|
).toBe('client_primary')
|
|
77
80
|
expect(workosClientIdFromEnv({ VITE_WORKOS_CLIENT_ID: 'client_vite' })).toBe('client_vite')
|
|
78
|
-
expect(workosClientIdFromEnv({})).
|
|
79
|
-
expect(workosClientIdFromEnv({ WORKOS_CLIENT_ID: ' ' })).
|
|
81
|
+
expect(workosClientIdFromEnv({})).toBe('client_01KC29HET5F3QAQ8GNTPZ7F320')
|
|
82
|
+
expect(workosClientIdFromEnv({ WORKOS_CLIENT_ID: ' ' })).toBe(
|
|
83
|
+
'client_01KC29HET5F3QAQ8GNTPZ7F320',
|
|
84
|
+
)
|
|
80
85
|
})
|
|
81
86
|
|
|
82
87
|
test('stores client secret env names, not secret material', () => {
|
package/src/lib/admin-target.ts
CHANGED
|
@@ -5,11 +5,30 @@ import type { InstanceStore } from './instance'
|
|
|
5
5
|
|
|
6
6
|
import { AstraleError } from '../errors'
|
|
7
7
|
import { readInstances, resolveInstanceKey } from './instance'
|
|
8
|
+
import { DEFAULT_UPDATE_CHANNEL } from './update'
|
|
8
9
|
import { isHttpUrl } from './validation'
|
|
9
10
|
|
|
10
11
|
export const DEFAULT_ADMIN_TARGET_NAME = 'admin'
|
|
11
|
-
|
|
12
|
-
export
|
|
12
|
+
|
|
13
|
+
export function defaultAdminTargetForChannel(channel: string): {
|
|
14
|
+
readonly url: string
|
|
15
|
+
readonly domainIssuer: string
|
|
16
|
+
} {
|
|
17
|
+
return channel === 'stable'
|
|
18
|
+
? {
|
|
19
|
+
url: 'https://admin.eu.astrale.ai/api',
|
|
20
|
+
domainIssuer: 'https://admin.astrale.ai',
|
|
21
|
+
}
|
|
22
|
+
: {
|
|
23
|
+
url: 'https://admin.eu.beta.astrale.ai/api',
|
|
24
|
+
domainIssuer: 'https://admin.beta.astrale.ai',
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const DEFAULT_ADMIN_TARGET = defaultAdminTargetForChannel(DEFAULT_UPDATE_CHANNEL)
|
|
29
|
+
|
|
30
|
+
export const DEFAULT_ADMIN_TARGET_URL = DEFAULT_ADMIN_TARGET.url
|
|
31
|
+
export const DEFAULT_ADMIN_DOMAIN_ISSUER = DEFAULT_ADMIN_TARGET.domainIssuer
|
|
13
32
|
|
|
14
33
|
export const DEFAULT_ADMIN_TARGET_CONFIG = {
|
|
15
34
|
name: DEFAULT_ADMIN_TARGET_NAME,
|