okengine 0.10.2 → 0.11.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.
Files changed (343) hide show
  1. package/package.json +76 -10
  2. package/site/content/docs/ai/mcp.mdx +0 -1
  3. package/site/content/docs/deployment/docker-swarm.mdx +48 -111
  4. package/site/content/docs/deployment/docker.mdx +43 -36
  5. package/site/content/docs/deployment/index.mdx +9 -9
  6. package/site/content/docs/deployment/kubernetes.mdx +4 -4
  7. package/site/content/docs/elements/ai.mdx +7 -13
  8. package/site/content/docs/elements/channel.mdx +9 -13
  9. package/site/content/docs/elements/clock.mdx +8 -14
  10. package/site/content/docs/elements/flow.mdx +46 -54
  11. package/site/content/docs/elements/gate.mdx +6 -11
  12. package/site/content/docs/elements/signal.mdx +2 -8
  13. package/site/content/docs/elements/store.mdx +79 -93
  14. package/site/content/docs/elements/vault.mdx +89 -76
  15. package/site/content/docs/get-started/basic-usage.mdx +8 -14
  16. package/site/content/docs/get-started/installation.mdx +36 -36
  17. package/site/content/docs/get-started/introduction.mdx +11 -0
  18. package/site/content/docs/get-started/why.mdx +3 -4
  19. package/site/content/docs/index.mdx +0 -1
  20. package/site/content/docs/meta.json +0 -1
  21. package/site/content/docs/plugins/anonymous.mdx +1 -1
  22. package/site/content/docs/plugins/magic-link.mdx +11 -11
  23. package/site/content/docs/plugins/otp.mdx +2 -2
  24. package/site/content/docs/plugins/passkey.mdx +1 -1
  25. package/site/content/docs/plugins/two-factor.mdx +1 -1
  26. package/site/content/docs/plugins/username.mdx +1 -1
  27. package/site/content/docs/recipes/caddy.mdx +1 -1
  28. package/site/content/docs/recipes/cockroachdb.mdx +2 -2
  29. package/site/content/docs/recipes/dragonfly.mdx +1 -1
  30. package/site/content/docs/recipes/index.mdx +1 -2
  31. package/site/content/docs/recipes/llama-cpp.mdx +21 -23
  32. package/site/content/docs/recipes/mailpit.mdx +11 -11
  33. package/site/content/docs/recipes/meilisearch.mdx +10 -10
  34. package/site/content/docs/recipes/meta.json +0 -1
  35. package/site/content/docs/recipes/ollama.mdx +1 -1
  36. package/site/content/docs/recipes/pgdog.mdx +12 -9
  37. package/site/content/docs/recipes/postgres.mdx +3 -3
  38. package/site/content/docs/recipes/redis.mdx +2 -2
  39. package/site/content/docs/recipes/rustfs.mdx +10 -7
  40. package/site/content/docs/recipes/sglang.mdx +1 -1
  41. package/site/content/docs/recipes/supabase-docker.mdx +1 -1
  42. package/site/content/docs/recipes/timescale.mdx +2 -2
  43. package/site/content/docs/recipes/valkey.mdx +1 -1
  44. package/site/content/docs/recipes/vllm.mdx +1 -1
  45. package/site/content/docs/recipes/yugabytedb.mdx +2 -2
  46. package/site/content/docs/reference/cli.md +61 -38
  47. package/site/content/docs/reference/configuration.mdx +145 -70
  48. package/site/content/docs/reference/environment-variables.mdx +36 -28
  49. package/site/content/docs/reference/errors.mdx +28 -29
  50. package/site/content/docs/reference/fx.mdx +14 -7
  51. package/site/content/docs/reference/i18n.mdx +17 -6
  52. package/site/content/docs/reference/index.mdx +5 -0
  53. package/site/content/docs/reference/meta.json +1 -0
  54. package/site/content/docs/reference/migrating-environments.mdx +158 -0
  55. package/site/content/docs/reference/plugins.mdx +2 -2
  56. package/src/auth/gate-auth.test.ts +12 -10
  57. package/src/cli/ai-setup/ai-setup.test.ts +30 -16
  58. package/src/cli/ai-setup/apply.ts +111 -15
  59. package/src/cli/ai-setup/catalog.ts +3 -3
  60. package/src/cli/ai-setup/index.ts +1 -1
  61. package/src/cli/ai-setup/prompts.ts +1 -1
  62. package/src/cli/ai-setup/recommend.test.ts +1 -1
  63. package/src/cli/ask-seed.test.ts +3 -3
  64. package/src/cli/build.ts +8 -9
  65. package/src/cli/db-auto-push.test.ts +6 -3
  66. package/src/cli/db-auto-push.ts +7 -5
  67. package/src/cli/db-seed.ts +7 -8
  68. package/src/cli/db.test.ts +70 -71
  69. package/src/cli/db.ts +86 -12
  70. package/src/cli/dev-controller.test.ts +35 -0
  71. package/src/cli/dev-controller.ts +298 -0
  72. package/src/cli/dev-controls.ts +11 -65
  73. package/src/cli/dev-db-push.test.ts +47 -15
  74. package/src/cli/dev-schema-sync.test.ts +11 -11
  75. package/src/cli/dev-schema-sync.ts +10 -10
  76. package/src/cli/dev-session-lock.test.ts +106 -0
  77. package/src/cli/dev-session-lock.ts +209 -0
  78. package/src/cli/dev.test.ts +246 -114
  79. package/src/cli/dev.ts +153 -205
  80. package/src/cli/doc-staleness.test.ts +3 -6
  81. package/src/cli/docker-clean.test.ts +33 -1
  82. package/src/cli/docker-clean.ts +28 -33
  83. package/src/cli/docker-cli.test.ts +12 -11
  84. package/src/cli/docker.ts +95 -20
  85. package/src/cli/doctor.test.ts +40 -0
  86. package/src/cli/doctor.ts +142 -9
  87. package/src/cli/drizzle-env.test.ts +11 -13
  88. package/src/cli/drizzle-env.ts +18 -11
  89. package/src/cli/ensure-drizzle-config.ts +11 -14
  90. package/src/cli/hero-meta.test.ts +15 -15
  91. package/src/cli/hero-meta.ts +10 -9
  92. package/src/cli/index.ts +36 -6
  93. package/src/cli/load-config.images.test.ts +44 -10
  94. package/src/cli/load-config.source.test.ts +50 -0
  95. package/src/cli/load-config.ts +35 -29
  96. package/src/cli/meilisearch-local.ts +1 -2
  97. package/src/cli/mode.ts +7 -58
  98. package/src/cli/registry.ts +175 -19
  99. package/src/cli/resolve-dev-sql-env.test.ts +8 -16
  100. package/src/cli/resolve-dev-sql-env.ts +13 -15
  101. package/src/cli/safe-defaults.test.ts +29 -11
  102. package/src/cli/schema.ts +65 -16
  103. package/src/cli/test.ts +58 -0
  104. package/src/cli/tui/App.tsx +252 -0
  105. package/src/cli/tui/DevLive.tsx +116 -0
  106. package/src/cli/tui/components/ConfirmDialog.tsx +48 -0
  107. package/src/cli/tui/components/HeaderBar.tsx +67 -0
  108. package/src/cli/tui/components/LogStream.tsx +47 -0
  109. package/src/cli/tui/components/PanelCard.tsx +39 -0
  110. package/src/cli/tui/components/SelectRow.tsx +37 -0
  111. package/src/cli/tui/components/SlashPalette.tsx +172 -0
  112. package/src/cli/tui/components/Spinner.tsx +32 -0
  113. package/src/cli/tui/components/StatusBar.tsx +51 -0
  114. package/src/cli/tui/components/StatusDot.tsx +37 -0
  115. package/src/cli/tui/components/TabBar.tsx +49 -0
  116. package/src/cli/tui/components/Wordmark.tsx +43 -0
  117. package/src/cli/tui/format.ts +38 -0
  118. package/src/cli/tui/keys.test.ts +18 -0
  119. package/src/cli/tui/keys.ts +26 -0
  120. package/src/cli/tui/launch.test.ts +18 -0
  121. package/src/cli/tui/launch.ts +57 -0
  122. package/src/cli/tui/panels/Dashboard.tsx +201 -0
  123. package/src/cli/tui/panels/Database.tsx +198 -0
  124. package/src/cli/tui/panels/Dev.tsx +257 -0
  125. package/src/cli/tui/panels/Docker.tsx +357 -0
  126. package/src/cli/tui/panels/Navigator.test.ts +22 -0
  127. package/src/cli/tui/panels/Navigator.tsx +213 -0
  128. package/src/cli/tui/slash-catalog.test.ts +31 -0
  129. package/src/cli/tui/slash-catalog.ts +184 -0
  130. package/src/cli/tui/slash-run.ts +54 -0
  131. package/src/cli/tui/state/ports.ts +95 -0
  132. package/src/cli/tui/theme.ts +24 -0
  133. package/src/cli/vault-cmd.test.ts +402 -0
  134. package/src/cli/vault-cmd.ts +727 -69
  135. package/src/cli/vault-secure-input.test.ts +56 -0
  136. package/src/cli/vault-secure-input.ts +124 -0
  137. package/src/compiler/effects-infer.ts +7 -0
  138. package/src/compiler/extract.ts +12 -0
  139. package/src/compiler/fixtures/skyport/oke.config.ts +7 -5
  140. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
  141. package/src/compiler/fixtures/skyport.expected.json +1 -1
  142. package/src/compiler/generate-adopt.ts +27 -1
  143. package/src/compiler-entry.ts +7 -0
  144. package/src/config/define-config.test.ts +111 -47
  145. package/src/config/driver-defaults.test.ts +115 -0
  146. package/src/config/driver-defaults.ts +156 -0
  147. package/src/config/index.ts +246 -131
  148. package/src/config/resolve-driver.test.ts +14 -19
  149. package/src/console/server/app.ts +4 -2
  150. package/src/console/server/console.test.ts +58 -1
  151. package/src/console/server/flows.ts +22 -2
  152. package/src/console/server/index.ts +3 -0
  153. package/src/console/server/operator-db.test.ts +55 -13
  154. package/src/console/server/operator-db.ts +305 -263
  155. package/src/console/server/serve.ts +16 -7
  156. package/src/console/server/state.ts +31 -9
  157. package/src/console/server/vault.test.ts +120 -5
  158. package/src/console/server/vault.ts +208 -12
  159. package/src/console/ui/dist/assets/{index-D-9KFce5.js → index--Y0Uaz-m.js} +2 -2
  160. package/src/console/ui/dist/assets/panel-vault-BkZdJPX8.js +1 -0
  161. package/src/console/ui/dist/assets/style-C3L349iZ.css +3 -0
  162. package/src/console/ui/dist/index.html +2 -2
  163. package/src/console/ui/shell/client.ts +16 -0
  164. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +54 -1
  165. package/src/console/ui/vault/VaultA11yView.tsx +33 -1
  166. package/src/console/ui/vault/backend.test.ts +75 -0
  167. package/src/console/ui/vault/backend.ts +117 -0
  168. package/src/console/ui/vault/fixture.ts +21 -2
  169. package/src/console/ui/vault/index.ts +11 -1
  170. package/src/console/ui/vault/types.ts +26 -0
  171. package/src/docker/compose.ts +164 -61
  172. package/src/docker/derive.ts +106 -12
  173. package/src/docker/docker.test.ts +156 -110
  174. package/src/docker/helpers.ts +98 -0
  175. package/src/docker/images-config.test.ts +163 -0
  176. package/src/docker/index.ts +30 -5
  177. package/src/docker/recipes/index.ts +0 -3
  178. package/src/docker/recipes/llama-cpp.ts +4 -4
  179. package/src/docker/recipes/pgdog.ts +9 -2
  180. package/src/docker/resources.test.ts +71 -0
  181. package/src/docker/resources.ts +176 -0
  182. package/src/docker/stack-id.test.ts +11 -4
  183. package/src/docker/stack-id.ts +42 -32
  184. package/src/docker/stack.integration.test.ts +4 -15
  185. package/src/docker/types.ts +35 -3
  186. package/src/drivers/ai-ollama.integration.test.ts +2 -2
  187. package/src/drivers/conformance.test.ts +11 -12
  188. package/src/drivers/drizzle-dialect.test.ts +0 -4
  189. package/src/drivers/drizzle-dialect.ts +7 -13
  190. package/src/drivers/index.ts +24 -7
  191. package/src/drivers/journal-postgres.test.ts +3 -1
  192. package/src/drivers/journal-postgres.ts +4 -2
  193. package/src/drivers/meilisearch.ts +1 -1
  194. package/src/drivers/pglite.ts +28 -5
  195. package/src/drivers/types.ts +9 -11
  196. package/src/drivers/vault-aws-secrets-manager.test.ts +159 -0
  197. package/src/drivers/vault-aws-secrets-manager.ts +333 -0
  198. package/src/drivers/vault-builtin.test.ts +110 -0
  199. package/src/drivers/vault-builtin.ts +184 -0
  200. package/src/drivers/vault-driver-removal.test.ts +13 -0
  201. package/src/drivers/vault-managed.test.ts +95 -0
  202. package/src/drivers/vault-managed.ts +101 -25
  203. package/src/drivers/vault-types.ts +25 -5
  204. package/src/elements/ai/runtime.ts +1 -1
  205. package/src/elements/clock/chaos.test.ts +4 -1
  206. package/src/elements/clock/durable.ts +57 -4
  207. package/src/elements/clock.test.ts +13 -14
  208. package/src/elements/gate/constants.ts +18 -0
  209. package/src/elements/gate.test.ts +1 -1
  210. package/src/elements/gate.ts +2 -2
  211. package/src/elements/store/domain-ddl.test.ts +5 -12
  212. package/src/elements/store/emit-drizzle.ts +44 -19
  213. package/src/elements/store/index-boot.test.ts +15 -116
  214. package/src/elements/store/load-plugin-tables.ts +1 -1
  215. package/src/elements/store/resource-list-docs.fixture.ts +12 -6
  216. package/src/elements/store/resource-list-docs.test.ts +64 -44
  217. package/src/elements/store/resource.test.ts +17 -10
  218. package/src/elements/store/runtime.ts +9 -12
  219. package/src/elements/store/schema-decl.test.ts +16 -32
  220. package/src/elements/store/seed.test.ts +1 -2
  221. package/src/elements/store/seed.ts +7 -8
  222. package/src/elements/store/sql-condition.test.ts +2 -2
  223. package/src/elements/store/sql-session.test.ts +8 -10
  224. package/src/elements/store/sql-session.ts +10 -2
  225. package/src/elements/store.test.ts +13 -13
  226. package/src/elements/vault/audit.ts +233 -0
  227. package/src/elements/vault/boot-chain.test.ts +78 -0
  228. package/src/elements/vault/boot-chain.ts +43 -39
  229. package/src/elements/vault/builtin-adapter.test.ts +479 -0
  230. package/src/elements/vault/builtin-adapter.ts +1184 -0
  231. package/src/elements/vault/crypto.test.ts +237 -0
  232. package/src/elements/vault/crypto.ts +431 -0
  233. package/src/elements/vault/declare.ts +164 -3
  234. package/src/elements/vault/errors.ts +56 -0
  235. package/src/elements/vault/kms-unseal.test.ts +76 -0
  236. package/src/elements/vault/kms-unseal.ts +181 -0
  237. package/src/elements/vault/path.ts +90 -0
  238. package/src/elements/vault/resilience.test.ts +102 -0
  239. package/src/elements/vault/resilience.ts +107 -0
  240. package/src/elements/vault/runtime.ts +36 -4
  241. package/src/elements/vault/security-checklist.test.ts +130 -0
  242. package/src/elements/vault/storage.ts +448 -0
  243. package/src/elements/vault/types.ts +288 -0
  244. package/src/elements/vault/unseal.ts +150 -0
  245. package/src/elements/vault.test.ts +72 -4
  246. package/src/elements/vault.ts +91 -2
  247. package/src/full.ts +248 -0
  248. package/src/http.ts +41 -0
  249. package/src/i18n/interpolate-simple.ts +37 -0
  250. package/src/i18n/messages.ts +51 -4
  251. package/src/i18n-entry.ts +7 -0
  252. package/src/index.ts +35 -145
  253. package/src/journal-entry.ts +20 -0
  254. package/src/kernel/adopt-barrel-fresh.test.ts +25 -10
  255. package/src/kernel/app.ts +40 -42
  256. package/src/kernel/auto-registry.test.ts +2 -2
  257. package/src/kernel/boot-bind/ai.test.ts +5 -5
  258. package/src/kernel/boot-bind/ai.ts +2 -1
  259. package/src/kernel/boot-bind/channel.test.ts +6 -6
  260. package/src/kernel/boot-bind/channel.ts +5 -4
  261. package/src/kernel/boot-bind/clock.ts +5 -5
  262. package/src/kernel/boot-bind/gate.ts +6 -7
  263. package/src/kernel/boot-bind/honor-config.test.ts +42 -42
  264. package/src/kernel/boot-bind/journal.ts +5 -5
  265. package/src/kernel/boot-bind/signal.ts +3 -1
  266. package/src/kernel/boot-bind/store.test.ts +55 -37
  267. package/src/kernel/boot-bind/store.ts +24 -34
  268. package/src/kernel/boot-bind/vault.ts +19 -4
  269. package/src/kernel/boot.test.ts +12 -4
  270. package/src/kernel/boot.ts +31 -19
  271. package/src/kernel/budget-entry.ts +1 -1
  272. package/src/kernel/compensate.test.ts +288 -1
  273. package/src/kernel/compensate.ts +126 -0
  274. package/src/kernel/concurrency.test.ts +10 -9
  275. package/src/kernel/effects-stamping.test.ts +27 -2
  276. package/src/kernel/element-registries.ts +5 -3
  277. package/src/kernel/flow.ts +4 -2
  278. package/src/kernel/fx.test.ts +119 -3
  279. package/src/kernel/fx.ts +215 -40
  280. package/src/kernel/index.ts +14 -0
  281. package/src/kernel/journal.ts +130 -7
  282. package/src/kernel/pipeline.test.ts +20 -6
  283. package/src/kernel/redacted.test.ts +35 -0
  284. package/src/kernel/redacted.ts +24 -2
  285. package/src/kernel/router/create-default.ts +16 -0
  286. package/src/kernel/router/create-edge.ts +18 -0
  287. package/src/kernel/router/create.ts +23 -0
  288. package/src/kernel/router/index.ts +23 -0
  289. package/src/kernel/router/linear.ts +88 -0
  290. package/src/kernel/router/regexp.ts +188 -0
  291. package/src/kernel/router/smart.ts +120 -0
  292. package/src/kernel/router/trie.ts +108 -0
  293. package/src/kernel/router/types.ts +56 -0
  294. package/src/kernel/router.ts +18 -532
  295. package/src/kernel-entry.ts +43 -0
  296. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  297. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  298. package/src/plugins/config-source.test.ts +7 -7
  299. package/src/release/build-lib.ts +58 -0
  300. package/src/release/exports.test.ts +4 -2
  301. package/src/release/exports.ts +30 -4
  302. package/src/release/measure.ts +101 -22
  303. package/src/runs/duckdb.ts +7 -2
  304. package/src/shared/optional-peer.ts +41 -0
  305. package/src/term.test.ts +3 -44
  306. package/src/test/create-test-app.ts +12 -0
  307. package/src/test/provisions.integration.test.ts +1 -1
  308. package/src/test/reset-element-registries.ts +2 -0
  309. package/src/upgrade/codemods.test.ts +7 -20
  310. package/src/upgrade/codemods.ts +93 -60
  311. package/site/content/docs/console/access.mdx +0 -29
  312. package/site/content/docs/console/ai.mdx +0 -35
  313. package/site/content/docs/console/architecture.mdx +0 -35
  314. package/site/content/docs/console/channels.mdx +0 -37
  315. package/site/content/docs/console/clock.mdx +0 -51
  316. package/site/content/docs/console/flows.mdx +0 -31
  317. package/site/content/docs/console/gates.mdx +0 -73
  318. package/site/content/docs/console/index.mdx +0 -54
  319. package/site/content/docs/console/manifest-diff.mdx +0 -34
  320. package/site/content/docs/console/meta.json +0 -24
  321. package/site/content/docs/console/overview.mdx +0 -40
  322. package/site/content/docs/console/plugins.mdx +0 -41
  323. package/site/content/docs/console/privacy.mdx +0 -32
  324. package/site/content/docs/console/runs.mdx +0 -50
  325. package/site/content/docs/console/signals.mdx +0 -40
  326. package/site/content/docs/console/store.mdx +0 -32
  327. package/site/content/docs/console/tenancy.mdx +0 -32
  328. package/site/content/docs/console/traces.mdx +0 -38
  329. package/site/content/docs/console/vault.mdx +0 -41
  330. package/site/content/docs/recipes/openbao.mdx +0 -141
  331. package/src/cli/ask-dev-mode.ts +0 -40
  332. package/src/cli/dev-mode.test.ts +0 -45
  333. package/src/cli/dev-mode.ts +0 -78
  334. package/src/cli/openbao-bootstrap.test.ts +0 -150
  335. package/src/cli/openbao-bootstrap.ts +0 -321
  336. package/src/cli/openbao-restart.integration.test.ts +0 -145
  337. package/src/console/ui/dist/assets/panel-vault-Za1GyJfM.js +0 -1
  338. package/src/console/ui/dist/assets/style-C8MxEWPd.css +0 -3
  339. package/src/docker/recipes/openbao.ts +0 -47
  340. package/src/drivers/libsql.ts +0 -179
  341. package/src/drivers/sqlite.ts +0 -44
  342. package/src/drivers/vault-openbao.test.ts +0 -97
  343. package/src/drivers/vault-openbao.ts +0 -143
@@ -29,18 +29,18 @@ string. Custom app codes stay message-less until registered.
29
29
 
30
30
  ## OKE numeric codes
31
31
 
32
- | Code | Name | Cause | Fix |
33
- | ------ | ----------------- | ------------------------------------------------ | -------------------------------------------------- |
34
- | `1001` | undeclared read | Flow reads a resource not in `effects.reads` | Add it to the flow's `effects.reads` |
35
- | `1002` | undeclared write | Flow writes a resource not in `effects.writes` | Add it to the flow's `effects.writes` |
36
- | `1003` | undeclared emit | Flow emits a signal not in `effects.emits` | Add it to the flow's `effects.emits` |
37
- | `1004` | undeclared send | Flow sends a template not in `effects.sends` | Add it to the flow's `effects.sends` |
38
- | `1005` | undeclared ask | Flow asks a prompt not in `effects.asks` | Add it to the flow's `effects.asks` |
39
- | `1006` | undeclared secret | Flow reads a secret not in `effects.secrets` | Add it to the flow's `effects.secrets` |
40
- | `1007` | undeclared call | Flow calls a flow not in `effects.calls` | Add it to the flow's `effects.calls` |
41
- | `1042` | orphan emit | Emit with zero subscribers and `optional` false | Add `on(signal, …)` or declare `optional: true` |
42
- | `1043` | signal schema | Emit payload failed the signal's `schema` | Pass a payload that matches `schema`, or remove it |
43
- | `1101` | schema missing | Domain table absent in docker/prod — no auto-DDL | Run `oke db migrate` against this environment |
32
+ | Code | Name | Cause | Fix |
33
+ | ------ | ----------------- | ----------------------------------------------- | -------------------------------------------------- |
34
+ | `1001` | undeclared read | Flow reads a resource not in `effects.reads` | Add it to the flow's `effects.reads` |
35
+ | `1002` | undeclared write | Flow writes a resource not in `effects.writes` | Add it to the flow's `effects.writes` |
36
+ | `1003` | undeclared emit | Flow emits a signal not in `effects.emits` | Add it to the flow's `effects.emits` |
37
+ | `1004` | undeclared send | Flow sends a template not in `effects.sends` | Add it to the flow's `effects.sends` |
38
+ | `1005` | undeclared ask | Flow asks a prompt not in `effects.asks` | Add it to the flow's `effects.asks` |
39
+ | `1006` | undeclared secret | Flow reads a secret not in `effects.secrets` | Add it to the flow's `effects.secrets` |
40
+ | `1007` | undeclared call | Flow calls a flow not in `effects.calls` | Add it to the flow's `effects.calls` |
41
+ | `1042` | orphan emit | Emit with zero subscribers and `optional` false | Add `on(signal, …)` or declare `optional: true` |
42
+ | `1043` | signal schema | Emit payload failed the signal's `schema` | Pass a payload that matches `schema`, or remove it |
43
+ | `1101` | schema missing | Domain table absent in `prod` — no auto-DDL | Run `oke db migrate` against this environment |
44
44
 
45
45
  <Callout title="Effects are usually inferred">
46
46
  The 1001–1007 family exists for flows that declare effects explicitly. Most apps never write an
@@ -69,23 +69,22 @@ Returned, not thrown — the request never reached `do`:
69
69
 
70
70
  Thrown by specific subsystems — each names its own cause:
71
71
 
72
- | Error | Thrown when | What to do |
73
- | ----------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------- |
74
- | `VaultBootError` | A vault contract has no value in any resolution layer | Set the missing names — the error lists every gap |
75
- | `OpenBaoUnavailableError` | Vault driver can't reach OpenBao, or it's sealed, in docker/prod | Restore the vault or unseal it — never silently skipped |
76
- | `OpenBaoBootstrapError` | First-boot init/unseal failed, or key material is missing/unsafe | Read the message it names the exact failing step |
77
- | `AiPiiBuildError` | Build: a flow sends PII fields to a third-party model | Drop the fields or add `allowPii: true` fields named |
78
- | `AiSchemaValidationError` | A model response failed the prompt's `out` schema | Fix the prompt or the schema — response didn't conform |
79
- | `ScheduleNotOverridableError` | Console tried to edit a clock declared without `overridable: true` | Declare it overridable and redeploy |
80
- | `ClockResourceNotFoundError` | Console action targeted an unknown clock name | Check the name against your `clock()` declarations |
81
- | `DryRunWriteIsolationError` | A write attempted inside a dry run | Dry runs never write use a real run |
82
- | `ManifestValidationError` | The compiled Manifest failed schema validation | Re-run the build; the error names the offending entry |
83
- | `CrossPlaneError` | A user-plane token was used on the operator plane (or vice versa) | Use the correct principal for the plane |
84
- | `AttenuationError` | A token was used beyond its attenuated scope | Re-issue with the needed scope |
85
- | `SessionError` | Session token invalid, expired, or malformed | Re-authenticate |
86
- | `OperatorError` | Operator-plane operation failed its checks | Error message names the failed check |
87
- | `AccessGrantError` | Console access grant rejected | Re-request access with a valid grant |
88
- | `UnsupportedPathError` | A route path shape the router can't compile | Simplify the path pattern |
72
+ | Error | Thrown when | What to do |
73
+ | ----------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------ |
74
+ | `VaultBootError` | A vault contract has no value in any resolution layer | Set the missing names — the error lists every gap |
75
+ | `VaultError` (`UNSUPPORTED`) | Managed provider unknown or not implemented in core | Use `aws-secrets-manager`, built-in `vault`, or `env` |
76
+ | `AiPiiBuildError` | Build: a flow sends PII fields to a third-party model | Drop the fields or add `allowPii: true` fields named |
77
+ | `AiSchemaValidationError` | A model response failed the prompt's `out` schema | Fix the prompt or the schemaresponse didn't conform |
78
+ | `ScheduleNotOverridableError` | Console tried to edit a clock declared without `overridable: true` | Declare it overridable and redeploy |
79
+ | `ClockResourceNotFoundError` | Console action targeted an unknown clock name | Check the name against your `clock()` declarations |
80
+ | `DryRunWriteIsolationError` | A write attempted inside a dry run | Dry runs never write use a real run |
81
+ | `ManifestValidationError` | The compiled Manifest failed schema validation | Re-run the build; the error names the offending entry |
82
+ | `CrossPlaneError` | A user-plane token was used on the operator plane (or vice versa) | Use the correct principal for the plane |
83
+ | `AttenuationError` | A token was used beyond its attenuated scope | Re-issue with the needed scope |
84
+ | `SessionError` | Session token invalid, expired, or malformed | Re-authenticate |
85
+ | `OperatorError` | Operator-plane operation failed its checks | Error message names the failed check |
86
+ | `AccessGrantError` | Console access grant rejected | Re-request access with a valid grant |
87
+ | `UnsupportedPathError` | A route path shape the router can't compile | Simplify the path pattern |
89
88
 
90
89
  ## Learn more
91
90
 
@@ -156,9 +156,16 @@ AI calls are nondeterministic: journaling is forced on and auto-cache disabled a
156
156
 
157
157
  ## Vault
158
158
 
159
- | Signature | Records | Returns / notes |
160
- | -------------------- | ------- | ----------------------------------------------------------------------------------------- |
161
- | `fx.vault(contract)` | `read` | `Redacted<string>` — prints/logs as a placeholder; `.reveal()` at the credential boundary |
159
+ | Signature | Records | Returns / notes |
160
+ | ---------------------------------- | -------- | -------------------------------------------------------------------------------------------------- |
161
+ | `fx.vault.get(contract)` | `secret` | `Promise<Redacted<string>>` — prints/logs as a placeholder; `.reveal()` at the credential boundary |
162
+ | `fx.vault.set(path, value, opts?)` | `secret` | `{ path, version }` — needs a bound Vault backend |
163
+ | `fx.vault.rotate(path, value)` | `secret` | `{ path, version }` — new version with a fresh data key |
164
+ | `fx.vault.delete(path)` | `secret` | `boolean` — crypto-shreds the path |
165
+ | `fx.vault.list(prefix?)` | — | Secret paths, never values |
166
+ | `fx.vault.status()` | — | `{ sealed, initialized, backend }` |
167
+
168
+ `get` reads through the boot resolution chain. Everything else needs the encrypted-at-rest backend (`drivers.vault = "vault"`) and throws without it.
162
169
 
163
170
  ## Clock
164
171
 
@@ -205,7 +212,7 @@ Register catalogs with `defineLocale` before boot (nested trees → dot keys). A
205
212
  `Register` so keys autocomplete and typos fail at compile time:
206
213
 
207
214
  ```typescript
208
- import { defineLocale, defineMessages, type MessagesFor } from "okengine";
215
+ import { defineLocale, defineMessages, type MessagesFor } from "okengine/i18n";
209
216
 
210
217
  export const en = defineMessages({
211
218
  greeting: "Hello, {name}",
@@ -259,9 +266,9 @@ must log who started the call chain.
259
266
  ## Not on `fx`
260
267
 
261
268
  <Callout title="No fx.metric">
262
- Investigated and declined. [Runs](/docs/console/runs) already own per-invocation observability as
263
- wide events. Native alerting is `fx.runs` + Clock + Channel — not a second counter/gauge API.
264
- Optional OTLP export for existing Grafana/Datadog stacks is additive and never required.
269
+ Investigated and declined. `fx.runs` already provides per-invocation observability as wide events.
270
+ Native alerting is `fx.runs` + Clock + Channel — not a second counter/gauge API. Optional OTLP
271
+ export for existing Grafana/Datadog stacks is additive and never required.
265
272
  </Callout>
266
273
 
267
274
  ## Learn more
@@ -22,19 +22,22 @@ format inside a Flow with `fx.t`. Configure supported locales once in
22
22
  ### Configure locales
23
23
 
24
24
  ```typescript title="oke.config.ts"
25
- i18n: { locales: ["en", "ar"], default: "en", dir: { ar: "rtl" } },
25
+ i18n: { locales: ["en"], default: "en" },
26
26
  ```
27
27
 
28
- If `i18n` is omitted, boot still defaults to `locales: ["en", "ar"]` and
29
- `default: "en"`.
28
+ create-oke scaffolds English-only. Choose **Add more languages** (or
29
+ `--locales ar,fr`) to write locale files + `locales/index.ts` and expand
30
+ `i18n.locales` (Arabic also gets `dir: { ar: "rtl" }`).
31
+
32
+ If `i18n` is omitted, boot defaults to `locales: ["en"]` and `default: "en"`.
30
33
 
31
34
  </Step>
32
35
 
33
36
  <Step>
34
37
  ### Register catalogs
35
38
 
36
- Side-effect import locale modules before boot (the starter already does this
37
- from `src/app.ts`):
39
+ Each locale file calls `defineLocale`. The starter pulls them in once from
40
+ `core.ts` via `locales/index.ts` — `app.ts` only needs `import "@/core"`:
38
41
 
39
42
  ```typescript title="src/locales/en.ts"
40
43
  import { defineMessages, defineLocale } from "okengine";
@@ -55,7 +58,7 @@ declare module "okengine" {
55
58
 
56
59
  ```typescript title="src/locales/ar.ts"
57
60
  import { defineLocale, type MessagesFor } from "okengine";
58
- import { en } from "./en";
61
+ import type { en } from "./en";
59
62
 
60
63
  defineLocale("ar", {
61
64
  greeting: "مرحباً، {name}",
@@ -64,6 +67,14 @@ defineLocale("ar", {
64
67
  } satisfies MessagesFor<typeof en>);
65
68
  ```
66
69
 
70
+ ```typescript title="src/locales/index.ts"
71
+ import "./en";
72
+ import "./ar";
73
+ ```
74
+
75
+ When you add `ar` via create-oke, the Arabic catalog is filled in and
76
+ `locales/index.ts` gains `import "./ar"`. Other tags get an English stub.
77
+
67
78
  </Step>
68
79
 
69
80
  <Step>
@@ -15,6 +15,11 @@ Dense tables and command lists. Reach for these when you already know what you a
15
15
  description="Every option in oke.config.ts."
16
16
  href="/docs/reference/configuration"
17
17
  />
18
+ <Card
19
+ title="Migrating environments"
20
+ description="local/docker maps → dev/test/prod."
21
+ href="/docs/reference/migrating-environments"
22
+ />
18
23
  <Card title="fx" description="The complete fx surface and effects." href="/docs/reference/fx" />
19
24
  <Card
20
25
  title="i18n"
@@ -4,6 +4,7 @@
4
4
  "pages": [
5
5
  "index",
6
6
  "configuration",
7
+ "migrating-environments",
7
8
  "fx",
8
9
  "i18n",
9
10
  "client",
@@ -0,0 +1,158 @@
1
+ ---
2
+ title: "Migrating environments"
3
+ description: "Move from local/docker/test/prod driver maps to the Docker-first dev/test/prod model."
4
+ icon: "ArrowRightLeft"
5
+ ---
6
+
7
+ Older projects used four driver-map keys (`local` · `docker` · `test` · `prod`) and an optional
8
+ `oke mode` switch. Today there are three environments, `oke dev` always starts Docker Compose, and
9
+ SQLite-family drivers (`sqlite`, `libsql`) are gone.
10
+
11
+ There is **no** soft-compat and **no** upgrade codemod for this change. Edit `oke.config.ts` by
12
+ hand using this page.
13
+
14
+ <Callout title="The one rule">
15
+ Rename maps to `dev` / `test` / `prod`, pin `pglite` for SQL tests, delete `.oke/mode`, then run
16
+ `oke dev` / `oke test`.
17
+ </Callout>
18
+
19
+ ## Quick start
20
+
21
+ <Steps>
22
+
23
+ <Step>
24
+ ### Edit the three-key shape
25
+
26
+ ```typescript title="oke.config.ts"
27
+ import { defineConfig } from "okengine/config";
28
+
29
+ export default defineConfig({
30
+ drivers: {
31
+ store: {
32
+ sql: { dev: "postgres", test: "pglite", prod: "postgres" },
33
+ kv: { dev: "redis", test: "memory", prod: "redis" },
34
+ },
35
+ },
36
+ });
37
+ ```
38
+
39
+ </Step>
40
+
41
+ <Step>
42
+ ### Drop mode and use the new commands
43
+
44
+ ```bash title="Terminal"
45
+ rm -f .oke/mode # no longer read
46
+ oke dev # always Docker Compose
47
+ oke test # PGLite test posture (no Compose)
48
+ ```
49
+
50
+ `oke mode` prints an error and exits — it was removed.
51
+
52
+ </Step>
53
+
54
+ </Steps>
55
+
56
+ ## Key rename table
57
+
58
+ | Old key | New key | Notes |
59
+ | -------- | ------- | ------------------------------------------------ |
60
+ | `local` | `dev` | Compose laptop |
61
+ | `docker` | `dev` | Same Compose / prod-shaped protocols |
62
+ | `stack` | `dev` | Legacy alias |
63
+ | `test` | `test` | Unchanged; SQL must be `pglite` |
64
+ | `prod` | `prod` | Unchanged; missing `dev` still fills from `prod` |
65
+
66
+ ## sqlite / libsql removal
67
+
68
+ | Old pin | Replacement |
69
+ | --------------------------------- | --------------------------------------------- |
70
+ | `sql.*: "sqlite"` / `"libsql"` | `dev` / `prod`: `postgres` |
71
+ | `sql.test: "sqlite"` / `"libsql"` | `test: "pglite"` |
72
+ | `sql.test: "memory"` | `test: "pglite"` (required by `defineConfig`) |
73
+ | `index.*: "libsql"` | `dev` / `prod`: `pgvector`; `test`: `memory` |
74
+
75
+ `OKE_SQLITE_URL` / `OKE_LIBSQL_URL` are unused — use `DATABASE_URL` (Compose Postgres) or
76
+ `OKE_PGLITE_URL` (`memory://` under `oke test`).
77
+
78
+ ## Before / after
79
+
80
+ ```typescript title="Before (removed)"
81
+ drivers: {
82
+ store: {
83
+ sql: { local: "sqlite", docker: "postgres", test: "memory", prod: "postgres" },
84
+ kv: { local: "memory", docker: "redis", test: "memory", prod: "redis" },
85
+ },
86
+ },
87
+ ```
88
+
89
+ ```typescript title="After"
90
+ drivers: {
91
+ store: {
92
+ sql: { dev: "postgres", test: "pglite", prod: "postgres" },
93
+ kv: { dev: "redis", test: "memory", prod: "redis" },
94
+ },
95
+ },
96
+ ```
97
+
98
+ ## CLI changes
99
+
100
+ | Old | New |
101
+ | ------------------------- | ----------------------------------------------- |
102
+ | `oke mode local\|docker` | Removed — error message points at `oke dev` |
103
+ | `oke dev --local` / `-l` | Removed — exits with guidance to use `oke test` |
104
+ | `oke dev` (local default) | Always Docker Compose |
105
+ | `oke dev --docker` / `-d` | Optional **role filter** only (still Compose) |
106
+ | — | `oke test` — `bun test` + PGLite posture |
107
+
108
+ Loading `oke.config.ts` with a `local:` env key or a `"sqlite"` pin fails immediately:
109
+
110
+ ```text
111
+ Error: "local" is no longer a valid environment key in oke.config.ts.
112
+ ```
113
+
114
+ ```text
115
+ Error: "sqlite" is no longer a valid driver in oke.config.ts.
116
+ ```
117
+
118
+ ## Troubleshooting
119
+
120
+ <Accordions>
121
+
122
+ <Accordion title='CLI says "local" / "sqlite" is no longer valid'>
123
+ Edit `oke.config.ts` using the tables above. There is no automatic rewrite — fix the file, then
124
+ re-run the command.
125
+ </Accordion>
126
+
127
+ <Accordion title="defineConfig throws on sqlite, libsql, or non-pglite test SQL">
128
+ Those pins are hard errors. Fix the map, then restart `oke dev` / `oke test`. Exact messages are
129
+ documented under [Configuration · Safety](/docs/reference/configuration#safety-rules).
130
+ </Accordion>
131
+
132
+ </Accordions>
133
+
134
+ ## Learn more
135
+
136
+ - [Configuration](/docs/reference/configuration) — full `oke.config.ts` reference
137
+ - [CLI Reference](/docs/reference/cli) — `oke dev` · `oke test`
138
+ - [Installation](/docs/get-started/installation) — Docker-first quick start
139
+
140
+ ## Next
141
+
142
+ <Cards>
143
+ <Card
144
+ title="Configuration"
145
+ description="Drivers, images, db, ports."
146
+ href="/docs/reference/configuration"
147
+ />
148
+ <Card
149
+ title="CLI Reference"
150
+ description="oke and create-oke commands."
151
+ href="/docs/reference/cli"
152
+ />
153
+ <Card
154
+ title="Docker deployment"
155
+ description="Production compose shape."
156
+ href="/docs/deployment/docker"
157
+ />
158
+ </Cards>
@@ -54,7 +54,7 @@ export const app = oke({ name: "shop", env: "dev" }).plug(audit);
54
54
  <Step>
55
55
  ### Everything derives as usual
56
56
 
57
- Plugin flows appear in the Manifest, plugin tables land in `schema.generated.ts` on the next `oke db push`, plugin panels show up in the Console. No extra wiring — a contribution is ordinary OKE, just authored elsewhere.
57
+ Plugin flows appear in the Manifest, plugin tables land in `schema.drizzle.ts` on the next `oke db push`, plugin panels show up in the Console. No extra wiring — a contribution is ordinary OKE, just authored elsewhere.
58
58
 
59
59
  </Step>
60
60
 
@@ -225,7 +225,7 @@ Extending an existing **app-owned** table with plugin columns is not supported i
225
225
  two configurations of one plugin would silently diverge. Pass identical config, or rename one
226
226
  instance.
227
227
  </Accordion>
228
- <Accordion title="My plugin table is missing from schema.generated.ts">
228
+ <Accordion title="My plugin table is missing from schema.drizzle.ts">
229
229
  The CLI reads table contributions from the live app entry. Make sure the plugin is actually
230
230
  `.plug()`ed in `src/app.ts` (or `db.entry` if overridden), then re-run `oke db push`.
231
231
  </Accordion>
@@ -11,7 +11,7 @@ import { resolveAuthSchema } from "./schema.ts";
11
11
  import { emitSchemaSource, runSchemaGenerate } from "../cli/schema.ts";
12
12
  import { isSessionFresh, AUTH_SESSION_GATE } from "./bindings.ts";
13
13
  import { resolveGateAuth } from "./config.ts";
14
- import { mkdir, mkdtemp, rm } from "node:fs/promises";
14
+ import { mkdtemp, rm } from "node:fs/promises";
15
15
  import { tmpdir } from "node:os";
16
16
  import { join } from "node:path";
17
17
 
@@ -60,8 +60,8 @@ describe("gate.auth — config", () => {
60
60
 
61
61
  describe("gate.auth — autoBoot / posture", () => {
62
62
  test("auth HTTP bindings are in adopted and fail posture without gates", async () => {
63
- // Force a gap by constructing bindings then auditing with empty gates stripped —
64
- // real materialization always attaches gate.public / auth.session.
63
+ // Auth HTTP Bindings materialize lazily in doBoot (keeps auth/zod off the
64
+ // cold graph for public-gate apps). Boot first, then inspect adopted.
65
65
  const app = oke({
66
66
  name: "auth-posture",
67
67
  env: "test",
@@ -74,6 +74,7 @@ describe("gate.auth — autoBoot / posture", () => {
74
74
  unguardedHttp: "deny",
75
75
  },
76
76
  });
77
+ await app.boot({ env: "test" });
77
78
  const authPaths = app.bindings
78
79
  .filter((b) => b.trigger.kind === "http")
79
80
  .map(
@@ -87,14 +88,13 @@ describe("gate.auth — autoBoot / posture", () => {
87
88
  if (b.trigger.kind !== "http") continue;
88
89
  expect((b.trigger as { gates: readonly unknown[] }).gates.length).toBeGreaterThan(0);
89
90
  }
90
- await app.boot({ env: "test" });
91
91
  await app.stop();
92
92
  });
93
93
 
94
94
  test("bare oke gate.auth fetch goes through ensureBoot → doBoot", async () => {
95
95
  const app = oke({
96
96
  name: "auth-autoboot",
97
- env: "local",
97
+ env: "test",
98
98
  registry: "ignore",
99
99
  gate: {
100
100
  auth: {
@@ -118,10 +118,10 @@ describe("gate.auth — autoBoot / posture", () => {
118
118
  await app.stop();
119
119
  });
120
120
 
121
- test("auth routes are not registry flows[] alone — they are Bindings", () => {
121
+ test("auth routes are not registry flows[] alone — they are Bindings", async () => {
122
122
  const app = oke({
123
123
  name: "auth-bindings",
124
- env: "local",
124
+ env: "test",
125
125
  registry: "ignore",
126
126
  gate: {
127
127
  auth: {
@@ -130,9 +130,11 @@ describe("gate.auth — autoBoot / posture", () => {
130
130
  },
131
131
  },
132
132
  });
133
+ await app.boot({ env: "test" });
133
134
  expect(app.bindings.length).toBeGreaterThan(0);
134
135
  expect(app.bindings.every((b) => b.flow && b.trigger)).toBe(true);
135
136
  expect(app.router.match("POST", "/auth/sign-in/email")).toBeTruthy();
137
+ await app.stop();
136
138
  });
137
139
 
138
140
  test(".needs(auth) satisfied by gate.auth without .plug(auth())", async () => {
@@ -312,14 +314,14 @@ describe("gate.auth — email Flows + security", () => {
312
314
  on(http.get("/open"), flow("open", { do: () => ({ ok: true }) }));
313
315
  const app = oke({
314
316
  name: "gap",
315
- env: "local",
317
+ env: "test",
316
318
  gate: {
317
319
  auth: { secret: "test-secret-at-least-16", http: false },
318
320
  unguardedHttp: "deny",
319
321
  },
320
322
  startScheduler: false,
321
323
  });
322
- await expect(app.boot({ env: "local", startScheduler: false })).rejects.toBeInstanceOf(
324
+ await expect(app.boot({ env: "test", startScheduler: false })).rejects.toBeInstanceOf(
323
325
  GateBootError,
324
326
  );
325
327
  });
@@ -341,7 +343,6 @@ describe("oke schema generate — auth columns", () => {
341
343
 
342
344
  const dir = await mkdtemp(join(tmpdir(), "oke-schema-"));
343
345
  try {
344
- await mkdir(join(dir, "schema"), { recursive: true });
345
346
  const code = await runSchemaGenerate({
346
347
  cwd: dir,
347
348
  authSchema: {
@@ -353,6 +354,7 @@ describe("oke schema generate — auth columns", () => {
353
354
  write: () => {},
354
355
  });
355
356
  expect(code).toBe(0);
357
+ expect(await Bun.file(join(dir, ".oke/schema/oke.ts")).exists()).toBe(true);
356
358
  const checkOk = await runSchemaGenerate({
357
359
  cwd: dir,
358
360
  check: true,
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
6
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6
+ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
7
7
  import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
9
  import { applyAiSetup, renderAiTs, upsertAiDrivers, upsertEnv } from "./apply.ts";
@@ -48,8 +48,7 @@ describe("apply", () => {
48
48
  drivers: {
49
49
  channel: {
50
50
  email: {
51
- local: "console",
52
- docker: "smtp",
51
+ dev: "smtp",
53
52
  test: "console",
54
53
  prod: "smtp",
55
54
  },
@@ -65,7 +64,11 @@ describe("apply", () => {
65
64
  const config = new Function("defineConfig", body)(<T>(c: T): T => c) as {
66
65
  drivers?: { ai?: unknown; channel?: { ai?: unknown; email?: unknown } };
67
66
  };
68
- expect(config.drivers?.ai).toMatchObject({ local: "ollama", docker: "ollama" });
67
+ expect(config.drivers?.ai).toMatchObject({
68
+ dev: "ollama",
69
+ test: "mock",
70
+ prod: "ollama",
71
+ });
69
72
  expect(config.drivers?.channel?.ai).toBeUndefined();
70
73
  expect(config.drivers?.channel?.email).toBeDefined();
71
74
  });
@@ -99,7 +102,7 @@ describe("apply", () => {
99
102
  expect(ts).toContain("docsEmbed");
100
103
  });
101
104
 
102
- test("applyAiSetup writes config, env, core/ai.ts", () => {
105
+ test("applyAiSetup writes config, env, AI models in core.ts", () => {
103
106
  const dir = mkdtempSync(join(tmpdir(), "oke-ai-setup-"));
104
107
  try {
105
108
  writeFileSync(
@@ -109,22 +112,32 @@ export default defineConfig({
109
112
  drivers: {
110
113
  channel: {
111
114
  email: {
112
- local: "console",
113
- docker: "smtp",
115
+ dev: "smtp",
114
116
  test: "console",
115
117
  prod: "smtp",
116
118
  },
117
119
  },
118
120
  },
119
121
  images: {
120
- "store.sql": "postgres:18-alpine",
122
+ store: {
123
+ sql: "postgres:18-alpine",
124
+ },
121
125
  },
122
126
  });
123
127
  `,
124
128
  "utf8",
125
129
  );
126
130
  mkdirSync(join(dir, "src"), { recursive: true });
127
- writeFileSync(join(dir, "src", "app.ts"), `export const app = {};\n`, "utf8");
131
+ writeFileSync(
132
+ join(dir, "src", "core.ts"),
133
+ `import { store } from "okengine";\n\nexport const db = store.sql("app");\n`,
134
+ "utf8",
135
+ );
136
+ writeFileSync(
137
+ join(dir, "src", "app.ts"),
138
+ `import "@/core";\nexport const app = {};\n`,
139
+ "utf8",
140
+ );
128
141
 
129
142
  applyAiSetup(dir, {
130
143
  driver: "ollama",
@@ -135,18 +148,19 @@ export default defineConfig({
135
148
  });
136
149
 
137
150
  const config = readFileSync(join(dir, "oke.config.ts"), "utf8");
138
- expect(config).toContain('local: "ollama"');
151
+ expect(config).toContain('dev: "ollama"');
139
152
  expect(config).toContain('ai: "ollama/ollama:0.32.6"');
140
153
  const env = readFileSync(join(dir, ".env.local"), "utf8");
141
154
  expect(env).toContain("# OKE_AI_DRIVER=ollama");
142
- expect(env).toMatch(/^OKE_AI_MODEL=gemma4:e4b$/m);
143
- expect(env).not.toMatch(/^#\s*OKE_AI_MODEL=gemma4:e4b$/m);
155
+ expect(env).toMatch(/^#\s*OKE_AI_MODEL=gemma4:e4b$/m);
156
+ expect(env).not.toMatch(/^OKE_AI_MODEL=/m);
144
157
  expect(env).toContain("# OKE_AI_URL=http://127.0.0.1:11434");
145
158
  expect(env).not.toMatch(/^OKE_AI_URL=/m);
146
- const aiTs = readFileSync(join(dir, "src", "core", "ai.ts"), "utf8");
147
- expect(aiTs).toContain("smart");
148
- const app = readFileSync(join(dir, "src", "app.ts"), "utf8");
149
- expect(app).toContain('import "./core/ai"');
159
+ const core = readFileSync(join(dir, "src", "core.ts"), "utf8");
160
+ expect(core).toContain('import { ai, store } from "okengine"');
161
+ expect(core).toContain("smart");
162
+ expect(core).toContain('ai.model("vision"');
163
+ expect(existsSync(join(dir, "src", "core", "ai.ts"))).toBe(false);
150
164
  } finally {
151
165
  rmSync(dir, { recursive: true, force: true });
152
166
  }