okengine 0.19.9 → 0.21.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 +2 -1
- package/site/content/docs/client/auth.mdx +1 -2
- package/site/content/docs/client/calling.mdx +125 -37
- package/site/content/docs/client/index.mdx +7 -7
- 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 +42 -23
- package/site/content/docs/elements/flow/index.mdx +41 -30
- 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/gate/tenancy.mdx +1 -1
- package/site/content/docs/elements/store/files.mdx +11 -5
- package/site/content/docs/elements/store/index.mdx +13 -6
- package/site/content/docs/elements/store/kv.mdx +8 -2
- package/site/content/docs/elements/store/search.mdx +5 -5
- package/site/content/docs/elements/store/sql.mdx +100 -39
- package/site/content/docs/elements/vault/index.mdx +14 -13
- package/site/content/docs/elements/vault/secrets.mdx +6 -3
- package/site/content/docs/index.mdx +1 -1
- 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/recipes/rustfs.mdx +1 -1
- package/site/content/docs/reference/cli.mdx +7 -4
- package/site/content/docs/reference/configuration.mdx +8 -8
- package/site/content/docs/reference/errors.mdx +229 -55
- package/site/content/docs/reference/fx.mdx +22 -9
- package/site/content/docs/reference/i18n.mdx +4 -4
- package/site/content/docs/reference/plugins.mdx +4 -4
- package/site/content/docs/understand/the-architecture.mdx +2 -2
- package/site/content/docs/understand/try-it.mdx +759 -24
- 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-app-runner.ts +2 -1
- 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/cli/start.ts +2 -1
- package/src/client/create.ts +3 -3
- package/src/client/explain.test.ts +252 -0
- package/src/client/explain.ts +272 -0
- package/src/client/live.test.ts +44 -0
- package/src/client/notes-contract.test.ts +10 -0
- package/src/client/sse.ts +6 -2
- package/src/client/transport.test.ts +67 -0
- package/src/client/transport.ts +24 -40
- package/src/client/types.ts +17 -6
- package/src/client-react/browser.test.ts +23 -0
- package/src/client-react/live-resource.ts +6 -2
- 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/compiler/response.ts +17 -27
- package/src/config/index.ts +6 -4
- package/src/console/server/invoke-user-flow.test.ts +8 -2
- package/src/console/server/invoke-user-flow.ts +12 -18
- package/src/console/server/security.gate.test.ts +1 -1
- package/src/console/ui-next/dist/assets/{access-page-BoC83Ubl.js → access-page-tIbsiphz.js} +1 -1
- package/src/console/ui-next/dist/assets/{agent-disclosure-CKjAEOqA.js → agent-disclosure-CSKumwS2.js} +1 -1
- package/src/console/ui-next/dist/assets/{cache-glyph-Ceaq9pYh.js → cache-glyph-BCC-DxKT.js} +1 -1
- package/src/console/ui-next/dist/assets/{call-pii-button-C4lmY7ck.js → call-pii-button-jOmYISdc.js} +1 -1
- package/src/console/ui-next/dist/assets/{collapsible-82y257sL.js → collapsible-DC2xNaAb.js} +1 -1
- package/src/console/ui-next/dist/assets/{duration-tone-W63jaMZ8.js → duration-tone-CwoV56jn.js} +1 -1
- package/src/console/ui-next/dist/assets/{flows-page-KFTFj2rK.js → flows-page-gT1lsWQK.js} +1 -1
- package/src/console/ui-next/dist/assets/{highlighted-json-yE9zNTqC.js → highlighted-json-C2GZEJNI.js} +1 -1
- package/src/console/ui-next/dist/assets/{http-method-CwFeFroN.js → http-method-BdYjcIrD.js} +1 -1
- package/src/console/ui-next/dist/assets/{index-r7xXt_VV.js → index-Cul17AcV.js} +3 -3
- package/src/console/ui-next/dist/assets/{observability-page-BDiliMiC.js → observability-page-oY9vdYBk.js} +1 -1
- package/src/console/ui-next/dist/assets/{replica-lag-DYDzWUFT.js → replica-lag-C4QdAF7J.js} +1 -1
- package/src/console/ui-next/dist/assets/{request-meta-CzrOfgiz.js → request-meta-C43DHyld.js} +1 -1
- package/src/console/ui-next/dist/assets/{store-page-CZC2cwaw.js → store-page-CL0D9dOq.js} +1 -1
- package/src/console/ui-next/dist/assets/{trace-detail-sheet-DgeeejW7.js → trace-detail-sheet-Dcpo4Us_.js} +1 -1
- package/src/console/ui-next/dist/assets/{tree-expand-toggle-CzGIyOPY.js → tree-expand-toggle-CKJTuv43.js} +1 -1
- package/src/console/ui-next/dist/assets/{units-page-DBiDCLIB.js → units-page-1PlT19ft.js} +1 -1
- package/src/console/ui-next/dist/assets/{vault-page-CcHsthPe.js → vault-page-BwZ9YjTW.js} +1 -1
- package/src/console/ui-next/dist/index.html +1 -1
- package/src/docker/docker.test.ts +3 -3
- package/src/docker/images-config.test.ts +4 -4
- package/src/docker/stack-id.test.ts +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/files-errors.test.ts +149 -0
- package/src/elements/store/files-errors.ts +189 -0
- package/src/elements/store/kv-errors.test.ts +98 -0
- package/src/elements/store/kv-errors.ts +139 -0
- package/src/elements/store/load-plugin-tables.ts +1 -1
- package/src/elements/store/prepare-row.test.ts +57 -4
- package/src/elements/store/resource.ts +11 -7
- package/src/elements/store/runtime.ts +18 -13
- package/src/elements/store/schema-decl.test.ts +178 -0
- package/src/elements/store/sql-errors.test.ts +197 -0
- package/src/elements/store/sql-errors.ts +294 -0
- package/src/elements/store/sql-session.test.ts +52 -0
- package/src/elements/store/sql-session.ts +50 -2
- package/src/elements/store/store-errors.ts +47 -0
- package/src/elements/store/table.ts +8 -6
- package/src/http.ts +9 -1
- package/src/i18n/catalogs/ar.ts +18 -0
- package/src/i18n/catalogs/en.ts +18 -0
- package/src/index.ts +9 -1
- package/src/kernel/adopt-barrel-fresh.test.ts +1 -1
- package/src/kernel/app.ts +40 -34
- 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/builtin-errors.test.ts +117 -0
- package/src/kernel/builtin-errors.ts +129 -0
- package/src/kernel/call.test.ts +182 -0
- package/src/kernel/errors-vault.ts +16 -0
- package/src/kernel/errors.registry.test.ts +7 -0
- package/src/kernel/errors.ts +97 -24
- package/src/kernel/fail-helpers.ts +34 -0
- package/src/kernel/flow-units.ts +3 -3
- package/src/kernel/fx.test.ts +8 -0
- package/src/kernel/fx.ts +24 -8
- package/src/kernel/index.ts +12 -1
- 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
- package/src/runtime/dev-request-log.ts +29 -11
- package/src/term.test.ts +76 -0
- package/src/term.ts +166 -3
|
@@ -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
|
);
|
|
@@ -118,7 +118,7 @@ export const create = on(
|
|
|
118
118
|
|
|
119
119
|
<Tab value="Failures">
|
|
120
120
|
|
|
121
|
-
Declare domain errors on the exposure bag
|
|
121
|
+
Declare domain errors on the exposure bag. Built-in codes (`NotFound`, `Forbidden`, …) need no `errors:` — use the helpers:
|
|
122
122
|
|
|
123
123
|
```typescript title="src/flows/orders/[id]/get.ts"
|
|
124
124
|
import { on, flow, http } from "okengine";
|
|
@@ -130,12 +130,11 @@ export const get = on(
|
|
|
130
130
|
http.get({
|
|
131
131
|
in: z.object({ id: z.string() }),
|
|
132
132
|
out: z.object({ id: z.string(), sku: z.string(), qty: z.number() }),
|
|
133
|
-
errors: { NotFound: z.object({ id: z.string() }) },
|
|
134
133
|
}),
|
|
135
134
|
flow({
|
|
136
135
|
do: async ({ id }, fx) => {
|
|
137
136
|
const [order] = await fx.store(db).select().from(orders).where(eq(orders.id, id));
|
|
138
|
-
if (!order) return fx.fail(
|
|
137
|
+
if (!order) return fx.fail.notFound({ id });
|
|
139
138
|
return order;
|
|
140
139
|
},
|
|
141
140
|
}),
|
|
@@ -238,11 +237,14 @@ Invoke contracts (`in` / `out` / `errors` / `breaking`) belong on the exposure
|
|
|
238
237
|
## Contracts
|
|
239
238
|
|
|
240
239
|
<Callout title="Detailed section">
|
|
241
|
-
Invoke contracts live on the **exposure**
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
Invoke contracts live on the **exposure** (`http.post({ in, out, errors })`, `call("name", { in,
|
|
241
|
+
out, do })`, `mcp.tool("x", { in, out })`). Manifest `flows.*` is a projection from that bag.
|
|
242
|
+
|
|
243
|
+
`in` validates before `do`. After success, `out` projects the reply (Date → ISO-8601, extra keys
|
|
244
|
+
strip); a miss is not a client error. `fx.fail` skips `out`.
|
|
245
|
+
|
|
246
|
+
Signal / Channel `schema` is a separate **emit** contract (validated at `fx.emit` / `fx.send`).
|
|
247
|
+
|
|
246
248
|
</Callout>
|
|
247
249
|
|
|
248
250
|
<Tabs items={["Standard Schema", "Failures", "Envelope"]}>
|
|
@@ -315,15 +317,22 @@ HTTP success from a returned value is `200` + `{ data, error: null }`. `undefine
|
|
|
315
317
|
|
|
316
318
|
Status for `error.code`:
|
|
317
319
|
|
|
318
|
-
| Code
|
|
319
|
-
|
|
|
320
|
-
| `ValidationError`
|
|
321
|
-
| `Unauthorized`
|
|
322
|
-
| `Forbidden`
|
|
323
|
-
| `
|
|
324
|
-
|
|
|
325
|
-
|
|
326
|
-
|
|
320
|
+
| Code | Status |
|
|
321
|
+
| ------------------------------------------------------ | ------ |
|
|
322
|
+
| `ValidationError` | `422` |
|
|
323
|
+
| `Unauthorized` | `401` |
|
|
324
|
+
| `Forbidden` | `403` |
|
|
325
|
+
| `NotFound` | `404` |
|
|
326
|
+
| `Conflict` / `ForeignKey` | `409` |
|
|
327
|
+
| `UnsupportedMediaType` | `415` |
|
|
328
|
+
| `RateLimited` / `AuthRateLimited` | `429` |
|
|
329
|
+
| `DatabaseError` (`not_null` / `check`) | `422` |
|
|
330
|
+
| `DatabaseError` (`retryable`) / `ServiceUnavailable` | `503` |
|
|
331
|
+
| `DatabaseError` (else) / `InternalError` | `500` |
|
|
332
|
+
| Domain codes (`OutOfStock`, `FlightFull`, `Duplicate`) | `400` |
|
|
333
|
+
|
|
334
|
+
A bare `404` with body `Not Found` means **no route matched** — not `fx.fail.notFound`. Clients
|
|
335
|
+
distinguish router miss (plain text) from domain miss (JSON envelope).
|
|
327
336
|
|
|
328
337
|
</Tab>
|
|
329
338
|
|
|
@@ -344,8 +353,8 @@ A bare `404` with body `Not Found` means **no route matched** — not `fx.fail("
|
|
|
344
353
|
</Accordion>
|
|
345
354
|
|
|
346
355
|
<Accordion title="Name stamping">
|
|
347
|
-
Prefer nameless `flow({ do })` on HTTP tree files — `src/flows/
|
|
348
|
-
`export const get` stamps `
|
|
356
|
+
Prefer nameless `flow({ do })` on HTTP tree files — `src/flows/links/[code]/get.ts` +
|
|
357
|
+
`export const get` stamps `links.get`. Signal / Clock workers pass `flow("name", { do })`
|
|
349
358
|
(**OKE1072**; Clock inline is [Clock · Inline or named export](/docs/elements/clock#inline-or-named-export)).
|
|
350
359
|
</Accordion>
|
|
351
360
|
|
|
@@ -383,7 +392,9 @@ A bare `404` with body `Not Found` means **no route matched** — not `fx.fail("
|
|
|
383
392
|
|
|
384
393
|
<Accordion title="fx.call identity">
|
|
385
394
|
`fx.call` starts the callee with an **empty** `fx.auth` (fail-closed). `fx.tenant.id` propagates.
|
|
386
|
-
For audit only, read `fx.principal` — gates never consult it.
|
|
395
|
+
For audit only, read `fx.principal` — gates never consult it. Controlled `return fx.fail(...)`
|
|
396
|
+
comes back as a `FlowFailure` value; an unhandled `throw` rethrows to the caller (never silent
|
|
397
|
+
`undefined`). See [fx](/docs/reference/fx).
|
|
387
398
|
</Accordion>
|
|
388
399
|
|
|
389
400
|
<Accordion title="Undeclared effects (OKE1001–1007)">
|
|
@@ -543,8 +554,8 @@ Default is `true` once `gate.auth.tenant` is on.
|
|
|
543
554
|
</Accordion>
|
|
544
555
|
|
|
545
556
|
<Accordion title="Thrown Error becomes a mystery 500 instead of a typed envelope">
|
|
546
|
-
Uncaught exceptions
|
|
547
|
-
fx.fail("OutOfStock", payload)
|
|
557
|
+
Uncaught exceptions become `InternalError` (catalog message only — the thrown `message` is not
|
|
558
|
+
copied). For expected misses use `fx.fail.notFound` / domain `fx.fail("OutOfStock", payload)`.
|
|
548
559
|
</Accordion>
|
|
549
560
|
|
|
550
561
|
<Accordion title="422 ValidationError — path param missing from in">
|
|
@@ -553,9 +564,9 @@ Default is `true` once `gate.auth.tenant` is on.
|
|
|
553
564
|
Parsing](/docs/elements/flow/http#request-parsing).
|
|
554
565
|
</Accordion>
|
|
555
566
|
|
|
556
|
-
<Accordion title="
|
|
557
|
-
|
|
558
|
-
|
|
567
|
+
<Accordion title="Router 404 vs domain NotFound">
|
|
568
|
+
A bare `404` with body `Not Found` means **no route matched**. `fx.fail.notFound` is a JSON
|
|
569
|
+
envelope at **404** with `error.code: "NotFound"`. Clients distinguish by envelope, not status.
|
|
559
570
|
</Accordion>
|
|
560
571
|
|
|
561
572
|
<Accordion title="Read-only Flow never cache-hits">
|