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/hooks.test.ts
CHANGED
|
@@ -26,11 +26,9 @@ describe("hooks — order and composition", () => {
|
|
|
26
26
|
|
|
27
27
|
test("mergeHooks is app → unit → flow, registration order within", () => {
|
|
28
28
|
const order: string[] = [];
|
|
29
|
-
const mark =
|
|
30
|
-
(label
|
|
31
|
-
|
|
32
|
-
order.push(label);
|
|
33
|
-
};
|
|
29
|
+
const mark = (label: string) => () => {
|
|
30
|
+
order.push(label);
|
|
31
|
+
};
|
|
34
32
|
|
|
35
33
|
const merged = mergeHooks(
|
|
36
34
|
{ onRequest: [mark("app1"), mark("app2")] },
|
|
@@ -66,11 +64,13 @@ describe("hooks — order and composition", () => {
|
|
|
66
64
|
order.push("handler");
|
|
67
65
|
return { ok: true };
|
|
68
66
|
},
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
})
|
|
68
|
+
.hook("beforeHandle", () => {
|
|
69
|
+
order.push("flow:beforeHandle");
|
|
70
|
+
})
|
|
71
|
+
.hook("afterHandle", () => {
|
|
72
|
+
order.push("flow:afterHandle");
|
|
73
|
+
});
|
|
74
74
|
|
|
75
75
|
on(http.get("/ordered"), f);
|
|
76
76
|
|
|
@@ -146,6 +146,39 @@ describe("hooks — order and composition", () => {
|
|
|
146
146
|
expect(order).toEqual(["onAuth", "onResponse"]);
|
|
147
147
|
});
|
|
148
148
|
|
|
149
|
+
test("onResponse sees the serialized data response and may replace it", async () => {
|
|
150
|
+
let seenAtHook: Response | undefined;
|
|
151
|
+
|
|
152
|
+
on(
|
|
153
|
+
http.get("/data"),
|
|
154
|
+
flow({
|
|
155
|
+
name: "data",
|
|
156
|
+
do: () => ({ ok: true }),
|
|
157
|
+
}),
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const app = oke({ name: "data-res" }).hook("onResponse", (ctx) => {
|
|
161
|
+
seenAtHook = ctx.response;
|
|
162
|
+
if (!ctx.response) return;
|
|
163
|
+
const headers = new Headers(ctx.response.headers);
|
|
164
|
+
headers.set("x-stamped", "yes");
|
|
165
|
+
ctx.response = new Response(ctx.response.body, {
|
|
166
|
+
status: ctx.response.status,
|
|
167
|
+
headers,
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const res = await app.fetch(new Request("http://localhost/data"));
|
|
172
|
+
expect(res.status).toBe(200);
|
|
173
|
+
expect(res.headers.get("x-stamped")).toBe("yes");
|
|
174
|
+
// The hook saw the real serialized response, not undefined.
|
|
175
|
+
expect(seenAtHook).toBeDefined();
|
|
176
|
+
expect(seenAtHook!.headers.get("content-type")).toContain("application/json");
|
|
177
|
+
// The body survived the rebuild untouched.
|
|
178
|
+
const body = (await res.json()) as { data?: { ok: boolean } };
|
|
179
|
+
expect(body.data?.ok).toBe(true);
|
|
180
|
+
});
|
|
181
|
+
|
|
149
182
|
test("hook short-circuits with FlowFailure and runs onError", async () => {
|
|
150
183
|
const order: string[] = [];
|
|
151
184
|
|
package/src/kernel/hooks.ts
CHANGED
|
@@ -40,9 +40,7 @@ export const BEFORE_HANDLER_STAGES: readonly HookStage[] = [
|
|
|
40
40
|
] as const;
|
|
41
41
|
|
|
42
42
|
/** Stages that run after a successful handler (before onResponse). */
|
|
43
|
-
export const AFTER_HANDLER_STAGES: readonly HookStage[] = [
|
|
44
|
-
"afterHandle",
|
|
45
|
-
] as const;
|
|
43
|
+
export const AFTER_HANDLER_STAGES: readonly HookStage[] = ["afterHandle"] as const;
|
|
46
44
|
|
|
47
45
|
/** All user-registrable stages in pipeline order. */
|
|
48
46
|
export const HOOK_STAGES: readonly HookStage[] = [
|
|
@@ -97,11 +95,7 @@ export type HookFn = (
|
|
|
97
95
|
ctx: InvocationContext,
|
|
98
96
|
fxOrErr: Fx | unknown,
|
|
99
97
|
fx?: Fx,
|
|
100
|
-
) =>
|
|
101
|
-
| void
|
|
102
|
-
| Response
|
|
103
|
-
| FlowFailure
|
|
104
|
-
| Promise<void | Response | FlowFailure>;
|
|
98
|
+
) => void | Response | FlowFailure | Promise<void | Response | FlowFailure>;
|
|
105
99
|
|
|
106
100
|
/** Hook bag keyed by stage. */
|
|
107
101
|
export type HookMap = Partial<Record<HookStage, HookFn[]>>;
|
|
@@ -156,19 +150,34 @@ export interface PipelineResult {
|
|
|
156
150
|
readonly response: Response | undefined;
|
|
157
151
|
}
|
|
158
152
|
|
|
153
|
+
/** Serialize a pipeline outcome into an HTTP response (app-layer encoder). */
|
|
154
|
+
export type PipelineEncoder = (result: {
|
|
155
|
+
readonly response?: Response | undefined;
|
|
156
|
+
readonly failure?: FlowFailure | undefined;
|
|
157
|
+
readonly output?: unknown;
|
|
158
|
+
readonly error?: unknown;
|
|
159
|
+
}) => Response;
|
|
160
|
+
|
|
159
161
|
/**
|
|
160
162
|
* Run the seven-stage pipeline around `handler`.
|
|
161
163
|
*
|
|
164
|
+
* When `encode` is given (HTTP triggers), the outcome is serialized into
|
|
165
|
+
* `ctx.response` **before** `onResponse`, so the last stage sees — and may
|
|
166
|
+
* replace — the final response, as {@link InvocationContext.response}
|
|
167
|
+
* documents. Without `encode` (non-HTTP triggers) behavior is unchanged.
|
|
168
|
+
*
|
|
162
169
|
* @param ctx - Invocation context
|
|
163
170
|
* @param fx - Fx door
|
|
164
171
|
* @param hooks - Merged hooks
|
|
165
172
|
* @param handler - Flow body (the `handler` stage)
|
|
173
|
+
* @param encode - HTTP response encoder (e.g. `encodeExecuteResult`)
|
|
166
174
|
*/
|
|
167
175
|
export async function runPipeline(
|
|
168
176
|
ctx: InvocationContext,
|
|
169
177
|
fx: Fx,
|
|
170
178
|
hooks: HookMap,
|
|
171
179
|
handler: () => unknown | Promise<unknown>,
|
|
180
|
+
encode?: PipelineEncoder,
|
|
172
181
|
): Promise<PipelineResult> {
|
|
173
182
|
let shortCircuit: "response" | "error" | undefined;
|
|
174
183
|
|
|
@@ -221,6 +230,13 @@ export async function runPipeline(
|
|
|
221
230
|
await runStage("onError", hooks, ctx, fx);
|
|
222
231
|
}
|
|
223
232
|
|
|
233
|
+
// Serialize before the last stage so `onResponse` sees the final response
|
|
234
|
+
// (short-circuit wins; encoder input mirrors the app layer exactly).
|
|
235
|
+
if (encode !== undefined && ctx.response === undefined) {
|
|
236
|
+
const failure = isFlowFailure(ctx.error) ? ctx.error : undefined;
|
|
237
|
+
ctx.response = encode({ failure, output: ctx.result, error: ctx.error });
|
|
238
|
+
}
|
|
239
|
+
|
|
224
240
|
await runStage("onResponse", hooks, ctx, fx);
|
|
225
241
|
|
|
226
242
|
const failure = isFlowFailure(ctx.error) ? ctx.error : undefined;
|
|
@@ -247,10 +263,7 @@ async function runStage(
|
|
|
247
263
|
const started = pluginId !== undefined ? performance.now() : 0;
|
|
248
264
|
try {
|
|
249
265
|
// Spec apps use `.hook("onError", (ctx, err, fx) => …)`.
|
|
250
|
-
returned =
|
|
251
|
-
stage === "onError"
|
|
252
|
-
? await fn(ctx, ctx.error, fx)
|
|
253
|
-
: await fn(ctx, fx);
|
|
266
|
+
returned = stage === "onError" ? await fn(ctx, ctx.error, fx) : await fn(ctx, fx);
|
|
254
267
|
} catch (err) {
|
|
255
268
|
if (pluginId !== undefined) {
|
|
256
269
|
recordHookCost(pluginId, stage, performance.now() - started);
|
package/src/kernel/index.ts
CHANGED
|
@@ -50,11 +50,7 @@ export type {
|
|
|
50
50
|
RoutesFromAdoptArgs,
|
|
51
51
|
} from "./adopt-routes.ts";
|
|
52
52
|
|
|
53
|
-
export {
|
|
54
|
-
createCapabilityToken,
|
|
55
|
-
effectsFieldOf,
|
|
56
|
-
type CapabilityToken,
|
|
57
|
-
} from "./capability.ts";
|
|
53
|
+
export { createCapabilityToken, effectsFieldOf, type CapabilityToken } from "./capability.ts";
|
|
58
54
|
|
|
59
55
|
export {
|
|
60
56
|
createEffectLedger,
|
|
@@ -107,6 +103,8 @@ export {
|
|
|
107
103
|
export {
|
|
108
104
|
createFx,
|
|
109
105
|
createFxContext,
|
|
106
|
+
isJsonResult,
|
|
107
|
+
jsonResultBrand,
|
|
110
108
|
resolveName,
|
|
111
109
|
resolveStoreRef,
|
|
112
110
|
type CreateFxOptions,
|
|
@@ -117,12 +115,14 @@ export {
|
|
|
117
115
|
type FxCallHandler,
|
|
118
116
|
type FxClock,
|
|
119
117
|
type FxContext,
|
|
118
|
+
type FxJson,
|
|
120
119
|
type FxLog,
|
|
121
120
|
type FxOperator,
|
|
122
121
|
type FxSearchOptions,
|
|
123
122
|
type FxSendOptions,
|
|
124
123
|
type FxStoreHandle,
|
|
125
124
|
type FxTenant,
|
|
125
|
+
type JsonResult,
|
|
126
126
|
type NamedRef,
|
|
127
127
|
} from "./fx.ts";
|
|
128
128
|
|
|
@@ -181,12 +181,7 @@ export {
|
|
|
181
181
|
type HookCostSummary,
|
|
182
182
|
} from "./hook-timing.ts";
|
|
183
183
|
|
|
184
|
-
export {
|
|
185
|
-
listBindings,
|
|
186
|
-
on,
|
|
187
|
-
resetBindings,
|
|
188
|
-
type Binding,
|
|
189
|
-
} from "./on.ts";
|
|
184
|
+
export { listBindings, on, resetBindings, type Binding } from "./on.ts";
|
|
190
185
|
|
|
191
186
|
export {
|
|
192
187
|
isPlugin,
|
|
@@ -205,6 +200,7 @@ export {
|
|
|
205
200
|
type PluginOptions,
|
|
206
201
|
type PluginRegistration,
|
|
207
202
|
type TableContribution,
|
|
203
|
+
type PluginTableOptions,
|
|
208
204
|
} from "./plugin.ts";
|
|
209
205
|
|
|
210
206
|
export {
|
|
@@ -244,6 +240,7 @@ export {
|
|
|
244
240
|
every,
|
|
245
241
|
http,
|
|
246
242
|
internal,
|
|
243
|
+
isResourceMount,
|
|
247
244
|
isSignalTriggerSource,
|
|
248
245
|
normalizeTrigger,
|
|
249
246
|
table,
|
|
@@ -254,6 +251,8 @@ export {
|
|
|
254
251
|
type HttpMethod,
|
|
255
252
|
type HttpTrigger,
|
|
256
253
|
type InternalTrigger,
|
|
254
|
+
type ResourceFlowBag,
|
|
255
|
+
type ResourceMount,
|
|
257
256
|
type SignalAsTrigger,
|
|
258
257
|
type SignalSource,
|
|
259
258
|
type TableHandle,
|
|
@@ -270,11 +269,6 @@ export {
|
|
|
270
269
|
type JourneySlo,
|
|
271
270
|
} from "./journey.ts";
|
|
272
271
|
|
|
273
|
-
export {
|
|
274
|
-
unit,
|
|
275
|
-
consumeUnitPlugins,
|
|
276
|
-
resetUnitPlugins,
|
|
277
|
-
type UnitBag,
|
|
278
|
-
} from "./unit.ts";
|
|
272
|
+
export { unit, consumeUnitPlugins, resetUnitPlugins, type UnitBag } from "./unit.ts";
|
|
279
273
|
|
|
280
274
|
export { rateLimit, type RateLimitPluginOptions } from "./rate-limit.ts";
|
package/src/kernel/journal.ts
CHANGED
|
@@ -11,11 +11,7 @@ import { mkdir } from "node:fs/promises";
|
|
|
11
11
|
import { dirname } from "node:path";
|
|
12
12
|
|
|
13
13
|
/** Status of a durable run. */
|
|
14
|
-
export type JournalRunStatus =
|
|
15
|
-
| "running"
|
|
16
|
-
| "sleeping"
|
|
17
|
-
| "completed"
|
|
18
|
-
| "failed";
|
|
14
|
+
export type JournalRunStatus = "running" | "sleeping" | "completed" | "failed";
|
|
19
15
|
|
|
20
16
|
/** A completed named step. */
|
|
21
17
|
export interface JournalStepEntry {
|
|
@@ -44,10 +40,7 @@ export interface JournalEffectEntry {
|
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
/** One journaled event in call order. */
|
|
47
|
-
export type JournalEntry =
|
|
48
|
-
| JournalStepEntry
|
|
49
|
-
| JournalSleepEntry
|
|
50
|
-
| JournalEffectEntry;
|
|
43
|
+
export type JournalEntry = JournalStepEntry | JournalSleepEntry | JournalEffectEntry;
|
|
51
44
|
|
|
52
45
|
/** Persisted durable run. */
|
|
53
46
|
export interface JournalRun {
|
|
@@ -103,9 +96,7 @@ export interface JournalStore {
|
|
|
103
96
|
}
|
|
104
97
|
|
|
105
98
|
/** In-memory journal store. */
|
|
106
|
-
export function createMemoryJournalStore(
|
|
107
|
-
seed?: readonly JournalRun[],
|
|
108
|
-
): JournalStore {
|
|
99
|
+
export function createMemoryJournalStore(seed?: readonly JournalRun[]): JournalStore {
|
|
109
100
|
const runs = new Map<string, JournalRun>();
|
|
110
101
|
for (const r of seed ?? []) {
|
|
111
102
|
runs.set(r.id, cloneRun(r));
|
|
@@ -147,10 +138,7 @@ export function createFileJournalStore(path: string): JournalStore {
|
|
|
147
138
|
|
|
148
139
|
async function flush(map: Map<string, JournalRun>): Promise<void> {
|
|
149
140
|
await mkdir(dirname(path), { recursive: true });
|
|
150
|
-
await Bun.write(
|
|
151
|
-
path,
|
|
152
|
-
JSON.stringify({ runs: [...map.values()] }, null, 2),
|
|
153
|
-
);
|
|
141
|
+
await Bun.write(path, JSON.stringify({ runs: [...map.values()] }, null, 2));
|
|
154
142
|
}
|
|
155
143
|
|
|
156
144
|
return {
|
|
@@ -204,11 +192,7 @@ export interface JournalSession {
|
|
|
204
192
|
* @param duration - Duration string (`7d`, `2m`, …)
|
|
205
193
|
* @param parseMs - Duration → milliseconds
|
|
206
194
|
*/
|
|
207
|
-
sleep(
|
|
208
|
-
label: string,
|
|
209
|
-
duration: string,
|
|
210
|
-
parseMs: (duration: string) => number,
|
|
211
|
-
): Promise<void>;
|
|
195
|
+
sleep(label: string, duration: string, parseMs: (duration: string) => number): Promise<void>;
|
|
212
196
|
/**
|
|
213
197
|
* Journal an arbitrary fx effect (replay returns recorded value).
|
|
214
198
|
*
|
|
@@ -216,11 +200,7 @@ export interface JournalSession {
|
|
|
216
200
|
* @param resource - Resource ref
|
|
217
201
|
* @param execute - Side-effecting body
|
|
218
202
|
*/
|
|
219
|
-
effect<T>(
|
|
220
|
-
effectKind: string,
|
|
221
|
-
resource: string,
|
|
222
|
-
execute: () => T | Promise<T>,
|
|
223
|
-
): Promise<T>;
|
|
203
|
+
effect<T>(effectKind: string, resource: string, execute: () => T | Promise<T>): Promise<T>;
|
|
224
204
|
/** Persist current run status / output. */
|
|
225
205
|
commit(
|
|
226
206
|
status: JournalRunStatus,
|
|
@@ -327,11 +307,7 @@ export function createJournal(options: CreateJournalOptions): Journal {
|
|
|
327
307
|
): Promise<T> {
|
|
328
308
|
for (let i = cursor; i < run.entries.length; i++) {
|
|
329
309
|
const e = run.entries[i]!;
|
|
330
|
-
if (
|
|
331
|
-
e.kind === "effect" &&
|
|
332
|
-
e.effectKind === effectKind &&
|
|
333
|
-
e.resource === resource
|
|
334
|
-
) {
|
|
310
|
+
if (e.kind === "effect" && e.effectKind === effectKind && e.resource === resource) {
|
|
335
311
|
cursor = i + 1;
|
|
336
312
|
return e.value as T;
|
|
337
313
|
}
|
package/src/kernel/on.ts
CHANGED
|
@@ -6,15 +6,13 @@
|
|
|
6
6
|
* The return type carries the bound trigger so `typeof app` can derive REST.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { isFlow, type AnyFlowDef, type FlowDef, type FlowErrorMap } from "./flow.ts";
|
|
9
10
|
import {
|
|
10
|
-
|
|
11
|
-
type AnyFlowDef,
|
|
12
|
-
type FlowDef,
|
|
13
|
-
type FlowErrorMap,
|
|
14
|
-
} from "./flow.ts";
|
|
15
|
-
import {
|
|
11
|
+
isResourceMount,
|
|
16
12
|
normalizeTrigger,
|
|
17
13
|
type BoundTriggerOf,
|
|
14
|
+
type ResourceFlowBag,
|
|
15
|
+
type ResourceMount,
|
|
18
16
|
type SignalSource,
|
|
19
17
|
type Trigger,
|
|
20
18
|
} from "./triggers.ts";
|
|
@@ -44,17 +42,55 @@ export function on<
|
|
|
44
42
|
>(
|
|
45
43
|
trigger: T,
|
|
46
44
|
flowDef: FlowDef<I, O, E, D, Trigger | undefined>,
|
|
47
|
-
): FlowDef<I, O, E, D, BoundTriggerOf<T
|
|
45
|
+
): FlowDef<I, O, E, D, BoundTriggerOf<T>>;
|
|
46
|
+
/**
|
|
47
|
+
* Mount a CRUD resource (`http.resource(path, ops)`): registers the five
|
|
48
|
+
* verb bindings and returns the ops bag (unit keys `list` · `create` ·
|
|
49
|
+
* `get` · `update` · `remove`) for `.adopt({ notes })`.
|
|
50
|
+
*
|
|
51
|
+
* @param mount - Branded {@link ResourceMount}
|
|
52
|
+
*/
|
|
53
|
+
export function on(mount: ResourceMount): ResourceFlowBag;
|
|
54
|
+
export function on(
|
|
55
|
+
triggerOrMount: Trigger | SignalSource | ResourceMount,
|
|
56
|
+
flowDef?: FlowDef<any, any, any, any, Trigger | undefined>,
|
|
57
|
+
): unknown {
|
|
58
|
+
if (isResourceMount(triggerOrMount)) {
|
|
59
|
+
if (flowDef !== undefined) {
|
|
60
|
+
throw new TypeError("on(http.resource(...)) takes no second argument");
|
|
61
|
+
}
|
|
62
|
+
const byIdVerb: Partial<Record<string, "get" | "update" | "remove">> = {
|
|
63
|
+
GET: "get",
|
|
64
|
+
PATCH: "update",
|
|
65
|
+
DELETE: "remove",
|
|
66
|
+
};
|
|
67
|
+
const baseVerb: Partial<Record<string, "list" | "create">> = {
|
|
68
|
+
GET: "list",
|
|
69
|
+
POST: "create",
|
|
70
|
+
};
|
|
71
|
+
const ops: Record<string, unknown> = {};
|
|
72
|
+
for (const { trigger, flow } of triggerOrMount.mounts) {
|
|
73
|
+
const key = trigger.path.endsWith("/:id")
|
|
74
|
+
? byIdVerb[trigger.method]
|
|
75
|
+
: baseVerb[trigger.method];
|
|
76
|
+
if (key === undefined || !isFlow(flow)) {
|
|
77
|
+
throw new TypeError("on(http.resource(...)) expects the five CRUD FlowDefs");
|
|
78
|
+
}
|
|
79
|
+
on(trigger, flow as FlowDef<any, any, any, any, Trigger | undefined>);
|
|
80
|
+
ops[key] = flow;
|
|
81
|
+
}
|
|
82
|
+
return ops as unknown as ResourceFlowBag;
|
|
83
|
+
}
|
|
48
84
|
if (!isFlow(flowDef)) {
|
|
49
85
|
throw new TypeError("on() expected a flow() definition as the second argument");
|
|
50
86
|
}
|
|
51
|
-
const normalized = normalizeTrigger(
|
|
87
|
+
const normalized = normalizeTrigger(triggerOrMount as Trigger | SignalSource);
|
|
52
88
|
const list = flowDef.triggers as Trigger[];
|
|
53
89
|
list.push(normalized);
|
|
54
90
|
// Stamp runtime carrier for the first bound trigger (type follows BoundTriggerOf).
|
|
55
91
|
(flowDef as { $trigger: Trigger }).$trigger = normalized;
|
|
56
92
|
bindings.push({ trigger: normalized, flow: flowDef as AnyFlowDef });
|
|
57
|
-
return flowDef
|
|
93
|
+
return flowDef;
|
|
58
94
|
}
|
|
59
95
|
|
|
60
96
|
/**
|
|
@@ -9,10 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { describe, expect, test } from "bun:test";
|
|
11
11
|
import { z } from "zod";
|
|
12
|
-
import {
|
|
13
|
-
createSessionStore,
|
|
14
|
-
issueSessionWithScopes,
|
|
15
|
-
} from "../auth/sessions.ts";
|
|
12
|
+
import { createSessionStore, issueSessionWithScopes } from "../auth/sessions.ts";
|
|
16
13
|
import { createClockRuntime } from "../elements/clock.ts";
|
|
17
14
|
import { gate } from "../elements/gate.ts";
|
|
18
15
|
import { createRunsRuntime, memoryRunsDriver } from "../runs/index.ts";
|
|
@@ -20,16 +17,11 @@ import { oke } from "./app.ts";
|
|
|
20
17
|
import { flow, resetFlowSeq } from "./flow.ts";
|
|
21
18
|
import { on, resetBindings } from "./on.ts";
|
|
22
19
|
import { http } from "./triggers.ts";
|
|
23
|
-
import {
|
|
24
|
-
gateDenialFailure,
|
|
25
|
-
recordGateEvaluations,
|
|
26
|
-
} from "./pipeline.ts";
|
|
20
|
+
import { gateDenialFailure, recordGateEvaluations } from "./pipeline.ts";
|
|
27
21
|
import { createRunTelemetry } from "./run-telemetry.ts";
|
|
28
22
|
|
|
29
23
|
const member = gate.policy("member", ({ auth }) => !!auth.verified);
|
|
30
|
-
const canOrder = gate.policy("order:create", ({ auth }) =>
|
|
31
|
-
auth.scopes.has("order:create"),
|
|
32
|
-
);
|
|
24
|
+
const canOrder = gate.policy("order:create", ({ auth }) => auth.scopes.has("order:create"));
|
|
33
25
|
|
|
34
26
|
describe("gateDenialFailure", () => {
|
|
35
27
|
test("anonymous → Unauthorized; authed → Forbidden; rate → RateLimited", () => {
|
|
@@ -217,18 +209,17 @@ describe("pipeline — Bearer cryptographic verification", () => {
|
|
|
217
209
|
const app = oke({
|
|
218
210
|
name: "auth-forge",
|
|
219
211
|
gates: [member],
|
|
220
|
-
env: "
|
|
212
|
+
env: "local",
|
|
221
213
|
auth: { secret: "hmac-secret-for-tests", sessions },
|
|
222
214
|
startScheduler: false,
|
|
223
215
|
});
|
|
224
|
-
await app.boot({ env: "
|
|
216
|
+
await app.boot({ env: "local", gates: [member], startScheduler: false });
|
|
225
217
|
|
|
226
218
|
const res = await app.fetch(
|
|
227
219
|
new Request("http://localhost/secure", {
|
|
228
220
|
method: "GET",
|
|
229
221
|
headers: {
|
|
230
|
-
authorization:
|
|
231
|
-
"Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJoYWNrZXIifQ.forgedsignature",
|
|
222
|
+
authorization: "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJoYWNrZXIifQ.forgedsignature",
|
|
232
223
|
},
|
|
233
224
|
}),
|
|
234
225
|
);
|
|
@@ -272,13 +263,13 @@ describe("pipeline — Bearer cryptographic verification", () => {
|
|
|
272
263
|
const app = oke({
|
|
273
264
|
name: "auth-expired",
|
|
274
265
|
gates: [member],
|
|
275
|
-
env: "
|
|
266
|
+
env: "local",
|
|
276
267
|
auth: { secret, sessions, now: () => nowMs },
|
|
277
268
|
elements: { clock: clockRt },
|
|
278
269
|
startScheduler: false,
|
|
279
270
|
});
|
|
280
271
|
await app.boot({
|
|
281
|
-
env: "
|
|
272
|
+
env: "local",
|
|
282
273
|
gates: [member],
|
|
283
274
|
startScheduler: false,
|
|
284
275
|
elements: { clock: clockRt },
|
|
@@ -324,10 +315,10 @@ describe("pipeline — Bearer cryptographic verification", () => {
|
|
|
324
315
|
const app = oke({
|
|
325
316
|
name: "no-inject",
|
|
326
317
|
gates: [member],
|
|
327
|
-
env: "
|
|
318
|
+
env: "local",
|
|
328
319
|
startScheduler: false,
|
|
329
320
|
});
|
|
330
|
-
await app.boot({ env: "
|
|
321
|
+
await app.boot({ env: "local", gates: [member], startScheduler: false });
|
|
331
322
|
|
|
332
323
|
const result = await app.execute(
|
|
333
324
|
app.flow("orders.inject")!,
|
package/src/kernel/pipeline.ts
CHANGED
|
@@ -74,18 +74,14 @@ export type GateDenialCode = "Unauthorized" | "Forbidden" | "RateLimited";
|
|
|
74
74
|
* @param evaluation - First denying evaluation
|
|
75
75
|
* @param ctx - Policy context at denial time
|
|
76
76
|
*/
|
|
77
|
-
export function gateDenialFailure(
|
|
78
|
-
evaluation: GateEvaluation,
|
|
79
|
-
ctx: GatePolicyContext,
|
|
80
|
-
): FlowFailure {
|
|
77
|
+
export function gateDenialFailure(evaluation: GateEvaluation, ctx: GatePolicyContext): FlowFailure {
|
|
81
78
|
if (evaluation.kind === "rate" || evaluation.reason === "rate limited") {
|
|
82
79
|
return fail("RateLimited", {
|
|
83
80
|
retryAfterMs: evaluation.retryAfterMs ?? 0,
|
|
84
81
|
});
|
|
85
82
|
}
|
|
86
83
|
|
|
87
|
-
const authenticated =
|
|
88
|
-
ctx.auth.userId !== null && ctx.auth.userId !== undefined;
|
|
84
|
+
const authenticated = ctx.auth.userId !== null && ctx.auth.userId !== undefined;
|
|
89
85
|
if (!authenticated) {
|
|
90
86
|
return fail("Unauthorized", {});
|
|
91
87
|
}
|
|
@@ -102,9 +98,7 @@ export function gateDenialFailure(
|
|
|
102
98
|
*/
|
|
103
99
|
export function gateNamesOf(trigger: Trigger): string[] {
|
|
104
100
|
if (trigger.kind !== "http") return [];
|
|
105
|
-
return (trigger as HttpTrigger).gates.map((g) =>
|
|
106
|
-
typeof g === "string" ? g : g.name,
|
|
107
|
-
);
|
|
101
|
+
return (trigger as HttpTrigger).gates.map((g) => (typeof g === "string" ? g : g.name));
|
|
108
102
|
}
|
|
109
103
|
|
|
110
104
|
/**
|
|
@@ -129,10 +123,7 @@ export function recordGateEvaluations(
|
|
|
129
123
|
* @param bag - Mutable principal bag
|
|
130
124
|
* @param resolved - Identity
|
|
131
125
|
*/
|
|
132
|
-
export function applyPrincipal(
|
|
133
|
-
bag: PrincipalBag,
|
|
134
|
-
resolved: ResolvedPrincipal | undefined,
|
|
135
|
-
): void {
|
|
126
|
+
export function applyPrincipal(bag: PrincipalBag, resolved: ResolvedPrincipal | undefined): void {
|
|
136
127
|
if (!resolved) return;
|
|
137
128
|
if (resolved.plane === "operator" || resolved.operatorId !== undefined) {
|
|
138
129
|
bag.operator.id = resolved.operatorId ?? null;
|
|
@@ -217,10 +208,7 @@ export function createElementPipelineHooks(deps: PipelineDeps): {
|
|
|
217
208
|
* @param fx - Fx door
|
|
218
209
|
* @param ctx - Invocation context (for IP / meta)
|
|
219
210
|
*/
|
|
220
|
-
export function policyContextOf(
|
|
221
|
-
fx: Fx,
|
|
222
|
-
ctx: InvocationContext,
|
|
223
|
-
): GatePolicyContext {
|
|
211
|
+
export function policyContextOf(fx: Fx, ctx: InvocationContext): GatePolicyContext {
|
|
224
212
|
const auth = fx.auth as FxAuth;
|
|
225
213
|
const operator = fx.operator as FxOperator;
|
|
226
214
|
const ip =
|
package/src/kernel/plug.ts
CHANGED
|
@@ -14,10 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
import type { AnyFlowDef } from "./flow.ts";
|
|
16
16
|
import { isPlugin, type DecorationsOf, type PluginDef } from "./plugin.ts";
|
|
17
|
-
import {
|
|
18
|
-
type PluginRegistry,
|
|
19
|
-
type PluginScope,
|
|
20
|
-
} from "./registry.ts";
|
|
17
|
+
import { type PluginRegistry, type PluginScope } from "./registry.ts";
|
|
21
18
|
|
|
22
19
|
/**
|
|
23
20
|
* Apply a plugin to a registry at the given scope.
|
|
@@ -43,10 +40,8 @@ export function applyPlugin(
|
|
|
43
40
|
* @typeParam Base - Existing decorations
|
|
44
41
|
* @typeParam P - Plugin being plugged
|
|
45
42
|
*/
|
|
46
|
-
export type AccumulateDecorations<
|
|
47
|
-
|
|
48
|
-
P,
|
|
49
|
-
> = Base & DecorationsOf<P>;
|
|
43
|
+
export type AccumulateDecorations<Base extends Record<string, unknown>, P> = Base &
|
|
44
|
+
DecorationsOf<P>;
|
|
50
45
|
|
|
51
46
|
/** Something that can receive `.plug()` with type accumulation. */
|
|
52
47
|
export interface Pluggable<D extends Record<string, unknown> = {}> {
|
|
@@ -55,9 +50,7 @@ export interface Pluggable<D extends Record<string, unknown> = {}> {
|
|
|
55
50
|
*
|
|
56
51
|
* @param pluginDef - Plugin from {@link plugin}
|
|
57
52
|
*/
|
|
58
|
-
plug<P extends PluginDef>(
|
|
59
|
-
pluginDef: P,
|
|
60
|
-
): Pluggable<AccumulateDecorations<D, P>>;
|
|
53
|
+
plug<P extends PluginDef>(pluginDef: P): Pluggable<AccumulateDecorations<D, P>>;
|
|
61
54
|
}
|
|
62
55
|
|
|
63
56
|
/**
|
|
@@ -10,19 +10,11 @@ describe("plugin conflict detection", () => {
|
|
|
10
10
|
test("table-name collision fails the boot with both plugin names", () => {
|
|
11
11
|
const registry = createPluginRegistry();
|
|
12
12
|
|
|
13
|
-
registry.plug(
|
|
14
|
-
plugin("audit", { version: "1.0.0" }).table("events"),
|
|
15
|
-
{ kind: "app" },
|
|
16
|
-
);
|
|
13
|
+
registry.plug(plugin("audit", { version: "1.0.0" }).table("events"), { kind: "app" });
|
|
17
14
|
|
|
18
15
|
expect(() =>
|
|
19
|
-
registry.plug(
|
|
20
|
-
|
|
21
|
-
{ kind: "app" },
|
|
22
|
-
),
|
|
23
|
-
).toThrow(
|
|
24
|
-
'Plugin conflict: table "events" claimed by "audit" and "billing"',
|
|
25
|
-
);
|
|
16
|
+
registry.plug(plugin("billing", { version: "1.0.0" }).table("events"), { kind: "app" }),
|
|
17
|
+
).toThrow('Plugin conflict: table "events" claimed by "audit" and "billing"');
|
|
26
18
|
});
|
|
27
19
|
|
|
28
20
|
test("panel-id collision names both sides", () => {
|
|
@@ -79,28 +71,24 @@ describe("plugin conflict detection", () => {
|
|
|
79
71
|
config: { max: 30 },
|
|
80
72
|
}).hook("onRequest", () => {});
|
|
81
73
|
|
|
82
|
-
expect(
|
|
83
|
-
|
|
84
|
-
).toBeDefined();
|
|
85
|
-
expect(
|
|
86
|
-
registry.plug(p, { kind: "unit", name: "payments" }),
|
|
87
|
-
).toBeDefined();
|
|
74
|
+
expect(registry.plug(p, { kind: "unit", name: "orders" })).toBeDefined();
|
|
75
|
+
expect(registry.plug(p, { kind: "unit", name: "payments" })).toBeDefined();
|
|
88
76
|
expect(registry.installed).toHaveLength(2);
|
|
89
77
|
});
|
|
90
78
|
|
|
91
79
|
test("same plugin twice with conflicting config is a boot error", () => {
|
|
92
80
|
const registry = createPluginRegistry();
|
|
93
81
|
|
|
94
|
-
registry.plug(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
82
|
+
registry.plug(plugin("rate-limit", { version: "1.0.0", config: { max: 30 } }), {
|
|
83
|
+
kind: "unit",
|
|
84
|
+
name: "orders",
|
|
85
|
+
});
|
|
98
86
|
|
|
99
87
|
expect(() =>
|
|
100
|
-
registry.plug(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
),
|
|
88
|
+
registry.plug(plugin("rate-limit", { version: "1.0.0", config: { max: 60 } }), {
|
|
89
|
+
kind: "unit",
|
|
90
|
+
name: "payments",
|
|
91
|
+
}),
|
|
104
92
|
).toThrow(/conflicting config/);
|
|
105
93
|
});
|
|
106
94
|
});
|
|
@@ -15,8 +15,7 @@ beforeEach(() => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
/** Compile-time assert: `Actual` extends `Expected`. */
|
|
18
|
-
type ExpectExtends<Actual, Expected> =
|
|
19
|
-
Actual extends Expected ? true : false;
|
|
18
|
+
type ExpectExtends<Actual, Expected> = Actual extends Expected ? true : false;
|
|
20
19
|
|
|
21
20
|
describe("plugin decorate — types and runtime", () => {
|
|
22
21
|
test("decoration is visible in downstream handlers", async () => {
|
|
@@ -45,14 +44,12 @@ describe("plugin decorate — types and runtime", () => {
|
|
|
45
44
|
});
|
|
46
45
|
|
|
47
46
|
test("types accumulate through .plug()", () => {
|
|
48
|
-
const withAudit = plugin("audit", { version: "1.0.0" }).decorate(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{ currency: "SAR" as const },
|
|
55
|
-
);
|
|
47
|
+
const withAudit = plugin("audit", { version: "1.0.0" }).decorate("audit", {
|
|
48
|
+
enabled: true as const,
|
|
49
|
+
});
|
|
50
|
+
const withBilling = plugin("billing", { version: "1.0.0" }).decorate("billing", {
|
|
51
|
+
currency: "SAR" as const,
|
|
52
|
+
});
|
|
56
53
|
|
|
57
54
|
const app = oke({ name: "types" }).plug(withAudit).plug(withBilling);
|
|
58
55
|
|
|
@@ -98,9 +95,7 @@ describe("plugin decorate — types and runtime", () => {
|
|
|
98
95
|
);
|
|
99
96
|
|
|
100
97
|
const app = oke({ name: "deco-scope" });
|
|
101
|
-
app.unit("orders").plug(
|
|
102
|
-
plugin("flag", { version: "1.0.0" }).decorate("flag", "orders-only"),
|
|
103
|
-
);
|
|
98
|
+
app.unit("orders").plug(plugin("flag", { version: "1.0.0" }).decorate("flag", "orders-only"));
|
|
104
99
|
|
|
105
100
|
await app.fetch(new Request("http://localhost/orders"));
|
|
106
101
|
await app.fetch(new Request("http://localhost/payments"));
|