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
|
@@ -20,10 +20,7 @@ beforeEach(() => {
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
/** Compile-time equality. */
|
|
23
|
-
type Eq<A, B> =
|
|
24
|
-
(<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2
|
|
25
|
-
? true
|
|
26
|
-
: false;
|
|
23
|
+
type Eq<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
27
24
|
type Assert<T extends true> = T;
|
|
28
25
|
|
|
29
26
|
const NoteId = z.object({ id: z.string() });
|
|
@@ -54,9 +51,7 @@ const get = on(
|
|
|
54
51
|
out: Note,
|
|
55
52
|
errors: { NotFound },
|
|
56
53
|
do: ({ id }, fx) =>
|
|
57
|
-
id === "missing"
|
|
58
|
-
? fx.fail("NotFound", {})
|
|
59
|
-
: { id, title: "First", body: "Hello" },
|
|
54
|
+
id === "missing" ? fx.fail("NotFound", {}) : { id, title: "First", body: "Hello" },
|
|
60
55
|
}),
|
|
61
56
|
);
|
|
62
57
|
|
|
@@ -121,9 +116,7 @@ describe("Notes — typeof app carries contracts", () => {
|
|
|
121
116
|
{
|
|
122
117
|
const { data, error } = await api.notes.get({ id: "n_1" });
|
|
123
118
|
if (error?.code === "NotFound") {
|
|
124
|
-
type _Empty = Assert<
|
|
125
|
-
Eq<typeof error.data, Record<string, never>>
|
|
126
|
-
>;
|
|
119
|
+
type _Empty = Assert<Eq<typeof error.data, Record<string, never>>>;
|
|
127
120
|
const keep: _Empty = true;
|
|
128
121
|
expect(keep).toBe(true);
|
|
129
122
|
throw new Error("unexpected NotFound");
|
|
@@ -244,9 +237,7 @@ describe("Notes — typeof app carries contracts", () => {
|
|
|
244
237
|
type PartialClient = Client<typeof createOnly>;
|
|
245
238
|
|
|
246
239
|
type FullHasGet = "get" extends keyof FullClient["notes"] ? true : false;
|
|
247
|
-
type PartialHasGet = "get" extends keyof PartialClient["notes"]
|
|
248
|
-
? true
|
|
249
|
-
: false;
|
|
240
|
+
type PartialHasGet = "get" extends keyof PartialClient["notes"] ? true : false;
|
|
250
241
|
|
|
251
242
|
type _Full = Assert<Eq<FullHasGet, true>>;
|
|
252
243
|
type _Part = Assert<Eq<PartialHasGet, false>>;
|
package/src/client/transport.ts
CHANGED
|
@@ -24,12 +24,8 @@ export interface Transport {
|
|
|
24
24
|
* @param base - Absolute origin (no trailing slash)
|
|
25
25
|
* @param opts - Client options
|
|
26
26
|
*/
|
|
27
|
-
export function createTransport(
|
|
28
|
-
|
|
29
|
-
opts: ClientOptions = {},
|
|
30
|
-
): Transport {
|
|
31
|
-
const fetchFn: ClientFetch =
|
|
32
|
-
opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
27
|
+
export function createTransport(base: string, opts: ClientOptions = {}): Transport {
|
|
28
|
+
const fetchFn: ClientFetch = opts.fetch ?? globalThis.fetch.bind(globalThis);
|
|
33
29
|
const retries = opts.retry?.retries ?? 0;
|
|
34
30
|
const delay0 = opts.retry?.delay ?? 50;
|
|
35
31
|
const backoff = opts.retry?.backoff ?? 2;
|
|
@@ -94,10 +90,7 @@ async function once(
|
|
|
94
90
|
: rpcRequest(base, key, input);
|
|
95
91
|
|
|
96
92
|
const headers = new Headers();
|
|
97
|
-
const extra =
|
|
98
|
-
typeof opts.headers === "function"
|
|
99
|
-
? await opts.headers()
|
|
100
|
-
: opts.headers;
|
|
93
|
+
const extra = typeof opts.headers === "function" ? await opts.headers() : opts.headers;
|
|
101
94
|
if (Array.isArray(extra)) {
|
|
102
95
|
for (const [k, v] of extra) headers.set(k, v);
|
|
103
96
|
} else if (extra) {
|
|
@@ -114,9 +107,7 @@ async function once(
|
|
|
114
107
|
|
|
115
108
|
const ctrl = opts.timeout !== undefined ? new AbortController() : undefined;
|
|
116
109
|
const timer =
|
|
117
|
-
ctrl && opts.timeout !== undefined
|
|
118
|
-
? setTimeout(() => ctrl.abort(), opts.timeout)
|
|
119
|
-
: undefined;
|
|
110
|
+
ctrl && opts.timeout !== undefined ? setTimeout(() => ctrl.abort(), opts.timeout) : undefined;
|
|
120
111
|
|
|
121
112
|
try {
|
|
122
113
|
const res = await fetchFn(url, {
|
|
@@ -140,8 +131,7 @@ function rpcRequest(
|
|
|
140
131
|
input: unknown,
|
|
141
132
|
): { url: string; method: string; body: string | undefined } {
|
|
142
133
|
const url = `${base}/_oke/${key}`;
|
|
143
|
-
const body =
|
|
144
|
-
input === undefined ? undefined : JSON.stringify(input ?? {});
|
|
134
|
+
const body = input === undefined ? undefined : JSON.stringify(input ?? {});
|
|
145
135
|
return { url, method: "POST", body };
|
|
146
136
|
}
|
|
147
137
|
|
|
@@ -152,9 +142,7 @@ function restRequest(
|
|
|
152
142
|
input: unknown,
|
|
153
143
|
): { url: string; method: string; body: string | undefined } {
|
|
154
144
|
const params =
|
|
155
|
-
input !== null && typeof input === "object"
|
|
156
|
-
? (input as Record<string, unknown>)
|
|
157
|
-
: {};
|
|
145
|
+
input !== null && typeof input === "object" ? (input as Record<string, unknown>) : {};
|
|
158
146
|
let pathOut = path;
|
|
159
147
|
const query: string[] = [];
|
|
160
148
|
const rest: Record<string, unknown> = {};
|
|
@@ -173,15 +161,11 @@ function restRequest(
|
|
|
173
161
|
if (upper === "GET" || upper === "HEAD") {
|
|
174
162
|
for (const [k, v] of Object.entries(rest)) {
|
|
175
163
|
if (v !== undefined) {
|
|
176
|
-
query.push(
|
|
177
|
-
`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`,
|
|
178
|
-
);
|
|
164
|
+
query.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
|
|
179
165
|
}
|
|
180
166
|
}
|
|
181
167
|
} else if (Object.keys(rest).length > 0 || path === pathOut) {
|
|
182
|
-
body = JSON.stringify(
|
|
183
|
-
Object.keys(rest).length > 0 ? rest : (input ?? {}),
|
|
184
|
-
);
|
|
168
|
+
body = JSON.stringify(Object.keys(rest).length > 0 ? rest : (input ?? {}));
|
|
185
169
|
}
|
|
186
170
|
|
|
187
171
|
const qs = query.length ? `?${query.join("&")}` : "";
|
|
@@ -221,12 +205,7 @@ async function decode(res: Response): Promise<ClientResult> {
|
|
|
221
205
|
};
|
|
222
206
|
}
|
|
223
207
|
|
|
224
|
-
if (
|
|
225
|
-
json !== null &&
|
|
226
|
-
typeof json === "object" &&
|
|
227
|
-
"data" in json &&
|
|
228
|
-
"error" in json
|
|
229
|
-
) {
|
|
208
|
+
if (json !== null && typeof json === "object" && "data" in json && "error" in json) {
|
|
230
209
|
return json as ClientResult;
|
|
231
210
|
}
|
|
232
211
|
|
package/src/client/types.ts
CHANGED
|
@@ -88,9 +88,7 @@ export type RoutesOf<App> = App extends { readonly $routes: infer R }
|
|
|
88
88
|
? R
|
|
89
89
|
: {
|
|
90
90
|
[U in keyof R]: {
|
|
91
|
-
[F in keyof R[U]]: R[U][F] extends FlowContract
|
|
92
|
-
? R[U][F]
|
|
93
|
-
: FlowContract;
|
|
91
|
+
[F in keyof R[U]]: R[U][F] extends FlowContract ? R[U][F] : FlowContract;
|
|
94
92
|
};
|
|
95
93
|
}
|
|
96
94
|
: App extends ClientRouteMap
|
|
@@ -102,9 +100,7 @@ export type RoutesOf<App> = App extends { readonly $routes: infer R }
|
|
|
102
100
|
*
|
|
103
101
|
* @typeParam E - Error code → data map
|
|
104
102
|
*/
|
|
105
|
-
export type ClientError<
|
|
106
|
-
E extends Record<string, unknown> = Record<string, unknown>,
|
|
107
|
-
> = {
|
|
103
|
+
export type ClientError<E extends Record<string, unknown> = Record<string, unknown>> = {
|
|
108
104
|
[K in keyof E & string]: {
|
|
109
105
|
readonly code: K;
|
|
110
106
|
readonly data: E[K];
|
|
@@ -126,6 +122,8 @@ export interface TransportError {
|
|
|
126
122
|
|
|
127
123
|
/**
|
|
128
124
|
* Client call result — errors are values, never thrown for flow failures.
|
|
125
|
+
* Success may carry an optional top-level `meta` (Stripe-style envelope,
|
|
126
|
+
* e.g. paginated lists).
|
|
129
127
|
*
|
|
130
128
|
* @typeParam O - Success data
|
|
131
129
|
* @typeParam E - Declared error map
|
|
@@ -134,14 +132,15 @@ export type ClientResult<
|
|
|
134
132
|
O = unknown,
|
|
135
133
|
E extends Record<string, unknown> = Record<string, unknown>,
|
|
136
134
|
> =
|
|
137
|
-
| {
|
|
135
|
+
| {
|
|
136
|
+
readonly data: O;
|
|
137
|
+
readonly error: null;
|
|
138
|
+
readonly meta?: Record<string, unknown>;
|
|
139
|
+
}
|
|
138
140
|
| { readonly data: null; readonly error: ClientError<E> | TransportError };
|
|
139
141
|
|
|
140
142
|
/** Minimal fetch signature (avoids DOM `HeadersInit` / `preconnect` coupling). */
|
|
141
|
-
export type ClientFetch = (
|
|
142
|
-
input: string | URL | Request,
|
|
143
|
-
init?: RequestInit,
|
|
144
|
-
) => Promise<Response>;
|
|
143
|
+
export type ClientFetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
145
144
|
|
|
146
145
|
/** Header bag accepted by the client. */
|
|
147
146
|
export type ClientHeaders = Record<string, string> | [string, string][];
|
|
@@ -153,9 +152,7 @@ export interface ClientOptions {
|
|
|
153
152
|
/** Override `globalThis.fetch`. */
|
|
154
153
|
readonly fetch?: ClientFetch;
|
|
155
154
|
/** Static headers, or a getter invoked per request. */
|
|
156
|
-
readonly headers?:
|
|
157
|
-
| ClientHeaders
|
|
158
|
-
| (() => ClientHeaders | Promise<ClientHeaders>);
|
|
155
|
+
readonly headers?: ClientHeaders | (() => ClientHeaders | Promise<ClientHeaders>);
|
|
159
156
|
/** Abort the request after this many milliseconds. */
|
|
160
157
|
readonly timeout?: number;
|
|
161
158
|
/** Retry transient failures (network / 5xx). */
|
|
@@ -173,11 +170,7 @@ export interface ClientOptions {
|
|
|
173
170
|
*/
|
|
174
171
|
readonly auth?: {
|
|
175
172
|
/** Current access token (Bearer), or null. */
|
|
176
|
-
readonly getToken: () =>
|
|
177
|
-
| string
|
|
178
|
-
| null
|
|
179
|
-
| undefined
|
|
180
|
-
| Promise<string | null | undefined>;
|
|
173
|
+
readonly getToken: () => string | null | undefined | Promise<string | null | undefined>;
|
|
181
174
|
/** Obtain a new access token after 401. */
|
|
182
175
|
readonly refresh: () => Promise<string | null | undefined>;
|
|
183
176
|
};
|
|
@@ -186,9 +179,7 @@ export interface ClientOptions {
|
|
|
186
179
|
* When absent, the client uses `POST /_oke/{unit}/{flow}` unless
|
|
187
180
|
* {@link ClientOptions.$routes} supplies HTTP method/path from adopt.
|
|
188
181
|
*/
|
|
189
|
-
readonly routes?: Readonly<
|
|
190
|
-
Record<string, { readonly method: string; readonly path: string }>
|
|
191
|
-
>;
|
|
182
|
+
readonly routes?: Readonly<Record<string, { readonly method: string; readonly path: string }>>;
|
|
192
183
|
/**
|
|
193
184
|
* Runtime route map from `app.$routes` (typed adopt). HTTP triggers become
|
|
194
185
|
* REST; flows without method/path fall back to RPC.
|
|
@@ -203,11 +194,7 @@ export interface ClientOptions {
|
|
|
203
194
|
* @typeParam O - Output
|
|
204
195
|
* @typeParam E - Errors
|
|
205
196
|
*/
|
|
206
|
-
export type ClientCall<
|
|
207
|
-
I,
|
|
208
|
-
O,
|
|
209
|
-
E extends Record<string, unknown>,
|
|
210
|
-
> = [I] extends [void]
|
|
197
|
+
export type ClientCall<I, O, E extends Record<string, unknown>> = [I] extends [void]
|
|
211
198
|
? () => Promise<ClientResult<O, E>>
|
|
212
199
|
: Partial<I> extends I
|
|
213
200
|
? (input?: I) => Promise<ClientResult<O, E>>
|
|
@@ -223,9 +210,7 @@ type ContractIn<C> = "in" extends keyof C
|
|
|
223
210
|
: void;
|
|
224
211
|
|
|
225
212
|
/** Pull output from a contract shape. */
|
|
226
|
-
type ContractOut<C> = "out" extends keyof C
|
|
227
|
-
? NonNullable<C["out"]>
|
|
228
|
-
: unknown;
|
|
213
|
+
type ContractOut<C> = "out" extends keyof C ? NonNullable<C["out"]> : unknown;
|
|
229
214
|
|
|
230
215
|
/** Pull error map from a contract shape. */
|
|
231
216
|
type ContractErrors<C> = "errors" extends keyof C
|
package/src/compiler/aot.test.ts
CHANGED
|
@@ -30,11 +30,7 @@ describe("sucrose — context inference", () => {
|
|
|
30
30
|
|
|
31
31
|
test("detects context.body / query / headers access", () => {
|
|
32
32
|
const inference = sucrose({
|
|
33
|
-
handler: ((ctx: {
|
|
34
|
-
body: unknown;
|
|
35
|
-
query: unknown;
|
|
36
|
-
headers: unknown;
|
|
37
|
-
}) => ({
|
|
33
|
+
handler: ((ctx: { body: unknown; query: unknown; headers: unknown }) => ({
|
|
38
34
|
body: ctx.body,
|
|
39
35
|
q: ctx.query,
|
|
40
36
|
h: ctx.headers,
|
|
@@ -191,10 +187,7 @@ describe("AoT throughput ≥ 1.5× dynamic", () => {
|
|
|
191
187
|
seats: z.number().int().min(1).max(9),
|
|
192
188
|
note: z.string().max(200).optional(),
|
|
193
189
|
});
|
|
194
|
-
const handler = ((input: {
|
|
195
|
-
flightId: string;
|
|
196
|
-
seats: number;
|
|
197
|
-
}) => input) as never;
|
|
190
|
+
const handler = ((input: { flightId: string; seats: number }) => input) as never;
|
|
198
191
|
|
|
199
192
|
const aot = compileAot({
|
|
200
193
|
method: "POST",
|
package/src/compiler/aot.ts
CHANGED
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import type { FlowFailure } from "../kernel/errors.ts";
|
|
10
|
-
import {
|
|
11
|
-
validate,
|
|
12
|
-
type SchemaInput,
|
|
13
|
-
} from "../validation/standard-schema.ts";
|
|
10
|
+
import { validate, type SchemaInput } from "../validation/standard-schema.ts";
|
|
14
11
|
import {
|
|
15
12
|
assembleInput,
|
|
16
13
|
extractParts,
|
|
@@ -49,11 +49,7 @@ function generateContracts(count: number, seed = 42): GeneratedContract[] {
|
|
|
49
49
|
method: "POST",
|
|
50
50
|
path,
|
|
51
51
|
schema,
|
|
52
|
-
handler: ((input: {
|
|
53
|
-
flightId: string;
|
|
54
|
-
seats: number;
|
|
55
|
-
cabin?: string;
|
|
56
|
-
}) => ({
|
|
52
|
+
handler: ((input: { flightId: string; seats: number; cabin?: string }) => ({
|
|
57
53
|
ok: true,
|
|
58
54
|
flightId: input.flightId,
|
|
59
55
|
seats: input.seats,
|
|
@@ -140,10 +136,7 @@ function generateContracts(count: number, seed = 42): GeneratedContract[] {
|
|
|
140
136
|
method: "POST",
|
|
141
137
|
path,
|
|
142
138
|
schema,
|
|
143
|
-
handler: ((input: {
|
|
144
|
-
tags: string[];
|
|
145
|
-
meta: { source: string; n: number };
|
|
146
|
-
}) => ({
|
|
139
|
+
handler: ((input: { tags: string[]; meta: { source: string; n: number } }) => ({
|
|
147
140
|
count: input.tags.length,
|
|
148
141
|
source: input.meta.source,
|
|
149
142
|
n: input.meta.n,
|
|
@@ -188,8 +181,7 @@ async function runSample(
|
|
|
188
181
|
request: Request,
|
|
189
182
|
params: Readonly<Record<string, string>>,
|
|
190
183
|
) => Promise<
|
|
191
|
-
|
|
192
|
-
| { ok: false; failure: import("../kernel/errors.ts").FlowFailure }
|
|
184
|
+
{ ok: true; input: unknown } | { ok: false; failure: import("../kernel/errors.ts").FlowFailure }
|
|
193
185
|
>,
|
|
194
186
|
handler: (...args: never[]) => unknown,
|
|
195
187
|
sample: GeneratedContract["samples"][number],
|
package/src/compiler/dynamic.ts
CHANGED
|
@@ -37,10 +37,7 @@ export function compileDynamic(options: CompileRouteOptions): CompiledRoute {
|
|
|
37
37
|
* @param options - Route metadata
|
|
38
38
|
* @param aot - When `false`, force the dynamic path
|
|
39
39
|
*/
|
|
40
|
-
export function compileRoute(
|
|
41
|
-
options: CompileRouteOptions,
|
|
42
|
-
aot: boolean = true,
|
|
43
|
-
): CompiledRoute {
|
|
40
|
+
export function compileRoute(options: CompileRouteOptions, aot: boolean = true): CompiledRoute {
|
|
44
41
|
if (!aot) return compileDynamic(options);
|
|
45
42
|
return compileAot(options);
|
|
46
43
|
}
|
|
@@ -105,15 +105,7 @@ const READ_METHODS = new Set([
|
|
|
105
105
|
"find",
|
|
106
106
|
]);
|
|
107
107
|
|
|
108
|
-
const WRITE_METHODS = new Set([
|
|
109
|
-
"insert",
|
|
110
|
-
"set",
|
|
111
|
-
"delete",
|
|
112
|
-
"increment",
|
|
113
|
-
"update",
|
|
114
|
-
"upsert",
|
|
115
|
-
"log",
|
|
116
|
-
]);
|
|
108
|
+
const WRITE_METHODS = new Set(["insert", "set", "delete", "increment", "update", "upsert", "log"]);
|
|
117
109
|
|
|
118
110
|
/** Methods whose first argument is a table / collection identifier. */
|
|
119
111
|
const TABLE_ARG_METHODS = new Set([
|
|
@@ -204,19 +196,13 @@ export function inferEffects(options: InferEffectsOptions): InferredEffects {
|
|
|
204
196
|
// the sibling call that carries the table arg records the real resource.
|
|
205
197
|
const leaf = resolved.methods[resolved.methods.length - 1]!;
|
|
206
198
|
const hasTable = tableFromStoreChain(call) !== undefined;
|
|
207
|
-
if (
|
|
208
|
-
!hasTable &&
|
|
209
|
-
(leaf === "select" || leaf === "insert" || leaf === "update")
|
|
210
|
-
) {
|
|
199
|
+
if (!hasTable && (leaf === "select" || leaf === "insert" || leaf === "update")) {
|
|
211
200
|
continue;
|
|
212
201
|
}
|
|
213
202
|
// Intermediate chain links that only forward (where/values/returning)
|
|
214
203
|
// still carry read/write from earlier methods — record once we have a table
|
|
215
204
|
// or a terminal key-based op.
|
|
216
|
-
if (
|
|
217
|
-
!hasTable &&
|
|
218
|
-
(leaf === "where" || leaf === "values" || leaf === "returning")
|
|
219
|
-
) {
|
|
205
|
+
if (!hasTable && (leaf === "where" || leaf === "values" || leaf === "returning")) {
|
|
220
206
|
continue;
|
|
221
207
|
}
|
|
222
208
|
if (op === "read" || op === "both") reads.add(resolved.resource);
|
|
@@ -306,10 +292,7 @@ export function fxMemberChain(call: CallExpression): FxChain | null {
|
|
|
306
292
|
const prop = (member.property as Identifier).name;
|
|
307
293
|
methods.unshift(prop);
|
|
308
294
|
|
|
309
|
-
if (
|
|
310
|
-
member.object.type === "Identifier" &&
|
|
311
|
-
(member.object as Identifier).name === "fx"
|
|
312
|
-
) {
|
|
295
|
+
if (member.object.type === "Identifier" && (member.object as Identifier).name === "fx") {
|
|
313
296
|
rootCall = current;
|
|
314
297
|
rootMethod = prop;
|
|
315
298
|
break;
|
|
@@ -377,9 +360,7 @@ export function storeResourceFromCall(
|
|
|
377
360
|
const literal = stringArg(storeArg);
|
|
378
361
|
if (literal) {
|
|
379
362
|
return {
|
|
380
|
-
resource: (literal.includes(":")
|
|
381
|
-
? literal
|
|
382
|
-
: `${facet}:${literal}`) as ResourceRef,
|
|
363
|
+
resource: (literal.includes(":") ? literal : `${facet}:${literal}`) as ResourceRef,
|
|
383
364
|
methods: chain.methods,
|
|
384
365
|
};
|
|
385
366
|
}
|
|
@@ -418,9 +399,7 @@ function tableFromStoreChain(call: CallExpression): string | undefined {
|
|
|
418
399
|
return undefined;
|
|
419
400
|
}
|
|
420
401
|
|
|
421
|
-
function classifyStoreMethods(
|
|
422
|
-
methods: string[],
|
|
423
|
-
): "read" | "write" | "both" | "none" {
|
|
402
|
+
function classifyStoreMethods(methods: string[]): "read" | "write" | "both" | "none" {
|
|
424
403
|
const ops = methods.slice(1);
|
|
425
404
|
let read = false;
|
|
426
405
|
let write = false;
|
|
@@ -490,9 +469,7 @@ export function stringArg(node: AstNode | undefined): string | undefined {
|
|
|
490
469
|
const quasis = (node as AstNode & { quasis?: AstNode[] }).quasis;
|
|
491
470
|
const exprs = (node as AstNode & { expressions?: AstNode[] }).expressions;
|
|
492
471
|
if (quasis?.length === 1 && (exprs?.length ?? 0) === 0) {
|
|
493
|
-
const cooked = (
|
|
494
|
-
quasis[0] as AstNode & { value?: { cooked?: string } }
|
|
495
|
-
).value?.cooked;
|
|
472
|
+
const cooked = (quasis[0] as AstNode & { value?: { cooked?: string } }).value?.cooked;
|
|
496
473
|
if (typeof cooked === "string") return cooked;
|
|
497
474
|
}
|
|
498
475
|
}
|
|
@@ -530,10 +507,7 @@ function containsAuthUserId(root: AstNode): boolean {
|
|
|
530
507
|
};
|
|
531
508
|
if (auth.property.type !== "Identifier") return;
|
|
532
509
|
if ((auth.property as Identifier).name !== "auth") return;
|
|
533
|
-
if (
|
|
534
|
-
auth.object.type === "Identifier" &&
|
|
535
|
-
(auth.object as Identifier).name === "fx"
|
|
536
|
-
) {
|
|
510
|
+
if (auth.object.type === "Identifier" && (auth.object as Identifier).name === "fx") {
|
|
537
511
|
found = true;
|
|
538
512
|
}
|
|
539
513
|
});
|
package/src/compiler/emit.ts
CHANGED
|
@@ -22,9 +22,7 @@ export interface EmitManifestOptions {
|
|
|
22
22
|
* @param options - Path and document
|
|
23
23
|
* @returns Absolute path written
|
|
24
24
|
*/
|
|
25
|
-
export async function emitManifest(
|
|
26
|
-
options: EmitManifestOptions,
|
|
27
|
-
): Promise<string> {
|
|
25
|
+
export async function emitManifest(options: EmitManifestOptions): Promise<string> {
|
|
28
26
|
const text = serializeManifest(options.manifest);
|
|
29
27
|
await Bun.write(options.path, text);
|
|
30
28
|
return options.path;
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
deepMatch,
|
|
5
|
-
extractFromSources,
|
|
6
|
-
extractManifest,
|
|
7
|
-
} from "./extract.ts";
|
|
3
|
+
import { deepMatch, extractFromSources, extractManifest } from "./extract.ts";
|
|
8
4
|
import { emitManifest, manifestPathIn } from "./emit.ts";
|
|
9
5
|
import { serializeManifest } from "../manifest/validate.ts";
|
|
10
6
|
import type { Manifest } from "../manifest/types.ts";
|
|
11
7
|
|
|
12
8
|
const skyportRoot = new URL("./fixtures/skyport/", import.meta.url).pathname;
|
|
13
9
|
const goldenUrl = new URL("./fixtures/skyport.expected.json", import.meta.url);
|
|
14
|
-
const excerptUrl = new URL(
|
|
15
|
-
"../manifest/fixtures/skyport.excerpt.json",
|
|
16
|
-
import.meta.url,
|
|
17
|
-
);
|
|
10
|
+
const excerptUrl = new URL("../manifest/fixtures/skyport.excerpt.json", import.meta.url);
|
|
18
11
|
|
|
19
|
-
async function loadSkyportFiles(): Promise<
|
|
20
|
-
{ path: string; source: string }[]
|
|
21
|
-
> {
|
|
12
|
+
async function loadSkyportFiles(): Promise<{ path: string; source: string }[]> {
|
|
22
13
|
const glob = new Bun.Glob("**/*.{ts,tsx}");
|
|
23
14
|
const files: { path: string; source: string }[] = [];
|
|
24
15
|
for await (const path of glob.scan({ cwd: skyportRoot, onlyFiles: true })) {
|
|
@@ -71,33 +62,23 @@ describe("extractManifest — five trigger types", () => {
|
|
|
71
62
|
expect(manifest.flows?.["triggers.http"]?.trigger).toEqual({
|
|
72
63
|
http: { method: "POST", path: "/orders" },
|
|
73
64
|
});
|
|
74
|
-
expect(manifest.flows?.["triggers.http"]?.effects?.writes).toEqual([
|
|
75
|
-
"sql:orders",
|
|
76
|
-
]);
|
|
65
|
+
expect(manifest.flows?.["triggers.http"]?.effects?.writes).toEqual(["sql:orders"]);
|
|
77
66
|
|
|
78
67
|
expect(manifest.flows?.["triggers.every"]?.trigger).toEqual({
|
|
79
68
|
every: "10m",
|
|
80
69
|
});
|
|
81
|
-
expect(manifest.flows?.["triggers.every"]?.effects?.writes).toEqual([
|
|
82
|
-
"sql:links",
|
|
83
|
-
]);
|
|
70
|
+
expect(manifest.flows?.["triggers.every"]?.effects?.writes).toEqual(["sql:links"]);
|
|
84
71
|
|
|
85
72
|
expect(manifest.flows?.["triggers.signal"]?.trigger).toEqual({
|
|
86
73
|
signal: "link-clicked",
|
|
87
74
|
});
|
|
88
|
-
expect(manifest.flows?.["triggers.signal"]?.effects?.writes).toContain(
|
|
89
|
-
|
|
90
|
-
);
|
|
91
|
-
expect(manifest.flows?.["triggers.signal"]?.effects?.emits).toContain(
|
|
92
|
-
"link-clicked",
|
|
93
|
-
);
|
|
75
|
+
expect(manifest.flows?.["triggers.signal"]?.effects?.writes).toContain("sql:links");
|
|
76
|
+
expect(manifest.flows?.["triggers.signal"]?.effects?.emits).toContain("link-clicked");
|
|
94
77
|
|
|
95
78
|
expect(manifest.flows?.["triggers.cdc"]?.trigger).toEqual({
|
|
96
79
|
cdc: { table: "orders", column: "status" },
|
|
97
80
|
});
|
|
98
|
-
expect(manifest.flows?.["triggers.cdc"]?.effects?.writes).toEqual([
|
|
99
|
-
"sql:orders",
|
|
100
|
-
]);
|
|
81
|
+
expect(manifest.flows?.["triggers.cdc"]?.effects?.writes).toEqual(["sql:orders"]);
|
|
101
82
|
|
|
102
83
|
// internal trigger → no trigger key (call-only), or empty trigger object
|
|
103
84
|
const internal = manifest.flows?.["triggers.internal"];
|
|
@@ -119,9 +100,7 @@ describe("extractManifest — fx.raw", () => {
|
|
|
119
100
|
|
|
120
101
|
expect(manifest.flows?.["raw.unannotated"]?.cache).toBe(false);
|
|
121
102
|
expect(manifest.flows?.["raw.annotated"]?.cache).toBeUndefined();
|
|
122
|
-
expect(manifest.flows?.["raw.annotated"]?.effects?.reads).toEqual([
|
|
123
|
-
"sql:orders",
|
|
124
|
-
]);
|
|
103
|
+
expect(manifest.flows?.["raw.annotated"]?.effects?.reads).toEqual(["sql:orders"]);
|
|
125
104
|
});
|
|
126
105
|
});
|
|
127
106
|
|
|
@@ -175,3 +154,130 @@ describe("serializeManifest stability", () => {
|
|
|
175
154
|
expect(again).toEqual(manifest);
|
|
176
155
|
});
|
|
177
156
|
});
|
|
157
|
+
|
|
158
|
+
describe("extractManifest — relational with: is never expanded (path b)", () => {
|
|
159
|
+
test("findMany({ with: { daily: true } }) records no related-table effects", async () => {
|
|
160
|
+
const source = `
|
|
161
|
+
import { on, flow, http, store } from "okengine";
|
|
162
|
+
|
|
163
|
+
export const db = store.sql("db");
|
|
164
|
+
export const links = { name: "links" };
|
|
165
|
+
export const daily = { name: "daily" };
|
|
166
|
+
|
|
167
|
+
export const listLinks = on(
|
|
168
|
+
http.get("/links"),
|
|
169
|
+
flow({
|
|
170
|
+
name: "rel.root",
|
|
171
|
+
do: async (_input, fx) => {
|
|
172
|
+
return fx.store(db).select().from(links);
|
|
173
|
+
},
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Hypothetical RQB-shaped call. inferEffects never consults schema
|
|
178
|
+
// relations, so the related table must NOT appear in effects.
|
|
179
|
+
export const withDaily = on(
|
|
180
|
+
http.get("/links/with-daily"),
|
|
181
|
+
flow({
|
|
182
|
+
name: "rel.with",
|
|
183
|
+
do: async (_input, fx) => {
|
|
184
|
+
return fx.store(db).findMany({ with: { daily: true } });
|
|
185
|
+
},
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
`;
|
|
189
|
+
const manifest = await extractFromSources({ "src/flows/rel.ts": source });
|
|
190
|
+
|
|
191
|
+
// Root-table read stays exact.
|
|
192
|
+
expect(manifest.flows?.["rel.root"]?.effects?.reads).toEqual(["sql:links"]);
|
|
193
|
+
|
|
194
|
+
// The with: argument is not walked — falls back to the store-level
|
|
195
|
+
// resource, never the relation target.
|
|
196
|
+
expect(manifest.flows?.["rel.with"]?.effects?.reads).toEqual(["sql:db"]);
|
|
197
|
+
|
|
198
|
+
const allEffects = Object.values(manifest.flows ?? {}).flatMap((f) => [
|
|
199
|
+
...(f.effects?.reads ?? []),
|
|
200
|
+
...(f.effects?.writes ?? []),
|
|
201
|
+
]);
|
|
202
|
+
expect(allEffects).not.toContain("sql:daily");
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
describe("extractManifest — store.schema.table", () => {
|
|
207
|
+
test("extracts DeclaredColumn with PII into manifest stores", async () => {
|
|
208
|
+
const source = `
|
|
209
|
+
import { store, field, id, now } from "okengine";
|
|
210
|
+
|
|
211
|
+
export const notes = store.schema.table("notes", {
|
|
212
|
+
id: field.text().primaryKey().defaultFn(id),
|
|
213
|
+
title: field.text().notNull(),
|
|
214
|
+
body: field.text().notNull().pii(),
|
|
215
|
+
createdAt: field.integer().notNull().defaultFn(now),
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
export const db = store.sql("app", { schema: { notes } });
|
|
219
|
+
`;
|
|
220
|
+
const manifest = await extractFromSources({
|
|
221
|
+
"src/schema.decl.ts": source,
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
expect(manifest.stores?.app?.facet).toBe("sql");
|
|
225
|
+
const cols = manifest.stores?.app?.tables?.notes?.columns;
|
|
226
|
+
expect(cols?.body).toMatchObject({
|
|
227
|
+
type: "text",
|
|
228
|
+
pii: true,
|
|
229
|
+
nullable: false,
|
|
230
|
+
sqlName: "body",
|
|
231
|
+
});
|
|
232
|
+
expect(cols?.createdAt).toMatchObject({
|
|
233
|
+
type: "integer",
|
|
234
|
+
sqlName: "created_at",
|
|
235
|
+
nullable: false,
|
|
236
|
+
});
|
|
237
|
+
expect(cols?.id).toMatchObject({
|
|
238
|
+
type: "text",
|
|
239
|
+
primaryKey: true,
|
|
240
|
+
sqlName: "id",
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe("extractManifest — on(http.resource(...))", () => {
|
|
246
|
+
test("expands the mount into five CRUD bindings with store effects", async () => {
|
|
247
|
+
const source = `
|
|
248
|
+
import { on, http, store } from "okengine";
|
|
249
|
+
|
|
250
|
+
export const db = store.sql("notes", { schema: {} });
|
|
251
|
+
|
|
252
|
+
const notesR = store.resource(db, {}, { unit: "notes", breaking: true });
|
|
253
|
+
|
|
254
|
+
const mounted = on(http.resource("/notes", notesR.all()));
|
|
255
|
+
|
|
256
|
+
export const list = mounted.list;
|
|
257
|
+
export const create = mounted.create;
|
|
258
|
+
export const get = mounted.get;
|
|
259
|
+
export const update = mounted.update;
|
|
260
|
+
export const remove = mounted.remove;
|
|
261
|
+
`;
|
|
262
|
+
const manifest = await extractFromSources({ "src/flows/notes.ts": source });
|
|
263
|
+
|
|
264
|
+
expect(manifest.flows?.list?.trigger).toEqual({
|
|
265
|
+
http: { method: "GET", path: "/notes" },
|
|
266
|
+
});
|
|
267
|
+
expect(manifest.flows?.create?.trigger).toEqual({
|
|
268
|
+
http: { method: "POST", path: "/notes" },
|
|
269
|
+
});
|
|
270
|
+
expect(manifest.flows?.get?.trigger).toEqual({
|
|
271
|
+
http: { method: "GET", path: "/notes/:id" },
|
|
272
|
+
});
|
|
273
|
+
expect(manifest.flows?.update?.trigger).toEqual({
|
|
274
|
+
http: { method: "PATCH", path: "/notes/:id" },
|
|
275
|
+
});
|
|
276
|
+
expect(manifest.flows?.remove?.trigger).toEqual({
|
|
277
|
+
http: { method: "DELETE", path: "/notes/:id" },
|
|
278
|
+
});
|
|
279
|
+
expect(manifest.flows?.list?.effects?.reads).toEqual(["sql:notes"]);
|
|
280
|
+
expect(manifest.flows?.create?.effects?.writes).toEqual(["sql:notes"]);
|
|
281
|
+
expect(manifest.flows?.list?.breaking).toBe(true);
|
|
282
|
+
});
|
|
283
|
+
});
|