okengine 0.2.6 → 0.2.8
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 +24 -23
- package/README.md +52 -346
- package/docs/spec/console.md +165 -142
- package/docs/spec/example.md +490 -312
- package/docs/spec/four-applications.md +495 -314
- package/docs/spec/unified-theory.md +184 -175
- package/package.json +45 -37
- package/spec/manifest.v1.schema.json +40 -9
- package/src/auth/api-keys.ts +2 -5
- package/src/auth/attenuation.ts +2 -6
- package/src/auth/auth.test.ts +53 -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 +386 -0
- package/src/cli/dev-app-runner.ts +2 -8
- package/src/cli/dev-db-push.test.ts +163 -0
- package/src/cli/dev-mode.test.ts +45 -0
- package/src/cli/dev-mode.ts +78 -0
- package/src/cli/dev.test.ts +148 -21
- package/src/cli/dev.ts +208 -134
- package/src/cli/doc-drift.test.ts +3 -2
- package/src/cli/doc-drift.ts +21 -50
- package/src/cli/doc-staleness.test.ts +69 -0
- package/src/cli/docker-cli.test.ts +7 -8
- package/src/cli/docker.ts +1 -3
- package/src/cli/doctor-diff-examples.ts +1 -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/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 +41 -47
- package/src/cli/mcp-from-console.ts +1 -4
- package/src/cli/mode.ts +45 -0
- package/src/cli/ports.test.ts +4 -13
- package/src/cli/ports.ts +1 -3
- package/src/cli/privacy-erase.ts +1 -3
- package/src/cli/registry.ts +75 -25
- package/src/cli/schema.ts +3 -10
- package/src/cli/stack.ts +2 -7
- package/src/cli/start.ts +4 -15
- package/src/cli/upgrade.ts +1 -4
- 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 +8 -29
- 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 +96 -30
- package/src/compiler/extract.ts +362 -156
- package/src/compiler/fixtures/skyport/oke.config.ts +1 -1
- 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 +4 -7
- package/src/compiler/sucrose.ts +11 -31
- package/src/config/define-config.test.ts +57 -34
- package/src/config/index.ts +181 -37
- 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 +14 -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 +23 -60
- 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 +112 -20
- package/src/docker/derive.ts +5 -19
- package/src/docker/docker.test.ts +15 -15
- package/src/docker/dockerfile.integration.test.ts +12 -21
- package/src/docker/helpers.ts +5 -4
- package/src/docker/index.ts +4 -11
- package/src/docker/pin.ts +1 -9
- package/src/docker/recipes/index.ts +5 -6
- package/src/docker/recipes/mailpit.ts +22 -0
- package/src/docker/recipes/postgres.ts +17 -6
- package/src/docker/recipes/redis.ts +6 -1
- package/src/docker/recipes/rustfs.ts +33 -0
- package/src/docker/stack-id.test.ts +33 -0
- package/src/docker/stack-id.ts +25 -13
- package/src/docker/stack.integration.test.ts +6 -21
- package/src/docker/types.ts +13 -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/fs.ts +2 -8
- package/src/drivers/index.ts +12 -56
- package/src/drivers/memory.ts +14 -41
- 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 +5 -17
- 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-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.ts +1 -5
- package/src/drivers/vault-sops.ts +10 -35
- package/src/drivers/vault-types.ts +1 -7
- 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 +8 -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/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.ts +11 -21
- package/src/elements/store/sql-session.test.ts +50 -0
- package/src/elements/store/sql-session.ts +60 -63
- package/src/elements/store/table.ts +35 -19
- package/src/elements/store.test.ts +17 -39
- package/src/elements/store.ts +37 -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 +18 -32
- package/src/elements/vault.test.ts +12 -28
- package/src/elements/vault.ts +8 -12
- package/src/index.ts +5 -2
- package/src/kernel/adopt-routes.ts +15 -29
- package/src/kernel/app.ts +34 -94
- package/src/kernel/auth-resolve.ts +2 -9
- package/src/kernel/boot-bind/ai.ts +1 -4
- package/src/kernel/boot-bind/channel.ts +2 -8
- 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 +17 -17
- package/src/kernel/boot-bind/store.ts +44 -50
- package/src/kernel/boot-bind/vault.ts +2 -8
- package/src/kernel/boot.test.ts +4 -9
- package/src/kernel/boot.ts +29 -76
- 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/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 +5 -25
- package/src/kernel/fx.test.ts +15 -44
- package/src/kernel/fx.ts +27 -79
- package/src/kernel/hook-timing.test.ts +3 -6
- package/src/kernel/hook-timing.ts +5 -14
- package/src/kernel/hooks.test.ts +10 -10
- package/src/kernel/hooks.ts +3 -12
- package/src/kernel/index.ts +4 -17
- package/src/kernel/journal.ts +7 -31
- package/src/kernel/on.ts +1 -6
- 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 +48 -24
- package/src/kernel/registry.ts +80 -29
- 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 +4 -21
- package/src/manifest/diff.test.ts +26 -91
- package/src/manifest/diff.ts +95 -225
- package/src/manifest/index.ts +2 -9
- package/src/manifest/types.ts +29 -5
- 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 +4 -14
- 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/node-import-scan.ts +2 -5
- 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 +15 -43
- 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 +13 -31
- 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/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
package/src/cli/db.ts
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `oke db push|generate|migrate` — domain schema sync via drizzle-kit.
|
|
3
|
+
*
|
|
4
|
+
* Distinct from `oke schema generate` (core/plugin stub tables).
|
|
5
|
+
* When abstract decls exist (`src/schema.decl.ts`), emits Drizzle first —
|
|
6
|
+
* not a third schema CLI.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { resolve } from "node:path";
|
|
10
|
+
import {
|
|
11
|
+
dialectFromDriverId,
|
|
12
|
+
maybeEmitDomainSchema,
|
|
13
|
+
type SqlDialect,
|
|
14
|
+
} from "../elements/store/emit-drizzle.ts";
|
|
15
|
+
import { loadPluginTablesFromAppEntry } from "../elements/store/load-plugin-tables.ts";
|
|
16
|
+
import { resolveDriverId, type ConfigEnv, type OkeConfig } from "../config/index.ts";
|
|
17
|
+
import type { TableContribution } from "../kernel/plugin.ts";
|
|
18
|
+
import { EXIT_OK, EXIT_RUNTIME, EXIT_USAGE } from "./exit.ts";
|
|
19
|
+
import { loadOkeConfig } from "./load-config.ts";
|
|
20
|
+
|
|
21
|
+
/** Subcommands under `oke db`. */
|
|
22
|
+
export type DbSubcommand = "push" | "generate" | "migrate";
|
|
23
|
+
|
|
24
|
+
/** Options for {@link runDb}. */
|
|
25
|
+
export interface DbOptions {
|
|
26
|
+
readonly cwd?: string;
|
|
27
|
+
/** Path to drizzle.config.ts (overrides `db.config`). */
|
|
28
|
+
readonly config?: string;
|
|
29
|
+
readonly write?: (text: string) => void;
|
|
30
|
+
/** Injectable push (tests). */
|
|
31
|
+
readonly pushFn?: (opts: { config: string }) => Promise<DbKitResult>;
|
|
32
|
+
/** Injectable generate (tests). */
|
|
33
|
+
readonly generateFn?: (opts: {
|
|
34
|
+
config: string;
|
|
35
|
+
}) => Promise<DbKitResult & { readonly migration_path?: string }>;
|
|
36
|
+
/** Injectable migrate (tests). */
|
|
37
|
+
readonly migrateFn?: (opts: { config: string; cwd: string }) => Promise<number>;
|
|
38
|
+
/**
|
|
39
|
+
* Dry-run push via drizzle-kit `explain` — used by doctor drift checks.
|
|
40
|
+
*/
|
|
41
|
+
readonly explain?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Skip abstract-schema emit pre-step (tests / explain-only).
|
|
44
|
+
*/
|
|
45
|
+
readonly skipEmit?: boolean;
|
|
46
|
+
/** Active config env for dialect resolution (default `local`). */
|
|
47
|
+
readonly env?: ConfigEnv;
|
|
48
|
+
/**
|
|
49
|
+
* Injectable plugin tables for emit (tests). When omitted, loads the live
|
|
50
|
+
* app entry and reads `app.plugins.tableContributions()`.
|
|
51
|
+
*/
|
|
52
|
+
readonly pluginTables?: readonly TableContribution[];
|
|
53
|
+
/** Override app entry path for plugin-table discovery. */
|
|
54
|
+
readonly entry?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Minimal drizzle-kit envelope we handle. */
|
|
58
|
+
export interface DbKitResult {
|
|
59
|
+
readonly status: "ok" | "no_changes" | "missing_hints" | "error" | string;
|
|
60
|
+
readonly error?: { readonly code?: string; readonly message?: string };
|
|
61
|
+
readonly unresolved?: readonly unknown[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the drizzle config path for a project.
|
|
66
|
+
*
|
|
67
|
+
* @param cwd - Project root
|
|
68
|
+
* @param options - CLI / config overrides
|
|
69
|
+
*/
|
|
70
|
+
export async function resolveDrizzleConfigPath(
|
|
71
|
+
cwd: string,
|
|
72
|
+
options: {
|
|
73
|
+
readonly config?: string;
|
|
74
|
+
readonly loadedConfig?: OkeConfig | null;
|
|
75
|
+
} = {},
|
|
76
|
+
): Promise<string> {
|
|
77
|
+
if (options.config) return resolve(cwd, options.config);
|
|
78
|
+
const loaded = options.loadedConfig ?? (await loadOkeConfig(cwd).catch(() => null))?.config;
|
|
79
|
+
const fromConfig = loaded?.db?.config;
|
|
80
|
+
return resolve(cwd, fromConfig ?? "drizzle.config.ts");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Run `oke db <subcommand>`.
|
|
85
|
+
*
|
|
86
|
+
* @param sub - push | generate | migrate
|
|
87
|
+
* @param options - Paths / injectables
|
|
88
|
+
*/
|
|
89
|
+
export async function runDb(sub: DbSubcommand, options: DbOptions = {}): Promise<number> {
|
|
90
|
+
const write = options.write ?? ((t) => process.stdout.write(t));
|
|
91
|
+
const cwd = options.cwd ?? process.cwd();
|
|
92
|
+
const loaded = await loadOkeConfig(cwd).catch(() => null);
|
|
93
|
+
if (!options.skipEmit) {
|
|
94
|
+
await emitAbstractSchemaPrestep(cwd, loaded?.config, write, options.env ?? "local", {
|
|
95
|
+
pluginTables: options.pluginTables,
|
|
96
|
+
entry: options.entry,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const configPath = await resolveDrizzleConfigPath(cwd, {
|
|
100
|
+
config: options.config,
|
|
101
|
+
loadedConfig: loaded?.config,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (sub === "push") {
|
|
105
|
+
return runPush(configPath, write, { ...options, skipEmit: true });
|
|
106
|
+
}
|
|
107
|
+
if (sub === "generate") {
|
|
108
|
+
return runGenerate(configPath, write, { ...options, skipEmit: true });
|
|
109
|
+
}
|
|
110
|
+
if (sub === "migrate") {
|
|
111
|
+
return runMigrate(configPath, cwd, write, { ...options, skipEmit: true });
|
|
112
|
+
}
|
|
113
|
+
write(`oke db: unknown subcommand\n`);
|
|
114
|
+
return EXIT_USAGE;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Emit `schema.generated.ts` from abstract decls + live plugged plugin tables.
|
|
119
|
+
*
|
|
120
|
+
* @param cwd - Project root
|
|
121
|
+
* @param config - Loaded oke config
|
|
122
|
+
* @param write - Output
|
|
123
|
+
* @param env - Active env for dialect
|
|
124
|
+
* @param options - Injectables / entry override
|
|
125
|
+
*/
|
|
126
|
+
export async function emitAbstractSchemaPrestep(
|
|
127
|
+
cwd: string,
|
|
128
|
+
config: OkeConfig | null | undefined,
|
|
129
|
+
write: (text: string) => void = () => {},
|
|
130
|
+
env: ConfigEnv = "local",
|
|
131
|
+
options: {
|
|
132
|
+
readonly pluginTables?: readonly TableContribution[];
|
|
133
|
+
readonly entry?: string;
|
|
134
|
+
} = {},
|
|
135
|
+
): Promise<boolean> {
|
|
136
|
+
const driverId = resolveDriverId(config?.drivers?.store?.sql, env);
|
|
137
|
+
const dialect: SqlDialect = dialectFromDriverId(driverId);
|
|
138
|
+
const pluginTables =
|
|
139
|
+
options.pluginTables ??
|
|
140
|
+
(await loadPluginTablesFromAppEntry(cwd, {
|
|
141
|
+
entry: options.entry ?? config?.db?.entry,
|
|
142
|
+
write,
|
|
143
|
+
}));
|
|
144
|
+
const result = await maybeEmitDomainSchema({
|
|
145
|
+
cwd,
|
|
146
|
+
dialect,
|
|
147
|
+
declarePath: config?.db?.declare,
|
|
148
|
+
outPath: config?.db?.generated,
|
|
149
|
+
pluginTables,
|
|
150
|
+
write,
|
|
151
|
+
});
|
|
152
|
+
return result.emitted;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Push domain schema to the live database (dev).
|
|
157
|
+
*
|
|
158
|
+
* @param configPath - Absolute drizzle.config.ts
|
|
159
|
+
* @param write - Output
|
|
160
|
+
* @param options - Injectables / explain
|
|
161
|
+
*/
|
|
162
|
+
export async function runPush(
|
|
163
|
+
configPath: string,
|
|
164
|
+
write: (text: string) => void = (t) => process.stdout.write(t),
|
|
165
|
+
options: DbOptions = {},
|
|
166
|
+
): Promise<number> {
|
|
167
|
+
const cwd = options.cwd ?? process.cwd();
|
|
168
|
+
if (!options.skipEmit) {
|
|
169
|
+
const loaded = await loadOkeConfig(cwd).catch(() => null);
|
|
170
|
+
await emitAbstractSchemaPrestep(cwd, loaded?.config, write, options.env ?? "local", {
|
|
171
|
+
pluginTables: options.pluginTables,
|
|
172
|
+
entry: options.entry,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const pushFn =
|
|
177
|
+
options.pushFn ??
|
|
178
|
+
(async (opts: { config: string }) => {
|
|
179
|
+
const { push } = await import("drizzle-kit/cli");
|
|
180
|
+
return (await push({
|
|
181
|
+
config: opts.config,
|
|
182
|
+
...(options.explain ? { explain: true } : {}),
|
|
183
|
+
})) as DbKitResult;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
let result: DbKitResult;
|
|
187
|
+
try {
|
|
188
|
+
result = await pushFn({ config: configPath });
|
|
189
|
+
} catch (err) {
|
|
190
|
+
write(`oke db push: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
191
|
+
write(" → install drizzle-kit and ensure drizzle.config.ts exists\n");
|
|
192
|
+
return EXIT_RUNTIME;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return reportKitResult("push", result, write);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Generate versioned migration SQL under `out` (prod artefact folder).
|
|
200
|
+
*
|
|
201
|
+
* @param configPath - Absolute drizzle.config.ts
|
|
202
|
+
* @param write - Output
|
|
203
|
+
* @param options - Injectables
|
|
204
|
+
*/
|
|
205
|
+
export async function runGenerate(
|
|
206
|
+
configPath: string,
|
|
207
|
+
write: (text: string) => void = (t) => process.stdout.write(t),
|
|
208
|
+
options: DbOptions = {},
|
|
209
|
+
): Promise<number> {
|
|
210
|
+
const cwd = options.cwd ?? process.cwd();
|
|
211
|
+
if (!options.skipEmit) {
|
|
212
|
+
const loaded = await loadOkeConfig(cwd).catch(() => null);
|
|
213
|
+
await emitAbstractSchemaPrestep(cwd, loaded?.config, write, options.env ?? "local", {
|
|
214
|
+
pluginTables: options.pluginTables,
|
|
215
|
+
entry: options.entry,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const generateFn =
|
|
220
|
+
options.generateFn ??
|
|
221
|
+
(async (opts: { config: string }) => {
|
|
222
|
+
const { generate } = await import("drizzle-kit/cli");
|
|
223
|
+
return (await generate({ config: opts.config })) as DbKitResult & {
|
|
224
|
+
readonly migration_path?: string;
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
let result: DbKitResult & { readonly migration_path?: string };
|
|
229
|
+
try {
|
|
230
|
+
result = await generateFn({ config: configPath });
|
|
231
|
+
} catch (err) {
|
|
232
|
+
write(`oke db generate: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
233
|
+
write(" → install drizzle-kit and ensure drizzle.config.ts exists\n");
|
|
234
|
+
return EXIT_RUNTIME;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (result.status === "ok" && result.migration_path) {
|
|
238
|
+
write(`oke db generate: wrote ${result.migration_path}\n`);
|
|
239
|
+
return EXIT_OK;
|
|
240
|
+
}
|
|
241
|
+
return reportKitResult("generate", result, write);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Apply versioned migrations (`drizzle-kit migrate`).
|
|
246
|
+
*
|
|
247
|
+
* @param configPath - Absolute drizzle.config.ts
|
|
248
|
+
* @param cwd - Project root
|
|
249
|
+
* @param write - Output
|
|
250
|
+
* @param options - Injectables
|
|
251
|
+
*/
|
|
252
|
+
export async function runMigrate(
|
|
253
|
+
configPath: string,
|
|
254
|
+
cwd: string,
|
|
255
|
+
write: (text: string) => void = (t) => process.stdout.write(t),
|
|
256
|
+
options: DbOptions = {},
|
|
257
|
+
): Promise<number> {
|
|
258
|
+
if (!options.skipEmit) {
|
|
259
|
+
const loaded = await loadOkeConfig(cwd).catch(() => null);
|
|
260
|
+
await emitAbstractSchemaPrestep(cwd, loaded?.config, write, options.env ?? "local", {
|
|
261
|
+
pluginTables: options.pluginTables,
|
|
262
|
+
entry: options.entry,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const migrateFn =
|
|
267
|
+
options.migrateFn ??
|
|
268
|
+
(async (opts: { config: string; cwd: string }) => {
|
|
269
|
+
const proc = Bun.spawn(["bunx", "drizzle-kit", "migrate", "--config", opts.config], {
|
|
270
|
+
cwd: opts.cwd,
|
|
271
|
+
stdout: "inherit",
|
|
272
|
+
stderr: "inherit",
|
|
273
|
+
env: process.env as Record<string, string>,
|
|
274
|
+
});
|
|
275
|
+
return await proc.exited;
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
const code = await migrateFn({ config: configPath, cwd });
|
|
280
|
+
if (code === 0) {
|
|
281
|
+
write("oke db migrate: applied\n");
|
|
282
|
+
return EXIT_OK;
|
|
283
|
+
}
|
|
284
|
+
write(`oke db migrate: exited ${code}\n`);
|
|
285
|
+
return EXIT_RUNTIME;
|
|
286
|
+
} catch (err) {
|
|
287
|
+
write(`oke db migrate: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
288
|
+
return EXIT_RUNTIME;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Whether domain schema differs from the live DB (drizzle-kit push explain).
|
|
294
|
+
*
|
|
295
|
+
* @param options - Paths / injectables
|
|
296
|
+
*/
|
|
297
|
+
export async function detectDbDrift(options: DbOptions = {}): Promise<{
|
|
298
|
+
readonly drifted: boolean;
|
|
299
|
+
readonly detail?: string;
|
|
300
|
+
}> {
|
|
301
|
+
const cwd = options.cwd ?? process.cwd();
|
|
302
|
+
const configPath = await resolveDrizzleConfigPath(cwd, { config: options.config });
|
|
303
|
+
const pushFn =
|
|
304
|
+
options.pushFn ??
|
|
305
|
+
(async (opts: { config: string }) => {
|
|
306
|
+
const { push } = await import("drizzle-kit/cli");
|
|
307
|
+
return (await push({ config: opts.config, explain: true })) as DbKitResult;
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
const result = await pushFn({ config: configPath });
|
|
312
|
+
if (result.status === "no_changes") return { drifted: false };
|
|
313
|
+
if (result.status === "ok" || result.status === "missing_hints") {
|
|
314
|
+
return { drifted: true, detail: `drizzle-kit push explain: ${result.status}` };
|
|
315
|
+
}
|
|
316
|
+
if (result.status === "error") {
|
|
317
|
+
return {
|
|
318
|
+
drifted: false,
|
|
319
|
+
detail: result.error?.message ?? "drizzle-kit push explain failed",
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return { drifted: false };
|
|
323
|
+
} catch (err) {
|
|
324
|
+
return {
|
|
325
|
+
drifted: false,
|
|
326
|
+
detail: err instanceof Error ? err.message : String(err),
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* CLI entry: parse `oke db <push|generate|migrate> [--config path]`.
|
|
333
|
+
*
|
|
334
|
+
* @param args - Args after `db`
|
|
335
|
+
*/
|
|
336
|
+
export async function dbCli(args: readonly string[]): Promise<number> {
|
|
337
|
+
const sub = args[0];
|
|
338
|
+
if (!sub || sub === "--help" || sub === "-h") {
|
|
339
|
+
console.log(`oke db push|generate|migrate [--config|-c drizzle.config.ts]
|
|
340
|
+
|
|
341
|
+
Domain schema sync via drizzle-kit.
|
|
342
|
+
When src/schema.decl.ts and/or a plugged app entry exists, emits
|
|
343
|
+
schema.generated.ts from store.schema.table + live plugin .table()
|
|
344
|
+
contributions — then runs drizzle-kit.
|
|
345
|
+
Hand-written src/schema.ts remains supported (emit skipped if nothing to emit).
|
|
346
|
+
Not the same as \`oke schema generate\` (core/plugin stub tables).
|
|
347
|
+
|
|
348
|
+
push Apply schema to the live local DB (dev; no migration files)
|
|
349
|
+
generate Write versioned SQL under drizzle/ for review
|
|
350
|
+
migrate Apply generated migrations (explicit; never automatic in prod)
|
|
351
|
+
`);
|
|
352
|
+
return sub ? EXIT_OK : EXIT_USAGE;
|
|
353
|
+
}
|
|
354
|
+
if (sub !== "push" && sub !== "generate" && sub !== "migrate") {
|
|
355
|
+
console.error(`oke db: unknown subcommand "${sub}"`);
|
|
356
|
+
return EXIT_USAGE;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
let config: string | undefined;
|
|
360
|
+
for (let i = 1; i < args.length; i++) {
|
|
361
|
+
const a = args[i]!;
|
|
362
|
+
if (a === "--config" || a === "-c") config = args[++i];
|
|
363
|
+
else if (a === "--help" || a === "-h") {
|
|
364
|
+
return dbCli(["--help"]);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return runDb(sub, { config });
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function reportKitResult(verb: string, result: DbKitResult, write: (text: string) => void): number {
|
|
372
|
+
if (result.status === "ok" || result.status === "no_changes") {
|
|
373
|
+
write(`oke db ${verb}: ${result.status}\n`);
|
|
374
|
+
return EXIT_OK;
|
|
375
|
+
}
|
|
376
|
+
if (result.status === "missing_hints") {
|
|
377
|
+
write(
|
|
378
|
+
`oke db ${verb}: missing_hints — resolve destructive changes manually (not auto-applied)\n`,
|
|
379
|
+
);
|
|
380
|
+
return EXIT_RUNTIME;
|
|
381
|
+
}
|
|
382
|
+
write(
|
|
383
|
+
`oke db ${verb}: ${result.status}${result.error?.message ? ` — ${result.error.message}` : ""}\n`,
|
|
384
|
+
);
|
|
385
|
+
return EXIT_RUNTIME;
|
|
386
|
+
}
|
|
@@ -19,11 +19,7 @@ import { resolve } from "node:path";
|
|
|
19
19
|
import { pathToFileURL } from "node:url";
|
|
20
20
|
import { createBunRuntime } from "../runtime/bun.ts";
|
|
21
21
|
import { APP_PORT, type FetchApp } from "../runtime/types.ts";
|
|
22
|
-
import {
|
|
23
|
-
clearTerminalScreen,
|
|
24
|
-
formatAppReadyLine,
|
|
25
|
-
formatDevHero,
|
|
26
|
-
} from "../term.ts";
|
|
22
|
+
import { clearTerminalScreen, formatAppReadyLine, formatDevHero } from "../term.ts";
|
|
27
23
|
import { decodeHeroSnapshot } from "./hero-meta.ts";
|
|
28
24
|
|
|
29
25
|
/** Stable Bun.serve id so `--hot` reuses the socket across soft reloads. */
|
|
@@ -62,9 +58,7 @@ if (
|
|
|
62
58
|
typeof mod.app.boot !== "function" ||
|
|
63
59
|
typeof mod.app.fetch !== "function"
|
|
64
60
|
) {
|
|
65
|
-
console.error(
|
|
66
|
-
`oke dev: ${absoluteEntry} must export app with boot() and fetch()`,
|
|
67
|
-
);
|
|
61
|
+
console.error(`oke dev: ${absoluteEntry} must export app with boot() and fetch()`);
|
|
68
62
|
process.exit(1);
|
|
69
63
|
}
|
|
70
64
|
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `oke dev` auto `oke db push` on schema change + opt-out.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
6
|
+
import { mkdir, mkdtemp, writeFile } from "node:fs/promises";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { runDev, type DevSession } from "./dev.ts";
|
|
10
|
+
|
|
11
|
+
const sessions: DevSession[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
for (const s of sessions.splice(0)) s.stop();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function scaffoldProject(): Promise<string> {
|
|
18
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-dev-db-"));
|
|
19
|
+
await mkdir(join(dir, "src"), { recursive: true });
|
|
20
|
+
const configMod = join(import.meta.dir, "../config/index.ts");
|
|
21
|
+
await writeFile(
|
|
22
|
+
join(dir, "oke.config.ts"),
|
|
23
|
+
`import { defineConfig } from ${JSON.stringify(configMod)};
|
|
24
|
+
export default defineConfig({
|
|
25
|
+
drivers: { store: { sql: { local: "sqlite", test: "memory", prod: "postgres" } } },
|
|
26
|
+
});
|
|
27
|
+
`,
|
|
28
|
+
);
|
|
29
|
+
await writeFile(join(dir, "src", "app.ts"), `export {};\n`);
|
|
30
|
+
await writeFile(
|
|
31
|
+
join(dir, "src", "schema.ts"),
|
|
32
|
+
`import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
33
|
+
export const entries = sqliteTable("entries", { id: text("id").primaryKey() });
|
|
34
|
+
`,
|
|
35
|
+
);
|
|
36
|
+
await writeFile(
|
|
37
|
+
join(dir, "drizzle.config.ts"),
|
|
38
|
+
`import { defineConfig } from "drizzle-kit";
|
|
39
|
+
export default defineConfig({
|
|
40
|
+
dialect: "sqlite",
|
|
41
|
+
schema: "./src/schema.ts",
|
|
42
|
+
out: "./drizzle",
|
|
43
|
+
dbCredentials: { url: "file::memory:" },
|
|
44
|
+
});
|
|
45
|
+
`,
|
|
46
|
+
);
|
|
47
|
+
return dir;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe("oke dev db auto-push", () => {
|
|
51
|
+
test("schema change triggers dbPush when auto-push is on", async () => {
|
|
52
|
+
const cwd = await scaffoldProject();
|
|
53
|
+
const pushes: string[] = [];
|
|
54
|
+
let resolveReady!: () => void;
|
|
55
|
+
const ready = new Promise<void>((r) => {
|
|
56
|
+
resolveReady = r;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const result = await runDev({
|
|
60
|
+
cwd,
|
|
61
|
+
local: true,
|
|
62
|
+
keepAlive: false,
|
|
63
|
+
dryRun: false,
|
|
64
|
+
appPort: 0,
|
|
65
|
+
consolePort: 0,
|
|
66
|
+
mcpPort: 0,
|
|
67
|
+
silentClaim: true,
|
|
68
|
+
stdinIsTTY: false,
|
|
69
|
+
startApp: async () => ({
|
|
70
|
+
port: 0,
|
|
71
|
+
url: new URL("http://127.0.0.1:9"),
|
|
72
|
+
stop() {},
|
|
73
|
+
}),
|
|
74
|
+
serveConsole: async () => ({
|
|
75
|
+
port: 0,
|
|
76
|
+
stop() {},
|
|
77
|
+
}),
|
|
78
|
+
serveMcp: async () => ({
|
|
79
|
+
port: 0,
|
|
80
|
+
url: new URL("http://127.0.0.1:9"),
|
|
81
|
+
stop() {},
|
|
82
|
+
}),
|
|
83
|
+
regenClient: async () => {},
|
|
84
|
+
dbPush: async () => {
|
|
85
|
+
pushes.push("push");
|
|
86
|
+
return 0;
|
|
87
|
+
},
|
|
88
|
+
onDbAutoPush: () => {
|
|
89
|
+
resolveReady();
|
|
90
|
+
},
|
|
91
|
+
onReady: async (session) => {
|
|
92
|
+
sessions.push(session);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
expect(result.code).toBe(0);
|
|
97
|
+
// Initial boot triggers one push.
|
|
98
|
+
await Promise.race([ready, Bun.sleep(800)]);
|
|
99
|
+
expect(pushes.length).toBeGreaterThanOrEqual(1);
|
|
100
|
+
|
|
101
|
+
const before = pushes.length;
|
|
102
|
+
await writeFile(
|
|
103
|
+
join(cwd, "src", "schema.ts"),
|
|
104
|
+
`import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
|
|
105
|
+
export const entries = sqliteTable("entries", {
|
|
106
|
+
id: text("id").primaryKey(),
|
|
107
|
+
n: integer("n"),
|
|
108
|
+
});
|
|
109
|
+
`,
|
|
110
|
+
);
|
|
111
|
+
await Bun.sleep(500);
|
|
112
|
+
expect(pushes.length).toBeGreaterThan(before);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test("--no-db-push / noDbPush never calls dbPush", async () => {
|
|
116
|
+
const cwd = await scaffoldProject();
|
|
117
|
+
const pushes: string[] = [];
|
|
118
|
+
|
|
119
|
+
const result = await runDev({
|
|
120
|
+
cwd,
|
|
121
|
+
local: true,
|
|
122
|
+
noDbPush: true,
|
|
123
|
+
keepAlive: false,
|
|
124
|
+
appPort: 0,
|
|
125
|
+
consolePort: 0,
|
|
126
|
+
mcpPort: 0,
|
|
127
|
+
silentClaim: true,
|
|
128
|
+
stdinIsTTY: false,
|
|
129
|
+
startApp: async () => ({
|
|
130
|
+
port: 0,
|
|
131
|
+
url: new URL("http://127.0.0.1:9"),
|
|
132
|
+
stop() {},
|
|
133
|
+
}),
|
|
134
|
+
serveConsole: async () => ({
|
|
135
|
+
port: 0,
|
|
136
|
+
stop() {},
|
|
137
|
+
}),
|
|
138
|
+
serveMcp: async () => ({
|
|
139
|
+
port: 0,
|
|
140
|
+
url: new URL("http://127.0.0.1:9"),
|
|
141
|
+
stop() {},
|
|
142
|
+
}),
|
|
143
|
+
regenClient: async () => {},
|
|
144
|
+
dbPush: async () => {
|
|
145
|
+
pushes.push("push");
|
|
146
|
+
return 0;
|
|
147
|
+
},
|
|
148
|
+
onReady: async (session) => {
|
|
149
|
+
sessions.push(session);
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(result.code).toBe(0);
|
|
154
|
+
await writeFile(
|
|
155
|
+
join(cwd, "src", "schema.ts"),
|
|
156
|
+
`import { sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
157
|
+
export const entries = sqliteTable("entries", { id: text("id").primaryKey(), x: text("x") });
|
|
158
|
+
`,
|
|
159
|
+
);
|
|
160
|
+
await Bun.sleep(500);
|
|
161
|
+
expect(pushes).toHaveLength(0);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.oke/mode` persistence and prompt gating.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
6
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { parseDevMode, readDevMode, shouldAskDevMode, writeDevMode } from "./dev-mode.ts";
|
|
10
|
+
|
|
11
|
+
const dirs: string[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(async () => {
|
|
14
|
+
await Promise.all(dirs.splice(0).map((d) => rm(d, { recursive: true, force: true })));
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function tempDir(): Promise<string> {
|
|
18
|
+
const dir = await mkdtemp(join(tmpdir(), "oke-mode-"));
|
|
19
|
+
dirs.push(dir);
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("dev-mode", () => {
|
|
24
|
+
test("parseDevMode accepts local|docker only", () => {
|
|
25
|
+
expect(parseDevMode("local")).toBe("local");
|
|
26
|
+
expect(parseDevMode(" docker \n")).toBe("docker");
|
|
27
|
+
expect(parseDevMode("stack")).toBeNull();
|
|
28
|
+
expect(parseDevMode(undefined)).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("read/write round-trip", async () => {
|
|
32
|
+
const dir = await tempDir();
|
|
33
|
+
expect(await readDevMode(dir)).toBeNull();
|
|
34
|
+
await writeDevMode(dir, "docker");
|
|
35
|
+
expect(await readDevMode(dir)).toBe("docker");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("shouldAskDevMode: TTY + unset → ask; non-TTY → never", () => {
|
|
39
|
+
expect(shouldAskDevMode({ saved: null, explicit: false, stdinIsTTY: true })).toBe(true);
|
|
40
|
+
expect(shouldAskDevMode({ saved: null, explicit: false, stdinIsTTY: false })).toBe(false);
|
|
41
|
+
expect(shouldAskDevMode({ saved: null, explicit: false, stdinIsTTY: undefined })).toBe(false);
|
|
42
|
+
expect(shouldAskDevMode({ saved: "local", explicit: false, stdinIsTTY: true })).toBe(false);
|
|
43
|
+
expect(shouldAskDevMode({ saved: null, explicit: true, stdinIsTTY: true })).toBe(false);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted `oke dev` run mode — `local` vs `docker`.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { mkdir } from "node:fs/promises";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
|
|
8
|
+
/** Saved / selectable `oke dev` infrastructure mode. */
|
|
9
|
+
export type DevMode = "local" | "docker";
|
|
10
|
+
|
|
11
|
+
/** Relative path under the project root. */
|
|
12
|
+
export const DEV_MODE_RELATIVE_PATH = ".oke/mode";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Absolute path to the mode preference file.
|
|
16
|
+
*
|
|
17
|
+
* @param cwd - Project root
|
|
18
|
+
*/
|
|
19
|
+
export function devModePath(cwd: string): string {
|
|
20
|
+
return resolve(cwd, DEV_MODE_RELATIVE_PATH);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Parse a raw mode string.
|
|
25
|
+
*
|
|
26
|
+
* @param raw - File contents or CLI arg
|
|
27
|
+
*/
|
|
28
|
+
export function parseDevMode(raw: string | undefined | null): DevMode | null {
|
|
29
|
+
if (raw === undefined || raw === null) return null;
|
|
30
|
+
const value = raw.trim().toLowerCase();
|
|
31
|
+
if (value === "local" || value === "docker") return value;
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Read the saved mode from `.oke/mode`, or `null` when unset / invalid.
|
|
37
|
+
*
|
|
38
|
+
* @param cwd - Project root
|
|
39
|
+
*/
|
|
40
|
+
export async function readDevMode(cwd: string): Promise<DevMode | null> {
|
|
41
|
+
const path = devModePath(cwd);
|
|
42
|
+
const file = Bun.file(path);
|
|
43
|
+
if (!(await file.exists())) return null;
|
|
44
|
+
try {
|
|
45
|
+
return parseDevMode(await file.text());
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Persist the preferred mode for future `oke dev` invocations.
|
|
53
|
+
*
|
|
54
|
+
* @param cwd - Project root
|
|
55
|
+
* @param mode - Mode to save
|
|
56
|
+
*/
|
|
57
|
+
export async function writeDevMode(cwd: string, mode: DevMode): Promise<void> {
|
|
58
|
+
const path = devModePath(cwd);
|
|
59
|
+
await mkdir(join(cwd, ".oke"), { recursive: true });
|
|
60
|
+
await Bun.write(path, `${mode}\n`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Whether `oke dev` should open the one-time mode prompt.
|
|
65
|
+
*
|
|
66
|
+
* Mirrors create-oke: never prompt when stdin is not a TTY.
|
|
67
|
+
*
|
|
68
|
+
* @param options - Preference + TTY + explicit flag
|
|
69
|
+
*/
|
|
70
|
+
export function shouldAskDevMode(options: {
|
|
71
|
+
readonly saved: DevMode | null;
|
|
72
|
+
readonly explicit: boolean;
|
|
73
|
+
readonly stdinIsTTY: boolean | undefined;
|
|
74
|
+
}): boolean {
|
|
75
|
+
if (options.explicit) return false;
|
|
76
|
+
if (options.saved !== null) return false;
|
|
77
|
+
return Boolean(options.stdinIsTTY);
|
|
78
|
+
}
|