okengine 0.18.5 → 0.19.0
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 +18 -10
- package/README.md +2 -2
- package/package.json +51 -50
- package/site/content/docs/ai/llms-txt.mdx +1 -1
- package/site/content/docs/ai/meta.json +1 -1
- package/site/content/docs/ai/skills.mdx +4 -1
- package/site/content/docs/ai/try-it.mdx +58 -0
- package/site/content/docs/client/auth.mdx +208 -0
- package/site/content/docs/client/calling.mdx +451 -0
- package/site/content/docs/client/index.mdx +209 -0
- package/site/content/docs/client/live.mdx +234 -0
- package/site/content/docs/client/meta.json +5 -0
- package/site/content/docs/client/react.mdx +249 -0
- package/site/content/docs/elements/ai/agents.mdx +232 -0
- package/site/content/docs/elements/ai/index.mdx +341 -0
- package/site/content/docs/elements/ai/mcp.mdx +275 -0
- package/site/content/docs/elements/ai/meta.json +5 -0
- package/site/content/docs/elements/ai/models.mdx +283 -0
- package/site/content/docs/elements/ai/prompts.mdx +256 -0
- package/site/content/docs/elements/channel/email.mdx +266 -0
- package/site/content/docs/elements/channel/index.mdx +344 -0
- package/site/content/docs/elements/channel/meta.json +5 -0
- package/site/content/docs/elements/channel/push.mdx +218 -0
- package/site/content/docs/elements/channel/receipts.mdx +206 -0
- package/site/content/docs/elements/channel/sms.mdx +264 -0
- package/site/content/docs/elements/channel/whatsapp.mdx +220 -0
- package/site/content/docs/elements/clock/index.mdx +300 -0
- package/site/content/docs/elements/clock/meta.json +5 -0
- package/site/content/docs/elements/clock/schedules.mdx +508 -0
- package/site/content/docs/elements/clock/sleep.mdx +445 -0
- package/site/content/docs/elements/flow/consumers.mdx +707 -0
- package/site/content/docs/elements/flow/http.mdx +1080 -0
- package/site/content/docs/elements/flow/index.mdx +618 -0
- package/site/content/docs/elements/flow/meta.json +5 -0
- package/site/content/docs/elements/flow/routing.mdx +559 -0
- package/site/content/docs/elements/flow/workflows.mdx +640 -0
- package/site/content/docs/elements/gate/auth.mdx +371 -0
- package/site/content/docs/elements/gate/authorization.mdx +298 -0
- package/site/content/docs/elements/gate/index.mdx +418 -0
- package/site/content/docs/elements/gate/meta.json +5 -0
- package/site/content/docs/elements/gate/rate-limits.mdx +365 -0
- package/site/content/docs/elements/gate/rls.mdx +303 -0
- package/site/content/docs/elements/gate/tenancy.mdx +372 -0
- package/site/content/docs/elements/index.mdx +20 -10
- package/site/content/docs/elements/signal/broadcast.mdx +517 -0
- package/site/content/docs/elements/signal/index.mdx +352 -0
- package/site/content/docs/elements/signal/live.mdx +590 -0
- package/site/content/docs/elements/signal/meta.json +5 -0
- package/site/content/docs/elements/signal/once.mdx +596 -0
- package/site/content/docs/elements/store/files.mdx +659 -0
- package/site/content/docs/elements/store/index.mdx +310 -0
- package/site/content/docs/elements/store/kv.mdx +629 -0
- package/site/content/docs/elements/store/meta.json +5 -0
- package/site/content/docs/elements/store/search.mdx +946 -0
- package/site/content/docs/elements/store/sql.mdx +937 -0
- package/site/content/docs/elements/vault/config.mdx +256 -0
- package/site/content/docs/elements/vault/index.mdx +356 -0
- package/site/content/docs/elements/vault/meta.json +5 -0
- package/site/content/docs/elements/vault/rotation.mdx +273 -0
- package/site/content/docs/elements/vault/secrets.mdx +285 -0
- package/site/content/docs/index.mdx +63 -36
- package/site/content/docs/meta.json +8 -7
- package/site/content/docs/plugins/cors.mdx +2 -1
- package/site/content/docs/plugins/csrf.mdx +4 -1
- package/site/content/docs/plugins/headers.mdx +2 -1
- package/site/content/docs/plugins/ip-allowlist.mdx +2 -1
- package/site/content/docs/plugins/magic-link.mdx +6 -0
- package/site/content/docs/plugins/maintenance-mode.mdx +2 -1
- package/site/content/docs/plugins/oauth.mdx +1 -1
- package/site/content/docs/plugins/otp.mdx +12 -1
- package/site/content/docs/plugins/passkey.mdx +39 -15
- package/site/content/docs/plugins/two-factor.mdx +91 -34
- package/site/content/docs/plugins/username.mdx +1 -1
- package/site/content/docs/recipes/caddy.mdx +3 -3
- package/site/content/docs/recipes/index.mdx +18 -28
- package/site/content/docs/recipes/mailpit.mdx +1 -1
- package/site/content/docs/recipes/meilisearch.mdx +3 -3
- package/site/content/docs/recipes/meta.json +1 -4
- package/site/content/docs/recipes/nginx.mdx +2 -2
- package/site/content/docs/recipes/openrouter.mdx +283 -0
- package/site/content/docs/recipes/pgdog.mdx +3 -3
- package/site/content/docs/recipes/postgres.mdx +1 -2
- package/site/content/docs/recipes/rustfs.mdx +2 -2
- package/site/content/docs/recipes/traefik.mdx +3 -3
- package/site/content/docs/reference/cli.mdx +231 -0
- package/site/content/docs/reference/configuration.mdx +30 -10
- package/site/content/docs/reference/environment-variables.mdx +93 -20
- package/site/content/docs/reference/errors.mdx +132 -29
- package/site/content/docs/reference/fx.mdx +137 -73
- package/site/content/docs/reference/index.mdx +13 -21
- package/site/content/docs/reference/meta.json +4 -5
- package/site/content/docs/reference/okid.mdx +42 -17
- package/site/content/docs/reference/plugins.mdx +4 -3
- package/site/content/docs/reference/security.mdx +197 -0
- package/site/content/docs/understand/meta.json +5 -0
- package/site/content/docs/understand/the-anatomy.mdx +132 -0
- package/site/content/docs/understand/the-model.mdx +32 -0
- package/site/content/docs/understand/the-problem.mdx +74 -0
- package/site/content/docs/understand/the-vocabulary.mdx +26 -0
- package/src/auth/api-keys.ts +2 -1
- package/src/auth/bindings.ts +64 -16
- package/src/auth/gate-auth.test.ts +6 -1
- package/src/auth/identity.ts +152 -5
- package/src/auth/index.ts +29 -0
- package/src/auth/invites.ts +2 -1
- package/src/auth/method-context.ts +41 -0
- package/src/auth/oauth-as/crypto.ts +2 -1
- package/src/auth/oauth-as/stores.ts +2 -1
- package/src/auth/operator.ts +2 -1
- package/src/auth/sessions-jwt.test.ts +77 -0
- package/src/auth/sessions.ts +20 -4
- package/src/auth/tenants.ts +3 -2
- package/src/auth/two-factor-challenge.test.ts +61 -0
- package/src/auth/two-factor-challenge.ts +284 -0
- package/src/auth/verification.ts +5 -0
- package/src/bench/REPORT.md +49 -0
- package/src/bench/g03-signal-once.bench.ts +1 -1
- package/src/bench/g10-observability-contention.bench.ts +1 -1
- package/src/bench/g17-hybrid-search.bench.ts +572 -0
- package/src/bench/load-app.ts +2 -10
- package/src/cli/ai-setup/ai-setup.test.ts +331 -42
- package/src/cli/ai-setup/apply.ts +294 -52
- package/src/cli/ai-setup/catalog.ts +238 -1342
- package/src/cli/ai-setup/index.ts +14 -99
- package/src/cli/ai-setup/prompts.ts +60 -443
- package/src/cli/ask-seed.test.ts +96 -0
- package/src/cli/ask-seed.ts +82 -0
- package/src/cli/ask-vault-gaps.test.ts +84 -0
- package/src/cli/ask-vault-gaps.ts +146 -0
- package/src/cli/build.ts +2 -2
- package/src/cli/client-add.test.ts +26 -1
- package/src/cli/client-add.ts +106 -27
- package/src/cli/db-seed.ts +2 -0
- package/src/cli/db.ts +150 -11
- package/src/cli/dev.ts +119 -211
- package/src/cli/docker-clean.ts +2 -2
- package/src/cli/docker-cli.test.ts +1 -1
- package/src/cli/doctor-diff.ts +4 -2
- package/src/cli/doctor-pii.test.ts +1 -1
- package/src/cli/doctor.ts +14 -1
- package/src/cli/hero-meta.test.ts +4 -2
- package/src/cli/load-config.images.test.ts +8 -10
- package/src/cli/load-config.ts +1 -1
- package/src/cli/registry.ts +22 -10
- package/src/cli/replay.ts +3 -1
- package/src/cli/start.ts +1 -1
- package/src/cli/tui/keys.ts +2 -3
- package/src/client/auth/cookies.ts +74 -0
- package/src/client/auth/create-auth-client.ts +636 -0
- package/src/client/auth/denials.ts +99 -0
- package/src/client/auth/session.ts +283 -0
- package/src/client/auth.test.ts +251 -0
- package/src/client/auth.ts +39 -114
- package/src/client/create-with-session.ts +245 -0
- package/src/client/create.ts +51 -5
- package/src/client/index.ts +11 -1
- package/src/client/live.ts +11 -79
- package/src/client/notes-contract.test.ts +5 -10
- package/src/client/sse.ts +137 -0
- package/src/client/stream.ts +147 -0
- package/src/client/transport.test.ts +32 -0
- package/src/client/transport.ts +123 -26
- package/src/client/types.ts +118 -14
- package/src/client-react/index.ts +185 -24
- package/src/client-react/use-live-query.ts +13 -3
- package/src/compiler/aot.test.ts +7 -4
- package/src/compiler/effects-embed.test.ts +56 -0
- package/src/compiler/effects-fetch.test.ts +43 -0
- package/src/compiler/effects-infer.ts +58 -2
- package/src/compiler/extract.test.ts +257 -43
- package/src/compiler/extract.ts +566 -48
- package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -4
- package/src/compiler/fixtures/skyport/src/flows/bookings/signals.ts +2 -8
- package/src/compiler/fixtures/skyport.expected.json +4 -4
- package/src/compiler/fixtures/triggers/five-triggers.ts +14 -10
- package/src/compiler/response.ts +2 -2
- package/src/compiler/search-writer-isolation.test.ts +40 -0
- package/src/config/index.ts +11 -0
- package/src/console/server/app.ts +17 -23
- package/src/console/server/bind.ts +4 -0
- package/src/console/server/console.test.ts +2 -2
- package/src/console/server/flows-invoke.test.ts +50 -34
- package/src/console/server/flows.ts +436 -255
- package/src/console/server/runs-ingest.test.ts +6 -3
- package/src/console/server/serve.ts +1 -1
- package/src/console/server/signals.test.ts +1 -5
- package/src/console/server/signals.ts +8 -6
- package/src/console/server/state.ts +6 -1
- package/src/console/server/store.ts +1 -1
- package/src/console/ui-next/dist/assets/FileExportIcon-Ck-5od4R.js +1 -0
- package/src/console/ui-next/dist/assets/MoreHorizontalCircle01Icon-gMNGsE37.js +1 -0
- package/src/console/ui-next/dist/assets/PlusSignIcon-CwG3nxfu.js +1 -0
- package/src/console/ui-next/dist/assets/UnavailableIcon-D9cvHVPr.js +1 -0
- package/src/console/ui-next/dist/assets/UserIcon-DaE2PB5_.js +1 -0
- package/src/console/ui-next/dist/assets/access-page-DFeymU07.js +4 -0
- package/src/console/ui-next/dist/assets/agent-disclosure-U1rdfblp.js +1 -0
- package/src/console/ui-next/dist/assets/cache-glyph-BeFJeqBG.js +1 -0
- package/src/console/ui-next/dist/assets/call-pii-button-CVAONPii.js +1 -0
- package/src/console/ui-next/dist/assets/collapsible-D2A6NJ-3.js +1 -0
- package/src/console/ui-next/dist/assets/copy-inline-button-CAYD18cr.js +1 -0
- package/src/console/ui-next/dist/assets/dagre.esm-B1_XeuLP.js +1 -0
- package/src/console/ui-next/dist/assets/detail-header-DVWNjWjg.js +1 -0
- package/src/console/ui-next/dist/assets/dropdown-menu-4h2LOVXM.js +1 -0
- package/src/console/ui-next/dist/assets/duration-tone-Cgk_h5ja.js +9 -0
- package/src/console/ui-next/dist/assets/element-icons-BI8cJgdh.js +1 -0
- package/src/console/ui-next/dist/assets/explorer-empty-CJs5A-wm.js +1 -0
- package/src/console/ui-next/dist/assets/flows-page-Dss7941e.js +1 -0
- package/src/console/ui-next/dist/assets/highlighted-json-MYZQtRnw.js +154 -0
- package/src/console/ui-next/dist/assets/http-method-Jrh39p7A.js +1 -0
- package/src/console/ui-next/dist/assets/index-D0zS5rKO.css +2 -0
- package/src/console/ui-next/dist/assets/index-DXP2dBIF.js +63 -0
- package/src/console/ui-next/dist/assets/observability-page-HvolXxTI.js +4 -0
- package/src/console/ui-next/dist/assets/react-dom-Ddte4I-Q.js +9 -0
- package/src/console/ui-next/dist/assets/replica-lag-CSh2dzrb.js +18 -0
- package/src/console/ui-next/dist/assets/request-meta-BatF8KrK.js +1 -0
- package/src/console/ui-next/dist/assets/shortcut-keys-3ILd8oGn.js +1 -0
- package/src/console/ui-next/dist/assets/{sql-BskegiFM.js → sql-BsFa4tDR.js} +1 -1
- package/src/console/ui-next/dist/assets/store-page-eiKiHnNe.js +41 -0
- package/src/console/ui-next/dist/assets/trace-detail-sheet-CZkMeKS-.js +2 -0
- package/src/console/ui-next/dist/assets/tree-expand-toggle-CW8y5A2h.js +55 -0
- package/src/console/ui-next/dist/assets/units-page-B_RWJrEO.js +1 -0
- package/src/console/ui-next/dist/assets/{use-vault-list-uk4WVboC.js → use-vault-list-CT4-gajj.js} +1 -1
- package/src/console/ui-next/dist/assets/vault-page-CWrg-A68.js +2 -0
- package/src/console/ui-next/dist/assets/xyflow-CSyC6ryz.css +1 -0
- package/src/console/ui-next/dist/assets/xyflow-yApv7D4e.js +7 -0
- package/src/console/ui-next/dist/index.html +6 -13
- package/src/console/ui-next/seed-invoke-host.ts +21 -18
- package/src/console/ui-next/src/client.ts +7 -2
- package/src/console/ui-next/src/features/flows/graph/element-map.ts +2 -0
- package/src/console/ui-next/src/features/flows/traces/effect-kind.ts +12 -2
- package/src/console/ui-next/src/features/flows/traces/effect-summary.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/trace-detail-sheet.tsx +8 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-bars.ts +4 -0
- package/src/console/ui-next/src/features/flows/traces/waterfall-tooltip.ts +9 -3
- package/src/console/ui-next/src/features/store/detail/reveal-cell.tsx +7 -11
- package/src/console/ui-next/src/features/store/detail/store-row-detail-sheet.tsx +2 -2
- package/src/console/ui-next/src/features/store/lib/fields-from-table.ts +2 -0
- package/src/console/ui-next/src/features/store/lib/grid-model.test.ts +25 -1
- package/src/console/ui-next/src/features/store/lib/grid-model.ts +36 -1
- package/src/console/ui-next/src/features/store/query/query-results.tsx +3 -3
- package/src/console/ui-next/src/features/units/detail/effects-summary.tsx +2 -0
- package/src/console/ui-next/src/features/units/lib/call-read-safe.ts +3 -1
- package/src/console/ui-next/src/features/units/lib/fields-from-schema.ts +6 -0
- package/src/docker/ai-model-status.test.ts +1 -12
- package/src/docker/ai-model-status.ts +10 -38
- package/src/docker/compose-up.test.ts +100 -0
- package/src/docker/compose-up.ts +292 -0
- package/src/docker/compose.ts +4 -14
- package/src/docker/derive.ts +9 -34
- package/src/docker/docker.test.ts +16 -261
- package/src/docker/images-config.test.ts +13 -25
- package/src/docker/index.ts +1 -24
- package/src/docker/recipes/index.ts +0 -23
- package/src/docker/recipes/pgdog.ts +6 -4
- package/src/docker/stack-id.test.ts +2 -2
- package/src/docker/stack-id.ts +0 -1
- package/src/docker/types.ts +2 -2
- package/src/drivers/ai-anthropic.ts +10 -0
- package/src/drivers/ai-openai-compatible.ts +34 -7
- package/src/drivers/ai-providers.test.ts +0 -107
- package/src/drivers/ai-stream.test.ts +0 -34
- package/src/drivers/ai-types.ts +17 -8
- package/src/drivers/channel-fcm.ts +6 -1
- package/src/drivers/channel-msegat.ts +6 -1
- package/src/drivers/channel-resend.ts +5 -1
- package/src/drivers/channel-smtp.ts +5 -1
- package/src/drivers/channel-sndr.ts +10 -1
- package/src/drivers/channel-taqnyat-mail.ts +5 -1
- package/src/drivers/channel-taqnyat-whatsapp.ts +6 -1
- package/src/drivers/channel-taqnyat.ts +6 -1
- package/src/drivers/channel-types.ts +10 -0
- package/src/drivers/channel-unifonic.ts +6 -1
- package/src/drivers/channel-wa-cloud.ts +6 -1
- package/src/drivers/channel-webpush.ts +6 -1
- package/src/drivers/external.ts +33 -0
- package/src/drivers/index.ts +0 -10
- package/src/drivers/meilisearch.ts +6 -0
- package/src/drivers/oauth-types.ts +4 -0
- package/src/drivers/postgres.test.ts +74 -3
- package/src/drivers/postgres.ts +175 -6
- package/src/drivers/signal-types.ts +5 -5
- package/src/drivers/types.ts +7 -0
- package/src/drivers/vault-types.ts +5 -0
- package/src/elements/ai/declare.ts +17 -4
- package/src/elements/ai/eval.ts +1 -1
- package/src/elements/ai/mcp-http.ts +1 -1
- package/src/elements/ai/pii.ts +1 -1
- package/src/elements/ai/providers.test.ts +289 -0
- package/src/elements/ai/providers.ts +169 -0
- package/src/elements/ai/runtime.ts +68 -5
- package/src/elements/ai/schema.ts +2 -2
- package/src/elements/ai.test.ts +7 -7
- package/src/elements/ai.ts +17 -1
- package/src/elements/channel/runtime.ts +105 -12
- package/src/elements/clock/cron-fields.test.ts +144 -0
- package/src/elements/clock/cron-fields.ts +185 -0
- package/src/elements/clock/declare.ts +247 -3
- package/src/elements/clock.ts +21 -1
- package/src/elements/index.ts +15 -0
- package/src/elements/signal/chaos-child.ts +1 -2
- package/src/elements/signal/declare.ts +65 -37
- package/src/elements/signal/delivery-modes.test.ts +11 -31
- package/src/elements/signal/dry-run-replay.test.ts +1 -7
- package/src/elements/signal/dry-run-write-isolation.test.ts +1 -7
- package/src/elements/signal/key-ordering.test.ts +6 -26
- package/src/elements/signal/lease-reclaim.test.ts +2 -6
- package/src/elements/signal/optional-emit.test.ts +6 -9
- package/src/elements/signal/order-lifecycle.test.ts +4 -17
- package/src/elements/signal/orphan-messages.test.ts +4 -15
- package/src/elements/signal/reconcile.test.ts +2 -2
- package/src/elements/signal/runtime.ts +1 -1
- package/src/elements/signal/schema-emit.test.ts +4 -8
- package/src/elements/signal.test.ts +24 -49
- package/src/elements/signal.ts +9 -2
- package/src/elements/store/domain-ddl.test.ts +1 -1
- package/src/elements/store/live-http.test.ts +9 -4
- package/src/elements/store/prepare-row.test.ts +123 -0
- package/src/elements/store/resource.ts +43 -12
- package/src/elements/store/schema-decl.ts +117 -0
- package/src/elements/store/search-backfill.ts +205 -0
- package/src/elements/store/search-bind.ts +66 -0
- package/src/elements/store/search-bm25.ts +78 -0
- package/src/elements/store/search-ddl.ts +156 -0
- package/src/elements/store/search-embed-flow.ts +141 -0
- package/src/elements/store/search-errors.ts +34 -0
- package/src/elements/store/search-fusion.ts +112 -0
- package/src/elements/store/search-lsh.ts +179 -0
- package/src/elements/store/search-runtime.ts +300 -0
- package/src/elements/store/search.test.ts +144 -0
- package/src/elements/store/sql-session.test.ts +1 -0
- package/src/elements/store/sql-session.ts +83 -3
- package/src/elements/store/table.ts +23 -2
- package/src/elements/store/upsert-app.test.ts +1 -3
- package/src/elements/store.ts +50 -0
- package/src/full.ts +4 -2
- package/src/http.ts +4 -1
- package/src/i18n/catalogs/ar.ts +14 -6
- package/src/i18n/catalogs/en.ts +14 -6
- package/src/index.ts +6 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +7 -7
- package/src/kernel/adopt-routes.ts +9 -1
- package/src/kernel/app-auth.ts +5 -0
- package/src/kernel/app.ts +102 -9
- package/src/kernel/auto-cache.test.ts +6 -12
- package/src/kernel/auto-registry.test.ts +3 -3
- package/src/kernel/boot-bind/ai.test.ts +22 -19
- package/src/kernel/boot-bind/ai.ts +5 -43
- package/src/kernel/boot-bind/clock.ts +23 -5
- package/src/kernel/boot-bind/honor-config.test.ts +4 -4
- package/src/kernel/boot.test.ts +11 -6
- package/src/kernel/boot.ts +66 -16
- package/src/kernel/boundary-contract.ts +93 -0
- package/src/kernel/budget.test.ts +1 -1
- package/src/kernel/call.ts +89 -0
- package/src/kernel/capability.ts +6 -0
- package/src/kernel/client-descriptor.ts +123 -0
- package/src/kernel/clock-timezone.test.ts +80 -0
- package/src/kernel/correlation.test.ts +1 -1
- package/src/kernel/dry-run.ts +11 -8
- package/src/kernel/effects-stamping.test.ts +42 -9
- package/src/kernel/effects.test.ts +4 -2
- package/src/kernel/effects.ts +51 -9
- package/src/kernel/errors-channel.ts +17 -0
- package/src/kernel/errors-live-resume.ts +3 -2
- package/src/kernel/errors-tenant.ts +7 -4
- package/src/kernel/errors.registry-helpers.ts +96 -0
- package/src/kernel/errors.registry.test.ts +139 -25
- package/src/kernel/errors.ts +102 -23
- package/src/kernel/external-effects.test.ts +196 -0
- package/src/kernel/flow.test.ts +13 -4
- package/src/kernel/flow.ts +69 -71
- package/src/kernel/fx-ask-telemetry.test.ts +2 -2
- package/src/kernel/fx-dead-letters.test.ts +3 -3
- package/src/kernel/fx-fetch.ts +55 -0
- package/src/kernel/fx-live-stream.ts +2 -2
- package/src/kernel/fx-live.test.ts +8 -8
- package/src/kernel/fx.test.ts +17 -11
- package/src/kernel/fx.ts +180 -57
- package/src/kernel/horizontal-child.ts +1 -1
- package/src/kernel/http-query.test.ts +3 -6
- package/src/kernel/index.ts +13 -3
- package/src/kernel/instance-id.ts +1 -1
- package/src/kernel/instances.test.ts +40 -0
- package/src/kernel/instances.ts +47 -9
- package/src/kernel/live-http.test.ts +6 -7
- package/src/kernel/live-http.ts +6 -2
- package/src/kernel/live-resume.test.ts +1 -1
- package/src/kernel/mcp-tool.test.ts +3 -3
- package/src/kernel/on.ts +98 -4
- package/src/kernel/pipeline.test.ts +12 -15
- package/src/kernel/plugin-elements.test.ts +1 -1
- package/src/kernel/stamp-http.test.ts +3 -3
- package/src/kernel/triggers.ts +210 -95
- package/src/kernel-entry.ts +0 -1
- package/src/manifest/diff.ts +11 -1
- package/src/manifest/fixtures/skyport.excerpt.json +1 -1
- package/src/manifest/types.ts +46 -2
- package/src/mcp/docs-index.ts +3 -3
- package/src/mcp/docs-mcp.test.ts +2 -2
- package/src/mcp/docs-tools.ts +1 -1
- package/src/okid.test.ts +56 -0
- package/src/okid.ts +55 -11
- package/src/plugins/anonymous.ts +8 -4
- package/src/plugins/auth/shared.ts +27 -3
- package/src/plugins/auth-delivery.mailpit.integration.test.ts +1 -1
- package/src/plugins/auth-methods.security.test.ts +561 -23
- package/src/plugins/config-source.ts +1 -1
- package/src/plugins/csrf.test.ts +65 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/magic-link.ts +36 -16
- package/src/plugins/oauth/shared.ts +3 -1
- package/src/plugins/oauth.ts +22 -14
- package/src/plugins/otp.ts +37 -21
- package/src/plugins/passkey-webauthn.ts +9 -6
- package/src/plugins/passkey.ts +98 -26
- package/src/plugins/pre-account-hijack.test.ts +223 -0
- package/src/plugins/two-factor.ts +466 -37
- package/src/plugins/username.ts +19 -7
- package/src/release/build-lib.ts +1 -0
- package/src/release/limits.ts +2 -2
- package/src/release/measure.ts +1 -1
- package/src/runs/collect.test.ts +0 -2
- package/src/runtime/json-code-block.test.ts +250 -20
- package/src/runtime/json-code-block.ts +1261 -41
- package/src/term.test.ts +1 -1
- package/src/test/create-test-app.test.ts +12 -12
- package/src/test/live-signals.test.ts +6 -6
- package/src/test/provisions.integration.test.ts +10 -14
- package/src/test/reset-element-registries.ts +1 -1
- package/src/test/tenant-isolation.test.ts +12 -6
- package/site/content/docs/deployment/docker-swarm.mdx +0 -164
- package/site/content/docs/deployment/docker.mdx +0 -227
- package/site/content/docs/deployment/index.mdx +0 -83
- package/site/content/docs/deployment/kubernetes.mdx +0 -176
- package/site/content/docs/deployment/meta.json +0 -5
- package/site/content/docs/deployment/reverse-proxy.mdx +0 -234
- package/site/content/docs/elements/ai.mdx +0 -385
- package/site/content/docs/elements/channel.mdx +0 -346
- package/site/content/docs/elements/clock.mdx +0 -244
- package/site/content/docs/elements/flow.mdx +0 -420
- package/site/content/docs/elements/gate.mdx +0 -436
- package/site/content/docs/elements/signal.mdx +0 -380
- package/site/content/docs/elements/store.mdx +0 -1099
- package/site/content/docs/elements/vault.mdx +0 -405
- package/site/content/docs/get-started/basic-usage.mdx +0 -173
- package/site/content/docs/get-started/index.mdx +0 -43
- package/site/content/docs/get-started/installation.mdx +0 -220
- package/site/content/docs/get-started/introduction.mdx +0 -144
- package/site/content/docs/get-started/meta.json +0 -13
- package/site/content/docs/get-started/project-structure.mdx +0 -925
- package/site/content/docs/get-started/testing.mdx +0 -328
- package/site/content/docs/get-started/why.mdx +0 -114
- package/site/content/docs/recipes/llama-cpp.mdx +0 -151
- package/site/content/docs/recipes/ollama.mdx +0 -142
- package/site/content/docs/recipes/sglang.mdx +0 -105
- package/site/content/docs/recipes/vllm.mdx +0 -106
- package/site/content/docs/reference/cli.md +0 -232
- package/site/content/docs/reference/client.mdx +0 -469
- package/site/content/docs/reference/security.md +0 -74
- package/src/cli/ai-setup/detect-ollama.ts +0 -213
- package/src/cli/ai-setup/recommend.test.ts +0 -225
- package/src/cli/ai-setup/recommend.ts +0 -225
- package/src/cli/dev-controls.test.ts +0 -122
- package/src/cli/dev-controls.ts +0 -164
- package/src/cli/tui/DevLive.tsx +0 -126
- package/src/console/ui-next/dist/assets/access-page-3-EFj-2G.js +0 -4
- package/src/console/ui-next/dist/assets/agent-disclosure-BP0Y0Sux.js +0 -1
- package/src/console/ui-next/dist/assets/cache-glyph-B5X-NM0-.js +0 -1
- package/src/console/ui-next/dist/assets/call-pii-button-ChAUiLo9.js +0 -1
- package/src/console/ui-next/dist/assets/collapsible-DGnOM2ph.js +0 -1
- package/src/console/ui-next/dist/assets/copy-inline-button-DBHhgHKP.js +0 -1
- package/src/console/ui-next/dist/assets/dagre.esm-ZwcdTuZZ.js +0 -1
- package/src/console/ui-next/dist/assets/detail-header-DhHM1iaZ.js +0 -1
- package/src/console/ui-next/dist/assets/dropdown-menu-_NjTEo5_.js +0 -1
- package/src/console/ui-next/dist/assets/duration-tone-sC3lGABz.js +0 -9
- package/src/console/ui-next/dist/assets/element-icons-BVXtRyd3.js +0 -1
- package/src/console/ui-next/dist/assets/explorer-empty-2uIhBu0_.js +0 -1
- package/src/console/ui-next/dist/assets/flows-page-cVFnA4HH.js +0 -1
- package/src/console/ui-next/dist/assets/highlighted-json-Awq7gYdu.js +0 -154
- package/src/console/ui-next/dist/assets/http-method-_UHM2ODJ.js +0 -1
- package/src/console/ui-next/dist/assets/index-CMIgUbD0.js +0 -66
- package/src/console/ui-next/dist/assets/index-Ck88Jmv8.css +0 -2
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-CQ3p34ip.js +0 -4
- package/src/console/ui-next/dist/assets/preload-helper-oH4irX4C.js +0 -1
- package/src/console/ui-next/dist/assets/react-D8E3mtu1.js +0 -1
- package/src/console/ui-next/dist/assets/react-dom-Bph1y7z7.js +0 -9
- package/src/console/ui-next/dist/assets/replica-lag-DKRrbvdo.js +0 -18
- package/src/console/ui-next/dist/assets/request-meta-DV0ywz7t.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-JQIZlWfm.js +0 -1
- package/src/console/ui-next/dist/assets/shortcut-keys-DKxNTe_m.js +0 -1
- package/src/console/ui-next/dist/assets/skeleton-D-czQJT6.js +0 -1
- package/src/console/ui-next/dist/assets/store-page-02xOiqIK.js +0 -41
- package/src/console/ui-next/dist/assets/trace-detail-sheet-B09O8rA6.js +0 -2
- package/src/console/ui-next/dist/assets/tree-expand-toggle-BtyhmWb4.js +0 -55
- package/src/console/ui-next/dist/assets/units-page-l8FeKfnP.js +0 -1
- package/src/console/ui-next/dist/assets/useMutation-B8EO02Ej.js +0 -1
- package/src/console/ui-next/dist/assets/useRender-BE2A9BWC.js +0 -1
- package/src/console/ui-next/dist/assets/vault-page-CL-d_mLE.js +0 -2
- package/src/console/ui-next/dist/assets/xyflow-D7n4g6go.js +0 -7
- package/src/console/ui-next/dist/assets/xyflow-DZ0Ws1xk.css +0 -1
- package/src/docker/ollama-pull.ts +0 -232
- package/src/docker/recipes/llama-cpp.ts +0 -298
- package/src/docker/recipes/ollama.ts +0 -44
- package/src/docker/recipes/sglang.ts +0 -55
- package/src/docker/recipes/vllm.ts +0 -44
- package/src/drivers/ai-ollama-tools.integration.test.ts +0 -109
- package/src/drivers/ai-ollama.integration.test.ts +0 -184
- package/src/drivers/ai-ollama.ts +0 -389
- package/src/drivers/ollama.ts +0 -14
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-time interactive prompt: run `oke db seed` after first successful push.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { confirm, isCancel } from "@clack/prompts";
|
|
6
|
+
import type { ConfigEnv } from "../config/index.ts";
|
|
7
|
+
import { resolveSeedIdentity, seedPromptMessage } from "../elements/store/seed.ts";
|
|
8
|
+
import { formatCliChrome } from "../term.ts";
|
|
9
|
+
import { loadSeedDef, resolveSeedModulePath, runSeed } from "./db-seed.ts";
|
|
10
|
+
import { isProjectSeeded, markProjectSeeded } from "./project-state.ts";
|
|
11
|
+
|
|
12
|
+
/** @deprecated Use `.oke/state.json` `seededAt` via {@link isProjectSeeded}. */
|
|
13
|
+
export { LEGACY_SEEDED_MARKER as SEEDED_MARKER } from "./project-state.ts";
|
|
14
|
+
|
|
15
|
+
/** Options for {@link maybeAskSeed}. */
|
|
16
|
+
export interface AskSeedOptions {
|
|
17
|
+
readonly cwd: string;
|
|
18
|
+
readonly env: ConfigEnv;
|
|
19
|
+
readonly write?: (text: string) => void;
|
|
20
|
+
readonly stdinIsTTY?: boolean;
|
|
21
|
+
/** Skip prompt (tests / `--yes` / non-interactive). */
|
|
22
|
+
readonly skip?: boolean;
|
|
23
|
+
/** Injectable confirm (tests). */
|
|
24
|
+
readonly confirmFn?: () => Promise<boolean>;
|
|
25
|
+
/** Injectable seed runner (tests). */
|
|
26
|
+
readonly seedFn?: (cwd: string, env: ConfigEnv) => Promise<number>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* After a successful `oke db push`, ask once whether to seed this app
|
|
31
|
+
* (`defineSeed({ name })` or the project folder). Skips when non-TTY,
|
|
32
|
+
* already seeded for that identity, or no seed module.
|
|
33
|
+
*
|
|
34
|
+
* @param options - Project / env / injectables
|
|
35
|
+
*/
|
|
36
|
+
export async function maybeAskSeed(options: AskSeedOptions): Promise<void> {
|
|
37
|
+
if (options.skip) return;
|
|
38
|
+
const tty = options.stdinIsTTY ?? Boolean(process.stdin.isTTY);
|
|
39
|
+
if (!tty) return;
|
|
40
|
+
|
|
41
|
+
const cwd = options.cwd;
|
|
42
|
+
const seedPath = await resolveSeedModulePath(cwd);
|
|
43
|
+
if (!(await Bun.file(seedPath).exists())) return;
|
|
44
|
+
|
|
45
|
+
const def = await loadSeedDef(cwd).catch(() => undefined);
|
|
46
|
+
const identity = resolveSeedIdentity(def, cwd);
|
|
47
|
+
if (await isProjectSeeded(cwd, identity.name)) return;
|
|
48
|
+
|
|
49
|
+
const write = options.write ?? ((t) => process.stdout.write(t));
|
|
50
|
+
const chromeWrite = (t: string) => write(formatCliChrome(t));
|
|
51
|
+
const ok =
|
|
52
|
+
options.confirmFn !== undefined
|
|
53
|
+
? await options.confirmFn()
|
|
54
|
+
: await (async () => {
|
|
55
|
+
const value = await confirm({
|
|
56
|
+
message: seedPromptMessage(identity),
|
|
57
|
+
initialValue: true,
|
|
58
|
+
});
|
|
59
|
+
if (isCancel(value)) return false;
|
|
60
|
+
return Boolean(value);
|
|
61
|
+
})();
|
|
62
|
+
|
|
63
|
+
if (!ok) {
|
|
64
|
+
chromeWrite("oke db seed: skipped (run `oke db seed` later)\n");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const seed =
|
|
69
|
+
options.seedFn ??
|
|
70
|
+
((projectCwd, env) =>
|
|
71
|
+
runSeed({
|
|
72
|
+
cwd: projectCwd,
|
|
73
|
+
env,
|
|
74
|
+
write: chromeWrite,
|
|
75
|
+
force: true,
|
|
76
|
+
stdinIsTTY: false,
|
|
77
|
+
}));
|
|
78
|
+
const code = await seed(cwd, options.env);
|
|
79
|
+
if (code === 0) {
|
|
80
|
+
await markProjectSeeded(cwd, { seed: identity.name });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for interactive Vault gap fill during `oke dev`.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from "bun:test";
|
|
6
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { maybeAskVaultGaps } from "./ask-vault-gaps.ts";
|
|
10
|
+
|
|
11
|
+
describe("maybeAskVaultGaps", () => {
|
|
12
|
+
test("skips when non-TTY", async () => {
|
|
13
|
+
const dir = mkdtempSync(join(tmpdir(), "ask-vault-"));
|
|
14
|
+
try {
|
|
15
|
+
let reads = 0;
|
|
16
|
+
const code = await maybeAskVaultGaps({
|
|
17
|
+
cwd: dir,
|
|
18
|
+
stdinIsTTY: false,
|
|
19
|
+
gapsFn: async () => [{ name: "OPENROUTER_API_KEY", description: "OpenRouter API key" }],
|
|
20
|
+
readSecret: async () => {
|
|
21
|
+
reads += 1;
|
|
22
|
+
return "sk-test";
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
expect(code).toBe(0);
|
|
26
|
+
expect(reads).toBe(0);
|
|
27
|
+
} finally {
|
|
28
|
+
rmSync(dir, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("writes each gap into .env.local and hydrates process.env", async () => {
|
|
33
|
+
const dir = mkdtempSync(join(tmpdir(), "ask-vault-"));
|
|
34
|
+
const prev = process.env.OPENROUTER_API_KEY;
|
|
35
|
+
try {
|
|
36
|
+
delete process.env.OPENROUTER_API_KEY;
|
|
37
|
+
const prompts: string[] = [];
|
|
38
|
+
const code = await maybeAskVaultGaps({
|
|
39
|
+
cwd: dir,
|
|
40
|
+
stdinIsTTY: true,
|
|
41
|
+
gapsFn: async () => [
|
|
42
|
+
{ name: "OPENROUTER_API_KEY", description: "OpenRouter API key" },
|
|
43
|
+
{ name: "OTHER_SECRET" },
|
|
44
|
+
],
|
|
45
|
+
readSecret: async (prompt) => {
|
|
46
|
+
prompts.push(prompt);
|
|
47
|
+
return prompt.includes("OPENROUTER") ? "sk-or-v1-test" : "other-value";
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
expect(code).toBe(0);
|
|
51
|
+
expect(prompts).toHaveLength(2);
|
|
52
|
+
// `delete process.env.OPENROUTER_API_KEY` narrows that property to
|
|
53
|
+
// `undefined` for the rest of the block — widen before asserting.
|
|
54
|
+
expect(process.env.OPENROUTER_API_KEY as string | undefined).toBe("sk-or-v1-test");
|
|
55
|
+
expect(process.env.OTHER_SECRET as string | undefined).toBe("other-value");
|
|
56
|
+
const env = readFileSync(join(dir, ".env.local"), "utf8");
|
|
57
|
+
expect(env).toContain("OPENROUTER_API_KEY=sk-or-v1-test");
|
|
58
|
+
expect(env).toContain("OTHER_SECRET=other-value");
|
|
59
|
+
} finally {
|
|
60
|
+
if (prev === undefined) delete process.env.OPENROUTER_API_KEY;
|
|
61
|
+
else process.env.OPENROUTER_API_KEY = prev;
|
|
62
|
+
delete process.env.OTHER_SECRET;
|
|
63
|
+
rmSync(dir, { recursive: true, force: true });
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("empty value leaves a gap and returns 1", async () => {
|
|
68
|
+
const dir = mkdtempSync(join(tmpdir(), "ask-vault-"));
|
|
69
|
+
try {
|
|
70
|
+
const logs: string[] = [];
|
|
71
|
+
const code = await maybeAskVaultGaps({
|
|
72
|
+
cwd: dir,
|
|
73
|
+
stdinIsTTY: true,
|
|
74
|
+
write: (t) => logs.push(t),
|
|
75
|
+
gapsFn: async () => [{ name: "OPENROUTER_API_KEY" }],
|
|
76
|
+
readSecret: async () => "",
|
|
77
|
+
});
|
|
78
|
+
expect(code).toBe(1);
|
|
79
|
+
expect(logs.some((l) => l.includes("missing secret"))).toBe(true);
|
|
80
|
+
} finally {
|
|
81
|
+
rmSync(dir, { recursive: true, force: true });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive fill for Vault boot gaps during `oke dev`.
|
|
3
|
+
*
|
|
4
|
+
* Probes the same gap set app boot would throw (`allowDevFallbacks` on for
|
|
5
|
+
* `dev`), then prompts one-by-one and persists into `.env.local`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { resolve } from "node:path";
|
|
9
|
+
import { resolveDriverId } from "../config/index.ts";
|
|
10
|
+
import { VAULT_DEFAULTS } from "../config/driver-defaults.ts";
|
|
11
|
+
import { resolveAppEntryForPluginTables } from "../elements/store/load-plugin-tables.ts";
|
|
12
|
+
import { buildVaultBootChain, normalizeVaultDriverId } from "../elements/vault/boot-chain.ts";
|
|
13
|
+
import { createVaultRuntime, VaultBootError, type VaultGap } from "../elements/vault/runtime.ts";
|
|
14
|
+
import { requiredEnvRegistry, secretRegistry } from "../kernel/element-registries.ts";
|
|
15
|
+
import { formatCliChrome } from "../term.ts";
|
|
16
|
+
import { loadOkeConfig } from "./load-config.ts";
|
|
17
|
+
import { openEnvStore } from "./vault-cmd.ts";
|
|
18
|
+
import { promptHidden } from "./vault-secure-input.ts";
|
|
19
|
+
|
|
20
|
+
/** Options for {@link maybeAskVaultGaps}. */
|
|
21
|
+
export interface AskVaultGapsOptions {
|
|
22
|
+
readonly cwd: string;
|
|
23
|
+
/** App entry override (relative or absolute). */
|
|
24
|
+
readonly entry?: string;
|
|
25
|
+
readonly write?: (text: string) => void;
|
|
26
|
+
readonly stdinIsTTY?: boolean;
|
|
27
|
+
/** Skip prompt (tests / non-interactive). */
|
|
28
|
+
readonly skip?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Injectable gap probe (tests). Default: import entry + vault boot.
|
|
31
|
+
*/
|
|
32
|
+
readonly gapsFn?: () => Promise<readonly VaultGap[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Injectable secret reader (tests). Default: {@link promptHidden}.
|
|
35
|
+
*/
|
|
36
|
+
readonly readSecret?: (prompt: string) => Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Env file relative to cwd (default `.env.local`).
|
|
39
|
+
*/
|
|
40
|
+
readonly envFile?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Probe Vault contracts declared by the app entry and return boot gaps.
|
|
45
|
+
*
|
|
46
|
+
* @param cwd - Project root
|
|
47
|
+
* @param entry - Optional entry override
|
|
48
|
+
*/
|
|
49
|
+
export async function probeVaultGaps(cwd: string, entry?: string): Promise<readonly VaultGap[]> {
|
|
50
|
+
const prevSecrets = secretRegistry.slice();
|
|
51
|
+
const prevRequired = requiredEnvRegistry.slice();
|
|
52
|
+
secretRegistry.length = 0;
|
|
53
|
+
requiredEnvRegistry.length = 0;
|
|
54
|
+
try {
|
|
55
|
+
const entryAbs = await resolveAppEntryForPluginTables(cwd, entry);
|
|
56
|
+
if (!entryAbs) return [];
|
|
57
|
+
await import(entryAbs);
|
|
58
|
+
const secrets = secretRegistry.slice();
|
|
59
|
+
const requiredEnv = requiredEnvRegistry.slice();
|
|
60
|
+
if (secrets.length === 0 && requiredEnv.length === 0) return [];
|
|
61
|
+
|
|
62
|
+
const loaded = await loadOkeConfig(cwd).catch(() => null);
|
|
63
|
+
const configEnv = "dev" as const;
|
|
64
|
+
const driverId = normalizeVaultDriverId(
|
|
65
|
+
resolveDriverId(loaded?.config?.drivers?.vault, configEnv, VAULT_DEFAULTS) ?? "env",
|
|
66
|
+
);
|
|
67
|
+
const chain = buildVaultBootChain({
|
|
68
|
+
driverId,
|
|
69
|
+
env: configEnv,
|
|
70
|
+
cwd,
|
|
71
|
+
seed: {},
|
|
72
|
+
});
|
|
73
|
+
const vault = createVaultRuntime({
|
|
74
|
+
secrets,
|
|
75
|
+
requiredEnv,
|
|
76
|
+
chain,
|
|
77
|
+
allowDevFallbacks: true,
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
await vault.boot();
|
|
81
|
+
return [];
|
|
82
|
+
} catch (err) {
|
|
83
|
+
if (err instanceof VaultBootError) return err.gaps;
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
} finally {
|
|
87
|
+
secretRegistry.length = 0;
|
|
88
|
+
secretRegistry.push(...prevSecrets);
|
|
89
|
+
requiredEnvRegistry.length = 0;
|
|
90
|
+
requiredEnvRegistry.push(...prevRequired);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* After compose hydrate (and usually schema push), fill Vault boot gaps
|
|
96
|
+
* one-by-one into `.env.local`. Skips when non-TTY or no gaps.
|
|
97
|
+
*
|
|
98
|
+
* @param options - Project / injectables
|
|
99
|
+
* @returns `0` when ready to continue, `1` when aborted (still missing)
|
|
100
|
+
*/
|
|
101
|
+
export async function maybeAskVaultGaps(options: AskVaultGapsOptions): Promise<number> {
|
|
102
|
+
if (options.skip) return 0;
|
|
103
|
+
const tty = options.stdinIsTTY ?? Boolean(process.stdin.isTTY);
|
|
104
|
+
if (!tty) return 0;
|
|
105
|
+
|
|
106
|
+
const cwd = options.cwd;
|
|
107
|
+
const write = options.write ?? ((t) => process.stdout.write(t));
|
|
108
|
+
const chromeWrite = (t: string) => write(formatCliChrome(t));
|
|
109
|
+
|
|
110
|
+
const gaps = options.gapsFn ? await options.gapsFn() : await probeVaultGaps(cwd, options.entry);
|
|
111
|
+
if (gaps.length === 0) return 0;
|
|
112
|
+
|
|
113
|
+
chromeWrite(
|
|
114
|
+
gaps.length === 1
|
|
115
|
+
? "oke vault: 1 missing secret — enter a value (stored in .env.local)\n"
|
|
116
|
+
: `oke vault: ${gaps.length} missing secrets — enter each value (stored in .env.local)\n`,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const envPath = resolve(cwd, options.envFile ?? ".env.local");
|
|
120
|
+
const store = await openEnvStore(envPath);
|
|
121
|
+
const read =
|
|
122
|
+
options.readSecret ?? ((prompt: string) => promptHidden(prompt, { write: chromeWrite }));
|
|
123
|
+
|
|
124
|
+
const remaining: VaultGap[] = [];
|
|
125
|
+
for (const gap of gaps) {
|
|
126
|
+
const label = gap.description ? `${gap.name} (${gap.description})` : gap.name;
|
|
127
|
+
const value = (await read(`Enter value for ${label}: `)).trim();
|
|
128
|
+
if (value.length === 0) {
|
|
129
|
+
remaining.push(gap);
|
|
130
|
+
chromeWrite(`oke vault: skipped ${gap.name} (empty)\n`);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
store.set(gap.name, value);
|
|
134
|
+
process.env[gap.name] = value;
|
|
135
|
+
chromeWrite(`oke vault: set ${gap.name}\n`);
|
|
136
|
+
}
|
|
137
|
+
await store.save?.();
|
|
138
|
+
|
|
139
|
+
if (remaining.length > 0) {
|
|
140
|
+
const err = new VaultBootError(remaining);
|
|
141
|
+
chromeWrite(`${err.message}\n`);
|
|
142
|
+
chromeWrite("oke vault: set the missing names, then re-run `oke dev`\n");
|
|
143
|
+
return 1;
|
|
144
|
+
}
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
package/src/cli/build.ts
CHANGED
|
@@ -44,7 +44,7 @@ async function defaultSyncAdoptBarrel(rootDir: string): Promise<readonly string[
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Build a deployable bundle. Edge target aims at the <
|
|
47
|
+
* Build a deployable bundle. Edge target aims at the <17 kB kernel budget.
|
|
48
48
|
*
|
|
49
49
|
* @param options - Target / entry
|
|
50
50
|
*/
|
|
@@ -109,7 +109,7 @@ export async function buildCli(args: readonly string[]): Promise<number> {
|
|
|
109
109
|
else if (a === "--help" || a === "-h") {
|
|
110
110
|
console.log(`oke build [--target|-t bun|node|edge] [--entry|-e src/app.ts]
|
|
111
111
|
|
|
112
|
-
Tree-shaken bundle. --target edge aims at the <
|
|
112
|
+
Tree-shaken bundle. --target edge aims at the <17 kB kernel budget.
|
|
113
113
|
`);
|
|
114
114
|
return 0;
|
|
115
115
|
}
|
|
@@ -35,12 +35,37 @@ describe("oke client add", () => {
|
|
|
35
35
|
expect(src).toContain("export {}");
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
test("
|
|
38
|
+
test("emitAmbient includes live/stream stamps", () => {
|
|
39
|
+
const src = emitAmbient({
|
|
40
|
+
routes: {
|
|
41
|
+
orders: {
|
|
42
|
+
events: {
|
|
43
|
+
in: "{ orderId: string }",
|
|
44
|
+
out: "{ status: string }",
|
|
45
|
+
errors: {},
|
|
46
|
+
method: "GET",
|
|
47
|
+
path: "/orders/:orderId/events",
|
|
48
|
+
live: "order-status",
|
|
49
|
+
stream: true,
|
|
50
|
+
matchKey: ["orderId"],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
expect(src).toContain('live: "order-status"');
|
|
56
|
+
expect(src).toContain("stream: true");
|
|
57
|
+
expect(src).toContain('matchKey: ["orderId"]');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("writes ambient + routes modules and a compiling .d.ts", async () => {
|
|
39
61
|
const dir = await mkdtemp(join(tmpdir(), "oke-client-add-"));
|
|
40
62
|
const out = join(dir, "oke-client.d.ts");
|
|
41
63
|
|
|
42
64
|
const result = await clientAdd({ descriptor: fixture, out });
|
|
43
65
|
expect(result.out).toBe(out);
|
|
66
|
+
expect(result.routesOut).toContain("oke-client.routes.ts");
|
|
67
|
+
expect(result.routesSource).toContain("export const routes");
|
|
68
|
+
expect(result.routesSource).toContain('"/bookings"');
|
|
44
69
|
expect(result.source).toContain("FlightFull");
|
|
45
70
|
|
|
46
71
|
// Ambient-only project — proves the .d.ts itself is valid TypeScript.
|
package/src/cli/client-add.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `oke client add <url>` — ambient client types for a separate frontend repo.
|
|
3
3
|
*
|
|
4
|
-
* Fetches `GET {url}/_oke/client.json` and writes
|
|
5
|
-
*
|
|
4
|
+
* Fetches `GET {url}/_oke/client.json` and writes:
|
|
5
|
+
* - `oke-client.d.ts` — Register augmentation
|
|
6
|
+
* - `oke-client.routes.ts` — value `$routes` for REST / live / stream wire
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
9
|
import type { ClientDescriptor, ClientFetch } from "../client/types.ts";
|
|
@@ -11,24 +12,30 @@ import type { ClientDescriptor, ClientFetch } from "../client/types.ts";
|
|
|
11
12
|
export interface ClientAddOptions {
|
|
12
13
|
/** App base URL (required unless `descriptor` is provided). */
|
|
13
14
|
readonly url?: string;
|
|
14
|
-
/** Output path (default: `oke-client.d.ts`). */
|
|
15
|
+
/** Output path for ambient types (default: `oke-client.d.ts`). */
|
|
15
16
|
readonly out?: string;
|
|
16
17
|
/** Override fetch (tests). */
|
|
17
18
|
readonly fetch?: ClientFetch;
|
|
18
19
|
/** Inject a descriptor instead of fetching (tests). */
|
|
19
20
|
readonly descriptor?: ClientDescriptor;
|
|
21
|
+
/** Skip writing `oke-client.routes.ts` (tests). */
|
|
22
|
+
readonly skipRoutes?: boolean;
|
|
20
23
|
}
|
|
21
24
|
|
|
22
25
|
/** Result of a successful {@link clientAdd}. */
|
|
23
26
|
export interface ClientAddResult {
|
|
24
|
-
/** Absolute or relative path written. */
|
|
27
|
+
/** Absolute or relative path written for ambient types. */
|
|
25
28
|
readonly out: string;
|
|
26
29
|
/** Emitted TypeScript declaration source. */
|
|
27
30
|
readonly source: string;
|
|
31
|
+
/** Routes module path when written. */
|
|
32
|
+
readonly routesOut?: string;
|
|
33
|
+
/** Routes module source when written. */
|
|
34
|
+
readonly routesSource?: string;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
/**
|
|
31
|
-
* Fetch (or accept) a client descriptor and write
|
|
38
|
+
* Fetch (or accept) a client descriptor and write ambient + routes modules.
|
|
32
39
|
*
|
|
33
40
|
* @param options - URL / out / test overrides
|
|
34
41
|
*/
|
|
@@ -37,7 +44,14 @@ export async function clientAdd(options: ClientAddOptions): Promise<ClientAddRes
|
|
|
37
44
|
const descriptor = options.descriptor ?? (await fetchDescriptor(options.url, options.fetch));
|
|
38
45
|
const source = emitAmbient(descriptor);
|
|
39
46
|
await Bun.write(out, source);
|
|
40
|
-
|
|
47
|
+
let routesOut: string | undefined;
|
|
48
|
+
let routesSource: string | undefined;
|
|
49
|
+
if (!options.skipRoutes) {
|
|
50
|
+
routesOut = routesPathFor(out);
|
|
51
|
+
routesSource = emitRoutes(descriptor);
|
|
52
|
+
await Bun.write(routesOut, routesSource);
|
|
53
|
+
}
|
|
54
|
+
return { out, source, routesOut, routesSource };
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
/**
|
|
@@ -65,6 +79,7 @@ export async function clientAddCli(args: readonly string[]): Promise<number> {
|
|
|
65
79
|
try {
|
|
66
80
|
const result = await clientAdd({ url, out });
|
|
67
81
|
console.log(`Wrote ${result.out}`);
|
|
82
|
+
if (result.routesOut) console.log(`Wrote ${result.routesOut}`);
|
|
68
83
|
return 0;
|
|
69
84
|
} catch (err) {
|
|
70
85
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -85,27 +100,7 @@ export function emitAmbient(descriptor: ClientDescriptor): string {
|
|
|
85
100
|
: units
|
|
86
101
|
.map(([unit, flows]) => {
|
|
87
102
|
const flowLines = Object.entries(flows)
|
|
88
|
-
.map(([flow, c]) =>
|
|
89
|
-
const errors = c.errors
|
|
90
|
-
? Object.entries(c.errors)
|
|
91
|
-
.map(([code, ty]) => ` ${JSON.stringify(code)}: ${ty}`)
|
|
92
|
-
.join(";\n")
|
|
93
|
-
: "";
|
|
94
|
-
const errorBlock = errors
|
|
95
|
-
? ` errors: {\n${errors};\n };`
|
|
96
|
-
: " errors: {};";
|
|
97
|
-
return [
|
|
98
|
-
` ${JSON.stringify(flow)}: {`,
|
|
99
|
-
` in: ${c.in ?? "unknown"};`,
|
|
100
|
-
` out: ${c.out ?? "unknown"};`,
|
|
101
|
-
errorBlock,
|
|
102
|
-
c.method ? ` method: ${JSON.stringify(c.method)};` : undefined,
|
|
103
|
-
c.path ? ` path: ${JSON.stringify(c.path)};` : undefined,
|
|
104
|
-
` }`,
|
|
105
|
-
]
|
|
106
|
-
.filter((line): line is string => line !== undefined)
|
|
107
|
-
.join("\n");
|
|
108
|
-
})
|
|
103
|
+
.map(([flow, c]) => emitFlowContract(flow, c, "ambient"))
|
|
109
104
|
.join(";\n");
|
|
110
105
|
return ` ${JSON.stringify(unit)}: {\n${flowLines};\n }`;
|
|
111
106
|
})
|
|
@@ -115,6 +110,7 @@ export function emitAmbient(descriptor: ClientDescriptor): string {
|
|
|
115
110
|
/**
|
|
116
111
|
* Generated by \`oke client add\` — do not edit by hand.
|
|
117
112
|
* Ambient types for \`createClient(url)\` without importing App.
|
|
113
|
+
* Pair with \`oke-client.routes.ts\`: createClient(url, { $routes: routes }).
|
|
118
114
|
*/
|
|
119
115
|
declare module "okengine/client" {
|
|
120
116
|
interface Register {
|
|
@@ -130,6 +126,89 @@ export {};
|
|
|
130
126
|
`;
|
|
131
127
|
}
|
|
132
128
|
|
|
129
|
+
/**
|
|
130
|
+
* Emit a value `$routes` module for wire REST / live / stream.
|
|
131
|
+
*
|
|
132
|
+
* @param descriptor - Client descriptor
|
|
133
|
+
*/
|
|
134
|
+
export function emitRoutes(descriptor: ClientDescriptor): string {
|
|
135
|
+
const units = Object.entries(descriptor.routes);
|
|
136
|
+
const body =
|
|
137
|
+
units.length === 0
|
|
138
|
+
? " // no HTTP flows"
|
|
139
|
+
: units
|
|
140
|
+
.map(([unit, flows]) => {
|
|
141
|
+
const flowLines = Object.entries(flows)
|
|
142
|
+
.map(([flow, c]) => emitFlowContract(flow, c, "value"))
|
|
143
|
+
.join(",\n");
|
|
144
|
+
return ` ${JSON.stringify(unit)}: {\n${flowLines},\n }`;
|
|
145
|
+
})
|
|
146
|
+
.join(",\n");
|
|
147
|
+
|
|
148
|
+
return `/* eslint-disable */
|
|
149
|
+
/**
|
|
150
|
+
* Generated by \`oke client add\` — do not edit by hand.
|
|
151
|
+
* Runtime route stamps for createClient(url, { $routes: routes }).
|
|
152
|
+
*/
|
|
153
|
+
export const routes = {
|
|
154
|
+
${body},
|
|
155
|
+
} as const;
|
|
156
|
+
|
|
157
|
+
export default routes;
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function emitFlowContract(
|
|
162
|
+
flow: string,
|
|
163
|
+
c: ClientDescriptor["routes"][string][string],
|
|
164
|
+
mode: "ambient" | "value",
|
|
165
|
+
): string {
|
|
166
|
+
if (mode === "value") {
|
|
167
|
+
const fields = [
|
|
168
|
+
c.method !== undefined ? ` method: ${JSON.stringify(c.method)}` : undefined,
|
|
169
|
+
c.path !== undefined ? ` path: ${JSON.stringify(c.path)}` : undefined,
|
|
170
|
+
c.live !== undefined ? ` live: ${JSON.stringify(c.live)}` : undefined,
|
|
171
|
+
c.stream === true ? ` stream: true as const` : undefined,
|
|
172
|
+
c.matchKey !== undefined ? ` matchKey: ${JSON.stringify(c.matchKey)} as const` : undefined,
|
|
173
|
+
c.gates !== undefined && c.gates.length > 0
|
|
174
|
+
? ` gates: ${JSON.stringify(c.gates)} as const`
|
|
175
|
+
: undefined,
|
|
176
|
+
].filter((line): line is string => line !== undefined);
|
|
177
|
+
if (fields.length === 0) return ` ${JSON.stringify(flow)}: {}`;
|
|
178
|
+
return ` ${JSON.stringify(flow)}: {\n${fields.join(",\n")},\n }`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const errors = c.errors
|
|
182
|
+
? Object.entries(c.errors)
|
|
183
|
+
.map(([code, ty]) => ` ${JSON.stringify(code)}: ${ty}`)
|
|
184
|
+
.join(";\n")
|
|
185
|
+
: "";
|
|
186
|
+
const errorBlock = errors
|
|
187
|
+
? ` errors: {\n${errors};\n };`
|
|
188
|
+
: " errors: {};";
|
|
189
|
+
return [
|
|
190
|
+
` ${JSON.stringify(flow)}: {`,
|
|
191
|
+
` in: ${c.in ?? "unknown"};`,
|
|
192
|
+
` out: ${c.out ?? "unknown"};`,
|
|
193
|
+
errorBlock,
|
|
194
|
+
c.method ? ` method: ${JSON.stringify(c.method)};` : undefined,
|
|
195
|
+
c.path ? ` path: ${JSON.stringify(c.path)};` : undefined,
|
|
196
|
+
c.live ? ` live: ${JSON.stringify(c.live)};` : undefined,
|
|
197
|
+
c.stream === true ? ` stream: true;` : undefined,
|
|
198
|
+
c.matchKey ? ` matchKey: ${JSON.stringify(c.matchKey)};` : undefined,
|
|
199
|
+
c.gates && c.gates.length > 0 ? ` gates: ${JSON.stringify(c.gates)};` : undefined,
|
|
200
|
+
` }`,
|
|
201
|
+
]
|
|
202
|
+
.filter((line): line is string => line !== undefined)
|
|
203
|
+
.join("\n");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function routesPathFor(dtsOut: string): string {
|
|
207
|
+
if (dtsOut.endsWith(".d.ts")) return `${dtsOut.slice(0, -5)}.routes.ts`;
|
|
208
|
+
if (dtsOut.endsWith(".ts")) return dtsOut.replace(/\.ts$/, ".routes.ts");
|
|
209
|
+
return `${dtsOut}.routes.ts`;
|
|
210
|
+
}
|
|
211
|
+
|
|
133
212
|
async function fetchDescriptor(
|
|
134
213
|
url: string | undefined,
|
|
135
214
|
fetchFn: ClientFetch = globalThis.fetch.bind(globalThis),
|
package/src/cli/db-seed.ts
CHANGED
|
@@ -329,6 +329,8 @@ export async function runSeed(options: SeedOptions = {}): Promise<number> {
|
|
|
329
329
|
: await bootSeedFx(cwd, env, options.entry, loaded?.config);
|
|
330
330
|
stop = session.stop;
|
|
331
331
|
await executeSeedDef(def, env, session.fx, write);
|
|
332
|
+
const { markProjectSeeded } = await import("./project-state.ts");
|
|
333
|
+
await markProjectSeeded(cwd, { seed: identity.name });
|
|
332
334
|
write("oke db seed: ok\n");
|
|
333
335
|
return finish(EXIT_OK, "oke db seed: ok");
|
|
334
336
|
} catch (err) {
|