okengine 0.2.6 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +33 -30
- package/README.md +74 -340
- package/{spec/manifest.v1.schema.json → manifest.v1.schema.json} +40 -9
- package/package.json +47 -44
- package/site/content/docs/ai/llms-txt.mdx +54 -0
- package/site/content/docs/ai/mcp.mdx +123 -0
- package/site/content/docs/ai/meta.json +5 -0
- package/site/content/docs/ai/skills.mdx +53 -0
- package/site/content/docs/console/access.mdx +29 -0
- package/site/content/docs/console/ai.mdx +35 -0
- package/site/content/docs/console/architecture.mdx +35 -0
- package/site/content/docs/console/channels.mdx +37 -0
- package/site/content/docs/console/clock.mdx +31 -0
- package/site/content/docs/console/flows.mdx +31 -0
- package/site/content/docs/console/gates.mdx +35 -0
- package/site/content/docs/console/manifest-diff.mdx +34 -0
- package/site/content/docs/console/meta.json +23 -0
- package/site/content/docs/console/overview.mdx +40 -0
- package/site/content/docs/console/plugins.mdx +41 -0
- package/site/content/docs/console/privacy.mdx +32 -0
- package/site/content/docs/console/runs.mdx +40 -0
- package/site/content/docs/console/signals.mdx +31 -0
- package/site/content/docs/console/store.mdx +32 -0
- package/site/content/docs/console/tenancy.mdx +32 -0
- package/site/content/docs/console/traces.mdx +34 -0
- package/site/content/docs/console/vault.mdx +37 -0
- package/site/content/docs/elements/ai.mdx +180 -0
- package/site/content/docs/elements/channel.mdx +167 -0
- package/site/content/docs/elements/clock.mdx +182 -0
- package/site/content/docs/elements/flow.mdx +288 -0
- package/site/content/docs/elements/gate.mdx +171 -0
- package/site/content/docs/elements/meta.json +5 -0
- package/site/content/docs/elements/signal.mdx +171 -0
- package/site/content/docs/elements/store.mdx +320 -0
- package/site/content/docs/elements/vault.mdx +263 -0
- package/site/content/docs/get-started/basic-usage.mdx +124 -0
- package/site/content/docs/get-started/comparison.mdx +65 -0
- package/site/content/docs/get-started/installation.mdx +113 -0
- package/site/content/docs/get-started/introduction.mdx +123 -0
- package/site/content/docs/get-started/meta.json +5 -0
- package/site/content/docs/index.mdx +63 -0
- package/site/content/docs/meta.json +5 -0
- package/site/content/docs/plugins/compression.mdx +60 -0
- package/site/content/docs/plugins/cors.mdx +92 -0
- package/site/content/docs/plugins/csrf.mdx +96 -0
- package/site/content/docs/plugins/ip-allowlist.mdx +92 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +101 -0
- package/site/content/docs/plugins/meta.json +15 -0
- package/site/content/docs/plugins/security-headers.mdx +136 -0
- package/site/content/docs/reference/cli.md +101 -0
- package/site/content/docs/reference/configuration.mdx +159 -0
- package/site/content/docs/reference/environment-variables.mdx +87 -0
- package/site/content/docs/reference/errors.mdx +80 -0
- package/site/content/docs/reference/fx.mdx +117 -0
- package/site/content/docs/reference/meta.json +5 -0
- package/site/content/docs/reference/plugins.mdx +249 -0
- package/site/content/docs/reference/security.md +63 -0
- package/src/auth/api-keys.ts +2 -5
- package/src/auth/attenuation.ts +2 -6
- package/src/auth/auth.test.ts +56 -31
- package/src/auth/invoke-as.ts +1 -3
- package/src/auth/operator.ts +8 -26
- package/src/auth/planes.ts +2 -7
- package/src/auth/plugin.ts +4 -7
- package/src/auth/roles.ts +1 -5
- package/src/auth/sessions.ts +10 -39
- package/src/cli/args.ts +1 -5
- package/src/cli/ask-dev-mode.ts +40 -0
- package/src/cli/build.ts +1 -2
- package/src/cli/client-add.test.ts +8 -15
- package/src/cli/client-add.ts +5 -14
- package/src/cli/completion.test.ts +1 -5
- package/src/cli/completion.ts +4 -17
- package/src/cli/db-auto-push.test.ts +64 -0
- package/src/cli/db-auto-push.ts +72 -0
- package/src/cli/db.test.ts +189 -0
- package/src/cli/db.ts +456 -0
- package/src/cli/dev-app-runner.ts +2 -8
- package/src/cli/dev-db-push.test.ts +193 -0
- package/src/cli/dev-mode.test.ts +45 -0
- package/src/cli/dev-mode.ts +78 -0
- package/src/cli/dev-schema-sync.test.ts +66 -0
- package/src/cli/dev-schema-sync.ts +139 -0
- package/src/cli/dev.test.ts +264 -15
- package/src/cli/dev.ts +355 -139
- package/src/cli/doc-staleness.test.ts +69 -0
- package/src/cli/docker-cli.test.ts +27 -8
- package/src/cli/docker.ts +11 -3
- package/src/cli/doctor-diff.test.ts +1 -5
- package/src/cli/doctor-diff.ts +17 -46
- package/src/cli/doctor-pii.ts +2 -7
- package/src/cli/doctor.test.ts +26 -4
- package/src/cli/doctor.ts +35 -11
- package/src/cli/drizzle-env.test.ts +67 -0
- package/src/cli/drizzle-env.ts +78 -0
- package/src/cli/ensure-drizzle-config.ts +50 -0
- package/src/cli/eval.ts +4 -14
- package/src/cli/gates-list.ts +1 -4
- package/src/cli/hero-meta.test.ts +17 -19
- package/src/cli/hero-meta.ts +20 -30
- package/src/cli/images.ts +3 -8
- package/src/cli/index.ts +11 -2
- package/src/cli/load-config.images.test.ts +14 -14
- package/src/cli/load-config.ts +47 -47
- package/src/cli/mcp-from-console.ts +1 -4
- package/src/cli/mode.ts +65 -0
- package/src/cli/openbao-bootstrap.test.ts +147 -0
- package/src/cli/openbao-bootstrap.ts +280 -0
- package/src/cli/openbao-restart.integration.test.ts +136 -0
- package/src/cli/ports.test.ts +7 -14
- package/src/cli/ports.ts +7 -5
- package/src/cli/privacy-erase.ts +1 -3
- package/src/cli/registry.ts +75 -25
- package/src/cli/resolve-dev-sql-env.test.ts +48 -0
- package/src/cli/resolve-dev-sql-env.ts +42 -0
- package/src/cli/schema.ts +3 -10
- package/src/cli/stack.ts +8 -10
- package/src/cli/start.ts +4 -15
- package/src/cli/upgrade.ts +1 -4
- package/src/cli/vault-cmd.ts +63 -0
- package/src/client/budget-entry.ts +1 -6
- package/src/client/create.test.ts +6 -12
- package/src/client/create.ts +2 -8
- package/src/client/errors.ts +1 -4
- package/src/client/index.ts +1 -6
- package/src/client/notes-contract.test.ts +4 -13
- package/src/client/transport.ts +9 -30
- package/src/client/types.ts +15 -30
- package/src/compiler/aot.test.ts +2 -9
- package/src/compiler/aot.ts +1 -4
- package/src/compiler/differential.test.ts +3 -11
- package/src/compiler/dynamic.ts +1 -4
- package/src/compiler/effects-infer.ts +8 -34
- package/src/compiler/emit.ts +1 -3
- package/src/compiler/extract.test.ts +136 -30
- package/src/compiler/extract.ts +485 -157
- package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
- package/src/compiler/fixtures/skyport.expected.json +24 -83
- package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
- package/src/compiler/http-parse.ts +2 -9
- package/src/compiler/index.ts +1 -5
- package/src/compiler/response.ts +16 -7
- package/src/compiler/sucrose.ts +11 -31
- package/src/config/define-config.test.ts +55 -34
- package/src/config/index.ts +177 -46
- package/src/config/resolve-driver.test.ts +28 -17
- package/src/console/budget.test.ts +1 -4
- package/src/console/index.ts +1 -4
- package/src/console/server/access.test.ts +15 -43
- package/src/console/server/access.ts +19 -49
- package/src/console/server/ai.test.ts +3 -11
- package/src/console/server/ai.ts +23 -46
- package/src/console/server/app.ts +16 -45
- package/src/console/server/auth-rate.test.ts +4 -12
- package/src/console/server/bind.ts +1 -5
- package/src/console/server/channels.test.ts +2 -6
- package/src/console/server/channels.ts +10 -35
- package/src/console/server/claim.ts +2 -8
- package/src/console/server/clock.test.ts +2 -6
- package/src/console/server/clock.ts +8 -26
- package/src/console/server/console.test.ts +1 -3
- package/src/console/server/diff.test.ts +5 -17
- package/src/console/server/diff.ts +10 -31
- package/src/console/server/dry-run.audit.test.ts +2 -8
- package/src/console/server/flows.ts +64 -233
- package/src/console/server/gates.test.ts +14 -50
- package/src/console/server/gates.ts +13 -48
- package/src/console/server/index.ts +2 -9
- package/src/console/server/live.ts +3 -12
- package/src/console/server/operator-db.test.ts +4 -15
- package/src/console/server/operator-db.ts +13 -32
- package/src/console/server/plugin.ts +50 -53
- package/src/console/server/plugins.test.ts +2 -6
- package/src/console/server/plugins.ts +17 -56
- package/src/console/server/runs-pii.ts +2 -7
- package/src/console/server/security.gate.test.ts +18 -40
- package/src/console/server/serve.ts +10 -25
- package/src/console/server/signals.test.ts +1 -3
- package/src/console/server/signals.ts +17 -40
- package/src/console/server/state.ts +21 -59
- package/src/console/server/store.test.ts +20 -22
- package/src/console/server/store.ts +31 -76
- package/src/console/server/vault.test.ts +12 -29
- package/src/console/server/vault.ts +44 -66
- package/src/console/ui/access/AccessA11yView.tsx +6 -21
- package/src/console/ui/access/a11y.test.tsx +3 -12
- package/src/console/ui/access/acknowledgement.test.ts +1 -4
- package/src/console/ui/access/acknowledgement.ts +1 -3
- package/src/console/ui/access/blast-radius.ts +1 -3
- package/src/console/ui/access/confirmation.test.ts +1 -5
- package/src/console/ui/access/confirmation.ts +1 -4
- package/src/console/ui/access/fixture.ts +1 -5
- package/src/console/ui/access/grantable.test.ts +1 -3
- package/src/console/ui/access/grantable.ts +2 -7
- package/src/console/ui/access/index.ts +2 -9
- package/src/console/ui/access/provenance.test.ts +1 -3
- package/src/console/ui/access/provenance.ts +2 -6
- package/src/console/ui/access/search.test.ts +1 -5
- package/src/console/ui/access/search.ts +2 -6
- package/src/console/ui/ai/AiA11yView.tsx +6 -17
- package/src/console/ui/ai/a11y.test.tsx +2 -5
- package/src/console/ui/ai/fixture.ts +2 -7
- package/src/console/ui/ai/format.ts +1 -3
- package/src/console/ui/ai/group.test.ts +1 -3
- package/src/console/ui/ai/group.ts +4 -12
- package/src/console/ui/ai/index.ts +2 -9
- package/src/console/ui/ai/promotion.test.ts +2 -7
- package/src/console/ui/ai/promotion.ts +4 -13
- package/src/console/ui/ai/search.test.ts +2 -11
- package/src/console/ui/ai/search.ts +3 -13
- package/src/console/ui/ai/types.ts +1 -8
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
- package/src/console/ui/architecture/a11y.test.tsx +1 -2
- package/src/console/ui/architecture/declared.ts +1 -5
- package/src/console/ui/architecture/index.ts +7 -35
- package/src/console/ui/architecture/layout.ts +1 -3
- package/src/console/ui/architecture/pathologies.ts +10 -19
- package/src/console/ui/architecture/search.ts +6 -15
- package/src/console/ui/architecture/traffic.ts +4 -14
- package/src/console/ui/architecture/types.ts +2 -10
- package/src/console/ui/architecture/view.test.ts +7 -19
- package/src/console/ui/architecture/view.ts +9 -36
- package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
- package/src/console/ui/channels/a11y.test.tsx +1 -2
- package/src/console/ui/channels/confirmation.test.ts +1 -4
- package/src/console/ui/channels/confirmation.ts +1 -4
- package/src/console/ui/channels/findings.ts +1 -5
- package/src/console/ui/channels/index.ts +2 -8
- package/src/console/ui/channels/locale.test.ts +1 -3
- package/src/console/ui/channels/locale.ts +2 -8
- package/src/console/ui/channels/search.ts +4 -13
- package/src/console/ui/channels/taxonomy.ts +1 -3
- package/src/console/ui/clock/ClockA11yView.tsx +9 -26
- package/src/console/ui/clock/a11y.test.tsx +2 -5
- package/src/console/ui/clock/confirmation.test.ts +1 -3
- package/src/console/ui/clock/confirmation.ts +1 -4
- package/src/console/ui/clock/findings.ts +1 -4
- package/src/console/ui/clock/health.ts +2 -7
- package/src/console/ui/clock/index.ts +2 -10
- package/src/console/ui/clock/search.test.ts +1 -3
- package/src/console/ui/clock/search.ts +2 -6
- package/src/console/ui/clock/timeline.test.ts +1 -3
- package/src/console/ui/clock/waiting-on.test.ts +1 -5
- package/src/console/ui/clock/waiting-on.ts +2 -7
- package/src/console/ui/diff/DiffA11yView.tsx +8 -17
- package/src/console/ui/diff/a11y.test.tsx +2 -5
- package/src/console/ui/diff/group.test.ts +3 -13
- package/src/console/ui/diff/group.ts +2 -8
- package/src/console/ui/diff/index.ts +2 -8
- package/src/console/ui/diff/search.test.ts +1 -5
- package/src/console/ui/diff/search.ts +4 -16
- package/src/console/ui/diff/summary.ts +1 -2
- package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
- package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
- package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
- package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
- package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
- package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
- package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
- package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
- package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
- package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
- package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
- package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
- package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
- package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
- package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
- package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
- package/src/console/ui/dist/index.html +1 -1
- package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
- package/src/console/ui/flows/a11y.test.tsx +2 -8
- package/src/console/ui/flows/buffer.test.ts +3 -11
- package/src/console/ui/flows/buffer.ts +4 -11
- package/src/console/ui/flows/confirmation.ts +1 -3
- package/src/console/ui/flows/contract.test.ts +3 -7
- package/src/console/ui/flows/contract.ts +12 -36
- package/src/console/ui/flows/graph.test.ts +3 -11
- package/src/console/ui/flows/graph.ts +5 -15
- package/src/console/ui/flows/index.ts +1 -6
- package/src/console/ui/flows/save-as-test.ts +1 -3
- package/src/console/ui/flows/search.ts +8 -25
- package/src/console/ui/flows/tiers.ts +2 -9
- package/src/console/ui/gates/GatesA11yView.tsx +4 -13
- package/src/console/ui/gates/a11y.test.tsx +2 -5
- package/src/console/ui/gates/audit.ts +1 -3
- package/src/console/ui/gates/denial.test.ts +1 -3
- package/src/console/ui/gates/denial.ts +4 -12
- package/src/console/ui/gates/findings.ts +1 -3
- package/src/console/ui/gates/group.test.ts +3 -3
- package/src/console/ui/gates/group.ts +3 -11
- package/src/console/ui/gates/index.ts +2 -10
- package/src/console/ui/gates/search.ts +3 -10
- package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
- package/src/console/ui/overview/a11y.test.tsx +1 -2
- package/src/console/ui/overview/busiest.ts +1 -3
- package/src/console/ui/overview/compose.ts +1 -13
- package/src/console/ui/overview/cost.ts +34 -38
- package/src/console/ui/overview/fixture.ts +21 -26
- package/src/console/ui/overview/golden.ts +4 -14
- package/src/console/ui/overview/index.ts +2 -9
- package/src/console/ui/overview/rank.test.ts +3 -10
- package/src/console/ui/overview/rank.ts +2 -7
- package/src/console/ui/overview/slo.test.ts +5 -9
- package/src/console/ui/overview/slo.ts +6 -23
- package/src/console/ui/overview/verdict.ts +3 -10
- package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
- package/src/console/ui/plugins/a11y.test.tsx +1 -2
- package/src/console/ui/plugins/fixture.ts +2 -4
- package/src/console/ui/plugins/group.test.ts +1 -3
- package/src/console/ui/plugins/group.ts +1 -6
- package/src/console/ui/plugins/index.ts +3 -13
- package/src/console/ui/plugins/search.ts +7 -19
- package/src/console/ui/runs/RunsA11yView.tsx +5 -20
- package/src/console/ui/runs/a11y.test.tsx +2 -5
- package/src/console/ui/runs/explain.ts +2 -6
- package/src/console/ui/runs/group.ts +3 -12
- package/src/console/ui/runs/histogram.test.ts +2 -11
- package/src/console/ui/runs/histogram.ts +1 -4
- package/src/console/ui/runs/index.ts +4 -18
- package/src/console/ui/runs/project.ts +2 -6
- package/src/console/ui/runs/query.test.ts +1 -3
- package/src/console/ui/runs/query.ts +12 -35
- package/src/console/ui/runs/search.ts +5 -19
- package/src/console/ui/runs/trace-link.test.ts +2 -6
- package/src/console/ui/runs/trace-link.ts +4 -16
- package/src/console/ui/runs/types.ts +1 -3
- package/src/console/ui/shell/App.tsx +2 -10
- package/src/console/ui/shell/client.ts +22 -115
- package/src/console/ui/shell/components/ui.tsx +1 -4
- package/src/console/ui/shell/layout/Shell.tsx +2 -4
- package/src/console/ui/shell/main.tsx +31 -96
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
- package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
- package/src/console/ui/shell/setup/Wizard.tsx +3 -5
- package/src/console/ui/shell/styles.css +1 -2
- package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
- package/src/console/ui/signals/a11y.test.tsx +2 -5
- package/src/console/ui/signals/confirmation.test.ts +1 -5
- package/src/console/ui/signals/confirmation.ts +2 -6
- package/src/console/ui/signals/dry-run.ts +1 -3
- package/src/console/ui/signals/durable.ts +1 -3
- package/src/console/ui/signals/findings.ts +1 -3
- package/src/console/ui/signals/group.test.ts +2 -8
- package/src/console/ui/signals/group.ts +2 -10
- package/src/console/ui/signals/index.ts +1 -4
- package/src/console/ui/signals/monitor.ts +2 -7
- package/src/console/ui/signals/schema-form.test.ts +3 -14
- package/src/console/ui/signals/schema-form.ts +1 -4
- package/src/console/ui/signals/search.ts +4 -13
- package/src/console/ui/store/StoreA11yView.tsx +3 -9
- package/src/console/ui/store/a11y.test.tsx +2 -5
- package/src/console/ui/store/confirmation.test.ts +1 -3
- package/src/console/ui/store/confirmation.ts +1 -4
- package/src/console/ui/store/dry-run.ts +2 -5
- package/src/console/ui/store/fixture.ts +1 -2
- package/src/console/ui/store/group.test.ts +1 -6
- package/src/console/ui/store/group.ts +1 -4
- package/src/console/ui/store/index.ts +1 -5
- package/src/console/ui/store/search.ts +2 -6
- package/src/console/ui/store/will-not-fire.ts +1 -2
- package/src/console/ui/traces/TracesA11yView.tsx +10 -29
- package/src/console/ui/traces/a11y.test.tsx +1 -2
- package/src/console/ui/traces/chain.test.ts +5 -19
- package/src/console/ui/traces/chain.ts +1 -3
- package/src/console/ui/traces/critical-path.test.ts +1 -3
- package/src/console/ui/traces/critical-path.ts +2 -6
- package/src/console/ui/traces/filter.test.ts +2 -6
- package/src/console/ui/traces/filter.ts +5 -13
- package/src/console/ui/traces/fold.test.ts +4 -12
- package/src/console/ui/traces/fold.ts +1 -3
- package/src/console/ui/traces/mini.ts +1 -3
- package/src/console/ui/traces/replay.test.ts +1 -3
- package/src/console/ui/traces/replay.ts +1 -3
- package/src/console/ui/traces/sampling.ts +1 -4
- package/src/console/ui/traces/search.ts +4 -17
- package/src/console/ui/traces/tier.ts +1 -3
- package/src/console/ui/vault/VaultA11yView.tsx +5 -17
- package/src/console/ui/vault/a11y.test.tsx +1 -2
- package/src/console/ui/vault/blast-radius.ts +1 -3
- package/src/console/ui/vault/confirmation.test.ts +1 -5
- package/src/console/ui/vault/confirmation.ts +1 -4
- package/src/console/ui/vault/dormant.test.ts +1 -4
- package/src/console/ui/vault/export-safe.test.ts +1 -5
- package/src/console/ui/vault/export-safe.ts +1 -4
- package/src/console/ui/vault/fixture.ts +3 -3
- package/src/console/ui/vault/group.ts +1 -2
- package/src/console/ui/vault/index.ts +2 -10
- package/src/console/ui/vault/search.ts +2 -6
- package/src/console/ui/vault/types.ts +1 -1
- package/src/console/xss.gate.test.ts +1 -3
- package/src/docker/compose.ts +215 -27
- package/src/docker/derive.ts +6 -14
- package/src/docker/docker.test.ts +118 -15
- package/src/docker/dockerfile.integration.test.ts +12 -21
- package/src/docker/helpers.ts +5 -4
- package/src/docker/index.ts +9 -6
- package/src/docker/pin.ts +1 -9
- package/src/docker/recipes/index.ts +6 -6
- package/src/docker/recipes/mailpit.ts +22 -0
- package/src/docker/recipes/openbao.ts +47 -0
- package/src/docker/recipes/postgres.ts +17 -6
- package/src/docker/recipes/redis.ts +11 -2
- package/src/docker/recipes/rustfs.ts +32 -0
- package/src/docker/stack-id.test.ts +73 -5
- package/src/docker/stack-id.ts +124 -33
- package/src/docker/stack.integration.test.ts +6 -21
- package/src/docker/stack.ts +36 -4
- package/src/docker/types.ts +16 -4
- package/src/docs-origin.ts +4 -4
- package/src/drivers/ai-anthropic.ts +5 -14
- package/src/drivers/ai-mock.ts +2 -5
- package/src/drivers/ai-openai-compatible.ts +4 -10
- package/src/drivers/ai-providers.test.ts +6 -13
- package/src/drivers/bun-native-completeness.test.ts +6 -15
- package/src/drivers/channel-console.ts +6 -7
- package/src/drivers/channel-fcm.ts +20 -30
- package/src/drivers/channel-resend.ts +1 -3
- package/src/drivers/channel-smtp.ts +2 -6
- package/src/drivers/channel-types.ts +2 -12
- package/src/drivers/channel-unifonic.ts +2 -6
- package/src/drivers/channel-wa-cloud.ts +2 -6
- package/src/drivers/channel-webpush.ts +21 -60
- package/src/drivers/conformance.test.ts +2 -10
- package/src/drivers/conformance.ts +8 -21
- package/src/drivers/drizzle-dialect.test.ts +20 -0
- package/src/drivers/drizzle-dialect.ts +37 -0
- package/src/drivers/fs.ts +2 -8
- package/src/drivers/index.ts +12 -57
- package/src/drivers/memory.ts +287 -75
- package/src/drivers/pgvector.ts +7 -11
- package/src/drivers/postgres.ts +7 -13
- package/src/drivers/redis.ts +13 -37
- package/src/drivers/s3.ts +15 -18
- package/src/drivers/signal-engine.ts +12 -49
- package/src/drivers/signal-memory.ts +2 -8
- package/src/drivers/signal-nats.ts +4 -9
- package/src/drivers/signal-postgres.ts +62 -129
- package/src/drivers/signal-redis.ts +7 -21
- package/src/drivers/signal-types.ts +1 -4
- package/src/drivers/sqlite.ts +3 -12
- package/src/drivers/types.ts +4 -23
- package/src/drivers/vault-driver-removal.test.ts +55 -0
- package/src/drivers/vault-env.ts +2 -6
- package/src/drivers/vault-infisical.ts +1 -5
- package/src/drivers/vault-managed.ts +1 -5
- package/src/drivers/vault-memory.ts +1 -5
- package/src/drivers/vault-openbao.test.ts +97 -0
- package/src/drivers/vault-openbao.ts +103 -40
- package/src/drivers/vault-types.ts +3 -16
- package/src/elements/ai/declare.ts +4 -14
- package/src/elements/ai/eval.ts +2 -6
- package/src/elements/ai/pii.ts +1 -3
- package/src/elements/ai/runtime.ts +12 -50
- package/src/elements/ai/schema.ts +4 -15
- package/src/elements/ai.test.ts +13 -24
- package/src/elements/ai.ts +1 -5
- package/src/elements/channel/consent.ts +3 -12
- package/src/elements/channel/costs.ts +4 -15
- package/src/elements/channel/declare.ts +1 -4
- package/src/elements/channel/email-auth.ts +1 -4
- package/src/elements/channel/locale.ts +2 -10
- package/src/elements/channel/mask.ts +1 -3
- package/src/elements/channel/mime.ts +2 -12
- package/src/elements/channel/outcomes.test.ts +1 -5
- package/src/elements/channel/outcomes.ts +5 -15
- package/src/elements/channel/receipts.ts +2 -7
- package/src/elements/channel/runtime.ts +28 -74
- package/src/elements/channel/suppression.ts +8 -14
- package/src/elements/channel.test.ts +8 -31
- package/src/elements/channel.ts +3 -14
- package/src/elements/clock/actions.ts +6 -18
- package/src/elements/clock/declare.ts +1 -3
- package/src/elements/clock/dst.ts +1 -5
- package/src/elements/clock/durable.ts +4 -16
- package/src/elements/clock/health.ts +2 -7
- package/src/elements/clock/leader.ts +2 -9
- package/src/elements/clock/reconcile.ts +4 -15
- package/src/elements/clock/runtime.ts +2 -5
- package/src/elements/clock/schedule.ts +4 -20
- package/src/elements/clock.test.ts +2 -7
- package/src/elements/clock.ts +5 -23
- package/src/elements/gate/permissions.ts +1 -4
- package/src/elements/gate/runtime.ts +7 -28
- package/src/elements/gate.ts +1 -5
- package/src/elements/index.ts +9 -7
- package/src/elements/signal/declare.ts +2 -7
- package/src/elements/signal/reconcile.test.ts +1 -4
- package/src/elements/signal/runtime.ts +1 -3
- package/src/elements/signal.test.ts +3 -15
- package/src/elements/signal.ts +2 -8
- package/src/elements/store/cache.test.ts +46 -0
- package/src/elements/store/cache.ts +3 -11
- package/src/elements/store/classify.ts +5 -22
- package/src/elements/store/declare.ts +11 -17
- package/src/elements/store/domain-ddl.test.ts +86 -0
- package/src/elements/store/emit-drizzle.ts +363 -0
- package/src/elements/store/files-policy.test.ts +1 -5
- package/src/elements/store/files-policy.ts +4 -12
- package/src/elements/store/load-plugin-tables.ts +103 -0
- package/src/elements/store/missing-relation.test.ts +83 -0
- package/src/elements/store/missing-relation.ts +38 -0
- package/src/elements/store/replica.ts +1 -4
- package/src/elements/store/resource-list-docs.fixture.ts +56 -0
- package/src/elements/store/resource-list-docs.test.ts +79 -0
- package/src/elements/store/resource.test.ts +253 -0
- package/src/elements/store/resource.ts +786 -0
- package/src/elements/store/runtime.ts +25 -28
- package/src/elements/store/schema-decl.test.ts +227 -0
- package/src/elements/store/schema-decl.ts +516 -0
- package/src/elements/store/sql-condition.test.ts +132 -0
- package/src/elements/store/sql-condition.ts +293 -65
- package/src/elements/store/sql-session.test.ts +135 -0
- package/src/elements/store/sql-session.ts +241 -84
- package/src/elements/store/table.ts +69 -23
- package/src/elements/store.test.ts +17 -39
- package/src/elements/store.ts +53 -31
- package/src/elements/vault/chain.ts +34 -0
- package/src/elements/vault/declare.ts +22 -32
- package/src/elements/vault/fingerprint.ts +2 -7
- package/src/elements/vault/redact.ts +2 -6
- package/src/elements/vault/runtime.ts +19 -33
- package/src/elements/vault.test.ts +12 -55
- package/src/elements/vault.ts +9 -13
- package/src/index.ts +5 -2
- package/src/kernel/adopt-routes.ts +15 -29
- package/src/kernel/app.ts +92 -118
- package/src/kernel/auth-resolve.ts +2 -9
- package/src/kernel/boot-bind/ai.ts +1 -4
- package/src/kernel/boot-bind/channel.test.ts +60 -0
- package/src/kernel/boot-bind/channel.ts +61 -5
- package/src/kernel/boot-bind/clock.ts +2 -6
- package/src/kernel/boot-bind/gate.ts +2 -8
- package/src/kernel/boot-bind/runs.ts +1 -3
- package/src/kernel/boot-bind/signal.ts +3 -10
- package/src/kernel/boot-bind/store.test.ts +27 -18
- package/src/kernel/boot-bind/store.ts +93 -52
- package/src/kernel/boot-bind/vault.ts +2 -8
- package/src/kernel/boot.test.ts +4 -10
- package/src/kernel/boot.ts +30 -77
- package/src/kernel/budget.test.ts +1 -3
- package/src/kernel/capability.ts +3 -10
- package/src/kernel/dry-run.test.ts +1 -4
- package/src/kernel/dry-run.ts +3 -11
- package/src/kernel/edge.test.ts +68 -0
- package/src/kernel/effects.test.ts +1 -5
- package/src/kernel/effects.ts +4 -11
- package/src/kernel/errors.registry.test.ts +2 -8
- package/src/kernel/errors.ts +23 -32
- package/src/kernel/flow.test.ts +12 -25
- package/src/kernel/flow.ts +13 -25
- package/src/kernel/fx.test.ts +31 -40
- package/src/kernel/fx.ts +135 -90
- package/src/kernel/hook-timing.test.ts +3 -6
- package/src/kernel/hook-timing.ts +5 -14
- package/src/kernel/hooks.test.ts +43 -10
- package/src/kernel/hooks.ts +25 -12
- package/src/kernel/index.ts +11 -17
- package/src/kernel/journal.ts +7 -31
- package/src/kernel/on.ts +45 -9
- package/src/kernel/pipeline.test.ts +10 -19
- package/src/kernel/pipeline.ts +5 -17
- package/src/kernel/plug.ts +4 -11
- package/src/kernel/plugin/conflicts.test.ts +13 -25
- package/src/kernel/plugin/decorate.test.ts +8 -13
- package/src/kernel/plugin/scoping.test.ts +4 -11
- package/src/kernel/plugin.ts +81 -27
- package/src/kernel/registry-isolation.test.ts +74 -0
- package/src/kernel/registry.ts +102 -30
- package/src/kernel/router.test.ts +15 -13
- package/src/kernel/router.ts +9 -29
- package/src/kernel/routing-budget.test.ts +1 -3
- package/src/kernel/run-telemetry.ts +1 -3
- package/src/kernel/triggers.ts +63 -21
- package/src/manifest/diff.test.ts +26 -91
- package/src/manifest/diff.ts +95 -225
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/fixtures/skyport.manifest.json +1 -1
- package/src/manifest/index.ts +3 -10
- package/src/manifest/types.ts +30 -6
- package/src/manifest/undeclared.test.ts +4 -12
- package/src/manifest/undeclared.ts +1 -2
- package/src/manifest/validate.test.ts +2 -6
- package/src/manifest/validate.ts +5 -15
- package/src/mcp/authorization.ts +8 -27
- package/src/mcp/confirmation.ts +3 -10
- package/src/mcp/data.ts +2 -6
- package/src/mcp/docs-index.ts +4 -7
- package/src/mcp/docs-mcp.test.ts +3 -12
- package/src/mcp/docs-server.ts +7 -27
- package/src/mcp/docs-tools.ts +2 -6
- package/src/mcp/index.ts +1 -6
- package/src/mcp/injection.gate.test.ts +4 -18
- package/src/mcp/mcp.test.ts +18 -49
- package/src/mcp/protocol.ts +3 -10
- package/src/mcp/server.ts +11 -52
- package/src/mcp/session.ts +4 -14
- package/src/mcp/tools.ts +14 -50
- package/src/plugins/catalogue.test.ts +3 -7
- package/src/plugins/catalogue.ts +1 -3
- package/src/plugins/compression.test.ts +127 -0
- package/src/plugins/compression.ts +94 -0
- package/src/plugins/config-source.test.ts +204 -0
- package/src/plugins/config-source.ts +209 -0
- package/src/plugins/cors.test.ts +138 -0
- package/src/plugins/cors.ts +129 -0
- package/src/plugins/csrf.test.ts +102 -0
- package/src/plugins/csrf.ts +86 -0
- package/src/plugins/headers.ts +54 -0
- package/src/plugins/index.ts +26 -0
- package/src/plugins/ip-allowlist.test.ts +105 -0
- package/src/plugins/ip-allowlist.ts +76 -0
- package/src/plugins/maintenance-mode.test.ts +91 -0
- package/src/plugins/maintenance-mode.ts +85 -0
- package/src/plugins/node-import-scan.ts +2 -5
- package/src/plugins/security-headers.test.ts +243 -0
- package/src/plugins/security-headers.ts +255 -0
- package/src/plugins/supply-chain.ts +5 -17
- package/src/release/exports.ts +3 -8
- package/src/release/measure.exports.test.ts +1 -3
- package/src/release/measure.ts +16 -45
- package/src/runs/bench.test.ts +1 -3
- package/src/runs/collect.ts +8 -25
- package/src/runs/drivers/clickhouse.ts +2 -9
- package/src/runs/drivers/files.ts +9 -31
- package/src/runs/drivers/memory.ts +5 -22
- package/src/runs/drivers/postgres.ts +8 -20
- package/src/runs/duckdb.ts +2 -8
- package/src/runs/index.ts +3 -14
- package/src/runs/outlier.ts +3 -10
- package/src/runs/parquet.ts +8 -26
- package/src/runs/privacy.ts +2 -8
- package/src/runs/runs.test.ts +3 -9
- package/src/runs/runtime.ts +7 -32
- package/src/runs/shred.ts +10 -29
- package/src/runs/types.ts +1 -4
- package/src/runtime/bun.ts +4 -15
- package/src/runtime/cold-start.bench.ts +1 -3
- package/src/runtime/dev-request-log.test.ts +1 -4
- package/src/runtime/dev-request-log.ts +1 -4
- package/src/runtime/index.ts +1 -6
- package/src/runtime/primitives.ts +5 -4
- package/src/runtime/security.ts +3 -13
- package/src/runtime/serve.test.ts +4 -7
- package/src/runtime/types.ts +1 -4
- package/src/runtime/web-standard.ts +3 -15
- package/src/term.test.ts +4 -6
- package/src/term.ts +49 -98
- package/src/test/create-test-app.test.ts +4 -14
- package/src/test/create-test-app.ts +27 -33
- package/src/test/provisions.integration.test.ts +3 -11
- package/src/upgrade/codemods.test.ts +25 -6
- package/src/upgrade/codemods.ts +116 -3
- package/src/validation/standard-schema.test.ts +2 -5
- package/src/validation/standard-schema.ts +13 -33
- package/docs/spec/console.md +0 -739
- package/docs/spec/example.md +0 -1196
- package/docs/spec/four-applications.md +0 -1195
- package/docs/spec/unified-theory.md +0 -489
- package/src/cli/doc-drift.test.ts +0 -146
- package/src/cli/doc-drift.ts +0 -430
- package/src/cli/doctor-diff-examples.ts +0 -92
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
- package/src/drivers/vault-sops.ts +0 -271
package/src/drivers/memory.ts
CHANGED
|
@@ -45,38 +45,47 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
|
|
|
45
45
|
async query(sql, params = []) {
|
|
46
46
|
const text = sql.trim();
|
|
47
47
|
|
|
48
|
+
const countStar =
|
|
49
|
+
/^SELECT\s+COUNT\(\*\)\s+AS\s+"?[a-zA-Z_][a-zA-Z0-9_]*"?\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?\s*$/i.exec(
|
|
50
|
+
text,
|
|
51
|
+
);
|
|
52
|
+
if (countStar) {
|
|
53
|
+
const table = getTable(parseIdent(countStar[1]!));
|
|
54
|
+
const whereClause = countStar[2]?.trim();
|
|
55
|
+
let rows = table.rows;
|
|
56
|
+
if (whereClause) {
|
|
57
|
+
const ast = parseWhere(whereClause);
|
|
58
|
+
rows = rows.filter((r) => evalWhere(ast, r, params, { i: 0 }));
|
|
59
|
+
}
|
|
60
|
+
return [{ count: rows.length }];
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
const selectGeneric =
|
|
49
|
-
/^SELECT\s+(.+?)\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?(?:\s+ORDER\s+BY\s+(
|
|
64
|
+
/^SELECT\s+(.+?)\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?(?:\s+ORDER\s+BY\s+(.+?))?(?:\s+LIMIT\s+(\d+))?(?:\s+OFFSET\s+(\d+))?\s*$/i.exec(
|
|
50
65
|
text,
|
|
51
66
|
);
|
|
52
67
|
if (selectGeneric && !/^\s*1\s+AS\s+/i.test(selectGeneric[1]!)) {
|
|
53
68
|
const table = getTable(parseIdent(selectGeneric[2]!));
|
|
54
69
|
const selectList = selectGeneric[1]!.trim();
|
|
55
70
|
const whereClause = selectGeneric[3]?.trim();
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const limit = selectGeneric[5]
|
|
60
|
-
? Number(selectGeneric[5])
|
|
61
|
-
: undefined;
|
|
71
|
+
const orderClause = selectGeneric[4]?.trim();
|
|
72
|
+
const limit = selectGeneric[5] ? Number(selectGeneric[5]) : undefined;
|
|
73
|
+
const offset = selectGeneric[6] ? Number(selectGeneric[6]) : undefined;
|
|
62
74
|
let rows = table.rows.map((r) => ({ ...r }));
|
|
63
75
|
if (whereClause) {
|
|
64
|
-
const
|
|
65
|
-
rows = rows.filter((r) =>
|
|
66
|
-
preds.every((p, i) => compareRow(r[p.column], params[i], p.op)),
|
|
67
|
-
);
|
|
76
|
+
const ast = parseWhere(whereClause);
|
|
77
|
+
rows = rows.filter((r) => evalWhere(ast, r, params, { i: 0 }));
|
|
68
78
|
}
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
);
|
|
79
|
+
if (orderClause) {
|
|
80
|
+
const terms = parseOrderTerms(orderClause);
|
|
81
|
+
rows = [...rows].sort((a, b) => compareByTerms(a, b, terms));
|
|
73
82
|
}
|
|
83
|
+
if (offset !== undefined) rows = rows.slice(offset);
|
|
74
84
|
if (limit !== undefined) rows = rows.slice(0, limit);
|
|
75
85
|
if (selectList === "*") return rows;
|
|
76
86
|
const cols = selectList.split(",").map((part) => {
|
|
77
|
-
const as =
|
|
78
|
-
part
|
|
79
|
-
);
|
|
87
|
+
const as =
|
|
88
|
+
/^\s*("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+AS\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*$/i.exec(part);
|
|
80
89
|
if (as) {
|
|
81
90
|
return { sql: parseIdent(as[1]!), alias: parseIdent(as[2]!) };
|
|
82
91
|
}
|
|
@@ -97,9 +106,7 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
|
|
|
97
106
|
if (exists) {
|
|
98
107
|
const table = getTable(parseIdent(exists[2]!));
|
|
99
108
|
const preds = parseEqualityWhere(exists[3]!);
|
|
100
|
-
const hit = table.rows.some((r) =>
|
|
101
|
-
preds.every((p, i) => r[p] === params[i]),
|
|
102
|
-
);
|
|
109
|
+
const hit = table.rows.some((r) => preds.every((p, i) => r[p] === params[i]));
|
|
103
110
|
return hit ? [{ [parseIdent(exists[1]!)]: 1 }] : [];
|
|
104
111
|
}
|
|
105
112
|
|
|
@@ -215,18 +222,14 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
|
|
|
215
222
|
throw new Error(`memory sql: unsupported exec: ${sql}`);
|
|
216
223
|
}
|
|
217
224
|
const preds = parseEqualityWhere(updateIncAnd[4]!);
|
|
218
|
-
const row = table.rows.find((r) =>
|
|
219
|
-
preds.every((p, i) => r[p] === params[i]),
|
|
220
|
-
);
|
|
225
|
+
const row = table.rows.find((r) => preds.every((p, i) => r[p] === params[i]));
|
|
221
226
|
if (!row) return { changes: 0 };
|
|
222
227
|
row[setCol] = Number(row[setCol] ?? 0) + 1;
|
|
223
228
|
return { changes: 1 };
|
|
224
229
|
}
|
|
225
230
|
|
|
226
231
|
const updateSet =
|
|
227
|
-
/^UPDATE\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+SET\s+(.+?)\s+WHERE\s+(.+)\s*$/i.exec(
|
|
228
|
-
text,
|
|
229
|
-
);
|
|
232
|
+
/^UPDATE\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+SET\s+(.+?)\s+WHERE\s+(.+)\s*$/i.exec(text);
|
|
230
233
|
if (updateSet) {
|
|
231
234
|
const table = getTable(parseIdent(updateSet[1]!));
|
|
232
235
|
const setParts = updateSet[2]!.split(",").map((p) => p.trim());
|
|
@@ -235,12 +238,8 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
|
|
|
235
238
|
if (!m) throw new Error(`memory sql: unsupported SET: ${part}`);
|
|
236
239
|
return parseIdent(m[1]!);
|
|
237
240
|
});
|
|
238
|
-
const
|
|
239
|
-
const row = table.rows.find((r) =>
|
|
240
|
-
preds.every((p, i) =>
|
|
241
|
-
compareRow(r[p.column], params[setCols.length + i], p.op),
|
|
242
|
-
),
|
|
243
|
-
);
|
|
241
|
+
const ast = parseWhere(updateSet[3]!);
|
|
242
|
+
const row = table.rows.find((r) => evalWhere(ast, r, params, { i: setCols.length }));
|
|
244
243
|
if (!row) return { changes: 0 };
|
|
245
244
|
setCols.forEach((col, i) => {
|
|
246
245
|
row[col] = params[i];
|
|
@@ -256,60 +255,279 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
|
|
|
256
255
|
};
|
|
257
256
|
}
|
|
258
257
|
|
|
259
|
-
/**
|
|
258
|
+
/** One comparison operator for the memory SQL driver. */
|
|
259
|
+
type WhereOp =
|
|
260
|
+
| "="
|
|
261
|
+
| "<"
|
|
262
|
+
| ">"
|
|
263
|
+
| "<="
|
|
264
|
+
| ">="
|
|
265
|
+
| "!="
|
|
266
|
+
| "like"
|
|
267
|
+
| "ilike"
|
|
268
|
+
| "in"
|
|
269
|
+
| "is null"
|
|
270
|
+
| "is not null";
|
|
271
|
+
|
|
272
|
+
/** WHERE condition AST node — leaf comparison or AND/OR group. */
|
|
273
|
+
type WhereNode =
|
|
274
|
+
| { readonly kind: "cmp"; readonly column: string; readonly op: WhereOp; readonly arity: number }
|
|
275
|
+
| { readonly kind: "and"; readonly children: readonly WhereNode[] }
|
|
276
|
+
| { readonly kind: "or"; readonly children: readonly WhereNode[] };
|
|
277
|
+
|
|
278
|
+
/** One `ORDER BY` term. */
|
|
279
|
+
interface OrderTerm {
|
|
280
|
+
readonly column: string;
|
|
281
|
+
readonly direction: "ASC" | "DESC";
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Parse a WHERE clause into an AST. Supports parenthesized groups, `AND` /
|
|
286
|
+
* `OR`, binary comparisons, and `like` / `ilike` — the shapes the store
|
|
287
|
+
* session compiler emits. Anything else throws.
|
|
288
|
+
*
|
|
289
|
+
* @param clause - WHERE text (without the `WHERE` keyword)
|
|
290
|
+
*/
|
|
291
|
+
function parseWhere(clause: string): WhereNode {
|
|
292
|
+
const tokens = tokenizeWhere(clause);
|
|
293
|
+
const unsupported = (): Error => new Error(`memory sql: unsupported WHERE: ${clause}`);
|
|
294
|
+
let pos = 0;
|
|
295
|
+
|
|
296
|
+
const peek = (): string | undefined => tokens[pos];
|
|
297
|
+
const parseLevel = (keyword: "AND" | "OR", down: () => WhereNode): WhereNode => {
|
|
298
|
+
const first = down();
|
|
299
|
+
if (peek()?.toUpperCase() !== keyword) return first;
|
|
300
|
+
const rest: WhereNode[] = [];
|
|
301
|
+
do {
|
|
302
|
+
pos++;
|
|
303
|
+
rest.push(down());
|
|
304
|
+
} while (peek()?.toUpperCase() === keyword);
|
|
305
|
+
const children = [first, ...rest];
|
|
306
|
+
return keyword === "AND" ? { kind: "and", children } : { kind: "or", children };
|
|
307
|
+
};
|
|
308
|
+
const parseFactor = (): WhereNode => {
|
|
309
|
+
if (peek() === "(") {
|
|
310
|
+
pos++;
|
|
311
|
+
const node = parseLevel("OR", () => parseLevel("AND", parseFactor));
|
|
312
|
+
if (peek() !== ")") throw unsupported();
|
|
313
|
+
pos++;
|
|
314
|
+
return node;
|
|
315
|
+
}
|
|
316
|
+
const colTok = tokens[pos++];
|
|
317
|
+
const opTok = tokens[pos++];
|
|
318
|
+
if (colTok === undefined || opTok === undefined) throw unsupported();
|
|
319
|
+
if (opTok.toLowerCase() === "is") {
|
|
320
|
+
const second = tokens[pos++]?.toLowerCase();
|
|
321
|
+
const nullOp =
|
|
322
|
+
second === "null"
|
|
323
|
+
? "is null"
|
|
324
|
+
: second === "not" && tokens[pos++]?.toLowerCase() === "null"
|
|
325
|
+
? "is not null"
|
|
326
|
+
: undefined;
|
|
327
|
+
if (nullOp === undefined) throw unsupported();
|
|
328
|
+
return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op: nullOp, arity: 0 };
|
|
329
|
+
}
|
|
330
|
+
if (opTok.toLowerCase() === "in") {
|
|
331
|
+
if (peek() !== "(") throw unsupported();
|
|
332
|
+
pos++;
|
|
333
|
+
let arity = 0;
|
|
334
|
+
while (peek() === "?") {
|
|
335
|
+
arity++;
|
|
336
|
+
pos++;
|
|
337
|
+
if (peek() === ",") pos++;
|
|
338
|
+
}
|
|
339
|
+
if (arity === 0 || peek() !== ")") throw unsupported();
|
|
340
|
+
pos++;
|
|
341
|
+
return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op: "in", arity };
|
|
342
|
+
}
|
|
343
|
+
const paramTok = tokens[pos++];
|
|
344
|
+
if (paramTok !== "?") throw unsupported();
|
|
345
|
+
const op = asWhereOp(opTok);
|
|
346
|
+
if (op === undefined) throw unsupported();
|
|
347
|
+
return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op, arity: 1 };
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const node = parseLevel("OR", () => parseLevel("AND", parseFactor));
|
|
351
|
+
if (pos !== tokens.length) throw unsupported();
|
|
352
|
+
return node;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function tokenizeWhere(clause: string): string[] {
|
|
356
|
+
const out: string[] = [];
|
|
357
|
+
let i = 0;
|
|
358
|
+
while (i < clause.length) {
|
|
359
|
+
const ch = clause[i]!;
|
|
360
|
+
if (/\s/.test(ch)) {
|
|
361
|
+
i++;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
if (ch === "(" || ch === ")" || ch === "?" || ch === ",") {
|
|
365
|
+
out.push(ch);
|
|
366
|
+
i++;
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
if (ch === '"') {
|
|
370
|
+
const end = clause.indexOf('"', i + 1);
|
|
371
|
+
if (end === -1) throw new Error(`memory sql: unsupported WHERE: ${clause}`);
|
|
372
|
+
out.push(clause.slice(i, end + 1));
|
|
373
|
+
i = end + 1;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
const two = clause.slice(i, i + 2);
|
|
377
|
+
if (two === "<=" || two === ">=" || two === "<>" || two === "!=") {
|
|
378
|
+
out.push(two);
|
|
379
|
+
i += 2;
|
|
380
|
+
continue;
|
|
381
|
+
}
|
|
382
|
+
if (ch === "=" || ch === "<" || ch === ">") {
|
|
383
|
+
out.push(ch);
|
|
384
|
+
i++;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
const word = /^[a-zA-Z_][a-zA-Z0-9_]*/.exec(clause.slice(i));
|
|
388
|
+
if (word) {
|
|
389
|
+
out.push(word[0]);
|
|
390
|
+
i += word[0].length;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
throw new Error(`memory sql: unsupported WHERE: ${clause}`);
|
|
394
|
+
}
|
|
395
|
+
return out;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function asWhereOp(token: string): WhereOp | undefined {
|
|
399
|
+
switch (token.toLowerCase()) {
|
|
400
|
+
case "=":
|
|
401
|
+
return "=";
|
|
402
|
+
case "<":
|
|
403
|
+
return "<";
|
|
404
|
+
case ">":
|
|
405
|
+
return ">";
|
|
406
|
+
case "<=":
|
|
407
|
+
return "<=";
|
|
408
|
+
case ">=":
|
|
409
|
+
return ">=";
|
|
410
|
+
case "!=":
|
|
411
|
+
case "<>":
|
|
412
|
+
return "!=";
|
|
413
|
+
case "like":
|
|
414
|
+
return "like";
|
|
415
|
+
case "ilike":
|
|
416
|
+
return "ilike";
|
|
417
|
+
default:
|
|
418
|
+
return undefined;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** Evaluate a WHERE AST against a row, consuming `?` params in order. */
|
|
423
|
+
function evalWhere(
|
|
424
|
+
node: WhereNode,
|
|
425
|
+
row: SqlRow,
|
|
426
|
+
params: readonly unknown[],
|
|
427
|
+
state: { i: number },
|
|
428
|
+
): boolean {
|
|
429
|
+
if (node.kind === "and") {
|
|
430
|
+
return node.children.every((c) => evalWhere(c, row, params, state));
|
|
431
|
+
}
|
|
432
|
+
if (node.kind === "or") {
|
|
433
|
+
return node.children.some((c) => evalWhere(c, row, params, state));
|
|
434
|
+
}
|
|
435
|
+
if (node.op === "is null") {
|
|
436
|
+
return row[node.column] === null || row[node.column] === undefined;
|
|
437
|
+
}
|
|
438
|
+
if (node.op === "is not null") {
|
|
439
|
+
return row[node.column] !== null && row[node.column] !== undefined;
|
|
440
|
+
}
|
|
441
|
+
if (node.op === "in") {
|
|
442
|
+
const wants = params.slice(state.i, state.i + node.arity);
|
|
443
|
+
state.i += node.arity;
|
|
444
|
+
return wants.some((w) => compareRow(row[node.column], w, "="));
|
|
445
|
+
}
|
|
446
|
+
const want = params[state.i++];
|
|
447
|
+
return compareRow(row[node.column], want, node.op);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/** Parse `col = ? AND col2 = ?` into ordered column names (equality-only). */
|
|
260
451
|
function parseEqualityWhere(clause: string): string[] {
|
|
261
|
-
|
|
262
|
-
|
|
452
|
+
const node = parseWhere(clause);
|
|
453
|
+
const cols: string[] = [];
|
|
454
|
+
const walk = (n: WhereNode): void => {
|
|
455
|
+
if (n.kind === "and") {
|
|
456
|
+
n.children.forEach(walk);
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
if (n.kind === "or" || n.op !== "=") {
|
|
263
460
|
throw new Error(`memory sql: unsupported WHERE: ${clause}`);
|
|
264
461
|
}
|
|
265
|
-
|
|
266
|
-
}
|
|
462
|
+
cols.push(n.column);
|
|
463
|
+
};
|
|
464
|
+
walk(node);
|
|
465
|
+
return cols;
|
|
267
466
|
}
|
|
268
467
|
|
|
269
|
-
/**
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
468
|
+
/** Parse `"a" DESC, "b"` into ordered terms (default ASC). */
|
|
469
|
+
function parseOrderTerms(clause: string): OrderTerm[] {
|
|
470
|
+
return clause.split(",").map((part) => {
|
|
471
|
+
const m = /^\s*("?[a-zA-Z_][a-zA-Z0-9_]*"?)(?:\s+(ASC|DESC))?\s*$/i.exec(part);
|
|
472
|
+
if (!m) throw new Error(`memory sql: unsupported ORDER BY: ${clause}`);
|
|
473
|
+
return {
|
|
474
|
+
column: m[1]!.replaceAll('"', "").trim(),
|
|
475
|
+
direction: (m[2]?.toUpperCase() ?? "ASC") as OrderTerm["direction"],
|
|
476
|
+
};
|
|
477
|
+
});
|
|
273
478
|
}
|
|
274
479
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
480
|
+
function compareByTerms(a: SqlRow, b: SqlRow, terms: readonly OrderTerm[]): number {
|
|
481
|
+
for (const term of terms) {
|
|
482
|
+
const av = a[term.column];
|
|
483
|
+
const bv = b[term.column];
|
|
484
|
+
let cmp: number;
|
|
485
|
+
if (typeof av === "number" && typeof bv === "number") {
|
|
486
|
+
cmp = av - bv;
|
|
487
|
+
} else {
|
|
488
|
+
cmp = String(av ?? "").localeCompare(String(bv ?? ""));
|
|
489
|
+
}
|
|
490
|
+
if (cmp !== 0) return term.direction === "DESC" ? -cmp : cmp;
|
|
491
|
+
}
|
|
492
|
+
return 0;
|
|
288
493
|
}
|
|
289
494
|
|
|
290
|
-
function compareRow(
|
|
291
|
-
cell: unknown,
|
|
292
|
-
want: unknown,
|
|
293
|
-
op: WherePred["op"],
|
|
294
|
-
): boolean {
|
|
495
|
+
function compareRow(cell: unknown, want: unknown, op: WhereOp): boolean {
|
|
295
496
|
if (op === "=") return cell === want;
|
|
296
497
|
if (op === "!=") return cell !== want;
|
|
297
|
-
|
|
298
|
-
|
|
498
|
+
// sqlite parity: LIKE is case-insensitive for ASCII; ILIKE matches it.
|
|
499
|
+
if (op === "like" || op === "ilike") return likeMatch(cell, want);
|
|
500
|
+
let cmp: number;
|
|
501
|
+
if (typeof cell === "number" && typeof want === "number") {
|
|
502
|
+
cmp = cell - want;
|
|
503
|
+
} else if (typeof cell === "string" && typeof want === "string") {
|
|
504
|
+
cmp = cell.localeCompare(want);
|
|
505
|
+
} else {
|
|
506
|
+
cmp = Number(cell ?? 0) - Number(want ?? 0);
|
|
507
|
+
}
|
|
299
508
|
switch (op) {
|
|
300
509
|
case "<":
|
|
301
|
-
return
|
|
510
|
+
return cmp < 0;
|
|
302
511
|
case ">":
|
|
303
|
-
return
|
|
512
|
+
return cmp > 0;
|
|
304
513
|
case "<=":
|
|
305
|
-
return
|
|
514
|
+
return cmp <= 0;
|
|
306
515
|
case ">=":
|
|
307
|
-
return
|
|
516
|
+
return cmp >= 0;
|
|
308
517
|
default:
|
|
309
518
|
return false;
|
|
310
519
|
}
|
|
311
520
|
}
|
|
312
521
|
|
|
522
|
+
function likeMatch(cell: unknown, pattern: unknown): boolean {
|
|
523
|
+
const text = String(cell ?? "");
|
|
524
|
+
const source = String(pattern ?? "")
|
|
525
|
+
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
526
|
+
.replace(/%/g, ".*")
|
|
527
|
+
.replace(/_/g, ".");
|
|
528
|
+
return new RegExp(`^${source}$`, "i").test(text);
|
|
529
|
+
}
|
|
530
|
+
|
|
313
531
|
/** Memory SQL driver. */
|
|
314
532
|
export const memorySqlDriver: SqlDriver = {
|
|
315
533
|
id: "memory",
|
|
@@ -382,8 +600,7 @@ export const memoryFilesDriver: FilesDriver = {
|
|
|
382
600
|
return {
|
|
383
601
|
driverId: "memory",
|
|
384
602
|
async put(key, data) {
|
|
385
|
-
const bytes =
|
|
386
|
-
typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
603
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
387
604
|
objects.set(prefix + key, bytes);
|
|
388
605
|
},
|
|
389
606
|
async get(key) {
|
|
@@ -425,17 +642,12 @@ export const memoryIndexDriver: IndexDriver = {
|
|
|
425
642
|
id: "memory",
|
|
426
643
|
facet: "index",
|
|
427
644
|
async open(options: IndexOpenOptions): Promise<IndexStore> {
|
|
428
|
-
const docs = new Map<
|
|
429
|
-
string,
|
|
430
|
-
{ vector: number[]; meta?: Record<string, unknown> }
|
|
431
|
-
>();
|
|
645
|
+
const docs = new Map<string, { vector: number[]; meta?: Record<string, unknown> }>();
|
|
432
646
|
return {
|
|
433
647
|
driverId: "memory",
|
|
434
648
|
async upsert(id, vector, meta) {
|
|
435
649
|
if (vector.length !== options.dims) {
|
|
436
|
-
throw new Error(
|
|
437
|
-
`vector dims ${vector.length} !== index dims ${options.dims}`,
|
|
438
|
-
);
|
|
650
|
+
throw new Error(`vector dims ${vector.length} !== index dims ${options.dims}`);
|
|
439
651
|
}
|
|
440
652
|
docs.set(id, { vector: [...vector], meta });
|
|
441
653
|
},
|
package/src/drivers/pgvector.ts
CHANGED
|
@@ -18,9 +18,7 @@ import type {
|
|
|
18
18
|
*
|
|
19
19
|
* @param options - Name / dims / SQL connection
|
|
20
20
|
*/
|
|
21
|
-
export async function openPgvectorIndex(
|
|
22
|
-
options: IndexOpenOptions,
|
|
23
|
-
): Promise<IndexStore> {
|
|
21
|
+
export async function openPgvectorIndex(options: IndexOpenOptions): Promise<IndexStore> {
|
|
24
22
|
if (options.sql) {
|
|
25
23
|
return openPgvectorSql(options.name, options.dims, options.sql);
|
|
26
24
|
}
|
|
@@ -45,10 +43,11 @@ async function openPgvectorSql(
|
|
|
45
43
|
throw new Error(`vector dims ${vector.length} !== index dims ${dims}`);
|
|
46
44
|
}
|
|
47
45
|
await sql.exec(`DELETE FROM "${table}" WHERE id = ?`, [id]);
|
|
48
|
-
await sql.exec(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
await sql.exec(`INSERT INTO "${table}" (id, embedding, meta) VALUES (?, ?, ?)`, [
|
|
47
|
+
id,
|
|
48
|
+
JSON.stringify(vector),
|
|
49
|
+
meta ? JSON.stringify(meta) : null,
|
|
50
|
+
]);
|
|
52
51
|
},
|
|
53
52
|
async search(vector, topK = 10): Promise<IndexHit[]> {
|
|
54
53
|
const rows = await sql.query(`SELECT id, embedding, meta FROM "${table}"`);
|
|
@@ -78,10 +77,7 @@ async function openPgvectorSql(
|
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
function openPgvectorMemory(dims: number): IndexStore {
|
|
81
|
-
const docs = new Map<
|
|
82
|
-
string,
|
|
83
|
-
{ vector: number[]; meta?: Record<string, unknown> }
|
|
84
|
-
>();
|
|
80
|
+
const docs = new Map<string, { vector: number[]; meta?: Record<string, unknown> }>();
|
|
85
81
|
return {
|
|
86
82
|
driverId: "pgvector",
|
|
87
83
|
async upsert(id, vector, meta) {
|
package/src/drivers/postgres.ts
CHANGED
|
@@ -4,16 +4,14 @@
|
|
|
4
4
|
* Protocol-named: Neon, Supabase, RDS, Timescale all speak postgres.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
8
|
-
SqlConnectOptions,
|
|
9
|
-
SqlConnection,
|
|
10
|
-
SqlDriver,
|
|
11
|
-
SqlRow,
|
|
12
|
-
} from "./types.ts";
|
|
7
|
+
import type { SqlConnectOptions, SqlConnection, SqlDriver, SqlRow } from "./types.ts";
|
|
13
8
|
|
|
14
9
|
/** Minimal surface we use from Bun.SQL (and test fakes). */
|
|
15
10
|
export interface PostgresClientLike {
|
|
16
|
-
unsafe(
|
|
11
|
+
unsafe(
|
|
12
|
+
sql: string,
|
|
13
|
+
values?: unknown[],
|
|
14
|
+
): PromiseLike<SqlRow[] | { length: number; changes?: number } | SqlRow[]>;
|
|
17
15
|
close?(options?: { timeout?: number }): Promise<void>;
|
|
18
16
|
}
|
|
19
17
|
|
|
@@ -32,9 +30,7 @@ export function toPostgresParams(sql: string): string {
|
|
|
32
30
|
*
|
|
33
31
|
* @param options - URL / role / injected client
|
|
34
32
|
*/
|
|
35
|
-
export async function connectPostgres(
|
|
36
|
-
options: SqlConnectOptions = {},
|
|
37
|
-
): Promise<SqlConnection> {
|
|
33
|
+
export async function connectPostgres(options: SqlConnectOptions = {}): Promise<SqlConnection> {
|
|
38
34
|
const role = options.role ?? "primary";
|
|
39
35
|
const client =
|
|
40
36
|
(options.client as PostgresClientLike | undefined) ??
|
|
@@ -121,9 +117,7 @@ export function createPostgresFakeClient(): PostgresClientLike & {
|
|
|
121
117
|
if (exists) {
|
|
122
118
|
const rows = tables.get(parseIdent(exists[2]!)) ?? [];
|
|
123
119
|
const preds = parseEqualityWhere(exists[3]!);
|
|
124
|
-
const hit = rows.some((r) =>
|
|
125
|
-
preds.every((p, i) => r[p] === values[i]),
|
|
126
|
-
);
|
|
120
|
+
const hit = rows.some((r) => preds.every((p, i) => r[p] === values[i]));
|
|
127
121
|
return hit ? [{ [parseIdent(exists[1]!)]: 1 }] : [];
|
|
128
122
|
}
|
|
129
123
|
|
package/src/drivers/redis.ts
CHANGED
|
@@ -5,24 +5,15 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { LuaKvStore } from "./kv-lua.ts";
|
|
8
|
-
import type {
|
|
9
|
-
KvClientLike,
|
|
10
|
-
KvDriver,
|
|
11
|
-
KvNamespace,
|
|
12
|
-
KvOpenOptions,
|
|
13
|
-
} from "./types.ts";
|
|
8
|
+
import type { KvClientLike, KvDriver, KvNamespace, KvOpenOptions } from "./types.ts";
|
|
14
9
|
|
|
15
10
|
/**
|
|
16
11
|
* Open a KV namespace over the redis protocol.
|
|
17
12
|
*
|
|
18
13
|
* @param options - Name / URL / injected client
|
|
19
14
|
*/
|
|
20
|
-
export async function openRedisKv(
|
|
21
|
-
|
|
22
|
-
): Promise<KvNamespace> {
|
|
23
|
-
const client: KvClientLike =
|
|
24
|
-
options.client ??
|
|
25
|
-
createBunRedisClient(options.url);
|
|
15
|
+
export async function openRedisKv(options: KvOpenOptions): Promise<KvNamespace> {
|
|
16
|
+
const client: KvClientLike = options.client ?? createBunRedisClient(options.url);
|
|
26
17
|
|
|
27
18
|
const prefix = `oke:kv:${options.name}:`;
|
|
28
19
|
|
|
@@ -39,8 +30,7 @@ export async function openRedisKv(
|
|
|
39
30
|
},
|
|
40
31
|
async set(key, value, ttl) {
|
|
41
32
|
const payload = JSON.stringify(value);
|
|
42
|
-
const ex =
|
|
43
|
-
ttl !== undefined ? Math.max(1, Math.ceil(ttlToSeconds(ttl))) : undefined;
|
|
33
|
+
const ex = ttl !== undefined ? Math.max(1, Math.ceil(ttlToSeconds(ttl))) : undefined;
|
|
44
34
|
if (ex !== undefined) {
|
|
45
35
|
await client.set(prefix + key, payload, { ex });
|
|
46
36
|
} else {
|
|
@@ -70,11 +60,7 @@ export async function openRedisKv(
|
|
|
70
60
|
return (await client.eval(script, prefixed.length, ...keysAndArgs)) as T;
|
|
71
61
|
}
|
|
72
62
|
if (client.send) {
|
|
73
|
-
return (await client.send("EVAL", [
|
|
74
|
-
script,
|
|
75
|
-
String(prefixed.length),
|
|
76
|
-
...keysAndArgs,
|
|
77
|
-
])) as T;
|
|
63
|
+
return (await client.send("EVAL", [script, String(prefixed.length), ...keysAndArgs])) as T;
|
|
78
64
|
}
|
|
79
65
|
throw new Error("redis kv.eval: client lacks eval/send");
|
|
80
66
|
},
|
|
@@ -90,10 +76,7 @@ export async function openRedisKv(
|
|
|
90
76
|
* @param client - Redis-like client
|
|
91
77
|
* @param match - MATCH pattern
|
|
92
78
|
*/
|
|
93
|
-
async function scanAll(
|
|
94
|
-
client: KvClientLike,
|
|
95
|
-
match: string,
|
|
96
|
-
): Promise<string[]> {
|
|
79
|
+
async function scanAll(client: KvClientLike, match: string): Promise<string[]> {
|
|
97
80
|
if (client.scan) {
|
|
98
81
|
const out: string[] = [];
|
|
99
82
|
let cursor = "0";
|
|
@@ -111,13 +94,10 @@ async function scanAll(
|
|
|
111
94
|
const out: string[] = [];
|
|
112
95
|
let cursor = "0";
|
|
113
96
|
do {
|
|
114
|
-
const reply = (await client.send("SCAN", [
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
"COUNT",
|
|
119
|
-
"100",
|
|
120
|
-
])) as [string, string[]];
|
|
97
|
+
const reply = (await client.send("SCAN", [cursor, "MATCH", match, "COUNT", "100"])) as [
|
|
98
|
+
string,
|
|
99
|
+
string[],
|
|
100
|
+
];
|
|
121
101
|
const next = String(reply[0]);
|
|
122
102
|
const batch = reply[1] ?? [];
|
|
123
103
|
out.push(...batch);
|
|
@@ -125,9 +105,7 @@ async function scanAll(
|
|
|
125
105
|
} while (cursor !== "0");
|
|
126
106
|
return out;
|
|
127
107
|
}
|
|
128
|
-
throw new Error(
|
|
129
|
-
"redis kv.list: client lacks SCAN — key browse refused rather than KEYS *",
|
|
130
|
-
);
|
|
108
|
+
throw new Error("redis kv.list: client lacks SCAN — key browse refused rather than KEYS *");
|
|
131
109
|
}
|
|
132
110
|
|
|
133
111
|
function ttlToSeconds(ttl: string): number {
|
|
@@ -159,8 +137,7 @@ function ttlToSeconds(ttl: string): number {
|
|
|
159
137
|
* @param url - Optional Redis URL
|
|
160
138
|
*/
|
|
161
139
|
export function createBunRedisClient(url?: string): KvClientLike {
|
|
162
|
-
const redis =
|
|
163
|
-
url !== undefined ? new Bun.RedisClient(url) : Bun.redis;
|
|
140
|
+
const redis = url !== undefined ? new Bun.RedisClient(url) : Bun.redis;
|
|
164
141
|
|
|
165
142
|
return {
|
|
166
143
|
get: (key) => redis.get(key),
|
|
@@ -224,8 +201,7 @@ export function createRedisFakeClient(nowMs?: () => number): KvClientLike & {
|
|
|
224
201
|
},
|
|
225
202
|
async scan(cursor, opts) {
|
|
226
203
|
const match = opts?.match ?? "*";
|
|
227
|
-
const prefix =
|
|
228
|
-
match.endsWith("*") ? match.slice(0, -1) : match;
|
|
204
|
+
const prefix = match.endsWith("*") ? match.slice(0, -1) : match;
|
|
229
205
|
const all = [...data.keys()].filter((k) =>
|
|
230
206
|
match.endsWith("*") ? k.startsWith(prefix) : k === match,
|
|
231
207
|
);
|