okengine 0.18.4 → 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/index.mdx +25 -6
- 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 +52 -11
- 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 +78 -30
- package/site/content/docs/meta.json +11 -8
- 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/competitor-mention-removal.test.ts +1 -1
- 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 +258 -44
- 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 -132
- 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 -162
- 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-De7Lc2JC.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-RGy7VEA_.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-Ck88Jmv8.css +0 -2
- package/src/console/ui-next/dist/assets/index-_rgpdVzo.js +0 -66
- package/src/console/ui-next/dist/assets/link-BX6Vqztd.js +0 -1
- package/src/console/ui-next/dist/assets/observability-page-Ds6pcnh-.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-4rHOePuE.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-DISPgxLM.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,234 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Live"
|
|
3
|
+
description: "api.live SSE subscribe, exposure matching, resume gaps, and live resource queries."
|
|
4
|
+
icon: "Activity"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`signal.live` is HTTP SSE. Expose with `.live(signal)` on GET (or `http.live(signal)` for
|
|
9
|
+
`GET /_oke/live/{name}`), then subscribe with a callback. `for await` stays on the server.
|
|
10
|
+
|
|
11
|
+
For developers streaming shipment status, checkout progress, or live inbox rows into a browser or
|
|
12
|
+
ops console.
|
|
13
|
+
|
|
14
|
+
<Callout title="The one rule">
|
|
15
|
+
Subscribe with a callback and an unsubscribe function. Reconnects send `Last-Event-ID` from the
|
|
16
|
+
last `id:` the client actually received. A **410** `LiveResumeGap` (**OKE1210**) means that cursor
|
|
17
|
+
is gone.
|
|
18
|
+
</Callout>
|
|
19
|
+
|
|
20
|
+
## Smallest Example
|
|
21
|
+
|
|
22
|
+
<Steps>
|
|
23
|
+
|
|
24
|
+
<Step>
|
|
25
|
+
### Subscribe to a shipment feed
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
import { shipmentStatus } from "@/signals/orders";
|
|
29
|
+
|
|
30
|
+
const stop = api.live(
|
|
31
|
+
shipmentStatus,
|
|
32
|
+
{ orderId: "ord_9c2e" },
|
|
33
|
+
{
|
|
34
|
+
onEvent: (event) => {
|
|
35
|
+
// { orderId, status: "packed" | "shipped" | "delivered", eta? }
|
|
36
|
+
updateTrackingCard(event.status, event.eta);
|
|
37
|
+
},
|
|
38
|
+
onError: (err) => {
|
|
39
|
+
showTrackingBanner(err);
|
|
40
|
+
},
|
|
41
|
+
autoResubscribe: false, // default — true reopens after a drop (500ms…30s backoff)
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
</Step>
|
|
47
|
+
|
|
48
|
+
<Step>
|
|
49
|
+
### Clean up when the shopper leaves the page
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
stop(); // useEffect cleanup / process exit
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`api.orders.events({ orderId }, { onEvent })` is the same shape on the exposing Flow.
|
|
56
|
+
|
|
57
|
+
</Step>
|
|
58
|
+
|
|
59
|
+
</Steps>
|
|
60
|
+
|
|
61
|
+
## Progressive Patterns
|
|
62
|
+
|
|
63
|
+
<Tabs items={["Callback", "Flow-shaped", "autoResubscribe", "Live query"]}>
|
|
64
|
+
|
|
65
|
+
<Tab value="Callback">
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
const stop = api.live(
|
|
69
|
+
shipmentStatus,
|
|
70
|
+
{ orderId: "ord_9c2e" },
|
|
71
|
+
{
|
|
72
|
+
onEvent: (event) => updateTrackingCard(event.status, event.eta),
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
stop();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
</Tab>
|
|
79
|
+
|
|
80
|
+
<Tab value="Flow-shaped">
|
|
81
|
+
|
|
82
|
+
When the route is the exposing Flow itself:
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const stop = api.orders.events(
|
|
86
|
+
{ orderId: "ord_9c2e" },
|
|
87
|
+
{
|
|
88
|
+
onEvent: (event) => {
|
|
89
|
+
updateTrackingCard(event.status, event.eta);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
stop();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
</Tab>
|
|
97
|
+
|
|
98
|
+
<Tab value="autoResubscribe">
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const stop = api.live(
|
|
102
|
+
shipmentStatus,
|
|
103
|
+
{ orderId: "ord_9c2e" },
|
|
104
|
+
{
|
|
105
|
+
onEvent: (event) => updateTrackingCard(event.status, event.eta),
|
|
106
|
+
onError: (err) => showTrackingBanner(err),
|
|
107
|
+
autoResubscribe: true, // reopen after a drop — 500ms…30s backoff
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Reconnects send `Last-Event-ID` from the last `id:` the client actually received.
|
|
113
|
+
|
|
114
|
+
</Tab>
|
|
115
|
+
|
|
116
|
+
<Tab value="Live query">
|
|
117
|
+
|
|
118
|
+
When a resource opts into `live: true`, the compiler mounts `GET <path>/live` next to the CRUD
|
|
119
|
+
verbs. That route streams **classified** row events — not a shared tape — so each subscriber only
|
|
120
|
+
sees rows that still pass their RLS stamp + list filters (e.g. open tickets for this tenant).
|
|
121
|
+
|
|
122
|
+
Prefer [React · useLiveQuery](/docs/client/react) for UI. Core transport helpers live on
|
|
123
|
+
`okengine/client`.
|
|
124
|
+
|
|
125
|
+
</Tab>
|
|
126
|
+
|
|
127
|
+
</Tabs>
|
|
128
|
+
|
|
129
|
+
## Live handlers
|
|
130
|
+
|
|
131
|
+
| Option | Type | Default | Meaning |
|
|
132
|
+
| ----------------- | -------------------- | ------- | --------------------------------------------- |
|
|
133
|
+
| `onEvent` | `(event) => void` | — | Required — each SSE payload |
|
|
134
|
+
| `onError` | `(err) => void` | — | 4xx, envelope, network drop |
|
|
135
|
+
| `onOpen` | `() => void` | — | Stream connected |
|
|
136
|
+
| `autoResubscribe` | `boolean` | `false` | Reopen after drop (500ms…30s backoff) |
|
|
137
|
+
| `via` | `"unit.flow"` string | — | Disambiguate when two exposures match equally |
|
|
138
|
+
|
|
139
|
+
## Exposure matching
|
|
140
|
+
|
|
141
|
+
The client picks the unique exposure whose `matchKey` fields are a subset of the input, preferring
|
|
142
|
+
the largest match (`{ orderId }` beats firehose). A tie needs `via: "unit.flow"`.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
api.live(
|
|
146
|
+
shipmentStatus,
|
|
147
|
+
{ orderId: "ord_9c2e" },
|
|
148
|
+
{
|
|
149
|
+
onEvent: updateTrackingCard,
|
|
150
|
+
via: "orders.events",
|
|
151
|
+
},
|
|
152
|
+
);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Or call the exposing Flow directly: `api.orders.events(input, { onEvent })`.
|
|
156
|
+
|
|
157
|
+
## Resume and LiveResumeGap
|
|
158
|
+
|
|
159
|
+
Reconnects send `Last-Event-ID` from the last `id:` the client actually received.
|
|
160
|
+
|
|
161
|
+
A **410** `LiveResumeGap` (**OKE1210**) means that cursor is gone — `onError` fires, the cursor is
|
|
162
|
+
dropped, and `autoResubscribe` replays the remaining tape after backoff.
|
|
163
|
+
|
|
164
|
+
Server exposure: [Signal · Live](/docs/elements/signal/live) and
|
|
165
|
+
[HTTP · Live Streams](/docs/elements/flow/http#live-streams).
|
|
166
|
+
|
|
167
|
+
## Live queries (`store.resource({ live: true })`)
|
|
168
|
+
|
|
169
|
+
| `kind` | Meaning |
|
|
170
|
+
| --------- | -------------------------------------------------------------- |
|
|
171
|
+
| `upsert` | Row visible under stamp + query — merge/replace by primary key |
|
|
172
|
+
| `revoked` | Row left visibility (`reason: "rls"` \| `"query"`) — remove |
|
|
173
|
+
| `delete` | Row deleted in CDC — remove |
|
|
174
|
+
|
|
175
|
+
Every `mutate` from `useLiveQuery` generates a client UUID sent as the `X-Oke-Mutation-Id`
|
|
176
|
+
header — the server echoes it onto that write's CDC events, so:
|
|
177
|
+
|
|
178
|
+
- Your own late SSE echoes never double-apply (pending-set dedupe).
|
|
179
|
+
- Reconnects replay-guard by event `seq` (`isReplayedEvent`).
|
|
180
|
+
- Manual `refetch()` re-runs only the HTTP list read; reconnects always do a full
|
|
181
|
+
subscribe-protocol cycle (new snapshot + replay).
|
|
182
|
+
|
|
183
|
+
| State | Meaning |
|
|
184
|
+
| ---------------- | ------------------------------------------------------------------- |
|
|
185
|
+
| `isLoading` | Waiting for the first snapshot — no data yet |
|
|
186
|
+
| `isConnected` | SSE stream is open |
|
|
187
|
+
| `isReconnecting` | Stream dropped after a successful load; reconnect backoff in flight |
|
|
188
|
+
|
|
189
|
+
**Consequence:** optimistic patches roll back automatically when the Flow returns `error !== null`.
|
|
190
|
+
Server CDC / the successful response clear the override so the next upsert is authoritative.
|
|
191
|
+
|
|
192
|
+
Full React wiring: [React](/docs/client/react).
|
|
193
|
+
|
|
194
|
+
## Troubleshooting
|
|
195
|
+
|
|
196
|
+
<Accordions>
|
|
197
|
+
|
|
198
|
+
<Accordion title="api.live throws Multiple live exposures">
|
|
199
|
+
Two routes share the same match shape. Pass `via: "unit.flow"` or call the exposing flow
|
|
200
|
+
(`api.orders.events(input, {onEvent})`).
|
|
201
|
+
</Accordion>
|
|
202
|
+
|
|
203
|
+
<Accordion title="onError sees LiveResumeGap / HTTP 410">
|
|
204
|
+
The last `id:` is not on the server tape. The client drops the cursor. With `autoResubscribe:
|
|
205
|
+
true` the next request omits `Last-Event-ID` and replays what remains.
|
|
206
|
+
</Accordion>
|
|
207
|
+
|
|
208
|
+
<Accordion title="No events after subscribe">
|
|
209
|
+
Confirm the server exposed the signal (`.live(signal)` on GET or `http.live(signal)`), the
|
|
210
|
+
`matchKey` fields are present in `input`, and gates allow the identity. See [Signal ·
|
|
211
|
+
Live](/docs/elements/signal/live).
|
|
212
|
+
</Accordion>
|
|
213
|
+
|
|
214
|
+
</Accordions>
|
|
215
|
+
|
|
216
|
+
## Learn more
|
|
217
|
+
|
|
218
|
+
- [React](/docs/client/react) — `useLive`, `useLiveQuery`
|
|
219
|
+
- [Calling](/docs/client/calling) — typed proxy and envelopes
|
|
220
|
+
- [Signal · Live](/docs/elements/signal/live) — tape, resume, OKE1210
|
|
221
|
+
- [HTTP · Live Streams](/docs/elements/flow/http#live-streams) — server exposure
|
|
222
|
+
- [Store](/docs/elements/store) — `live: true` on resources
|
|
223
|
+
|
|
224
|
+
## Next
|
|
225
|
+
|
|
226
|
+
<Cards>
|
|
227
|
+
<Card title="React" description="useLive and useLiveQuery hooks." href="/docs/client/react" />
|
|
228
|
+
<Card
|
|
229
|
+
title="Signal · Live"
|
|
230
|
+
description="Server tape, Last-Event-ID, resume gaps."
|
|
231
|
+
href="/docs/elements/signal/live"
|
|
232
|
+
/>
|
|
233
|
+
<Card title="Calling" description="createClient and REST vs RPC." href="/docs/client/calling" />
|
|
234
|
+
</Cards>
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "React"
|
|
3
|
+
description: "useSession, Can, useLive, and useLiveQuery from okengine/client-react — React helpers over createClient."
|
|
4
|
+
icon: "Atom"
|
|
5
|
+
source: "docs/spec/unified-theory.md"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
`okengine/client-react` is a separate package so core `okengine/client` stays under the size
|
|
9
|
+
budget. Hooks wrap the same typed client: session status, live SSE, and live resource lists with
|
|
10
|
+
optimistic `mutate`.
|
|
11
|
+
|
|
12
|
+
For developers building React storefronts and ops consoles on top of `createClient`.
|
|
13
|
+
|
|
14
|
+
<Callout title="The one rule">
|
|
15
|
+
Pass the same `api` you built with `createClient`. Hooks never open a second client factory — they
|
|
16
|
+
subscribe, call Flows, and clean up on unmount.
|
|
17
|
+
</Callout>
|
|
18
|
+
|
|
19
|
+
## Smallest Example
|
|
20
|
+
|
|
21
|
+
<Steps>
|
|
22
|
+
|
|
23
|
+
<Step>
|
|
24
|
+
### Create the client and session
|
|
25
|
+
|
|
26
|
+
```typescript title="web/src/session.ts"
|
|
27
|
+
import { createClient } from "okengine/client";
|
|
28
|
+
import { vault } from "okengine/vault";
|
|
29
|
+
import { app } from "../../src/app";
|
|
30
|
+
|
|
31
|
+
export const api = createClient(app, vault.env("PUBLIC_API_URL") ?? "", {
|
|
32
|
+
auth: { mode: "cookie", csrfConfigured: true },
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
</Step>
|
|
37
|
+
|
|
38
|
+
<Step>
|
|
39
|
+
### Show the signed-in shopper in the header
|
|
40
|
+
|
|
41
|
+
```typescript title="web/src/AccountMenu.tsx"
|
|
42
|
+
import { Can, useSession } from "okengine/client-react";
|
|
43
|
+
import { api } from "./session";
|
|
44
|
+
|
|
45
|
+
export function AccountMenu() {
|
|
46
|
+
const { status, user, signOut } = useSession(api.auth!);
|
|
47
|
+
|
|
48
|
+
if (status === "loading") return null;
|
|
49
|
+
if (status === "unauthenticated") return <a href="/sign-in">Sign in</a>;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<>
|
|
53
|
+
<Can auth={api.auth!} all={["orders:write"]} fallback={null}>
|
|
54
|
+
<a href="/fulfillment">Fulfillment</a>
|
|
55
|
+
</Can>
|
|
56
|
+
<button type="button" onClick={() => signOut()}>
|
|
57
|
+
{user?.email}
|
|
58
|
+
</button>
|
|
59
|
+
</>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`Can` / `useAuthorize` are UI-only — Gate on Flows remains real authz.
|
|
65
|
+
|
|
66
|
+
</Step>
|
|
67
|
+
|
|
68
|
+
</Steps>
|
|
69
|
+
|
|
70
|
+
## Progressive Patterns
|
|
71
|
+
|
|
72
|
+
<Tabs items={["useSession", "Can / useAuthorize", "useLive", "useLiveQuery", "mutate"]}>
|
|
73
|
+
|
|
74
|
+
<Tab value="useSession">
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
import { useSession } from "okengine/client-react";
|
|
78
|
+
|
|
79
|
+
const { status, user, accessToken, refresh, signOut } = useSession(api.auth!);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
| Field | Meaning |
|
|
83
|
+
| ------------- | ------------------------------------------------------- |
|
|
84
|
+
| `status` | `"loading"` \| `"authenticated"` \| `"unauthenticated"` |
|
|
85
|
+
| `user` | `auth.me` payload or `null` |
|
|
86
|
+
| `accessToken` | Current Bearer from `memorySession` (or `null`) |
|
|
87
|
+
| `refresh()` | Re-run `auth.me` |
|
|
88
|
+
| `signOut()` | `session.clear()` + unauthenticated |
|
|
89
|
+
|
|
90
|
+
</Tab>
|
|
91
|
+
|
|
92
|
+
<Tab value="Can / useAuthorize">
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { Can, useAuthorize } from "okengine/client-react";
|
|
96
|
+
|
|
97
|
+
<Can auth={api.auth!} all={["orders:write"]} fallback={<Denied />}>
|
|
98
|
+
<FulfillmentLink />
|
|
99
|
+
</Can>;
|
|
100
|
+
|
|
101
|
+
const { status, missing } = useAuthorize(api.auth!, { all: ["orders:write"] });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
UI chrome only — Gate on Flows is the security boundary. Prefer these over bare `useScope` /
|
|
105
|
+
`useCan`.
|
|
106
|
+
|
|
107
|
+
</Tab>
|
|
108
|
+
|
|
109
|
+
<Tab value="useLive">
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { useLive } from "okengine/client-react";
|
|
113
|
+
import { shipmentStatus } from "@/signals/orders";
|
|
114
|
+
|
|
115
|
+
const { events, latest, error, isConnected } = useLive(
|
|
116
|
+
api,
|
|
117
|
+
shipmentStatus,
|
|
118
|
+
{ orderId: "ord_9c2e" },
|
|
119
|
+
{
|
|
120
|
+
autoResubscribe: true,
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// latest?.status → "packed" | "shipped" | "delivered"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Cleanup calls `stop()` on unmount. Changing `signal` / `input` / `via` resets `events`.
|
|
128
|
+
|
|
129
|
+
| Option | Meaning |
|
|
130
|
+
| ----------------- | -------------------------------------- |
|
|
131
|
+
| `autoResubscribe` | Reopen after drop (same as `api.live`) |
|
|
132
|
+
| `via` | Disambiguate equal exposure matches |
|
|
133
|
+
|
|
134
|
+
</Tab>
|
|
135
|
+
|
|
136
|
+
<Tab value="useLiveQuery">
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { useLiveQuery } from "okengine/client-react";
|
|
140
|
+
|
|
141
|
+
const { data, error, isLoading, isConnected, isReconnecting, refetch, mutate } = useLiveQuery({
|
|
142
|
+
api,
|
|
143
|
+
listFlow: api.inbox.list,
|
|
144
|
+
query: { status: "open", assignee: "me" },
|
|
145
|
+
live: { method: "GET", path: "/inbox/live" }, // from app.$routes
|
|
146
|
+
options: {
|
|
147
|
+
enabled: session.status === "authenticated", // default true — idle when false
|
|
148
|
+
refreshKey: workspaceId, // switch workspace → full re-subscribe
|
|
149
|
+
onAuthRefresh: onAuthRefreshed, // auth.refresh() → new snapshot + replay
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
| State | Meaning |
|
|
155
|
+
| ---------------- | ------------------------------------------------------------------- |
|
|
156
|
+
| `isLoading` | Waiting for the first snapshot — no data yet |
|
|
157
|
+
| `isConnected` | SSE stream is open |
|
|
158
|
+
| `isReconnecting` | Stream dropped after a successful load; reconnect backoff in flight |
|
|
159
|
+
|
|
160
|
+
</Tab>
|
|
161
|
+
|
|
162
|
+
<Tab value="mutate">
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
await mutate(
|
|
166
|
+
api.inbox.update,
|
|
167
|
+
{ id: ticketId, status: "resolved" },
|
|
168
|
+
{
|
|
169
|
+
optimistic: (rows) =>
|
|
170
|
+
rows.map((row) => (row.id === ticketId ? { ...row, status: "resolved" } : row)),
|
|
171
|
+
pkOf: (input) => input.id,
|
|
172
|
+
},
|
|
173
|
+
);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Every `mutate` call generates a client UUID sent as the `X-Oke-Mutation-Id` header — the server
|
|
177
|
+
echoes it onto that write's CDC events for pending-set dedupe and replay guards.
|
|
178
|
+
|
|
179
|
+
**Consequence:** optimistic patches roll back automatically when the Flow returns `error !== null`.
|
|
180
|
+
Server CDC / the successful response clear the override so the next upsert is authoritative.
|
|
181
|
+
|
|
182
|
+
</Tab>
|
|
183
|
+
|
|
184
|
+
</Tabs>
|
|
185
|
+
|
|
186
|
+
## Package boundary
|
|
187
|
+
|
|
188
|
+
| Export | Package | Role |
|
|
189
|
+
| ----------------------------------------- | ----------------------- | ------------------------------------------- |
|
|
190
|
+
| `createClient` / `api.live` | `okengine/client` | Typed proxy + SSE subscribe |
|
|
191
|
+
| `createAuthClient` / `memorySession` | `okengine/client/auth` | Secure session orchestration |
|
|
192
|
+
| `vault` / `vault.env` | `okengine/vault` | Env + config contracts (subpath — not root) |
|
|
193
|
+
| `useSession` / `useLive` / `useLiveQuery` | `okengine/client-react` | React hooks (`react` optional peer) |
|
|
194
|
+
| `subscribeLiveResource` | `okengine/client-react` | Non-hook live resource stream helper |
|
|
195
|
+
|
|
196
|
+
Prefer [`createAuthClient`](/docs/client/auth) for cookie/Bearer sessions and method helpers.
|
|
197
|
+
`useLiveQuery` accepts `listPath` to derive `GET ${listPath}/live` when `live` is omitted.
|
|
198
|
+
|
|
199
|
+
## `useLiveQuery` options
|
|
200
|
+
|
|
201
|
+
| Option | Meaning |
|
|
202
|
+
| --------------- | ---------------------------------------------- |
|
|
203
|
+
| `enabled` | Default `true` — idle when `false` |
|
|
204
|
+
| `refreshKey` | Identity change → full re-subscribe |
|
|
205
|
+
| `onAuthRefresh` | After `auth.refresh()` → new snapshot + replay |
|
|
206
|
+
|
|
207
|
+
`refetch()` re-runs only the HTTP list read; reconnects always do a full subscribe-protocol cycle
|
|
208
|
+
(new snapshot + replay). Event kinds and resume physics: [Live](/docs/client/live).
|
|
209
|
+
|
|
210
|
+
## Troubleshooting
|
|
211
|
+
|
|
212
|
+
<Accordions>
|
|
213
|
+
|
|
214
|
+
<Accordion title="Cannot find module okengine/client-react">
|
|
215
|
+
Install / import the React package separately. Core `okengine/client` does not re-export hooks —
|
|
216
|
+
that keeps the client runtime under budget.
|
|
217
|
+
</Accordion>
|
|
218
|
+
|
|
219
|
+
<Accordion title="useSession stuck on loading">
|
|
220
|
+
Confirm `auth.me` is adopted, Bearer `getToken` returns a token, and the me Flow is reachable.
|
|
221
|
+
Without a token, status becomes `"unauthenticated"`.
|
|
222
|
+
</Accordion>
|
|
223
|
+
|
|
224
|
+
<Accordion title="useLiveQuery never connects">
|
|
225
|
+
Pass `live: { method, path }` from `app.$routes` for the resource’s `/live` route. Set
|
|
226
|
+
`enabled: true` (or omit). See [Live](/docs/client/live) for exposure and resume errors.
|
|
227
|
+
</Accordion>
|
|
228
|
+
|
|
229
|
+
</Accordions>
|
|
230
|
+
|
|
231
|
+
## Learn more
|
|
232
|
+
|
|
233
|
+
- [Auth](/docs/client/auth) — `memorySession` and gate denials
|
|
234
|
+
- [Live](/docs/client/live) — `api.live`, resume, live query kinds
|
|
235
|
+
- [Calling](/docs/client/calling) — envelopes and list pager
|
|
236
|
+
- [Signal · Live](/docs/elements/signal/live) — server tape
|
|
237
|
+
- [Store](/docs/elements/store) — `live: true` resources
|
|
238
|
+
|
|
239
|
+
## Next
|
|
240
|
+
|
|
241
|
+
<Cards>
|
|
242
|
+
<Card
|
|
243
|
+
title="Live"
|
|
244
|
+
description="SSE subscribe and live resource physics."
|
|
245
|
+
href="/docs/client/live"
|
|
246
|
+
/>
|
|
247
|
+
<Card title="Auth" description="Bearer sessions behind the hooks." href="/docs/client/auth" />
|
|
248
|
+
<Card title="Calling" description="createClient forms and options." href="/docs/client/calling" />
|
|
249
|
+
</Cards>
|