okengine 0.1.4
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 +91 -0
- package/README.md +327 -0
- package/docs/spec/complete-example.md +1188 -0
- package/docs/spec/console.md +739 -0
- package/docs/spec/four-applications.md +1188 -0
- package/docs/spec/unified-theory.md +489 -0
- package/package.json +152 -0
- package/spec/manifest.v1.schema.json +624 -0
- package/src/auth/api-keys.ts +168 -0
- package/src/auth/attenuation.ts +116 -0
- package/src/auth/auth.test.ts +273 -0
- package/src/auth/cross-plane.ts +98 -0
- package/src/auth/index.ts +112 -0
- package/src/auth/invites.ts +66 -0
- package/src/auth/invoke-as.ts +49 -0
- package/src/auth/operator.ts +178 -0
- package/src/auth/planes.ts +102 -0
- package/src/auth/plugin.ts +44 -0
- package/src/auth/roles.ts +84 -0
- package/src/auth/sessions.ts +418 -0
- package/src/auth/tables.ts +131 -0
- package/src/cli/args.ts +50 -0
- package/src/cli/branch.ts +75 -0
- package/src/cli/build.ts +86 -0
- package/src/cli/client-add.test.ts +140 -0
- package/src/cli/client-add.ts +164 -0
- package/src/cli/completion.test.ts +58 -0
- package/src/cli/completion.ts +296 -0
- package/src/cli/dev-app-runner.ts +77 -0
- package/src/cli/dev.test.ts +435 -0
- package/src/cli/dev.ts +594 -0
- package/src/cli/doc-drift.test.ts +146 -0
- package/src/cli/doc-drift.ts +397 -0
- package/src/cli/docker-cli.test.ts +221 -0
- package/src/cli/docker.ts +127 -0
- package/src/cli/doctor-diff-examples.ts +92 -0
- package/src/cli/doctor-diff.test.ts +91 -0
- package/src/cli/doctor-diff.ts +274 -0
- package/src/cli/doctor-pii.test.ts +98 -0
- package/src/cli/doctor-pii.ts +151 -0
- package/src/cli/doctor.test.ts +150 -0
- package/src/cli/doctor.ts +223 -0
- package/src/cli/eval.ts +122 -0
- package/src/cli/exit.ts +19 -0
- package/src/cli/gates-list.test.ts +47 -0
- package/src/cli/gates-list.ts +84 -0
- package/src/cli/images.ts +277 -0
- package/src/cli/index.ts +99 -0
- package/src/cli/json-out.test.ts +129 -0
- package/src/cli/load-config.ts +71 -0
- package/src/cli/mcp-from-console.ts +50 -0
- package/src/cli/privacy-erase.ts +73 -0
- package/src/cli/registry.ts +455 -0
- package/src/cli/safe-defaults.test.ts +92 -0
- package/src/cli/schema.ts +196 -0
- package/src/cli/stack.ts +82 -0
- package/src/cli/start.ts +106 -0
- package/src/cli/upgrade.ts +105 -0
- package/src/cli/vault-cmd.ts +140 -0
- package/src/client/budget-entry.ts +34 -0
- package/src/client/budget.test.ts +17 -0
- package/src/client/create.test.ts +159 -0
- package/src/client/create.ts +152 -0
- package/src/client/errors.ts +60 -0
- package/src/client/index.ts +35 -0
- package/src/client/notes-contract.test.ts +289 -0
- package/src/client/transport.test.ts +123 -0
- package/src/client/transport.ts +254 -0
- package/src/client/types.ts +282 -0
- package/src/compiler/aot.test.ts +248 -0
- package/src/compiler/aot.ts +182 -0
- package/src/compiler/differential.test.ts +241 -0
- package/src/compiler/dynamic.ts +54 -0
- package/src/compiler/effects-infer.ts +541 -0
- package/src/compiler/emit.ts +40 -0
- package/src/compiler/extract.test.ts +177 -0
- package/src/compiler/extract.ts +1368 -0
- package/src/compiler/fixtures/raw/raw-unannotated.ts +28 -0
- package/src/compiler/fixtures/skyport/oke.config.ts +24 -0
- package/src/compiler/fixtures/skyport/src/ai.ts +15 -0
- package/src/compiler/fixtures/skyport/src/app.ts +10 -0
- package/src/compiler/fixtures/skyport/src/channels.ts +6 -0
- package/src/compiler/fixtures/skyport/src/core.ts +3 -0
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +57 -0
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +11 -0
- package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +14 -0
- package/src/compiler/fixtures/skyport/src/flows/support/index.ts +20 -0
- package/src/compiler/fixtures/skyport/src/gates.ts +14 -0
- package/src/compiler/fixtures/skyport/src/journeys.ts +9 -0
- package/src/compiler/fixtures/skyport/src/schema.ts +3 -0
- package/src/compiler/fixtures/skyport/src/vault.ts +6 -0
- package/src/compiler/fixtures/skyport.expected.json +241 -0
- package/src/compiler/fixtures/triggers/five-triggers.ts +69 -0
- package/src/compiler/http-parse.ts +214 -0
- package/src/compiler/index.ts +67 -0
- package/src/compiler/response.ts +89 -0
- package/src/compiler/sucrose.ts +238 -0
- package/src/config/index.ts +167 -0
- package/src/console/budget.test.ts +73 -0
- package/src/console/index.ts +30 -0
- package/src/console/server/access.test.ts +370 -0
- package/src/console/server/access.ts +777 -0
- package/src/console/server/ai.test.ts +172 -0
- package/src/console/server/ai.ts +632 -0
- package/src/console/server/app.ts +294 -0
- package/src/console/server/auth-rate.test.ts +81 -0
- package/src/console/server/auth-rate.ts +72 -0
- package/src/console/server/bind.ts +25 -0
- package/src/console/server/channels.test.ts +179 -0
- package/src/console/server/channels.ts +469 -0
- package/src/console/server/claim.test.ts +66 -0
- package/src/console/server/claim.ts +134 -0
- package/src/console/server/clock.test.ts +239 -0
- package/src/console/server/clock.ts +390 -0
- package/src/console/server/console.test.ts +338 -0
- package/src/console/server/diff.test.ts +299 -0
- package/src/console/server/diff.ts +352 -0
- package/src/console/server/dry-run.audit.test.ts +118 -0
- package/src/console/server/flows-invoke.test.ts +148 -0
- package/src/console/server/flows.ts +3633 -0
- package/src/console/server/gates.test.ts +360 -0
- package/src/console/server/gates.ts +869 -0
- package/src/console/server/index.ts +141 -0
- package/src/console/server/live.test.ts +30 -0
- package/src/console/server/live.ts +109 -0
- package/src/console/server/plugin.ts +50 -0
- package/src/console/server/plugins.test.ts +131 -0
- package/src/console/server/plugins.ts +429 -0
- package/src/console/server/runs-pii.ts +98 -0
- package/src/console/server/security-headers.ts +97 -0
- package/src/console/server/security.gate.test.ts +286 -0
- package/src/console/server/serve.ts +319 -0
- package/src/console/server/signals.test.ts +88 -0
- package/src/console/server/signals.ts +282 -0
- package/src/console/server/state.ts +982 -0
- package/src/console/server/store.test.ts +233 -0
- package/src/console/server/store.ts +861 -0
- package/src/console/server/structural.ts +95 -0
- package/src/console/server/vault.test.ts +251 -0
- package/src/console/server/vault.ts +430 -0
- package/src/console/ui/access/AccessA11yView.tsx +237 -0
- package/src/console/ui/access/a11y.test.tsx +122 -0
- package/src/console/ui/access/acknowledgement.test.ts +13 -0
- package/src/console/ui/access/acknowledgement.ts +35 -0
- package/src/console/ui/access/blast-radius.test.ts +26 -0
- package/src/console/ui/access/blast-radius.ts +40 -0
- package/src/console/ui/access/confirmation.test.ts +38 -0
- package/src/console/ui/access/confirmation.ts +36 -0
- package/src/console/ui/access/fixture.ts +203 -0
- package/src/console/ui/access/grantable.test.ts +17 -0
- package/src/console/ui/access/grantable.ts +36 -0
- package/src/console/ui/access/hygiene.test.ts +12 -0
- package/src/console/ui/access/hygiene.ts +39 -0
- package/src/console/ui/access/index.ts +54 -0
- package/src/console/ui/access/provenance.test.ts +12 -0
- package/src/console/ui/access/provenance.ts +29 -0
- package/src/console/ui/access/search.test.ts +17 -0
- package/src/console/ui/access/search.ts +72 -0
- package/src/console/ui/access/types.ts +111 -0
- package/src/console/ui/ai/AiA11yView.tsx +265 -0
- package/src/console/ui/ai/a11y.test.tsx +99 -0
- package/src/console/ui/ai/findings.ts +41 -0
- package/src/console/ui/ai/fixture.ts +182 -0
- package/src/console/ui/ai/format.ts +90 -0
- package/src/console/ui/ai/group.test.ts +37 -0
- package/src/console/ui/ai/group.ts +88 -0
- package/src/console/ui/ai/index.ts +66 -0
- package/src/console/ui/ai/promotion.test.ts +77 -0
- package/src/console/ui/ai/promotion.ts +150 -0
- package/src/console/ui/ai/search.test.ts +40 -0
- package/src/console/ui/ai/search.ts +89 -0
- package/src/console/ui/ai/types.ts +139 -0
- package/src/console/ui/architecture/ArchitectureA11yView.tsx +163 -0
- package/src/console/ui/architecture/a11y.test.tsx +97 -0
- package/src/console/ui/architecture/boundary.ts +42 -0
- package/src/console/ui/architecture/declared.ts +165 -0
- package/src/console/ui/architecture/fixture.ts +74 -0
- package/src/console/ui/architecture/index.ts +84 -0
- package/src/console/ui/architecture/layers.ts +64 -0
- package/src/console/ui/architecture/layout.ts +68 -0
- package/src/console/ui/architecture/pathologies.ts +260 -0
- package/src/console/ui/architecture/search.ts +145 -0
- package/src/console/ui/architecture/traffic.ts +102 -0
- package/src/console/ui/architecture/types.ts +144 -0
- package/src/console/ui/architecture/view.test.ts +165 -0
- package/src/console/ui/architecture/view.ts +516 -0
- package/src/console/ui/channels/ChannelsA11yView.tsx +180 -0
- package/src/console/ui/channels/a11y.test.tsx +96 -0
- package/src/console/ui/channels/confirmation.test.ts +37 -0
- package/src/console/ui/channels/confirmation.ts +27 -0
- package/src/console/ui/channels/fallback.test.ts +15 -0
- package/src/console/ui/channels/fallback.ts +20 -0
- package/src/console/ui/channels/findings.ts +38 -0
- package/src/console/ui/channels/fixture.ts +134 -0
- package/src/console/ui/channels/group.ts +25 -0
- package/src/console/ui/channels/index.ts +57 -0
- package/src/console/ui/channels/locale.test.ts +17 -0
- package/src/console/ui/channels/locale.ts +31 -0
- package/src/console/ui/channels/mask.test.ts +14 -0
- package/src/console/ui/channels/mask.ts +12 -0
- package/src/console/ui/channels/search.ts +58 -0
- package/src/console/ui/channels/taxonomy.test.ts +17 -0
- package/src/console/ui/channels/taxonomy.ts +49 -0
- package/src/console/ui/channels/types.ts +117 -0
- package/src/console/ui/clock/ClockA11yView.tsx +182 -0
- package/src/console/ui/clock/a11y.test.tsx +99 -0
- package/src/console/ui/clock/confirmation.test.ts +32 -0
- package/src/console/ui/clock/confirmation.ts +34 -0
- package/src/console/ui/clock/findings.ts +40 -0
- package/src/console/ui/clock/fixture.ts +111 -0
- package/src/console/ui/clock/health.test.ts +25 -0
- package/src/console/ui/clock/health.ts +61 -0
- package/src/console/ui/clock/index.ts +49 -0
- package/src/console/ui/clock/search.test.ts +39 -0
- package/src/console/ui/clock/search.ts +76 -0
- package/src/console/ui/clock/timeline.test.ts +44 -0
- package/src/console/ui/clock/timeline.ts +41 -0
- package/src/console/ui/clock/types.ts +78 -0
- package/src/console/ui/clock/waiting-on.test.ts +34 -0
- package/src/console/ui/clock/waiting-on.ts +83 -0
- package/src/console/ui/confirmation.unify.test.ts +92 -0
- package/src/console/ui/diff/DiffA11yView.tsx +85 -0
- package/src/console/ui/diff/a11y.test.tsx +99 -0
- package/src/console/ui/diff/fixture.ts +85 -0
- package/src/console/ui/diff/group.test.ts +58 -0
- package/src/console/ui/diff/group.ts +97 -0
- package/src/console/ui/diff/index.ts +38 -0
- package/src/console/ui/diff/search.test.ts +32 -0
- package/src/console/ui/diff/search.ts +75 -0
- package/src/console/ui/diff/summary.ts +74 -0
- package/src/console/ui/diff/types.ts +48 -0
- package/src/console/ui/dist/assets/index-B71Yl_SS.js +10 -0
- package/src/console/ui/dist/assets/panel-access-Dd37LU2c.js +64 -0
- package/src/console/ui/dist/assets/panel-ai-CC7LR6-J.js +1 -0
- package/src/console/ui/dist/assets/panel-architecture-B5b3iKCz.js +1 -0
- package/src/console/ui/dist/assets/panel-channels-CeNjTKXp.js +1 -0
- package/src/console/ui/dist/assets/panel-clock-DgFTLoHV.js +1 -0
- package/src/console/ui/dist/assets/panel-diff-DxehccqB.js +1 -0
- package/src/console/ui/dist/assets/panel-flows-BtrVn-Eg.js +45 -0
- package/src/console/ui/dist/assets/panel-gates-Z9MKRGdH.js +1 -0
- package/src/console/ui/dist/assets/panel-overview-Bd48d9km.js +1 -0
- package/src/console/ui/dist/assets/panel-plugins-DWd0TowH.js +1 -0
- package/src/console/ui/dist/assets/panel-runs-BwsWqKeB.js +1 -0
- package/src/console/ui/dist/assets/panel-signals-9najbZY2.js +1 -0
- package/src/console/ui/dist/assets/panel-store-OHkP2pDp.js +1 -0
- package/src/console/ui/dist/assets/panel-traces-tn2JoY8U.js +1 -0
- package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +1 -0
- package/src/console/ui/dist/assets/rolldown-runtime-CNC7AqOf.js +1 -0
- package/src/console/ui/dist/assets/style-Cnl7WLya.css +3 -0
- package/src/console/ui/dist/index.html +14 -0
- package/src/console/ui/flows/FlowsA11yView.tsx +155 -0
- package/src/console/ui/flows/a11y.test.tsx +105 -0
- package/src/console/ui/flows/buffer.test.ts +91 -0
- package/src/console/ui/flows/buffer.ts +118 -0
- package/src/console/ui/flows/confirmation.ts +131 -0
- package/src/console/ui/flows/contract.test.ts +89 -0
- package/src/console/ui/flows/contract.ts +353 -0
- package/src/console/ui/flows/fixture.ts +81 -0
- package/src/console/ui/flows/graph.test.ts +101 -0
- package/src/console/ui/flows/graph.ts +549 -0
- package/src/console/ui/flows/index.ts +87 -0
- package/src/console/ui/flows/save-as-test.test.ts +47 -0
- package/src/console/ui/flows/save-as-test.ts +99 -0
- package/src/console/ui/flows/search.ts +255 -0
- package/src/console/ui/flows/tiers.ts +140 -0
- package/src/console/ui/gates/GatesA11yView.tsx +192 -0
- package/src/console/ui/gates/a11y.test.tsx +116 -0
- package/src/console/ui/gates/audit.test.ts +40 -0
- package/src/console/ui/gates/audit.ts +63 -0
- package/src/console/ui/gates/denial.test.ts +36 -0
- package/src/console/ui/gates/denial.ts +51 -0
- package/src/console/ui/gates/findings.ts +19 -0
- package/src/console/ui/gates/fixture.ts +189 -0
- package/src/console/ui/gates/group.test.ts +30 -0
- package/src/console/ui/gates/group.ts +102 -0
- package/src/console/ui/gates/index.ts +47 -0
- package/src/console/ui/gates/search.test.ts +49 -0
- package/src/console/ui/gates/search.ts +115 -0
- package/src/console/ui/gates/types.ts +121 -0
- package/src/console/ui/overview/OverviewA11yView.tsx +152 -0
- package/src/console/ui/overview/a11y.test.tsx +113 -0
- package/src/console/ui/overview/busiest.ts +26 -0
- package/src/console/ui/overview/compose.ts +133 -0
- package/src/console/ui/overview/cost.test.ts +39 -0
- package/src/console/ui/overview/cost.ts +138 -0
- package/src/console/ui/overview/fixture.ts +161 -0
- package/src/console/ui/overview/golden.ts +57 -0
- package/src/console/ui/overview/index.ts +59 -0
- package/src/console/ui/overview/rank.test.ts +136 -0
- package/src/console/ui/overview/rank.ts +210 -0
- package/src/console/ui/overview/slo.test.ts +73 -0
- package/src/console/ui/overview/slo.ts +229 -0
- package/src/console/ui/overview/types.ts +121 -0
- package/src/console/ui/overview/verdict.ts +131 -0
- package/src/console/ui/plugins/PluginsA11yView.tsx +227 -0
- package/src/console/ui/plugins/a11y.test.tsx +97 -0
- package/src/console/ui/plugins/command.test.ts +22 -0
- package/src/console/ui/plugins/command.ts +27 -0
- package/src/console/ui/plugins/findings.ts +39 -0
- package/src/console/ui/plugins/fixture.ts +233 -0
- package/src/console/ui/plugins/group.test.ts +38 -0
- package/src/console/ui/plugins/group.ts +67 -0
- package/src/console/ui/plugins/index.ts +40 -0
- package/src/console/ui/plugins/search.ts +67 -0
- package/src/console/ui/plugins/types.ts +115 -0
- package/src/console/ui/runs/RunsA11yView.tsx +267 -0
- package/src/console/ui/runs/a11y.test.tsx +99 -0
- package/src/console/ui/runs/explain.test.ts +23 -0
- package/src/console/ui/runs/explain.ts +32 -0
- package/src/console/ui/runs/fixture.ts +189 -0
- package/src/console/ui/runs/group.test.ts +24 -0
- package/src/console/ui/runs/group.ts +85 -0
- package/src/console/ui/runs/histogram.test.ts +31 -0
- package/src/console/ui/runs/histogram.ts +85 -0
- package/src/console/ui/runs/index.ts +75 -0
- package/src/console/ui/runs/project.ts +122 -0
- package/src/console/ui/runs/query.test.ts +50 -0
- package/src/console/ui/runs/query.ts +283 -0
- package/src/console/ui/runs/search.test.ts +45 -0
- package/src/console/ui/runs/search.ts +141 -0
- package/src/console/ui/runs/trace-link.test.ts +30 -0
- package/src/console/ui/runs/trace-link.ts +99 -0
- package/src/console/ui/runs/types.ts +137 -0
- package/src/console/ui/shell/App.tsx +56 -0
- package/src/console/ui/shell/client.ts +1715 -0
- package/src/console/ui/shell/components/ui.tsx +110 -0
- package/src/console/ui/shell/index.html +12 -0
- package/src/console/ui/shell/layout/Shell.tsx +95 -0
- package/src/console/ui/shell/main.tsx +281 -0
- package/src/console/ui/shell/panels/Access.tsx +5 -0
- package/src/console/ui/shell/panels/Ai.tsx +5 -0
- package/src/console/ui/shell/panels/Architecture.tsx +5 -0
- package/src/console/ui/shell/panels/Channels.tsx +5 -0
- package/src/console/ui/shell/panels/Clock.tsx +5 -0
- package/src/console/ui/shell/panels/Diff.tsx +5 -0
- package/src/console/ui/shell/panels/Flows.tsx +5 -0
- package/src/console/ui/shell/panels/Gates.tsx +5 -0
- package/src/console/ui/shell/panels/Overview.tsx +6 -0
- package/src/console/ui/shell/panels/Plugins.tsx +5 -0
- package/src/console/ui/shell/panels/Runs.tsx +5 -0
- package/src/console/ui/shell/panels/Signals.tsx +5 -0
- package/src/console/ui/shell/panels/Store.tsx +5 -0
- package/src/console/ui/shell/panels/Traces.tsx +5 -0
- package/src/console/ui/shell/panels/Vault.tsx +5 -0
- package/src/console/ui/shell/panels/access/AccessPanel.tsx +813 -0
- package/src/console/ui/shell/panels/ai/AiPanel.tsx +563 -0
- package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +377 -0
- package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +454 -0
- package/src/console/ui/shell/panels/clock/ClockPanel.tsx +479 -0
- package/src/console/ui/shell/panels/diff/DiffPanel.tsx +275 -0
- package/src/console/ui/shell/panels/flows/ContractEditor.tsx +301 -0
- package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +350 -0
- package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +502 -0
- package/src/console/ui/shell/panels/gates/GatesPanel.tsx +482 -0
- package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +428 -0
- package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +413 -0
- package/src/console/ui/shell/panels/runs/RunsPanel.tsx +649 -0
- package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +840 -0
- package/src/console/ui/shell/panels/store/StorePanel.tsx +787 -0
- package/src/console/ui/shell/panels/traces/TracesPanel.tsx +539 -0
- package/src/console/ui/shell/panels/vault/VaultPanel.tsx +449 -0
- package/src/console/ui/shell/plugin/Sandbox.tsx +29 -0
- package/src/console/ui/shell/setup/Wizard.tsx +189 -0
- package/src/console/ui/shell/styles.css +75 -0
- package/src/console/ui/signals/SignalsA11yView.tsx +276 -0
- package/src/console/ui/signals/a11y.test.tsx +99 -0
- package/src/console/ui/signals/confirmation.test.ts +39 -0
- package/src/console/ui/signals/confirmation.ts +63 -0
- package/src/console/ui/signals/dry-run.test.ts +18 -0
- package/src/console/ui/signals/dry-run.ts +36 -0
- package/src/console/ui/signals/durable.test.ts +22 -0
- package/src/console/ui/signals/durable.ts +41 -0
- package/src/console/ui/signals/findings.ts +33 -0
- package/src/console/ui/signals/fixture.ts +242 -0
- package/src/console/ui/signals/group.test.ts +32 -0
- package/src/console/ui/signals/group.ts +49 -0
- package/src/console/ui/signals/index.ts +52 -0
- package/src/console/ui/signals/monitor.test.ts +30 -0
- package/src/console/ui/signals/monitor.ts +79 -0
- package/src/console/ui/signals/schema-form.test.ts +34 -0
- package/src/console/ui/signals/schema-form.ts +112 -0
- package/src/console/ui/signals/search.ts +102 -0
- package/src/console/ui/signals/types.ts +71 -0
- package/src/console/ui/store/StoreA11yView.tsx +199 -0
- package/src/console/ui/store/a11y.test.tsx +99 -0
- package/src/console/ui/store/cache-view.test.ts +13 -0
- package/src/console/ui/store/cache-view.ts +36 -0
- package/src/console/ui/store/confirmation.test.ts +38 -0
- package/src/console/ui/store/confirmation.ts +55 -0
- package/src/console/ui/store/dry-run.test.ts +15 -0
- package/src/console/ui/store/dry-run.ts +29 -0
- package/src/console/ui/store/fixture.ts +163 -0
- package/src/console/ui/store/group.test.ts +21 -0
- package/src/console/ui/store/group.ts +41 -0
- package/src/console/ui/store/index.ts +40 -0
- package/src/console/ui/store/search.ts +78 -0
- package/src/console/ui/store/types.ts +65 -0
- package/src/console/ui/store/will-not-fire.test.ts +19 -0
- package/src/console/ui/store/will-not-fire.ts +40 -0
- package/src/console/ui/traces/TracesA11yView.tsx +200 -0
- package/src/console/ui/traces/a11y.test.tsx +97 -0
- package/src/console/ui/traces/chain.test.ts +61 -0
- package/src/console/ui/traces/chain.ts +144 -0
- package/src/console/ui/traces/critical-path.test.ts +24 -0
- package/src/console/ui/traces/critical-path.ts +59 -0
- package/src/console/ui/traces/filter.test.ts +78 -0
- package/src/console/ui/traces/filter.ts +112 -0
- package/src/console/ui/traces/fixture.ts +126 -0
- package/src/console/ui/traces/fold.test.ts +67 -0
- package/src/console/ui/traces/fold.ts +170 -0
- package/src/console/ui/traces/index.ts +64 -0
- package/src/console/ui/traces/mini.ts +65 -0
- package/src/console/ui/traces/replay.test.ts +24 -0
- package/src/console/ui/traces/replay.ts +35 -0
- package/src/console/ui/traces/sampling.test.ts +26 -0
- package/src/console/ui/traces/sampling.ts +66 -0
- package/src/console/ui/traces/search.ts +148 -0
- package/src/console/ui/traces/tier.ts +72 -0
- package/src/console/ui/traces/types.ts +125 -0
- package/src/console/ui/tsconfig.json +20 -0
- package/src/console/ui/vault/VaultA11yView.tsx +177 -0
- package/src/console/ui/vault/a11y.test.tsx +97 -0
- package/src/console/ui/vault/blast-radius.test.ts +35 -0
- package/src/console/ui/vault/blast-radius.ts +55 -0
- package/src/console/ui/vault/confirmation.test.ts +41 -0
- package/src/console/ui/vault/confirmation.ts +39 -0
- package/src/console/ui/vault/dormant.test.ts +37 -0
- package/src/console/ui/vault/dormant.ts +28 -0
- package/src/console/ui/vault/export-safe.test.ts +30 -0
- package/src/console/ui/vault/export-safe.ts +65 -0
- package/src/console/ui/vault/fixture.ts +75 -0
- package/src/console/ui/vault/group.test.ts +25 -0
- package/src/console/ui/vault/group.ts +50 -0
- package/src/console/ui/vault/index.ts +45 -0
- package/src/console/ui/vault/search.ts +62 -0
- package/src/console/ui/vault/types.ts +57 -0
- package/src/console/ui/vite.config.ts +84 -0
- package/src/console/xss.gate.test.ts +118 -0
- package/src/docker/compose.ts +226 -0
- package/src/docker/credentials.ts +25 -0
- package/src/docker/derive.ts +83 -0
- package/src/docker/docker.test.ts +185 -0
- package/src/docker/dockerfile.integration.test.ts +170 -0
- package/src/docker/dockerfile.ts +39 -0
- package/src/docker/helpers.ts +103 -0
- package/src/docker/index.ts +52 -0
- package/src/docker/pin.ts +90 -0
- package/src/docker/recipes/index.ts +33 -0
- package/src/docker/recipes/postgres.ts +18 -0
- package/src/docker/recipes/redis.ts +18 -0
- package/src/docker/stack.integration.test.ts +140 -0
- package/src/docker/stack.ts +62 -0
- package/src/docker/types.ts +134 -0
- package/src/drivers/ai-anthropic.ts +128 -0
- package/src/drivers/ai-mock.ts +82 -0
- package/src/drivers/ai-openai-compatible.ts +139 -0
- package/src/drivers/ai-providers.test.ts +163 -0
- package/src/drivers/ai-types.ts +83 -0
- package/src/drivers/bun-native-completeness.test.ts +155 -0
- package/src/drivers/channel-console.ts +118 -0
- package/src/drivers/channel-fcm.ts +96 -0
- package/src/drivers/channel-resend.ts +27 -0
- package/src/drivers/channel-smtp.ts +33 -0
- package/src/drivers/channel-types.ts +160 -0
- package/src/drivers/channel-unifonic.ts +79 -0
- package/src/drivers/channel-wa-cloud.ts +84 -0
- package/src/drivers/channel-webpush.ts +317 -0
- package/src/drivers/conformance.test.ts +89 -0
- package/src/drivers/conformance.ts +162 -0
- package/src/drivers/fs.ts +73 -0
- package/src/drivers/index.ts +194 -0
- package/src/drivers/kv-lua.ts +222 -0
- package/src/drivers/memory.ts +472 -0
- package/src/drivers/pgvector.ts +130 -0
- package/src/drivers/postgres.ts +221 -0
- package/src/drivers/redis.ts +254 -0
- package/src/drivers/s3.ts +129 -0
- package/src/drivers/signal-engine.ts +690 -0
- package/src/drivers/signal-memory.ts +27 -0
- package/src/drivers/signal-nats.ts +131 -0
- package/src/drivers/signal-postgres.ts +1089 -0
- package/src/drivers/signal-redis.ts +275 -0
- package/src/drivers/signal-types.ts +328 -0
- package/src/drivers/sqlite.ts +53 -0
- package/src/drivers/types.ts +334 -0
- package/src/drivers/vault-dotenv-parse.ts +56 -0
- package/src/drivers/vault-env.ts +101 -0
- package/src/drivers/vault-infisical.ts +61 -0
- package/src/drivers/vault-managed.ts +42 -0
- package/src/drivers/vault-memory.ts +38 -0
- package/src/drivers/vault-openbao.ts +80 -0
- package/src/drivers/vault-sops.ts +252 -0
- package/src/drivers/vault-types.ts +84 -0
- package/src/elements/ai/declare.ts +206 -0
- package/src/elements/ai/eval.ts +113 -0
- package/src/elements/ai/pii.ts +108 -0
- package/src/elements/ai/runtime.ts +540 -0
- package/src/elements/ai/schema.ts +194 -0
- package/src/elements/ai.test.ts +393 -0
- package/src/elements/ai.ts +56 -0
- package/src/elements/channel/consent.ts +81 -0
- package/src/elements/channel/costs.test.ts +62 -0
- package/src/elements/channel/costs.ts +130 -0
- package/src/elements/channel/declare.ts +141 -0
- package/src/elements/channel/email-auth.test.ts +47 -0
- package/src/elements/channel/email-auth.ts +109 -0
- package/src/elements/channel/locale.ts +97 -0
- package/src/elements/channel/mask.test.ts +19 -0
- package/src/elements/channel/mask.ts +60 -0
- package/src/elements/channel/mime.ts +23 -0
- package/src/elements/channel/outcomes.test.ts +40 -0
- package/src/elements/channel/outcomes.ts +126 -0
- package/src/elements/channel/receipts.ts +121 -0
- package/src/elements/channel/runtime.ts +500 -0
- package/src/elements/channel/suppression.ts +136 -0
- package/src/elements/channel.test.ts +232 -0
- package/src/elements/channel.ts +109 -0
- package/src/elements/clock/actions.ts +170 -0
- package/src/elements/clock/declare.ts +58 -0
- package/src/elements/clock/dst.ts +197 -0
- package/src/elements/clock/durable.ts +140 -0
- package/src/elements/clock/duration.ts +29 -0
- package/src/elements/clock/health.test.ts +103 -0
- package/src/elements/clock/health.ts +112 -0
- package/src/elements/clock/leader.ts +127 -0
- package/src/elements/clock/reconcile.ts +241 -0
- package/src/elements/clock/runtime.ts +243 -0
- package/src/elements/clock/schedule.ts +262 -0
- package/src/elements/clock/time-travel.ts +53 -0
- package/src/elements/clock.test.ts +365 -0
- package/src/elements/clock.ts +80 -0
- package/src/elements/gate/declare.ts +134 -0
- package/src/elements/gate/permissions.ts +104 -0
- package/src/elements/gate/runtime.ts +177 -0
- package/src/elements/gate/strategies.ts +388 -0
- package/src/elements/gate.test.ts +145 -0
- package/src/elements/gate.ts +41 -0
- package/src/elements/index.ts +169 -0
- package/src/elements/signal/chaos-child.ts +47 -0
- package/src/elements/signal/declare.ts +77 -0
- package/src/elements/signal/dry-run-replay.test.ts +95 -0
- package/src/elements/signal/dry-run-write-isolation.test.ts +94 -0
- package/src/elements/signal/reconcile.test.ts +23 -0
- package/src/elements/signal/reconcile.ts +122 -0
- package/src/elements/signal/runtime.ts +94 -0
- package/src/elements/signal.test.ts +457 -0
- package/src/elements/signal.ts +26 -0
- package/src/elements/store/cache.ts +197 -0
- package/src/elements/store/classify.ts +125 -0
- package/src/elements/store/declare.ts +200 -0
- package/src/elements/store/files-policy.test.ts +31 -0
- package/src/elements/store/files-policy.ts +70 -0
- package/src/elements/store/replica.ts +68 -0
- package/src/elements/store/runtime.ts +393 -0
- package/src/elements/store/sql-condition.ts +205 -0
- package/src/elements/store/sql-session.ts +579 -0
- package/src/elements/store/table.ts +282 -0
- package/src/elements/store.test.ts +370 -0
- package/src/elements/store.ts +99 -0
- package/src/elements/vault/declare.ts +143 -0
- package/src/elements/vault/fingerprint.ts +30 -0
- package/src/elements/vault/redact.ts +52 -0
- package/src/elements/vault/runtime.ts +461 -0
- package/src/elements/vault.test.ts +296 -0
- package/src/elements/vault.ts +44 -0
- package/src/index.ts +183 -0
- package/src/kernel/adopt-routes.ts +194 -0
- package/src/kernel/app.ts +1068 -0
- package/src/kernel/auth-resolve.ts +93 -0
- package/src/kernel/boot.test.ts +173 -0
- package/src/kernel/boot.ts +439 -0
- package/src/kernel/budget-entry.ts +55 -0
- package/src/kernel/budget.test.ts +19 -0
- package/src/kernel/call.test.ts +83 -0
- package/src/kernel/capability.ts +113 -0
- package/src/kernel/dry-run.test.ts +64 -0
- package/src/kernel/dry-run.ts +171 -0
- package/src/kernel/effects.test.ts +89 -0
- package/src/kernel/effects.ts +140 -0
- package/src/kernel/errors.registry.test.ts +39 -0
- package/src/kernel/errors.ts +225 -0
- package/src/kernel/flow.test.ts +154 -0
- package/src/kernel/flow.ts +290 -0
- package/src/kernel/fx.test.ts +245 -0
- package/src/kernel/fx.ts +996 -0
- package/src/kernel/hook-timing.test.ts +72 -0
- package/src/kernel/hook-timing.ts +190 -0
- package/src/kernel/hooks.test.ts +181 -0
- package/src/kernel/hooks.ts +275 -0
- package/src/kernel/index.ts +278 -0
- package/src/kernel/journal.ts +405 -0
- package/src/kernel/journey.ts +75 -0
- package/src/kernel/on.ts +74 -0
- package/src/kernel/pipeline.test.ts +349 -0
- package/src/kernel/pipeline.ts +245 -0
- package/src/kernel/plug.ts +82 -0
- package/src/kernel/plugin/capabilities.test.ts +84 -0
- package/src/kernel/plugin/conflicts.test.ts +106 -0
- package/src/kernel/plugin/decorate.test.ts +111 -0
- package/src/kernel/plugin/scoping.test.ts +138 -0
- package/src/kernel/plugin.ts +485 -0
- package/src/kernel/rate-limit.ts +25 -0
- package/src/kernel/registry.ts +398 -0
- package/src/kernel/router.test.ts +114 -0
- package/src/kernel/router.ts +556 -0
- package/src/kernel/routing-budget.test.ts +19 -0
- package/src/kernel/run-telemetry.ts +70 -0
- package/src/kernel/triggers.ts +324 -0
- package/src/kernel/unit.ts +88 -0
- package/src/manifest/diff.test.ts +866 -0
- package/src/manifest/diff.ts +1670 -0
- package/src/manifest/fixtures/base.manifest.json +112 -0
- package/src/manifest/fixtures/skyport.excerpt.json +51 -0
- package/src/manifest/fixtures/skyport.manifest.json +153 -0
- package/src/manifest/index.ts +27 -0
- package/src/manifest/types.ts +358 -0
- package/src/manifest/undeclared.test.ts +82 -0
- package/src/manifest/undeclared.ts +65 -0
- package/src/manifest/validate.test.ts +105 -0
- package/src/manifest/validate.ts +174 -0
- package/src/mcp/authorization.ts +340 -0
- package/src/mcp/confirmation.ts +174 -0
- package/src/mcp/data.ts +90 -0
- package/src/mcp/index.ts +80 -0
- package/src/mcp/injection.gate.test.ts +176 -0
- package/src/mcp/mcp.test.ts +348 -0
- package/src/mcp/protocol.ts +172 -0
- package/src/mcp/server.ts +283 -0
- package/src/mcp/session.ts +139 -0
- package/src/mcp/tools.ts +391 -0
- package/src/plugins/catalogue.test.ts +48 -0
- package/src/plugins/catalogue.ts +113 -0
- package/src/plugins/node-import-scan.test.ts +28 -0
- package/src/plugins/node-import-scan.ts +98 -0
- package/src/plugins/supply-chain.test.ts +48 -0
- package/src/plugins/supply-chain.ts +460 -0
- package/src/release/index.ts +30 -0
- package/src/release/limits.ts +20 -0
- package/src/release/measure.ts +443 -0
- package/src/release/publish.ts +56 -0
- package/src/runs/bench.test.ts +93 -0
- package/src/runs/collect.ts +144 -0
- package/src/runs/drivers/clickhouse.ts +108 -0
- package/src/runs/drivers/files.ts +201 -0
- package/src/runs/drivers/memory.ts +94 -0
- package/src/runs/drivers/postgres.ts +110 -0
- package/src/runs/duckdb.ts +99 -0
- package/src/runs/index.ts +82 -0
- package/src/runs/outlier.ts +180 -0
- package/src/runs/parquet.ts +210 -0
- package/src/runs/privacy.ts +49 -0
- package/src/runs/runs.test.ts +324 -0
- package/src/runs/runtime.ts +229 -0
- package/src/runs/shred.ts +243 -0
- package/src/runs/telemetry.ts +10 -0
- package/src/runs/types.ts +179 -0
- package/src/runtime/bun.ts +140 -0
- package/src/runtime/cold-start.bench.ts +20 -0
- package/src/runtime/index.ts +46 -0
- package/src/runtime/primitives.ts +242 -0
- package/src/runtime/security.test.ts +170 -0
- package/src/runtime/security.ts +168 -0
- package/src/runtime/serve.test.ts +223 -0
- package/src/runtime/types.ts +217 -0
- package/src/runtime/web-standard.ts +77 -0
- package/src/test/create-test-app.test.ts +161 -0
- package/src/test/create-test-app.ts +533 -0
- package/src/test/index.ts +21 -0
- package/src/test/provisions.integration.test.ts +174 -0
- package/src/upgrade/codemods.test.ts +58 -0
- package/src/upgrade/codemods.ts +83 -0
- package/src/validation/index.ts +23 -0
- package/src/validation/standard-schema.test.ts +96 -0
- package/src/validation/standard-schema.ts +316 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bun native-client completeness — gaps closed vs platform limitations.
|
|
3
|
+
*
|
|
4
|
+
* Checked against Bun 1.3.14 (runtime + bun-types). Do not invent custom
|
|
5
|
+
* protocol clients where Bun still lacks an API.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, expect, test } from "bun:test";
|
|
9
|
+
import { createBunRedisClient } from "./redis.ts";
|
|
10
|
+
import {
|
|
11
|
+
createBunSignalRedisClient,
|
|
12
|
+
parseXreadgroupReply,
|
|
13
|
+
} from "./signal-redis.ts";
|
|
14
|
+
|
|
15
|
+
/** One row in the completeness report. */
|
|
16
|
+
export interface BunNativeGapRow {
|
|
17
|
+
readonly surface: string;
|
|
18
|
+
readonly capability: string;
|
|
19
|
+
readonly status: "closed" | "bun_limitation";
|
|
20
|
+
readonly note: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Report table: which Bun client gaps closed vs genuine platform limits.
|
|
25
|
+
*
|
|
26
|
+
* Kept as a pure function so the gate test and human report share one source.
|
|
27
|
+
*/
|
|
28
|
+
export function bunNativeCompletenessReport(): readonly BunNativeGapRow[] {
|
|
29
|
+
const redisProto = Bun.RedisClient.prototype as unknown as Record<
|
|
30
|
+
string,
|
|
31
|
+
unknown
|
|
32
|
+
>;
|
|
33
|
+
const hasTypedScan = typeof redisProto.scan === "function";
|
|
34
|
+
const hasTypedPublish = typeof redisProto.publish === "function";
|
|
35
|
+
const hasTypedSubscribe = typeof redisProto.subscribe === "function";
|
|
36
|
+
const hasTypedSend = typeof redisProto.send === "function";
|
|
37
|
+
const hasTypedXadd = typeof redisProto.xadd === "function";
|
|
38
|
+
const hasTypedEval = typeof redisProto.eval === "function";
|
|
39
|
+
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
surface: "redis kv",
|
|
43
|
+
capability: "SCAN (typed)",
|
|
44
|
+
status: hasTypedScan ? "closed" : "bun_limitation",
|
|
45
|
+
note: hasTypedScan
|
|
46
|
+
? "createBunRedisClient binds RedisClient.scan"
|
|
47
|
+
: "Bun.redis.scan unavailable — would keep send(SCAN)",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
surface: "redis kv",
|
|
51
|
+
capability: "EVAL (typed)",
|
|
52
|
+
status: hasTypedEval ? "closed" : "bun_limitation",
|
|
53
|
+
note: hasTypedEval
|
|
54
|
+
? "typed eval bound"
|
|
55
|
+
: "Bun 1.3.14 has no typed eval — driver uses send(EVAL)",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
surface: "redis signal",
|
|
59
|
+
capability: "native Bun bind (publish/subscribe)",
|
|
60
|
+
status:
|
|
61
|
+
hasTypedPublish && hasTypedSubscribe ? "closed" : "bun_limitation",
|
|
62
|
+
note:
|
|
63
|
+
hasTypedPublish && hasTypedSubscribe
|
|
64
|
+
? "createBunSignalRedisClient uses typed publish/subscribe"
|
|
65
|
+
: "pub/sub still unavailable on Bun.RedisClient",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
surface: "redis signal",
|
|
69
|
+
capability: "XADD / XREADGROUP (typed)",
|
|
70
|
+
status: hasTypedXadd ? "closed" : "bun_limitation",
|
|
71
|
+
note: hasTypedXadd
|
|
72
|
+
? "typed stream helpers bound"
|
|
73
|
+
: "Bun 1.3.14 has no typed xadd — Streams use send (native, not a custom client)",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
surface: "redis signal",
|
|
77
|
+
capability: "send escape hatch",
|
|
78
|
+
status: hasTypedSend ? "closed" : "bun_limitation",
|
|
79
|
+
note: hasTypedSend
|
|
80
|
+
? "send present — Streams/EVAL ride the native client"
|
|
81
|
+
: "Bun.RedisClient.send missing",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
surface: "postgres signal",
|
|
85
|
+
capability: "LISTEN / NOTIFY on Bun.SQL",
|
|
86
|
+
status: "bun_limitation",
|
|
87
|
+
note: "Bun.SQL has no listen/notify API — injectable PostgresSignalSql + fake remain",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
surface: "postgres sql",
|
|
91
|
+
capability: "Bun.SQL.unsafe query/exec",
|
|
92
|
+
status: "closed",
|
|
93
|
+
note: "postgres driver already binds Bun.SQL; fake only for CI without a server",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
surface: "s3 files",
|
|
97
|
+
capability: "Bun.S3Client file/list",
|
|
98
|
+
status: "closed",
|
|
99
|
+
note: "s3 driver binds write/arrayBuffer/exists/delete/list; presign/multipart unused by FilesBucket",
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
describe("Bun native client completeness", () => {
|
|
105
|
+
test("report table is exact and matches runtime Bun 1.3.x", () => {
|
|
106
|
+
const rows = bunNativeCompletenessReport();
|
|
107
|
+
expect(rows.length).toBe(8);
|
|
108
|
+
|
|
109
|
+
const closed = rows.filter((r) => r.status === "closed").map((r) => r.capability);
|
|
110
|
+
const limited = rows
|
|
111
|
+
.filter((r) => r.status === "bun_limitation")
|
|
112
|
+
.map((r) => r.capability);
|
|
113
|
+
|
|
114
|
+
// Closed on Bun 1.3.14
|
|
115
|
+
expect(closed).toContain("SCAN (typed)");
|
|
116
|
+
expect(closed).toContain("native Bun bind (publish/subscribe)");
|
|
117
|
+
expect(closed).toContain("send escape hatch");
|
|
118
|
+
expect(closed).toContain("Bun.SQL.unsafe query/exec");
|
|
119
|
+
expect(closed).toContain("Bun.S3Client file/list");
|
|
120
|
+
|
|
121
|
+
// Genuine Bun platform limitations (do not invent workarounds)
|
|
122
|
+
expect(limited).toContain("EVAL (typed)");
|
|
123
|
+
expect(limited).toContain("XADD / XREADGROUP (typed)");
|
|
124
|
+
expect(limited).toContain("LISTEN / NOTIFY on Bun.SQL");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("createBunRedisClient exposes native scan", () => {
|
|
128
|
+
const client = createBunRedisClient();
|
|
129
|
+
expect(typeof client.scan).toBe("function");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("createBunSignalRedisClient exposes stream + pub/sub surface", () => {
|
|
133
|
+
const client = createBunSignalRedisClient();
|
|
134
|
+
expect(typeof client.xadd).toBe("function");
|
|
135
|
+
expect(typeof client.publish).toBe("function");
|
|
136
|
+
expect(typeof client.subscribe).toBe("function");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("parseXreadgroupReply reads nested Redis arrays", () => {
|
|
140
|
+
const parsed = parseXreadgroupReply([
|
|
141
|
+
[
|
|
142
|
+
"oke:signal:order",
|
|
143
|
+
[
|
|
144
|
+
["1-0", ["payload", "{\"a\":1}", "signal", "order"]],
|
|
145
|
+
["1-1", ["payload", "{}", "signal", "order"]],
|
|
146
|
+
],
|
|
147
|
+
],
|
|
148
|
+
]);
|
|
149
|
+
expect(parsed).toEqual([
|
|
150
|
+
{ id: "1-0", fields: { payload: "{\"a\":1}", signal: "order" } },
|
|
151
|
+
{ id: "1-1", fields: { payload: "{}", signal: "order" } },
|
|
152
|
+
]);
|
|
153
|
+
expect(parseXreadgroupReply(null)).toEqual([]);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `console` channel driver — dev inbox for every medium.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { AddressInput, MailOptions, SendResult, Transport } from "sently";
|
|
6
|
+
import type {
|
|
7
|
+
ChannelDriver,
|
|
8
|
+
ChannelInbox,
|
|
9
|
+
ChannelMessage,
|
|
10
|
+
ChannelOpenOptions,
|
|
11
|
+
ChannelSendResult,
|
|
12
|
+
ChannelTransport,
|
|
13
|
+
} from "./channel-types.ts";
|
|
14
|
+
import { createChannelInbox } from "./channel-types.ts";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Flatten a sently {@link AddressInput} to a comma-separated string.
|
|
18
|
+
*
|
|
19
|
+
* @param input - Address input
|
|
20
|
+
*/
|
|
21
|
+
function formatAddressInput(input: AddressInput): string {
|
|
22
|
+
if (typeof input === "string") return input;
|
|
23
|
+
if (Array.isArray(input)) {
|
|
24
|
+
return input
|
|
25
|
+
.map((t) => (typeof t === "string" ? t : t.address))
|
|
26
|
+
.join(",");
|
|
27
|
+
}
|
|
28
|
+
return input.address;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Open a console channel driver bound to an inbox.
|
|
33
|
+
*
|
|
34
|
+
* @param options - Optional shared inbox
|
|
35
|
+
*/
|
|
36
|
+
export function openConsoleChannel(
|
|
37
|
+
options: ChannelOpenOptions = {},
|
|
38
|
+
): ChannelDriver {
|
|
39
|
+
const inbox = options.inbox ?? createChannelInbox();
|
|
40
|
+
|
|
41
|
+
const channel: ChannelTransport = {
|
|
42
|
+
provider: "console",
|
|
43
|
+
mediums: ["email", "sms", "whatsapp", "push", "any"],
|
|
44
|
+
async send(message: ChannelMessage): Promise<ChannelSendResult> {
|
|
45
|
+
const id = crypto.randomUUID();
|
|
46
|
+
inbox.push({
|
|
47
|
+
id,
|
|
48
|
+
medium: message.medium,
|
|
49
|
+
to: message.to,
|
|
50
|
+
subject: message.subject,
|
|
51
|
+
text: message.text,
|
|
52
|
+
html: message.html,
|
|
53
|
+
data: message.data,
|
|
54
|
+
template: message.template,
|
|
55
|
+
locale: message.locale,
|
|
56
|
+
at: Date.now(),
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
ok: true,
|
|
60
|
+
messageId: id,
|
|
61
|
+
driverId: "console",
|
|
62
|
+
attempts: [
|
|
63
|
+
{
|
|
64
|
+
driverId: "console",
|
|
65
|
+
ok: true,
|
|
66
|
+
at: Date.now(),
|
|
67
|
+
messageId: id,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const transport: Transport = {
|
|
75
|
+
provider: "console",
|
|
76
|
+
async send(mail: MailOptions): Promise<SendResult> {
|
|
77
|
+
const to = formatAddressInput(mail.to);
|
|
78
|
+
const from = formatAddressInput(mail.from);
|
|
79
|
+
const id = crypto.randomUUID();
|
|
80
|
+
inbox.push({
|
|
81
|
+
id,
|
|
82
|
+
medium: "email",
|
|
83
|
+
to,
|
|
84
|
+
subject: mail.subject,
|
|
85
|
+
text: mail.text,
|
|
86
|
+
html: mail.html,
|
|
87
|
+
data: mail.data,
|
|
88
|
+
template: mail.template,
|
|
89
|
+
at: Date.now(),
|
|
90
|
+
});
|
|
91
|
+
const recipients = to.split(",").map((s) => s.trim()).filter(Boolean);
|
|
92
|
+
return {
|
|
93
|
+
messageId: id,
|
|
94
|
+
accepted: recipients,
|
|
95
|
+
rejected: [],
|
|
96
|
+
response: "console: accepted",
|
|
97
|
+
envelope: {
|
|
98
|
+
from,
|
|
99
|
+
to: recipients,
|
|
100
|
+
},
|
|
101
|
+
provider: "console",
|
|
102
|
+
providerIndex: 0,
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return { id: "console", transport, channel };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Console driver factory (stateless open via {@link openConsoleChannel}).
|
|
112
|
+
*/
|
|
113
|
+
export const consoleChannelDriver = {
|
|
114
|
+
id: "console" as const,
|
|
115
|
+
open: openConsoleChannel,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export type { ChannelInbox };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `fcm` channel driver — Firebase Cloud Messaging HTTP v1 (protocol-shaped).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
ChannelDriver,
|
|
7
|
+
ChannelMessage,
|
|
8
|
+
ChannelOpenOptions,
|
|
9
|
+
ChannelSendResult,
|
|
10
|
+
ChannelTransport,
|
|
11
|
+
} from "./channel-types.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Open an FCM push driver.
|
|
15
|
+
*
|
|
16
|
+
* @param options - `token` (OAuth access token) + `from` (project id)
|
|
17
|
+
*/
|
|
18
|
+
export function openFcmChannel(
|
|
19
|
+
options: ChannelOpenOptions = {},
|
|
20
|
+
): ChannelDriver {
|
|
21
|
+
const accessToken = options.token ?? options.apiKey;
|
|
22
|
+
const projectId = options.from;
|
|
23
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
24
|
+
const base = options.url ?? "https://fcm.googleapis.com";
|
|
25
|
+
|
|
26
|
+
const channel: ChannelTransport = {
|
|
27
|
+
provider: "fcm",
|
|
28
|
+
mediums: ["push"],
|
|
29
|
+
async send(message: ChannelMessage): Promise<ChannelSendResult> {
|
|
30
|
+
if (!accessToken || !projectId) {
|
|
31
|
+
throw new Error("fcm: token and from (project id) are required");
|
|
32
|
+
}
|
|
33
|
+
const res = await fetchFn(
|
|
34
|
+
`${base}/v1/projects/${projectId}/messages:send`,
|
|
35
|
+
{
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: `Bearer ${accessToken}`,
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({
|
|
42
|
+
message: {
|
|
43
|
+
token: message.to,
|
|
44
|
+
notification: {
|
|
45
|
+
title: message.subject ?? message.template ?? "notification",
|
|
46
|
+
body: message.text ?? "",
|
|
47
|
+
},
|
|
48
|
+
data: Object.fromEntries(
|
|
49
|
+
Object.entries(message.data ?? {}).map(([k, v]) => [
|
|
50
|
+
k,
|
|
51
|
+
String(v),
|
|
52
|
+
]),
|
|
53
|
+
),
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
const body = (await res.json().catch(() => ({}))) as {
|
|
59
|
+
name?: string;
|
|
60
|
+
error?: { message?: string };
|
|
61
|
+
};
|
|
62
|
+
const id = body.name ?? crypto.randomUUID();
|
|
63
|
+
if (!res.ok) {
|
|
64
|
+
return {
|
|
65
|
+
ok: false,
|
|
66
|
+
messageId: id,
|
|
67
|
+
driverId: "fcm",
|
|
68
|
+
attempts: [
|
|
69
|
+
{
|
|
70
|
+
driverId: "fcm",
|
|
71
|
+
ok: false,
|
|
72
|
+
error: body.error?.message ?? `HTTP ${res.status}`,
|
|
73
|
+
at: Date.now(),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
ok: true,
|
|
80
|
+
messageId: id,
|
|
81
|
+
driverId: "fcm",
|
|
82
|
+
attempts: [
|
|
83
|
+
{ driverId: "fcm", ok: true, at: Date.now(), messageId: id },
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return { id: "fcm", channel };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** FCM driver factory. */
|
|
93
|
+
export const fcmChannelDriver = {
|
|
94
|
+
id: "fcm" as const,
|
|
95
|
+
open: openFcmChannel,
|
|
96
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resend` channel driver — wraps sently's Resend transport unchanged.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ResendTransport } from "sently/transports/resend";
|
|
6
|
+
import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Open a Resend channel driver.
|
|
10
|
+
*
|
|
11
|
+
* @param options - API key
|
|
12
|
+
*/
|
|
13
|
+
export function openResendChannel(
|
|
14
|
+
options: ChannelOpenOptions = {},
|
|
15
|
+
): ChannelDriver {
|
|
16
|
+
if (!options.apiKey) {
|
|
17
|
+
throw new Error("resend channel: apiKey is required");
|
|
18
|
+
}
|
|
19
|
+
const transport = new ResendTransport({ apiKey: options.apiKey });
|
|
20
|
+
return { id: "resend", transport };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Resend driver factory. */
|
|
24
|
+
export const resendChannelDriver = {
|
|
25
|
+
id: "resend" as const,
|
|
26
|
+
open: openResendChannel,
|
|
27
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `smtp` channel driver — wraps sently's SMTP transport unchanged.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { SMTPTransport } from "sently/transports/smtp";
|
|
6
|
+
import type { ChannelDriver, ChannelOpenOptions } from "./channel-types.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Open an SMTP channel driver.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Host / port / auth
|
|
12
|
+
*/
|
|
13
|
+
export function openSmtpChannel(
|
|
14
|
+
options: ChannelOpenOptions = {},
|
|
15
|
+
): ChannelDriver {
|
|
16
|
+
if (!options.host) {
|
|
17
|
+
throw new Error("smtp channel: host is required");
|
|
18
|
+
}
|
|
19
|
+
const transport = new SMTPTransport({
|
|
20
|
+
host: options.host,
|
|
21
|
+
port: options.port ?? 587,
|
|
22
|
+
...(options.user && options.pass
|
|
23
|
+
? { auth: { user: options.user, pass: options.pass } }
|
|
24
|
+
: {}),
|
|
25
|
+
});
|
|
26
|
+
return { id: "smtp", transport };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** SMTP driver factory. */
|
|
30
|
+
export const smtpChannelDriver = {
|
|
31
|
+
id: "smtp" as const,
|
|
32
|
+
open: openSmtpChannel,
|
|
33
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Protocol-named channel driver contracts.
|
|
3
|
+
*
|
|
4
|
+
* Email transports implement sently's {@link Transport} so sently transports
|
|
5
|
+
* run unchanged. Non-email media (sms / whatsapp / push) use {@link ChannelTransport}.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
MailOptions,
|
|
10
|
+
SendResult,
|
|
11
|
+
Transport,
|
|
12
|
+
VerifyResult,
|
|
13
|
+
} from "sently";
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
Address,
|
|
17
|
+
AddressInput,
|
|
18
|
+
Attachment,
|
|
19
|
+
MailOptions,
|
|
20
|
+
SendResult,
|
|
21
|
+
Transport,
|
|
22
|
+
VerifyResult,
|
|
23
|
+
Envelope,
|
|
24
|
+
RetryConfig,
|
|
25
|
+
} from "sently";
|
|
26
|
+
|
|
27
|
+
/** Protocol ids for channel drivers. */
|
|
28
|
+
export type ChannelDriverId =
|
|
29
|
+
| "console"
|
|
30
|
+
| "smtp"
|
|
31
|
+
| "resend"
|
|
32
|
+
| "unifonic"
|
|
33
|
+
| "wa-cloud"
|
|
34
|
+
| "fcm"
|
|
35
|
+
| "webpush";
|
|
36
|
+
|
|
37
|
+
/** Channel medium. */
|
|
38
|
+
export type ChannelMediumId =
|
|
39
|
+
| "email"
|
|
40
|
+
| "sms"
|
|
41
|
+
| "whatsapp"
|
|
42
|
+
| "push"
|
|
43
|
+
| "any";
|
|
44
|
+
|
|
45
|
+
/** Unified outbound message (medium-agnostic). */
|
|
46
|
+
export interface ChannelMessage {
|
|
47
|
+
readonly medium: ChannelMediumId;
|
|
48
|
+
readonly to: string;
|
|
49
|
+
readonly from?: string;
|
|
50
|
+
readonly subject?: string;
|
|
51
|
+
readonly text?: string;
|
|
52
|
+
readonly html?: string;
|
|
53
|
+
readonly data?: Readonly<Record<string, unknown>>;
|
|
54
|
+
readonly locale?: string;
|
|
55
|
+
readonly template?: string;
|
|
56
|
+
/** Raw email options when medium is email (sently-compatible). */
|
|
57
|
+
readonly mail?: MailOptions;
|
|
58
|
+
/** Web Push subscription endpoint + keys. */
|
|
59
|
+
readonly pushSubscription?: {
|
|
60
|
+
readonly endpoint: string;
|
|
61
|
+
readonly keys: { readonly p256dh: string; readonly auth: string };
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Delivery attempt record (fallback chains record every try). */
|
|
66
|
+
export interface ChannelAttempt {
|
|
67
|
+
readonly driverId: ChannelDriverId | string;
|
|
68
|
+
readonly ok: boolean;
|
|
69
|
+
readonly error?: string;
|
|
70
|
+
readonly at: number;
|
|
71
|
+
readonly messageId?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Result of a channel send including chain history. */
|
|
75
|
+
export interface ChannelSendResult {
|
|
76
|
+
readonly ok: boolean;
|
|
77
|
+
readonly messageId: string;
|
|
78
|
+
readonly driverId: string;
|
|
79
|
+
readonly attempts: readonly ChannelAttempt[];
|
|
80
|
+
/** Present when an email transport returned a sently {@link SendResult}. */
|
|
81
|
+
readonly mail?: SendResult;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Medium-agnostic transport (sms / whatsapp / push / console). */
|
|
85
|
+
export interface ChannelTransport {
|
|
86
|
+
readonly provider: string;
|
|
87
|
+
readonly mediums: readonly ChannelMediumId[];
|
|
88
|
+
send(message: ChannelMessage): Promise<ChannelSendResult>;
|
|
89
|
+
verify?(): Promise<VerifyResult>;
|
|
90
|
+
close?(): Promise<void>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Dual-shape driver: email drivers expose a sently {@link Transport};
|
|
95
|
+
* others expose a {@link ChannelTransport}.
|
|
96
|
+
*/
|
|
97
|
+
export interface ChannelDriver {
|
|
98
|
+
readonly id: ChannelDriverId;
|
|
99
|
+
/** Sently-compatible email transport (smtp / resend / console-email). */
|
|
100
|
+
readonly transport?: Transport;
|
|
101
|
+
/** Medium-agnostic transport. */
|
|
102
|
+
readonly channel?: ChannelTransport;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Open options shared by channel drivers. */
|
|
106
|
+
export interface ChannelOpenOptions {
|
|
107
|
+
readonly apiKey?: string;
|
|
108
|
+
readonly from?: string;
|
|
109
|
+
readonly host?: string;
|
|
110
|
+
readonly port?: number;
|
|
111
|
+
readonly user?: string;
|
|
112
|
+
readonly pass?: string;
|
|
113
|
+
readonly url?: string;
|
|
114
|
+
readonly token?: string;
|
|
115
|
+
/** VAPID keys for webpush. */
|
|
116
|
+
readonly vapidPublicKey?: string;
|
|
117
|
+
readonly vapidPrivateKey?: string;
|
|
118
|
+
readonly vapidSubject?: string;
|
|
119
|
+
/** Injected fetch for HTTP drivers. */
|
|
120
|
+
readonly fetch?: typeof globalThis.fetch;
|
|
121
|
+
/** Dev inbox sink for console driver. */
|
|
122
|
+
readonly inbox?: ChannelInbox;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Dev inbox entry. */
|
|
126
|
+
export interface ChannelInboxEntry {
|
|
127
|
+
readonly id: string;
|
|
128
|
+
readonly medium: ChannelMediumId;
|
|
129
|
+
readonly to: string;
|
|
130
|
+
readonly subject?: string;
|
|
131
|
+
readonly text?: string;
|
|
132
|
+
readonly html?: string;
|
|
133
|
+
readonly data?: Readonly<Record<string, unknown>>;
|
|
134
|
+
readonly template?: string;
|
|
135
|
+
readonly locale?: string;
|
|
136
|
+
readonly at: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Mutable dev inbox. */
|
|
140
|
+
export interface ChannelInbox {
|
|
141
|
+
readonly entries: ChannelInboxEntry[];
|
|
142
|
+
push(entry: ChannelInboxEntry): void;
|
|
143
|
+
clear(): void;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create an in-memory inbox for the console driver.
|
|
148
|
+
*/
|
|
149
|
+
export function createChannelInbox(): ChannelInbox {
|
|
150
|
+
const entries: ChannelInboxEntry[] = [];
|
|
151
|
+
return {
|
|
152
|
+
entries,
|
|
153
|
+
push(entry) {
|
|
154
|
+
entries.push(entry);
|
|
155
|
+
},
|
|
156
|
+
clear() {
|
|
157
|
+
entries.length = 0;
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `unifonic` channel driver — SMS via Unifonic REST API.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
ChannelDriver,
|
|
7
|
+
ChannelMessage,
|
|
8
|
+
ChannelOpenOptions,
|
|
9
|
+
ChannelSendResult,
|
|
10
|
+
ChannelTransport,
|
|
11
|
+
} from "./channel-types.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Open a Unifonic SMS driver.
|
|
15
|
+
*
|
|
16
|
+
* @param options - `apiKey` + optional `from` (sender id)
|
|
17
|
+
*/
|
|
18
|
+
export function openUnifonicChannel(
|
|
19
|
+
options: ChannelOpenOptions = {},
|
|
20
|
+
): ChannelDriver {
|
|
21
|
+
const apiKey = options.apiKey;
|
|
22
|
+
const from = options.from ?? "OKE";
|
|
23
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
24
|
+
const base = options.url ?? "https://el.cloud.unifonic.com";
|
|
25
|
+
|
|
26
|
+
const channel: ChannelTransport = {
|
|
27
|
+
provider: "unifonic",
|
|
28
|
+
mediums: ["sms"],
|
|
29
|
+
async send(message: ChannelMessage): Promise<ChannelSendResult> {
|
|
30
|
+
if (!apiKey) {
|
|
31
|
+
throw new Error("unifonic: apiKey is required");
|
|
32
|
+
}
|
|
33
|
+
const body = new URLSearchParams({
|
|
34
|
+
AppSid: apiKey,
|
|
35
|
+
Recipient: message.to,
|
|
36
|
+
Body: message.text ?? String(message.data?.code ?? ""),
|
|
37
|
+
SenderID: message.from ?? from,
|
|
38
|
+
});
|
|
39
|
+
const res = await fetchFn(`${base}/rest/SMS/messages`, {
|
|
40
|
+
method: "POST",
|
|
41
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
42
|
+
body,
|
|
43
|
+
});
|
|
44
|
+
const text = await res.text();
|
|
45
|
+
const id = crypto.randomUUID();
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
return {
|
|
48
|
+
ok: false,
|
|
49
|
+
messageId: id,
|
|
50
|
+
driverId: "unifonic",
|
|
51
|
+
attempts: [
|
|
52
|
+
{
|
|
53
|
+
driverId: "unifonic",
|
|
54
|
+
ok: false,
|
|
55
|
+
error: text || `HTTP ${res.status}`,
|
|
56
|
+
at: Date.now(),
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
ok: true,
|
|
63
|
+
messageId: id,
|
|
64
|
+
driverId: "unifonic",
|
|
65
|
+
attempts: [
|
|
66
|
+
{ driverId: "unifonic", ok: true, at: Date.now(), messageId: id },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
return { id: "unifonic", channel };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Unifonic driver factory. */
|
|
76
|
+
export const unifonicChannelDriver = {
|
|
77
|
+
id: "unifonic" as const,
|
|
78
|
+
open: openUnifonicChannel,
|
|
79
|
+
};
|