okengine 0.19.9 → 0.20.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 +1 -1
- package/package.json +1 -1
- package/site/content/docs/client/auth.mdx +1 -2
- package/site/content/docs/client/calling.mdx +8 -8
- package/site/content/docs/client/index.mdx +4 -4
- package/site/content/docs/client/react.mdx +5 -0
- package/site/content/docs/elements/channel/email.mdx +25 -36
- package/site/content/docs/elements/channel/index.mdx +88 -46
- package/site/content/docs/elements/channel/push.mdx +7 -9
- package/site/content/docs/elements/channel/sms.mdx +6 -4
- package/site/content/docs/elements/channel/whatsapp.mdx +11 -9
- package/site/content/docs/elements/clock/index.mdx +14 -25
- package/site/content/docs/elements/flow/http.mdx +24 -8
- package/site/content/docs/elements/flow/index.mdx +15 -12
- package/site/content/docs/elements/flow/routing.mdx +166 -122
- package/site/content/docs/elements/gate/rls.mdx +2 -2
- package/site/content/docs/elements/store/index.mdx +11 -3
- package/site/content/docs/elements/store/search.mdx +5 -5
- package/site/content/docs/elements/store/sql.mdx +91 -33
- package/site/content/docs/elements/vault/index.mdx +3 -5
- package/site/content/docs/plugins/magic-link.mdx +4 -3
- package/site/content/docs/plugins/otp.mdx +4 -3
- package/site/content/docs/plugins/two-factor.mdx +4 -0
- package/site/content/docs/providers/index.mdx +1 -1
- package/site/content/docs/recipes/index.mdx +1 -1
- package/site/content/docs/reference/cli.mdx +7 -4
- package/site/content/docs/reference/configuration.mdx +7 -7
- package/site/content/docs/reference/errors.mdx +30 -30
- package/site/content/docs/reference/fx.mdx +16 -8
- package/site/content/docs/reference/i18n.mdx +4 -4
- package/site/content/docs/reference/plugins.mdx +4 -4
- package/site/content/docs/understand/try-it.mdx +2 -0
- package/src/cli/ai-setup/ai-setup.test.ts +40 -0
- package/src/cli/ai-setup/apply.ts +28 -46
- package/src/cli/build.test.ts +3 -3
- package/src/cli/build.ts +5 -5
- package/src/cli/db-auto-push.test.ts +11 -0
- package/src/cli/db-auto-push.ts +6 -2
- package/src/cli/db.test.ts +1 -1
- package/src/cli/db.ts +6 -6
- package/src/cli/dev-db-push.test.ts +6 -2
- package/src/cli/dev-schema-sync.ts +1 -1
- package/src/cli/dev.test.ts +10 -7
- package/src/cli/dev.ts +13 -11
- package/src/cli/ensure-drizzle-config.ts +4 -3
- package/src/client-react/browser.test.ts +23 -0
- package/src/client-react/use-live-query.ts +1 -1
- package/src/compiler/flow-path.test.ts +1 -0
- package/src/compiler/flow-path.ts +1 -1
- package/src/compiler/generate-adopt.test.ts +55 -1
- package/src/compiler/generate-adopt.ts +111 -21
- package/src/config/index.ts +6 -4
- package/src/console/ui-next/dist/assets/{access-page-BoC83Ubl.js → access-page-DFLu0wTA.js} +1 -1
- package/src/console/ui-next/dist/assets/{agent-disclosure-CKjAEOqA.js → agent-disclosure-DGscxaF5.js} +1 -1
- package/src/console/ui-next/dist/assets/{cache-glyph-Ceaq9pYh.js → cache-glyph-BGmRZk7d.js} +1 -1
- package/src/console/ui-next/dist/assets/{call-pii-button-C4lmY7ck.js → call-pii-button--feUYxvG.js} +1 -1
- package/src/console/ui-next/dist/assets/{collapsible-82y257sL.js → collapsible-JWvpaiGY.js} +1 -1
- package/src/console/ui-next/dist/assets/{duration-tone-W63jaMZ8.js → duration-tone-D9yCJG4n.js} +1 -1
- package/src/console/ui-next/dist/assets/{flows-page-KFTFj2rK.js → flows-page-Bs6MD9GB.js} +1 -1
- package/src/console/ui-next/dist/assets/{highlighted-json-yE9zNTqC.js → highlighted-json-xH8MrEnv.js} +1 -1
- package/src/console/ui-next/dist/assets/{http-method-CwFeFroN.js → http-method-C4vB6ZIw.js} +1 -1
- package/src/console/ui-next/dist/assets/{index-r7xXt_VV.js → index-yTCY4AcS.js} +3 -3
- package/src/console/ui-next/dist/assets/{observability-page-BDiliMiC.js → observability-page-BxJ3R6dU.js} +1 -1
- package/src/console/ui-next/dist/assets/{replica-lag-DYDzWUFT.js → replica-lag-QRKB_IE8.js} +1 -1
- package/src/console/ui-next/dist/assets/{request-meta-CzrOfgiz.js → request-meta-DqZ-fMu5.js} +1 -1
- package/src/console/ui-next/dist/assets/{store-page-CZC2cwaw.js → store-page-Dixb6L7a.js} +1 -1
- package/src/console/ui-next/dist/assets/{trace-detail-sheet-DgeeejW7.js → trace-detail-sheet-CazhjtiU.js} +1 -1
- package/src/console/ui-next/dist/assets/{tree-expand-toggle-CzGIyOPY.js → tree-expand-toggle-DlnqYKfr.js} +1 -1
- package/src/console/ui-next/dist/assets/{units-page-DBiDCLIB.js → units-page-BXTLjU2-.js} +1 -1
- package/src/console/ui-next/dist/assets/{vault-page-CcHsthPe.js → vault-page-39KR__bc.js} +1 -1
- package/src/console/ui-next/dist/index.html +1 -1
- package/src/drivers/clock-postgres.test.ts +10 -2
- package/src/drivers/clock-postgres.ts +18 -2
- package/src/drivers/vault-driver-removal.test.ts +2 -2
- package/src/elements/channel/declare.ts +66 -3
- package/src/elements/channel/runtime.ts +9 -11
- package/src/elements/channel.test.ts +42 -0
- package/src/elements/channel.ts +4 -2
- package/src/elements/clock/reconcile.ts +45 -24
- package/src/elements/clock.test.ts +33 -0
- package/src/elements/store/emit-drizzle.ts +285 -65
- package/src/elements/store/load-plugin-tables.ts +1 -1
- package/src/elements/store/prepare-row.test.ts +57 -4
- package/src/elements/store/schema-decl.test.ts +178 -0
- package/src/elements/store/sql-session.ts +44 -2
- package/src/elements/store/table.ts +8 -6
- package/src/kernel/adopt-barrel-fresh.test.ts +1 -1
- package/src/kernel/app.ts +26 -32
- package/src/kernel/auto-registry.test.ts +26 -1
- package/src/kernel/boot.ts +2 -2
- package/src/kernel/boundary-contract.ts +6 -1
- package/src/kernel/errors.ts +3 -3
- package/src/kernel/flow-units.ts +3 -3
- package/src/kernel/fx.ts +12 -2
- package/src/kernel/mutation-id.ts +8 -0
- package/src/kernel/plugin.ts +4 -3
- package/src/kernel/project-out.test.ts +176 -0
- package/src/kernel/project-out.ts +91 -0
- package/src/kernel/realtime-bind.ts +2 -3
- package/src/kernel/router/linear.ts +12 -6
- package/src/kernel/router.test.ts +13 -0
- package/src/plugins/magic-link.ts +25 -24
- package/src/plugins/otp.ts +35 -24
- package/src/plugins/two-factor.ts +15 -0
- package/src/runs/duckdb.test.ts +2 -2
|
@@ -299,12 +299,15 @@ export const get = on(
|
|
|
299
299
|
);
|
|
300
300
|
```
|
|
301
301
|
|
|
302
|
+
Declared `out` projects the row — return it as-is (Date or `fx.clock.now()` epoch-ms → ISO-8601; extra columns strip).
|
|
303
|
+
|
|
302
304
|
</Tab>
|
|
303
305
|
|
|
304
306
|
<Tab value="POST">
|
|
305
307
|
|
|
306
|
-
Create a resource or run a command. `fx.json.create(
|
|
307
|
-
`{ data: value, error: null }
|
|
308
|
+
Create a resource or run a command. `fx.json.create(row)` returns `201 Created` with
|
|
309
|
+
`{ data: value, error: null }`. Declared `out` projects the store row (Date / epoch-ms → ISO).
|
|
310
|
+
HTTP `in` timestamps are ISO (`z.iso.datetime()`); store writes coerce them to `Date`.
|
|
308
311
|
|
|
309
312
|
```typescript title="src/flows/notes/create.ts"
|
|
310
313
|
import { on, flow, http } from "okengine";
|
|
@@ -319,8 +322,8 @@ export const create = on(
|
|
|
319
322
|
flow({
|
|
320
323
|
do: async ({ title }, fx) => {
|
|
321
324
|
const id = fx.id();
|
|
322
|
-
await fx.store(db).insert(notes).values({ id, title });
|
|
323
|
-
return fx.json.create(
|
|
325
|
+
const [row] = await fx.store(db).insert(notes).values({ id, title }).returning();
|
|
326
|
+
return fx.json.create(row);
|
|
324
327
|
},
|
|
325
328
|
}),
|
|
326
329
|
);
|
|
@@ -934,8 +937,9 @@ Every HTTP flow returns the same envelope shape. You choose status and optional
|
|
|
934
937
|
custom wrapper.
|
|
935
938
|
|
|
936
939
|
<Callout title="Envelope is fixed">
|
|
937
|
-
Success and failure always use `{ data, error }` (optional top-level `meta`).
|
|
938
|
-
|
|
940
|
+
Success and failure always use `{ data, error }` (optional top-level `meta`). Use `fx.json.*` for
|
|
941
|
+
status and `meta`; use `fx.fail` for typed errors. A raw `Response` from `do` is the exception —
|
|
942
|
+
`302` + `Location` for redirects.
|
|
939
943
|
</Callout>
|
|
940
944
|
|
|
941
945
|
**Success** — returning a value from `do` produces `200 OK`:
|
|
@@ -946,14 +950,21 @@ custom wrapper.
|
|
|
946
950
|
|
|
947
951
|
Returning `undefined` produces a `204 No Content` response with an empty body.
|
|
948
952
|
|
|
949
|
-
**Custom status** — `fx.json.create` for `201 Created`, or `fx.json.ok` with optional `meta
|
|
953
|
+
**Custom status** — `fx.json.create` for `201 Created`, or `fx.json.ok` with optional `meta`.
|
|
954
|
+
When `out` is set, pass the store row — the kernel projects it (Date → ISO-8601; extra keys strip):
|
|
950
955
|
|
|
951
956
|
```typescript
|
|
952
|
-
return fx.json.create(
|
|
957
|
+
return fx.json.create(row);
|
|
953
958
|
// or
|
|
954
959
|
return fx.json.ok({ id: "ord_1" }, { meta: { traceId: fx.runId } });
|
|
955
960
|
```
|
|
956
961
|
|
|
962
|
+
**Redirects** — return a raw `Response` so the kernel does not wrap `{ data, error }`:
|
|
963
|
+
|
|
964
|
+
```typescript
|
|
965
|
+
return new Response(null, { status: 302, headers: { Location: url } });
|
|
966
|
+
```
|
|
967
|
+
|
|
957
968
|
**Typed failures** — `fx.fail(code, data)` formats the error envelope and maps status:
|
|
958
969
|
|
|
959
970
|
```typescript
|
|
@@ -1004,6 +1015,11 @@ Standard status code mappings:
|
|
|
1004
1015
|
`error.data.issues` array for the specific field validation failure.
|
|
1005
1016
|
</Accordion>
|
|
1006
1017
|
|
|
1018
|
+
<Accordion title="I mapped Date columns to ISO by hand">
|
|
1019
|
+
Declared `out` already projects store rows. `fx.json.create(row)`, `return row`, and
|
|
1020
|
+
`fx.json.withQuery(rows, input)` are enough — extra columns strip. A miss is not a client error.
|
|
1021
|
+
</Accordion>
|
|
1022
|
+
|
|
1007
1023
|
<Accordion title="Browser blocked by CORS / missing Access-Control-*">
|
|
1008
1024
|
Cross-origin access is closed until you plug the [`cors`](/docs/plugins/cors) plugin with an
|
|
1009
1025
|
explicit `origin`. Same-origin calls need no CORS headers. Preflight `OPTIONS` is answered by the
|
|
@@ -96,19 +96,19 @@ export const ping = on(
|
|
|
96
96
|
|
|
97
97
|
`in` / `out` live on the HTTP bag. Invalid input never enters `do`:
|
|
98
98
|
|
|
99
|
-
```typescript title="src/flows/
|
|
99
|
+
```typescript title="src/flows/links/create.ts"
|
|
100
100
|
import { on, flow, http } from "okengine";
|
|
101
101
|
import { z } from "zod";
|
|
102
102
|
|
|
103
103
|
export const create = on(
|
|
104
104
|
http.post({
|
|
105
|
-
in: z.object({
|
|
106
|
-
out: z.object({ id: z.string(),
|
|
105
|
+
in: z.object({ url: z.string().url() }),
|
|
106
|
+
out: z.object({ id: z.string(), url: z.string() }),
|
|
107
107
|
}),
|
|
108
108
|
flow({
|
|
109
|
-
do: async ({
|
|
109
|
+
do: async ({ url }, fx) => {
|
|
110
110
|
const id = fx.id();
|
|
111
|
-
return { id,
|
|
111
|
+
return { id, url };
|
|
112
112
|
},
|
|
113
113
|
}),
|
|
114
114
|
);
|
|
@@ -238,11 +238,14 @@ Invoke contracts (`in` / `out` / `errors` / `breaking`) belong on the exposure
|
|
|
238
238
|
## Contracts
|
|
239
239
|
|
|
240
240
|
<Callout title="Detailed section">
|
|
241
|
-
Invoke contracts live on the **exposure**
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
241
|
+
Invoke contracts live on the **exposure** (`http.post({ in, out, errors })`, `call("name", { in,
|
|
242
|
+
out, do })`, `mcp.tool("x", { in, out })`). Manifest `flows.*` is a projection from that bag.
|
|
243
|
+
|
|
244
|
+
`in` validates before `do`. After success, `out` projects the reply (Date → ISO-8601, extra keys
|
|
245
|
+
strip); a miss is not a client error. `fx.fail` skips `out`.
|
|
246
|
+
|
|
247
|
+
Signal / Channel `schema` is a separate **emit** contract (validated at `fx.emit` / `fx.send`).
|
|
248
|
+
|
|
246
249
|
</Callout>
|
|
247
250
|
|
|
248
251
|
<Tabs items={["Standard Schema", "Failures", "Envelope"]}>
|
|
@@ -344,8 +347,8 @@ A bare `404` with body `Not Found` means **no route matched** — not `fx.fail("
|
|
|
344
347
|
</Accordion>
|
|
345
348
|
|
|
346
349
|
<Accordion title="Name stamping">
|
|
347
|
-
Prefer nameless `flow({ do })` on HTTP tree files — `src/flows/
|
|
348
|
-
`export const get` stamps `
|
|
350
|
+
Prefer nameless `flow({ do })` on HTTP tree files — `src/flows/links/[code]/get.ts` +
|
|
351
|
+
`export const get` stamps `links.get`. Signal / Clock workers pass `flow("name", { do })`
|
|
349
352
|
(**OKE1072**; Clock inline is [Clock · Inline or named export](/docs/elements/clock#inline-or-named-export)).
|
|
350
353
|
</Accordion>
|
|
351
354
|
|