@astrale-os/cli 1.0.0-beta.32 → 1.0.0-beta.43
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/CHANGELOG.md +928 -0
- package/README.md +53 -43
- package/THIRD-PARTY-NOTICES.md +37 -1
- package/dist/astrale.js +349631 -83669
- package/dist/public/connect-core.js +16 -47
- package/dist/public/keys/index.js +1 -1
- package/dist/types/admin/contract.d.ts +11 -0
- package/dist/types/admin/graph/index.d.ts +1 -0
- package/dist/types/admin/graph/nodes.d.ts +12 -0
- package/dist/types/admin/instance/client.d.ts +2 -0
- package/dist/types/connection/lifetime.d.ts +1 -1
- package/dist/types/errors.d.ts +3 -0
- package/dist/types/lib/proc.d.ts +1 -0
- package/dist/types/lib/update.d.ts +15 -7
- package/package.json +8 -6
- package/studio/client/dist/assets/index-5C1uT6ML.css +2 -0
- package/studio/client/dist/assets/index-C4kNlvwF.js +80 -0
- package/studio/client/dist/assets/schema-studio-BR9d0faB.js +8 -0
- package/studio/client/dist/index.html +13 -2
- package/studio/package.json +2 -1
- package/studio/server/agent/ask.test.ts +7 -1
- package/studio/server/agent/bridge/grant.ts +15 -3
- package/studio/server/agent/prompts/system.test.ts +5 -0
- package/studio/server/agent/prompts/system.ts +19 -4
- package/studio/server/agent/routes.test.ts +39 -1
- package/studio/server/agent/routes.ts +3 -0
- package/studio/server/agent/run/coordinator.test.ts +7 -1
- package/studio/server/agent/run/preparation.ts +1 -0
- package/studio/server/agent/run/transcript.test.ts +47 -2
- package/studio/server/agent/run/transcript.ts +32 -3
- package/studio/server/api/documents.test.ts +31 -0
- package/studio/server/api/documents.ts +35 -1
- package/studio/server/api-agent-loadout.test.ts +7 -1
- package/studio/server/api.test.ts +7 -1
- package/studio/server/cache.ts +4 -4
- package/studio/server/detect.ts +9 -12
- package/studio/server/domain.test.ts +83 -3
- package/studio/server/domain.ts +205 -27
- package/studio/server/handoff/service.ts +1 -1
- package/studio/server/index.ts +5 -8
- package/studio/server/introspect/extractor.ts +111 -17
- package/studio/server/introspect/overlay-tsmorph.test.ts +9 -9
- package/studio/server/introspect/overlay.ts +1 -1
- package/studio/server/introspect/runtime.ts +9 -1
- package/studio/server/introspect/source-overlay/spans.ts +2 -5
- package/studio/server/lifecycle.ts +1 -1
- package/studio/server/state/baseline.test.ts +14 -0
- package/studio/server/state/baseline.ts +16 -2
- package/studio/server/watch.test.ts +2 -1
- package/studio/server/watch.ts +5 -2
- package/studio/server/workspace/create.ts +9 -8
- package/studio/server/workspace-state.ts +4 -6
- package/studio/server/workspace-watch.ts +33 -22
- package/studio/shared/contracts/agent.ts +3 -0
- package/viewer/dist/main.js +12 -12
- package/src/__tests__/fixtures/publication.ts +0 -20
- package/src/admin/.spec/api.d.ts +0 -3
- package/src/admin/.spec/architecture.md +0 -22
- package/src/admin/.spec/icon.svg +0 -3
- package/src/admin/.spec/layout.ts +0 -6
- package/src/admin/__tests__/fixture.ts +0 -25
- package/src/admin/catalog/.spec/api.d.ts +0 -63
- package/src/admin/catalog/.spec/architecture.md +0 -7
- package/src/admin/catalog/.spec/icon.svg +0 -3
- package/src/admin/catalog/.spec/layout.ts +0 -6
- package/src/admin/catalog/__tests__/client.test.ts +0 -245
- package/src/admin/catalog/client.ts +0 -195
- package/src/admin/catalog/index.ts +0 -13
- package/src/admin/catalog/model.ts +0 -41
- package/src/admin/catalog/tsconfig.json +0 -8
- package/src/admin/contract.ts +0 -47
- package/src/admin/graph/.spec/api.d.ts +0 -22
- package/src/admin/graph/.spec/architecture.md +0 -5
- package/src/admin/graph/.spec/icon.svg +0 -3
- package/src/admin/graph/.spec/layout.ts +0 -3
- package/src/admin/graph/index.ts +0 -6
- package/src/admin/graph/nodes.ts +0 -56
- package/src/admin/index.ts +0 -2
- package/src/admin/instance/.spec/api.d.ts +0 -62
- package/src/admin/instance/.spec/architecture.md +0 -10
- package/src/admin/instance/.spec/icon.svg +0 -3
- package/src/admin/instance/.spec/layout.ts +0 -6
- package/src/admin/instance/__tests__/client.test.ts +0 -273
- package/src/admin/instance/client.ts +0 -191
- package/src/admin/instance/index.ts +0 -15
- package/src/admin/instance/model.ts +0 -59
- package/src/admin/instance/tsconfig.json +0 -8
- package/src/commands/__tests__/admin-instance.test.ts +0 -91
- package/src/commands/__tests__/auth-login.test.ts +0 -231
- package/src/commands/__tests__/auth-token.test.ts +0 -223
- package/src/commands/__tests__/call-describe.test.ts +0 -80
- package/src/commands/__tests__/call.test.ts +0 -63
- package/src/commands/__tests__/domain-install-operation.test.ts +0 -145
- package/src/commands/__tests__/domain-install-owned.test.ts +0 -191
- package/src/commands/__tests__/domain-list.test.ts +0 -133
- package/src/commands/__tests__/domain-uninstall.test.ts +0 -53
- package/src/commands/__tests__/install-direct.test.ts +0 -128
- package/src/commands/__tests__/install-identity-override.test.ts +0 -76
- package/src/commands/__tests__/instance-bookmark.test.ts +0 -166
- package/src/commands/__tests__/instance-list-admin.test.ts +0 -26
- package/src/commands/__tests__/instance-list-rows.test.ts +0 -64
- package/src/commands/__tests__/instance-status.test.ts +0 -139
- package/src/commands/__tests__/instance-use.test.ts +0 -67
- package/src/commands/__tests__/introspect-parse.test.ts +0 -100
- package/src/commands/__tests__/logs.test.ts +0 -345
- package/src/commands/__tests__/read-commands.test.ts +0 -377
- package/src/commands/__tests__/setup-plan.test.ts +0 -61
- package/src/commands/__tests__/studio-descriptor.test.ts +0 -22
- package/src/commands/__tests__/token-ttl.test.ts +0 -66
- package/src/commands/__tests__/update.test.ts +0 -95
- package/src/commands/__tests__/view-build.test.ts +0 -58
- package/src/commands/__tests__/view.test.ts +0 -197
- package/src/commands/admin/status.ts +0 -61
- package/src/commands/admin/use.ts +0 -100
- package/src/commands/auth/login.ts +0 -82
- package/src/commands/auth/logout.ts +0 -53
- package/src/commands/auth/status.ts +0 -86
- package/src/commands/auth/token.ts +0 -174
- package/src/commands/browser.ts +0 -236
- package/src/commands/call-describe.ts +0 -123
- package/src/commands/call.ts +0 -230
- package/src/commands/domain/install.ts +0 -575
- package/src/commands/domain/list.ts +0 -155
- package/src/commands/domain/publish.ts +0 -136
- package/src/commands/domain/uninstall.ts +0 -128
- package/src/commands/get.ts +0 -69
- package/src/commands/identity/__tests__/register.test.ts +0 -93
- package/src/commands/identity/create.ts +0 -35
- package/src/commands/identity/delete.ts +0 -24
- package/src/commands/identity/export.ts +0 -46
- package/src/commands/identity/import.ts +0 -61
- package/src/commands/identity/list.ts +0 -56
- package/src/commands/identity/register.ts +0 -195
- package/src/commands/identity/sync.ts +0 -38
- package/src/commands/identity/unsync.ts +0 -34
- package/src/commands/identity/use.ts +0 -24
- package/src/commands/identity/whoami.ts +0 -34
- package/src/commands/idp/add.ts +0 -150
- package/src/commands/idp/list.ts +0 -57
- package/src/commands/idp/refresh.ts +0 -38
- package/src/commands/idp/remove.ts +0 -36
- package/src/commands/idp/show.ts +0 -29
- package/src/commands/instance/active.ts +0 -73
- package/src/commands/instance/bookmark.ts +0 -101
- package/src/commands/instance/create.ts +0 -61
- package/src/commands/instance/delete.ts +0 -69
- package/src/commands/instance/forget.ts +0 -26
- package/src/commands/instance/list.ts +0 -197
- package/src/commands/instance/status.ts +0 -92
- package/src/commands/instance/use.ts +0 -263
- package/src/commands/introspect.ts +0 -129
- package/src/commands/logs.ts +0 -371
- package/src/commands/mutate.ts +0 -122
- package/src/commands/query.ts +0 -142
- package/src/commands/session/analyze.ts +0 -72
- package/src/commands/session/list.ts +0 -36
- package/src/commands/setup.ts +0 -54
- package/src/commands/status.ts +0 -60
- package/src/commands/studio.ts +0 -434
- package/src/commands/token.ts +0 -121
- package/src/commands/ui/__tests__/commands.test.ts +0 -152
- package/src/commands/ui/add.ts +0 -51
- package/src/commands/ui/doctor.ts +0 -21
- package/src/commands/ui/init.ts +0 -38
- package/src/commands/ui/list.ts +0 -26
- package/src/commands/ui/preset-apply.ts +0 -19
- package/src/commands/ui/preset-list.ts +0 -12
- package/src/commands/ui/shared.ts +0 -25
- package/src/commands/update.ts +0 -356
- package/src/commands/use.ts +0 -86
- package/src/commands/view-serve.ts +0 -26
- package/src/commands/view.ts +0 -658
- package/src/connect-core.test.ts +0 -38
- package/src/connect-core.ts +0 -42
- package/src/connection/.spec/api.d.ts +0 -110
- package/src/connection/.spec/architecture.md +0 -58
- package/src/connection/.spec/capabilities/connection.ts +0 -13
- package/src/connection/.spec/examples/call.ts +0 -7
- package/src/connection/.spec/flows/command.ts +0 -20
- package/src/connection/.spec/flows/session.ts +0 -62
- package/src/connection/.spec/laws/connection.ts +0 -213
- package/src/connection/.spec/layout.ts +0 -22
- package/src/connection/__tests__/auth.test.ts +0 -129
- package/src/connection/__tests__/ca-fetch.test.ts +0 -60
- package/src/connection/__tests__/call.test.ts +0 -17
- package/src/connection/__tests__/credential.test.ts +0 -254
- package/src/connection/__tests__/errors.test.ts +0 -577
- package/src/connection/__tests__/exchange.test.ts +0 -404
- package/src/connection/__tests__/failure-fixtures.ts +0 -39
- package/src/connection/__tests__/failure-safety.test.ts +0 -75
- package/src/connection/__tests__/fixtures/localhost-cert.pem +0 -19
- package/src/connection/__tests__/fixtures/localhost-key.base64 +0 -1
- package/src/connection/__tests__/managed.test.ts +0 -39
- package/src/connection/__tests__/reasons.test.ts +0 -78
- package/src/connection/__tests__/self.test.ts +0 -71
- package/src/connection/__tests__/session.test.ts +0 -144
- package/src/connection/__tests__/target.test.ts +0 -95
- package/src/connection/auth.ts +0 -265
- package/src/connection/call.ts +0 -7
- package/src/connection/command.ts +0 -67
- package/src/connection/credential.ts +0 -138
- package/src/connection/errors.ts +0 -1
- package/src/connection/exchange.ts +0 -394
- package/src/connection/failure/classify.ts +0 -110
- package/src/connection/failure/index.ts +0 -18
- package/src/connection/failure/model.ts +0 -28
- package/src/connection/failure/render.ts +0 -116
- package/src/connection/index.ts +0 -8
- package/src/connection/lifetime.ts +0 -25
- package/src/connection/reasons.ts +0 -209
- package/src/connection/self.ts +0 -138
- package/src/connection/session.ts +0 -203
- package/src/connection/target.ts +0 -112
- package/src/connection/tsconfig.json +0 -6
- package/src/errors.ts +0 -66
- package/src/graph/.spec/api.d.ts +0 -41
- package/src/graph/.spec/laws/documents.ts +0 -24
- package/src/graph/.spec/laws/projection.ts +0 -13
- package/src/graph/.spec/layout.ts +0 -14
- package/src/graph/__tests__/mutation.test.ts +0 -51
- package/src/graph/__tests__/projection.test.ts +0 -22
- package/src/graph/__tests__/query.test.ts +0 -180
- package/src/graph/class.ts +0 -30
- package/src/graph/index.ts +0 -4
- package/src/graph/mutation.ts +0 -46
- package/src/graph/projection.ts +0 -21
- package/src/graph/query.ts +0 -95
- package/src/graph/tsconfig.json +0 -6
- package/src/identity/.history/ard/bootstrap-root-transfer.md +0 -57
- package/src/identity/.history/ard/domain-mediated-registration.md +0 -36
- package/src/identity/.spec/api.d.ts +0 -124
- package/src/identity/.spec/architecture.md +0 -33
- package/src/identity/.spec/capabilities/identity.ts +0 -7
- package/src/identity/.spec/flows/bootstrap-root.ts +0 -79
- package/src/identity/.spec/flows/domain-mediated-registration.ts +0 -51
- package/src/identity/.spec/flows/import.ts +0 -29
- package/src/identity/.spec/laws/identity.ts +0 -56
- package/src/identity/.spec/layout.ts +0 -13
- package/src/identity/__tests__/fixtures/registry-journey.ts +0 -65
- package/src/identity/__tests__/registration.test.ts +0 -64
- package/src/identity/__tests__/registry.test.ts +0 -74
- package/src/identity/__tests__/transfer.test.ts +0 -198
- package/src/identity/index.ts +0 -23
- package/src/identity/registration.ts +0 -72
- package/src/identity/registry.ts +0 -181
- package/src/identity/transfer.ts +0 -187
- package/src/identity/tsconfig.json +0 -6
- package/src/index.ts +0 -1
- package/src/keys/.spec/api.d.ts +0 -74
- package/src/keys/.spec/architecture.md +0 -13
- package/src/keys/.spec/laws/keys.ts +0 -43
- package/src/keys/.spec/layout.ts +0 -6
- package/src/keys/__tests__/algorithm.test.ts +0 -39
- package/src/keys/__tests__/keys.test.ts +0 -172
- package/src/keys/algorithm.ts +0 -33
- package/src/keys/credential.ts +0 -113
- package/src/keys/index.ts +0 -14
- package/src/keys/pair.ts +0 -219
- package/src/keys/tsconfig.json +0 -6
- package/src/lib/__tests__/admin-target.test.ts +0 -184
- package/src/lib/__tests__/binary.test.ts +0 -70
- package/src/lib/__tests__/browser-retention.test.ts +0 -212
- package/src/lib/__tests__/command-dx.test.ts +0 -102
- package/src/lib/__tests__/concurrency.test.ts +0 -62
- package/src/lib/__tests__/config.test.ts +0 -81
- package/src/lib/__tests__/design.test.ts +0 -99
- package/src/lib/__tests__/domain-publication.test.ts +0 -138
- package/src/lib/__tests__/format.test.ts +0 -22
- package/src/lib/__tests__/idp-session.driver.ts +0 -60
- package/src/lib/__tests__/idp-session.test.ts +0 -404
- package/src/lib/__tests__/idp.test.ts +0 -415
- package/src/lib/__tests__/instance-candidates.test.ts +0 -146
- package/src/lib/__tests__/instance-target.test.ts +0 -213
- package/src/lib/__tests__/instance.test.ts +0 -192
- package/src/lib/__tests__/local-status.test.ts +0 -202
- package/src/lib/__tests__/log-errors.test.ts +0 -64
- package/src/lib/__tests__/log.test.ts +0 -31
- package/src/lib/__tests__/meta.test.ts +0 -55
- package/src/lib/__tests__/output.test.ts +0 -162
- package/src/lib/__tests__/panel.test.ts +0 -40
- package/src/lib/__tests__/port.test.ts +0 -44
- package/src/lib/__tests__/prompt.test.ts +0 -25
- package/src/lib/__tests__/sdk-deps.test.ts +0 -68
- package/src/lib/__tests__/self.test.ts +0 -50
- package/src/lib/__tests__/skills.test.ts +0 -834
- package/src/lib/__tests__/studio-server-deps.test.ts +0 -111
- package/src/lib/__tests__/table.test.ts +0 -53
- package/src/lib/__tests__/update.test.ts +0 -511
- package/src/lib/__tests__/use-target.test.ts +0 -56
- package/src/lib/__tests__/validation.test.ts +0 -34
- package/src/lib/__tests__/view-assets.test.ts +0 -171
- package/src/lib/__tests__/view-external-open-intent.test.ts +0 -150
- package/src/lib/__tests__/view-external-open-origins.test.ts +0 -27
- package/src/lib/__tests__/view-open-intent.test.ts +0 -280
- package/src/lib/__tests__/view-port-allocation.test.ts +0 -82
- package/src/lib/__tests__/view-server.test.ts +0 -91
- package/src/lib/__tests__/view-session.test.ts +0 -100
- package/src/lib/__tests__/view-snapshot.test.ts +0 -77
- package/src/lib/admin-domain.ts +0 -43
- package/src/lib/admin-instance.ts +0 -56
- package/src/lib/admin-target.ts +0 -290
- package/src/lib/binary.ts +0 -127
- package/src/lib/browser-retention.ts +0 -210
- package/src/lib/browser.ts +0 -150
- package/src/lib/ca-fetch.ts +0 -133
- package/src/lib/command-dx.ts +0 -191
- package/src/lib/concurrency.ts +0 -31
- package/src/lib/config.ts +0 -57
- package/src/lib/credential-lifetime.ts +0 -24
- package/src/lib/domain-publication.ts +0 -104
- package/src/lib/failure-debug.ts +0 -26
- package/src/lib/format.ts +0 -4
- package/src/lib/idp-session.ts +0 -156
- package/src/lib/idp.ts +0 -926
- package/src/lib/instance-candidates.ts +0 -49
- package/src/lib/instance-target.ts +0 -197
- package/src/lib/instance.ts +0 -468
- package/src/lib/invocation.ts +0 -11
- package/src/lib/local-status.ts +0 -152
- package/src/lib/log.ts +0 -143
- package/src/lib/login-flow.ts +0 -201
- package/src/lib/meta.ts +0 -90
- package/src/lib/output.ts +0 -238
- package/src/lib/panel.ts +0 -61
- package/src/lib/port.ts +0 -41
- package/src/lib/proc.ts +0 -87
- package/src/lib/prompt.ts +0 -136
- package/src/lib/provision-instance.ts +0 -139
- package/src/lib/sdk-deps.ts +0 -104
- package/src/lib/self.ts +0 -22
- package/src/lib/skills/lock.ts +0 -117
- package/src/lib/skills/sync.ts +0 -878
- package/src/lib/skills.ts +0 -120
- package/src/lib/table.ts +0 -62
- package/src/lib/update.ts +0 -568
- package/src/lib/use-target.ts +0 -24
- package/src/lib/validation.ts +0 -59
- package/src/lib/view/assets.ts +0 -87
- package/src/lib/view/external-open-intent.ts +0 -41
- package/src/lib/view/external-open-origins.ts +0 -37
- package/src/lib/view/host-capabilities.ts +0 -17
- package/src/lib/view/open-intent.ts +0 -67
- package/src/lib/view/port-allocation.ts +0 -19
- package/src/lib/view/resolve.ts +0 -111
- package/src/lib/view/server.ts +0 -259
- package/src/lib/view/session.ts +0 -154
- package/src/lib/view/snapshot.ts +0 -101
- package/src/paths/.spec/api.d.ts +0 -13
- package/src/paths/.spec/architecture.md +0 -5
- package/src/paths/.spec/layout.ts +0 -3
- package/src/paths/index.ts +0 -13
- package/src/program/.spec/api.d.ts +0 -43
- package/src/program/.spec/architecture.md +0 -18
- package/src/program/.spec/laws/program.ts +0 -29
- package/src/program/.spec/layout.ts +0 -14
- package/src/program/__tests__/program.test.ts +0 -556
- package/src/program/argv.ts +0 -14
- package/src/program/build.ts +0 -205
- package/src/program/command.ts +0 -43
- package/src/program/index.ts +0 -3
- package/src/program/options.ts +0 -41
- package/src/program/registry.ts +0 -64
- package/src/program/tsconfig.json +0 -6
- package/src/setup/__tests__/instance-step.test.ts +0 -256
- package/src/setup/__tests__/util.test.ts +0 -29
- package/src/setup/engine.ts +0 -83
- package/src/setup/render.ts +0 -107
- package/src/setup/steps/admin.ts +0 -93
- package/src/setup/steps/agent-browser.ts +0 -81
- package/src/setup/steps/auth.ts +0 -54
- package/src/setup/steps/domain.ts +0 -68
- package/src/setup/steps/index.ts +0 -18
- package/src/setup/steps/instance.ts +0 -206
- package/src/setup/steps/skills-bridge.ts +0 -70
- package/src/setup/steps/skills.ts +0 -61
- package/src/setup/types.ts +0 -61
- package/src/setup/util.ts +0 -34
- package/src/state/.spec/api.d.ts +0 -152
- package/src/state/.spec/architecture.md +0 -45
- package/src/state/.spec/capabilities/state.ts +0 -7
- package/src/state/.spec/flows/identity-update.ts +0 -22
- package/src/state/.spec/laws/state.ts +0 -73
- package/src/state/.spec/layout.ts +0 -15
- package/src/state/__tests__/exchange-credentials.test.ts +0 -341
- package/src/state/__tests__/files.test.ts +0 -136
- package/src/state/__tests__/fixtures/identity-transition.ts +0 -37
- package/src/state/__tests__/fixtures/session-route-process.ts +0 -93
- package/src/state/__tests__/identities.test.ts +0 -142
- package/src/state/__tests__/paths.test.ts +0 -28
- package/src/state/__tests__/session-routes.test.ts +0 -138
- package/src/state/exchange-credentials.ts +0 -250
- package/src/state/files.ts +0 -170
- package/src/state/identities.ts +0 -229
- package/src/state/index.ts +0 -31
- package/src/state/paths.ts +0 -64
- package/src/state/session-routes.ts +0 -34
- package/src/state/tsconfig.json +0 -6
- package/src/telemetry/__tests__/analyze-log.test.ts +0 -38
- package/src/telemetry/__tests__/gate.test.ts +0 -63
- package/src/telemetry/__tests__/recorder.test.ts +0 -111
- package/src/telemetry/__tests__/redact.test.ts +0 -79
- package/src/telemetry/__tests__/retention.test.ts +0 -267
- package/src/telemetry/__tests__/session.test.ts +0 -166
- package/src/telemetry/__tests__/settings.test.ts +0 -102
- package/src/telemetry/__tests__/store-scan.test.ts +0 -128
- package/src/telemetry/__tests__/trigger.test.ts +0 -78
- package/src/telemetry/adapters/__tests__/claude-code.test.ts +0 -89
- package/src/telemetry/adapters/__tests__/codex.test.ts +0 -138
- package/src/telemetry/adapters/__tests__/index.test.ts +0 -88
- package/src/telemetry/adapters/claude-code.ts +0 -90
- package/src/telemetry/adapters/codex.ts +0 -160
- package/src/telemetry/adapters/index.ts +0 -45
- package/src/telemetry/adapters/types.ts +0 -21
- package/src/telemetry/analyze.ts +0 -249
- package/src/telemetry/gate.ts +0 -79
- package/src/telemetry/recorder.ts +0 -68
- package/src/telemetry/redact.ts +0 -53
- package/src/telemetry/retention.ts +0 -176
- package/src/telemetry/session.ts +0 -94
- package/src/telemetry/settings.ts +0 -79
- package/src/telemetry/store.ts +0 -174
- package/src/telemetry/trigger.ts +0 -107
- package/src/telemetry/types.ts +0 -64
- package/src/test-utils.ts +0 -18
- package/src/ui/.spec/api.d.ts +0 -14
- package/src/ui/.spec/architecture.md +0 -14
- package/src/ui/.spec/laws.ts +0 -50
- package/src/ui/.spec/layout.ts +0 -16
- package/src/ui/__tests__/ui.test.ts +0 -1742
- package/src/ui/index.ts +0 -13
- package/src/ui/lock.ts +0 -89
- package/src/ui/model.ts +0 -83
- package/src/ui/operations.ts +0 -1044
- package/src/ui/project.ts +0 -333
- package/src/ui/release.ts +0 -398
- package/src/ui/runner.ts +0 -18
- package/studio/client/dist/assets/index-BFVFs_8x.js +0 -81
- package/studio/client/dist/assets/index-DuB9iUdu.css +0 -2
- package/studio/client/dist/assets/schema-studio-DH6oEWME.js +0 -8
- package/studio/tsconfig.json +0 -24
- package/viewer/tsconfig.json +0 -13
|
@@ -31,13 +31,19 @@ function fixture(nested = false): string {
|
|
|
31
31
|
? "import application from './domain/application.js'\nexport default { application }\n"
|
|
32
32
|
: 'export default {}\n',
|
|
33
33
|
)
|
|
34
|
-
writeFileSync(join(owner, 'application.ts'), 'export default {}\n')
|
|
35
34
|
writeFileSync(join(owner, 'schema/index.ts'), 'export const schema = {}\n')
|
|
35
|
+
writeFileSync(
|
|
36
|
+
join(owner, 'application.ts'),
|
|
37
|
+
`import { defineApplication } from '@astrale-os/sdk/application'
|
|
38
|
+
import { schema } from './schema/index.js'
|
|
39
|
+
export default defineApplication({ schema, runtime: {} as never })
|
|
40
|
+
`,
|
|
41
|
+
)
|
|
36
42
|
return root
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
describe('SDK V1 project discovery', () => {
|
|
40
|
-
test('discovers conventional root Application
|
|
46
|
+
test('discovers the Schema selected by the conventional root Application', () => {
|
|
41
47
|
const root = fixture()
|
|
42
48
|
expect(isDomainDir(root)).toBe(true)
|
|
43
49
|
expect(basename(resolveApplicationEntry(root)!)).toBe('application.ts')
|
|
@@ -48,13 +54,87 @@ describe('SDK V1 project discovery', () => {
|
|
|
48
54
|
expect(handle.schemaDirName).toBe('schema')
|
|
49
55
|
})
|
|
50
56
|
|
|
51
|
-
test('follows a config-imported nested Application and
|
|
57
|
+
test('follows a config-imported nested Application and its Schema binding', () => {
|
|
52
58
|
const root = fixture(true)
|
|
53
59
|
const application = resolveApplicationEntry(root)!
|
|
54
60
|
expect(application).toBe(join(root, 'domain/application.ts'))
|
|
55
61
|
expect(resolveSchemaEntry(root, application)).toBe(join(root, 'domain/schema/index.ts'))
|
|
56
62
|
})
|
|
57
63
|
|
|
64
|
+
test('uses Application.schema instead of guessing a conventional Schema path', () => {
|
|
65
|
+
const root = mkdtempSync(join(tmpdir(), 'studio-application-source-of-truth-'))
|
|
66
|
+
roots.push(root)
|
|
67
|
+
mkdirSync(join(root, 'model'), { recursive: true })
|
|
68
|
+
mkdirSync(join(root, 'schema'), { recursive: true })
|
|
69
|
+
writeFileSync(join(root, 'astrale.config.ts'), 'export default {}\n')
|
|
70
|
+
writeFileSync(join(root, 'schema/index.ts'), 'export const decoy = {}\n')
|
|
71
|
+
writeFileSync(join(root, 'model/domain-definition.ts'), 'export const selected = {}\n')
|
|
72
|
+
writeFileSync(
|
|
73
|
+
join(root, 'application.ts'),
|
|
74
|
+
`import { defineApplication as compose } from '@astrale-os/sdk/application'
|
|
75
|
+
import * as definitions from './model/domain-definition.js'
|
|
76
|
+
export default compose({ schema: definitions.selected, runtime: {} as never })
|
|
77
|
+
`,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const application = resolveApplicationEntry(root)!
|
|
81
|
+
expect(resolveSchemaEntry(root, application)).toBe(join(root, 'model/domain-definition.ts'))
|
|
82
|
+
const handle = registerDomain(root)!
|
|
83
|
+
domainIds.push(handle.id)
|
|
84
|
+
expect(handle.schemaDirName).toBe('model')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
test('resolves an extensionless Schema directory import to its authored index', () => {
|
|
88
|
+
const root = mkdtempSync(join(tmpdir(), 'studio-extensionless-schema-'))
|
|
89
|
+
roots.push(root)
|
|
90
|
+
mkdirSync(join(root, 'definition'))
|
|
91
|
+
writeFileSync(join(root, 'astrale.config.ts'), 'export default {}\n')
|
|
92
|
+
writeFileSync(join(root, 'definition/index.ts'), 'export default {}\n')
|
|
93
|
+
writeFileSync(
|
|
94
|
+
join(root, 'application.ts'),
|
|
95
|
+
`import { defineApplication } from '@astrale-os/sdk/application'
|
|
96
|
+
import schema from './definition'
|
|
97
|
+
export default defineApplication({ schema, runtime: {} as never })
|
|
98
|
+
`,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
expect(resolveSchemaEntry(root, join(root, 'application.ts'))).toBe(
|
|
102
|
+
join(root, 'definition/index.ts'),
|
|
103
|
+
)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
test('rejects a conventional Schema that is not selected by Application', () => {
|
|
107
|
+
const root = mkdtempSync(join(tmpdir(), 'studio-unbound-schema-'))
|
|
108
|
+
roots.push(root)
|
|
109
|
+
mkdirSync(join(root, 'schema'))
|
|
110
|
+
writeFileSync(join(root, 'astrale.config.ts'), 'export default {}\n')
|
|
111
|
+
writeFileSync(join(root, 'application.ts'), 'export default {}\n')
|
|
112
|
+
writeFileSync(join(root, 'schema/index.ts'), 'export const schema = {}\n')
|
|
113
|
+
expect(isDomainDir(root)).toBe(false)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('preserves a stable handle and replaces it when Application selects another Schema', () => {
|
|
117
|
+
const root = fixture()
|
|
118
|
+
const first = registerDomain(root)!
|
|
119
|
+
domainIds.push(first.id)
|
|
120
|
+
expect(registerDomain(root)).toBe(first)
|
|
121
|
+
|
|
122
|
+
mkdirSync(join(root, 'model'))
|
|
123
|
+
writeFileSync(join(root, 'model/replacement.ts'), 'export const replacement = {}\n')
|
|
124
|
+
writeFileSync(
|
|
125
|
+
join(root, 'application.ts'),
|
|
126
|
+
`import { defineApplication } from '@astrale-os/sdk/application'
|
|
127
|
+
import { replacement } from './model/replacement.js'
|
|
128
|
+
export default defineApplication({ schema: replacement, runtime: {} as never })
|
|
129
|
+
`,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
const moved = registerDomain(root)!
|
|
133
|
+
expect(moved).not.toBe(first)
|
|
134
|
+
expect(moved.schemaIndex).toBe(join(root, 'model/replacement.ts'))
|
|
135
|
+
expect(moved.schemaDirName).toBe('model')
|
|
136
|
+
})
|
|
137
|
+
|
|
58
138
|
test('requires the semantic SDK dependency, not Kernel implementation packages', () => {
|
|
59
139
|
const root = fixture()
|
|
60
140
|
expect(depsInstalled(root)).toBe(false)
|
package/studio/server/domain.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
/** SDK V1 project discovery and the in-process Studio registry. */
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs'
|
|
3
|
-
import { basename, dirname, extname, join, relative, resolve } from 'node:path'
|
|
2
|
+
import { existsSync, readFileSync, statSync } from 'node:fs'
|
|
3
|
+
import { basename, dirname, extname, isAbsolute, join, relative, resolve } from 'node:path'
|
|
4
|
+
import {
|
|
5
|
+
Node,
|
|
6
|
+
Project,
|
|
7
|
+
SyntaxKind,
|
|
8
|
+
type CallExpression,
|
|
9
|
+
type ObjectLiteralExpression,
|
|
10
|
+
type SourceFile,
|
|
11
|
+
} from 'ts-morph'
|
|
4
12
|
|
|
5
13
|
export interface DomainHandle {
|
|
6
14
|
readonly id: string
|
|
@@ -46,35 +54,43 @@ export function resolveApplicationEntry(root: string): string | null {
|
|
|
46
54
|
return null
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the authored Schema module selected by `defineApplication({ schema })`.
|
|
59
|
+
*
|
|
60
|
+
* Application is the composition source of truth, but importing it would also load
|
|
61
|
+
* Runtime, Frontend, integrations, and any authored top-level effects. Studio follows
|
|
62
|
+
* the Schema binding statically instead, then imports only that module in its isolated
|
|
63
|
+
* extractor subprocess.
|
|
64
|
+
*/
|
|
65
|
+
export function resolveSchemaEntry(root: string, applicationFile: string): string | null {
|
|
55
66
|
const project = resolve(root)
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
const source = addSourceFile(applicationFile)
|
|
68
|
+
if (source === null) return null
|
|
69
|
+
|
|
70
|
+
for (const call of source.getDescendantsOfKind(SyntaxKind.CallExpression)) {
|
|
71
|
+
if (!isDefineApplicationCall(call, source)) continue
|
|
72
|
+
const input = resolveLocalValue(call.getArguments()[0], source)
|
|
73
|
+
if (!input || !Node.isObjectLiteralExpression(input)) continue
|
|
74
|
+
const schema = objectPropertyValue(input, 'schema')
|
|
75
|
+
if (!schema) continue
|
|
76
|
+
const selected = schemaModuleOf(schema, source, project)
|
|
77
|
+
if (selected !== null) return selected
|
|
78
|
+
}
|
|
79
|
+
return null
|
|
64
80
|
}
|
|
65
81
|
|
|
66
|
-
export function isDomainDir(root: string
|
|
82
|
+
export function isDomainDir(root: string): boolean {
|
|
67
83
|
const project = resolve(root)
|
|
68
84
|
if (!existsSync(join(project, 'astrale.config.ts'))) return false
|
|
69
85
|
const application = resolveApplicationEntry(project)
|
|
70
|
-
return application !== null && resolveSchemaEntry(project, application
|
|
86
|
+
return application !== null && resolveSchemaEntry(project, application) !== null
|
|
71
87
|
}
|
|
72
88
|
|
|
73
|
-
export function registerDomain(root: string
|
|
89
|
+
export function registerDomain(root: string): DomainHandle | null {
|
|
74
90
|
const project = resolve(root)
|
|
75
91
|
const applicationFile = resolveApplicationEntry(project)
|
|
76
92
|
if (applicationFile === null || !existsSync(join(project, 'astrale.config.ts'))) return null
|
|
77
|
-
const schemaIndex = resolveSchemaEntry(project, applicationFile
|
|
93
|
+
const schemaIndex = resolveSchemaEntry(project, applicationFile)
|
|
78
94
|
if (schemaIndex === null) return null
|
|
79
95
|
const schemaDir = dirname(schemaIndex)
|
|
80
96
|
const handle: DomainHandle = {
|
|
@@ -86,6 +102,15 @@ export function registerDomain(root: string, schemaDirName = 'schema'): DomainHa
|
|
|
86
102
|
schemaDir,
|
|
87
103
|
schemaIndex,
|
|
88
104
|
}
|
|
105
|
+
const current = registry.get(handle.id)
|
|
106
|
+
if (
|
|
107
|
+
current?.root === handle.root &&
|
|
108
|
+
current.configFile === handle.configFile &&
|
|
109
|
+
current.applicationFile === handle.applicationFile &&
|
|
110
|
+
current.schemaIndex === handle.schemaIndex
|
|
111
|
+
) {
|
|
112
|
+
return current
|
|
113
|
+
}
|
|
89
114
|
registry.set(handle.id, handle)
|
|
90
115
|
return handle
|
|
91
116
|
}
|
|
@@ -114,11 +139,164 @@ export function depsInstalled(root: string): boolean {
|
|
|
114
139
|
}
|
|
115
140
|
|
|
116
141
|
function resolveSourceFile(root: string, specifier: string): string | null {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
142
|
+
return sourceCandidates(resolve(root, specifier)).find(isFile) ?? null
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function addSourceFile(file: string): SourceFile | null {
|
|
146
|
+
try {
|
|
147
|
+
const project = new Project({
|
|
148
|
+
useInMemoryFileSystem: false,
|
|
149
|
+
skipAddingFilesFromTsConfig: true,
|
|
150
|
+
skipFileDependencyResolution: true,
|
|
151
|
+
skipLoadingLibFiles: true,
|
|
152
|
+
compilerOptions: { allowJs: true, allowImportingTsExtensions: true },
|
|
153
|
+
})
|
|
154
|
+
return project.addSourceFileAtPath(file)
|
|
155
|
+
} catch {
|
|
156
|
+
return null
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function unwrap(node: Node): Node {
|
|
161
|
+
let current = node
|
|
162
|
+
while (
|
|
163
|
+
Node.isAsExpression(current) ||
|
|
164
|
+
Node.isSatisfiesExpression(current) ||
|
|
165
|
+
Node.isParenthesizedExpression(current) ||
|
|
166
|
+
Node.isTypeAssertion(current) ||
|
|
167
|
+
Node.isNonNullExpression(current)
|
|
168
|
+
) {
|
|
169
|
+
current = current.getExpression()
|
|
170
|
+
}
|
|
171
|
+
return current
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function resolveLocalValue(
|
|
175
|
+
node: Node | undefined,
|
|
176
|
+
source: SourceFile,
|
|
177
|
+
seen = new Set<string>(),
|
|
178
|
+
): Node | null {
|
|
179
|
+
if (!node) return null
|
|
180
|
+
const value = unwrap(node)
|
|
181
|
+
if (!Node.isIdentifier(value)) return value
|
|
182
|
+
const key = `${source.getFilePath()}:${value.getText()}`
|
|
183
|
+
if (seen.has(key)) return value
|
|
184
|
+
seen.add(key)
|
|
185
|
+
const initializer = source.getVariableDeclaration(value.getText())?.getInitializer()
|
|
186
|
+
return initializer ? resolveLocalValue(initializer, source, seen) : value
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function isDefineApplicationCall(call: CallExpression, source: SourceFile): boolean {
|
|
190
|
+
const expression = call.getExpression()
|
|
191
|
+
if (Node.isIdentifier(expression)) {
|
|
192
|
+
const localName = expression.getText()
|
|
193
|
+
return source
|
|
194
|
+
.getImportDeclarations()
|
|
195
|
+
.some(
|
|
196
|
+
(declaration) =>
|
|
197
|
+
declaration.getModuleSpecifierValue() === '@astrale-os/sdk/application' &&
|
|
198
|
+
declaration
|
|
199
|
+
.getNamedImports()
|
|
200
|
+
.some(
|
|
201
|
+
(named) =>
|
|
202
|
+
named.getName() === 'defineApplication' &&
|
|
203
|
+
(named.getAliasNode()?.getText() ?? named.getName()) === localName,
|
|
204
|
+
),
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
if (
|
|
208
|
+
!Node.isPropertyAccessExpression(expression) ||
|
|
209
|
+
expression.getName() !== 'defineApplication'
|
|
210
|
+
) {
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
213
|
+
const namespace = expression.getExpression()
|
|
214
|
+
if (!Node.isIdentifier(namespace)) return false
|
|
215
|
+
return source
|
|
216
|
+
.getImportDeclarations()
|
|
217
|
+
.some(
|
|
218
|
+
(declaration) =>
|
|
219
|
+
declaration.getModuleSpecifierValue() === '@astrale-os/sdk/application' &&
|
|
220
|
+
declaration.getNamespaceImport()?.getText() === namespace.getText(),
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function objectPropertyValue(object: ObjectLiteralExpression, name: string) {
|
|
225
|
+
const property = object.getProperty(name)
|
|
226
|
+
if (property && Node.isPropertyAssignment(property)) return property.getInitializer()
|
|
227
|
+
if (property && Node.isShorthandPropertyAssignment(property)) return property.getNameNode()
|
|
228
|
+
return undefined
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function schemaModuleOf(node: Node, source: SourceFile, root: string): string | null {
|
|
232
|
+
const value = unwrap(node)
|
|
233
|
+
if (Node.isIdentifier(value)) {
|
|
234
|
+
const initializer = source.getVariableDeclaration(value.getText())?.getInitializer()
|
|
235
|
+
if (initializer) return schemaModuleOf(initializer, source, root)
|
|
236
|
+
for (const declaration of source.getImportDeclarations()) {
|
|
237
|
+
const imported = declaration
|
|
238
|
+
.getNamedImports()
|
|
239
|
+
.some((named) => (named.getAliasNode()?.getText() ?? named.getName()) === value.getText())
|
|
240
|
+
const defaultImported = declaration.getDefaultImport()?.getText() === value.getText()
|
|
241
|
+
if (imported || defaultImported) {
|
|
242
|
+
return resolveAuthoredModule(root, source, declaration.getModuleSpecifierValue())
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return null
|
|
246
|
+
}
|
|
247
|
+
if (Node.isPropertyAccessExpression(value) && Node.isIdentifier(value.getExpression())) {
|
|
248
|
+
const namespace = value.getExpression().getText()
|
|
249
|
+
for (const declaration of source.getImportDeclarations()) {
|
|
250
|
+
if (declaration.getNamespaceImport()?.getText() === namespace) {
|
|
251
|
+
return resolveAuthoredModule(root, source, declaration.getModuleSpecifierValue())
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return null
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function resolveAuthoredModule(root: string, from: SourceFile, specifier: string): string | null {
|
|
259
|
+
let candidates: string[] = []
|
|
260
|
+
if (specifier.startsWith('.')) {
|
|
261
|
+
candidates = sourceCandidates(resolve(dirname(from.getFilePath()), specifier))
|
|
262
|
+
} else if (specifier.startsWith('#')) {
|
|
263
|
+
try {
|
|
264
|
+
candidates = sourceCandidates(Bun.resolveSync(specifier, dirname(from.getFilePath())))
|
|
265
|
+
} catch {
|
|
266
|
+
return null
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
return null
|
|
270
|
+
}
|
|
271
|
+
for (const candidate of candidates) {
|
|
272
|
+
if (!isFile(candidate)) continue
|
|
273
|
+
const rel = relative(root, candidate)
|
|
274
|
+
if (rel === '..' || rel.startsWith('../') || rel.startsWith('..\\') || isAbsolute(rel)) {
|
|
275
|
+
continue
|
|
276
|
+
}
|
|
277
|
+
return candidate
|
|
278
|
+
}
|
|
279
|
+
return null
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function sourceCandidates(file: string): string[] {
|
|
283
|
+
const extension = extname(file)
|
|
284
|
+
const sourceBase = /\.[cm]?jsx?$/u.test(extension) ? file.slice(0, -extension.length) : file
|
|
285
|
+
return [
|
|
286
|
+
file,
|
|
287
|
+
`${sourceBase}.ts`,
|
|
288
|
+
`${sourceBase}.tsx`,
|
|
289
|
+
`${sourceBase}.mts`,
|
|
290
|
+
`${sourceBase}.cts`,
|
|
291
|
+
join(file, 'index.ts'),
|
|
292
|
+
join(file, 'index.tsx'),
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function isFile(file: string): boolean {
|
|
297
|
+
try {
|
|
298
|
+
return statSync(file).isFile()
|
|
299
|
+
} catch {
|
|
300
|
+
return false
|
|
301
|
+
}
|
|
124
302
|
}
|
|
@@ -16,7 +16,7 @@ import { detectGit, gitDiff } from '../workspace/git'
|
|
|
16
16
|
/** Current changes vs the review baseline (schema IR diff + anatomy file diff). */
|
|
17
17
|
export async function changeSet(handle: DomainHandle): Promise<ChangeSet> {
|
|
18
18
|
const bundle = await getBundle(handle.id)
|
|
19
|
-
const files = hashAnatomyFiles(handle.root, handle.schemaDirName)
|
|
19
|
+
const files = hashAnatomyFiles(handle.root, handle.schemaDirName, handle.applicationFile)
|
|
20
20
|
const { hasGit } = detectGit(handle.root)
|
|
21
21
|
const diffText = hasGit ? gitDiff(handle.root, handle.schemaDirName) : null
|
|
22
22
|
return computeChanges(handle.root, bundle?.ir ?? null, files, {
|
package/studio/server/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* index.ts — the Domain Studio server entrypoint.
|
|
4
4
|
*
|
|
5
|
-
* bun server/index.ts [path | --workspace dir] [--port n] [--
|
|
5
|
+
* bun server/index.ts [path | --workspace dir] [--port n] [--open]
|
|
6
6
|
*
|
|
7
7
|
* `path` may be an astrale.config.ts, a domain dir, or a workspace to scan.
|
|
8
8
|
* Boots a Bun HTTP server: serves the built SPA, the JSON API, and the SSE
|
|
@@ -23,14 +23,12 @@ import { watchWorkspace } from './workspace-watch'
|
|
|
23
23
|
const argv = process.argv.slice(2)
|
|
24
24
|
let target = ''
|
|
25
25
|
let port = Number(process.env.PORT) || 4319
|
|
26
|
-
let schemaDir = 'schema'
|
|
27
26
|
// Default OFF — printing the URL is enough; popping a browser is invasive. The CLI
|
|
28
27
|
// owns browser-opening (its own --open), and always passes --no-open here.
|
|
29
28
|
let open = false
|
|
30
29
|
for (let i = 0; i < argv.length; i++) {
|
|
31
30
|
const a = argv[i]
|
|
32
31
|
if (a === '--port') port = Number(argv[++i])
|
|
33
|
-
else if (a === '--schema-dir') schemaDir = argv[++i]
|
|
34
32
|
else if (a === '--open') open = true
|
|
35
33
|
else if (a === '--no-open') open = false
|
|
36
34
|
else if (a === '--workspace') target = argv[++i]
|
|
@@ -38,11 +36,11 @@ for (let i = 0; i < argv.length; i++) {
|
|
|
38
36
|
}
|
|
39
37
|
if (!target) target = process.cwd()
|
|
40
38
|
|
|
41
|
-
const domains = resolveTarget(target
|
|
39
|
+
const domains = resolveTarget(target)
|
|
42
40
|
if (!domains.length) {
|
|
43
41
|
console.error(`\n ✗ No Astrale domains found at ${target}`)
|
|
44
42
|
console.error(
|
|
45
|
-
|
|
43
|
+
' (looking for: astrale.config.ts + an Application whose schema binding resolves to authored source)\n',
|
|
46
44
|
)
|
|
47
45
|
process.exit(1)
|
|
48
46
|
}
|
|
@@ -56,9 +54,8 @@ for (const h of domains) {
|
|
|
56
54
|
|
|
57
55
|
// keep the registry in sync with the workspace — pick up domains added/removed at runtime
|
|
58
56
|
const watchRoot = target.endsWith('astrale.config.ts') ? dirname(resolve(target)) : resolve(target)
|
|
59
|
-
initWorkspaceState(watchRoot
|
|
60
|
-
if (existsSync(watchRoot) && statSync(watchRoot).isDirectory())
|
|
61
|
-
watchWorkspace(watchRoot, schemaDir, stoppers)
|
|
57
|
+
initWorkspaceState(watchRoot) // where `create new` scaffolds + the create endpoint reads
|
|
58
|
+
if (existsSync(watchRoot) && statSync(watchRoot).isDirectory()) watchWorkspace(watchRoot, stoppers)
|
|
62
59
|
|
|
63
60
|
const DIST = process.env.DOMAIN_STUDIO_DIST || join(import.meta.dir, '..', 'client', 'dist')
|
|
64
61
|
const DEV = process.env.DOMAIN_STUDIO_DEV === '1'
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
/** Bun subprocess that imports only the authored Schema entry and its installed SDK. */
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { tmpdir } from 'node:os'
|
|
6
|
+
import { dirname, join } from 'node:path'
|
|
7
|
+
import { pathToFileURL } from 'node:url'
|
|
8
|
+
|
|
2
9
|
import type { SchemaSdk } from './canonical-schema'
|
|
3
10
|
|
|
4
11
|
import { extractCanonicalSchemaFromSdk, findCanonicalDomainSchemaExport } from './canonical-schema'
|
|
@@ -6,26 +13,113 @@ import { extractCanonicalSchemaFromSdk, findCanonicalDomainSchemaExport } from '
|
|
|
6
13
|
const schemaPath = process.argv[2]
|
|
7
14
|
const projectRoot = process.argv[3] ?? process.cwd()
|
|
8
15
|
|
|
16
|
+
async function installedSdkSchema(root: string): Promise<string> {
|
|
17
|
+
let directory = root
|
|
18
|
+
for (;;) {
|
|
19
|
+
const packageRoot = join(directory, 'node_modules', '@astrale-os', 'sdk')
|
|
20
|
+
const manifestPath = join(packageRoot, 'package.json')
|
|
21
|
+
if (existsSync(manifestPath)) {
|
|
22
|
+
const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as {
|
|
23
|
+
exports?: Record<string, string | { import?: string; default?: string; types?: string }>
|
|
24
|
+
}
|
|
25
|
+
const exported = manifest.exports?.['./schema']
|
|
26
|
+
const target =
|
|
27
|
+
typeof exported === 'string'
|
|
28
|
+
? exported
|
|
29
|
+
: (exported?.import ?? exported?.default ?? exported?.types)
|
|
30
|
+
if (target) return join(packageRoot, target)
|
|
31
|
+
throw new Error(`${manifestPath} does not export @astrale-os/sdk/schema`)
|
|
32
|
+
}
|
|
33
|
+
const parent = dirname(directory)
|
|
34
|
+
if (parent === directory) break
|
|
35
|
+
directory = parent
|
|
36
|
+
}
|
|
37
|
+
throw new Error(`Cannot find @astrale-os/sdk from ${root}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function buildFailure(cause: unknown): Error {
|
|
41
|
+
if (cause && typeof cause === 'object') {
|
|
42
|
+
const errors = (cause as { errors?: unknown[] }).errors
|
|
43
|
+
if (Array.isArray(errors) && errors.length > 0) {
|
|
44
|
+
const details = errors
|
|
45
|
+
.map((entry) => (entry instanceof Error ? entry.message : String(entry)))
|
|
46
|
+
.join('\n')
|
|
47
|
+
return new Error(details, { cause })
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return cause instanceof Error ? cause : new Error(String(cause))
|
|
51
|
+
}
|
|
52
|
+
|
|
9
53
|
async function main(): Promise<void> {
|
|
10
54
|
if (!schemaPath) throw new Error('extractor: missing <schemaPath>')
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
55
|
+
const temporary = await mkdtemp(join(tmpdir(), 'astrale-studio-extractor-'))
|
|
56
|
+
try {
|
|
57
|
+
// A compiled Bun executable cannot resolve package imports from a dynamic,
|
|
58
|
+
// external TypeScript entrypoint. Build one short-lived island rooted at the
|
|
59
|
+
// Domain instead: Bun resolves and bundles the authored Schema plus that
|
|
60
|
+
// Domain's exact SDK, then the standalone extractor imports the result.
|
|
61
|
+
const sdkPath = await installedSdkSchema(projectRoot)
|
|
62
|
+
const wrapper = join(temporary, 'entry.ts')
|
|
63
|
+
await writeFile(
|
|
64
|
+
wrapper,
|
|
65
|
+
`import * as authored from ${JSON.stringify(schemaPath)};\n` +
|
|
66
|
+
`import * as sdk from ${JSON.stringify(sdkPath)};\n` +
|
|
67
|
+
`export { authored, sdk };\n`,
|
|
68
|
+
)
|
|
69
|
+
const built = await Bun.build({
|
|
70
|
+
entrypoints: [wrapper],
|
|
71
|
+
outdir: temporary,
|
|
72
|
+
target: 'bun',
|
|
73
|
+
format: 'cjs',
|
|
74
|
+
packages: 'bundle',
|
|
75
|
+
}).catch((cause: unknown) => {
|
|
76
|
+
throw buildFailure(cause)
|
|
77
|
+
})
|
|
78
|
+
if (!built.success) {
|
|
79
|
+
const details = built.logs
|
|
80
|
+
.map((log) => {
|
|
81
|
+
const position = log.position
|
|
82
|
+
const location = position ? `${position.file}:${position.line}:${position.column}: ` : ''
|
|
83
|
+
return `${location}${log.message}`
|
|
84
|
+
})
|
|
85
|
+
.join('\n')
|
|
86
|
+
throw new Error(details || 'schema bundle failed')
|
|
87
|
+
}
|
|
88
|
+
const output = built.outputs.find((candidate) => candidate.kind === 'entry-point')
|
|
89
|
+
if (!output) throw new Error('schema bundle produced no entrypoint')
|
|
90
|
+
const source = await output.text()
|
|
91
|
+
const module = { exports: {} as Record<string, unknown> }
|
|
92
|
+
const require = createRequire(pathToFileURL(join(projectRoot, 'package.json')))
|
|
93
|
+
const factory = new Function(`return (\n${source}\n);`)() as (
|
|
94
|
+
exports: Record<string, unknown>,
|
|
95
|
+
require: NodeRequire,
|
|
96
|
+
module: { exports: Record<string, unknown> },
|
|
97
|
+
filename: string,
|
|
98
|
+
directory: string,
|
|
99
|
+
) => void
|
|
100
|
+
factory(module.exports, require, module, output.path, dirname(output.path))
|
|
101
|
+
const island = module.exports as {
|
|
102
|
+
authored: Record<string, unknown>
|
|
103
|
+
sdk: SchemaSdk
|
|
104
|
+
}
|
|
105
|
+
if (!island?.authored || !island?.sdk) {
|
|
106
|
+
throw new Error(`schema bundle exports are invalid (${Object.keys(island ?? {}).join(', ')})`)
|
|
107
|
+
}
|
|
108
|
+
const candidate = findCanonicalDomainSchemaExport(island.authored)
|
|
109
|
+
if (candidate === null) throw new Error('Schema entry exports no canonical V1 DomainSchema.')
|
|
110
|
+
const extraction = extractCanonicalSchemaFromSdk(island.sdk, candidate)
|
|
111
|
+
process.stdout.write(
|
|
112
|
+
JSON.stringify({
|
|
113
|
+
ok: true,
|
|
114
|
+
ir: extraction.ir,
|
|
115
|
+
root: extraction.root,
|
|
116
|
+
schemaMode: extraction.status === 'admitted' ? 'canonical-admitted' : 'canonical-preview',
|
|
117
|
+
revision: extraction.revision,
|
|
118
|
+
}),
|
|
119
|
+
)
|
|
120
|
+
} finally {
|
|
121
|
+
await rm(temporary, { recursive: true, force: true })
|
|
15
122
|
}
|
|
16
|
-
const sdk = (await import(
|
|
17
|
-
Bun.resolveSync('@astrale-os/sdk/schema', projectRoot)
|
|
18
|
-
)) as unknown as SchemaSdk
|
|
19
|
-
const extraction = extractCanonicalSchemaFromSdk(sdk, candidate)
|
|
20
|
-
process.stdout.write(
|
|
21
|
-
JSON.stringify({
|
|
22
|
-
ok: true,
|
|
23
|
-
ir: extraction.ir,
|
|
24
|
-
root: extraction.root,
|
|
25
|
-
schemaMode: extraction.status === 'admitted' ? 'canonical-admitted' : 'canonical-preview',
|
|
26
|
-
revision: extraction.revision,
|
|
27
|
-
}),
|
|
28
|
-
)
|
|
29
123
|
}
|
|
30
124
|
|
|
31
125
|
main().catch((cause: unknown) => {
|
|
@@ -104,8 +104,8 @@ describe('source overlay', () => {
|
|
|
104
104
|
test('indexes Class, Property, Method, Edge endpoint, and Function declarations', () => {
|
|
105
105
|
const root = mkdtempSync(join(tmpdir(), 'studio-schema-spans-'))
|
|
106
106
|
roots.push(root)
|
|
107
|
-
const schemaDir = join(root, '
|
|
108
|
-
mkdirSync(schemaDir)
|
|
107
|
+
const schemaDir = join(root, 'domain/model')
|
|
108
|
+
mkdirSync(schemaDir, { recursive: true })
|
|
109
109
|
writeFileSync(
|
|
110
110
|
join(schemaDir, 'members.ts'),
|
|
111
111
|
`
|
|
@@ -131,12 +131,12 @@ describe('source overlay', () => {
|
|
|
131
131
|
})
|
|
132
132
|
`,
|
|
133
133
|
)
|
|
134
|
-
const spans = buildSourceSpans({ ir, schemaDir })
|
|
135
|
-
expect(spans['class.Issue.property.title']?.file).toBe('
|
|
136
|
-
expect(spans['class.Issue.method.rename']?.file).toBe('
|
|
137
|
-
expect(spans['edge.assigned_to.endpoint.issue']?.file).toBe('
|
|
138
|
-
expect(spans['edge.assigned_to.endpoint.owner']?.file).toBe('
|
|
139
|
-
expect(spans['edge.assigned_to.property.note']?.file).toBe('
|
|
140
|
-
expect(spans['function.createIssue']?.file).toBe('
|
|
134
|
+
const spans = buildSourceSpans({ ir, domainRoot: root, schemaDir })
|
|
135
|
+
expect(spans['class.Issue.property.title']?.file).toBe('domain/model/members.ts')
|
|
136
|
+
expect(spans['class.Issue.method.rename']?.file).toBe('domain/model/members.ts')
|
|
137
|
+
expect(spans['edge.assigned_to.endpoint.issue']?.file).toBe('domain/model/members.ts')
|
|
138
|
+
expect(spans['edge.assigned_to.endpoint.owner']?.file).toBe('domain/model/members.ts')
|
|
139
|
+
expect(spans['edge.assigned_to.property.note']?.file).toBe('domain/model/members.ts')
|
|
140
|
+
expect(spans['function.createIssue']?.file).toBe('domain/model/members.ts')
|
|
141
141
|
})
|
|
142
142
|
})
|
|
@@ -14,6 +14,6 @@ export interface OverlayArgs {
|
|
|
14
14
|
export function buildOverlay({ ir, domainRoot, schemaDir }: OverlayArgs): SchemaOverlay {
|
|
15
15
|
return {
|
|
16
16
|
handlerLinks: buildHandlerLinks({ ir, domainRoot }),
|
|
17
|
-
sourceSpans: buildSourceSpans({ ir, schemaDir }),
|
|
17
|
+
sourceSpans: buildSourceSpans({ ir, domainRoot, schemaDir }),
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import type { SchemaIR, SchemaRevision, StudioSchemaBundle } from '../../shared/types'
|
|
9
9
|
|
|
10
10
|
import { isSchemaRevision } from '../../shared/types'
|
|
11
|
+
import { studioCliCommand } from '../cli'
|
|
11
12
|
|
|
12
13
|
const EXTRACTOR = new URL('./extractor.ts', import.meta.url).pathname
|
|
13
14
|
|
|
@@ -28,7 +29,14 @@ export async function runtimeExtract(
|
|
|
28
29
|
timeoutMs = 20000,
|
|
29
30
|
): Promise<RuntimeExtractResult> {
|
|
30
31
|
try {
|
|
31
|
-
|
|
32
|
+
let command: string[]
|
|
33
|
+
try {
|
|
34
|
+
command = studioCliCommand(['__studio-extractor', schemaIndexPath, domainDir])
|
|
35
|
+
} catch {
|
|
36
|
+
// Direct Studio development remains supported outside `astrale studio`.
|
|
37
|
+
command = [process.execPath, EXTRACTOR, schemaIndexPath, domainDir]
|
|
38
|
+
}
|
|
39
|
+
const proc = Bun.spawn(command, {
|
|
32
40
|
cwd: domainDir,
|
|
33
41
|
stdout: 'pipe',
|
|
34
42
|
stderr: 'pipe',
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* Source coordinates and leading documentation for authored schema members.
|
|
3
3
|
*/
|
|
4
4
|
import { existsSync } from 'node:fs'
|
|
5
|
-
import { dirname } from 'node:path'
|
|
6
5
|
import { Node, SyntaxKind, type CallExpression, type SourceFile } from 'ts-morph'
|
|
7
6
|
|
|
8
7
|
import type { SchemaIR, SourceSpan } from '../../../shared/types'
|
|
@@ -170,14 +169,12 @@ function resolveMemberKind(
|
|
|
170
169
|
|
|
171
170
|
export function buildSourceSpans(args: {
|
|
172
171
|
ir: SchemaIR | null
|
|
172
|
+
domainRoot: string
|
|
173
173
|
schemaDir: string
|
|
174
174
|
}): Record<string, SourceSpan> {
|
|
175
|
-
const { ir, schemaDir } = args
|
|
175
|
+
const { ir, domainRoot, schemaDir } = args
|
|
176
176
|
if (!schemaDir || !existsSync(schemaDir)) return {}
|
|
177
177
|
|
|
178
|
-
// The domain root is the parent of the schema dir (spans are relative to it).
|
|
179
|
-
const domainRoot = dirname(schemaDir.replace(/\/$/, ''))
|
|
180
|
-
|
|
181
178
|
const project = newProject()
|
|
182
179
|
let files: string[] = []
|
|
183
180
|
try {
|