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/kernel/flow.ts
CHANGED
|
@@ -7,20 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { Effects, FlowPlane, Slo } from "../manifest/types.ts";
|
|
10
|
-
import type {
|
|
11
|
-
InferSchemaOutput,
|
|
12
|
-
SchemaInput,
|
|
13
|
-
} from "../validation/standard-schema.ts";
|
|
10
|
+
import type { InferSchemaOutput, SchemaInput } from "../validation/standard-schema.ts";
|
|
14
11
|
import type { FlowFailure } from "./errors.ts";
|
|
15
12
|
import type { Fx } from "./fx.ts";
|
|
16
13
|
import type { HookFn, HookStage } from "./hooks.ts";
|
|
17
14
|
import type { PluginDef } from "./plugin.ts";
|
|
18
15
|
import type { Trigger } from "./triggers.ts";
|
|
19
16
|
|
|
20
|
-
export type {
|
|
21
|
-
SchemaInput,
|
|
22
|
-
StandardSchemaV1,
|
|
23
|
-
} from "../validation/standard-schema.ts";
|
|
17
|
+
export type { SchemaInput, StandardSchemaV1 } from "../validation/standard-schema.ts";
|
|
24
18
|
|
|
25
19
|
/** Result of a Standard Schema validate call (re-export shape). */
|
|
26
20
|
export type StandardSchemaResult<Output> =
|
|
@@ -42,11 +36,7 @@ export type FlowHandler<I = unknown, O = unknown> = (
|
|
|
42
36
|
) => O | FlowFailure | Promise<O | FlowFailure>;
|
|
43
37
|
|
|
44
38
|
/** Options for {@link flow}. */
|
|
45
|
-
export interface FlowOptions<
|
|
46
|
-
I = unknown,
|
|
47
|
-
O = unknown,
|
|
48
|
-
E extends FlowErrorMap = FlowErrorMap,
|
|
49
|
-
> {
|
|
39
|
+
export interface FlowOptions<I = unknown, O = unknown, E extends FlowErrorMap = FlowErrorMap> {
|
|
50
40
|
/** Optional stable name (used by `fx.call` and the Manifest). */
|
|
51
41
|
readonly name?: string;
|
|
52
42
|
/** Optional unit scope for unit-level hooks. */
|
|
@@ -72,6 +62,11 @@ export interface FlowOptions<
|
|
|
72
62
|
* Cross-plane invocation is a compile error.
|
|
73
63
|
*/
|
|
74
64
|
readonly plane?: FlowPlane;
|
|
65
|
+
/**
|
|
66
|
+
* Acknowledge intentional Manifest contract breaks for this flow
|
|
67
|
+
* (`oke doctor --diff` / CI gate).
|
|
68
|
+
*/
|
|
69
|
+
readonly breaking?: boolean;
|
|
75
70
|
/** The behavior. */
|
|
76
71
|
readonly do: FlowHandler<I, O>;
|
|
77
72
|
}
|
|
@@ -160,6 +155,8 @@ export interface FlowDef<
|
|
|
160
155
|
readonly slo: Slo | undefined;
|
|
161
156
|
/** Plane (user vs operator). */
|
|
162
157
|
readonly plane: FlowPlane | undefined;
|
|
158
|
+
/** Intentional contract-break acknowledgement for Manifest Diff. */
|
|
159
|
+
readonly breaking: boolean;
|
|
163
160
|
/** Handler body. */
|
|
164
161
|
readonly do: FlowHandler<I, O>;
|
|
165
162
|
/** Triggers bound via {@link on} (zero or more). */
|
|
@@ -192,13 +189,7 @@ export interface FlowDef<
|
|
|
192
189
|
*/
|
|
193
190
|
plug<P extends PluginDef>(
|
|
194
191
|
pluginDef: P,
|
|
195
|
-
): FlowDef<
|
|
196
|
-
I,
|
|
197
|
-
O,
|
|
198
|
-
E,
|
|
199
|
-
D & (P extends PluginDef<infer PD> ? PD : Record<string, never>),
|
|
200
|
-
T
|
|
201
|
-
>;
|
|
192
|
+
): FlowDef<I, O, E, D & (P extends PluginDef<infer PD> ? PD : Record<string, never>), T>;
|
|
202
193
|
}
|
|
203
194
|
|
|
204
195
|
/** Unique brand symbol for {@link FlowDef}. */
|
|
@@ -222,11 +213,7 @@ export function flow<Opts extends FlowOptions<any, any, any>>(
|
|
|
222
213
|
const hooks: Partial<Record<HookStage, HookFn[]>> = {};
|
|
223
214
|
const pendingPlugins: PluginDef[] = [];
|
|
224
215
|
|
|
225
|
-
const def: FlowDef<
|
|
226
|
-
InferFlowIn<Opts>,
|
|
227
|
-
InferFlowOut<Opts>,
|
|
228
|
-
InferFlowErrors<Opts>
|
|
229
|
-
> = {
|
|
216
|
+
const def: FlowDef<InferFlowIn<Opts>, InferFlowOut<Opts>, InferFlowErrors<Opts>> = {
|
|
230
217
|
[flowBrand]: true,
|
|
231
218
|
name,
|
|
232
219
|
unit: options.unit,
|
|
@@ -239,6 +226,7 @@ export function flow<Opts extends FlowOptions<any, any, any>>(
|
|
|
239
226
|
cache: options.cache,
|
|
240
227
|
slo: options.slo,
|
|
241
228
|
plane: options.plane,
|
|
229
|
+
breaking: options.breaking ?? false,
|
|
242
230
|
do: options.do as FlowHandler<InferFlowIn<Opts>, InferFlowOut<Opts>>,
|
|
243
231
|
triggers,
|
|
244
232
|
$trigger: undefined,
|
package/src/kernel/fx.test.ts
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
import { createCapabilityToken } from "./capability.ts";
|
|
3
3
|
import { createEffectLedger, reversibilityOf } from "./effects.ts";
|
|
4
|
-
import {
|
|
5
|
-
fail,
|
|
6
|
-
formatOkeMessage,
|
|
7
|
-
lookupOkeError,
|
|
8
|
-
OKE_ERRORS,
|
|
9
|
-
OkeError,
|
|
10
|
-
} from "./errors.ts";
|
|
4
|
+
import { fail, formatOkeMessage, lookupOkeError, OKE_ERRORS, OkeError } from "./errors.ts";
|
|
11
5
|
import {
|
|
12
6
|
createFx,
|
|
13
7
|
createFxContext,
|
|
8
|
+
jsonResultBrand,
|
|
14
9
|
type Fx,
|
|
15
10
|
type FxStubStoreHandle,
|
|
16
11
|
} from "./fx.ts";
|
|
@@ -37,16 +32,10 @@ describe("fx — capability enforcement", () => {
|
|
|
37
32
|
expect(err).toBeInstanceOf(OkeError);
|
|
38
33
|
const oke = err as OkeError;
|
|
39
34
|
expect(oke.code).toBe(1001);
|
|
40
|
-
expect(oke.causeText).toBe(
|
|
41
|
-
|
|
42
|
-
);
|
|
43
|
-
expect(oke.
|
|
44
|
-
'Add "sql:users" to this flow\'s effects.reads.',
|
|
45
|
-
);
|
|
46
|
-
expect(oke.docsUrl).toBe("https://okengine.vercel.app/e/1001");
|
|
47
|
-
expect(oke.message).toBe(
|
|
48
|
-
formatOkeMessage(1001, oke.causeText, oke.fix, oke.docsUrl),
|
|
49
|
-
);
|
|
35
|
+
expect(oke.causeText).toBe('Flow "bookings.create" reads "sql:users" without declaring it.');
|
|
36
|
+
expect(oke.fix).toBe('Add "sql:users" to this flow\'s effects.reads.');
|
|
37
|
+
expect(oke.docsUrl).toBe("https://oke.omqkhafi.dev/e/1001");
|
|
38
|
+
expect(oke.message).toBe(formatOkeMessage(1001, oke.causeText, oke.fix, oke.docsUrl));
|
|
50
39
|
});
|
|
51
40
|
|
|
52
41
|
test("declared store read succeeds", async () => {
|
|
@@ -79,21 +68,13 @@ describe("fx — effect ledger", () => {
|
|
|
79
68
|
await fx.emit("order-placed", { orderId: "o1" });
|
|
80
69
|
|
|
81
70
|
expect(ledger.entries).toHaveLength(3);
|
|
82
|
-
expect(ledger.entries.map((e) => e.kind)).toEqual([
|
|
83
|
-
"read",
|
|
84
|
-
"write",
|
|
85
|
-
"emit",
|
|
86
|
-
]);
|
|
71
|
+
expect(ledger.entries.map((e) => e.kind)).toEqual(["read", "write", "emit"]);
|
|
87
72
|
expect(ledger.entries.map((e) => e.resource)).toEqual([
|
|
88
73
|
"sql:bookings",
|
|
89
74
|
"sql:bookings",
|
|
90
75
|
"order-placed",
|
|
91
76
|
]);
|
|
92
|
-
expect(ledger.entries.map((e) => e.reversibility)).toEqual([
|
|
93
|
-
"none",
|
|
94
|
-
"reversible",
|
|
95
|
-
"deferred",
|
|
96
|
-
]);
|
|
77
|
+
expect(ledger.entries.map((e) => e.reversibility)).toEqual(["none", "reversible", "deferred"]);
|
|
97
78
|
});
|
|
98
79
|
|
|
99
80
|
test("all seven kinds receive the correct reversibility tier via fx", async () => {
|
|
@@ -123,15 +104,7 @@ describe("fx — effect ledger", () => {
|
|
|
123
104
|
|
|
124
105
|
expect(ledger.entries).toHaveLength(7);
|
|
125
106
|
const kinds = ledger.entries.map((e) => e.kind);
|
|
126
|
-
expect(kinds).toEqual([
|
|
127
|
-
"read",
|
|
128
|
-
"write",
|
|
129
|
-
"emit",
|
|
130
|
-
"send",
|
|
131
|
-
"ask",
|
|
132
|
-
"secret",
|
|
133
|
-
"call",
|
|
134
|
-
]);
|
|
107
|
+
expect(kinds).toEqual(["read", "write", "emit", "send", "ask", "secret", "call"]);
|
|
135
108
|
for (const entry of ledger.entries) {
|
|
136
109
|
expect(entry.reversibility).toBe(reversibilityOf(entry.kind));
|
|
137
110
|
}
|
|
@@ -191,6 +164,20 @@ describe("fx — wholesale swap", () => {
|
|
|
191
164
|
operator: { id: null },
|
|
192
165
|
tenant: { id: "t1" },
|
|
193
166
|
fail,
|
|
167
|
+
json: {
|
|
168
|
+
ok(value, opts) {
|
|
169
|
+
return { [jsonResultBrand]: true, status: 200, value, meta: opts?.meta };
|
|
170
|
+
},
|
|
171
|
+
create(value) {
|
|
172
|
+
return { [jsonResultBrand]: true, status: 201, value };
|
|
173
|
+
},
|
|
174
|
+
empty() {
|
|
175
|
+
return { [jsonResultBrand]: true, status: 204 };
|
|
176
|
+
},
|
|
177
|
+
with(data, meta) {
|
|
178
|
+
return { [jsonResultBrand]: true, status: 200, value: data, meta };
|
|
179
|
+
},
|
|
180
|
+
},
|
|
194
181
|
async step(_name, fn) {
|
|
195
182
|
return fn();
|
|
196
183
|
},
|
|
@@ -218,15 +205,19 @@ describe("errors — registry", () => {
|
|
|
218
205
|
});
|
|
219
206
|
expect(err.message).toContain("OKE1042");
|
|
220
207
|
expect(err.message).toContain("no subscriber");
|
|
221
|
-
expect(err.message).toContain("https://
|
|
208
|
+
expect(err.message).toContain("https://oke.omqkhafi.dev/e/1042");
|
|
222
209
|
expect(err.message).toContain("→");
|
|
223
210
|
});
|
|
224
211
|
|
|
225
212
|
test("fx.fail returns a value, not an exception", () => {
|
|
226
213
|
const fx = createFx({ flow: "x", effects: {} });
|
|
227
|
-
const result = fx.fail(
|
|
228
|
-
|
|
229
|
-
|
|
214
|
+
const result = fx.fail(
|
|
215
|
+
"FlightFull",
|
|
216
|
+
{ seatsLeft: 0 },
|
|
217
|
+
{
|
|
218
|
+
message: "full",
|
|
219
|
+
},
|
|
220
|
+
);
|
|
230
221
|
expect(result).toEqual({
|
|
231
222
|
data: null,
|
|
232
223
|
error: { code: "FlightFull", data: { seatsLeft: 0 }, message: "full" },
|
package/src/kernel/fx.ts
CHANGED
|
@@ -11,26 +11,20 @@
|
|
|
11
11
|
|
|
12
12
|
import type { Effects, ResourceRef } from "../manifest/types.ts";
|
|
13
13
|
import type {
|
|
14
|
+
SelectOrderBuilder,
|
|
14
15
|
StoreDecl,
|
|
15
16
|
StoreHandle,
|
|
16
17
|
StoreRuntime,
|
|
17
18
|
SqlStoreHandle,
|
|
18
19
|
} from "../elements/store.ts";
|
|
20
|
+
import type { SqlRow } from "../drivers/types.ts";
|
|
19
21
|
import type { SignalRuntime } from "../elements/signal.ts";
|
|
20
22
|
import type { VaultRuntime } from "../elements/vault.ts";
|
|
21
23
|
import type { ChannelRuntime } from "../elements/channel.ts";
|
|
22
24
|
import type { AiRuntime } from "../elements/ai.ts";
|
|
23
25
|
import { parseDurationMs } from "../elements/clock/duration.ts";
|
|
24
|
-
import {
|
|
25
|
-
|
|
26
|
-
type CapabilityToken,
|
|
27
|
-
} from "./capability.ts";
|
|
28
|
-
import {
|
|
29
|
-
createEffectLedger,
|
|
30
|
-
recordEffect,
|
|
31
|
-
reversibilityOf,
|
|
32
|
-
type EffectLedger,
|
|
33
|
-
} from "./effects.ts";
|
|
26
|
+
import { createCapabilityToken, type CapabilityToken } from "./capability.ts";
|
|
27
|
+
import { createEffectLedger, recordEffect, reversibilityOf, type EffectLedger } from "./effects.ts";
|
|
34
28
|
import {
|
|
35
29
|
DryRunWriteIsolationError,
|
|
36
30
|
isDryRun,
|
|
@@ -196,23 +190,55 @@ export interface FxSearchOptions {
|
|
|
196
190
|
readonly topK?: number;
|
|
197
191
|
}
|
|
198
192
|
|
|
193
|
+
/** Brand for {@link JsonResult} (kept internal — flows never construct it). */
|
|
194
|
+
export const jsonResultBrand: unique symbol = Symbol.for("oke.json");
|
|
195
|
+
|
|
196
|
+
/** Carrier from {@link FxJson} — status + body read by the response encoder. */
|
|
197
|
+
export interface JsonResult<T = unknown> {
|
|
198
|
+
readonly [jsonResultBrand]: true;
|
|
199
|
+
readonly status: number;
|
|
200
|
+
readonly value?: T;
|
|
201
|
+
readonly meta?: Record<string, unknown>;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** True when `value` is an {@link FxJson} carrier. */
|
|
205
|
+
export function isJsonResult(value: unknown): value is JsonResult {
|
|
206
|
+
return (
|
|
207
|
+
typeof value === "object" && value !== null && (value as JsonResult)[jsonResultBrand] === true
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* JSON response helpers. `fx.json.create` answers 201; `fx.json.ok` can carry
|
|
213
|
+
* a top-level `meta` (Stripe-style `{ data, meta?, error }`);
|
|
214
|
+
* `fx.json.empty` answers 204.
|
|
215
|
+
*/
|
|
216
|
+
export interface FxJson {
|
|
217
|
+
/** 200 — body `{ data: value, meta?, error: null }`. */
|
|
218
|
+
ok<T>(value: T, opts?: { readonly meta?: Record<string, unknown> }): JsonResult<T>;
|
|
219
|
+
/** 201 — body `{ data: value, error: null }`. */
|
|
220
|
+
create<T>(value: T): JsonResult<T>;
|
|
221
|
+
/** 204 — no body. */
|
|
222
|
+
empty(): JsonResult<never>;
|
|
223
|
+
/** 200 — body `{ data, meta, error: null }` (paginated lists). */
|
|
224
|
+
with<T>(data: T, meta: Record<string, unknown>): JsonResult<T>;
|
|
225
|
+
}
|
|
226
|
+
|
|
199
227
|
/**
|
|
200
228
|
* The `fx` context object — v1 surface.
|
|
201
229
|
*
|
|
202
230
|
* Implementations must be plain objects so tests can replace `fx` wholesale.
|
|
203
231
|
*/
|
|
204
232
|
export interface Fx {
|
|
205
|
-
/**
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
store(
|
|
214
|
-
ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl,
|
|
215
|
-
): FxStoreHandle;
|
|
233
|
+
/**
|
|
234
|
+
* Open a store handle for `ref` (capability checked on each op).
|
|
235
|
+
*
|
|
236
|
+
* When a {@link CreateFxOptions.storeRuntime} is bound and `ref` is a
|
|
237
|
+
* registered store declaration, returns the driver-backed handle.
|
|
238
|
+
*
|
|
239
|
+
* @param ref - Store resource ref, named handle, or store declaration
|
|
240
|
+
*/
|
|
241
|
+
store(ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl): FxStoreHandle;
|
|
216
242
|
/**
|
|
217
243
|
* Emit a signal (records `emit`).
|
|
218
244
|
*
|
|
@@ -251,11 +277,7 @@ export interface Fx {
|
|
|
251
277
|
* @param input - Prompt input
|
|
252
278
|
* @param opts - Model routing opts
|
|
253
279
|
*/
|
|
254
|
-
ask(
|
|
255
|
-
prompt: NamedRef,
|
|
256
|
-
input?: unknown,
|
|
257
|
-
opts?: FxAskOptions,
|
|
258
|
-
): Promise<Record<string, unknown>>;
|
|
280
|
+
ask(prompt: NamedRef, input?: unknown, opts?: FxAskOptions): Promise<Record<string, unknown>>;
|
|
259
281
|
/**
|
|
260
282
|
* Similarity search over an index/embed (records `read` on the embed ref).
|
|
261
283
|
*
|
|
@@ -263,21 +285,14 @@ export interface Fx {
|
|
|
263
285
|
* @param query - Query text or vector
|
|
264
286
|
* @param opts - Search options
|
|
265
287
|
*/
|
|
266
|
-
search(
|
|
267
|
-
embed: NamedRef,
|
|
268
|
-
query: unknown,
|
|
269
|
-
opts?: FxSearchOptions,
|
|
270
|
-
): Promise<unknown[]>;
|
|
288
|
+
search(embed: NamedRef, query: unknown, opts?: FxSearchOptions): Promise<unknown[]>;
|
|
271
289
|
/**
|
|
272
290
|
* Run a bounded AI agent (records `ask`).
|
|
273
291
|
*
|
|
274
292
|
* @param agent - Agent name or handle
|
|
275
293
|
* @param input - Agent input (`{ message }` or string)
|
|
276
294
|
*/
|
|
277
|
-
run(
|
|
278
|
-
agent: NamedRef,
|
|
279
|
-
input?: unknown,
|
|
280
|
-
): Promise<unknown>;
|
|
295
|
+
run(agent: NamedRef, input?: unknown): Promise<unknown>;
|
|
281
296
|
/**
|
|
282
297
|
* Stream model tokens (records `ask`). Returns an async iterable of chunks.
|
|
283
298
|
*
|
|
@@ -313,6 +328,8 @@ export interface Fx {
|
|
|
313
328
|
* @param opts - Optional message
|
|
314
329
|
*/
|
|
315
330
|
fail<E>(code: string, data: E, opts?: FailOptions): FlowFailure<E>;
|
|
331
|
+
/** JSON response helpers (status + Stripe-style envelope). */
|
|
332
|
+
readonly json: FxJson;
|
|
316
333
|
/**
|
|
317
334
|
* Named durable step — never re-runs on journal replay.
|
|
318
335
|
*
|
|
@@ -326,10 +343,7 @@ export interface Fx {
|
|
|
326
343
|
* Dispatch target for {@link Fx.call}. Wired by the app so untriggered
|
|
327
344
|
* flows execute through the same pipeline as triggered ones.
|
|
328
345
|
*/
|
|
329
|
-
export type FxCallHandler = (
|
|
330
|
-
name: string,
|
|
331
|
-
input: unknown,
|
|
332
|
-
) => Promise<unknown>;
|
|
346
|
+
export type FxCallHandler = (name: string, input: unknown) => Promise<unknown>;
|
|
333
347
|
|
|
334
348
|
/** Options for {@link createFx}. */
|
|
335
349
|
export interface CreateFxOptions {
|
|
@@ -352,9 +366,7 @@ export interface CreateFxOptions {
|
|
|
352
366
|
/** Secret name → value map for `fx.vault`. */
|
|
353
367
|
readonly secrets?: Readonly<Record<string, string>>;
|
|
354
368
|
/** Seed data for in-memory stores: ref → key → value. */
|
|
355
|
-
readonly storeData?: Readonly<
|
|
356
|
-
Record<string, Readonly<Record<string, unknown>>>
|
|
357
|
-
>;
|
|
369
|
+
readonly storeData?: Readonly<Record<string, Readonly<Record<string, unknown>>>>;
|
|
358
370
|
/** Optional log sink (defaults to no-op). */
|
|
359
371
|
readonly onLog?: (
|
|
360
372
|
level: "debug" | "info" | "warn" | "error",
|
|
@@ -435,9 +447,7 @@ export function createFx(options: CreateFxOptions): Fx {
|
|
|
435
447
|
*/
|
|
436
448
|
export function createFxContext(options: CreateFxOptions): FxContext {
|
|
437
449
|
const ledger = options.ledger ?? createEffectLedger();
|
|
438
|
-
const capability =
|
|
439
|
-
options.capability ??
|
|
440
|
-
createCapabilityToken(options.flow, options.effects);
|
|
450
|
+
const capability = options.capability ?? createCapabilityToken(options.flow, options.effects);
|
|
441
451
|
const now = options.now ?? (() => Date.now());
|
|
442
452
|
const secrets = options.secrets ?? {};
|
|
443
453
|
const onLog = options.onLog;
|
|
@@ -499,15 +509,12 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
499
509
|
select(): Promise<unknown[]> {
|
|
500
510
|
return gated("read", ref, () => {
|
|
501
511
|
const values = [...table().values()];
|
|
502
|
-
return isDryRun()
|
|
503
|
-
? values.map((v) => structuredClone(v))
|
|
504
|
-
: values;
|
|
512
|
+
return isDryRun() ? values.map((v) => structuredClone(v)) : values;
|
|
505
513
|
});
|
|
506
514
|
},
|
|
507
515
|
insert(row: Record<string, unknown>): Promise<{ id: string }> {
|
|
508
516
|
return gated("write", ref, () => {
|
|
509
|
-
const id =
|
|
510
|
-
typeof row.id === "string" ? row.id : crypto.randomUUID();
|
|
517
|
+
const id = typeof row.id === "string" ? row.id : crypto.randomUUID();
|
|
511
518
|
table().set(id, { ...row, id });
|
|
512
519
|
return { id };
|
|
513
520
|
});
|
|
@@ -532,10 +539,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
532
539
|
* @param decl - Store declaration
|
|
533
540
|
* @param open - Opens (and caches) the runtime handle
|
|
534
541
|
*/
|
|
535
|
-
function gatedSqlHandle(
|
|
536
|
-
decl: StoreDecl,
|
|
537
|
-
open: () => Promise<SqlStoreHandle>,
|
|
538
|
-
): SqlStoreHandle {
|
|
542
|
+
function gatedSqlHandle(decl: StoreDecl, open: () => Promise<SqlStoreHandle>): SqlStoreHandle {
|
|
539
543
|
const ref = decl.ref as `sql:${string}`;
|
|
540
544
|
let cached: SqlStoreHandle | undefined;
|
|
541
545
|
const ensure = async (): Promise<SqlStoreHandle> => {
|
|
@@ -562,30 +566,53 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
562
566
|
select(columns?) {
|
|
563
567
|
return {
|
|
564
568
|
from(table) {
|
|
565
|
-
const
|
|
566
|
-
|
|
567
|
-
|
|
569
|
+
const run = (plan: {
|
|
570
|
+
where?: unknown;
|
|
571
|
+
orders?: readonly unknown[];
|
|
572
|
+
limit?: number;
|
|
573
|
+
offset?: number;
|
|
574
|
+
}): Promise<SqlRow[]> =>
|
|
575
|
+
gated("read", ref, async () => {
|
|
576
|
+
const h = await ensure();
|
|
577
|
+
const from = h.select(columns).from(table);
|
|
578
|
+
const filtered = plan.where === undefined ? from : from.where(plan.where);
|
|
579
|
+
const ordered =
|
|
580
|
+
plan.orders === undefined ? filtered : filtered.orderBy(...plan.orders);
|
|
581
|
+
if (plan.offset !== undefined) return ordered.offset(plan.offset);
|
|
582
|
+
return plan.limit === undefined ? ordered : ordered.limit(plan.limit);
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const tail = (plan: {
|
|
586
|
+
where?: unknown;
|
|
587
|
+
orders?: readonly unknown[];
|
|
588
|
+
}): SelectOrderBuilder => ({
|
|
589
|
+
limit(n) {
|
|
590
|
+
return run({ ...plan, limit: n });
|
|
591
|
+
},
|
|
592
|
+
offset(n) {
|
|
593
|
+
return run({ ...plan, offset: n });
|
|
594
|
+
},
|
|
595
|
+
then(onfulfilled, onrejected) {
|
|
596
|
+
return run(plan).then(onfulfilled, onrejected);
|
|
597
|
+
},
|
|
568
598
|
});
|
|
599
|
+
|
|
569
600
|
return {
|
|
570
601
|
where(where) {
|
|
571
|
-
const filtered = gated("read", ref, async () => {
|
|
572
|
-
const h = await ensure();
|
|
573
|
-
return h.select(columns).from(table).where(where);
|
|
574
|
-
});
|
|
575
602
|
return {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
const h = await ensure();
|
|
579
|
-
return h.select(columns).from(table).where(where).limit(n);
|
|
580
|
-
});
|
|
581
|
-
},
|
|
582
|
-
then(onfulfilled, onrejected) {
|
|
583
|
-
return filtered.then(onfulfilled, onrejected);
|
|
584
|
-
},
|
|
603
|
+
...tail({ where }),
|
|
604
|
+
orderBy: (...orders: readonly unknown[]) => tail({ where, orders }),
|
|
585
605
|
};
|
|
586
606
|
},
|
|
607
|
+
orderBy: (...orders: readonly unknown[]) => tail({ orders }),
|
|
608
|
+
limit(n: number) {
|
|
609
|
+
return run({ limit: n });
|
|
610
|
+
},
|
|
611
|
+
offset(n: number) {
|
|
612
|
+
return run({ offset: n });
|
|
613
|
+
},
|
|
587
614
|
then(onfulfilled, onrejected) {
|
|
588
|
-
return
|
|
615
|
+
return run({}).then(onfulfilled, onrejected);
|
|
589
616
|
},
|
|
590
617
|
};
|
|
591
618
|
},
|
|
@@ -674,6 +701,18 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
674
701
|
return h.raw(sql, params);
|
|
675
702
|
});
|
|
676
703
|
},
|
|
704
|
+
count(table, where) {
|
|
705
|
+
return gated("read", ref, async () => {
|
|
706
|
+
const h = await ensure();
|
|
707
|
+
return h.count(table, where);
|
|
708
|
+
});
|
|
709
|
+
},
|
|
710
|
+
page(table, pageOptions) {
|
|
711
|
+
return gated("read", ref, async () => {
|
|
712
|
+
const h = await ensure();
|
|
713
|
+
return h.page(table, pageOptions);
|
|
714
|
+
});
|
|
715
|
+
},
|
|
677
716
|
ensureTable(table) {
|
|
678
717
|
return gated("write", ref, async () => {
|
|
679
718
|
refuseDryRunWrite();
|
|
@@ -684,9 +723,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
684
723
|
} as SqlStoreHandle;
|
|
685
724
|
}
|
|
686
725
|
|
|
687
|
-
function storeHandle(
|
|
688
|
-
ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl,
|
|
689
|
-
): FxStoreHandle {
|
|
726
|
+
function storeHandle(ref: NamedRef | { readonly ref: ResourceRef } | StoreDecl): FxStoreHandle {
|
|
690
727
|
const runtime = options.storeRuntime;
|
|
691
728
|
if (runtime && typeof ref === "object" && ref !== null && "facet" in ref) {
|
|
692
729
|
const decl = ref;
|
|
@@ -714,8 +751,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
714
751
|
get(_t, prop) {
|
|
715
752
|
if (prop === "ref") return baseRef;
|
|
716
753
|
if (prop === "then") return undefined;
|
|
717
|
-
const isRead =
|
|
718
|
-
prop === "get" || prop === "search" || prop === "list";
|
|
754
|
+
const isRead = prop === "get" || prop === "search" || prop === "list";
|
|
719
755
|
return (...args: unknown[]) =>
|
|
720
756
|
gated(isRead ? "read" : "write", baseRef, async () => {
|
|
721
757
|
if (!isRead && isDryRun()) {
|
|
@@ -724,18 +760,14 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
724
760
|
);
|
|
725
761
|
}
|
|
726
762
|
const h = await open();
|
|
727
|
-
const fn = (h as unknown as Record<string | symbol, unknown>)[
|
|
728
|
-
prop
|
|
729
|
-
];
|
|
763
|
+
const fn = (h as unknown as Record<string | symbol, unknown>)[prop];
|
|
730
764
|
if (typeof fn !== "function") return undefined;
|
|
731
765
|
return (fn as (...a: unknown[]) => unknown).apply(h, args);
|
|
732
766
|
});
|
|
733
767
|
},
|
|
734
768
|
});
|
|
735
769
|
}
|
|
736
|
-
return stubStoreHandle(
|
|
737
|
-
resolveStoreRef(ref as NamedRef | { readonly ref: ResourceRef }),
|
|
738
|
-
);
|
|
770
|
+
return stubStoreHandle(resolveStoreRef(ref as NamedRef | { readonly ref: ResourceRef }));
|
|
739
771
|
}
|
|
740
772
|
|
|
741
773
|
const clock: FxClock = {
|
|
@@ -768,11 +800,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
768
800
|
if (aiDisablesCache) return;
|
|
769
801
|
cacheStore.set(key, value);
|
|
770
802
|
},
|
|
771
|
-
async getOrSet<T>(
|
|
772
|
-
key: string,
|
|
773
|
-
_ttl: string,
|
|
774
|
-
produce: () => T | Promise<T>,
|
|
775
|
-
): Promise<T> {
|
|
803
|
+
async getOrSet<T>(key: string, _ttl: string, produce: () => T | Promise<T>): Promise<T> {
|
|
776
804
|
if (aiDisablesCache) return await produce();
|
|
777
805
|
if (cacheStore.has(key)) {
|
|
778
806
|
if (telemetry) telemetry.cacheHits += 1;
|
|
@@ -792,9 +820,7 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
792
820
|
const vault = options.vaultRuntime;
|
|
793
821
|
if (!vault) return { message, data };
|
|
794
822
|
const safeMessage = vault.redactString(message);
|
|
795
|
-
const safeData = data
|
|
796
|
-
? (vault.redact(data) as Record<string, unknown>)
|
|
797
|
-
: undefined;
|
|
823
|
+
const safeData = data ? (vault.redact(data) as Record<string, unknown>) : undefined;
|
|
798
824
|
return { message: safeMessage, data: safeData };
|
|
799
825
|
}
|
|
800
826
|
|
|
@@ -984,6 +1010,25 @@ export function createFxContext(options: CreateFxOptions): FxContext {
|
|
|
984
1010
|
operator,
|
|
985
1011
|
tenant,
|
|
986
1012
|
fail,
|
|
1013
|
+
json: {
|
|
1014
|
+
ok<T>(value: T, opts?: { readonly meta?: Record<string, unknown> }): JsonResult<T> {
|
|
1015
|
+
return {
|
|
1016
|
+
[jsonResultBrand]: true,
|
|
1017
|
+
status: 200,
|
|
1018
|
+
value,
|
|
1019
|
+
...(opts?.meta !== undefined ? { meta: opts.meta } : {}),
|
|
1020
|
+
} as JsonResult<T>;
|
|
1021
|
+
},
|
|
1022
|
+
create<T>(value: T): JsonResult<T> {
|
|
1023
|
+
return { [jsonResultBrand]: true, status: 201, value } as JsonResult<T>;
|
|
1024
|
+
},
|
|
1025
|
+
empty(): JsonResult<never> {
|
|
1026
|
+
return { [jsonResultBrand]: true, status: 204 } as JsonResult<never>;
|
|
1027
|
+
},
|
|
1028
|
+
with<T>(data: T, meta: Record<string, unknown>): JsonResult<T> {
|
|
1029
|
+
return { [jsonResultBrand]: true, status: 200, value: data, meta } as JsonResult<T>;
|
|
1030
|
+
},
|
|
1031
|
+
},
|
|
987
1032
|
async step<T>(name: string, fn: () => T | Promise<T>): Promise<T> {
|
|
988
1033
|
if (journal) {
|
|
989
1034
|
return journal.step(name, fn);
|
|
@@ -49,12 +49,9 @@ describe("hook timing", () => {
|
|
|
49
49
|
|
|
50
50
|
test("registry tags hooks at plug time", async () => {
|
|
51
51
|
const registry = createPluginRegistry();
|
|
52
|
-
const p = plugin("metered", { version: "1.0.0" }).hook(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
await Bun.sleep(1);
|
|
56
|
-
},
|
|
57
|
-
);
|
|
52
|
+
const p = plugin("metered", { version: "1.0.0" }).hook("onRequest", async () => {
|
|
53
|
+
await Bun.sleep(1);
|
|
54
|
+
});
|
|
58
55
|
applyPlugin(registry, p, appPluginScope);
|
|
59
56
|
const hooks = registry.hooksAt("app", undefined, "x");
|
|
60
57
|
const ctx: InvocationContext = {
|
|
@@ -132,10 +132,7 @@ export function resetHookCosts(): void {
|
|
|
132
132
|
filled = 0;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
function summarize(
|
|
136
|
-
pluginId: string,
|
|
137
|
-
mine: readonly HookCostSample[],
|
|
138
|
-
): HookCostSummary {
|
|
135
|
+
function summarize(pluginId: string, mine: readonly HookCostSample[]): HookCostSummary {
|
|
139
136
|
if (mine.length === 0) {
|
|
140
137
|
return {
|
|
141
138
|
pluginId,
|
|
@@ -149,18 +146,15 @@ function summarize(
|
|
|
149
146
|
}
|
|
150
147
|
const durations = mine.map((s) => s.durationMs).sort((a, b) => a - b);
|
|
151
148
|
const sum = durations.reduce((a, b) => a + b, 0);
|
|
152
|
-
const byStageAcc: Partial<
|
|
153
|
-
Record<HookStage, { count: number; total: number }>
|
|
154
|
-
> = {};
|
|
149
|
+
const byStageAcc: Partial<Record<HookStage, { count: number; total: number }>> = {};
|
|
155
150
|
for (const s of mine) {
|
|
156
151
|
const cur = byStageAcc[s.stage] ?? { count: 0, total: 0 };
|
|
157
152
|
cur.count++;
|
|
158
153
|
cur.total += s.durationMs;
|
|
159
154
|
byStageAcc[s.stage] = cur;
|
|
160
155
|
}
|
|
161
|
-
const byStage: Partial<
|
|
162
|
-
|
|
163
|
-
> = {};
|
|
156
|
+
const byStage: Partial<Record<HookStage, { readonly count: number; readonly meanMs: number }>> =
|
|
157
|
+
{};
|
|
164
158
|
for (const [stage, acc] of Object.entries(byStageAcc) as Array<
|
|
165
159
|
[HookStage, { count: number; total: number }]
|
|
166
160
|
>) {
|
|
@@ -182,9 +176,6 @@ function summarize(
|
|
|
182
176
|
|
|
183
177
|
function percentile(sorted: readonly number[], p: number): number {
|
|
184
178
|
if (sorted.length === 0) return 0;
|
|
185
|
-
const idx = Math.min(
|
|
186
|
-
sorted.length - 1,
|
|
187
|
-
Math.max(0, Math.ceil(p * sorted.length) - 1),
|
|
188
|
-
);
|
|
179
|
+
const idx = Math.min(sorted.length - 1, Math.max(0, Math.ceil(p * sorted.length) - 1));
|
|
189
180
|
return sorted[idx]!;
|
|
190
181
|
}
|