@astrale-os/cli 1.0.0-beta.0 → 1.0.0-beta.10
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 +23 -12
- package/dist/astrale.js +51494 -56307
- package/dist/public/connect-core.js +2028 -26846
- package/dist/public/keys/index.js +1755 -40694
- package/dist/public/paths/index.js +859 -39518
- package/dist/types/admin/binding.d.ts +19 -0
- package/dist/types/admin/instance/client.d.ts +22 -0
- package/dist/types/admin/instance/index.d.ts +2 -0
- package/dist/types/admin/instance/model.d.ts +5 -12
- 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 +6 -2
- package/dist/types/lib/failure-debug.d.ts +1 -0
- package/dist/types/lib/idp.d.ts +7 -0
- package/dist/types/lib/instance-target.d.ts +1 -1
- package/dist/types/lib/instance.d.ts +10 -2
- package/dist/types/lib/log.d.ts +5 -3
- package/dist/types/lib/meta.d.ts +2 -2
- 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 +131 -0
- package/package.json +8 -10
- package/src/__tests__/fixtures/publication.ts +20 -0
- package/src/admin/__tests__/binding.test.ts +31 -0
- package/src/admin/__tests__/fixture.ts +101 -0
- package/src/admin/binding.ts +98 -0
- package/src/admin/catalog/.spec/api.d.ts +2 -2
- package/src/admin/catalog/__tests__/client.test.ts +20 -49
- package/src/admin/catalog/client.ts +36 -32
- package/src/admin/catalog/model.ts +3 -4
- 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 +2 -2
- package/src/admin/instance/__tests__/client.test.ts +40 -163
- package/src/admin/instance/client.ts +35 -137
- package/src/admin/instance/index.ts +1 -2
- package/src/admin/instance/model.ts +11 -20
- package/src/commands/__tests__/admin-instance.test.ts +11 -8
- package/src/commands/__tests__/auth-login.test.ts +54 -1
- package/src/commands/__tests__/call-describe.test.ts +46 -33
- package/src/commands/__tests__/call.test.ts +5 -1
- package/src/commands/__tests__/domain-install-operation.test.ts +12 -7
- package/src/commands/__tests__/domain-install-owned.test.ts +6 -2
- package/src/commands/__tests__/domain-list.test.ts +63 -4
- package/src/commands/__tests__/install-identity-override.test.ts +19 -19
- 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__/read-commands.test.ts +35 -10
- package/src/commands/__tests__/studio-descriptor.test.ts +22 -0
- package/src/commands/__tests__/update.test.ts +95 -0
- package/src/commands/call-describe.ts +60 -68
- package/src/commands/call.ts +43 -56
- package/src/commands/domain/install.ts +13 -17
- package/src/commands/domain/list.ts +18 -13
- 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 +9 -16
- package/src/commands/logs.ts +24 -25
- package/src/commands/mutate.ts +6 -5
- package/src/commands/query.ts +27 -30
- package/src/commands/studio.ts +20 -0
- package/src/commands/token.ts +8 -7
- package/src/commands/update.ts +68 -22
- package/src/commands/view.ts +7 -6
- 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 +43 -32
- package/src/connection/__tests__/exchange.test.ts +36 -6
- 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 +52 -27
- 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__/command-dx.test.ts +1 -1
- package/src/lib/__tests__/domain-publication.test.ts +138 -0
- package/src/lib/__tests__/idp-session.test.ts +22 -0
- package/src/lib/__tests__/idp.test.ts +36 -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__/instance.test.ts +6 -0
- package/src/lib/__tests__/log-errors.test.ts +64 -0
- package/src/lib/__tests__/studio-server-deps.test.ts +53 -16
- package/src/lib/__tests__/update.test.ts +113 -8
- package/src/lib/__tests__/view-open-intent.test.ts +0 -2
- package/src/lib/__tests__/view-server.test.ts +1 -1
- package/src/lib/__tests__/view-session.test.ts +1 -1
- package/src/lib/admin-instance.ts +14 -8
- package/src/lib/admin-target.ts +21 -2
- package/src/lib/command-dx.ts +9 -9
- package/src/lib/domain-publication.ts +104 -0
- package/src/lib/failure-debug.ts +26 -0
- package/src/lib/idp.ts +39 -4
- package/src/lib/instance-candidates.ts +2 -2
- package/src/lib/instance-target.ts +3 -14
- package/src/lib/instance.ts +22 -12
- package/src/lib/log.ts +16 -9
- package/src/lib/login-flow.ts +13 -3
- package/src/lib/meta.ts +2 -2
- package/src/lib/provision-instance.ts +34 -57
- package/src/lib/update.ts +124 -30
- package/src/lib/validation.ts +2 -2
- package/src/lib/view/resolve.ts +1 -1
- package/src/program/__tests__/program.test.ts +20 -4
- package/src/program/build.ts +2 -2
- package/src/setup/__tests__/instance-step.test.ts +27 -10
- package/src/setup/steps/instance.ts +22 -15
- package/studio/client/dist/assets/{elk-api-D2xgMJvi.js → elk-api-ByzoDZWH.js} +1 -1
- package/studio/client/dist/assets/index-B0RCgUOT.js +8 -0
- package/studio/client/dist/assets/index-BiGR8Oo9.css +1 -0
- package/studio/client/dist/assets/index-N8J8EKlB.js +81 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/package.json +5 -10
- 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/bridge/stdio.ts +8 -1
- package/studio/server/agent/conversation.test.ts +10 -5
- package/studio/server/agent/conversation.ts +56 -8
- package/studio/server/agent/harness/claude/adapter.test.ts +15 -5
- package/studio/server/agent/harness/codex/loadout.ts +18 -21
- package/studio/server/agent/harness/gateway/config.ts +20 -18
- package/studio/server/agent/harness/selection.ts +9 -1
- 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 +6 -5
- package/studio/server/agent/prompts/turn.ts +13 -4
- package/studio/server/agent/routes.test.ts +1 -1
- package/studio/server/agent/run/completion.ts +2 -2
- package/studio/server/agent/run/coordinator.test.ts +1 -1
- package/studio/server/agent/run/preparation.ts +6 -5
- package/studio/server/agent/run/transcript.test.ts +35 -1
- package/studio/server/agent/run/transcript.ts +169 -3
- package/studio/server/agent/run/usage.test.ts +24 -0
- package/studio/server/agent/run/usage.ts +26 -1
- package/studio/server/api/canvas.ts +43 -0
- package/studio/server/api/comments.ts +85 -0
- package/studio/server/api/context.ts +61 -0
- package/studio/server/api/deployment.ts +39 -0
- package/studio/server/api/documents.ts +55 -0
- package/studio/server/api/domain.ts +59 -0
- package/studio/server/api/http.ts +45 -0
- package/studio/server/api/project.ts +57 -0
- package/studio/server/api/schema.ts +12 -0
- package/studio/server/api/views.ts +57 -0
- package/studio/server/api/workspace.ts +60 -0
- package/studio/server/api-agent-loadout.test.ts +1 -1
- package/studio/server/api.test.ts +147 -0
- package/studio/server/api.ts +20 -422
- package/studio/server/cache.test.ts +122 -0
- package/studio/server/cache.ts +162 -11
- package/studio/server/cli-consumers.test.ts +494 -0
- package/studio/server/cli.test.ts +88 -0
- package/studio/server/cli.ts +240 -0
- package/studio/server/client-package.ts +25 -1
- package/studio/server/domain.test.ts +50 -40
- package/studio/server/domain.ts +83 -52
- package/studio/server/environment/dotenv-preview.test.ts +39 -0
- package/studio/server/environment/dotenv-preview.ts +27 -0
- package/studio/server/environment/files.test.ts +53 -0
- package/studio/server/{state/env.ts → environment/files.ts} +7 -48
- package/studio/server/{state → handoff}/copy.ts +21 -6
- package/studio/server/handoff/service.test.ts +22 -0
- package/studio/server/{state/handoff.ts → handoff/service.ts} +21 -14
- package/studio/server/index.ts +1 -1
- package/studio/server/instances/active.ts +72 -0
- package/studio/server/instances/deploy-record.test.ts +31 -0
- package/studio/server/instances/deploy-record.ts +37 -0
- package/studio/server/instances/deploy.ts +56 -0
- package/studio/server/{state/instance.test.ts → instances/probe.test.ts} +25 -21
- package/studio/server/instances/probe.ts +67 -0
- package/studio/server/instances/status.test.ts +12 -0
- package/studio/server/instances/status.ts +49 -0
- package/studio/server/introspect/anatomy/client-tree.ts +57 -0
- package/studio/server/introspect/anatomy/env-fields.ts +66 -0
- package/studio/server/introspect/anatomy/schema-definition.ts +53 -0
- package/studio/server/introspect/anatomy/source.ts +181 -0
- package/studio/server/introspect/anatomy/views/routes.ts +114 -0
- package/studio/server/introspect/anatomy/views.ts +53 -0
- package/studio/server/introspect/anatomy-extras.test.ts +106 -35
- package/studio/server/introspect/anatomy-extras.ts +7 -726
- package/studio/server/introspect/anatomy.test.ts +22 -14
- package/studio/server/introspect/anatomy.ts +52 -28
- package/studio/server/introspect/bundle.ts +15 -9
- package/studio/server/introspect/canonical-schema.test.ts +93 -309
- package/studio/server/introspect/canonical-schema.ts +257 -425
- package/studio/server/introspect/config-preview.test.ts +32 -0
- package/studio/server/introspect/config-preview.ts +119 -0
- package/studio/server/introspect/core-extractor.ts +18 -127
- package/studio/server/introspect/core.ts +1 -2
- package/studio/server/introspect/diff.test.ts +18 -18
- package/studio/server/introspect/diff.ts +44 -90
- package/studio/server/introspect/extractor.ts +23 -116
- package/studio/server/introspect/hash.ts +5 -2
- package/studio/server/introspect/overlay-tsmorph.test.ts +119 -240
- package/studio/server/introspect/overlay-tsmorph.ts +7 -1305
- package/studio/server/introspect/overlay.test.ts +26 -54
- package/studio/server/introspect/overlay.ts +10 -37
- package/studio/server/introspect/revision.test.ts +54 -0
- package/studio/server/introspect/revision.ts +49 -0
- package/studio/server/introspect/runtime.test.ts +83 -143
- package/studio/server/introspect/runtime.ts +40 -11
- package/studio/server/introspect/schema-ir-json.test.ts +70 -0
- package/studio/server/introspect/schema-ir-json.ts +151 -0
- 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/annotations.ts +14 -0
- package/studio/server/introspect/source-overlay/handlers.ts +161 -0
- package/studio/server/introspect/source-overlay/kernel-calls.ts +46 -0
- package/studio/server/introspect/source-overlay/project.ts +248 -0
- package/studio/server/introspect/source-overlay/spans.ts +330 -0
- package/studio/server/json.ts +46 -0
- package/studio/server/lifecycle.ts +5 -1
- package/studio/server/sse.test.ts +26 -0
- package/studio/server/sse.ts +4 -1
- package/studio/server/state/baseline.test.ts +223 -7
- package/studio/server/state/baseline.ts +148 -34
- package/studio/server/state/comments.test.ts +66 -1
- package/studio/server/state/comments.ts +173 -10
- package/studio/server/state/context.ts +34 -2
- package/studio/server/state/documents.ts +42 -1
- package/studio/server/state/integrations.ts +27 -1
- package/studio/server/state/layout.test.ts +34 -0
- package/studio/server/state/layout.ts +44 -17
- package/studio/server/state/settings.ts +29 -22
- package/studio/server/state/store.test.ts +122 -0
- package/studio/server/state/store.ts +66 -17
- package/studio/server/state/visibility.ts +22 -11
- package/studio/server/views/model.test.ts +57 -0
- package/studio/server/views/model.ts +66 -0
- package/studio/server/views/runtime.ts +40 -0
- package/studio/server/views/selection-repository.test.ts +31 -0
- package/studio/server/views/selection-repository.ts +60 -0
- package/studio/server/views/session.test.ts +73 -0
- package/studio/server/views/session.ts +166 -0
- package/studio/server/views/target.test.ts +78 -0
- package/studio/server/views/target.ts +222 -0
- package/studio/server/watch.test.ts +11 -11
- package/studio/server/watch.ts +9 -5
- package/studio/server/workspace/catalog.test.ts +17 -0
- package/studio/server/workspace/catalog.ts +43 -0
- package/studio/server/{state → workspace}/create.test.ts +1 -1
- package/studio/server/{state → workspace}/create.ts +1 -1
- package/studio/server/{state → workspace}/git.ts +1 -1
- package/studio/server/workspace/updates.ts +83 -0
- package/studio/server/workspace-state.ts +1 -1
- package/studio/server/workspace-watch.ts +2 -2
- package/studio/shared/contracts/README.md +16 -0
- package/studio/shared/contracts/agent.ts +270 -0
- package/studio/shared/contracts/runtime.ts +50 -0
- package/studio/shared/contracts/schema.ts +393 -0
- package/studio/shared/contracts/surface.test.ts +317 -0
- package/studio/shared/contracts/workspace.ts +265 -0
- package/studio/shared/layout.test.ts +116 -0
- package/studio/shared/schema/identity.test.ts +34 -0
- package/studio/shared/schema/identity.ts +68 -0
- package/studio/shared/types.ts +11 -1099
- package/studio/tsconfig.json +1 -1
- package/viewer/dist/main.js +40 -61
- package/.check-workspace.cjs +0 -40
- package/src/commands/__tests__/instance-create-hosts.test.ts +0 -29
- package/studio/client/dist/assets/index-BMdnsIJA.css +0 -1
- package/studio/client/dist/assets/index-D-vRV8w7.js +0 -8
- package/studio/client/dist/assets/index-LGSWRrk8.js +0 -81
- package/studio/server/state/catalog.ts +0 -117
- package/studio/server/state/instance.ts +0 -280
- package/studio/server/state/updates.ts +0 -63
- package/studio/server/state/views.test.ts +0 -286
- package/studio/server/state/views.ts +0 -535
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test'
|
|
2
|
+
|
|
3
|
+
import { parseConfigPreview } from './config-preview'
|
|
4
|
+
|
|
5
|
+
test('config preview ignores examples in comments and preserves URL literals', () => {
|
|
6
|
+
const preview = parseConfigPreview(`
|
|
7
|
+
// cloudflare({ prod: { route: 'commented.invalid', secrets: '.env.fake' } })
|
|
8
|
+
/* astrale({ prod: { instance: 'commented-instance' } }) */
|
|
9
|
+
export default deploy(domain, cloudflare({
|
|
10
|
+
dev: { client: { dir: 'client' }, secrets: '.env.dev' },
|
|
11
|
+
prod: {
|
|
12
|
+
client: { dir: 'client' },
|
|
13
|
+
route: 'https://services.example.dev/path',
|
|
14
|
+
secrets: '.env.prod',
|
|
15
|
+
},
|
|
16
|
+
}))
|
|
17
|
+
`)
|
|
18
|
+
|
|
19
|
+
expect(preview).toEqual({
|
|
20
|
+
adapter: 'cloudflare',
|
|
21
|
+
prodTarget: 'route: https://services.example.dev/path',
|
|
22
|
+
devSecrets: '.env.dev',
|
|
23
|
+
configuredSecretFiles: ['.env.dev', '.env.prod'],
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
test('config preview reports dynamic configuration as unknown instead of inventing authority', () => {
|
|
28
|
+
expect(parseConfigPreview(`export default makeDeployment(domain)`)).toEqual({
|
|
29
|
+
adapter: 'unknown',
|
|
30
|
+
configuredSecretFiles: [],
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static, non-authoritative preview of astrale.config.ts.
|
|
3
|
+
*
|
|
4
|
+
* Deployment configuration is owned by the SDK adapter and is executable
|
|
5
|
+
* TypeScript. Studio deliberately does not execute it during anatomy/env reads;
|
|
6
|
+
* these few fields are only display/editor hints and may be unknown when the
|
|
7
|
+
* configuration is computed dynamically.
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync } from 'node:fs'
|
|
10
|
+
import { join } from 'node:path'
|
|
11
|
+
|
|
12
|
+
export interface ConfigPreview {
|
|
13
|
+
adapter: 'astrale' | 'cloudflare' | 'unknown'
|
|
14
|
+
prodTarget?: string
|
|
15
|
+
devSecrets?: string
|
|
16
|
+
configuredSecretFiles: string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function withoutComments(source: string): string {
|
|
20
|
+
let output = ''
|
|
21
|
+
let quote: "'" | '"' | '`' | null = null
|
|
22
|
+
let escaped = false
|
|
23
|
+
for (let index = 0; index < source.length; index++) {
|
|
24
|
+
const char = source[index]!
|
|
25
|
+
const next = source[index + 1]
|
|
26
|
+
if (quote) {
|
|
27
|
+
output += char
|
|
28
|
+
if (escaped) escaped = false
|
|
29
|
+
else if (char === '\\') escaped = true
|
|
30
|
+
else if (char === quote) quote = null
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
34
|
+
quote = char
|
|
35
|
+
output += char
|
|
36
|
+
continue
|
|
37
|
+
}
|
|
38
|
+
if (char === '/' && next === '/') {
|
|
39
|
+
while (index + 1 < source.length && source[index + 1] !== '\n') index++
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
if (char === '/' && next === '*') {
|
|
43
|
+
index += 2
|
|
44
|
+
while (index < source.length && !(source[index] === '*' && source[index + 1] === '/')) {
|
|
45
|
+
if (source[index] === '\n') output += '\n'
|
|
46
|
+
index++
|
|
47
|
+
}
|
|
48
|
+
index++
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
output += char
|
|
52
|
+
}
|
|
53
|
+
return output
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function stringField(source: string, name: string): string | undefined {
|
|
57
|
+
const match = new RegExp(`\\b${name}\\s*:\\s*(['"])(.*?)\\1`).exec(source)
|
|
58
|
+
return match?.[2]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function objectBody(source: string, name: string): string | undefined {
|
|
62
|
+
const start = new RegExp(`\\b${name}\\s*:\\s*\\{`).exec(source)
|
|
63
|
+
if (!start) return undefined
|
|
64
|
+
const opening = source.indexOf('{', start.index)
|
|
65
|
+
let depth = 1
|
|
66
|
+
let quote: "'" | '"' | '`' | null = null
|
|
67
|
+
let escaped = false
|
|
68
|
+
for (let index = opening + 1; index < source.length; index++) {
|
|
69
|
+
const char = source[index]!
|
|
70
|
+
if (quote) {
|
|
71
|
+
if (escaped) escaped = false
|
|
72
|
+
else if (char === '\\') escaped = true
|
|
73
|
+
else if (char === quote) quote = null
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
if (char === "'" || char === '"' || char === '`') {
|
|
77
|
+
quote = char
|
|
78
|
+
continue
|
|
79
|
+
}
|
|
80
|
+
if (char === '{') depth++
|
|
81
|
+
else if (char === '}' && --depth === 0) return source.slice(opening + 1, index)
|
|
82
|
+
}
|
|
83
|
+
return undefined
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function parseConfigPreview(source: string): ConfigPreview {
|
|
87
|
+
const active = withoutComments(source)
|
|
88
|
+
const adapter: ConfigPreview['adapter'] = /\bastrale\s*\(/.test(active)
|
|
89
|
+
? 'astrale'
|
|
90
|
+
: /\bcloudflare\s*\(/.test(active)
|
|
91
|
+
? 'cloudflare'
|
|
92
|
+
: 'unknown'
|
|
93
|
+
const prod = objectBody(active, 'prod') ?? active
|
|
94
|
+
const dev = objectBody(active, 'dev') ?? ''
|
|
95
|
+
const instance = stringField(prod, 'instance')
|
|
96
|
+
const route = stringField(prod, 'route')
|
|
97
|
+
const configuredSecretFiles = [...active.matchAll(/\bsecrets\s*:\s*(['"])(.*?)\1/g)].map(
|
|
98
|
+
(match) => match[2]!,
|
|
99
|
+
)
|
|
100
|
+
const devSecrets = stringField(dev, 'secrets')
|
|
101
|
+
return {
|
|
102
|
+
adapter,
|
|
103
|
+
...(instance
|
|
104
|
+
? { prodTarget: `instance: ${instance}` }
|
|
105
|
+
: route
|
|
106
|
+
? { prodTarget: `route: ${route}` }
|
|
107
|
+
: {}),
|
|
108
|
+
...(devSecrets ? { devSecrets } : {}),
|
|
109
|
+
configuredSecretFiles: [...new Set(configuredSecretFiles)],
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function readConfigPreview(root: string): ConfigPreview {
|
|
114
|
+
try {
|
|
115
|
+
return parseConfigPreview(readFileSync(join(root, 'astrale.config.ts'), 'utf8'))
|
|
116
|
+
} catch {
|
|
117
|
+
return { adapter: 'unknown', configuredSecretFiles: [] }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,139 +1,30 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* core-extractor.ts — the Bun-executed island for a domain's CORE (genesis) data.
|
|
3
|
-
* Spawned as a short-lived subprocess by runtime.ts (cwd = domain dir, so the
|
|
4
|
-
* domain's own node_modules resolve @astrale-os/*). It imports the pure schema
|
|
5
|
-
* entry and reads canonical V1 `schema.core` directly. Importing the composition
|
|
6
|
-
* entry and discovering legacy `defineCore(...)` output is retained only as a
|
|
7
|
-
* fallback.
|
|
8
|
-
*
|
|
9
|
-
* bun core-extractor.ts <schemaIndexPath> <domainFile> <domainDir>
|
|
10
|
-
*
|
|
11
|
-
* Contract mirrors extractor.ts exactly: NEVER crash. A thrown error prints
|
|
12
|
-
* { ok:false } and exits 0 — the driver treats it as a render state. A domain
|
|
13
|
-
* with no core prints { ok:true, core:null }.
|
|
14
|
-
*
|
|
15
|
-
* NOTE: the `export {}` below marks this as a module so its top-level `domainDir`/
|
|
16
|
-
* `main` are module-scoped (extractor.ts is a sibling script with the same names).
|
|
17
|
-
*
|
|
18
|
-
* className resolution: a core node's `def` is the runtime class-definition
|
|
19
|
-
* object (shape `{ __kind, config }` — it carries NO name field). We resolve the
|
|
20
|
-
* name by identity-matching `def` against the core's own `schema.classes` /
|
|
21
|
-
* `schema.interfaces`, AND every `schema.imports[*]` group — imported kernel
|
|
22
|
-
* classes like `Folder` ONLY resolve via the imports walk. `data` is passed
|
|
23
|
-
* through as the author wrote it in `node(Class, {...})` (most readable form).
|
|
24
|
-
*/
|
|
25
|
-
export {} // module marker — see header note
|
|
1
|
+
/** Bun subprocess that projects canonical Core directly from the pure Schema entry. */
|
|
26
2
|
import { isAbsolute, resolve } from 'node:path'
|
|
27
3
|
|
|
28
4
|
import { findCanonicalDomainSchemaExport, projectCanonicalCore } from './canonical-schema'
|
|
29
5
|
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
const schemaFile = resolveInput(process.argv[2])
|
|
34
|
-
const domainFile = resolveInput(process.argv[3])
|
|
6
|
+
const projectRoot = process.argv[3] ?? process.cwd()
|
|
7
|
+
const input = process.argv[2]
|
|
8
|
+
const schemaFile = input && !isAbsolute(input) ? resolve(projectRoot, input) : input
|
|
35
9
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
10
|
+
async function main(): Promise<void> {
|
|
11
|
+
if (!schemaFile) throw new Error('core-extractor: missing <schemaPath>')
|
|
12
|
+
const exports = (await import(schemaFile)) as Record<string, unknown>
|
|
13
|
+
const schema = findCanonicalDomainSchemaExport(exports)
|
|
14
|
+
if (schema === null) throw new Error('Schema entry exports no canonical V1 DomainSchema.')
|
|
15
|
+
const core = projectCanonicalCore(schema)
|
|
16
|
+
process.stdout.write(
|
|
17
|
+
JSON.stringify({
|
|
18
|
+
ok: true,
|
|
19
|
+
core: core.nodes.length === 0 && core.edges.length === 0 ? null : core,
|
|
20
|
+
}),
|
|
47
21
|
)
|
|
48
22
|
}
|
|
49
23
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const wired = mod?.domain?.core ?? mod?.default?.core ?? mod?.core
|
|
53
|
-
if (looksLikeCore(wired)) return wired
|
|
54
|
-
// export name varies per domain (GatewayCore / IntegrationCore / …) — scan by shape
|
|
55
|
-
for (const v of Object.values(mod ?? {})) {
|
|
56
|
-
if (looksLikeCore(v)) return v
|
|
57
|
-
if (v && typeof v === 'object' && looksLikeCore((v as AnyRec).core)) return (v as AnyRec).core
|
|
58
|
-
}
|
|
59
|
-
return null
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Build def→className from the schema's own classes/interfaces + imported schemas. */
|
|
63
|
-
function classNameMap(schema: AnyRec): Map<any, string> {
|
|
64
|
-
const m = new Map<any, string>()
|
|
65
|
-
const add = (group?: AnyRec) => {
|
|
66
|
-
for (const [name, def] of Object.entries(group ?? {})) if (def && !m.has(def)) m.set(def, name)
|
|
67
|
-
}
|
|
68
|
-
add(schema?.interfaces)
|
|
69
|
-
add(schema?.classes)
|
|
70
|
-
for (const imp of schema?.imports ?? []) {
|
|
71
|
-
add(imp?.interfaces)
|
|
72
|
-
add(imp?.classes)
|
|
73
|
-
}
|
|
74
|
-
return m
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async function main() {
|
|
78
|
-
if (!schemaFile) throw new Error('core-extractor: missing <schemaIndexPath>')
|
|
79
|
-
|
|
80
|
-
// Current SDK roots embed genesis data in the canonical, portable schema.
|
|
81
|
-
// Do not import implementation.ts/domain.ts when that source of truth exists.
|
|
82
|
-
try {
|
|
83
|
-
const schemaModule: AnyRec = await import(schemaFile)
|
|
84
|
-
const canonical = findCanonicalDomainSchemaExport(schemaModule)
|
|
85
|
-
if (canonical) {
|
|
86
|
-
const core = projectCanonicalCore(canonical)
|
|
87
|
-
const empty = core.nodes.length === 0 && core.edges.length === 0
|
|
88
|
-
process.stdout.write(JSON.stringify({ ok: true, core: empty ? null : core }))
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
} catch {
|
|
92
|
-
// A legacy composition entry may still expose a valid defineCore result.
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (!domainFile) throw new Error('core-extractor: missing <domainFile> legacy fallback')
|
|
96
|
-
const mod: AnyRec = await import(domainFile)
|
|
97
|
-
const core = findCore(mod)
|
|
98
|
-
if (!core) {
|
|
99
|
-
process.stdout.write(JSON.stringify({ ok: true, core: null }))
|
|
100
|
-
return
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const names = classNameMap(core.schema)
|
|
104
|
-
const nameOf = (def: any): string => names.get(def) ?? def?.config?.name ?? def?.name ?? '?'
|
|
105
|
-
// CorePath is a branded string; nested parents are objects with toString/valueOf,
|
|
106
|
-
// so String() is the correct universal coercion (never JSON.stringify a path).
|
|
107
|
-
const pathStr = (p: any): string => (p == null ? '' : String(p))
|
|
108
|
-
// An edge endpoint is a CorePath OR a SelfMarker ({ type:'core-self', __def }).
|
|
109
|
-
const endpoint = (e: any): string =>
|
|
110
|
-
e && typeof e === 'object' && (e.type === 'core-self' || e.__def)
|
|
111
|
-
? `self(${nameOf(e.__def)})`
|
|
112
|
-
: pathStr(e)
|
|
113
|
-
|
|
114
|
-
const nodes = (core.__nodes ?? []).map((n: AnyRec) => ({
|
|
115
|
-
path: pathStr(n.path),
|
|
116
|
-
className: nameOf(n.def),
|
|
117
|
-
data: n.data ?? {},
|
|
118
|
-
...(n.parent != null ? { parent: pathStr(n.parent) } : {}),
|
|
119
|
-
}))
|
|
120
|
-
|
|
121
|
-
const edges = (core.__edges ?? []).map((e: AnyRec) => ({
|
|
122
|
-
from: endpoint(e.from),
|
|
123
|
-
to: endpoint(e.to),
|
|
124
|
-
edgeName: nameOf(e.edge),
|
|
125
|
-
...(e.data != null ? { data: e.data } : {}),
|
|
126
|
-
}))
|
|
127
|
-
|
|
128
|
-
process.stdout.write(JSON.stringify({ ok: true, core: { domain: core.domain, nodes, edges } }))
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
main().catch((err: any) => {
|
|
24
|
+
main().catch((cause: unknown) => {
|
|
25
|
+
const error = cause instanceof Error ? cause : new Error(String(cause))
|
|
132
26
|
process.stdout.write(
|
|
133
|
-
JSON.stringify({
|
|
134
|
-
ok: false,
|
|
135
|
-
error: { message: String(err?.message ?? err), stack: String(err?.stack ?? '') },
|
|
136
|
-
}),
|
|
27
|
+
JSON.stringify({ ok: false, error: { message: error.message, stack: error.stack ?? '' } }),
|
|
137
28
|
)
|
|
138
29
|
process.exit(0)
|
|
139
30
|
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* core.ts — assembles a domain's StudioCore: the genesis node/edge graph
|
|
3
|
-
* extracted from canonical `schema.core
|
|
3
|
+
* extracted from canonical `schema.core`, gated
|
|
4
4
|
* on installed deps. Never throws; a failed import or a domain with no core both
|
|
5
5
|
* become a well-formed (empty) render state.
|
|
6
6
|
*/
|
|
@@ -28,7 +28,6 @@ export async function buildCore(handle: DomainHandle): Promise<StudioCore> {
|
|
|
28
28
|
|
|
29
29
|
const r = await coreExtract(
|
|
30
30
|
handle.schemaIndex,
|
|
31
|
-
handle.domainFile,
|
|
32
31
|
handle.root,
|
|
33
32
|
readSettings(handle.root).introspectTimeoutMs,
|
|
34
33
|
)
|
|
@@ -2,27 +2,27 @@ import { describe, expect, test } from 'bun:test'
|
|
|
2
2
|
|
|
3
3
|
import type { IrClass, IrFunction, SchemaIR } from '../../shared/types'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { diffSchemas, structuralStatusOf } from './diff'
|
|
6
6
|
|
|
7
7
|
const callable = (returnsType = 'string'): IrFunction => ({
|
|
8
8
|
name: 'inspect',
|
|
9
9
|
input: { type: 'object', properties: {}, additionalProperties: false },
|
|
10
|
-
params: {},
|
|
11
10
|
output: { mode: 'value', schema: { type: returnsType } },
|
|
12
|
-
returns: { type: returnsType },
|
|
13
|
-
static: true,
|
|
14
|
-
inheritance: 'default',
|
|
15
11
|
auth: 'authenticated',
|
|
16
12
|
})
|
|
17
13
|
|
|
18
14
|
const schema = (functions: SchemaIR['functions']): SchemaIR => ({
|
|
19
15
|
version: 'v1',
|
|
16
|
+
format: 'astrale.dsl',
|
|
20
17
|
domain: 'example.test',
|
|
21
|
-
types: {},
|
|
22
|
-
interfaces: {},
|
|
23
18
|
classes: {},
|
|
24
|
-
|
|
19
|
+
importsByKey: {},
|
|
20
|
+
importedClassesByKey: {},
|
|
25
21
|
functions,
|
|
22
|
+
views: {},
|
|
23
|
+
policies: {},
|
|
24
|
+
dependencies: [],
|
|
25
|
+
core: {},
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
const withClass = (member: IrClass): SchemaIR => ({
|
|
@@ -31,21 +31,19 @@ const withClass = (member: IrClass): SchemaIR => ({
|
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
describe('canonical standalone Function diffs', () => {
|
|
34
|
-
test('
|
|
34
|
+
test('reports additions and removals without claiming Runtime compatibility', () => {
|
|
35
35
|
const empty = schema({})
|
|
36
36
|
const populated = schema({ inspect: callable() })
|
|
37
|
-
expect(diffSchemas(empty, populated)).toEqual([
|
|
38
|
-
{ kind: 'function-added', target: 'inspect', breaking: false },
|
|
39
|
-
])
|
|
37
|
+
expect(diffSchemas(empty, populated)).toEqual([{ kind: 'function-added', target: 'inspect' }])
|
|
40
38
|
const removed = diffSchemas(populated, empty)
|
|
41
|
-
expect(removed).toEqual([{ kind: 'function-removed', target: 'inspect'
|
|
42
|
-
expect(
|
|
39
|
+
expect(removed).toEqual([{ kind: 'function-removed', target: 'inspect' }])
|
|
40
|
+
expect(structuralStatusOf(removed)).toBe('changed')
|
|
43
41
|
})
|
|
44
42
|
|
|
45
43
|
test('detects a standalone Function signature change', () => {
|
|
46
44
|
expect(
|
|
47
45
|
diffSchemas(schema({ inspect: callable() }), schema({ inspect: callable('number') })),
|
|
48
|
-
).toEqual([{ kind: 'function-signature-changed', target: 'inspect'
|
|
46
|
+
).toEqual([{ kind: 'function-signature-changed', target: 'inspect' }])
|
|
49
47
|
})
|
|
50
48
|
|
|
51
49
|
test('detects auth and output-mode changes in callable contracts', () => {
|
|
@@ -57,7 +55,7 @@ describe('canonical standalone Function diffs', () => {
|
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
expect(diffSchemas(schema({ inspect: before }), schema({ inspect: after }))).toEqual([
|
|
60
|
-
{ kind: 'function-signature-changed', target: 'inspect'
|
|
58
|
+
{ kind: 'function-signature-changed', target: 'inspect' },
|
|
61
59
|
])
|
|
62
60
|
})
|
|
63
61
|
|
|
@@ -65,6 +63,8 @@ describe('canonical standalone Function diffs', () => {
|
|
|
65
63
|
const member = (required: string[], minLength: number): IrClass => ({
|
|
66
64
|
type: 'node',
|
|
67
65
|
name: 'Person',
|
|
66
|
+
origin: 'example.test',
|
|
67
|
+
ref: { origin: 'example.test', kind: 'class', name: 'Person' },
|
|
68
68
|
properties: { name: { type: 'string', minLength } },
|
|
69
69
|
required,
|
|
70
70
|
methods: {},
|
|
@@ -75,13 +75,11 @@ describe('canonical standalone Function diffs', () => {
|
|
|
75
75
|
kind: 'prop-schema-changed',
|
|
76
76
|
target: 'Person.name',
|
|
77
77
|
detail: 'value constraints changed',
|
|
78
|
-
breaking: true,
|
|
79
78
|
},
|
|
80
79
|
{
|
|
81
80
|
kind: 'prop-required-changed',
|
|
82
81
|
target: 'Person.name',
|
|
83
82
|
detail: 'optional → required',
|
|
84
|
-
breaking: true,
|
|
85
83
|
},
|
|
86
84
|
])
|
|
87
85
|
})
|
|
@@ -91,6 +89,8 @@ describe('canonical standalone Function diffs', () => {
|
|
|
91
89
|
...withClass({
|
|
92
90
|
type: 'edge',
|
|
93
91
|
name: 'owns',
|
|
92
|
+
origin: 'example.test',
|
|
93
|
+
ref: { origin: 'example.test', kind: 'class', name: 'owns' },
|
|
94
94
|
properties: {},
|
|
95
95
|
required: [],
|
|
96
96
|
methods: {},
|