okengine 0.2.6 → 0.3.2
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/AGENTS.md +33 -30
- package/README.md +74 -340
- package/{spec/manifest.v1.schema.json → manifest.v1.schema.json} +40 -9
- package/package.json +47 -44
- package/site/content/docs/ai/llms-txt.mdx +54 -0
- package/site/content/docs/ai/mcp.mdx +123 -0
- package/site/content/docs/ai/meta.json +5 -0
- package/site/content/docs/ai/skills.mdx +53 -0
- package/site/content/docs/console/access.mdx +29 -0
- package/site/content/docs/console/ai.mdx +35 -0
- package/site/content/docs/console/architecture.mdx +35 -0
- package/site/content/docs/console/channels.mdx +37 -0
- package/site/content/docs/console/clock.mdx +31 -0
- package/site/content/docs/console/flows.mdx +31 -0
- package/site/content/docs/console/gates.mdx +35 -0
- package/site/content/docs/console/manifest-diff.mdx +34 -0
- package/site/content/docs/console/meta.json +23 -0
- package/site/content/docs/console/overview.mdx +40 -0
- package/site/content/docs/console/plugins.mdx +41 -0
- package/site/content/docs/console/privacy.mdx +32 -0
- package/site/content/docs/console/runs.mdx +40 -0
- package/site/content/docs/console/signals.mdx +31 -0
- package/site/content/docs/console/store.mdx +32 -0
- package/site/content/docs/console/tenancy.mdx +32 -0
- package/site/content/docs/console/traces.mdx +34 -0
- package/site/content/docs/console/vault.mdx +37 -0
- package/site/content/docs/elements/ai.mdx +180 -0
- package/site/content/docs/elements/channel.mdx +167 -0
- package/site/content/docs/elements/clock.mdx +182 -0
- package/site/content/docs/elements/flow.mdx +288 -0
- package/site/content/docs/elements/gate.mdx +171 -0
- package/site/content/docs/elements/meta.json +5 -0
- package/site/content/docs/elements/signal.mdx +171 -0
- package/site/content/docs/elements/store.mdx +320 -0
- package/site/content/docs/elements/vault.mdx +263 -0
- package/site/content/docs/get-started/basic-usage.mdx +124 -0
- package/site/content/docs/get-started/comparison.mdx +65 -0
- package/site/content/docs/get-started/installation.mdx +113 -0
- package/site/content/docs/get-started/introduction.mdx +123 -0
- package/site/content/docs/get-started/meta.json +5 -0
- package/site/content/docs/index.mdx +63 -0
- package/site/content/docs/meta.json +5 -0
- package/site/content/docs/plugins/compression.mdx +60 -0
- package/site/content/docs/plugins/cors.mdx +92 -0
- package/site/content/docs/plugins/csrf.mdx +96 -0
- package/site/content/docs/plugins/ip-allowlist.mdx +92 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +101 -0
- package/site/content/docs/plugins/meta.json +15 -0
- package/site/content/docs/plugins/security-headers.mdx +136 -0
- package/site/content/docs/reference/cli.md +101 -0
- package/site/content/docs/reference/configuration.mdx +159 -0
- package/site/content/docs/reference/environment-variables.mdx +87 -0
- package/site/content/docs/reference/errors.mdx +80 -0
- package/site/content/docs/reference/fx.mdx +117 -0
- package/site/content/docs/reference/meta.json +5 -0
- package/site/content/docs/reference/plugins.mdx +249 -0
- package/site/content/docs/reference/security.md +63 -0
- package/src/auth/api-keys.ts +2 -5
- package/src/auth/attenuation.ts +2 -6
- package/src/auth/auth.test.ts +56 -31
- package/src/auth/invoke-as.ts +1 -3
- package/src/auth/operator.ts +8 -26
- package/src/auth/planes.ts +2 -7
- package/src/auth/plugin.ts +4 -7
- package/src/auth/roles.ts +1 -5
- package/src/auth/sessions.ts +10 -39
- package/src/cli/args.ts +1 -5
- package/src/cli/ask-dev-mode.ts +40 -0
- package/src/cli/build.ts +1 -2
- package/src/cli/client-add.test.ts +8 -15
- package/src/cli/client-add.ts +5 -14
- package/src/cli/completion.test.ts +1 -5
- package/src/cli/completion.ts +4 -17
- package/src/cli/db-auto-push.test.ts +64 -0
- package/src/cli/db-auto-push.ts +72 -0
- package/src/cli/db.test.ts +189 -0
- package/src/cli/db.ts +456 -0
- package/src/cli/dev-app-runner.ts +2 -8
- package/src/cli/dev-db-push.test.ts +193 -0
- package/src/cli/dev-mode.test.ts +45 -0
- package/src/cli/dev-mode.ts +78 -0
- package/src/cli/dev-schema-sync.test.ts +66 -0
- package/src/cli/dev-schema-sync.ts +139 -0
- package/src/cli/dev.test.ts +264 -15
- package/src/cli/dev.ts +355 -139
- package/src/cli/doc-staleness.test.ts +69 -0
- package/src/cli/docker-cli.test.ts +27 -8
- package/src/cli/docker.ts +11 -3
- package/src/cli/doctor-diff.test.ts +1 -5
- package/src/cli/doctor-diff.ts +17 -46
- package/src/cli/doctor-pii.ts +2 -7
- package/src/cli/doctor.test.ts +26 -4
- package/src/cli/doctor.ts +35 -11
- package/src/cli/drizzle-env.test.ts +67 -0
- package/src/cli/drizzle-env.ts +78 -0
- package/src/cli/ensure-drizzle-config.ts +50 -0
- package/src/cli/eval.ts +4 -14
- package/src/cli/gates-list.ts +1 -4
- package/src/cli/hero-meta.test.ts +17 -19
- package/src/cli/hero-meta.ts +20 -30
- package/src/cli/images.ts +3 -8
- package/src/cli/index.ts +11 -2
- package/src/cli/load-config.images.test.ts +14 -14
- package/src/cli/load-config.ts +47 -47
- package/src/cli/mcp-from-console.ts +1 -4
- package/src/cli/mode.ts +65 -0
- package/src/cli/openbao-bootstrap.test.ts +147 -0
- package/src/cli/openbao-bootstrap.ts +280 -0
- package/src/cli/openbao-restart.integration.test.ts +136 -0
- package/src/cli/ports.test.ts +7 -14
- package/src/cli/ports.ts +7 -5
- package/src/cli/privacy-erase.ts +1 -3
- package/src/cli/registry.ts +75 -25
- package/src/cli/resolve-dev-sql-env.test.ts +48 -0
- package/src/cli/resolve-dev-sql-env.ts +42 -0
- package/src/cli/schema.ts +3 -10
- package/src/cli/stack.ts +8 -10
- package/src/cli/start.ts +4 -15
- package/src/cli/upgrade.ts +1 -4
- package/src/cli/vault-cmd.ts +63 -0
- package/src/client/budget-entry.ts +1 -6
- package/src/client/create.test.ts +6 -12
- package/src/client/create.ts +2 -8
- package/src/client/errors.ts +1 -4
- package/src/client/index.ts +1 -6
- package/src/client/notes-contract.test.ts +4 -13
- package/src/client/transport.ts +9 -30
- package/src/client/types.ts +15 -30
- package/src/compiler/aot.test.ts +2 -9
- package/src/compiler/aot.ts +1 -4
- package/src/compiler/differential.test.ts +3 -11
- package/src/compiler/dynamic.ts +1 -4
- package/src/compiler/effects-infer.ts +8 -34
- package/src/compiler/emit.ts +1 -3
- package/src/compiler/extract.test.ts +136 -30
- package/src/compiler/extract.ts +485 -157
- package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
- package/src/compiler/fixtures/skyport.expected.json +24 -83
- package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
- package/src/compiler/http-parse.ts +2 -9
- package/src/compiler/index.ts +1 -5
- package/src/compiler/response.ts +16 -7
- package/src/compiler/sucrose.ts +11 -31
- package/src/config/define-config.test.ts +55 -34
- package/src/config/index.ts +177 -46
- package/src/config/resolve-driver.test.ts +28 -17
- package/src/console/budget.test.ts +1 -4
- package/src/console/index.ts +1 -4
- package/src/console/server/access.test.ts +15 -43
- package/src/console/server/access.ts +19 -49
- package/src/console/server/ai.test.ts +3 -11
- package/src/console/server/ai.ts +23 -46
- package/src/console/server/app.ts +16 -45
- package/src/console/server/auth-rate.test.ts +4 -12
- package/src/console/server/bind.ts +1 -5
- package/src/console/server/channels.test.ts +2 -6
- package/src/console/server/channels.ts +10 -35
- package/src/console/server/claim.ts +2 -8
- package/src/console/server/clock.test.ts +2 -6
- package/src/console/server/clock.ts +8 -26
- package/src/console/server/console.test.ts +1 -3
- package/src/console/server/diff.test.ts +5 -17
- package/src/console/server/diff.ts +10 -31
- package/src/console/server/dry-run.audit.test.ts +2 -8
- package/src/console/server/flows.ts +64 -233
- package/src/console/server/gates.test.ts +14 -50
- package/src/console/server/gates.ts +13 -48
- package/src/console/server/index.ts +2 -9
- package/src/console/server/live.ts +3 -12
- package/src/console/server/operator-db.test.ts +4 -15
- package/src/console/server/operator-db.ts +13 -32
- package/src/console/server/plugin.ts +50 -53
- package/src/console/server/plugins.test.ts +2 -6
- package/src/console/server/plugins.ts +17 -56
- package/src/console/server/runs-pii.ts +2 -7
- package/src/console/server/security.gate.test.ts +18 -40
- package/src/console/server/serve.ts +10 -25
- package/src/console/server/signals.test.ts +1 -3
- package/src/console/server/signals.ts +17 -40
- package/src/console/server/state.ts +21 -59
- package/src/console/server/store.test.ts +20 -22
- package/src/console/server/store.ts +31 -76
- package/src/console/server/vault.test.ts +12 -29
- package/src/console/server/vault.ts +44 -66
- package/src/console/ui/access/AccessA11yView.tsx +6 -21
- package/src/console/ui/access/a11y.test.tsx +3 -12
- package/src/console/ui/access/acknowledgement.test.ts +1 -4
- package/src/console/ui/access/acknowledgement.ts +1 -3
- package/src/console/ui/access/blast-radius.ts +1 -3
- package/src/console/ui/access/confirmation.test.ts +1 -5
- package/src/console/ui/access/confirmation.ts +1 -4
- package/src/console/ui/access/fixture.ts +1 -5
- package/src/console/ui/access/grantable.test.ts +1 -3
- package/src/console/ui/access/grantable.ts +2 -7
- package/src/console/ui/access/index.ts +2 -9
- package/src/console/ui/access/provenance.test.ts +1 -3
- package/src/console/ui/access/provenance.ts +2 -6
- package/src/console/ui/access/search.test.ts +1 -5
- package/src/console/ui/access/search.ts +2 -6
- package/src/console/ui/ai/AiA11yView.tsx +6 -17
- package/src/console/ui/ai/a11y.test.tsx +2 -5
- package/src/console/ui/ai/fixture.ts +2 -7
- package/src/console/ui/ai/format.ts +1 -3
- package/src/console/ui/ai/group.test.ts +1 -3
- package/src/console/ui/ai/group.ts +4 -12
- package/src/console/ui/ai/index.ts +2 -9
- package/src/console/ui/ai/promotion.test.ts +2 -7
- package/src/console/ui/ai/promotion.ts +4 -13
- package/src/console/ui/ai/search.test.ts +2 -11
- package/src/console/ui/ai/search.ts +3 -13
- package/src/console/ui/ai/types.ts +1 -8
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
- package/src/console/ui/architecture/a11y.test.tsx +1 -2
- package/src/console/ui/architecture/declared.ts +1 -5
- package/src/console/ui/architecture/index.ts +7 -35
- package/src/console/ui/architecture/layout.ts +1 -3
- package/src/console/ui/architecture/pathologies.ts +10 -19
- package/src/console/ui/architecture/search.ts +6 -15
- package/src/console/ui/architecture/traffic.ts +4 -14
- package/src/console/ui/architecture/types.ts +2 -10
- package/src/console/ui/architecture/view.test.ts +7 -19
- package/src/console/ui/architecture/view.ts +9 -36
- package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
- package/src/console/ui/channels/a11y.test.tsx +1 -2
- package/src/console/ui/channels/confirmation.test.ts +1 -4
- package/src/console/ui/channels/confirmation.ts +1 -4
- package/src/console/ui/channels/findings.ts +1 -5
- package/src/console/ui/channels/index.ts +2 -8
- package/src/console/ui/channels/locale.test.ts +1 -3
- package/src/console/ui/channels/locale.ts +2 -8
- package/src/console/ui/channels/search.ts +4 -13
- package/src/console/ui/channels/taxonomy.ts +1 -3
- package/src/console/ui/clock/ClockA11yView.tsx +9 -26
- package/src/console/ui/clock/a11y.test.tsx +2 -5
- package/src/console/ui/clock/confirmation.test.ts +1 -3
- package/src/console/ui/clock/confirmation.ts +1 -4
- package/src/console/ui/clock/findings.ts +1 -4
- package/src/console/ui/clock/health.ts +2 -7
- package/src/console/ui/clock/index.ts +2 -10
- package/src/console/ui/clock/search.test.ts +1 -3
- package/src/console/ui/clock/search.ts +2 -6
- package/src/console/ui/clock/timeline.test.ts +1 -3
- package/src/console/ui/clock/waiting-on.test.ts +1 -5
- package/src/console/ui/clock/waiting-on.ts +2 -7
- package/src/console/ui/diff/DiffA11yView.tsx +8 -17
- package/src/console/ui/diff/a11y.test.tsx +2 -5
- package/src/console/ui/diff/group.test.ts +3 -13
- package/src/console/ui/diff/group.ts +2 -8
- package/src/console/ui/diff/index.ts +2 -8
- package/src/console/ui/diff/search.test.ts +1 -5
- package/src/console/ui/diff/search.ts +4 -16
- package/src/console/ui/diff/summary.ts +1 -2
- package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
- package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
- package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
- package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
- package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
- package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
- package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
- package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
- package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
- package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
- package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
- package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
- package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
- package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
- package/src/console/ui/flows/a11y.test.tsx +2 -8
- package/src/console/ui/flows/buffer.test.ts +3 -11
- package/src/console/ui/flows/buffer.ts +4 -11
- package/src/console/ui/flows/confirmation.ts +1 -3
- package/src/console/ui/flows/contract.test.ts +3 -7
- package/src/console/ui/flows/contract.ts +12 -36
- package/src/console/ui/flows/graph.test.ts +3 -11
- package/src/console/ui/flows/graph.ts +5 -15
- package/src/console/ui/flows/index.ts +1 -6
- package/src/console/ui/flows/save-as-test.ts +1 -3
- package/src/console/ui/flows/search.ts +8 -25
- package/src/console/ui/flows/tiers.ts +2 -9
- package/src/console/ui/gates/GatesA11yView.tsx +4 -13
- package/src/console/ui/gates/a11y.test.tsx +2 -5
- package/src/console/ui/gates/audit.ts +1 -3
- package/src/console/ui/gates/denial.test.ts +1 -3
- package/src/console/ui/gates/denial.ts +4 -12
- package/src/console/ui/gates/findings.ts +1 -3
- package/src/console/ui/gates/group.test.ts +3 -3
- package/src/console/ui/gates/group.ts +3 -11
- package/src/console/ui/gates/index.ts +2 -10
- package/src/console/ui/gates/search.ts +3 -10
- package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
- package/src/console/ui/overview/a11y.test.tsx +1 -2
- package/src/console/ui/overview/busiest.ts +1 -3
- package/src/console/ui/overview/compose.ts +1 -13
- package/src/console/ui/overview/cost.ts +34 -38
- package/src/console/ui/overview/fixture.ts +21 -26
- package/src/console/ui/overview/golden.ts +4 -14
- package/src/console/ui/overview/index.ts +2 -9
- package/src/console/ui/overview/rank.test.ts +3 -10
- package/src/console/ui/overview/rank.ts +2 -7
- package/src/console/ui/overview/slo.test.ts +5 -9
- package/src/console/ui/overview/slo.ts +6 -23
- package/src/console/ui/overview/verdict.ts +3 -10
- package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
- package/src/console/ui/plugins/a11y.test.tsx +1 -2
- package/src/console/ui/plugins/fixture.ts +2 -4
- package/src/console/ui/plugins/group.test.ts +1 -3
- package/src/console/ui/plugins/group.ts +1 -6
- package/src/console/ui/plugins/index.ts +3 -13
- package/src/console/ui/plugins/search.ts +7 -19
- package/src/console/ui/runs/RunsA11yView.tsx +5 -20
- package/src/console/ui/runs/a11y.test.tsx +2 -5
- package/src/console/ui/runs/explain.ts +2 -6
- package/src/console/ui/runs/group.ts +3 -12
- package/src/console/ui/runs/histogram.test.ts +2 -11
- package/src/console/ui/runs/histogram.ts +1 -4
- package/src/console/ui/runs/index.ts +4 -18
- package/src/console/ui/runs/project.ts +2 -6
- package/src/console/ui/runs/query.test.ts +1 -3
- package/src/console/ui/runs/query.ts +12 -35
- package/src/console/ui/runs/search.ts +5 -19
- package/src/console/ui/runs/trace-link.test.ts +2 -6
- package/src/console/ui/runs/trace-link.ts +4 -16
- package/src/console/ui/runs/types.ts +1 -3
- package/src/console/ui/shell/App.tsx +2 -10
- package/src/console/ui/shell/client.ts +22 -115
- package/src/console/ui/shell/components/ui.tsx +1 -4
- package/src/console/ui/shell/layout/Shell.tsx +2 -4
- package/src/console/ui/shell/main.tsx +31 -96
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
- package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
- package/src/console/ui/shell/setup/Wizard.tsx +3 -5
- package/src/console/ui/shell/styles.css +1 -2
- package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
- package/src/console/ui/signals/a11y.test.tsx +2 -5
- package/src/console/ui/signals/confirmation.test.ts +1 -5
- package/src/console/ui/signals/confirmation.ts +2 -6
- package/src/console/ui/signals/dry-run.ts +1 -3
- package/src/console/ui/signals/durable.ts +1 -3
- package/src/console/ui/signals/findings.ts +1 -3
- package/src/console/ui/signals/group.test.ts +2 -8
- package/src/console/ui/signals/group.ts +2 -10
- package/src/console/ui/signals/index.ts +1 -4
- package/src/console/ui/signals/monitor.ts +2 -7
- package/src/console/ui/signals/schema-form.test.ts +3 -14
- package/src/console/ui/signals/schema-form.ts +1 -4
- package/src/console/ui/signals/search.ts +4 -13
- package/src/console/ui/store/StoreA11yView.tsx +3 -9
- package/src/console/ui/store/a11y.test.tsx +2 -5
- package/src/console/ui/store/confirmation.test.ts +1 -3
- package/src/console/ui/store/confirmation.ts +1 -4
- package/src/console/ui/store/dry-run.ts +2 -5
- package/src/console/ui/store/fixture.ts +1 -2
- package/src/console/ui/store/group.test.ts +1 -6
- package/src/console/ui/store/group.ts +1 -4
- package/src/console/ui/store/index.ts +1 -5
- package/src/console/ui/store/search.ts +2 -6
- package/src/console/ui/store/will-not-fire.ts +1 -2
- package/src/console/ui/traces/TracesA11yView.tsx +10 -29
- package/src/console/ui/traces/a11y.test.tsx +1 -2
- package/src/console/ui/traces/chain.test.ts +5 -19
- package/src/console/ui/traces/chain.ts +1 -3
- package/src/console/ui/traces/critical-path.test.ts +1 -3
- package/src/console/ui/traces/critical-path.ts +2 -6
- package/src/console/ui/traces/filter.test.ts +2 -6
- package/src/console/ui/traces/filter.ts +5 -13
- package/src/console/ui/traces/fold.test.ts +4 -12
- package/src/console/ui/traces/fold.ts +1 -3
- package/src/console/ui/traces/mini.ts +1 -3
- package/src/console/ui/traces/replay.test.ts +1 -3
- package/src/console/ui/traces/replay.ts +1 -3
- package/src/console/ui/traces/sampling.ts +1 -4
- package/src/console/ui/traces/search.ts +4 -17
- package/src/console/ui/traces/tier.ts +1 -3
- package/src/console/ui/vault/VaultA11yView.tsx +5 -17
- package/src/console/ui/vault/a11y.test.tsx +1 -2
- package/src/console/ui/vault/blast-radius.ts +1 -3
- package/src/console/ui/vault/confirmation.test.ts +1 -5
- package/src/console/ui/vault/confirmation.ts +1 -4
- package/src/console/ui/vault/dormant.test.ts +1 -4
- package/src/console/ui/vault/export-safe.test.ts +1 -5
- package/src/console/ui/vault/export-safe.ts +1 -4
- package/src/console/ui/vault/fixture.ts +3 -3
- package/src/console/ui/vault/group.ts +1 -2
- package/src/console/ui/vault/index.ts +2 -10
- package/src/console/ui/vault/search.ts +2 -6
- package/src/console/ui/vault/types.ts +1 -1
- package/src/console/xss.gate.test.ts +1 -3
- package/src/docker/compose.ts +215 -27
- package/src/docker/derive.ts +6 -14
- package/src/docker/docker.test.ts +118 -15
- package/src/docker/dockerfile.integration.test.ts +12 -21
- package/src/docker/helpers.ts +5 -4
- package/src/docker/index.ts +9 -6
- package/src/docker/pin.ts +1 -9
- package/src/docker/recipes/index.ts +6 -6
- package/src/docker/recipes/mailpit.ts +22 -0
- package/src/docker/recipes/openbao.ts +47 -0
- package/src/docker/recipes/postgres.ts +17 -6
- package/src/docker/recipes/redis.ts +11 -2
- package/src/docker/recipes/rustfs.ts +32 -0
- package/src/docker/stack-id.test.ts +73 -5
- package/src/docker/stack-id.ts +124 -33
- package/src/docker/stack.integration.test.ts +6 -21
- package/src/docker/stack.ts +36 -4
- package/src/docker/types.ts +16 -4
- package/src/docs-origin.ts +4 -4
- package/src/drivers/ai-anthropic.ts +5 -14
- package/src/drivers/ai-mock.ts +2 -5
- package/src/drivers/ai-openai-compatible.ts +4 -10
- package/src/drivers/ai-providers.test.ts +6 -13
- package/src/drivers/bun-native-completeness.test.ts +6 -15
- package/src/drivers/channel-console.ts +6 -7
- package/src/drivers/channel-fcm.ts +20 -30
- package/src/drivers/channel-resend.ts +1 -3
- package/src/drivers/channel-smtp.ts +2 -6
- package/src/drivers/channel-types.ts +2 -12
- package/src/drivers/channel-unifonic.ts +2 -6
- package/src/drivers/channel-wa-cloud.ts +2 -6
- package/src/drivers/channel-webpush.ts +21 -60
- package/src/drivers/conformance.test.ts +2 -10
- package/src/drivers/conformance.ts +8 -21
- package/src/drivers/drizzle-dialect.test.ts +20 -0
- package/src/drivers/drizzle-dialect.ts +37 -0
- package/src/drivers/fs.ts +2 -8
- package/src/drivers/index.ts +12 -57
- package/src/drivers/memory.ts +287 -75
- package/src/drivers/pgvector.ts +7 -11
- package/src/drivers/postgres.ts +7 -13
- package/src/drivers/redis.ts +13 -37
- package/src/drivers/s3.ts +15 -18
- package/src/drivers/signal-engine.ts +12 -49
- package/src/drivers/signal-memory.ts +2 -8
- package/src/drivers/signal-nats.ts +4 -9
- package/src/drivers/signal-postgres.ts +62 -129
- package/src/drivers/signal-redis.ts +7 -21
- package/src/drivers/signal-types.ts +1 -4
- package/src/drivers/sqlite.ts +3 -12
- package/src/drivers/types.ts +4 -23
- package/src/drivers/vault-driver-removal.test.ts +55 -0
- package/src/drivers/vault-env.ts +2 -6
- package/src/drivers/vault-infisical.ts +1 -5
- package/src/drivers/vault-managed.ts +1 -5
- package/src/drivers/vault-memory.ts +1 -5
- package/src/drivers/vault-openbao.test.ts +97 -0
- package/src/drivers/vault-openbao.ts +103 -40
- package/src/drivers/vault-types.ts +3 -16
- package/src/elements/ai/declare.ts +4 -14
- package/src/elements/ai/eval.ts +2 -6
- package/src/elements/ai/pii.ts +1 -3
- package/src/elements/ai/runtime.ts +12 -50
- package/src/elements/ai/schema.ts +4 -15
- package/src/elements/ai.test.ts +13 -24
- package/src/elements/ai.ts +1 -5
- package/src/elements/channel/consent.ts +3 -12
- package/src/elements/channel/costs.ts +4 -15
- package/src/elements/channel/declare.ts +1 -4
- package/src/elements/channel/email-auth.ts +1 -4
- package/src/elements/channel/locale.ts +2 -10
- package/src/elements/channel/mask.ts +1 -3
- package/src/elements/channel/mime.ts +2 -12
- package/src/elements/channel/outcomes.test.ts +1 -5
- package/src/elements/channel/outcomes.ts +5 -15
- package/src/elements/channel/receipts.ts +2 -7
- package/src/elements/channel/runtime.ts +28 -74
- package/src/elements/channel/suppression.ts +8 -14
- package/src/elements/channel.test.ts +8 -31
- package/src/elements/channel.ts +3 -14
- package/src/elements/clock/actions.ts +6 -18
- package/src/elements/clock/declare.ts +1 -3
- package/src/elements/clock/dst.ts +1 -5
- package/src/elements/clock/durable.ts +4 -16
- package/src/elements/clock/health.ts +2 -7
- package/src/elements/clock/leader.ts +2 -9
- package/src/elements/clock/reconcile.ts +4 -15
- package/src/elements/clock/runtime.ts +2 -5
- package/src/elements/clock/schedule.ts +4 -20
- package/src/elements/clock.test.ts +2 -7
- package/src/elements/clock.ts +5 -23
- package/src/elements/gate/permissions.ts +1 -4
- package/src/elements/gate/runtime.ts +7 -28
- package/src/elements/gate.ts +1 -5
- package/src/elements/index.ts +9 -7
- package/src/elements/signal/declare.ts +2 -7
- package/src/elements/signal/reconcile.test.ts +1 -4
- package/src/elements/signal/runtime.ts +1 -3
- package/src/elements/signal.test.ts +3 -15
- package/src/elements/signal.ts +2 -8
- package/src/elements/store/cache.test.ts +46 -0
- package/src/elements/store/cache.ts +3 -11
- package/src/elements/store/classify.ts +5 -22
- package/src/elements/store/declare.ts +11 -17
- package/src/elements/store/domain-ddl.test.ts +86 -0
- package/src/elements/store/emit-drizzle.ts +363 -0
- package/src/elements/store/files-policy.test.ts +1 -5
- package/src/elements/store/files-policy.ts +4 -12
- package/src/elements/store/load-plugin-tables.ts +103 -0
- package/src/elements/store/missing-relation.test.ts +83 -0
- package/src/elements/store/missing-relation.ts +38 -0
- package/src/elements/store/replica.ts +1 -4
- package/src/elements/store/resource-list-docs.fixture.ts +56 -0
- package/src/elements/store/resource-list-docs.test.ts +79 -0
- package/src/elements/store/resource.test.ts +253 -0
- package/src/elements/store/resource.ts +786 -0
- package/src/elements/store/runtime.ts +25 -28
- package/src/elements/store/schema-decl.test.ts +227 -0
- package/src/elements/store/schema-decl.ts +516 -0
- package/src/elements/store/sql-condition.test.ts +132 -0
- package/src/elements/store/sql-condition.ts +293 -65
- package/src/elements/store/sql-session.test.ts +135 -0
- package/src/elements/store/sql-session.ts +241 -84
- package/src/elements/store/table.ts +69 -23
- package/src/elements/store.test.ts +17 -39
- package/src/elements/store.ts +53 -31
- package/src/elements/vault/chain.ts +34 -0
- package/src/elements/vault/declare.ts +22 -32
- package/src/elements/vault/fingerprint.ts +2 -7
- package/src/elements/vault/redact.ts +2 -6
- package/src/elements/vault/runtime.ts +19 -33
- package/src/elements/vault.test.ts +12 -55
- package/src/elements/vault.ts +9 -13
- package/src/index.ts +5 -2
- package/src/kernel/adopt-routes.ts +15 -29
- package/src/kernel/app.ts +92 -118
- package/src/kernel/auth-resolve.ts +2 -9
- package/src/kernel/boot-bind/ai.ts +1 -4
- package/src/kernel/boot-bind/channel.test.ts +60 -0
- package/src/kernel/boot-bind/channel.ts +61 -5
- package/src/kernel/boot-bind/clock.ts +2 -6
- package/src/kernel/boot-bind/gate.ts +2 -8
- package/src/kernel/boot-bind/runs.ts +1 -3
- package/src/kernel/boot-bind/signal.ts +3 -10
- package/src/kernel/boot-bind/store.test.ts +27 -18
- package/src/kernel/boot-bind/store.ts +93 -52
- package/src/kernel/boot-bind/vault.ts +2 -8
- package/src/kernel/boot.test.ts +4 -10
- package/src/kernel/boot.ts +30 -77
- package/src/kernel/budget.test.ts +1 -3
- package/src/kernel/capability.ts +3 -10
- package/src/kernel/dry-run.test.ts +1 -4
- package/src/kernel/dry-run.ts +3 -11
- package/src/kernel/edge.test.ts +68 -0
- package/src/kernel/effects.test.ts +1 -5
- package/src/kernel/effects.ts +4 -11
- package/src/kernel/errors.registry.test.ts +2 -8
- package/src/kernel/errors.ts +23 -32
- package/src/kernel/flow.test.ts +12 -25
- package/src/kernel/flow.ts +13 -25
- package/src/kernel/fx.test.ts +31 -40
- package/src/kernel/fx.ts +135 -90
- package/src/kernel/hook-timing.test.ts +3 -6
- package/src/kernel/hook-timing.ts +5 -14
- package/src/kernel/hooks.test.ts +43 -10
- package/src/kernel/hooks.ts +25 -12
- package/src/kernel/index.ts +11 -17
- package/src/kernel/journal.ts +7 -31
- package/src/kernel/on.ts +45 -9
- package/src/kernel/pipeline.test.ts +10 -19
- package/src/kernel/pipeline.ts +5 -17
- package/src/kernel/plug.ts +4 -11
- package/src/kernel/plugin/conflicts.test.ts +13 -25
- package/src/kernel/plugin/decorate.test.ts +8 -13
- package/src/kernel/plugin/scoping.test.ts +4 -11
- package/src/kernel/plugin.ts +81 -27
- package/src/kernel/registry-isolation.test.ts +74 -0
- package/src/kernel/registry.ts +102 -30
- package/src/kernel/router.test.ts +15 -13
- package/src/kernel/router.ts +9 -29
- package/src/kernel/routing-budget.test.ts +1 -3
- package/src/kernel/run-telemetry.ts +1 -3
- package/src/kernel/triggers.ts +63 -21
- package/src/manifest/diff.test.ts +26 -91
- package/src/manifest/diff.ts +95 -225
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/fixtures/skyport.manifest.json +1 -1
- package/src/manifest/index.ts +3 -10
- package/src/manifest/types.ts +30 -6
- package/src/manifest/undeclared.test.ts +4 -12
- package/src/manifest/undeclared.ts +1 -2
- package/src/manifest/validate.test.ts +2 -6
- package/src/manifest/validate.ts +5 -15
- package/src/mcp/authorization.ts +8 -27
- package/src/mcp/confirmation.ts +3 -10
- package/src/mcp/data.ts +2 -6
- package/src/mcp/docs-index.ts +4 -7
- package/src/mcp/docs-mcp.test.ts +3 -12
- package/src/mcp/docs-server.ts +7 -27
- package/src/mcp/docs-tools.ts +2 -6
- package/src/mcp/index.ts +1 -6
- package/src/mcp/injection.gate.test.ts +4 -18
- package/src/mcp/mcp.test.ts +18 -49
- package/src/mcp/protocol.ts +3 -10
- package/src/mcp/server.ts +11 -52
- package/src/mcp/session.ts +4 -14
- package/src/mcp/tools.ts +14 -50
- package/src/plugins/catalogue.test.ts +3 -7
- package/src/plugins/catalogue.ts +1 -3
- package/src/plugins/compression.test.ts +127 -0
- package/src/plugins/compression.ts +94 -0
- package/src/plugins/config-source.test.ts +204 -0
- package/src/plugins/config-source.ts +209 -0
- package/src/plugins/cors.test.ts +138 -0
- package/src/plugins/cors.ts +129 -0
- package/src/plugins/csrf.test.ts +102 -0
- package/src/plugins/csrf.ts +86 -0
- package/src/plugins/headers.ts +54 -0
- package/src/plugins/index.ts +26 -0
- package/src/plugins/ip-allowlist.test.ts +105 -0
- package/src/plugins/ip-allowlist.ts +76 -0
- package/src/plugins/maintenance-mode.test.ts +91 -0
- package/src/plugins/maintenance-mode.ts +85 -0
- package/src/plugins/node-import-scan.ts +2 -5
- package/src/plugins/security-headers.test.ts +243 -0
- package/src/plugins/security-headers.ts +255 -0
- package/src/plugins/supply-chain.ts +5 -17
- package/src/release/exports.ts +3 -8
- package/src/release/measure.exports.test.ts +1 -3
- package/src/release/measure.ts +16 -45
- package/src/runs/bench.test.ts +1 -3
- package/src/runs/collect.ts +8 -25
- package/src/runs/drivers/clickhouse.ts +2 -9
- package/src/runs/drivers/files.ts +9 -31
- package/src/runs/drivers/memory.ts +5 -22
- package/src/runs/drivers/postgres.ts +8 -20
- package/src/runs/duckdb.ts +2 -8
- package/src/runs/index.ts +3 -14
- package/src/runs/outlier.ts +3 -10
- package/src/runs/parquet.ts +8 -26
- package/src/runs/privacy.ts +2 -8
- package/src/runs/runs.test.ts +3 -9
- package/src/runs/runtime.ts +7 -32
- package/src/runs/shred.ts +10 -29
- package/src/runs/types.ts +1 -4
- package/src/runtime/bun.ts +4 -15
- package/src/runtime/cold-start.bench.ts +1 -3
- package/src/runtime/dev-request-log.test.ts +1 -4
- package/src/runtime/dev-request-log.ts +1 -4
- package/src/runtime/index.ts +1 -6
- package/src/runtime/primitives.ts +5 -4
- package/src/runtime/security.ts +3 -13
- package/src/runtime/serve.test.ts +4 -7
- package/src/runtime/types.ts +1 -4
- package/src/runtime/web-standard.ts +3 -15
- package/src/term.test.ts +4 -6
- package/src/term.ts +49 -98
- package/src/test/create-test-app.test.ts +4 -14
- package/src/test/create-test-app.ts +27 -33
- package/src/test/provisions.integration.test.ts +3 -11
- package/src/upgrade/codemods.test.ts +25 -6
- package/src/upgrade/codemods.ts +116 -3
- package/src/validation/standard-schema.test.ts +2 -5
- package/src/validation/standard-schema.ts +13 -33
- package/docs/spec/console.md +0 -739
- package/docs/spec/example.md +0 -1196
- package/docs/spec/four-applications.md +0 -1195
- package/docs/spec/unified-theory.md +0 -489
- package/src/cli/doc-drift.test.ts +0 -146
- package/src/cli/doc-drift.ts +0 -430
- package/src/cli/doctor-diff-examples.ts +0 -92
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
- package/src/drivers/vault-sops.ts +0 -271
package/src/cli/dev.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `oke dev` — watch · hot reload · Console :6533 · MCP :6535 · client types on save.
|
|
3
|
-
* `
|
|
3
|
+
* Mode: `local` (in-memory) or `docker` (compose infra + host Bun).
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { watch } from "node:fs";
|
|
@@ -13,8 +13,9 @@ import type { ConsoleState } from "../console/server/state.ts";
|
|
|
13
13
|
import {
|
|
14
14
|
DEFAULT_DOCKER_DIR,
|
|
15
15
|
deriveInfrastructure,
|
|
16
|
-
|
|
16
|
+
loadExistingStackControls,
|
|
17
17
|
loadExistingStackCredentials,
|
|
18
|
+
resolveExtraPorts,
|
|
18
19
|
stackAppSlug,
|
|
19
20
|
stackInstanceId,
|
|
20
21
|
writeDerivedFiles,
|
|
@@ -22,11 +23,7 @@ import {
|
|
|
22
23
|
} from "../docker/index.ts";
|
|
23
24
|
import type { Manifest } from "../manifest/types.ts";
|
|
24
25
|
import type { McpContext } from "../mcp/tools.ts";
|
|
25
|
-
import {
|
|
26
|
-
APP_PORT,
|
|
27
|
-
CONSOLE_PORT,
|
|
28
|
-
MCP_PORT,
|
|
29
|
-
} from "../runtime/types.ts";
|
|
26
|
+
import { APP_PORT, CONSOLE_PORT, DOCS_MCP_PORT, MCP_PORT } from "../runtime/types.ts";
|
|
30
27
|
import {
|
|
31
28
|
formatDevBanner,
|
|
32
29
|
formatDevLogSeparator,
|
|
@@ -36,15 +33,16 @@ import {
|
|
|
36
33
|
} from "../term.ts";
|
|
37
34
|
import { clientAdd } from "./client-add.ts";
|
|
38
35
|
import { resolveDriverId } from "../config/index.ts";
|
|
36
|
+
import { askDevMode, type AskDevModeFn } from "./ask-dev-mode.ts";
|
|
39
37
|
import {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} from "./load-config.ts";
|
|
38
|
+
createDebouncedRunner,
|
|
39
|
+
isDomainSchemaWatchPath,
|
|
40
|
+
resolveDevAutoPush,
|
|
41
|
+
} from "./db-auto-push.ts";
|
|
42
|
+
import { resolveDrizzleConfigPath, runPush } from "./db.ts";
|
|
43
|
+
import { readDevMode, shouldAskDevMode, writeDevMode, type DevMode } from "./dev-mode.ts";
|
|
44
|
+
import { buildDevHeroSnapshot, encodeHeroSnapshot } from "./hero-meta.ts";
|
|
45
|
+
import { loadManifest, loadOkeConfig, resolveImages } from "./load-config.ts";
|
|
48
46
|
import { mcpContextFromConsole } from "./mcp-from-console.ts";
|
|
49
47
|
import { resolveDevPorts } from "./ports.ts";
|
|
50
48
|
|
|
@@ -94,6 +92,12 @@ export interface DevServeMcpOptions {
|
|
|
94
92
|
readonly hostname?: string;
|
|
95
93
|
}
|
|
96
94
|
|
|
95
|
+
/** Options for {@link DevOptions.serveDocsMcp}. */
|
|
96
|
+
export interface DevServeDocsMcpOptions {
|
|
97
|
+
readonly port: number;
|
|
98
|
+
readonly hostname?: string;
|
|
99
|
+
}
|
|
100
|
+
|
|
97
101
|
/** Live `oke dev` session — returned when {@link DevOptions.keepAlive} is false. */
|
|
98
102
|
export interface DevSession {
|
|
99
103
|
readonly plan: DevPlan;
|
|
@@ -103,6 +107,10 @@ export interface DevSession {
|
|
|
103
107
|
readonly consolePort: number;
|
|
104
108
|
readonly mcpPort: number;
|
|
105
109
|
readonly mcpUrl: URL | null;
|
|
110
|
+
/** Docs MCP listen port (read-only, unauthenticated). */
|
|
111
|
+
readonly docsMcpPort: number;
|
|
112
|
+
/** Docs MCP base URL — null when the surface was skipped. */
|
|
113
|
+
readonly docsMcpUrl: URL | null;
|
|
106
114
|
/** Shared with Console — mint `oke-mcp` tokens against this store/secret. */
|
|
107
115
|
readonly secret: string | null;
|
|
108
116
|
readonly sessions: SessionStore | null;
|
|
@@ -110,11 +118,43 @@ export interface DevSession {
|
|
|
110
118
|
readonly consoleState: ConsoleState | null;
|
|
111
119
|
}
|
|
112
120
|
|
|
121
|
+
/** Minimal filesystem watcher contract, injectable for deterministic tests. */
|
|
122
|
+
export type DevWatchFn = (
|
|
123
|
+
path: string,
|
|
124
|
+
options: { readonly recursive: true },
|
|
125
|
+
listener: (event: "rename" | "change", filename: string | null) => void,
|
|
126
|
+
) => { close(): void };
|
|
127
|
+
|
|
113
128
|
/** Options for {@link runDev}. */
|
|
114
129
|
export interface DevOptions {
|
|
115
130
|
readonly cwd?: string;
|
|
116
131
|
readonly entry?: string;
|
|
117
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Session-only mode override. `true` / role list → docker; `false` → local.
|
|
134
|
+
* When unset, resolve from `.oke/mode` / TTY ask / non-TTY default `local`.
|
|
135
|
+
*/
|
|
136
|
+
readonly docker?: boolean | readonly string[];
|
|
137
|
+
/** Force local for this session only (never writes `.oke/mode`). */
|
|
138
|
+
readonly local?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Opt out of auto `oke db push` on schema change for this session.
|
|
141
|
+
* Also set via `--no-db-push`.
|
|
142
|
+
*/
|
|
143
|
+
readonly noDbPush?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Injectable domain-schema push (tests). Default: {@link runPush}.
|
|
146
|
+
*
|
|
147
|
+
* @param cwd - Project root
|
|
148
|
+
*/
|
|
149
|
+
readonly dbPush?: (cwd: string) => Promise<number>;
|
|
150
|
+
/**
|
|
151
|
+
* Called when a schema watch path triggers auto-push (tests).
|
|
152
|
+
*
|
|
153
|
+
* @param filename - Relative path from the watcher
|
|
154
|
+
*/
|
|
155
|
+
readonly onDbAutoPush?: (filename: string) => void;
|
|
156
|
+
/** Watch project source changes (injectable for tests). */
|
|
157
|
+
readonly watchFs?: DevWatchFn;
|
|
118
158
|
readonly images?: Readonly<Record<string, string>>;
|
|
119
159
|
readonly credentials?: DeriveOptions["credentials"];
|
|
120
160
|
readonly write?: (text: string) => void;
|
|
@@ -137,16 +177,14 @@ export interface DevOptions {
|
|
|
137
177
|
readonly appPort?: number;
|
|
138
178
|
readonly consolePort?: number;
|
|
139
179
|
readonly mcpPort?: number;
|
|
180
|
+
readonly docsMcpPort?: number;
|
|
140
181
|
/**
|
|
141
|
-
* Boot compose
|
|
182
|
+
* Boot compose (injectable).
|
|
142
183
|
*
|
|
143
184
|
* @param composeFiles - `-f` list excluding override if missing
|
|
144
|
-
* @param cwd -
|
|
185
|
+
* @param cwd - Compose directory (`docker/`)
|
|
145
186
|
*/
|
|
146
|
-
readonly composeUp?: (
|
|
147
|
-
composeFiles: readonly string[],
|
|
148
|
-
cwd: string,
|
|
149
|
-
) => Promise<void>;
|
|
187
|
+
readonly composeUp?: (composeFiles: readonly string[], cwd: string) => Promise<void>;
|
|
150
188
|
/**
|
|
151
189
|
* Regenerate client types (injectable).
|
|
152
190
|
*
|
|
@@ -160,16 +198,27 @@ export interface DevOptions {
|
|
|
160
198
|
* Default: {@link serveMcp} on :6535.
|
|
161
199
|
*/
|
|
162
200
|
readonly serveMcp?: (options: DevServeMcpOptions) => Promise<DevMcpHandle>;
|
|
201
|
+
/**
|
|
202
|
+
* Serve the read-only docs MCP (injectable).
|
|
203
|
+
* Default: {@link serveDocsMcp} on :6536. Boot failure skips the surface —
|
|
204
|
+
* docs search must never take `oke dev` down.
|
|
205
|
+
*/
|
|
206
|
+
readonly serveDocsMcp?: (options: DevServeDocsMcpOptions) => Promise<DevMcpHandle>;
|
|
163
207
|
/**
|
|
164
208
|
* Boot + serve the app entry (injectable).
|
|
165
209
|
* Default: spawn `bun --hot` on the shipped {@link ./dev-app-runner.ts}
|
|
166
210
|
* (import → `app.boot()` → `createBunRuntime().serve`) so Bun soft-reloads
|
|
167
211
|
* app code while preserving the listen socket.
|
|
168
212
|
*/
|
|
169
|
-
readonly startApp?: (
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
213
|
+
readonly startApp?: (entry: string, env: Record<string, string>) => Promise<DevAppHandle>;
|
|
214
|
+
/**
|
|
215
|
+
* Injectable mode prompt (tests). Default: {@link askDevMode}.
|
|
216
|
+
*/
|
|
217
|
+
readonly ask?: AskDevModeFn;
|
|
218
|
+
/**
|
|
219
|
+
* Override stdin TTY detection (tests). Default: `process.stdin.isTTY`.
|
|
220
|
+
*/
|
|
221
|
+
readonly stdinIsTTY?: boolean;
|
|
173
222
|
}
|
|
174
223
|
|
|
175
224
|
/** Result of a dry-run / prepared / live-but-detached dev session. */
|
|
@@ -178,6 +227,7 @@ export interface DevPlan {
|
|
|
178
227
|
readonly appPort: number;
|
|
179
228
|
readonly consolePort: number;
|
|
180
229
|
readonly mcpPort: number;
|
|
230
|
+
readonly docsMcpPort: number;
|
|
181
231
|
readonly stackRoles: readonly string[] | null;
|
|
182
232
|
readonly composeFiles: readonly string[] | null;
|
|
183
233
|
readonly stackEnv: Readonly<Record<string, string>> | null;
|
|
@@ -202,24 +252,29 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
202
252
|
const preferredApp = options.appPort ?? Number(Bun.env.PORT ?? APP_PORT);
|
|
203
253
|
const preferredConsole = options.consolePort ?? CONSOLE_PORT;
|
|
204
254
|
const preferredMcp = options.mcpPort ?? MCP_PORT;
|
|
255
|
+
const preferredDocsMcp = options.docsMcpPort ?? DOCS_MCP_PORT;
|
|
205
256
|
// Explicit overrides (incl. `0` ephemeral) skip probing; otherwise +1 until free.
|
|
206
257
|
const ports =
|
|
207
258
|
options.appPort !== undefined ||
|
|
208
259
|
options.consolePort !== undefined ||
|
|
209
|
-
options.mcpPort !== undefined
|
|
260
|
+
options.mcpPort !== undefined ||
|
|
261
|
+
options.docsMcpPort !== undefined
|
|
210
262
|
? {
|
|
211
263
|
app: preferredApp,
|
|
212
264
|
console: preferredConsole,
|
|
213
265
|
mcp: preferredMcp,
|
|
266
|
+
docsMcp: preferredDocsMcp,
|
|
214
267
|
}
|
|
215
268
|
: await resolveDevPorts({
|
|
216
269
|
app: preferredApp,
|
|
217
270
|
console: preferredConsole,
|
|
218
271
|
mcp: preferredMcp,
|
|
272
|
+
docsMcp: preferredDocsMcp,
|
|
219
273
|
});
|
|
220
274
|
const appPort = ports.app;
|
|
221
275
|
const consolePort = ports.console;
|
|
222
276
|
const mcpPort = ports.mcp;
|
|
277
|
+
const docsMcpPort = ports.docsMcp;
|
|
223
278
|
const keepAlive = options.keepAlive ?? true;
|
|
224
279
|
|
|
225
280
|
let entry = options.entry;
|
|
@@ -236,20 +291,55 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
236
291
|
return { code: 1 };
|
|
237
292
|
}
|
|
238
293
|
|
|
294
|
+
const explicitLocal = options.local === true;
|
|
295
|
+
const explicitDocker = options.docker === true || Array.isArray(options.docker);
|
|
296
|
+
if (explicitLocal && explicitDocker) {
|
|
297
|
+
console.error("oke dev: use either --local or --docker, not both");
|
|
298
|
+
return { code: 1 };
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const savedMode = await readDevMode(cwd);
|
|
302
|
+
const explicit = explicitLocal || explicitDocker;
|
|
303
|
+
let mode: DevMode;
|
|
304
|
+
if (explicitLocal) {
|
|
305
|
+
mode = "local";
|
|
306
|
+
} else if (explicitDocker) {
|
|
307
|
+
mode = "docker";
|
|
308
|
+
} else if (savedMode !== null) {
|
|
309
|
+
mode = savedMode;
|
|
310
|
+
} else if (
|
|
311
|
+
shouldAskDevMode({
|
|
312
|
+
saved: savedMode,
|
|
313
|
+
explicit,
|
|
314
|
+
stdinIsTTY: options.stdinIsTTY ?? process.stdin.isTTY,
|
|
315
|
+
})
|
|
316
|
+
) {
|
|
317
|
+
const ask = options.ask ?? askDevMode;
|
|
318
|
+
const chosen = await ask();
|
|
319
|
+
if (chosen === null) {
|
|
320
|
+
console.error("oke dev: cancelled");
|
|
321
|
+
return { code: 1 };
|
|
322
|
+
}
|
|
323
|
+
mode = chosen;
|
|
324
|
+
await writeDevMode(cwd, mode);
|
|
325
|
+
} else {
|
|
326
|
+
// Non-TTY + unset: deterministic local — zero ask, zero docker, no save.
|
|
327
|
+
mode = "local";
|
|
328
|
+
}
|
|
329
|
+
|
|
239
330
|
let stackRoles: string[] | null = null;
|
|
240
331
|
let composeFiles: string[] | null = null;
|
|
241
332
|
let stackEnv: Record<string, string> | null = null;
|
|
242
333
|
let stackSqlDriver = "postgres";
|
|
243
334
|
let stackKvDriver = "redis";
|
|
244
|
-
let loadedConfig: Awaited<ReturnType<typeof loadOkeConfig>>["config"] | null =
|
|
245
|
-
null;
|
|
335
|
+
let loadedConfig: Awaited<ReturnType<typeof loadOkeConfig>>["config"] | null = null;
|
|
246
336
|
try {
|
|
247
337
|
loadedConfig = (await loadOkeConfig(cwd)).config;
|
|
248
338
|
} catch {
|
|
249
339
|
loadedConfig = null;
|
|
250
340
|
}
|
|
251
341
|
|
|
252
|
-
if (
|
|
342
|
+
if (mode === "docker") {
|
|
253
343
|
let images = options.images;
|
|
254
344
|
if (!images) {
|
|
255
345
|
if (!loadedConfig) {
|
|
@@ -271,28 +361,24 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
271
361
|
loadedConfig = null;
|
|
272
362
|
}
|
|
273
363
|
}
|
|
274
|
-
if (Array.isArray(options.
|
|
275
|
-
const allow = new Set(options.
|
|
276
|
-
images = Object.fromEntries(
|
|
277
|
-
Object.entries(images).filter(([role]) => allow.has(role)),
|
|
278
|
-
);
|
|
364
|
+
if (Array.isArray(options.docker)) {
|
|
365
|
+
const allow = new Set(options.docker);
|
|
366
|
+
images = Object.fromEntries(Object.entries(images).filter(([role]) => allow.has(role)));
|
|
279
367
|
stackRoles = [...allow];
|
|
280
368
|
} else {
|
|
281
369
|
stackRoles = Object.keys(images);
|
|
282
370
|
}
|
|
283
371
|
|
|
284
|
-
stackSqlDriver =
|
|
285
|
-
|
|
286
|
-
stackKvDriver =
|
|
287
|
-
resolveDriverId(loadedConfig?.drivers?.store?.kv, "prod") ?? "redis";
|
|
372
|
+
stackSqlDriver = resolveDriverId(loadedConfig?.drivers?.store?.sql, "prod") ?? "postgres";
|
|
373
|
+
stackKvDriver = resolveDriverId(loadedConfig?.drivers?.store?.kv, "prod") ?? "redis";
|
|
288
374
|
|
|
289
375
|
const composeDir = DEFAULT_DOCKER_DIR;
|
|
290
376
|
const dockerOut = resolve(cwd, composeDir);
|
|
291
377
|
const instanceId = stackInstanceId(cwd);
|
|
292
378
|
const appSlug = stackAppSlug(cwd);
|
|
293
379
|
const reusedCreds =
|
|
294
|
-
options.credentials ??
|
|
295
|
-
|
|
380
|
+
options.credentials ?? (await loadExistingStackCredentials(cwd, stackRoles));
|
|
381
|
+
const controls = await loadExistingStackControls(cwd);
|
|
296
382
|
const derived = deriveInfrastructure({
|
|
297
383
|
images,
|
|
298
384
|
app: appSlug,
|
|
@@ -301,46 +387,77 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
301
387
|
composeDir,
|
|
302
388
|
instanceId,
|
|
303
389
|
...(reusedCreds ? { credentials: reusedCreds } : {}),
|
|
390
|
+
...(controls ? { controls } : {}),
|
|
304
391
|
host: "127.0.0.1",
|
|
305
392
|
});
|
|
306
393
|
// Layer 4 is user-owned — include only if the file already exists.
|
|
307
|
-
const existingOverride = await Bun.file(
|
|
308
|
-
resolve(dockerOut, "compose.override.yml"),
|
|
309
|
-
).exists();
|
|
394
|
+
const existingOverride = await Bun.file(resolve(dockerOut, "compose.override.yml")).exists();
|
|
310
395
|
composeFiles = derived.composeFiles.filter(
|
|
311
396
|
(f) => f !== "compose.override.yml" || existingOverride,
|
|
312
397
|
);
|
|
313
398
|
stackEnv = { ...derived.stackEnv };
|
|
314
399
|
|
|
315
400
|
if (!options.dryRun) {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
});
|
|
320
|
-
// Ensure .env.stack is at project root for the host Bun app / vault.
|
|
321
|
-
await Bun.write(resolve(cwd, ".env.stack"), formatStackEnv(stackEnv));
|
|
322
|
-
const up =
|
|
323
|
-
options.composeUp ??
|
|
324
|
-
(async (files, dir) => {
|
|
325
|
-
const args = ["compose", ...files.flatMap((f) => ["-f", f]), "up", "-d"];
|
|
326
|
-
const proc = Bun.spawn(["docker", ...args], {
|
|
327
|
-
cwd: dir,
|
|
328
|
-
stdout: "inherit",
|
|
329
|
-
stderr: "inherit",
|
|
330
|
-
env: { ...process.env, ...stackEnv! },
|
|
331
|
-
});
|
|
332
|
-
const code = await proc.exited;
|
|
333
|
-
if (code !== 0) {
|
|
334
|
-
throw new Error(`oke dev --stack: docker compose exited ${code}`);
|
|
335
|
-
}
|
|
401
|
+
try {
|
|
402
|
+
await writeDerivedFiles(derived, dockerOut, {
|
|
403
|
+
writeStackEnv: true,
|
|
336
404
|
});
|
|
337
|
-
|
|
338
|
-
|
|
405
|
+
const up =
|
|
406
|
+
options.composeUp ??
|
|
407
|
+
(async (files, dir) => {
|
|
408
|
+
const args = ["compose", ...files.flatMap((f) => ["-f", f]), "up", "-d"];
|
|
409
|
+
const proc = Bun.spawn(["docker", ...args], {
|
|
410
|
+
cwd: dir,
|
|
411
|
+
stdout: "inherit",
|
|
412
|
+
stderr: "inherit",
|
|
413
|
+
env: { ...process.env, ...stackEnv! },
|
|
414
|
+
});
|
|
415
|
+
const code = await proc.exited;
|
|
416
|
+
if (code !== 0) {
|
|
417
|
+
throw new Error(`oke dev --docker: docker compose exited ${code}`);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
// Compose files live under docker/; cwd for compose is that directory.
|
|
421
|
+
await up(composeFiles, dockerOut);
|
|
422
|
+
|
|
423
|
+
// Real OpenBao vault: init once / unseal every start, then expose the
|
|
424
|
+
// least-privilege app token to the app + Console (never root).
|
|
425
|
+
const vaultSpec = derived.specs.find((s) => s.role === "vault");
|
|
426
|
+
if (vaultSpec) {
|
|
427
|
+
const { ensureOpenBao, openbaoStackEnv } = await import("./openbao-bootstrap.ts");
|
|
428
|
+
const vaultNames = await tryLoadVaultSecretNames(cwd);
|
|
429
|
+
const boot = await ensureOpenBao({
|
|
430
|
+
cwd,
|
|
431
|
+
url: `http://127.0.0.1:${vaultSpec.hostPort}`,
|
|
432
|
+
names: vaultNames,
|
|
433
|
+
});
|
|
434
|
+
Object.assign(stackEnv!, openbaoStackEnv(boot));
|
|
435
|
+
const envPath = resolve(dockerOut, ".env.docker");
|
|
436
|
+
const current = await Bun.file(envPath).text();
|
|
437
|
+
const tokenLine = `OKE_VAULT_TOKEN=${boot.appToken}`;
|
|
438
|
+
const next = /OKE_VAULT_TOKEN=.*/.test(current)
|
|
439
|
+
? current.replace(/OKE_VAULT_TOKEN=.*/, tokenLine)
|
|
440
|
+
: `${current.trimEnd()}\nOKE_VAULT_TOKEN=${boot.appToken}\nOKE_VAULT_MOUNT=secret\n`;
|
|
441
|
+
await Bun.write(envPath, next);
|
|
442
|
+
}
|
|
443
|
+
} catch (err) {
|
|
444
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
445
|
+
console.error(msg);
|
|
446
|
+
console.error("oke dev: docker mode failed — fix compose, or run `oke mode local`");
|
|
447
|
+
return { code: 1 };
|
|
448
|
+
}
|
|
339
449
|
const roleLabel = (role: string): string => {
|
|
340
450
|
if (role === "store.sql") return "postgres";
|
|
341
451
|
if (role === "store.kv") return "redis";
|
|
452
|
+
if (role === "store.files") return "files";
|
|
453
|
+
if (role === "channel.email") return "mail";
|
|
342
454
|
return role;
|
|
343
455
|
};
|
|
456
|
+
const extraLabel = (role: string, containerPort: number): string => {
|
|
457
|
+
if (role === "channel.email" && containerPort === 8025) return "mail-ui";
|
|
458
|
+
if (role === "store.files" && containerPort === 9001) return "files-ui";
|
|
459
|
+
return `${roleLabel(role)}+${containerPort}`;
|
|
460
|
+
};
|
|
344
461
|
const appDrivers = [
|
|
345
462
|
...(stackRoles.includes("store.sql") ? [stackSqlDriver] : []),
|
|
346
463
|
...(stackRoles.includes("store.kv") ? [stackKvDriver] : []),
|
|
@@ -348,10 +465,13 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
348
465
|
write(
|
|
349
466
|
formatStackSummary({
|
|
350
467
|
project: `oke-${appSlug}`,
|
|
351
|
-
services: derived.specs.
|
|
352
|
-
label: roleLabel(spec.role),
|
|
353
|
-
|
|
354
|
-
|
|
468
|
+
services: derived.specs.flatMap((spec) => [
|
|
469
|
+
{ label: roleLabel(spec.role), hostPort: spec.hostPort },
|
|
470
|
+
...resolveExtraPorts(spec, { images, instanceId }).map((p) => ({
|
|
471
|
+
label: extraLabel(spec.role, p.containerPort),
|
|
472
|
+
hostPort: p.hostPort,
|
|
473
|
+
})),
|
|
474
|
+
]),
|
|
355
475
|
appDrivers,
|
|
356
476
|
}),
|
|
357
477
|
);
|
|
@@ -363,6 +483,7 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
363
483
|
appPort,
|
|
364
484
|
consolePort,
|
|
365
485
|
mcpPort,
|
|
486
|
+
docsMcpPort,
|
|
366
487
|
stackRoles,
|
|
367
488
|
composeFiles,
|
|
368
489
|
stackEnv,
|
|
@@ -370,9 +491,9 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
370
491
|
|
|
371
492
|
let okeVersion = "0.0.0";
|
|
372
493
|
try {
|
|
373
|
-
const pkg = (await Bun.file(
|
|
374
|
-
|
|
375
|
-
|
|
494
|
+
const pkg = (await Bun.file(resolve(import.meta.dir, "../../package.json")).json()) as {
|
|
495
|
+
version?: string;
|
|
496
|
+
};
|
|
376
497
|
if (typeof pkg.version === "string") okeVersion = pkg.version;
|
|
377
498
|
} catch {
|
|
378
499
|
// shipped binary may not sit next to package.json
|
|
@@ -380,9 +501,9 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
380
501
|
|
|
381
502
|
const heroSnapshot = buildDevHeroSnapshot({
|
|
382
503
|
config: loadedConfig,
|
|
383
|
-
|
|
384
|
-
sqlDriver:
|
|
385
|
-
kvDriver:
|
|
504
|
+
docker: mode === "docker",
|
|
505
|
+
sqlDriver: mode === "docker" ? stackSqlDriver : undefined,
|
|
506
|
+
kvDriver: mode === "docker" ? stackKvDriver : undefined,
|
|
386
507
|
version: okeVersion,
|
|
387
508
|
nodeEnv: "development",
|
|
388
509
|
});
|
|
@@ -399,6 +520,34 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
399
520
|
|
|
400
521
|
if (options.dryRun) return { code: 0, plan };
|
|
401
522
|
|
|
523
|
+
// One-shot schema sync for the session profile (both local and docker):
|
|
524
|
+
// emits schema.generated.ts for the active dialect, then pushes via
|
|
525
|
+
// drizzle-kit. Data planes stay isolated — session flags never rewrite
|
|
526
|
+
// `.oke/mode`. Watch auto-push below remains local-only.
|
|
527
|
+
if (!options.noDbPush) {
|
|
528
|
+
const { syncDevSchema } = await import("./dev-schema-sync.ts");
|
|
529
|
+
try {
|
|
530
|
+
const result = await syncDevSchema(cwd, mode, { write });
|
|
531
|
+
write(
|
|
532
|
+
formatStatusLine(
|
|
533
|
+
`oke db push (${mode} · ${result.dialect}) ${result.code === 0 ? "ok" : "failed"}`,
|
|
534
|
+
),
|
|
535
|
+
);
|
|
536
|
+
} catch (err) {
|
|
537
|
+
write(
|
|
538
|
+
formatStatusLine(
|
|
539
|
+
`oke db push (${mode}) skipped — ${err instanceof Error ? err.message : String(err)}`,
|
|
540
|
+
),
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const autoPushEnabled = resolveDevAutoPush({
|
|
546
|
+
noDbPush: options.noDbPush,
|
|
547
|
+
docker: Boolean(stackEnv),
|
|
548
|
+
configAutoPush: loadedConfig?.db?.autoPush,
|
|
549
|
+
});
|
|
550
|
+
|
|
402
551
|
const env: Record<string, string> = {
|
|
403
552
|
...(process.env as Record<string, string>),
|
|
404
553
|
NODE_ENV: "development",
|
|
@@ -408,10 +557,12 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
408
557
|
OKE_DEV_HERO_CONSOLE: `http://127.0.0.1:${consolePort}`,
|
|
409
558
|
OKE_DEV_HERO_MCP: `http://127.0.0.1:${mcpPort}`,
|
|
410
559
|
OKE_DEV_HERO_META: encodeHeroSnapshot(heroSnapshot),
|
|
560
|
+
// Propagate opt-out so the app disables ensureFromMeta when auto-push owns DDL.
|
|
561
|
+
...(autoPushEnabled ? { OKE_DB_AUTO_PUSH: "1" } : { OKE_DB_AUTO_PUSH: "0" }),
|
|
411
562
|
...(stackEnv ?? {}),
|
|
412
563
|
...(stackEnv
|
|
413
564
|
? {
|
|
414
|
-
|
|
565
|
+
OKE_DOCKER: "1",
|
|
415
566
|
OKE_SQL_DRIVER: stackSqlDriver,
|
|
416
567
|
OKE_KV_DRIVER: stackKvDriver,
|
|
417
568
|
}
|
|
@@ -419,18 +570,12 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
419
570
|
};
|
|
420
571
|
process.env.OKE_DEV_REQUEST_LOG = "1";
|
|
421
572
|
|
|
422
|
-
const startApp =
|
|
423
|
-
options.startApp ??
|
|
424
|
-
((entryPath, appEnv) => startAppHot(cwd, entryPath, appEnv));
|
|
573
|
+
const startApp = options.startApp ?? ((entryPath, appEnv) => startAppHot(cwd, entryPath, appEnv));
|
|
425
574
|
|
|
426
575
|
const seedManifest =
|
|
427
|
-
options.manifest !== undefined
|
|
428
|
-
? options.manifest
|
|
429
|
-
: await tryLoadProjectManifest(cwd);
|
|
576
|
+
options.manifest !== undefined ? options.manifest : await tryLoadProjectManifest(cwd);
|
|
430
577
|
|
|
431
|
-
async function refreshManifestInto(
|
|
432
|
-
state: ConsoleState | null,
|
|
433
|
-
): Promise<void> {
|
|
578
|
+
async function refreshManifestInto(state: ConsoleState | null): Promise<void> {
|
|
434
579
|
if (!state) return;
|
|
435
580
|
try {
|
|
436
581
|
const { extractManifest } = await import("../compiler/extract.ts");
|
|
@@ -445,9 +590,7 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
445
590
|
const serveConsole =
|
|
446
591
|
options.serveConsole ??
|
|
447
592
|
(async (port) => {
|
|
448
|
-
const { serveConsole: serveConsoleKernel } = await import(
|
|
449
|
-
"../console/server/serve.ts"
|
|
450
|
-
);
|
|
593
|
+
const { serveConsole: serveConsoleKernel } = await import("../console/server/serve.ts");
|
|
451
594
|
const server = await serveConsoleKernel({
|
|
452
595
|
port,
|
|
453
596
|
hostname: "127.0.0.1",
|
|
@@ -455,16 +598,9 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
455
598
|
env: "dev",
|
|
456
599
|
silentClaim: options.silentClaim ?? false,
|
|
457
600
|
...(options.secret !== undefined ? { secret: options.secret } : {}),
|
|
458
|
-
...(seedManifest !== undefined && seedManifest !== null
|
|
459
|
-
? { manifest: seedManifest }
|
|
460
|
-
: {}),
|
|
601
|
+
...(seedManifest !== undefined && seedManifest !== null ? { manifest: seedManifest } : {}),
|
|
461
602
|
});
|
|
462
|
-
write(
|
|
463
|
-
formatServiceLine(
|
|
464
|
-
"Console",
|
|
465
|
-
`http://127.0.0.1:${server.port}`,
|
|
466
|
-
),
|
|
467
|
-
);
|
|
603
|
+
write(formatServiceLine("Console", `http://127.0.0.1:${server.port}`));
|
|
468
604
|
return {
|
|
469
605
|
console: server.console,
|
|
470
606
|
port: server.port,
|
|
@@ -496,6 +632,24 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
496
632
|
};
|
|
497
633
|
});
|
|
498
634
|
|
|
635
|
+
const serveDocsMcpSurface =
|
|
636
|
+
options.serveDocsMcp ??
|
|
637
|
+
(async (docsOptions) => {
|
|
638
|
+
const { serveDocsMcp } = await import("../mcp/docs-server.ts");
|
|
639
|
+
const server = await serveDocsMcp({
|
|
640
|
+
port: docsOptions.port,
|
|
641
|
+
hostname: docsOptions.hostname ?? "127.0.0.1",
|
|
642
|
+
});
|
|
643
|
+
write(formatServiceLine("Docs MCP", `http://127.0.0.1:${server.port}`));
|
|
644
|
+
return {
|
|
645
|
+
port: server.port,
|
|
646
|
+
url: server.url,
|
|
647
|
+
stop() {
|
|
648
|
+
server.stop(true);
|
|
649
|
+
},
|
|
650
|
+
};
|
|
651
|
+
});
|
|
652
|
+
|
|
499
653
|
const regen =
|
|
500
654
|
options.regenClient ??
|
|
501
655
|
(async (appUrl) => {
|
|
@@ -535,34 +689,76 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
535
689
|
});
|
|
536
690
|
}
|
|
537
691
|
|
|
692
|
+
// Docs MCP is independent of Console state — read-only, no sessions/secret.
|
|
693
|
+
// Boot failure (missing docs content, busy port) skips it, never kills dev.
|
|
694
|
+
let docsMcpServer: DevMcpHandle | null = null;
|
|
695
|
+
try {
|
|
696
|
+
docsMcpServer = await serveDocsMcpSurface({ port: docsMcpPort, hostname: "127.0.0.1" });
|
|
697
|
+
} catch (err) {
|
|
698
|
+
write(
|
|
699
|
+
formatStatusLine(`Docs MCP skipped — ${err instanceof Error ? err.message : String(err)}`),
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
|
|
538
703
|
const boundMcpPort = mcpServer?.port ?? mcpPort;
|
|
539
704
|
const mcpUrl = mcpServer?.url ?? null;
|
|
705
|
+
const boundDocsMcpPort = docsMcpServer?.port ?? docsMcpPort;
|
|
706
|
+
const docsMcpUrl = docsMcpServer?.url ?? null;
|
|
540
707
|
|
|
541
|
-
const appUrl =
|
|
542
|
-
app.url?.origin ?? `http://127.0.0.1:${boundAppPort}`;
|
|
708
|
+
const appUrl = app.url?.origin ?? `http://127.0.0.1:${boundAppPort}`;
|
|
543
709
|
await regen(appUrl);
|
|
710
|
+
|
|
711
|
+
const dbPush =
|
|
712
|
+
options.dbPush ??
|
|
713
|
+
(async (projectCwd: string) => {
|
|
714
|
+
const configPath = await resolveDrizzleConfigPath(projectCwd);
|
|
715
|
+
return runPush(configPath, (t) => write(t), { cwd: projectCwd, env: mode });
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
let lastSchemaFilename = "";
|
|
719
|
+
const autoPushRunner = createDebouncedRunner(async () => {
|
|
720
|
+
if (!autoPushEnabled) return;
|
|
721
|
+
options.onDbAutoPush?.(lastSchemaFilename);
|
|
722
|
+
write(formatStatusLine("oke db push (schema change)"));
|
|
723
|
+
try {
|
|
724
|
+
await dbPush(cwd);
|
|
725
|
+
} catch {
|
|
726
|
+
// Mid-edit / kit unavailable — next save retries.
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
// Initial sync so local DB matches schema.ts without a prior manual push.
|
|
731
|
+
if (autoPushEnabled) {
|
|
732
|
+
lastSchemaFilename = "src/schema.ts";
|
|
733
|
+
autoPushRunner.trigger();
|
|
734
|
+
}
|
|
735
|
+
|
|
544
736
|
write(formatDevLogSeparator());
|
|
545
737
|
|
|
546
|
-
const
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
()
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
738
|
+
const watchFs: DevWatchFn =
|
|
739
|
+
options.watchFs ?? ((path, watchOptions, listener) => watch(path, watchOptions, listener));
|
|
740
|
+
const watcher = watchFs(resolve(cwd, "src"), { recursive: true }, (_event, filename) => {
|
|
741
|
+
void regen(appUrl);
|
|
742
|
+
// Only live-extract when the host did not pin a Manifest (tests).
|
|
743
|
+
if (options.manifest === undefined) {
|
|
744
|
+
void refreshManifestInto(consoleState);
|
|
745
|
+
}
|
|
746
|
+
if (autoPushEnabled && isDomainSchemaWatchPath(filename?.toString())) {
|
|
747
|
+
lastSchemaFilename = filename?.toString() ?? "schema.ts";
|
|
748
|
+
autoPushRunner.trigger();
|
|
749
|
+
}
|
|
750
|
+
});
|
|
557
751
|
|
|
558
752
|
let stopped = false;
|
|
559
753
|
const stop = () => {
|
|
560
754
|
if (stopped) return;
|
|
561
755
|
stopped = true;
|
|
756
|
+
autoPushRunner.cancel();
|
|
562
757
|
watcher.close();
|
|
563
758
|
app.stop();
|
|
564
759
|
consoleServer.stop();
|
|
565
760
|
mcpServer?.stop();
|
|
761
|
+
docsMcpServer?.stop();
|
|
566
762
|
process.off("SIGINT", onSignal);
|
|
567
763
|
process.off("SIGTERM", onSignal);
|
|
568
764
|
};
|
|
@@ -580,12 +776,15 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
580
776
|
appPort: boundAppPort,
|
|
581
777
|
consolePort: boundConsolePort,
|
|
582
778
|
mcpPort: boundMcpPort,
|
|
779
|
+
docsMcpPort: boundDocsMcpPort,
|
|
583
780
|
},
|
|
584
781
|
stop,
|
|
585
782
|
appPort: boundAppPort,
|
|
586
783
|
consolePort: boundConsolePort,
|
|
587
784
|
mcpPort: boundMcpPort,
|
|
588
785
|
mcpUrl,
|
|
786
|
+
docsMcpPort: boundDocsMcpPort,
|
|
787
|
+
docsMcpUrl,
|
|
589
788
|
secret,
|
|
590
789
|
sessions,
|
|
591
790
|
consoleState,
|
|
@@ -602,6 +801,21 @@ export async function runDev(options: DevOptions = {}): Promise<DevResult> {
|
|
|
602
801
|
return { code: 0, plan: session.plan, session };
|
|
603
802
|
}
|
|
604
803
|
|
|
804
|
+
/**
|
|
805
|
+
* Declared vault secret names from the project Manifest (policy scope).
|
|
806
|
+
*
|
|
807
|
+
* @param cwd - Project root
|
|
808
|
+
*/
|
|
809
|
+
async function tryLoadVaultSecretNames(cwd: string): Promise<readonly string[]> {
|
|
810
|
+
try {
|
|
811
|
+
const { extractManifest } = await import("../compiler/extract.ts");
|
|
812
|
+
const manifest = await extractManifest({ rootDir: cwd });
|
|
813
|
+
return Object.keys(manifest.vault ?? {});
|
|
814
|
+
} catch {
|
|
815
|
+
return [];
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
605
819
|
/**
|
|
606
820
|
* True when a Manifest has no declared flows (scaffold / empty extract).
|
|
607
821
|
*
|
|
@@ -619,9 +833,7 @@ function isSparseManifest(manifest: Manifest): boolean {
|
|
|
619
833
|
*
|
|
620
834
|
* @param cwd - Project root
|
|
621
835
|
*/
|
|
622
|
-
async function tryLoadProjectManifest(
|
|
623
|
-
cwd: string,
|
|
624
|
-
): Promise<Manifest | null | undefined> {
|
|
836
|
+
async function tryLoadProjectManifest(cwd: string): Promise<Manifest | null | undefined> {
|
|
625
837
|
let extracted: Manifest | undefined;
|
|
626
838
|
try {
|
|
627
839
|
const { extractManifest } = await import("../compiler/extract.ts");
|
|
@@ -658,10 +870,7 @@ async function startAppHot(
|
|
|
658
870
|
): Promise<DevAppHandle> {
|
|
659
871
|
const absoluteEntry = resolve(cwd, entryPath);
|
|
660
872
|
const runner = resolve(import.meta.dir, "dev-app-runner.ts");
|
|
661
|
-
const readyPath = join(
|
|
662
|
-
tmpdir(),
|
|
663
|
-
`oke-dev-ready-${crypto.randomUUID()}.txt`,
|
|
664
|
-
);
|
|
873
|
+
const readyPath = join(tmpdir(), `oke-dev-ready-${crypto.randomUUID()}.txt`);
|
|
665
874
|
const hostname = "127.0.0.1";
|
|
666
875
|
const env: Record<string, string> = {
|
|
667
876
|
...appEnv,
|
|
@@ -696,11 +905,7 @@ async function startAppHot(
|
|
|
696
905
|
};
|
|
697
906
|
|
|
698
907
|
try {
|
|
699
|
-
const boundPort = await waitForAppReady(
|
|
700
|
-
readyPath,
|
|
701
|
-
proc,
|
|
702
|
-
APP_READY_TIMEOUT_MS,
|
|
703
|
-
);
|
|
908
|
+
const boundPort = await waitForAppReady(readyPath, proc, APP_READY_TIMEOUT_MS);
|
|
704
909
|
// Child prints the App ready line (again on each soft reload).
|
|
705
910
|
const url = new URL(`http://${hostname}:${boundPort}/`);
|
|
706
911
|
return { stop, port: boundPort, url };
|
|
@@ -726,9 +931,7 @@ async function waitForAppReady(
|
|
|
726
931
|
while (Date.now() - started < timeoutMs) {
|
|
727
932
|
const exitCode = proc.exitCode;
|
|
728
933
|
if (exitCode !== null) {
|
|
729
|
-
throw new Error(
|
|
730
|
-
`oke dev: app process exited before ready (code ${exitCode})`,
|
|
731
|
-
);
|
|
934
|
+
throw new Error(`oke dev: app process exited before ready (code ${exitCode})`);
|
|
732
935
|
}
|
|
733
936
|
if (await Bun.file(readyPath).exists()) {
|
|
734
937
|
const text = (await Bun.file(readyPath).text()).trim();
|
|
@@ -740,44 +943,57 @@ async function waitForAppReady(
|
|
|
740
943
|
}
|
|
741
944
|
await Bun.sleep(25);
|
|
742
945
|
}
|
|
743
|
-
throw new Error(
|
|
744
|
-
`oke dev: app did not become ready within ${timeoutMs}ms`,
|
|
745
|
-
);
|
|
946
|
+
throw new Error(`oke dev: app did not become ready within ${timeoutMs}ms`);
|
|
746
947
|
}
|
|
747
948
|
|
|
748
949
|
/**
|
|
749
|
-
* CLI entry for `oke dev [--
|
|
950
|
+
* CLI entry for `oke dev [--local|-l] [--docker|-d [roles]]`.
|
|
750
951
|
*
|
|
751
952
|
* @param args - Args after `dev`
|
|
752
953
|
*/
|
|
753
954
|
export async function devCli(args: readonly string[]): Promise<number> {
|
|
754
|
-
let
|
|
955
|
+
let docker: boolean | string[] | undefined;
|
|
956
|
+
let local = false;
|
|
957
|
+
let noDbPush = false;
|
|
755
958
|
let entry: string | undefined;
|
|
756
959
|
for (let i = 0; i < args.length; i++) {
|
|
757
960
|
const a = args[i]!;
|
|
758
|
-
if (a === "--
|
|
961
|
+
if (a === "--local" || a === "-l") {
|
|
962
|
+
local = true;
|
|
963
|
+
} else if (a === "--docker" || a === "-d") {
|
|
759
964
|
const next = args[i + 1];
|
|
760
965
|
if (next && !next.startsWith("-") && /^[\w.,]+$/.test(next)) {
|
|
761
|
-
|
|
966
|
+
docker = next
|
|
967
|
+
.split(",")
|
|
968
|
+
.map((s) => s.trim())
|
|
969
|
+
.filter(Boolean);
|
|
762
970
|
i++;
|
|
763
971
|
} else {
|
|
764
|
-
|
|
972
|
+
docker = true;
|
|
765
973
|
}
|
|
974
|
+
} else if (a === "--no-db-push") {
|
|
975
|
+
noDbPush = true;
|
|
766
976
|
} else if (a === "--entry" || a === "-e") entry = args[++i];
|
|
767
977
|
else if (a === "--help" || a === "-h") {
|
|
768
|
-
console.log(`oke dev [--
|
|
978
|
+
console.log(`oke dev [--local|-l] [--docker|-d [roles]] [--no-db-push] [--entry|-e src/app.ts]
|
|
769
979
|
|
|
770
980
|
Watch · hot reload · Console :6533 · app :6530 · MCP :6535
|
|
771
981
|
Regenerates client types on every save.
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
982
|
+
Local mode auto-runs \`oke db push\` when schema.ts changes (opt out: --no-db-push).
|
|
983
|
+
|
|
984
|
+
Bare \`oke dev\` uses .oke/mode (one-time prompt on a TTY; non-TTY → local).
|
|
985
|
+
--local / --docker override for this session only (never write .oke/mode).
|
|
986
|
+
--docker boots infra under docker/ and runs the app on host Bun with prod
|
|
987
|
+
store drivers (Postgres/Redis). Partial roles: -d store.sql,store.kv.
|
|
988
|
+
Change the saved default with \`oke mode local|docker\`.
|
|
775
989
|
`);
|
|
776
990
|
return 0;
|
|
777
991
|
}
|
|
778
992
|
}
|
|
779
993
|
const { code } = await runDev({
|
|
780
|
-
|
|
994
|
+
...(local ? { local: true } : {}),
|
|
995
|
+
...(docker === undefined ? {} : { docker }),
|
|
996
|
+
...(noDbPush ? { noDbPush: true } : {}),
|
|
781
997
|
entry,
|
|
782
998
|
});
|
|
783
999
|
return code;
|