@astrale-os/cli 1.0.0-beta.2 → 1.0.0-beta.20
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 +16 -1
- package/dist/astrale.js +51105 -58057
- package/dist/public/connect-core.js +2085 -30702
- package/dist/public/keys/index.js +884 -29476
- package/dist/public/paths/index.js +13101 -41452
- package/dist/types/admin/contract.d.ts +26 -0
- package/dist/types/admin/instance/client.d.ts +20 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +6 -10
- package/dist/types/connection/auth.d.ts +3 -0
- package/dist/types/connection/call.d.ts +3 -0
- package/dist/types/connection/command.d.ts +27 -0
- package/dist/types/connection/credential.d.ts +14 -0
- package/dist/types/connection/errors.d.ts +1 -0
- package/dist/types/connection/exchange.d.ts +9 -0
- package/dist/types/connection/failure/classify.d.ts +2 -0
- package/dist/types/connection/failure/index.d.ts +5 -0
- package/dist/types/connection/failure/model.d.ts +25 -0
- package/dist/types/connection/failure/render.d.ts +3 -0
- package/dist/types/connection/index.d.ts +8 -0
- package/dist/types/connection/reasons.d.ts +37 -0
- package/dist/types/connection/self.d.ts +37 -0
- package/dist/types/connection/session.d.ts +31 -0
- package/dist/types/connection/target.d.ts +38 -0
- package/dist/types/errors.d.ts +1 -1
- package/dist/types/lib/admin-instance.d.ts +17 -0
- package/dist/types/lib/admin-target.d.ts +11 -36
- package/dist/types/lib/config.d.ts +7 -59
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +25 -173
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +30 -88
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/output.d.ts +1 -1
- package/dist/types/lib/proc.d.ts +43 -0
- package/dist/types/lib/self.d.ts +9 -0
- package/dist/types/lib/update.d.ts +109 -0
- package/dist/types/lib/validation.d.ts +4 -1
- package/package.json +15 -20
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/.spec/architecture.md +12 -5
- package/src/admin/__tests__/fixture.ts +25 -0
- package/src/admin/catalog/.spec/api.d.ts +1 -3
- package/src/admin/catalog/.spec/architecture.md +5 -4
- package/src/admin/catalog/__tests__/client.test.ts +143 -69
- package/src/admin/catalog/client.ts +40 -54
- package/src/admin/catalog/model.ts +3 -4
- package/src/admin/contract.ts +46 -0
- package/src/admin/graph/.spec/api.d.ts +4 -10
- package/src/admin/graph/nodes.ts +1 -1
- package/src/admin/instance/.spec/api.d.ts +5 -9
- package/src/admin/instance/.spec/architecture.md +7 -7
- package/src/admin/instance/__tests__/client.test.ts +157 -175
- package/src/admin/instance/client.ts +39 -128
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +12 -18
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +34 -0
- package/src/commands/__tests__/domain-install-operation.test.ts +7 -22
- package/src/commands/__tests__/domain-install-owned.test.ts +1 -1
- package/src/commands/__tests__/domain-list.test.ts +5 -25
- package/src/commands/__tests__/install-direct.test.ts +115 -8
- package/src/commands/__tests__/install-identity-override.test.ts +3 -14
- package/src/commands/__tests__/instance-list-rows.test.ts +1 -1
- package/src/commands/__tests__/instance-status.test.ts +139 -0
- package/src/commands/__tests__/introspect-parse.test.ts +80 -1
- package/src/commands/__tests__/logs.test.ts +250 -2
- package/src/commands/__tests__/read-commands.test.ts +62 -10
- package/src/commands/__tests__/token-ttl.test.ts +49 -4
- package/src/commands/__tests__/update.test.ts +25 -3
- package/src/commands/__tests__/view.test.ts +49 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +71 -59
- package/src/commands/domain/install.ts +54 -35
- package/src/commands/domain/list.ts +1 -1
- package/src/commands/domain/publish.ts +14 -11
- package/src/commands/domain/uninstall.ts +2 -2
- package/src/commands/get.ts +14 -15
- package/src/commands/identity/__tests__/register.test.ts +3 -3
- package/src/commands/identity/register.ts +5 -4
- package/src/commands/instance/create.ts +8 -16
- package/src/commands/instance/delete.ts +12 -9
- package/src/commands/instance/list.ts +2 -2
- package/src/commands/instance/status.ts +66 -20
- package/src/commands/instance/use.ts +16 -12
- package/src/commands/introspect.ts +48 -35
- package/src/commands/logs.ts +123 -33
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +35 -32
- package/src/commands/token.ts +42 -27
- package/src/commands/ui/__tests__/commands.test.ts +152 -0
- package/src/commands/ui/add.ts +51 -0
- package/src/commands/ui/doctor.ts +13 -0
- package/src/commands/ui/init.ts +38 -0
- package/src/commands/ui/list.ts +26 -0
- package/src/commands/ui/preset-apply.ts +19 -0
- package/src/commands/ui/preset-list.ts +12 -0
- package/src/commands/ui/shared.ts +25 -0
- package/src/commands/update.ts +31 -11
- package/src/commands/view.ts +82 -37
- package/src/connection/.spec/api.d.ts +7 -8
- package/src/connection/.spec/architecture.md +5 -4
- package/src/connection/.spec/flows/session.ts +2 -2
- package/src/connection/.spec/laws/connection.ts +6 -2
- package/src/connection/.spec/layout.ts +1 -0
- package/src/connection/__tests__/credential.test.ts +20 -1
- package/src/connection/__tests__/errors.test.ts +27 -20
- package/src/connection/__tests__/exchange.test.ts +30 -1
- package/src/connection/__tests__/failure-fixtures.ts +39 -0
- package/src/connection/__tests__/failure-safety.test.ts +75 -0
- package/src/connection/__tests__/self.test.ts +31 -11
- package/src/connection/__tests__/session.test.ts +3 -3
- package/src/connection/__tests__/target.test.ts +1 -0
- package/src/connection/auth.ts +13 -0
- package/src/connection/call.ts +1 -1
- package/src/connection/credential.ts +2 -2
- package/src/connection/errors.ts +1 -355
- package/src/connection/exchange.ts +47 -23
- package/src/connection/failure/classify.ts +110 -0
- package/src/connection/failure/index.ts +18 -0
- package/src/connection/failure/model.ts +28 -0
- package/src/connection/failure/render.ts +116 -0
- package/src/connection/reasons.ts +16 -0
- package/src/connection/self.ts +39 -21
- package/src/connection/session.ts +19 -8
- package/src/errors.ts +3 -2
- package/src/graph/.spec/api.d.ts +12 -5
- package/src/graph/.spec/layout.ts +9 -1
- package/src/graph/__tests__/mutation.test.ts +2 -2
- package/src/graph/__tests__/query.test.ts +25 -6
- package/src/graph/class.ts +30 -0
- package/src/graph/index.ts +1 -0
- package/src/graph/query.ts +21 -32
- package/src/identity/.spec/api.d.ts +2 -2
- package/src/identity/__tests__/registration.test.ts +1 -1
- package/src/identity/registration.ts +3 -3
- package/src/keys/__tests__/keys.test.ts +4 -0
- package/src/keys/credential.ts +1 -0
- package/src/lib/__tests__/admin-target.test.ts +12 -0
- package/src/lib/__tests__/binary.test.ts +16 -1
- package/src/lib/__tests__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +10 -16
- package/src/lib/__tests__/idp.test.ts +34 -4
- package/src/lib/__tests__/instance-candidates.test.ts +1 -3
- package/src/lib/__tests__/instance-target.test.ts +7 -39
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +1 -1
- package/src/lib/__tests__/update.test.ts +264 -11
- package/src/lib/__tests__/view-assets.test.ts +14 -0
- package/src/lib/__tests__/view-external-open-intent.test.ts +150 -0
- package/src/lib/__tests__/view-external-open-origins.test.ts +27 -0
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +26 -3
- package/src/lib/__tests__/view-session.test.ts +2 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/binary.ts +22 -5
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +9 -7
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +34 -3
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +16 -11
- package/src/lib/log.ts +16 -9
- package/src/lib/output.ts +1 -1
- package/src/lib/proc.ts +7 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +298 -45
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/assets.ts +11 -2
- package/src/lib/view/external-open-intent.ts +41 -0
- package/src/lib/view/external-open-origins.ts +37 -0
- package/src/lib/view/host-capabilities.ts +17 -0
- package/src/lib/view/resolve.ts +1 -1
- package/src/lib/view/server.ts +18 -3
- package/src/lib/view/session.ts +2 -0
- package/src/program/.spec/api.d.ts +1 -0
- package/src/program/__tests__/program.test.ts +163 -6
- package/src/program/argv.ts +14 -0
- package/src/program/build.ts +26 -4
- package/src/program/command.ts +1 -0
- package/src/program/index.ts +1 -0
- package/src/program/registry.ts +2 -1
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/src/telemetry/__tests__/recorder.test.ts +1 -0
- package/src/telemetry/recorder.ts +9 -1
- package/src/ui/.spec/api.d.ts +14 -0
- package/src/ui/.spec/architecture.md +10 -0
- package/src/ui/.spec/laws.ts +36 -0
- package/src/ui/.spec/layout.ts +16 -0
- package/src/ui/__tests__/ui.test.ts +981 -0
- package/src/ui/index.ts +13 -0
- package/src/ui/lock.ts +87 -0
- package/src/ui/model.ts +83 -0
- package/src/ui/operations.ts +710 -0
- package/src/ui/project.ts +219 -0
- package/src/ui/release.ts +321 -0
- package/src/ui/runner.ts +18 -0
- package/studio/client/dist/assets/elk-api-DjmKsHXc.js +1 -0
- package/studio/client/dist/assets/index-7YHdeCxp.js +81 -0
- package/studio/client/dist/assets/index-C0FAnwNw.css +2 -0
- package/studio/client/dist/assets/rolldown-runtime-Dd_uD5pT.js +1 -0
- package/studio/client/dist/assets/schema-studio-BilUNb6Z.css +1 -0
- package/studio/client/dist/assets/schema-studio-CABpTfvH.js +8 -0
- package/studio/client/dist/index.html +3 -2
- package/studio/package.json +7 -13
- package/studio/server/agent/ask.test.ts +1 -1
- package/studio/server/agent/bridge/grant.test.ts +1 -1
- package/studio/server/agent/bridge/routes.test.ts +1 -1
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/gateway/token.test.ts +1 -1
- package/studio/server/agent/harness/gateway/token.ts +3 -3
- package/studio/server/agent/prompts/anchors.test.ts +32 -36
- package/studio/server/agent/prompts/anchors.ts +20 -49
- package/studio/server/agent/prompts/system.test.ts +3 -2
- package/studio/server/agent/prompts/system.ts +3 -3
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/api/canvas.ts +0 -1
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +1 -1
- package/studio/server/cache.test.ts +23 -12
- package/studio/server/cache.ts +12 -15
- package/studio/server/domain.test.ts +50 -68
- package/studio/server/domain.ts +82 -63
- package/studio/server/handoff/copy.ts +1 -1
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/probe.test.ts +1 -1
- package/studio/server/introspect/anatomy/views/routes.ts +46 -37
- package/studio/server/introspect/anatomy/views.ts +9 -14
- package/studio/server/introspect/anatomy-extras.test.ts +26 -42
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +6 -9
- package/studio/server/introspect/bundle.ts +0 -3
- package/studio/server/introspect/canonical-schema.test.ts +94 -389
- package/studio/server/introspect/canonical-schema.ts +227 -457
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +11 -7
- package/studio/server/introspect/diff.ts +18 -55
- package/studio/server/introspect/extractor.ts +22 -117
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +1 -1
- package/studio/server/introspect/revision.ts +1 -1
- package/studio/server/introspect/runtime.test.ts +65 -183
- package/studio/server/introspect/runtime.ts +8 -25
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +38 -68
- package/studio/server/introspect/schema-refs.test.ts +43 -88
- package/studio/server/introspect/schema-refs.ts +14 -49
- package/studio/server/introspect/source-overlay/handlers.ts +116 -636
- package/studio/server/introspect/source-overlay/kernel-calls.ts +0 -3
- package/studio/server/introspect/source-overlay/spans.ts +15 -45
- package/studio/server/state/baseline.test.ts +14 -9
- package/studio/server/state/baseline.ts +3 -5
- package/studio/server/state/visibility.ts +1 -5
- package/studio/server/views/model.ts +3 -3
- package/studio/server/views/target.test.ts +17 -74
- package/studio/server/views/target.ts +24 -50
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +8 -4
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/schema.ts +38 -107
- package/studio/shared/contracts/surface.test.ts +13 -15
- package/studio/shared/contracts/workspace.ts +2 -11
- package/studio/shared/schema/identity.test.ts +20 -44
- package/studio/shared/schema/identity.ts +9 -23
- package/viewer/dist/main.js +30 -51
- package/.check-workspace.cjs +0 -40
- package/src/admin/binding.ts +0 -168
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/elk-api-lwhFo7vB.js +0 -1
- package/studio/client/dist/assets/index-B-c-smo9.js +0 -8
- package/studio/client/dist/assets/index-BckHuAWk.js +0 -81
- package/studio/client/dist/assets/index-C4aNQ6dz.css +0 -1
- package/studio/client/dist/assets/index-ChOr3yP0.css +0 -1
- package/studio/server/introspect/anatomy/views/legacy.ts +0 -232
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.20",
|
|
4
4
|
"description": "Astrale CLI — connect to existing Astrale kernels",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astrale",
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"dist",
|
|
20
20
|
"src",
|
|
21
21
|
"tsconfig.json",
|
|
22
|
-
".check-workspace.cjs",
|
|
23
22
|
"studio/server",
|
|
24
23
|
"studio/shared",
|
|
25
24
|
"studio/client/dist",
|
|
@@ -59,26 +58,23 @@
|
|
|
59
58
|
"ora": "^9.0.0",
|
|
60
59
|
"ts-morph": "^25.0.1",
|
|
61
60
|
"yaml": "^2.8.2",
|
|
62
|
-
"zod": "^
|
|
61
|
+
"zod": "^4.4.3"
|
|
63
62
|
},
|
|
64
63
|
"devDependencies": {
|
|
65
|
-
"@astrale-os/
|
|
66
|
-
"@astrale-os/
|
|
67
|
-
"@astrale-os/
|
|
68
|
-
"@astrale-os/sdk": ">=0.5.0-beta.4 <1.0.0",
|
|
69
|
-
"@astrale-os/shell": ">=0.3.8-beta.2 <1.0.0",
|
|
64
|
+
"@astrale-os/ox": ">=0.1.3 <1.0.0",
|
|
65
|
+
"@astrale-os/sdk": "0.5.0-beta.50",
|
|
66
|
+
"@astrale-os/shell": "0.4.2-beta.5",
|
|
70
67
|
"@astrale/commitlint-config": "npm:@jsr/astrale__commitlint-config@~2.0.1",
|
|
71
|
-
"@commitlint/cli": "
|
|
72
|
-
"@commitlint/config-conventional": "
|
|
68
|
+
"@commitlint/cli": "21.2.2",
|
|
69
|
+
"@commitlint/config-conventional": "21.2.2",
|
|
73
70
|
"@types/bun": "^1.1.16",
|
|
74
71
|
"@types/node": "^22.0.0",
|
|
75
|
-
"@typescript/native-preview": "latest",
|
|
76
72
|
"husky": "~9.1.7",
|
|
77
|
-
"lint-staged": "
|
|
78
|
-
"msgpackr": "^
|
|
79
|
-
"oxfmt": "0.
|
|
80
|
-
"oxlint": "
|
|
81
|
-
"typescript": "
|
|
73
|
+
"lint-staged": "17.3.0",
|
|
74
|
+
"msgpackr": "^2.0.5",
|
|
75
|
+
"oxfmt": "0.63.0",
|
|
76
|
+
"oxlint": "1.78.0",
|
|
77
|
+
"typescript": "7.0.2"
|
|
82
78
|
},
|
|
83
79
|
"lint-staged": {
|
|
84
80
|
"*.{js,cjs,mjs,ts,tsx}": [
|
|
@@ -100,15 +96,14 @@
|
|
|
100
96
|
"node": ">=22"
|
|
101
97
|
},
|
|
102
98
|
"scripts": {
|
|
103
|
-
"preinstall": "node .check-workspace.cjs",
|
|
104
99
|
"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-
|
|
106
|
-
"typecheck": "
|
|
100
|
+
"package:check": "pnpm run typecheck && pnpm run test && pnpm run build && node scripts/verify-public-exports.mjs && node scripts/verify-public-dependency-boundary.mjs",
|
|
101
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.tests.json && tsc --noEmit -p viewer && pnpm --dir studio run typecheck",
|
|
107
102
|
"lint": "oxlint .",
|
|
108
103
|
"lint:fix": "oxlint --fix .",
|
|
109
104
|
"format": "pnpm exec oxfmt --write .",
|
|
110
105
|
"format:check": "pnpm exec oxfmt --check .",
|
|
111
|
-
"test": "bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs",
|
|
106
|
+
"test": "node scripts/qualification/source-boundary.mjs --target && bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs",
|
|
112
107
|
"test:studio": "pnpm --dir studio test",
|
|
113
108
|
"test:watch": "bun test --watch src"
|
|
114
109
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { schema } from '@astrale-os/sdk/schema'
|
|
2
|
+
|
|
3
|
+
import { defineApplication } from '@astrale-os/sdk/application'
|
|
4
|
+
import { compile } from '@astrale-os/sdk/deployment/build'
|
|
5
|
+
import { addressing, assemble } from '@astrale-os/sdk/deployment/release'
|
|
6
|
+
import { defineRuntime } from '@astrale-os/sdk/runtime'
|
|
7
|
+
|
|
8
|
+
/** Build a canonical empty-runtime Release for cross-boundary CLI tests. */
|
|
9
|
+
export function releaseFor<const Schema extends schema.DomainSchema>(
|
|
10
|
+
source: Schema,
|
|
11
|
+
issuer: string,
|
|
12
|
+
) {
|
|
13
|
+
const runtime = defineRuntime<Schema>()({
|
|
14
|
+
integrations: {},
|
|
15
|
+
initialize: () => ({ providers: {} }),
|
|
16
|
+
actions: [],
|
|
17
|
+
workflows: [],
|
|
18
|
+
})
|
|
19
|
+
return assemble(compile(defineApplication({ schema: source, runtime })), addressing(issuer))
|
|
20
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# CLI Admin adapters
|
|
2
2
|
|
|
3
|
-
This private aggregate translates the frozen CLI command journey into the
|
|
4
|
-
`admin.astrale.ai` contract.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Host directly, or persist remote graph truth.
|
|
3
|
+
This private aggregate translates the frozen CLI command journey into the stable public
|
|
4
|
+
`admin.astrale.ai` contract. Routine commands use canonical Admin Class, Property, Core receiver,
|
|
5
|
+
and Method paths through Kernel Client. They do not download, inspect, bind, or rebuild the Admin
|
|
6
|
+
schema. Strict local decoders admit every untrusted Admin result. The adapter does not import Admin
|
|
7
|
+
implementation code, call Host directly, or persist remote graph truth.
|
|
8
8
|
|
|
9
9
|
`instance` owns create/list/status/delete/install projection and explicitly excludes the reserved
|
|
10
10
|
Admin Host from consumer placement. `catalog` owns Domain inventory, publication, and default-set
|
|
@@ -13,3 +13,10 @@ configuration. `graph` is their bounded cursor helper and is not re-exported by
|
|
|
13
13
|
Commander grammar, help text, output shapes, bookmark behavior, and current interactive host
|
|
14
14
|
selection remain owned by the existing command surface; these adapters change only its remote
|
|
15
15
|
semantic owner.
|
|
16
|
+
|
|
17
|
+
## Performance contract
|
|
18
|
+
|
|
19
|
+
`instance list` performs one Admin method call after connection setup and no schema-discovery call.
|
|
20
|
+
Against the production beta Admin endpoint, the complete command must finish in less than 1 second
|
|
21
|
+
with a warm route/cache and less than 2 seconds from a cold CLI process. Unit tests prove the
|
|
22
|
+
single-call/no-reflection shape; retained live evidence proves the wall-clock bounds.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Call } from '@astrale-os/sdk/client'
|
|
2
|
+
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
3
|
+
|
|
4
|
+
import { mock } from 'bun:test'
|
|
5
|
+
|
|
6
|
+
export function adminSession(implementation?: (target: string, input: unknown) => unknown): {
|
|
7
|
+
readonly call: ReturnType<typeof mock>
|
|
8
|
+
readonly reflection: ReturnType<typeof mock>
|
|
9
|
+
readonly session: ClientSession
|
|
10
|
+
} {
|
|
11
|
+
const call = mock(async (request: Call) =>
|
|
12
|
+
implementation?.(String(request.target), request.input),
|
|
13
|
+
)
|
|
14
|
+
const reflection = mock(() => {
|
|
15
|
+
throw new Error('Routine Admin commands must not perform schema discovery or reflection.')
|
|
16
|
+
})
|
|
17
|
+
const session = {
|
|
18
|
+
call,
|
|
19
|
+
installation: reflection,
|
|
20
|
+
snapshot: reflection,
|
|
21
|
+
bind: reflection,
|
|
22
|
+
invoke: reflection,
|
|
23
|
+
} as unknown as ClientSession
|
|
24
|
+
return { call, reflection, session }
|
|
25
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ClientSession } from '@astrale-os/kernel-client/session'
|
|
1
|
+
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
3
2
|
|
|
4
3
|
import type { AdminGraphApi } from '../../graph/.spec/api.js'
|
|
5
4
|
|
|
@@ -55,7 +54,6 @@ export class AdminDomainNotFoundError extends Error {
|
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
export interface AdminCatalogDependencies {
|
|
58
|
-
readonly bind?: (session: ClientSession) => Promise<DomainBinding>
|
|
59
57
|
readonly operationId?: (kind: 'publish' | 'configure-default') => string
|
|
60
58
|
}
|
|
61
59
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# CLI Admin catalog adapter
|
|
2
2
|
|
|
3
|
-
The adapter reads policy-visible `Domain` Nodes through bounded Graph pages
|
|
4
|
-
membership from the Fleet relation.
|
|
5
|
-
|
|
6
|
-
no-op, and an
|
|
3
|
+
The adapter reads policy-visible `Domain` Nodes through bounded Graph pages using stable Class and
|
|
4
|
+
Property keys, and derives default membership from the stable Fleet relation. It performs no schema
|
|
5
|
+
discovery or reflection. Publication invokes `Fleet.publishDomain`; a requested default change is a
|
|
6
|
+
separate explicit `Domain.configureDefault` call. Unchanged publication input is a no-op, and an
|
|
7
|
+
omitted description preserves the current value.
|
|
@@ -1,67 +1,53 @@
|
|
|
1
1
|
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
2
2
|
import type { QueryAST } from '@astrale-os/sdk/query'
|
|
3
3
|
|
|
4
|
-
import { ClassPath } from '@astrale-os/sdk/graph/class'
|
|
5
4
|
import { NodeId } from '@astrale-os/sdk/graph/node'
|
|
6
|
-
import {
|
|
5
|
+
import { normalizeProperties } from '@astrale-os/sdk/graph/properties'
|
|
6
|
+
import { PropertyKey } from '@astrale-os/sdk/schema'
|
|
7
7
|
import { describe, expect, mock, test } from 'bun:test'
|
|
8
8
|
|
|
9
|
-
import type { AdminBinding } from '../../binding'
|
|
10
9
|
import type { AdminGraphApi } from '../../graph'
|
|
11
10
|
|
|
11
|
+
import { adminSession } from '../../__tests__/fixture'
|
|
12
12
|
import { connectAdminCatalog } from '../client'
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return { key: property }
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
}
|
|
14
|
+
const domainProperties = Object.freeze({
|
|
15
|
+
origin: PropertyKey('admin.astrale.ai:class.Domain.property.origin'),
|
|
16
|
+
name: PropertyKey('kernel.astrale.ai:class.Named.property.name'),
|
|
17
|
+
discoveryUrl: PropertyKey('admin.astrale.ai:class.Domain.property.discoveryUrl'),
|
|
18
|
+
description: PropertyKey('kernel.astrale.ai:class.Descriptable.property.description'),
|
|
19
|
+
createdAt: PropertyKey('kernel.astrale.ai:class.Timestamped.property.createdAt'),
|
|
20
|
+
updatedAt: PropertyKey('kernel.astrale.ai:class.Timestamped.property.updatedAt'),
|
|
21
|
+
})
|
|
27
22
|
|
|
28
23
|
function domainNode(id: string, origin: string): Node {
|
|
29
24
|
return {
|
|
30
25
|
id: NodeId(id),
|
|
31
|
-
class:
|
|
32
|
-
props: {
|
|
33
|
-
origin,
|
|
34
|
-
name: origin.split('.')[0]!,
|
|
35
|
-
discoveryUrl: `https://${origin}`,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
class: 'admin.astrale.ai:Domain' as Node['class'],
|
|
27
|
+
props: normalizeProperties({
|
|
28
|
+
[domainProperties.origin]: origin,
|
|
29
|
+
[domainProperties.name]: origin.split('.')[0]!,
|
|
30
|
+
[domainProperties.discoveryUrl]: `https://${origin}`,
|
|
31
|
+
[domainProperties.description]: `${origin} description`,
|
|
32
|
+
[domainProperties.createdAt]: '2026-08-12T00:00:00.000Z',
|
|
33
|
+
[domainProperties.updatedAt]: '2026-08-12T00:00:00.000Z',
|
|
34
|
+
}),
|
|
39
35
|
}
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
function fixture(input: {
|
|
43
39
|
domains?: readonly Node[]
|
|
44
40
|
defaults?: readonly Node[]
|
|
45
|
-
invoke?: (
|
|
41
|
+
invoke?: (target: string, value: unknown) => unknown
|
|
46
42
|
}) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
origin: 'admin.astrale.ai',
|
|
56
|
-
class(name: string) {
|
|
57
|
-
if (name === 'Domain') return Domain
|
|
58
|
-
if (name === 'Fleet') return Fleet
|
|
59
|
-
throw new Error(`Unexpected class ${name}`)
|
|
60
|
-
},
|
|
61
|
-
core: { nodes: { fleet: { path: Path.id(NodeId('fleet')) } } },
|
|
62
|
-
invoke,
|
|
63
|
-
},
|
|
64
|
-
} as unknown as AdminBinding
|
|
43
|
+
const calls: Array<{
|
|
44
|
+
target: string
|
|
45
|
+
value: unknown
|
|
46
|
+
}> = []
|
|
47
|
+
const remote = adminSession((target, value) => {
|
|
48
|
+
calls.push({ target, value })
|
|
49
|
+
return input.invoke?.(target, value)
|
|
50
|
+
})
|
|
65
51
|
const query = mock(async (_ast: QueryAST) => ({
|
|
66
52
|
result: {
|
|
67
53
|
kind: 'nodes' as const,
|
|
@@ -70,21 +56,30 @@ function fixture(input: {
|
|
|
70
56
|
page: {},
|
|
71
57
|
}))
|
|
72
58
|
const defaultNodes = input.defaults ?? []
|
|
73
|
-
const neighbors = mock(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
59
|
+
const neighbors = mock(
|
|
60
|
+
async (
|
|
61
|
+
_source: Parameters<AdminGraphApi['neighbors']>[0],
|
|
62
|
+
_via: Parameters<AdminGraphApi['neighbors']>[1],
|
|
63
|
+
_options: Parameters<AdminGraphApi['neighbors']>[2],
|
|
64
|
+
) => ({
|
|
65
|
+
nodes: defaultNodes,
|
|
66
|
+
first: defaultNodes[0] ?? null,
|
|
67
|
+
graph: { nodes: defaultNodes, edges: [] },
|
|
68
|
+
cursor: null,
|
|
69
|
+
collect: async () => ({ nodes: defaultNodes, cursor: null }),
|
|
70
|
+
}),
|
|
71
|
+
)
|
|
80
72
|
const graph = { query, neighbors } as unknown as AdminGraphApi
|
|
81
73
|
return {
|
|
82
|
-
|
|
74
|
+
call: remote.call,
|
|
75
|
+
reflection: remote.reflection,
|
|
76
|
+
query,
|
|
77
|
+
neighbors,
|
|
78
|
+
calls,
|
|
83
79
|
connect: () =>
|
|
84
80
|
connectAdminCatalog(
|
|
85
|
-
{ session:
|
|
81
|
+
{ session: remote.session, graph },
|
|
86
82
|
{
|
|
87
|
-
bind: async () => binding,
|
|
88
83
|
operationId: (kind) => `cli.domain.${kind}:test`,
|
|
89
84
|
},
|
|
90
85
|
),
|
|
@@ -106,16 +101,57 @@ describe('V2 Admin Domain catalog adapter', () => {
|
|
|
106
101
|
test('lists Domain nodes through GraphApi and joins the Fleet default relation', async () => {
|
|
107
102
|
const crm = domainNode('crm-domain', 'crm.acme.dev')
|
|
108
103
|
const notes = domainNode('notes-domain', 'notes.acme.dev')
|
|
109
|
-
const
|
|
104
|
+
const contract = fixture({ domains: [crm, notes], defaults: [crm] })
|
|
105
|
+
const api = await contract.connect()
|
|
110
106
|
|
|
111
107
|
await expect(api.list()).resolves.toEqual([
|
|
112
|
-
|
|
108
|
+
{
|
|
113
109
|
id: '@crm-domain',
|
|
114
110
|
origin: 'crm.acme.dev',
|
|
111
|
+
name: 'crm',
|
|
112
|
+
url: 'https://crm.acme.dev',
|
|
113
|
+
description: 'crm.acme.dev description',
|
|
115
114
|
installByDefault: true,
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
createdAt: '2026-08-12T00:00:00.000Z',
|
|
116
|
+
updatedAt: '2026-08-12T00:00:00.000Z',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: '@notes-domain',
|
|
120
|
+
origin: 'notes.acme.dev',
|
|
121
|
+
name: 'notes',
|
|
122
|
+
url: 'https://notes.acme.dev',
|
|
123
|
+
description: 'notes.acme.dev description',
|
|
124
|
+
createdAt: '2026-08-12T00:00:00.000Z',
|
|
125
|
+
updatedAt: '2026-08-12T00:00:00.000Z',
|
|
126
|
+
},
|
|
118
127
|
])
|
|
128
|
+
expect(contract.query).toHaveBeenCalledWith(
|
|
129
|
+
{
|
|
130
|
+
format: 'astrale.graph.query',
|
|
131
|
+
version: 'v6',
|
|
132
|
+
source: {
|
|
133
|
+
kind: 'node',
|
|
134
|
+
terms: [
|
|
135
|
+
{
|
|
136
|
+
kind: 'class',
|
|
137
|
+
class: { origin: 'admin.astrale.ai', kind: 'class', name: 'Domain' },
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
binding: 'n0',
|
|
141
|
+
},
|
|
142
|
+
steps: [],
|
|
143
|
+
select: { kind: 'nodes', binding: 'n0', projection: { kind: 'value' } },
|
|
144
|
+
},
|
|
145
|
+
{ page: { size: 256 } },
|
|
146
|
+
)
|
|
147
|
+
const [source, edge, options] = contract.neighbors.mock.calls[0]!
|
|
148
|
+
expect(String(source)).toBe('/:admin.astrale.ai:core.fleet')
|
|
149
|
+
expect(edge).toEqual({
|
|
150
|
+
origin: 'admin.astrale.ai',
|
|
151
|
+
kind: 'class',
|
|
152
|
+
name: 'fleet_installs_domain_by_default',
|
|
153
|
+
})
|
|
154
|
+
expect(options).toEqual({ direction: 'outgoing', page: { size: 256 } })
|
|
119
155
|
})
|
|
120
156
|
|
|
121
157
|
test('publishes through Fleet then configures the Domain default explicitly', async () => {
|
|
@@ -130,16 +166,9 @@ describe('V2 Admin Domain catalog adapter', () => {
|
|
|
130
166
|
installByDefault: true,
|
|
131
167
|
}),
|
|
132
168
|
).resolves.toMatchObject({ changed: true, isNew: true, entry: { installByDefault: true } })
|
|
133
|
-
expect(
|
|
134
|
-
contract.invoke.mock.calls.map(([method, receiver, value]) => ({
|
|
135
|
-
method,
|
|
136
|
-
receiver: String(receiver),
|
|
137
|
-
value,
|
|
138
|
-
})),
|
|
139
|
-
).toEqual([
|
|
169
|
+
expect(contract.calls).toEqual([
|
|
140
170
|
{
|
|
141
|
-
|
|
142
|
-
receiver: '@fleet',
|
|
171
|
+
target: '/:admin.astrale.ai:core.fleet::publishDomain',
|
|
143
172
|
value: {
|
|
144
173
|
operationId: 'cli.domain.publish:test',
|
|
145
174
|
origin: 'crm.acme.dev',
|
|
@@ -148,8 +177,7 @@ describe('V2 Admin Domain catalog adapter', () => {
|
|
|
148
177
|
},
|
|
149
178
|
},
|
|
150
179
|
{
|
|
151
|
-
|
|
152
|
-
receiver: '@crm-domain',
|
|
180
|
+
target: '@crm-domain::configureDefault',
|
|
153
181
|
value: {
|
|
154
182
|
operationId: 'cli.domain.configure-default:test',
|
|
155
183
|
enabled: true,
|
|
@@ -166,6 +194,52 @@ describe('V2 Admin Domain catalog adapter', () => {
|
|
|
166
194
|
await expect(
|
|
167
195
|
api.publish({ origin: 'crm.acme.dev', name: 'crm', url: 'https://crm.acme.dev' }),
|
|
168
196
|
).resolves.toMatchObject({ changed: false, isNew: false })
|
|
169
|
-
expect(contract.
|
|
197
|
+
expect(contract.call).not.toHaveBeenCalled()
|
|
198
|
+
expect(contract.reflection).not.toHaveBeenCalled()
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
test('connects without schema discovery or graph I/O', async () => {
|
|
202
|
+
const contract = fixture({})
|
|
203
|
+
|
|
204
|
+
await contract.connect()
|
|
205
|
+
|
|
206
|
+
expect(contract.call).not.toHaveBeenCalled()
|
|
207
|
+
expect(contract.reflection).not.toHaveBeenCalled()
|
|
208
|
+
expect(contract.query).not.toHaveBeenCalled()
|
|
209
|
+
expect(contract.neighbors).not.toHaveBeenCalled()
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
test('rejects malformed graph records and publication summaries', async () => {
|
|
213
|
+
const invalidNode = {
|
|
214
|
+
id: NodeId('invalid-domain'),
|
|
215
|
+
class: 'admin.astrale.ai:Domain' as Node['class'],
|
|
216
|
+
props: normalizeProperties({
|
|
217
|
+
[domainProperties.origin]: 'invalid.example.dev',
|
|
218
|
+
[domainProperties.name]: 'invalid',
|
|
219
|
+
[domainProperties.discoveryUrl]: 'https://invalid.example.dev',
|
|
220
|
+
[domainProperties.createdAt]: '2026-08-12T00:00:00.000Z',
|
|
221
|
+
}),
|
|
222
|
+
}
|
|
223
|
+
await expect((await fixture({ domains: [invalidNode] }).connect()).list()).rejects.toThrow(
|
|
224
|
+
'Admin Domain.updatedAt is invalid.',
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
const malformed = fixture({ invoke: () => ({ id: '@domain-only' }) })
|
|
228
|
+
await expect(
|
|
229
|
+
(await malformed.connect()).publish({
|
|
230
|
+
origin: 'crm.acme.dev',
|
|
231
|
+
name: 'crm',
|
|
232
|
+
url: 'https://crm.acme.dev',
|
|
233
|
+
}),
|
|
234
|
+
).rejects.toThrow('Admin Domain origin is invalid.')
|
|
235
|
+
|
|
236
|
+
const malformedPath = fixture({ invoke: () => ({ ...summary('crm.acme.dev'), id: 'bad' }) })
|
|
237
|
+
await expect(
|
|
238
|
+
(await malformedPath.connect()).publish({
|
|
239
|
+
origin: 'crm.acme.dev',
|
|
240
|
+
name: 'crm',
|
|
241
|
+
url: 'https://crm.acme.dev',
|
|
242
|
+
}),
|
|
243
|
+
).rejects.toThrow('Admin Domain id is invalid.')
|
|
170
244
|
})
|
|
171
245
|
})
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { ClientSession } from '@astrale-os/
|
|
1
|
+
import type { ClientSession } from '@astrale-os/sdk/client/session'
|
|
2
2
|
import type { Node } from '@astrale-os/sdk/graph/node'
|
|
3
3
|
|
|
4
4
|
import { Path } from '@astrale-os/sdk/graph/path'
|
|
5
5
|
import { Query } from '@astrale-os/sdk/query'
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import { AdminContract, callAdminMethod } from '../contract'
|
|
8
8
|
import { readAllNodes, type AdminGraphApi } from '../graph'
|
|
9
9
|
import {
|
|
10
10
|
AdminDomainNotFoundError,
|
|
@@ -13,16 +13,9 @@ import {
|
|
|
13
13
|
type PublishDomainResult,
|
|
14
14
|
} from './model'
|
|
15
15
|
|
|
16
|
-
const ADMIN_ORIGIN = 'admin.astrale.ai'
|
|
17
16
|
const PAGE_SIZE = 256
|
|
18
17
|
const MAXIMUM_DOMAINS = 10_000
|
|
19
18
|
const MAXIMUM_PAGES = Math.ceil(MAXIMUM_DOMAINS / PAGE_SIZE) + 1
|
|
20
|
-
const DomainRef = Object.freeze({ origin: ADMIN_ORIGIN, kind: 'class' as const, name: 'Domain' })
|
|
21
|
-
const fleetInstallsByDefault = Object.freeze({
|
|
22
|
-
origin: ADMIN_ORIGIN,
|
|
23
|
-
kind: 'class' as const,
|
|
24
|
-
name: 'fleet_installs_domain_by_default',
|
|
25
|
-
})
|
|
26
19
|
|
|
27
20
|
export interface AdminCatalogContext {
|
|
28
21
|
readonly session: ClientSession
|
|
@@ -36,30 +29,21 @@ export interface AdminCatalogApi {
|
|
|
36
29
|
}
|
|
37
30
|
|
|
38
31
|
export interface AdminCatalogDependencies {
|
|
39
|
-
readonly bind?: (session: ClientSession) => Promise<AdminBinding>
|
|
40
32
|
readonly operationId?: (kind: 'publish' | 'configure-default') => string
|
|
41
33
|
}
|
|
42
34
|
|
|
43
|
-
/**
|
|
35
|
+
/** Connect the Domain catalog journey without schema discovery or reflection. */
|
|
44
36
|
export async function connectAdminCatalog(
|
|
45
37
|
context: AdminCatalogContext,
|
|
46
38
|
dependencies: AdminCatalogDependencies = {},
|
|
47
39
|
): Promise<AdminCatalogApi> {
|
|
48
|
-
const binding = await (dependencies.bind ?? bindAdmin)(context.session)
|
|
49
|
-
if (binding.$.publication?.origin !== ADMIN_ORIGIN || binding.$.origin !== ADMIN_ORIGIN) {
|
|
50
|
-
throw new TypeError('Configured Admin target does not serve the Admin Domain.')
|
|
51
|
-
}
|
|
52
|
-
const Domain = binding.$.class('Domain')
|
|
53
|
-
const Fleet = binding.$.class('Fleet')
|
|
54
|
-
const fleet = binding.$.core.nodes.fleet?.path
|
|
55
|
-
if (fleet === undefined) throw new TypeError('Admin Domain has no singleton Fleet receiver.')
|
|
56
40
|
const operationId = dependencies.operationId ?? defaultOperationId
|
|
57
41
|
|
|
58
42
|
const list = async (): Promise<DomainInfo[]> => {
|
|
59
43
|
const [nodes, defaultsPage] = await Promise.all([
|
|
60
44
|
readAllNodes(
|
|
61
45
|
context.graph,
|
|
62
|
-
Query.from({
|
|
46
|
+
Query.from({ nodes: [AdminContract.classes.Domain] }).select({
|
|
63
47
|
kind: 'nodes',
|
|
64
48
|
projection: { kind: 'value' },
|
|
65
49
|
}),
|
|
@@ -69,16 +53,20 @@ export async function connectAdminCatalog(
|
|
|
69
53
|
maximumPages: MAXIMUM_PAGES,
|
|
70
54
|
},
|
|
71
55
|
),
|
|
72
|
-
context.graph.neighbors(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
context.graph.neighbors(
|
|
57
|
+
AdminContract.fleet,
|
|
58
|
+
AdminContract.edges.fleetInstallsDomainByDefault,
|
|
59
|
+
{
|
|
60
|
+
direction: 'outgoing',
|
|
61
|
+
page: { size: PAGE_SIZE },
|
|
62
|
+
},
|
|
63
|
+
),
|
|
76
64
|
])
|
|
77
65
|
const defaults = await defaultsPage.collect({ maximumPages: MAXIMUM_PAGES })
|
|
78
66
|
if (defaults.cursor !== null)
|
|
79
67
|
throw new TypeError('Admin default Domain catalog exceeded its bound.')
|
|
80
68
|
const defaultIds = new Set(defaults.nodes.map((node) => String(node.id)))
|
|
81
|
-
return nodes.map((node) => domainFromNode(
|
|
69
|
+
return nodes.map((node) => domainFromNode(node, defaultIds.has(String(node.id))))
|
|
82
70
|
}
|
|
83
71
|
|
|
84
72
|
const requireDomain = async (identifier: string): Promise<DomainInfo> => {
|
|
@@ -107,13 +95,13 @@ export async function connectAdminCatalog(
|
|
|
107
95
|
let entry = existing
|
|
108
96
|
if (registryChanged) {
|
|
109
97
|
entry = domainFromSummary(
|
|
110
|
-
await
|
|
98
|
+
await callAdminMethod(context.session, AdminContract.fleet, 'publishDomain', {
|
|
111
99
|
operationId: operationId('publish'),
|
|
112
100
|
origin: input.origin,
|
|
113
101
|
name: input.name,
|
|
114
102
|
discoveryUrl: input.url,
|
|
115
103
|
...(description === undefined ? {} : { description }),
|
|
116
|
-
}
|
|
104
|
+
}),
|
|
117
105
|
existing?.installByDefault === true,
|
|
118
106
|
)
|
|
119
107
|
}
|
|
@@ -124,14 +112,10 @@ export async function connectAdminCatalog(
|
|
|
124
112
|
(entry.installByDefault ?? false) !== input.installByDefault
|
|
125
113
|
if (defaultChanged) {
|
|
126
114
|
entry = domainFromSummary(
|
|
127
|
-
await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
operationId: operationId('configure-default'),
|
|
132
|
-
enabled: input.installByDefault,
|
|
133
|
-
} as never,
|
|
134
|
-
),
|
|
115
|
+
await callAdminMethod(context.session, Path.parse(entry.id), 'configureDefault', {
|
|
116
|
+
operationId: operationId('configure-default'),
|
|
117
|
+
enabled: input.installByDefault,
|
|
118
|
+
}),
|
|
135
119
|
input.installByDefault === true,
|
|
136
120
|
)
|
|
137
121
|
}
|
|
@@ -144,29 +128,23 @@ export async function connectAdminCatalog(
|
|
|
144
128
|
})
|
|
145
129
|
}
|
|
146
130
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
function domainFromNode(
|
|
150
|
-
definition: DynamicDefinition,
|
|
151
|
-
node: Node,
|
|
152
|
-
installByDefault: boolean,
|
|
153
|
-
): DomainInfo {
|
|
131
|
+
function domainFromNode(node: Node, installByDefault: boolean): DomainInfo {
|
|
154
132
|
return Object.freeze({
|
|
155
133
|
id: Path.id(node.id).raw,
|
|
156
|
-
origin: requiredProperty(
|
|
157
|
-
name: requiredProperty(
|
|
158
|
-
url: requiredProperty(
|
|
159
|
-
...optionalProperty(
|
|
134
|
+
origin: requiredProperty(node, 'origin'),
|
|
135
|
+
name: requiredProperty(node, 'name'),
|
|
136
|
+
url: requiredProperty(node, 'discoveryUrl'),
|
|
137
|
+
...optionalProperty(node, 'description'),
|
|
160
138
|
...(installByDefault ? { installByDefault: true } : {}),
|
|
161
|
-
createdAt: requiredProperty(
|
|
162
|
-
updatedAt: requiredProperty(
|
|
139
|
+
createdAt: requiredProperty(node, 'createdAt'),
|
|
140
|
+
updatedAt: requiredProperty(node, 'updatedAt'),
|
|
163
141
|
})
|
|
164
142
|
}
|
|
165
143
|
|
|
166
144
|
function domainFromSummary(input: unknown, installByDefault: boolean): DomainInfo {
|
|
167
145
|
const value = record(input, 'Admin Domain summary')
|
|
168
146
|
return Object.freeze({
|
|
169
|
-
id:
|
|
147
|
+
id: requiredNodePath(value.id, 'Admin Domain id'),
|
|
170
148
|
origin: requiredString(value.origin, 'Admin Domain origin'),
|
|
171
149
|
name: requiredString(value.name, 'Admin Domain name'),
|
|
172
150
|
url: requiredString(value.discoveryUrl, 'Admin Domain discovery URL'),
|
|
@@ -179,16 +157,15 @@ function domainFromSummary(input: unknown, installByDefault: boolean): DomainInf
|
|
|
179
157
|
})
|
|
180
158
|
}
|
|
181
159
|
|
|
182
|
-
function requiredProperty(
|
|
183
|
-
return requiredString(node.props[
|
|
160
|
+
function requiredProperty(node: Node, name: keyof typeof AdminContract.properties.domain): string {
|
|
161
|
+
return requiredString(node.props[AdminContract.properties.domain[name]], `Admin Domain.${name}`)
|
|
184
162
|
}
|
|
185
163
|
|
|
186
164
|
function optionalProperty(
|
|
187
|
-
definition: DynamicDefinition,
|
|
188
165
|
node: Node,
|
|
189
|
-
name:
|
|
166
|
+
name: keyof typeof AdminContract.properties.domain,
|
|
190
167
|
): Readonly<Record<string, string>> {
|
|
191
|
-
const value = node.props[
|
|
168
|
+
const value = node.props[AdminContract.properties.domain[name]]
|
|
192
169
|
return value === undefined ? {} : { [name]: requiredString(value, `Admin Domain.${name}`) }
|
|
193
170
|
}
|
|
194
171
|
|
|
@@ -197,6 +174,15 @@ function requiredString(input: unknown, label: string): string {
|
|
|
197
174
|
return input
|
|
198
175
|
}
|
|
199
176
|
|
|
177
|
+
function requiredNodePath(input: unknown, label: string): string {
|
|
178
|
+
const value = requiredString(input, label)
|
|
179
|
+
try {
|
|
180
|
+
return Path.parse(value).raw
|
|
181
|
+
} catch {
|
|
182
|
+
throw new TypeError(`${label} is invalid.`)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
200
186
|
function record(input: unknown, label: string): Readonly<Record<string, unknown>> {
|
|
201
187
|
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
202
188
|
throw new TypeError(`${label} is invalid.`)
|