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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compile Drizzle SQL operators (`eq`, `and`, `lt`, …) and plain
|
|
3
|
-
* maps into `WHERE` SQL + bound params for {@link SqlConnection}.
|
|
2
|
+
* Compile Drizzle SQL operators (`eq`, `and`, `or`, `lt`, `like`, …) and plain
|
|
3
|
+
* equality maps into `WHERE` SQL + bound params for {@link SqlConnection}.
|
|
4
4
|
*
|
|
5
5
|
* Table-agnostic query-builder support — not domain helpers.
|
|
6
6
|
*/
|
|
@@ -11,7 +11,18 @@ export type WhereMap = Readonly<Record<string, unknown>>;
|
|
|
11
11
|
/** One compiled predicate (`col op ?`). */
|
|
12
12
|
export interface CompiledPredicate {
|
|
13
13
|
readonly column: string;
|
|
14
|
-
readonly op:
|
|
14
|
+
readonly op:
|
|
15
|
+
| "="
|
|
16
|
+
| "<"
|
|
17
|
+
| ">"
|
|
18
|
+
| "<="
|
|
19
|
+
| ">="
|
|
20
|
+
| "!="
|
|
21
|
+
| "like"
|
|
22
|
+
| "ilike"
|
|
23
|
+
| "in"
|
|
24
|
+
| "is null"
|
|
25
|
+
| "is not null";
|
|
15
26
|
readonly value: unknown;
|
|
16
27
|
}
|
|
17
28
|
|
|
@@ -22,6 +33,21 @@ export interface CompiledWhere {
|
|
|
22
33
|
readonly predicates: readonly CompiledPredicate[];
|
|
23
34
|
}
|
|
24
35
|
|
|
36
|
+
/** One compiled `ORDER BY` term. */
|
|
37
|
+
export interface CompiledOrder {
|
|
38
|
+
readonly column: string;
|
|
39
|
+
readonly direction: "ASC" | "DESC";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Intermediate compiled node — a leaf comparison or a joined group. */
|
|
43
|
+
interface CompiledNode {
|
|
44
|
+
readonly clause: string;
|
|
45
|
+
readonly params: readonly unknown[];
|
|
46
|
+
readonly predicates: readonly CompiledPredicate[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const EMPTY_NODE: CompiledNode = { clause: "", params: [], predicates: [] };
|
|
50
|
+
|
|
25
51
|
/**
|
|
26
52
|
* True when `value` looks like a Drizzle `SQL` wrapper (`eq` / `and` / …).
|
|
27
53
|
*
|
|
@@ -35,12 +61,37 @@ export function isDrizzleSql(value: unknown): boolean {
|
|
|
35
61
|
);
|
|
36
62
|
}
|
|
37
63
|
|
|
64
|
+
/** Marker for {@link andWhere} — avoids importing `drizzle-orm` here. */
|
|
65
|
+
export interface AndCondition {
|
|
66
|
+
readonly [andConditionBrand]: true;
|
|
67
|
+
readonly conditions: readonly unknown[];
|
|
68
|
+
}
|
|
69
|
+
const andConditionBrand: unique symbol = Symbol("oke.and");
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Join conditions with `AND` without importing `drizzle-orm`.
|
|
73
|
+
* `undefined` entries are dropped; a single remaining condition compiles
|
|
74
|
+
* bare.
|
|
75
|
+
*
|
|
76
|
+
* @param conditions - Equality maps or Drizzle SQL
|
|
77
|
+
*/
|
|
78
|
+
export function andWhere(...conditions: readonly unknown[]): unknown {
|
|
79
|
+
const kept = conditions.filter((c) => c !== undefined && c !== null);
|
|
80
|
+
if (kept.length === 1) return kept[0];
|
|
81
|
+
return { [andConditionBrand]: true, conditions: kept } satisfies AndCondition;
|
|
82
|
+
}
|
|
83
|
+
|
|
38
84
|
/**
|
|
39
85
|
* Compile a where input into SQL.
|
|
40
86
|
*
|
|
41
87
|
* Accepts:
|
|
42
88
|
* - plain {@link WhereMap} equality maps
|
|
43
|
-
* - Drizzle `SQL` from `eq` / `and` / `lt` / …
|
|
89
|
+
* - Drizzle `SQL` from `eq` / `and` / `or` / `lt` / `like` / …
|
|
90
|
+
* - {@link AndCondition} from {@link andWhere}
|
|
91
|
+
*
|
|
92
|
+
* Nested `and(...)` / `or(...)` compile to parenthesized groups — `or` is
|
|
93
|
+
* never flattened into `AND`. Unsupported operators throw rather than
|
|
94
|
+
* silently dropping predicates.
|
|
44
95
|
*
|
|
45
96
|
* @param where - Condition
|
|
46
97
|
*/
|
|
@@ -50,40 +101,96 @@ export function compileWhere(where: unknown): CompiledWhere {
|
|
|
50
101
|
}
|
|
51
102
|
|
|
52
103
|
if (isDrizzleSql(where)) {
|
|
53
|
-
const
|
|
54
|
-
return
|
|
104
|
+
const node = compileSqlNode(where);
|
|
105
|
+
return { clause: node.clause, params: node.params, predicates: node.predicates };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isAndCondition(where)) {
|
|
109
|
+
const children = where.conditions.map(compileWhere).filter((c) => c.clause !== "");
|
|
110
|
+
if (children.length === 0) return { clause: "", params: [], predicates: [] };
|
|
111
|
+
if (children.length === 1) return children[0]!;
|
|
112
|
+
return {
|
|
113
|
+
clause: children.map((c) => `(${c.clause})`).join(" AND "),
|
|
114
|
+
params: children.flatMap((c) => c.params),
|
|
115
|
+
predicates: children.flatMap((c) => c.predicates),
|
|
116
|
+
};
|
|
55
117
|
}
|
|
56
118
|
|
|
57
119
|
if (typeof where === "object" && !Array.isArray(where)) {
|
|
58
|
-
const predicates: CompiledPredicate[] = Object.entries(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
120
|
+
const predicates: CompiledPredicate[] = Object.entries(where as WhereMap).map(
|
|
121
|
+
([column, value]) => ({
|
|
122
|
+
column,
|
|
123
|
+
op: "=" as const,
|
|
124
|
+
value,
|
|
125
|
+
}),
|
|
126
|
+
);
|
|
65
127
|
return predicatesToWhere(predicates);
|
|
66
128
|
}
|
|
67
129
|
|
|
68
|
-
throw new TypeError(
|
|
69
|
-
|
|
130
|
+
throw new TypeError("sql where: expected equality map or Drizzle SQL condition");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function isAndCondition(value: unknown): value is AndCondition {
|
|
134
|
+
return (
|
|
135
|
+
typeof value === "object" &&
|
|
136
|
+
value !== null &&
|
|
137
|
+
(value as AndCondition)[andConditionBrand] === true
|
|
70
138
|
);
|
|
71
139
|
}
|
|
72
140
|
|
|
73
141
|
/**
|
|
74
|
-
*
|
|
142
|
+
* Compile Drizzle `asc()` / `desc()` terms into `ORDER BY` entries.
|
|
143
|
+
* Bare column references default to `ASC`.
|
|
144
|
+
*
|
|
145
|
+
* @param orders - Order terms (`asc(col)` / `desc(col)` SQL or columns)
|
|
146
|
+
*/
|
|
147
|
+
export function compileOrderBy(orders: readonly unknown[]): readonly CompiledOrder[] {
|
|
148
|
+
return orders.map((order) => {
|
|
149
|
+
if (isDrizzleSql(order)) {
|
|
150
|
+
let column: string | undefined;
|
|
151
|
+
let text = "";
|
|
152
|
+
for (const chunk of chunksOf(order)) {
|
|
153
|
+
if (isDrizzleSql(chunk)) {
|
|
154
|
+
throw new TypeError("orderBy(): nested SQL is not supported");
|
|
155
|
+
}
|
|
156
|
+
const chunkString = chunkText(chunk);
|
|
157
|
+
if (chunkString !== undefined) {
|
|
158
|
+
text += chunkString;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const col = asColumn(chunk);
|
|
162
|
+
if (col === undefined) {
|
|
163
|
+
throw new TypeError("orderBy(): expected drizzle asc()/desc() SQL");
|
|
164
|
+
}
|
|
165
|
+
if (column !== undefined) {
|
|
166
|
+
throw new TypeError("orderBy(): one column per term");
|
|
167
|
+
}
|
|
168
|
+
column = col;
|
|
169
|
+
}
|
|
170
|
+
if (column === undefined) {
|
|
171
|
+
throw new TypeError("orderBy(): expected drizzle asc()/desc() SQL");
|
|
172
|
+
}
|
|
173
|
+
const dir = text.trim().toLowerCase();
|
|
174
|
+
if (dir === "" || dir === "asc") return { column, direction: "ASC" } as const;
|
|
175
|
+
if (dir === "desc") return { column, direction: "DESC" } as const;
|
|
176
|
+
throw new TypeError(`orderBy(): unsupported direction ${JSON.stringify(text.trim())}`);
|
|
177
|
+
}
|
|
178
|
+
const col = asColumn(order);
|
|
179
|
+
if (col !== undefined) return { column: col, direction: "ASC" } as const;
|
|
180
|
+
throw new TypeError("orderBy(): expected drizzle asc()/desc() SQL or a column");
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Turn predicates into `col = ? AND …` form (plain equality maps only).
|
|
75
186
|
*
|
|
76
187
|
* @param predicates - Ordered predicates
|
|
77
188
|
*/
|
|
78
|
-
function predicatesToWhere(
|
|
79
|
-
predicates: readonly CompiledPredicate[],
|
|
80
|
-
): CompiledWhere {
|
|
189
|
+
function predicatesToWhere(predicates: readonly CompiledPredicate[]): CompiledWhere {
|
|
81
190
|
if (predicates.length === 0) {
|
|
82
191
|
return { clause: "", params: [], predicates: [] };
|
|
83
192
|
}
|
|
84
|
-
const clause = predicates
|
|
85
|
-
.map((p) => `${quoteIdent(p.column)} ${p.op} ?`)
|
|
86
|
-
.join(" AND ");
|
|
193
|
+
const clause = predicates.map((p) => `${quoteIdent(p.column)} ${p.op} ?`).join(" AND ");
|
|
87
194
|
return {
|
|
88
195
|
clause,
|
|
89
196
|
params: predicates.map((p) => p.value),
|
|
@@ -92,41 +199,145 @@ function predicatesToWhere(
|
|
|
92
199
|
}
|
|
93
200
|
|
|
94
201
|
/**
|
|
95
|
-
*
|
|
202
|
+
* Recursively compile one Drizzle `SQL` node. Nodes with nested `SQL`
|
|
203
|
+
* children are groups joined by `AND` / `OR` (detected from the separator
|
|
204
|
+
* chunks Drizzle emits); nodes without are leaf comparisons.
|
|
96
205
|
*
|
|
97
|
-
* @param node - Drizzle SQL
|
|
206
|
+
* @param node - Drizzle SQL wrapper
|
|
98
207
|
*/
|
|
99
|
-
function
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
208
|
+
function compileSqlNode(node: unknown): CompiledNode {
|
|
209
|
+
const chunks = chunksOf(node);
|
|
210
|
+
const nested = chunks.filter(isDrizzleSql);
|
|
211
|
+
|
|
212
|
+
if (nested.length === 0) {
|
|
213
|
+
return compileLeaf(chunks);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Group level: only structural parens and ` and ` / ` or ` separators may
|
|
217
|
+
// appear next to nested conditions — anything else is a loud failure.
|
|
218
|
+
let joiner: "AND" | "OR" | undefined;
|
|
219
|
+
for (const chunk of chunks) {
|
|
220
|
+
if (isDrizzleSql(chunk)) continue;
|
|
221
|
+
const text = chunkText(chunk);
|
|
222
|
+
if (text === undefined) {
|
|
223
|
+
throw new TypeError("sql where: unsupported mixed condition");
|
|
224
|
+
}
|
|
225
|
+
const token = text.trim().toLowerCase();
|
|
226
|
+
if (token === "" || token === "(" || token === ")") continue;
|
|
227
|
+
if (token === "and" || token === "or") {
|
|
228
|
+
const next = token.toUpperCase() as "AND" | "OR";
|
|
229
|
+
if (joiner !== undefined && joiner !== next) {
|
|
230
|
+
throw new TypeError("sql where: mixed AND/OR at one level — parenthesize explicitly");
|
|
231
|
+
}
|
|
232
|
+
joiner = next;
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
throw new TypeError(`sql where: unsupported fragment ${JSON.stringify(text)}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const children = nested.map(compileSqlNode).filter((c) => c.clause !== "");
|
|
239
|
+
if (children.length === 0) return EMPTY_NODE;
|
|
240
|
+
if (children.length === 1) return children[0] ?? EMPTY_NODE;
|
|
241
|
+
const sep = joiner ?? "AND";
|
|
242
|
+
return {
|
|
243
|
+
clause: children.map((c) => `(${c.clause})`).join(` ${sep} `),
|
|
244
|
+
params: children.flatMap((c) => c.params),
|
|
245
|
+
predicates: children.flatMap((c) => c.predicates),
|
|
246
|
+
};
|
|
103
247
|
}
|
|
104
248
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Compile a leaf node (`col op ?`) from chunks with no nested `SQL`.
|
|
251
|
+
* Structural paren chunks are ignored; every other chunk must be part of the
|
|
252
|
+
* comparison or it throws. `is null` / `is not null` bind no value; `in`
|
|
253
|
+
* binds one placeholder per array element.
|
|
254
|
+
*
|
|
255
|
+
* @param chunks - Drizzle query chunks
|
|
256
|
+
*/
|
|
257
|
+
function compileLeaf(chunks: readonly unknown[]): CompiledNode {
|
|
258
|
+
let column: string | undefined;
|
|
259
|
+
let op: CompiledPredicate["op"] | undefined;
|
|
260
|
+
let value: unknown;
|
|
261
|
+
let state: "start" | "column" | "op" | "done" = "start";
|
|
109
262
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
263
|
+
for (const chunk of chunks) {
|
|
264
|
+
if (Array.isArray(chunk)) {
|
|
265
|
+
if (state !== "op" || op !== "in") {
|
|
266
|
+
throw new TypeError("sql where: unsupported condition shape");
|
|
267
|
+
}
|
|
268
|
+
const values = chunk.map(asInArrayValue);
|
|
269
|
+
value = values;
|
|
270
|
+
state = "done";
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
const text = chunkText(chunk);
|
|
274
|
+
if (text !== undefined) {
|
|
275
|
+
const token = text.trim().replace(/\)+$/, "");
|
|
276
|
+
if (token === "" || token === "(" || token === ")") continue;
|
|
277
|
+
if (state === "column") {
|
|
278
|
+
op = asOperator(token);
|
|
279
|
+
if (op === undefined) {
|
|
280
|
+
throw new TypeError(`sql where: unsupported operator ${JSON.stringify(token)}`);
|
|
281
|
+
}
|
|
282
|
+
state = op === "is null" || op === "is not null" ? "done" : "op";
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
throw new TypeError(`sql where: unsupported fragment ${JSON.stringify(text)}`);
|
|
117
286
|
}
|
|
287
|
+
const col = asColumn(chunk);
|
|
288
|
+
if (col !== undefined) {
|
|
289
|
+
if (state !== "start") {
|
|
290
|
+
throw new TypeError("sql where: unsupported condition shape");
|
|
291
|
+
}
|
|
292
|
+
column = col;
|
|
293
|
+
state = "column";
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
const param = asParamValue(chunk);
|
|
297
|
+
if (param.found) {
|
|
298
|
+
if (state !== "op") {
|
|
299
|
+
throw new TypeError("sql where: unsupported condition shape");
|
|
300
|
+
}
|
|
301
|
+
value = param.value;
|
|
302
|
+
state = "done";
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
throw new TypeError("sql where: unsupported condition chunk");
|
|
118
306
|
}
|
|
119
307
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
308
|
+
if (state === "start") return EMPTY_NODE;
|
|
309
|
+
if (state !== "done" || column === undefined || op === undefined) {
|
|
310
|
+
throw new TypeError("sql where: incomplete condition");
|
|
311
|
+
}
|
|
312
|
+
const predicate: CompiledPredicate = { column, op, value };
|
|
313
|
+
if (op === "is null" || op === "is not null") {
|
|
314
|
+
return { clause: `${quoteIdent(column)} ${op}`, params: [], predicates: [predicate] };
|
|
315
|
+
}
|
|
316
|
+
if (op === "in") {
|
|
317
|
+
const values = value as readonly unknown[];
|
|
318
|
+
const placeholders = values.map(() => "?").join(", ");
|
|
319
|
+
return {
|
|
320
|
+
clause: `${quoteIdent(column)} in (${placeholders})`,
|
|
321
|
+
params: [...values],
|
|
322
|
+
predicates: [predicate],
|
|
323
|
+
};
|
|
129
324
|
}
|
|
325
|
+
return {
|
|
326
|
+
clause: `${quoteIdent(column)} ${op} ?`,
|
|
327
|
+
params: [value],
|
|
328
|
+
predicates: [predicate],
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function chunksOf(node: unknown): readonly unknown[] {
|
|
333
|
+
return (node as { queryChunks: unknown[] }).queryChunks;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Joined text of a Drizzle `StringChunk` (`{ value: string[] }`). */
|
|
337
|
+
function chunkText(chunk: unknown): string | undefined {
|
|
338
|
+
if (!chunk || typeof chunk !== "object") return undefined;
|
|
339
|
+
const value = (chunk as { value?: unknown }).value;
|
|
340
|
+
return Array.isArray(value) ? value.join("") : undefined;
|
|
130
341
|
}
|
|
131
342
|
|
|
132
343
|
function asColumn(chunk: unknown): string | undefined {
|
|
@@ -135,16 +346,8 @@ function asColumn(chunk: unknown): string | undefined {
|
|
|
135
346
|
return typeof name === "string" && name.length > 0 ? name : undefined;
|
|
136
347
|
}
|
|
137
348
|
|
|
138
|
-
function asOperator(
|
|
139
|
-
|
|
140
|
-
const value = (chunk as { value?: unknown }).value;
|
|
141
|
-
const text = Array.isArray(value)
|
|
142
|
-
? value.join("")
|
|
143
|
-
: typeof value === "string"
|
|
144
|
-
? value
|
|
145
|
-
: "";
|
|
146
|
-
const trimmed = text.trim();
|
|
147
|
-
switch (trimmed) {
|
|
349
|
+
function asOperator(token: string): CompiledPredicate["op"] | undefined {
|
|
350
|
+
switch (token.toLowerCase()) {
|
|
148
351
|
case "=":
|
|
149
352
|
return "=";
|
|
150
353
|
case "<":
|
|
@@ -158,18 +361,43 @@ function asOperator(chunk: unknown): CompiledPredicate["op"] | undefined {
|
|
|
158
361
|
case "!=":
|
|
159
362
|
case "<>":
|
|
160
363
|
return "!=";
|
|
364
|
+
case "like":
|
|
365
|
+
return "like";
|
|
366
|
+
case "ilike":
|
|
367
|
+
return "ilike";
|
|
368
|
+
case "in":
|
|
369
|
+
return "in";
|
|
370
|
+
case "is null":
|
|
371
|
+
return "is null";
|
|
372
|
+
case "is not null":
|
|
373
|
+
return "is not null";
|
|
161
374
|
default:
|
|
162
375
|
return undefined;
|
|
163
376
|
}
|
|
164
377
|
}
|
|
165
378
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
return
|
|
379
|
+
/** Unwrap one element of a Drizzle `inArray` value array. */
|
|
380
|
+
function asInArrayValue(item: unknown): unknown {
|
|
381
|
+
const param = asParamValue(item);
|
|
382
|
+
if (!param.found) {
|
|
383
|
+
throw new TypeError("sql where: unsupported in-list value");
|
|
384
|
+
}
|
|
385
|
+
return param.value;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Param values arrive either as Drizzle `Param` instances (wrapped by
|
|
390
|
+
* `bindIfParam`) or as raw primitives interpolated by `sql` templates
|
|
391
|
+
* (`like`, `ilike`, …).
|
|
392
|
+
*/
|
|
393
|
+
function asParamValue(chunk: unknown): { readonly found: boolean; readonly value?: unknown } {
|
|
394
|
+
if (chunk === undefined) return { found: false };
|
|
395
|
+
if (chunk === null || typeof chunk !== "object") return { found: true, value: chunk };
|
|
396
|
+
if (Array.isArray(chunk)) return { found: false };
|
|
397
|
+
if (!("value" in (chunk as object))) return { found: false };
|
|
398
|
+
if (Array.isArray((chunk as { value: unknown }).value)) return { found: false };
|
|
399
|
+
if ((chunk as { name?: unknown }).name) return { found: false };
|
|
400
|
+
return { found: true, value: (chunk as { value: unknown }).value };
|
|
173
401
|
}
|
|
174
402
|
|
|
175
403
|
/**
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SqlStoreHandle surface lock — single-table SQL session only.
|
|
3
|
+
*
|
|
4
|
+
* Relational `with:` / Drizzle RQB (`db.query.*.findMany({ with })`) is a
|
|
5
|
+
* documented limitation: effects, cache keys, and PII masking assume one
|
|
6
|
+
* table per call, so no relational query surface may appear on the handle.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, expect, test } from "bun:test";
|
|
10
|
+
import { Database } from "bun:sqlite";
|
|
11
|
+
import { and, desc, eq, like, lt, or } from "drizzle-orm";
|
|
12
|
+
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
|
13
|
+
import { sqliteDriver } from "../../drivers/sqlite.ts";
|
|
14
|
+
import type { SqlConnection } from "../../drivers/types.ts";
|
|
15
|
+
import { createSqlStoreHandle, type SqlStoreHandle } from "./sql-session.ts";
|
|
16
|
+
|
|
17
|
+
const posts = sqliteTable("posts", {
|
|
18
|
+
id: text("id").primaryKey(),
|
|
19
|
+
title: text("title").notNull(),
|
|
20
|
+
createdAt: integer("created_at").notNull(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
async function openHandle(): Promise<{ handle: SqlStoreHandle; conn: SqlConnection }> {
|
|
24
|
+
const conn = await sqliteDriver.connect({
|
|
25
|
+
client: new Database(":memory:"),
|
|
26
|
+
role: "primary",
|
|
27
|
+
});
|
|
28
|
+
const handle = createSqlStoreHandle("sql:app", {
|
|
29
|
+
connection: conn,
|
|
30
|
+
classifications: new Map(),
|
|
31
|
+
routedRole: "primary",
|
|
32
|
+
domainDdl: "ensure",
|
|
33
|
+
});
|
|
34
|
+
return { handle, conn };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe("SqlStoreHandle — no relational query surface (path b)", () => {
|
|
38
|
+
test("created handle exposes exactly the single-table surface", async () => {
|
|
39
|
+
const db = new Database(":memory:");
|
|
40
|
+
const conn = await sqliteDriver.connect({ client: db, role: "primary" });
|
|
41
|
+
const handle = createSqlStoreHandle("sql:app", {
|
|
42
|
+
connection: conn,
|
|
43
|
+
classifications: new Map(),
|
|
44
|
+
routedRole: "primary",
|
|
45
|
+
domainDdl: "ensure",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
expect(Object.keys(handle).sort()).toEqual(
|
|
49
|
+
[
|
|
50
|
+
"ref",
|
|
51
|
+
"routedRole",
|
|
52
|
+
"driverId",
|
|
53
|
+
"select",
|
|
54
|
+
"insert",
|
|
55
|
+
"update",
|
|
56
|
+
"findById",
|
|
57
|
+
"delete",
|
|
58
|
+
"exists",
|
|
59
|
+
"increment",
|
|
60
|
+
"raw",
|
|
61
|
+
"count",
|
|
62
|
+
"page",
|
|
63
|
+
"ensureTable",
|
|
64
|
+
].sort(),
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// No Drizzle RQB / with: surface — ever.
|
|
68
|
+
expect("query" in handle).toBe(false);
|
|
69
|
+
expect("findMany" in handle).toBe(false);
|
|
70
|
+
expect("findFirst" in handle).toBe(false);
|
|
71
|
+
expect("with" in handle).toBe(false);
|
|
72
|
+
|
|
73
|
+
await conn.close();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe("SqlStoreHandle — orderBy / limit select chain", () => {
|
|
78
|
+
test("orderBy + limit without where", async () => {
|
|
79
|
+
const { handle, conn } = await openHandle();
|
|
80
|
+
await handle.insert(posts).values({ id: "p1", title: "one", createdAt: 100 });
|
|
81
|
+
await handle.insert(posts).values({ id: "p2", title: "two", createdAt: 300 });
|
|
82
|
+
await handle.insert(posts).values({ id: "p3", title: "three", createdAt: 200 });
|
|
83
|
+
|
|
84
|
+
const rows = await handle.select().from(posts).orderBy(desc(posts.createdAt)).limit(2);
|
|
85
|
+
expect(rows.map((r) => r.id)).toEqual(["p2", "p3"]);
|
|
86
|
+
await conn.close();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("limit directly on from() — no where required", async () => {
|
|
90
|
+
const { handle, conn } = await openHandle();
|
|
91
|
+
await handle.insert(posts).values({ id: "p1", title: "one", createdAt: 100 });
|
|
92
|
+
await handle.insert(posts).values({ id: "p2", title: "two", createdAt: 300 });
|
|
93
|
+
|
|
94
|
+
const rows = await handle.select().from(posts).limit(1);
|
|
95
|
+
expect(rows).toHaveLength(1);
|
|
96
|
+
await conn.close();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("composite cursor predicate: where → orderBy → limit", async () => {
|
|
100
|
+
const { handle, conn } = await openHandle();
|
|
101
|
+
await handle.insert(posts).values({ id: "p1", title: "one", createdAt: 100 });
|
|
102
|
+
await handle.insert(posts).values({ id: "p2", title: "two", createdAt: 300 });
|
|
103
|
+
await handle.insert(posts).values({ id: "p3", title: "three", createdAt: 200 });
|
|
104
|
+
// Tie on createdAt=200 with an id that sorts after the cursor id.
|
|
105
|
+
await handle.insert(posts).values({ id: "p0", title: "four", createdAt: 200 });
|
|
106
|
+
|
|
107
|
+
const order = [desc(posts.createdAt), desc(posts.id)] as const;
|
|
108
|
+
const page1 = await handle
|
|
109
|
+
.select()
|
|
110
|
+
.from(posts)
|
|
111
|
+
.orderBy(...order)
|
|
112
|
+
.limit(2);
|
|
113
|
+
expect(page1.map((r) => r.id)).toEqual(["p2", "p3"]);
|
|
114
|
+
|
|
115
|
+
// (createdAt, id) < (200, "p3") — the second page of a keyset cursor.
|
|
116
|
+
const page2 = await handle
|
|
117
|
+
.select()
|
|
118
|
+
.from(posts)
|
|
119
|
+
.where(or(lt(posts.createdAt, 200), and(eq(posts.createdAt, 200), lt(posts.id, "p3"))))
|
|
120
|
+
.orderBy(...order)
|
|
121
|
+
.limit(2);
|
|
122
|
+
expect(page2.map((r) => r.id)).toEqual(["p0", "p1"]);
|
|
123
|
+
await conn.close();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("like filters rows through the session (sqlite ASCII-insensitive)", async () => {
|
|
127
|
+
const { handle, conn } = await openHandle();
|
|
128
|
+
await handle.insert(posts).values({ id: "p1", title: "alpha", createdAt: 100 });
|
|
129
|
+
await handle.insert(posts).values({ id: "p2", title: "bravo", createdAt: 200 });
|
|
130
|
+
|
|
131
|
+
const rows = await handle.select().from(posts).where(like(posts.title, "A%"));
|
|
132
|
+
expect(rows.map((r) => r.id)).toEqual(["p1"]);
|
|
133
|
+
await conn.close();
|
|
134
|
+
});
|
|
135
|
+
});
|