okengine 0.10.3 → 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 (318) hide show
  1. package/package.json +76 -10
  2. package/site/content/docs/deployment/docker-swarm.mdx +48 -111
  3. package/site/content/docs/deployment/docker.mdx +43 -36
  4. package/site/content/docs/deployment/index.mdx +9 -9
  5. package/site/content/docs/deployment/kubernetes.mdx +4 -4
  6. package/site/content/docs/elements/ai.mdx +7 -7
  7. package/site/content/docs/elements/channel.mdx +9 -7
  8. package/site/content/docs/elements/clock.mdx +8 -8
  9. package/site/content/docs/elements/flow.mdx +46 -47
  10. package/site/content/docs/elements/gate.mdx +6 -5
  11. package/site/content/docs/elements/signal.mdx +2 -2
  12. package/site/content/docs/elements/store.mdx +71 -78
  13. package/site/content/docs/elements/vault.mdx +89 -70
  14. package/site/content/docs/get-started/basic-usage.mdx +8 -8
  15. package/site/content/docs/get-started/installation.mdx +36 -36
  16. package/site/content/docs/get-started/introduction.mdx +11 -0
  17. package/site/content/docs/get-started/why.mdx +2 -2
  18. package/site/content/docs/plugins/anonymous.mdx +1 -1
  19. package/site/content/docs/plugins/magic-link.mdx +11 -11
  20. package/site/content/docs/plugins/otp.mdx +2 -2
  21. package/site/content/docs/plugins/passkey.mdx +1 -1
  22. package/site/content/docs/plugins/two-factor.mdx +1 -1
  23. package/site/content/docs/plugins/username.mdx +1 -1
  24. package/site/content/docs/recipes/caddy.mdx +1 -1
  25. package/site/content/docs/recipes/cockroachdb.mdx +2 -2
  26. package/site/content/docs/recipes/dragonfly.mdx +1 -1
  27. package/site/content/docs/recipes/index.mdx +1 -2
  28. package/site/content/docs/recipes/llama-cpp.mdx +21 -23
  29. package/site/content/docs/recipes/mailpit.mdx +11 -11
  30. package/site/content/docs/recipes/meilisearch.mdx +10 -10
  31. package/site/content/docs/recipes/meta.json +0 -1
  32. package/site/content/docs/recipes/ollama.mdx +1 -1
  33. package/site/content/docs/recipes/pgdog.mdx +12 -9
  34. package/site/content/docs/recipes/postgres.mdx +3 -3
  35. package/site/content/docs/recipes/redis.mdx +2 -2
  36. package/site/content/docs/recipes/rustfs.mdx +10 -7
  37. package/site/content/docs/recipes/sglang.mdx +1 -1
  38. package/site/content/docs/recipes/supabase-docker.mdx +1 -1
  39. package/site/content/docs/recipes/timescale.mdx +2 -2
  40. package/site/content/docs/recipes/valkey.mdx +1 -1
  41. package/site/content/docs/recipes/vllm.mdx +1 -1
  42. package/site/content/docs/recipes/yugabytedb.mdx +2 -2
  43. package/site/content/docs/reference/cli.md +61 -38
  44. package/site/content/docs/reference/configuration.mdx +145 -70
  45. package/site/content/docs/reference/environment-variables.mdx +36 -28
  46. package/site/content/docs/reference/errors.mdx +28 -29
  47. package/site/content/docs/reference/fx.mdx +11 -4
  48. package/site/content/docs/reference/i18n.mdx +17 -6
  49. package/site/content/docs/reference/index.mdx +5 -0
  50. package/site/content/docs/reference/meta.json +1 -0
  51. package/site/content/docs/reference/migrating-environments.mdx +158 -0
  52. package/site/content/docs/reference/plugins.mdx +2 -2
  53. package/src/auth/gate-auth.test.ts +12 -10
  54. package/src/cli/ai-setup/ai-setup.test.ts +27 -15
  55. package/src/cli/ai-setup/apply.ts +111 -15
  56. package/src/cli/ai-setup/catalog.ts +3 -3
  57. package/src/cli/ai-setup/index.ts +1 -1
  58. package/src/cli/ai-setup/prompts.ts +1 -1
  59. package/src/cli/ai-setup/recommend.test.ts +1 -1
  60. package/src/cli/ask-seed.test.ts +3 -3
  61. package/src/cli/build.ts +1 -1
  62. package/src/cli/db-auto-push.test.ts +6 -3
  63. package/src/cli/db-auto-push.ts +7 -5
  64. package/src/cli/db-seed.ts +7 -8
  65. package/src/cli/db.test.ts +70 -71
  66. package/src/cli/db.ts +86 -12
  67. package/src/cli/dev-controller.test.ts +35 -0
  68. package/src/cli/dev-controller.ts +298 -0
  69. package/src/cli/dev-controls.ts +11 -65
  70. package/src/cli/dev-db-push.test.ts +47 -15
  71. package/src/cli/dev-schema-sync.test.ts +11 -11
  72. package/src/cli/dev-schema-sync.ts +10 -10
  73. package/src/cli/dev-session-lock.test.ts +106 -0
  74. package/src/cli/dev-session-lock.ts +209 -0
  75. package/src/cli/dev.test.ts +166 -121
  76. package/src/cli/dev.ts +138 -192
  77. package/src/cli/doc-staleness.test.ts +3 -6
  78. package/src/cli/docker-clean.test.ts +33 -1
  79. package/src/cli/docker-clean.ts +28 -33
  80. package/src/cli/docker-cli.test.ts +12 -11
  81. package/src/cli/docker.ts +95 -20
  82. package/src/cli/doctor.test.ts +40 -0
  83. package/src/cli/doctor.ts +55 -15
  84. package/src/cli/drizzle-env.test.ts +11 -13
  85. package/src/cli/drizzle-env.ts +18 -11
  86. package/src/cli/ensure-drizzle-config.ts +11 -14
  87. package/src/cli/hero-meta.test.ts +15 -15
  88. package/src/cli/hero-meta.ts +10 -9
  89. package/src/cli/index.ts +36 -6
  90. package/src/cli/load-config.images.test.ts +16 -12
  91. package/src/cli/load-config.source.test.ts +50 -0
  92. package/src/cli/load-config.ts +34 -28
  93. package/src/cli/meilisearch-local.ts +1 -2
  94. package/src/cli/mode.ts +7 -58
  95. package/src/cli/registry.ts +175 -19
  96. package/src/cli/resolve-dev-sql-env.test.ts +8 -16
  97. package/src/cli/resolve-dev-sql-env.ts +13 -15
  98. package/src/cli/safe-defaults.test.ts +28 -10
  99. package/src/cli/schema.ts +65 -16
  100. package/src/cli/test.ts +58 -0
  101. package/src/cli/tui/App.tsx +252 -0
  102. package/src/cli/tui/DevLive.tsx +116 -0
  103. package/src/cli/tui/components/ConfirmDialog.tsx +48 -0
  104. package/src/cli/tui/components/HeaderBar.tsx +67 -0
  105. package/src/cli/tui/components/LogStream.tsx +47 -0
  106. package/src/cli/tui/components/PanelCard.tsx +39 -0
  107. package/src/cli/tui/components/SelectRow.tsx +37 -0
  108. package/src/cli/tui/components/SlashPalette.tsx +172 -0
  109. package/src/cli/tui/components/Spinner.tsx +32 -0
  110. package/src/cli/tui/components/StatusBar.tsx +51 -0
  111. package/src/cli/tui/components/StatusDot.tsx +37 -0
  112. package/src/cli/tui/components/TabBar.tsx +49 -0
  113. package/src/cli/tui/components/Wordmark.tsx +43 -0
  114. package/src/cli/tui/format.ts +38 -0
  115. package/src/cli/tui/keys.test.ts +18 -0
  116. package/src/cli/tui/keys.ts +26 -0
  117. package/src/cli/tui/launch.test.ts +18 -0
  118. package/src/cli/tui/launch.ts +57 -0
  119. package/src/cli/tui/panels/Dashboard.tsx +201 -0
  120. package/src/cli/tui/panels/Database.tsx +198 -0
  121. package/src/cli/tui/panels/Dev.tsx +257 -0
  122. package/src/cli/tui/panels/Docker.tsx +357 -0
  123. package/src/cli/tui/panels/Navigator.test.ts +22 -0
  124. package/src/cli/tui/panels/Navigator.tsx +213 -0
  125. package/src/cli/tui/slash-catalog.test.ts +31 -0
  126. package/src/cli/tui/slash-catalog.ts +184 -0
  127. package/src/cli/tui/slash-run.ts +54 -0
  128. package/src/cli/tui/state/ports.ts +95 -0
  129. package/src/cli/tui/theme.ts +24 -0
  130. package/src/cli/vault-cmd.test.ts +402 -0
  131. package/src/cli/vault-cmd.ts +727 -69
  132. package/src/cli/vault-secure-input.test.ts +56 -0
  133. package/src/cli/vault-secure-input.ts +124 -0
  134. package/src/compiler/effects-infer.ts +7 -0
  135. package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
  136. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -1
  137. package/src/compiler/fixtures/skyport.expected.json +1 -1
  138. package/src/compiler-entry.ts +7 -0
  139. package/src/config/define-config.test.ts +111 -47
  140. package/src/config/driver-defaults.test.ts +16 -23
  141. package/src/config/driver-defaults.ts +33 -63
  142. package/src/config/index.ts +169 -144
  143. package/src/config/resolve-driver.test.ts +14 -19
  144. package/src/console/server/app.ts +4 -2
  145. package/src/console/server/console.test.ts +58 -1
  146. package/src/console/server/flows.ts +22 -2
  147. package/src/console/server/index.ts +3 -0
  148. package/src/console/server/operator-db.test.ts +55 -13
  149. package/src/console/server/operator-db.ts +305 -263
  150. package/src/console/server/serve.ts +16 -7
  151. package/src/console/server/state.ts +31 -9
  152. package/src/console/server/vault.test.ts +120 -5
  153. package/src/console/server/vault.ts +208 -12
  154. package/src/console/ui/dist/assets/{index-D-9KFce5.js → index--Y0Uaz-m.js} +2 -2
  155. package/src/console/ui/dist/assets/panel-vault-BkZdJPX8.js +1 -0
  156. package/src/console/ui/dist/assets/style-C3L349iZ.css +3 -0
  157. package/src/console/ui/dist/index.html +2 -2
  158. package/src/console/ui/shell/client.ts +16 -0
  159. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +54 -1
  160. package/src/console/ui/vault/VaultA11yView.tsx +33 -1
  161. package/src/console/ui/vault/backend.test.ts +75 -0
  162. package/src/console/ui/vault/backend.ts +117 -0
  163. package/src/console/ui/vault/fixture.ts +21 -2
  164. package/src/console/ui/vault/index.ts +11 -1
  165. package/src/console/ui/vault/types.ts +26 -0
  166. package/src/docker/compose.ts +164 -61
  167. package/src/docker/derive.ts +106 -12
  168. package/src/docker/docker.test.ts +156 -110
  169. package/src/docker/helpers.ts +98 -0
  170. package/src/docker/images-config.test.ts +3 -8
  171. package/src/docker/index.ts +30 -5
  172. package/src/docker/recipes/index.ts +0 -3
  173. package/src/docker/recipes/llama-cpp.ts +4 -4
  174. package/src/docker/recipes/pgdog.ts +9 -2
  175. package/src/docker/resources.test.ts +71 -0
  176. package/src/docker/resources.ts +176 -0
  177. package/src/docker/stack-id.test.ts +11 -4
  178. package/src/docker/stack-id.ts +42 -32
  179. package/src/docker/stack.integration.test.ts +4 -15
  180. package/src/docker/types.ts +35 -3
  181. package/src/drivers/ai-ollama.integration.test.ts +2 -2
  182. package/src/drivers/conformance.test.ts +11 -12
  183. package/src/drivers/drizzle-dialect.test.ts +0 -4
  184. package/src/drivers/drizzle-dialect.ts +7 -13
  185. package/src/drivers/index.ts +24 -7
  186. package/src/drivers/journal-postgres.test.ts +3 -1
  187. package/src/drivers/journal-postgres.ts +4 -2
  188. package/src/drivers/meilisearch.ts +1 -1
  189. package/src/drivers/pglite.ts +28 -5
  190. package/src/drivers/types.ts +9 -11
  191. package/src/drivers/vault-aws-secrets-manager.test.ts +159 -0
  192. package/src/drivers/vault-aws-secrets-manager.ts +333 -0
  193. package/src/drivers/vault-builtin.test.ts +110 -0
  194. package/src/drivers/vault-builtin.ts +184 -0
  195. package/src/drivers/vault-driver-removal.test.ts +13 -0
  196. package/src/drivers/vault-managed.test.ts +95 -0
  197. package/src/drivers/vault-managed.ts +101 -25
  198. package/src/drivers/vault-types.ts +25 -5
  199. package/src/elements/ai/runtime.ts +1 -1
  200. package/src/elements/clock/chaos.test.ts +4 -1
  201. package/src/elements/clock/durable.ts +57 -4
  202. package/src/elements/clock.test.ts +13 -14
  203. package/src/elements/gate/constants.ts +18 -0
  204. package/src/elements/gate.test.ts +1 -1
  205. package/src/elements/gate.ts +2 -2
  206. package/src/elements/store/domain-ddl.test.ts +5 -12
  207. package/src/elements/store/emit-drizzle.ts +44 -19
  208. package/src/elements/store/index-boot.test.ts +15 -116
  209. package/src/elements/store/load-plugin-tables.ts +1 -1
  210. package/src/elements/store/resource-list-docs.fixture.ts +12 -6
  211. package/src/elements/store/resource-list-docs.test.ts +64 -44
  212. package/src/elements/store/resource.test.ts +17 -10
  213. package/src/elements/store/runtime.ts +9 -12
  214. package/src/elements/store/schema-decl.test.ts +16 -32
  215. package/src/elements/store/seed.test.ts +1 -2
  216. package/src/elements/store/seed.ts +7 -8
  217. package/src/elements/store/sql-condition.test.ts +2 -2
  218. package/src/elements/store/sql-session.test.ts +8 -10
  219. package/src/elements/store/sql-session.ts +10 -2
  220. package/src/elements/store.test.ts +13 -13
  221. package/src/elements/vault/audit.ts +233 -0
  222. package/src/elements/vault/boot-chain.test.ts +78 -0
  223. package/src/elements/vault/boot-chain.ts +43 -39
  224. package/src/elements/vault/builtin-adapter.test.ts +479 -0
  225. package/src/elements/vault/builtin-adapter.ts +1184 -0
  226. package/src/elements/vault/crypto.test.ts +237 -0
  227. package/src/elements/vault/crypto.ts +431 -0
  228. package/src/elements/vault/declare.ts +164 -3
  229. package/src/elements/vault/errors.ts +56 -0
  230. package/src/elements/vault/kms-unseal.test.ts +76 -0
  231. package/src/elements/vault/kms-unseal.ts +181 -0
  232. package/src/elements/vault/path.ts +90 -0
  233. package/src/elements/vault/resilience.test.ts +102 -0
  234. package/src/elements/vault/resilience.ts +107 -0
  235. package/src/elements/vault/runtime.ts +36 -4
  236. package/src/elements/vault/security-checklist.test.ts +130 -0
  237. package/src/elements/vault/storage.ts +448 -0
  238. package/src/elements/vault/types.ts +288 -0
  239. package/src/elements/vault/unseal.ts +150 -0
  240. package/src/elements/vault.test.ts +72 -4
  241. package/src/elements/vault.ts +91 -2
  242. package/src/full.ts +248 -0
  243. package/src/http.ts +41 -0
  244. package/src/i18n/interpolate-simple.ts +37 -0
  245. package/src/i18n/messages.ts +51 -4
  246. package/src/i18n-entry.ts +7 -0
  247. package/src/index.ts +35 -145
  248. package/src/journal-entry.ts +20 -0
  249. package/src/kernel/adopt-barrel-fresh.test.ts +25 -10
  250. package/src/kernel/app.ts +40 -42
  251. package/src/kernel/auto-registry.test.ts +2 -2
  252. package/src/kernel/boot-bind/ai.test.ts +5 -5
  253. package/src/kernel/boot-bind/ai.ts +2 -1
  254. package/src/kernel/boot-bind/channel.test.ts +6 -6
  255. package/src/kernel/boot-bind/channel.ts +3 -10
  256. package/src/kernel/boot-bind/clock.ts +2 -2
  257. package/src/kernel/boot-bind/gate.ts +5 -9
  258. package/src/kernel/boot-bind/honor-config.test.ts +42 -42
  259. package/src/kernel/boot-bind/journal.ts +2 -2
  260. package/src/kernel/boot-bind/store.test.ts +43 -44
  261. package/src/kernel/boot-bind/store.ts +16 -41
  262. package/src/kernel/boot-bind/vault.ts +16 -1
  263. package/src/kernel/boot.test.ts +12 -4
  264. package/src/kernel/boot.ts +31 -19
  265. package/src/kernel/budget-entry.ts +1 -1
  266. package/src/kernel/compensate.test.ts +288 -1
  267. package/src/kernel/compensate.ts +126 -0
  268. package/src/kernel/concurrency.test.ts +10 -9
  269. package/src/kernel/effects-stamping.test.ts +27 -2
  270. package/src/kernel/element-registries.ts +5 -3
  271. package/src/kernel/flow.ts +4 -2
  272. package/src/kernel/fx.test.ts +119 -3
  273. package/src/kernel/fx.ts +215 -40
  274. package/src/kernel/index.ts +14 -0
  275. package/src/kernel/journal.ts +130 -7
  276. package/src/kernel/pipeline.test.ts +20 -6
  277. package/src/kernel/redacted.test.ts +35 -0
  278. package/src/kernel/redacted.ts +24 -2
  279. package/src/kernel/router/create-default.ts +16 -0
  280. package/src/kernel/router/create-edge.ts +18 -0
  281. package/src/kernel/router/create.ts +23 -0
  282. package/src/kernel/router/index.ts +23 -0
  283. package/src/kernel/router/linear.ts +88 -0
  284. package/src/kernel/router/regexp.ts +188 -0
  285. package/src/kernel/router/smart.ts +120 -0
  286. package/src/kernel/router/trie.ts +108 -0
  287. package/src/kernel/router/types.ts +56 -0
  288. package/src/kernel/router.ts +18 -532
  289. package/src/kernel-entry.ts +43 -0
  290. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  291. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  292. package/src/plugins/config-source.test.ts +7 -7
  293. package/src/release/build-lib.ts +58 -0
  294. package/src/release/exports.test.ts +4 -2
  295. package/src/release/exports.ts +30 -4
  296. package/src/release/measure.ts +101 -22
  297. package/src/runs/duckdb.ts +7 -2
  298. package/src/shared/optional-peer.ts +41 -0
  299. package/src/term.test.ts +3 -44
  300. package/src/test/create-test-app.ts +12 -0
  301. package/src/test/provisions.integration.test.ts +1 -1
  302. package/src/test/reset-element-registries.ts +2 -0
  303. package/src/upgrade/codemods.test.ts +7 -20
  304. package/src/upgrade/codemods.ts +93 -60
  305. package/site/content/docs/recipes/openbao.mdx +0 -141
  306. package/src/cli/ask-dev-mode.ts +0 -40
  307. package/src/cli/dev-mode.test.ts +0 -45
  308. package/src/cli/dev-mode.ts +0 -78
  309. package/src/cli/openbao-bootstrap.test.ts +0 -150
  310. package/src/cli/openbao-bootstrap.ts +0 -321
  311. package/src/cli/openbao-restart.integration.test.ts +0 -145
  312. package/src/console/ui/dist/assets/panel-vault-Za1GyJfM.js +0 -1
  313. package/src/console/ui/dist/assets/style-C8MxEWPd.css +0 -3
  314. package/src/docker/recipes/openbao.ts +0 -47
  315. package/src/drivers/libsql.ts +0 -179
  316. package/src/drivers/sqlite.ts +0 -44
  317. package/src/drivers/vault-openbao.test.ts +0 -97
  318. package/src/drivers/vault-openbao.ts +0 -143
@@ -24,18 +24,24 @@ import {
24
24
  type SchemaTableDecl,
25
25
  } from "./schema-decl.ts";
26
26
 
27
- /** Supported Drizzle dialects for domain schema emit. */
28
- export type SqlDialect = "sqlite" | "postgres";
27
+ /** Supported Drizzle dialects for domain schema emit (Postgres-family only). */
28
+ export type SqlDialect = "postgres";
29
29
 
30
30
  /** Header written at the top of generated files. */
31
31
  export const GENERATED_SCHEMA_HEADER = "// generated by oke — do not edit";
32
32
 
33
33
  /** Default output path (relative to project root). */
34
- export const DEFAULT_GENERATED_SCHEMA_REL = "src/db/schema.generated.ts";
34
+ export const DEFAULT_GENERATED_SCHEMA_REL = "src/db/schema.drizzle.ts";
35
35
 
36
36
  /** Default declaration module path (relative to project root). */
37
37
  export const DEFAULT_DECLARE_SCHEMA_REL = "src/db/schema.decl.ts";
38
38
 
39
+ /**
40
+ * Prior `src/db/` emit filename — still resolved when present and the new
41
+ * default does not exist yet.
42
+ */
43
+ export const PREV_GENERATED_SCHEMA_REL = "src/db/schema.generated.ts";
44
+
39
45
  /** Legacy paths kept so pre-layout projects keep resolving. */
40
46
  export const LEGACY_GENERATED_SCHEMA_REL = "src/schema.generated.ts";
41
47
 
@@ -45,11 +51,15 @@ export const LEGACY_DECLARE_SCHEMA_REL = "src/schema.decl.ts";
45
51
  /**
46
52
  * Map a store.sql driver id to an emit dialect.
47
53
  *
48
- * @param driverId - Protocol driver id (`sqlite` · `postgres` · `memory` · …)
54
+ * @param driverId - Protocol driver id (`postgres` · `pglite` · …)
49
55
  */
50
56
  export function dialectFromDriverId(driverId: string | undefined): SqlDialect {
51
- if (driverId === "postgres") return "postgres";
52
- return "sqlite";
57
+ if (driverId === undefined || driverId === "postgres" || driverId === "pglite") {
58
+ return "postgres";
59
+ }
60
+ throw new Error(
61
+ `oke schema emit: store.sql driver "${driverId}" is not supported (postgres | pglite)`,
62
+ );
53
63
  }
54
64
 
55
65
  /**
@@ -58,9 +68,14 @@ export function dialectFromDriverId(driverId: string | undefined): SqlDialect {
58
68
  * @param col - Column decl
59
69
  * @param dialect - Target dialect (affects import names only at file level)
60
70
  */
61
- export function emitColumnSource(col: SchemaColumnDecl, _dialect: SqlDialect): string {
62
- const fn = col.sqlType === "integer" ? "integer" : "text";
63
- let expr = `${fn}(${JSON.stringify(col.sqlName)})`;
71
+ export function emitColumnSource(col: SchemaColumnDecl, _dialect: SqlDialect = "postgres"): string {
72
+ // Postgres INTEGER is 32-bit; abstract `integer` (often ms clocks) → bigint.
73
+ // drizzle-orm's `bigint()` requires `{ mode }` — omitting it throws on
74
+ // `config.mode` when the generated schema is loaded by drizzle-kit push.
75
+ let expr =
76
+ col.sqlType === "integer"
77
+ ? `bigint(${JSON.stringify(col.sqlName)}, { mode: "number" })`
78
+ : `text(${JSON.stringify(col.sqlName)})`;
64
79
  if (col.primaryKey) expr += ".primaryKey()";
65
80
  else if (col.notNull) expr += ".notNull()";
66
81
  if (col.unique) expr += ".unique()";
@@ -157,19 +172,20 @@ export interface EmitDrizzleSourceOptions {
157
172
  * Emit a full Drizzle schema module from abstract table decls.
158
173
  *
159
174
  * @param tables - App + plugin tables (already merged)
160
- * @param dialect - sqlite sqliteTable · postgres pgTable
175
+ * @param dialect - Always `postgres` (`pgTable`); retained for call-site clarity
161
176
  * @param options - Optional relations to emit as `defineRelations`
162
177
  */
163
178
  export function emitDrizzleSource(
164
179
  tables: readonly SchemaTableDecl[],
165
- dialect: SqlDialect,
180
+ dialect: SqlDialect = "postgres",
166
181
  options: EmitDrizzleSourceOptions = {},
167
182
  ): string {
168
- const tableFn = dialect === "postgres" ? "pgTable" : "sqliteTable";
169
- const coreImport =
170
- dialect === "postgres"
171
- ? `import { pgTable, text, integer } from "drizzle-orm/pg-core";`
172
- : `import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";`;
183
+ void dialect;
184
+ const needsInteger = tables.some((t) =>
185
+ Object.values(t.columns).some((c) => c.sqlType === "integer"),
186
+ );
187
+ const pgIntImport = needsInteger ? "bigint" : null;
188
+ const coreImport = `import { pgTable, text${pgIntImport ? `, ${pgIntImport}` : ""} } from "drizzle-orm/pg-core";`;
173
189
 
174
190
  const needsId = tables.some((t) =>
175
191
  Object.values(t.columns).some((c) => c.defaultFnKind === "id"),
@@ -191,7 +207,7 @@ export function emitDrizzleSource(
191
207
  const lines = Object.values(table.columns).map(
192
208
  (col) => ` ${col.key}: ${emitColumnSource(col, dialect)},`,
193
209
  );
194
- return `export const ${exportNameForTable(table.name)} = ${tableFn}(${JSON.stringify(table.name)}, {\n${lines.join("\n")}\n});`;
210
+ return `export const ${exportNameForTable(table.name)} = pgTable(${JSON.stringify(table.name)}, {\n${lines.join("\n")}\n});`;
195
211
  });
196
212
 
197
213
  const relationsBlock = emitRelationsSource(relations);
@@ -380,11 +396,20 @@ export function resolveEmitPaths(
380
396
 
381
397
  let outRel = db?.generated;
382
398
  if (!outRel) {
383
- const preferLegacy =
399
+ const preferSrcLegacy =
384
400
  declareRel === LEGACY_DECLARE_SCHEMA_REL ||
385
401
  (!existsSync(join(cwd, DEFAULT_DECLARE_SCHEMA_REL)) &&
386
402
  existsSync(join(cwd, LEGACY_GENERATED_SCHEMA_REL)));
387
- outRel = preferLegacy ? LEGACY_GENERATED_SCHEMA_REL : DEFAULT_GENERATED_SCHEMA_REL;
403
+ if (preferSrcLegacy) {
404
+ outRel = LEGACY_GENERATED_SCHEMA_REL;
405
+ } else if (
406
+ !existsSync(join(cwd, DEFAULT_GENERATED_SCHEMA_REL)) &&
407
+ existsSync(join(cwd, PREV_GENERATED_SCHEMA_REL))
408
+ ) {
409
+ outRel = PREV_GENERATED_SCHEMA_REL;
410
+ } else {
411
+ outRel = DEFAULT_GENERATED_SCHEMA_REL;
412
+ }
388
413
  }
389
414
 
390
415
  return {
@@ -1,43 +1,28 @@
1
1
  /**
2
2
  * End-to-end `store.index()` boot wiring — the CONFIGURED driver resolves at
3
- * real boot for every backend (memory / libsql / pgvector over pglite /
4
- * pgvector over real Postgres), SQL-backed indexes share store.sql's
5
- * already-open connection (never a second, redundant one), and search runs
6
- * through each engine's native ANN index — no JS-side full scan survives.
3
+ * real boot for every backend (memory / pgvector over pglite / pgvector over
4
+ * real Postgres), SQL-backed indexes share store.sql's already-open connection
5
+ * (never a second, redundant one), and search runs through each engine's
6
+ * native ANN index — no JS-side full scan survives.
7
7
  */
8
8
 
9
9
  import { afterEach, describe, expect, test } from "bun:test";
10
- import {
11
- connectLibsql,
12
- libsqlDriver,
13
- libsqlIndexDriver,
14
- openLibsqlIndex,
15
- } from "../../drivers/libsql.ts";
16
10
  import { connectPglite } from "../../drivers/pglite.ts";
17
11
  import { openPgvectorIndex } from "../../drivers/pgvector.ts";
18
12
  import { connectPostgres } from "../../drivers/postgres.ts";
19
- import type { SqlConnection, SqlDriver } from "../../drivers/types.ts";
13
+ import type { SqlConnection } from "../../drivers/types.ts";
20
14
  import { bindStore } from "../../kernel/boot-bind/store.ts";
21
- import {
22
- createStoreRuntime,
23
- index as declareIndex,
24
- sql as declareSql,
25
- type SqlStoreHandle,
26
- type VectorIndexStoreFxHandle,
27
- } from "../store.ts";
15
+ import { index as declareIndex, type VectorIndexStoreFxHandle } from "../store.ts";
28
16
 
29
17
  const WRITE_CTX = (name: string) => ({
30
18
  effects: { reads: [`index:${name}` as const], writes: [`index:${name}` as const] },
31
19
  });
32
20
 
33
21
  const prev = {
34
- libsql: process.env.OKE_LIBSQL_URL,
35
22
  pglite: process.env.OKE_PGLITE_URL,
36
23
  };
37
24
 
38
25
  afterEach(() => {
39
- if (prev.libsql === undefined) delete process.env.OKE_LIBSQL_URL;
40
- else process.env.OKE_LIBSQL_URL = prev.libsql;
41
26
  if (prev.pglite === undefined) delete process.env.OKE_PGLITE_URL;
42
27
  else process.env.OKE_PGLITE_URL = prev.pglite;
43
28
  });
@@ -66,7 +51,7 @@ function recordingConn(conn: SqlConnection): { conn: SqlConnection; statements:
66
51
  describe("store.index boot wiring — memory", () => {
67
52
  test("boot with no configured index driver resolves memory end to end", async () => {
68
53
  const kb = declareIndex("kb", { dims: 3 });
69
- const runtime = bindStore({ stores: [kb] }, "local", () => Date.now());
54
+ const runtime = bindStore({ stores: [kb] }, "test", () => Date.now());
70
55
  const handle = (await runtime.open(kb, WRITE_CTX("kb"))) as VectorIndexStoreFxHandle;
71
56
  expect(handle.driverId).toBe("memory");
72
57
  await handle.upsert("near", [1, 0, 0]);
@@ -77,88 +62,16 @@ describe("store.index boot wiring — memory", () => {
77
62
  });
78
63
  });
79
64
 
80
- describe("store.index boot wiring — libsql", () => {
81
- test("boot: sql=libsql + index=libsql resolves native ANN end to end", async () => {
82
- process.env.OKE_LIBSQL_URL = ":memory:";
83
- const kb = declareIndex("kb", { dims: 3 });
84
- const runtime = bindStore(
85
- {
86
- config: { drivers: { store: { sql: { local: "libsql" }, index: { local: "libsql" } } } },
87
- stores: [kb],
88
- },
89
- "local",
90
- () => Date.now(),
91
- );
92
- const handle = (await runtime.open(kb, WRITE_CTX("kb"))) as VectorIndexStoreFxHandle;
93
- expect(handle.driverId).toBe("libsql");
94
-
95
- await handle.upsert("near", [1, 0.1, 0], { label: "near" });
96
- await handle.upsert("far", [0, 1, 0]);
97
- await handle.upsert("farther", [-1, 0, 0]);
98
- const hits = await handle.search([1, 0, 0], 3);
99
- expect(hits.map((h: { id: string }) => h.id)).toEqual(["near", "far", "farther"]);
100
- expect(hits[0]!.score).toBeGreaterThan(hits[1]!.score);
101
- expect(hits[0]!.meta).toEqual({ label: "near" });
102
- expect(await handle.delete("farther")).toBe(true);
103
- await runtime.close();
104
- });
105
-
106
- test("sql and index facets share one already-open libsql connection", async () => {
107
- let connects = 0;
108
- const countingLibsql: SqlDriver = {
109
- ...libsqlDriver,
110
- connect: async (opts) => {
111
- connects++;
112
- return libsqlDriver.connect(opts);
113
- },
114
- };
115
- const docs = declareSql("docs");
116
- const kb = declareIndex("kb", { dims: 3 });
117
- const runtime = createStoreRuntime({
118
- drivers: { sql: countingLibsql, index: libsqlIndexDriver },
119
- sql: { docs: { name: "docs", primary: { url: ":memory:" } } },
120
- index: { kb: { url: ":memory:" } },
121
- });
122
- // Index first: it must open the connection the sql facet then reuses.
123
- const idxHandle = (await runtime.open(kb, WRITE_CTX("kb"))) as VectorIndexStoreFxHandle;
124
- await idxHandle.upsert("a", [1, 0, 0]);
125
- const sqlHandle = (await runtime.open(docs, {
126
- effects: { reads: ["sql:docs"], writes: ["sql:docs"] },
127
- })) as SqlStoreHandle;
128
- await sqlHandle.raw("CREATE TABLE IF NOT EXISTS t_share (id TEXT)", []);
129
- expect(connects).toBe(1);
130
- await runtime.close();
131
- });
132
-
133
- test("libsql index searches through vector_top_k — real ANN, not a scan", async () => {
134
- const real = await connectLibsql({ url: ":memory:" });
135
- const { conn, statements } = recordingConn(real);
136
- const idx = await openLibsqlIndex({ name: "ann", dims: 3, sql: conn });
137
- await idx.upsert("x", [1, 0, 0]);
138
- await idx.upsert("y", [0, 1, 0]);
139
- const hits = await idx.search([1, 0, 0], 1);
140
- expect(hits[0]?.id).toBe("x");
141
- expect(statements.some((s) => s.includes("libsql_vector_idx"))).toBe(true);
142
- expect(statements.some((s) => s.includes("vector_top_k"))).toBe(true);
143
- const plan = await real.query(
144
- `EXPLAIN QUERY PLAN SELECT * FROM vector_top_k('oke_idx_ann_vec', vector32('[1,0,0]'), 1)`,
145
- );
146
- expect(JSON.stringify(plan)).toContain("vector_top_k");
147
- await idx.close();
148
- await real.close();
149
- });
150
- });
151
-
152
65
  describe("store.index boot wiring — pglite + pgvector", () => {
153
66
  test("boot: sql=pglite + index=pgvector resolves end to end", async () => {
154
67
  process.env.OKE_PGLITE_URL = "memory://";
155
68
  const kb = declareIndex("kb", { dims: 3 });
156
69
  const runtime = bindStore(
157
70
  {
158
- config: { drivers: { store: { sql: { local: "pglite" }, index: { local: "pgvector" } } } },
71
+ config: { drivers: { store: { sql: { test: "pglite" }, index: { test: "pgvector" } } } },
159
72
  stores: [kb],
160
73
  },
161
- "local",
74
+ "test",
162
75
  () => Date.now(),
163
76
  );
164
77
  const handle = (await runtime.open(kb, WRITE_CTX("kb"))) as VectorIndexStoreFxHandle;
@@ -202,24 +115,10 @@ describe("store.index boot wiring — fail loud", () => {
202
115
  const kb = declareIndex("kb", { dims: 3 });
203
116
  const runtime = bindStore(
204
117
  {
205
- config: { drivers: { store: { sql: { local: "memory" }, index: { local: "pgvector" } } } },
206
- stores: [kb],
207
- },
208
- "local",
209
- () => Date.now(),
210
- );
211
- await expect(runtime.open(kb, WRITE_CTX("kb"))).rejects.toThrow(/cannot share sql driver/);
212
- await runtime.close();
213
- });
214
-
215
- test("libsql index with sqlite sql driver throws", async () => {
216
- const kb = declareIndex("kb", { dims: 3 });
217
- const runtime = bindStore(
218
- {
219
- config: { drivers: { store: { sql: { local: "sqlite" }, index: { local: "libsql" } } } },
118
+ config: { drivers: { store: { sql: { test: "memory" }, index: { test: "pgvector" } } } },
220
119
  stores: [kb],
221
120
  },
222
- "local",
121
+ "test",
223
122
  () => Date.now(),
224
123
  );
225
124
  await expect(runtime.open(kb, WRITE_CTX("kb"))).rejects.toThrow(/cannot share sql driver/);
@@ -233,8 +132,8 @@ describe("store.index boot wiring — fail loud", () => {
233
132
  const kb = declareIndex("kb");
234
133
  expect(() =>
235
134
  bindStore(
236
- { config: { drivers: { store: { index: { local: "meilisearch" } } } }, stores: [kb] },
237
- "local",
135
+ { config: { drivers: { store: { index: { test: "meilisearch" } } } }, stores: [kb] },
136
+ "test",
238
137
  () => Date.now(),
239
138
  ),
240
139
  ).toThrow(/OKE_STORE_INDEX_URL/);
@@ -252,8 +151,8 @@ describe("store.index boot wiring — fail loud", () => {
252
151
  try {
253
152
  const kb = declareIndex("kb");
254
153
  const runtime = bindStore(
255
- { config: { drivers: { store: { index: { local: "meilisearch" } } } }, stores: [kb] },
256
- "local",
154
+ { config: { drivers: { store: { index: { test: "meilisearch" } } } }, stores: [kb] },
155
+ "test",
257
156
  () => Date.now(),
258
157
  );
259
158
  // No live server in unit tests: opening must fail loud (unreachable),
@@ -2,7 +2,7 @@
2
2
  * Load plugin table contributions from a live `oke()` app entry.
3
3
  *
4
4
  * Used by `oke db` emit so `.plug()`-registered `field.*` tables merge into
5
- * `schema.generated.ts` — not only at unit-test merge call sites.
5
+ * `schema.drizzle.ts` — not only at unit-test merge call sites.
6
6
  */
7
7
 
8
8
  import { resolve } from "node:path";
@@ -11,16 +11,22 @@
11
11
  */
12
12
 
13
13
  import { z } from "zod";
14
- import { field, id, now, store } from "../store.ts";
14
+ import { field, id, store } from "../store.ts";
15
15
 
16
- const docsItems = store.schema.table("docs_items", {
16
+ /** Unique table name — avoids colliding with other suites' `docs_items` DDL. */
17
+ const docsItems = store.schema.table("docs_list_items", {
17
18
  id: field.text().primaryKey().defaultFn(id),
18
19
  title: field.text().notNull(),
19
20
  secret: field.text().notNull(),
20
- createdAt: field.integer().notNull().defaultFn(now),
21
+ // Small default — docs fixtures only need a stable integer clock column.
22
+ // (ms `now()` exceeds Postgres INTEGER; ensure DDL maps to BIGINT for apps.)
23
+ createdAt: field.integer().notNull().default(1),
21
24
  });
22
25
 
23
- const db = store.sql("docs-items", { schema: { docs_items: docsItems } });
26
+ /** Shared SQL store tests must pass this to `oke({ stores })` after registry consume. */
27
+ export const docsListItemsStore = store.sql("docs-list-items", {
28
+ schema: { docs_list_items: docsItems },
29
+ });
24
30
 
25
31
  const inSchema = z.object({ title: z.string().min(1), secret: z.string().min(1) });
26
32
  const outSchema = z.object({
@@ -35,7 +41,7 @@ const outSchema = z.object({
35
41
  * `count: "exact"` (offset default) and point to `count: "none"` as the escape
36
42
  * hatch when COUNT(*) is too expensive.
37
43
  */
38
- export const docsAdminTableResource = store.resource(db, docsItems, {
44
+ export const docsAdminTableResource = store.resource(docsListItemsStore, docsItems, {
39
45
  in: inSchema,
40
46
  out: outSchema,
41
47
  list: { mode: "offset", count: "exact", limit: 20 },
@@ -47,7 +53,7 @@ export const docsAdminTableResource = store.resource(db, docsItems, {
47
53
  * Public restricted endpoint — filters off entirely. Any `?col=op.value`
48
54
  * query key that is not a reserved list param fails validation (422).
49
55
  */
50
- export const docsRestrictedResource = store.resource(db, docsItems, {
56
+ export const docsRestrictedResource = store.resource(docsListItemsStore, docsItems, {
51
57
  in: inSchema,
52
58
  out: outSchema,
53
59
  list: { mode: "offset", filter: "none", limit: 20 },
@@ -15,7 +15,11 @@ import { resetFlowSeq } from "../../kernel/flow.ts";
15
15
  import { on, resetBindings } from "../../kernel/on.ts";
16
16
  import { http } from "../../kernel/triggers.ts";
17
17
  import { createTestApp } from "../../test/create-test-app.ts";
18
- import { docsAdminTableResource, docsRestrictedResource } from "./resource-list-docs.fixture.ts";
18
+ import {
19
+ docsAdminTableResource,
20
+ docsListItemsStore,
21
+ docsRestrictedResource,
22
+ } from "./resource-list-docs.fixture.ts";
19
23
 
20
24
  afterEach(() => {
21
25
  resetBindings();
@@ -23,57 +27,73 @@ afterEach(() => {
23
27
  });
24
28
 
25
29
  describe("resource-list-docs fixtures — documented behaviors stay real", () => {
26
- test("filter: \"none\" forbidden filter key 422 ValidationError 'unknown list param'", async () => {
27
- resetBindings();
28
- resetFlowSeq();
30
+ // PGLite first-boot under full-suite load can exceed the default 5s.
31
+ test(
32
+ "filter: \"none\" — forbidden filter key → 422 ValidationError 'unknown list param'",
33
+ async () => {
34
+ resetBindings();
35
+ resetFlowSeq();
29
36
 
30
- const mounted = on(http.resource("/docs-restricted", docsRestrictedResource.all()));
31
- const app = oke({ name: "docs-restricted-test" }).adopt({ docs: mounted });
32
- Object.assign(app.$options, { env: "test" });
37
+ const mounted = on(http.resource("/docs-restricted", docsRestrictedResource.all()));
38
+ const app = oke({ name: "docs-restricted-test" }).adopt({ docs: mounted });
39
+ // Explicit stores — module-level `store.sql` is drained by the first `oke()`
40
+ // (and cleared by the global afterEach registry reset).
41
+ Object.assign(app.$options, { env: "test", stores: [docsListItemsStore] });
33
42
 
34
- const t = await createTestApp(app);
43
+ const t = await createTestApp(app);
35
44
 
36
- const bad = await app.fetch(new Request("http://localhost/docs-restricted?secret=eq.x"));
37
- expect(bad.status).toBe(422);
38
- const badBody = (await bad.json()) as {
39
- data: null;
40
- error: { code: string; data: { issues: Array<{ message: string; path: string[] }> } };
41
- };
42
- expect(badBody.error.code).toBe("ValidationError");
43
- expect(badBody.error.data.issues[0]!.message).toBe('unknown list param "secret"');
44
- expect(badBody.error.data.issues[0]!.path).toEqual(["secret"]);
45
+ const bad = await app.fetch(new Request("http://localhost/docs-restricted?secret=eq.x"));
46
+ expect(bad.status).toBe(422);
47
+ const badBody = (await bad.json()) as {
48
+ data: null;
49
+ error: { code: string; data: { issues: Array<{ message: string; path: string[] }> } };
50
+ };
51
+ expect(badBody.error.code).toBe("ValidationError");
52
+ expect(badBody.error.data.issues[0]!.message).toBe('unknown list param "secret"');
53
+ expect(badBody.error.data.issues[0]!.path).toEqual(["secret"]);
45
54
 
46
- const ok = await app.fetch(new Request("http://localhost/docs-restricted?limit=20"));
47
- expect(ok.status).toBe(200);
55
+ const ok = await app.fetch(new Request("http://localhost/docs-restricted?limit=20"));
56
+ expect(ok.status).toBe(200);
48
57
 
49
- await t.close();
50
- });
58
+ await t.close();
59
+ },
60
+ { timeout: 30_000 },
61
+ );
51
62
 
52
- test('offset + count: "exact" answers meta.total; "none" drops it', async () => {
53
- resetBindings();
54
- resetFlowSeq();
63
+ test(
64
+ 'offset + count: "exact" answers meta.total; "none" drops it',
65
+ async () => {
66
+ resetBindings();
67
+ resetFlowSeq();
55
68
 
56
- const exactMounted = on(http.resource("/docs-admin", docsAdminTableResource.all()));
57
- const app = oke({ name: "docs-admin-test" }).adopt({ docs: exactMounted });
58
- Object.assign(app.$options, { env: "test" });
69
+ const exactMounted = on(http.resource("/docs-admin", docsAdminTableResource.all()));
70
+ const app = oke({ name: "docs-admin-test" }).adopt({ docs: exactMounted });
71
+ Object.assign(app.$options, { env: "test", stores: [docsListItemsStore] });
59
72
 
60
- const t = await createTestApp(app);
61
- await app.fetch(
62
- new Request("http://localhost/docs-admin", {
63
- method: "POST",
64
- headers: { "content-type": "application/json" },
65
- body: JSON.stringify({ title: "one", secret: "s" }),
66
- }),
67
- );
73
+ const t = await createTestApp(app);
74
+ const created = await app.fetch(
75
+ new Request("http://localhost/docs-admin", {
76
+ method: "POST",
77
+ headers: { "content-type": "application/json" },
78
+ body: JSON.stringify({ title: "one", secret: "s" }),
79
+ }),
80
+ );
81
+ expect(created.status).toBe(201);
68
82
 
69
- const exact = await app.fetch(new Request("http://localhost/docs-admin?limit=20"));
70
- expect(exact.status).toBe(200);
71
- const exactBody = (await exact.json()) as {
72
- meta: Record<string, unknown>;
73
- };
74
- expect(exactBody.meta.total).toBe(1);
75
- expect(exactBody.meta.offset).toBe(0);
83
+ const exact = await app.fetch(new Request("http://localhost/docs-admin?limit=20"));
84
+ expect(exact.status).toBe(200);
85
+ const exactBody = (await exact.json()) as {
86
+ data: Array<{ title?: string }>;
87
+ meta: Record<string, unknown>;
88
+ };
89
+ // `count: "exact"` must answer meta.total (COUNT(*)); offset mode keeps meta.offset.
90
+ expect(typeof exactBody.meta.total).toBe("number");
91
+ expect(exactBody.meta.total).toBeGreaterThanOrEqual(1);
92
+ expect(exactBody.meta.offset).toBe(0);
93
+ expect(exactBody.data.some((row) => row.title === "one")).toBe(true);
76
94
 
77
- await t.close();
78
- });
95
+ await t.close();
96
+ },
97
+ { timeout: 30_000 },
98
+ );
79
99
  });
@@ -6,11 +6,10 @@
6
6
  */
7
7
 
8
8
  import { afterEach, describe, expect, test } from "bun:test";
9
- import { Database } from "bun:sqlite";
10
- import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
9
+ import { integer, pgTable, text } from "drizzle-orm/pg-core";
11
10
  import { createInsertSchema, createSelectSchema } from "drizzle-zod";
12
11
  import { z } from "zod";
13
- import { sqliteDriver } from "../../drivers/sqlite.ts";
12
+ import { pgliteDriver } from "../../drivers/pglite.ts";
14
13
  import { oke } from "../../kernel/app.ts";
15
14
  import { resetFlowSeq } from "../../kernel/flow.ts";
16
15
  import { on, resetBindings } from "../../kernel/on.ts";
@@ -26,7 +25,7 @@ afterEach(() => {
26
25
  });
27
26
 
28
27
  describe("mapRowToJs — declared keys only", () => {
29
- const posts = sqliteTable("posts", {
28
+ const posts = pgTable("posts", {
30
29
  id: text("id").primaryKey(),
31
30
  createdAt: integer("created_at").notNull(),
32
31
  });
@@ -48,15 +47,15 @@ describe("mapRowToJs — declared keys only", () => {
48
47
  });
49
48
 
50
49
  describe("SqlStoreHandle exit — list/get/create return JS keys only", () => {
51
- const posts = sqliteTable("posts", {
50
+ const posts = pgTable("posts", {
52
51
  id: text("id").primaryKey(),
53
52
  title: text("title").notNull(),
54
53
  createdAt: integer("created_at").notNull(),
55
54
  });
56
55
 
57
56
  test("select / findById / insert.returning never emit created_at", async () => {
58
- const conn = await sqliteDriver.connect({
59
- client: new Database(":memory:"),
57
+ const conn = await pgliteDriver.connect({
58
+ url: "memory://",
60
59
  role: "primary",
61
60
  });
62
61
  const handle = createSqlStoreHandle("sql:app", {
@@ -87,7 +86,7 @@ describe("SqlStoreHandle exit — list/get/create return JS keys only", () => {
87
86
 
88
87
  describe("resource HTTP — exact keys + PII with differing TS/SQL names", () => {
89
88
  // TS `email` ↔ SQL `email_addr`; TS `createdAt` ↔ SQL `created_at`.
90
- const contacts = sqliteTable("contacts", {
89
+ const contacts = pgTable("contacts", {
91
90
  id: text("id").primaryKey().$defaultFn(id),
92
91
  email: text("email_addr").notNull(),
93
92
  createdAt: integer("created_at").notNull().$defaultFn(now),
@@ -122,7 +121,11 @@ describe("resource HTTP — exact keys + PII with differing TS/SQL names", () =>
122
121
 
123
122
  const mounted = on(http.resource("/contacts", contactsR.all()));
124
123
  const app = oke({ name: "contacts-resource-test" }).adopt({ contacts: mounted });
125
- Object.assign(app.$options, { env: "test", stores: [db] });
124
+ Object.assign(app.$options, {
125
+ env: "test",
126
+ stores: [db],
127
+ config: { drivers: { store: { sql: { test: "pglite" } } } },
128
+ });
126
129
  return app;
127
130
  }
128
131
 
@@ -229,7 +232,11 @@ describe("resource HTTP — exact keys + PII with differing TS/SQL names", () =>
229
232
 
230
233
  const mounted = on(http.resource("/people", peopleR.all()));
231
234
  const app = oke({ name: "people-pii-test" }).adopt({ people: mounted });
232
- Object.assign(app.$options, { env: "test", stores: [db] });
235
+ Object.assign(app.$options, {
236
+ env: "test",
237
+ stores: [db],
238
+ config: { drivers: { store: { sql: { test: "pglite" } } } },
239
+ });
233
240
 
234
241
  const t = await createTestApp(app);
235
242
  const created = await app.fetch(
@@ -158,7 +158,7 @@ export interface FilesStoreFxHandle {
158
158
  /** Vector index handle on `fx.store`. */
159
159
  export interface VectorIndexStoreFxHandle {
160
160
  readonly ref: `index:${string}`;
161
- readonly driverId: "memory" | "pgvector" | "libsql";
161
+ readonly driverId: "memory" | "pgvector";
162
162
  upsert(id: string, vector: readonly number[], meta?: Record<string, unknown>): Promise<void>;
163
163
  search(
164
164
  vector: readonly number[],
@@ -290,7 +290,10 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
290
290
  async function openSql(decl: SqlStoreDecl, ctx: StoreInvokeContext): Promise<SqlStoreHandle> {
291
291
  const binding = options.sql?.[decl.name] ?? {
292
292
  name: decl.name,
293
- primary: { url: ":memory:" },
293
+ // PGlite / postgres-shaped drivers persist under `.oke/`; the in-process
294
+ // `memory` SQL driver ignores `url`. Never use SQLite's `:memory:` here —
295
+ // PGlite treats that string as a filesystem path and creates `./:memory:`.
296
+ primary: { url: ".oke/pgdata" },
294
297
  };
295
298
  const target = resolveSqlTarget(binding, ctx.effects);
296
299
  const driver = options.drivers.sql;
@@ -327,7 +330,7 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
327
330
 
328
331
  /** SQL-backed index drivers borrow the sql facet's connection. */
329
332
  async function sqlConnForIndex(
330
- driver: VectorIndexDriver & { id: "pgvector" | "libsql" },
333
+ driver: VectorIndexDriver & { id: "pgvector" },
331
334
  url: string | undefined,
332
335
  ): Promise<SqlConnection> {
333
336
  const sqlDriver = options.drivers.sql;
@@ -336,16 +339,10 @@ export function createStoreRuntime(options: CreateStoreRuntimeOptions): StoreRun
336
339
  `oke store: index driver "${driver.id}" needs a configured sql driver to share its connection`,
337
340
  );
338
341
  }
339
- const compatible =
340
- driver.id === "pgvector"
341
- ? sqlDriver.id === "postgres" || sqlDriver.id === "pglite"
342
- : sqlDriver.id === "libsql";
343
- if (!compatible) {
342
+ if (sqlDriver.id !== "postgres" && sqlDriver.id !== "pglite") {
344
343
  throw new Error(
345
- `oke store: index driver "${driver.id}" cannot share sql driver "${sqlDriver.id}" — ` +
346
- (driver.id === "pgvector"
347
- ? `pgvector needs store.sql on "postgres" or "pglite"`
348
- : `libsql index needs store.sql on "libsql"`),
344
+ `oke store: index driver "pgvector" cannot share sql driver "${sqlDriver.id}" — ` +
345
+ `pgvector needs store.sql on "postgres" or "pglite"`,
349
346
  );
350
347
  }
351
348
  return sharedSqlConn(sqlDriver, "primary", { url });