okengine 0.2.6 → 0.3.2

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 (681) hide show
  1. package/AGENTS.md +33 -30
  2. package/README.md +74 -340
  3. package/{spec/manifest.v1.schema.json → manifest.v1.schema.json} +40 -9
  4. package/package.json +47 -44
  5. package/site/content/docs/ai/llms-txt.mdx +54 -0
  6. package/site/content/docs/ai/mcp.mdx +123 -0
  7. package/site/content/docs/ai/meta.json +5 -0
  8. package/site/content/docs/ai/skills.mdx +53 -0
  9. package/site/content/docs/console/access.mdx +29 -0
  10. package/site/content/docs/console/ai.mdx +35 -0
  11. package/site/content/docs/console/architecture.mdx +35 -0
  12. package/site/content/docs/console/channels.mdx +37 -0
  13. package/site/content/docs/console/clock.mdx +31 -0
  14. package/site/content/docs/console/flows.mdx +31 -0
  15. package/site/content/docs/console/gates.mdx +35 -0
  16. package/site/content/docs/console/manifest-diff.mdx +34 -0
  17. package/site/content/docs/console/meta.json +23 -0
  18. package/site/content/docs/console/overview.mdx +40 -0
  19. package/site/content/docs/console/plugins.mdx +41 -0
  20. package/site/content/docs/console/privacy.mdx +32 -0
  21. package/site/content/docs/console/runs.mdx +40 -0
  22. package/site/content/docs/console/signals.mdx +31 -0
  23. package/site/content/docs/console/store.mdx +32 -0
  24. package/site/content/docs/console/tenancy.mdx +32 -0
  25. package/site/content/docs/console/traces.mdx +34 -0
  26. package/site/content/docs/console/vault.mdx +37 -0
  27. package/site/content/docs/elements/ai.mdx +180 -0
  28. package/site/content/docs/elements/channel.mdx +167 -0
  29. package/site/content/docs/elements/clock.mdx +182 -0
  30. package/site/content/docs/elements/flow.mdx +288 -0
  31. package/site/content/docs/elements/gate.mdx +171 -0
  32. package/site/content/docs/elements/meta.json +5 -0
  33. package/site/content/docs/elements/signal.mdx +171 -0
  34. package/site/content/docs/elements/store.mdx +320 -0
  35. package/site/content/docs/elements/vault.mdx +263 -0
  36. package/site/content/docs/get-started/basic-usage.mdx +124 -0
  37. package/site/content/docs/get-started/comparison.mdx +65 -0
  38. package/site/content/docs/get-started/installation.mdx +113 -0
  39. package/site/content/docs/get-started/introduction.mdx +123 -0
  40. package/site/content/docs/get-started/meta.json +5 -0
  41. package/site/content/docs/index.mdx +63 -0
  42. package/site/content/docs/meta.json +5 -0
  43. package/site/content/docs/plugins/compression.mdx +60 -0
  44. package/site/content/docs/plugins/cors.mdx +92 -0
  45. package/site/content/docs/plugins/csrf.mdx +96 -0
  46. package/site/content/docs/plugins/ip-allowlist.mdx +92 -0
  47. package/site/content/docs/plugins/maintenance-mode.mdx +101 -0
  48. package/site/content/docs/plugins/meta.json +15 -0
  49. package/site/content/docs/plugins/security-headers.mdx +136 -0
  50. package/site/content/docs/reference/cli.md +101 -0
  51. package/site/content/docs/reference/configuration.mdx +159 -0
  52. package/site/content/docs/reference/environment-variables.mdx +87 -0
  53. package/site/content/docs/reference/errors.mdx +80 -0
  54. package/site/content/docs/reference/fx.mdx +117 -0
  55. package/site/content/docs/reference/meta.json +5 -0
  56. package/site/content/docs/reference/plugins.mdx +249 -0
  57. package/site/content/docs/reference/security.md +63 -0
  58. package/src/auth/api-keys.ts +2 -5
  59. package/src/auth/attenuation.ts +2 -6
  60. package/src/auth/auth.test.ts +56 -31
  61. package/src/auth/invoke-as.ts +1 -3
  62. package/src/auth/operator.ts +8 -26
  63. package/src/auth/planes.ts +2 -7
  64. package/src/auth/plugin.ts +4 -7
  65. package/src/auth/roles.ts +1 -5
  66. package/src/auth/sessions.ts +10 -39
  67. package/src/cli/args.ts +1 -5
  68. package/src/cli/ask-dev-mode.ts +40 -0
  69. package/src/cli/build.ts +1 -2
  70. package/src/cli/client-add.test.ts +8 -15
  71. package/src/cli/client-add.ts +5 -14
  72. package/src/cli/completion.test.ts +1 -5
  73. package/src/cli/completion.ts +4 -17
  74. package/src/cli/db-auto-push.test.ts +64 -0
  75. package/src/cli/db-auto-push.ts +72 -0
  76. package/src/cli/db.test.ts +189 -0
  77. package/src/cli/db.ts +456 -0
  78. package/src/cli/dev-app-runner.ts +2 -8
  79. package/src/cli/dev-db-push.test.ts +193 -0
  80. package/src/cli/dev-mode.test.ts +45 -0
  81. package/src/cli/dev-mode.ts +78 -0
  82. package/src/cli/dev-schema-sync.test.ts +66 -0
  83. package/src/cli/dev-schema-sync.ts +139 -0
  84. package/src/cli/dev.test.ts +264 -15
  85. package/src/cli/dev.ts +355 -139
  86. package/src/cli/doc-staleness.test.ts +69 -0
  87. package/src/cli/docker-cli.test.ts +27 -8
  88. package/src/cli/docker.ts +11 -3
  89. package/src/cli/doctor-diff.test.ts +1 -5
  90. package/src/cli/doctor-diff.ts +17 -46
  91. package/src/cli/doctor-pii.ts +2 -7
  92. package/src/cli/doctor.test.ts +26 -4
  93. package/src/cli/doctor.ts +35 -11
  94. package/src/cli/drizzle-env.test.ts +67 -0
  95. package/src/cli/drizzle-env.ts +78 -0
  96. package/src/cli/ensure-drizzle-config.ts +50 -0
  97. package/src/cli/eval.ts +4 -14
  98. package/src/cli/gates-list.ts +1 -4
  99. package/src/cli/hero-meta.test.ts +17 -19
  100. package/src/cli/hero-meta.ts +20 -30
  101. package/src/cli/images.ts +3 -8
  102. package/src/cli/index.ts +11 -2
  103. package/src/cli/load-config.images.test.ts +14 -14
  104. package/src/cli/load-config.ts +47 -47
  105. package/src/cli/mcp-from-console.ts +1 -4
  106. package/src/cli/mode.ts +65 -0
  107. package/src/cli/openbao-bootstrap.test.ts +147 -0
  108. package/src/cli/openbao-bootstrap.ts +280 -0
  109. package/src/cli/openbao-restart.integration.test.ts +136 -0
  110. package/src/cli/ports.test.ts +7 -14
  111. package/src/cli/ports.ts +7 -5
  112. package/src/cli/privacy-erase.ts +1 -3
  113. package/src/cli/registry.ts +75 -25
  114. package/src/cli/resolve-dev-sql-env.test.ts +48 -0
  115. package/src/cli/resolve-dev-sql-env.ts +42 -0
  116. package/src/cli/schema.ts +3 -10
  117. package/src/cli/stack.ts +8 -10
  118. package/src/cli/start.ts +4 -15
  119. package/src/cli/upgrade.ts +1 -4
  120. package/src/cli/vault-cmd.ts +63 -0
  121. package/src/client/budget-entry.ts +1 -6
  122. package/src/client/create.test.ts +6 -12
  123. package/src/client/create.ts +2 -8
  124. package/src/client/errors.ts +1 -4
  125. package/src/client/index.ts +1 -6
  126. package/src/client/notes-contract.test.ts +4 -13
  127. package/src/client/transport.ts +9 -30
  128. package/src/client/types.ts +15 -30
  129. package/src/compiler/aot.test.ts +2 -9
  130. package/src/compiler/aot.ts +1 -4
  131. package/src/compiler/differential.test.ts +3 -11
  132. package/src/compiler/dynamic.ts +1 -4
  133. package/src/compiler/effects-infer.ts +8 -34
  134. package/src/compiler/emit.ts +1 -3
  135. package/src/compiler/extract.test.ts +136 -30
  136. package/src/compiler/extract.ts +485 -157
  137. package/src/compiler/fixtures/skyport/oke.config.ts +3 -3
  138. package/src/compiler/fixtures/skyport/src/flows/bookings/index.ts +7 -3
  139. package/src/compiler/fixtures/skyport/src/flows/payments/index.ts +1 -3
  140. package/src/compiler/fixtures/skyport/src/flows/support/index.ts +4 -1
  141. package/src/compiler/fixtures/skyport.expected.json +24 -83
  142. package/src/compiler/fixtures/triggers/five-triggers.ts +1 -2
  143. package/src/compiler/http-parse.ts +2 -9
  144. package/src/compiler/index.ts +1 -5
  145. package/src/compiler/response.ts +16 -7
  146. package/src/compiler/sucrose.ts +11 -31
  147. package/src/config/define-config.test.ts +55 -34
  148. package/src/config/index.ts +177 -46
  149. package/src/config/resolve-driver.test.ts +28 -17
  150. package/src/console/budget.test.ts +1 -4
  151. package/src/console/index.ts +1 -4
  152. package/src/console/server/access.test.ts +15 -43
  153. package/src/console/server/access.ts +19 -49
  154. package/src/console/server/ai.test.ts +3 -11
  155. package/src/console/server/ai.ts +23 -46
  156. package/src/console/server/app.ts +16 -45
  157. package/src/console/server/auth-rate.test.ts +4 -12
  158. package/src/console/server/bind.ts +1 -5
  159. package/src/console/server/channels.test.ts +2 -6
  160. package/src/console/server/channels.ts +10 -35
  161. package/src/console/server/claim.ts +2 -8
  162. package/src/console/server/clock.test.ts +2 -6
  163. package/src/console/server/clock.ts +8 -26
  164. package/src/console/server/console.test.ts +1 -3
  165. package/src/console/server/diff.test.ts +5 -17
  166. package/src/console/server/diff.ts +10 -31
  167. package/src/console/server/dry-run.audit.test.ts +2 -8
  168. package/src/console/server/flows.ts +64 -233
  169. package/src/console/server/gates.test.ts +14 -50
  170. package/src/console/server/gates.ts +13 -48
  171. package/src/console/server/index.ts +2 -9
  172. package/src/console/server/live.ts +3 -12
  173. package/src/console/server/operator-db.test.ts +4 -15
  174. package/src/console/server/operator-db.ts +13 -32
  175. package/src/console/server/plugin.ts +50 -53
  176. package/src/console/server/plugins.test.ts +2 -6
  177. package/src/console/server/plugins.ts +17 -56
  178. package/src/console/server/runs-pii.ts +2 -7
  179. package/src/console/server/security.gate.test.ts +18 -40
  180. package/src/console/server/serve.ts +10 -25
  181. package/src/console/server/signals.test.ts +1 -3
  182. package/src/console/server/signals.ts +17 -40
  183. package/src/console/server/state.ts +21 -59
  184. package/src/console/server/store.test.ts +20 -22
  185. package/src/console/server/store.ts +31 -76
  186. package/src/console/server/vault.test.ts +12 -29
  187. package/src/console/server/vault.ts +44 -66
  188. package/src/console/ui/access/AccessA11yView.tsx +6 -21
  189. package/src/console/ui/access/a11y.test.tsx +3 -12
  190. package/src/console/ui/access/acknowledgement.test.ts +1 -4
  191. package/src/console/ui/access/acknowledgement.ts +1 -3
  192. package/src/console/ui/access/blast-radius.ts +1 -3
  193. package/src/console/ui/access/confirmation.test.ts +1 -5
  194. package/src/console/ui/access/confirmation.ts +1 -4
  195. package/src/console/ui/access/fixture.ts +1 -5
  196. package/src/console/ui/access/grantable.test.ts +1 -3
  197. package/src/console/ui/access/grantable.ts +2 -7
  198. package/src/console/ui/access/index.ts +2 -9
  199. package/src/console/ui/access/provenance.test.ts +1 -3
  200. package/src/console/ui/access/provenance.ts +2 -6
  201. package/src/console/ui/access/search.test.ts +1 -5
  202. package/src/console/ui/access/search.ts +2 -6
  203. package/src/console/ui/ai/AiA11yView.tsx +6 -17
  204. package/src/console/ui/ai/a11y.test.tsx +2 -5
  205. package/src/console/ui/ai/fixture.ts +2 -7
  206. package/src/console/ui/ai/format.ts +1 -3
  207. package/src/console/ui/ai/group.test.ts +1 -3
  208. package/src/console/ui/ai/group.ts +4 -12
  209. package/src/console/ui/ai/index.ts +2 -9
  210. package/src/console/ui/ai/promotion.test.ts +2 -7
  211. package/src/console/ui/ai/promotion.ts +4 -13
  212. package/src/console/ui/ai/search.test.ts +2 -11
  213. package/src/console/ui/ai/search.ts +3 -13
  214. package/src/console/ui/ai/types.ts +1 -8
  215. package/src/console/ui/architecture/ArchitectureA11yView.tsx +8 -29
  216. package/src/console/ui/architecture/a11y.test.tsx +1 -2
  217. package/src/console/ui/architecture/declared.ts +1 -5
  218. package/src/console/ui/architecture/index.ts +7 -35
  219. package/src/console/ui/architecture/layout.ts +1 -3
  220. package/src/console/ui/architecture/pathologies.ts +10 -19
  221. package/src/console/ui/architecture/search.ts +6 -15
  222. package/src/console/ui/architecture/traffic.ts +4 -14
  223. package/src/console/ui/architecture/types.ts +2 -10
  224. package/src/console/ui/architecture/view.test.ts +7 -19
  225. package/src/console/ui/architecture/view.ts +9 -36
  226. package/src/console/ui/channels/ChannelsA11yView.tsx +4 -13
  227. package/src/console/ui/channels/a11y.test.tsx +1 -2
  228. package/src/console/ui/channels/confirmation.test.ts +1 -4
  229. package/src/console/ui/channels/confirmation.ts +1 -4
  230. package/src/console/ui/channels/findings.ts +1 -5
  231. package/src/console/ui/channels/index.ts +2 -8
  232. package/src/console/ui/channels/locale.test.ts +1 -3
  233. package/src/console/ui/channels/locale.ts +2 -8
  234. package/src/console/ui/channels/search.ts +4 -13
  235. package/src/console/ui/channels/taxonomy.ts +1 -3
  236. package/src/console/ui/clock/ClockA11yView.tsx +9 -26
  237. package/src/console/ui/clock/a11y.test.tsx +2 -5
  238. package/src/console/ui/clock/confirmation.test.ts +1 -3
  239. package/src/console/ui/clock/confirmation.ts +1 -4
  240. package/src/console/ui/clock/findings.ts +1 -4
  241. package/src/console/ui/clock/health.ts +2 -7
  242. package/src/console/ui/clock/index.ts +2 -10
  243. package/src/console/ui/clock/search.test.ts +1 -3
  244. package/src/console/ui/clock/search.ts +2 -6
  245. package/src/console/ui/clock/timeline.test.ts +1 -3
  246. package/src/console/ui/clock/waiting-on.test.ts +1 -5
  247. package/src/console/ui/clock/waiting-on.ts +2 -7
  248. package/src/console/ui/diff/DiffA11yView.tsx +8 -17
  249. package/src/console/ui/diff/a11y.test.tsx +2 -5
  250. package/src/console/ui/diff/group.test.ts +3 -13
  251. package/src/console/ui/diff/group.ts +2 -8
  252. package/src/console/ui/diff/index.ts +2 -8
  253. package/src/console/ui/diff/search.test.ts +1 -5
  254. package/src/console/ui/diff/search.ts +4 -16
  255. package/src/console/ui/diff/summary.ts +1 -2
  256. package/src/console/ui/dist/assets/{index-Dy4jht9P.js → index-BWo8R7NR.js} +2 -2
  257. package/src/console/ui/dist/assets/{panel-access-Dd37LU2c.js → panel-access-C0J2D-a2.js} +1 -1
  258. package/src/console/ui/dist/assets/{panel-ai-CC7LR6-J.js → panel-ai-D_m6WQI8.js} +1 -1
  259. package/src/console/ui/dist/assets/{panel-architecture-B5b3iKCz.js → panel-architecture-CKnXFyUx.js} +1 -1
  260. package/src/console/ui/dist/assets/{panel-channels-CeNjTKXp.js → panel-channels-BOmQ-onL.js} +1 -1
  261. package/src/console/ui/dist/assets/{panel-clock-DgFTLoHV.js → panel-clock-giAq0Ccv.js} +1 -1
  262. package/src/console/ui/dist/assets/{panel-diff-DxehccqB.js → panel-diff-cdonmH8c.js} +1 -1
  263. package/src/console/ui/dist/assets/{panel-flows-BtrVn-Eg.js → panel-flows-DlCU5zjA.js} +2 -2
  264. package/src/console/ui/dist/assets/{panel-gates-Z9MKRGdH.js → panel-gates-XclZxWD5.js} +1 -1
  265. package/src/console/ui/dist/assets/{panel-overview-Dt_AeXgd.js → panel-overview-BznEOTnb.js} +1 -1
  266. package/src/console/ui/dist/assets/{panel-plugins-DWd0TowH.js → panel-plugins-CcGM1g64.js} +1 -1
  267. package/src/console/ui/dist/assets/{panel-runs-DGstFHeq.js → panel-runs-CGWNHLR4.js} +1 -1
  268. package/src/console/ui/dist/assets/{panel-signals-DzEa2Fnt.js → panel-signals-CNywkdak.js} +1 -1
  269. package/src/console/ui/dist/assets/{panel-store-BJkbNgxx.js → panel-store-KmTbFHMH.js} +1 -1
  270. package/src/console/ui/dist/assets/{panel-traces-BaRVO3gM.js → panel-traces-DBLx2ilD.js} +1 -1
  271. package/src/console/ui/dist/assets/panel-vault-CEnFc0dk.js +1 -0
  272. package/src/console/ui/dist/index.html +1 -1
  273. package/src/console/ui/flows/FlowsA11yView.tsx +7 -22
  274. package/src/console/ui/flows/a11y.test.tsx +2 -8
  275. package/src/console/ui/flows/buffer.test.ts +3 -11
  276. package/src/console/ui/flows/buffer.ts +4 -11
  277. package/src/console/ui/flows/confirmation.ts +1 -3
  278. package/src/console/ui/flows/contract.test.ts +3 -7
  279. package/src/console/ui/flows/contract.ts +12 -36
  280. package/src/console/ui/flows/graph.test.ts +3 -11
  281. package/src/console/ui/flows/graph.ts +5 -15
  282. package/src/console/ui/flows/index.ts +1 -6
  283. package/src/console/ui/flows/save-as-test.ts +1 -3
  284. package/src/console/ui/flows/search.ts +8 -25
  285. package/src/console/ui/flows/tiers.ts +2 -9
  286. package/src/console/ui/gates/GatesA11yView.tsx +4 -13
  287. package/src/console/ui/gates/a11y.test.tsx +2 -5
  288. package/src/console/ui/gates/audit.ts +1 -3
  289. package/src/console/ui/gates/denial.test.ts +1 -3
  290. package/src/console/ui/gates/denial.ts +4 -12
  291. package/src/console/ui/gates/findings.ts +1 -3
  292. package/src/console/ui/gates/group.test.ts +3 -3
  293. package/src/console/ui/gates/group.ts +3 -11
  294. package/src/console/ui/gates/index.ts +2 -10
  295. package/src/console/ui/gates/search.ts +3 -10
  296. package/src/console/ui/overview/OverviewA11yView.tsx +9 -27
  297. package/src/console/ui/overview/a11y.test.tsx +1 -2
  298. package/src/console/ui/overview/busiest.ts +1 -3
  299. package/src/console/ui/overview/compose.ts +1 -13
  300. package/src/console/ui/overview/cost.ts +34 -38
  301. package/src/console/ui/overview/fixture.ts +21 -26
  302. package/src/console/ui/overview/golden.ts +4 -14
  303. package/src/console/ui/overview/index.ts +2 -9
  304. package/src/console/ui/overview/rank.test.ts +3 -10
  305. package/src/console/ui/overview/rank.ts +2 -7
  306. package/src/console/ui/overview/slo.test.ts +5 -9
  307. package/src/console/ui/overview/slo.ts +6 -23
  308. package/src/console/ui/overview/verdict.ts +3 -10
  309. package/src/console/ui/plugins/PluginsA11yView.tsx +8 -18
  310. package/src/console/ui/plugins/a11y.test.tsx +1 -2
  311. package/src/console/ui/plugins/fixture.ts +2 -4
  312. package/src/console/ui/plugins/group.test.ts +1 -3
  313. package/src/console/ui/plugins/group.ts +1 -6
  314. package/src/console/ui/plugins/index.ts +3 -13
  315. package/src/console/ui/plugins/search.ts +7 -19
  316. package/src/console/ui/runs/RunsA11yView.tsx +5 -20
  317. package/src/console/ui/runs/a11y.test.tsx +2 -5
  318. package/src/console/ui/runs/explain.ts +2 -6
  319. package/src/console/ui/runs/group.ts +3 -12
  320. package/src/console/ui/runs/histogram.test.ts +2 -11
  321. package/src/console/ui/runs/histogram.ts +1 -4
  322. package/src/console/ui/runs/index.ts +4 -18
  323. package/src/console/ui/runs/project.ts +2 -6
  324. package/src/console/ui/runs/query.test.ts +1 -3
  325. package/src/console/ui/runs/query.ts +12 -35
  326. package/src/console/ui/runs/search.ts +5 -19
  327. package/src/console/ui/runs/trace-link.test.ts +2 -6
  328. package/src/console/ui/runs/trace-link.ts +4 -16
  329. package/src/console/ui/runs/types.ts +1 -3
  330. package/src/console/ui/shell/App.tsx +2 -10
  331. package/src/console/ui/shell/client.ts +22 -115
  332. package/src/console/ui/shell/components/ui.tsx +1 -4
  333. package/src/console/ui/shell/layout/Shell.tsx +2 -4
  334. package/src/console/ui/shell/main.tsx +31 -96
  335. package/src/console/ui/shell/panels/access/AccessPanel.tsx +34 -98
  336. package/src/console/ui/shell/panels/ai/AiPanel.tsx +35 -106
  337. package/src/console/ui/shell/panels/architecture/ArchitecturePanel.tsx +18 -66
  338. package/src/console/ui/shell/panels/channels/ChannelsPanel.tsx +20 -57
  339. package/src/console/ui/shell/panels/clock/ClockPanel.tsx +22 -54
  340. package/src/console/ui/shell/panels/diff/DiffPanel.tsx +20 -61
  341. package/src/console/ui/shell/panels/flows/ContractEditor.tsx +6 -23
  342. package/src/console/ui/shell/panels/flows/FlowDrawer.tsx +13 -28
  343. package/src/console/ui/shell/panels/flows/FlowsPanel.tsx +9 -29
  344. package/src/console/ui/shell/panels/gates/GatesPanel.tsx +24 -80
  345. package/src/console/ui/shell/panels/overview/OverviewPanel.tsx +20 -58
  346. package/src/console/ui/shell/panels/plugins/PluginsPanel.tsx +16 -41
  347. package/src/console/ui/shell/panels/runs/RunsPanel.tsx +31 -99
  348. package/src/console/ui/shell/panels/signals/SignalsPanel.tsx +38 -101
  349. package/src/console/ui/shell/panels/store/StorePanel.tsx +27 -66
  350. package/src/console/ui/shell/panels/traces/TracesPanel.tsx +28 -89
  351. package/src/console/ui/shell/panels/vault/VaultPanel.tsx +22 -53
  352. package/src/console/ui/shell/setup/Wizard.tsx +3 -5
  353. package/src/console/ui/shell/styles.css +1 -2
  354. package/src/console/ui/signals/SignalsA11yView.tsx +9 -33
  355. package/src/console/ui/signals/a11y.test.tsx +2 -5
  356. package/src/console/ui/signals/confirmation.test.ts +1 -5
  357. package/src/console/ui/signals/confirmation.ts +2 -6
  358. package/src/console/ui/signals/dry-run.ts +1 -3
  359. package/src/console/ui/signals/durable.ts +1 -3
  360. package/src/console/ui/signals/findings.ts +1 -3
  361. package/src/console/ui/signals/group.test.ts +2 -8
  362. package/src/console/ui/signals/group.ts +2 -10
  363. package/src/console/ui/signals/index.ts +1 -4
  364. package/src/console/ui/signals/monitor.ts +2 -7
  365. package/src/console/ui/signals/schema-form.test.ts +3 -14
  366. package/src/console/ui/signals/schema-form.ts +1 -4
  367. package/src/console/ui/signals/search.ts +4 -13
  368. package/src/console/ui/store/StoreA11yView.tsx +3 -9
  369. package/src/console/ui/store/a11y.test.tsx +2 -5
  370. package/src/console/ui/store/confirmation.test.ts +1 -3
  371. package/src/console/ui/store/confirmation.ts +1 -4
  372. package/src/console/ui/store/dry-run.ts +2 -5
  373. package/src/console/ui/store/fixture.ts +1 -2
  374. package/src/console/ui/store/group.test.ts +1 -6
  375. package/src/console/ui/store/group.ts +1 -4
  376. package/src/console/ui/store/index.ts +1 -5
  377. package/src/console/ui/store/search.ts +2 -6
  378. package/src/console/ui/store/will-not-fire.ts +1 -2
  379. package/src/console/ui/traces/TracesA11yView.tsx +10 -29
  380. package/src/console/ui/traces/a11y.test.tsx +1 -2
  381. package/src/console/ui/traces/chain.test.ts +5 -19
  382. package/src/console/ui/traces/chain.ts +1 -3
  383. package/src/console/ui/traces/critical-path.test.ts +1 -3
  384. package/src/console/ui/traces/critical-path.ts +2 -6
  385. package/src/console/ui/traces/filter.test.ts +2 -6
  386. package/src/console/ui/traces/filter.ts +5 -13
  387. package/src/console/ui/traces/fold.test.ts +4 -12
  388. package/src/console/ui/traces/fold.ts +1 -3
  389. package/src/console/ui/traces/mini.ts +1 -3
  390. package/src/console/ui/traces/replay.test.ts +1 -3
  391. package/src/console/ui/traces/replay.ts +1 -3
  392. package/src/console/ui/traces/sampling.ts +1 -4
  393. package/src/console/ui/traces/search.ts +4 -17
  394. package/src/console/ui/traces/tier.ts +1 -3
  395. package/src/console/ui/vault/VaultA11yView.tsx +5 -17
  396. package/src/console/ui/vault/a11y.test.tsx +1 -2
  397. package/src/console/ui/vault/blast-radius.ts +1 -3
  398. package/src/console/ui/vault/confirmation.test.ts +1 -5
  399. package/src/console/ui/vault/confirmation.ts +1 -4
  400. package/src/console/ui/vault/dormant.test.ts +1 -4
  401. package/src/console/ui/vault/export-safe.test.ts +1 -5
  402. package/src/console/ui/vault/export-safe.ts +1 -4
  403. package/src/console/ui/vault/fixture.ts +3 -3
  404. package/src/console/ui/vault/group.ts +1 -2
  405. package/src/console/ui/vault/index.ts +2 -10
  406. package/src/console/ui/vault/search.ts +2 -6
  407. package/src/console/ui/vault/types.ts +1 -1
  408. package/src/console/xss.gate.test.ts +1 -3
  409. package/src/docker/compose.ts +215 -27
  410. package/src/docker/derive.ts +6 -14
  411. package/src/docker/docker.test.ts +118 -15
  412. package/src/docker/dockerfile.integration.test.ts +12 -21
  413. package/src/docker/helpers.ts +5 -4
  414. package/src/docker/index.ts +9 -6
  415. package/src/docker/pin.ts +1 -9
  416. package/src/docker/recipes/index.ts +6 -6
  417. package/src/docker/recipes/mailpit.ts +22 -0
  418. package/src/docker/recipes/openbao.ts +47 -0
  419. package/src/docker/recipes/postgres.ts +17 -6
  420. package/src/docker/recipes/redis.ts +11 -2
  421. package/src/docker/recipes/rustfs.ts +32 -0
  422. package/src/docker/stack-id.test.ts +73 -5
  423. package/src/docker/stack-id.ts +124 -33
  424. package/src/docker/stack.integration.test.ts +6 -21
  425. package/src/docker/stack.ts +36 -4
  426. package/src/docker/types.ts +16 -4
  427. package/src/docs-origin.ts +4 -4
  428. package/src/drivers/ai-anthropic.ts +5 -14
  429. package/src/drivers/ai-mock.ts +2 -5
  430. package/src/drivers/ai-openai-compatible.ts +4 -10
  431. package/src/drivers/ai-providers.test.ts +6 -13
  432. package/src/drivers/bun-native-completeness.test.ts +6 -15
  433. package/src/drivers/channel-console.ts +6 -7
  434. package/src/drivers/channel-fcm.ts +20 -30
  435. package/src/drivers/channel-resend.ts +1 -3
  436. package/src/drivers/channel-smtp.ts +2 -6
  437. package/src/drivers/channel-types.ts +2 -12
  438. package/src/drivers/channel-unifonic.ts +2 -6
  439. package/src/drivers/channel-wa-cloud.ts +2 -6
  440. package/src/drivers/channel-webpush.ts +21 -60
  441. package/src/drivers/conformance.test.ts +2 -10
  442. package/src/drivers/conformance.ts +8 -21
  443. package/src/drivers/drizzle-dialect.test.ts +20 -0
  444. package/src/drivers/drizzle-dialect.ts +37 -0
  445. package/src/drivers/fs.ts +2 -8
  446. package/src/drivers/index.ts +12 -57
  447. package/src/drivers/memory.ts +287 -75
  448. package/src/drivers/pgvector.ts +7 -11
  449. package/src/drivers/postgres.ts +7 -13
  450. package/src/drivers/redis.ts +13 -37
  451. package/src/drivers/s3.ts +15 -18
  452. package/src/drivers/signal-engine.ts +12 -49
  453. package/src/drivers/signal-memory.ts +2 -8
  454. package/src/drivers/signal-nats.ts +4 -9
  455. package/src/drivers/signal-postgres.ts +62 -129
  456. package/src/drivers/signal-redis.ts +7 -21
  457. package/src/drivers/signal-types.ts +1 -4
  458. package/src/drivers/sqlite.ts +3 -12
  459. package/src/drivers/types.ts +4 -23
  460. package/src/drivers/vault-driver-removal.test.ts +55 -0
  461. package/src/drivers/vault-env.ts +2 -6
  462. package/src/drivers/vault-infisical.ts +1 -5
  463. package/src/drivers/vault-managed.ts +1 -5
  464. package/src/drivers/vault-memory.ts +1 -5
  465. package/src/drivers/vault-openbao.test.ts +97 -0
  466. package/src/drivers/vault-openbao.ts +103 -40
  467. package/src/drivers/vault-types.ts +3 -16
  468. package/src/elements/ai/declare.ts +4 -14
  469. package/src/elements/ai/eval.ts +2 -6
  470. package/src/elements/ai/pii.ts +1 -3
  471. package/src/elements/ai/runtime.ts +12 -50
  472. package/src/elements/ai/schema.ts +4 -15
  473. package/src/elements/ai.test.ts +13 -24
  474. package/src/elements/ai.ts +1 -5
  475. package/src/elements/channel/consent.ts +3 -12
  476. package/src/elements/channel/costs.ts +4 -15
  477. package/src/elements/channel/declare.ts +1 -4
  478. package/src/elements/channel/email-auth.ts +1 -4
  479. package/src/elements/channel/locale.ts +2 -10
  480. package/src/elements/channel/mask.ts +1 -3
  481. package/src/elements/channel/mime.ts +2 -12
  482. package/src/elements/channel/outcomes.test.ts +1 -5
  483. package/src/elements/channel/outcomes.ts +5 -15
  484. package/src/elements/channel/receipts.ts +2 -7
  485. package/src/elements/channel/runtime.ts +28 -74
  486. package/src/elements/channel/suppression.ts +8 -14
  487. package/src/elements/channel.test.ts +8 -31
  488. package/src/elements/channel.ts +3 -14
  489. package/src/elements/clock/actions.ts +6 -18
  490. package/src/elements/clock/declare.ts +1 -3
  491. package/src/elements/clock/dst.ts +1 -5
  492. package/src/elements/clock/durable.ts +4 -16
  493. package/src/elements/clock/health.ts +2 -7
  494. package/src/elements/clock/leader.ts +2 -9
  495. package/src/elements/clock/reconcile.ts +4 -15
  496. package/src/elements/clock/runtime.ts +2 -5
  497. package/src/elements/clock/schedule.ts +4 -20
  498. package/src/elements/clock.test.ts +2 -7
  499. package/src/elements/clock.ts +5 -23
  500. package/src/elements/gate/permissions.ts +1 -4
  501. package/src/elements/gate/runtime.ts +7 -28
  502. package/src/elements/gate.ts +1 -5
  503. package/src/elements/index.ts +9 -7
  504. package/src/elements/signal/declare.ts +2 -7
  505. package/src/elements/signal/reconcile.test.ts +1 -4
  506. package/src/elements/signal/runtime.ts +1 -3
  507. package/src/elements/signal.test.ts +3 -15
  508. package/src/elements/signal.ts +2 -8
  509. package/src/elements/store/cache.test.ts +46 -0
  510. package/src/elements/store/cache.ts +3 -11
  511. package/src/elements/store/classify.ts +5 -22
  512. package/src/elements/store/declare.ts +11 -17
  513. package/src/elements/store/domain-ddl.test.ts +86 -0
  514. package/src/elements/store/emit-drizzle.ts +363 -0
  515. package/src/elements/store/files-policy.test.ts +1 -5
  516. package/src/elements/store/files-policy.ts +4 -12
  517. package/src/elements/store/load-plugin-tables.ts +103 -0
  518. package/src/elements/store/missing-relation.test.ts +83 -0
  519. package/src/elements/store/missing-relation.ts +38 -0
  520. package/src/elements/store/replica.ts +1 -4
  521. package/src/elements/store/resource-list-docs.fixture.ts +56 -0
  522. package/src/elements/store/resource-list-docs.test.ts +79 -0
  523. package/src/elements/store/resource.test.ts +253 -0
  524. package/src/elements/store/resource.ts +786 -0
  525. package/src/elements/store/runtime.ts +25 -28
  526. package/src/elements/store/schema-decl.test.ts +227 -0
  527. package/src/elements/store/schema-decl.ts +516 -0
  528. package/src/elements/store/sql-condition.test.ts +132 -0
  529. package/src/elements/store/sql-condition.ts +293 -65
  530. package/src/elements/store/sql-session.test.ts +135 -0
  531. package/src/elements/store/sql-session.ts +241 -84
  532. package/src/elements/store/table.ts +69 -23
  533. package/src/elements/store.test.ts +17 -39
  534. package/src/elements/store.ts +53 -31
  535. package/src/elements/vault/chain.ts +34 -0
  536. package/src/elements/vault/declare.ts +22 -32
  537. package/src/elements/vault/fingerprint.ts +2 -7
  538. package/src/elements/vault/redact.ts +2 -6
  539. package/src/elements/vault/runtime.ts +19 -33
  540. package/src/elements/vault.test.ts +12 -55
  541. package/src/elements/vault.ts +9 -13
  542. package/src/index.ts +5 -2
  543. package/src/kernel/adopt-routes.ts +15 -29
  544. package/src/kernel/app.ts +92 -118
  545. package/src/kernel/auth-resolve.ts +2 -9
  546. package/src/kernel/boot-bind/ai.ts +1 -4
  547. package/src/kernel/boot-bind/channel.test.ts +60 -0
  548. package/src/kernel/boot-bind/channel.ts +61 -5
  549. package/src/kernel/boot-bind/clock.ts +2 -6
  550. package/src/kernel/boot-bind/gate.ts +2 -8
  551. package/src/kernel/boot-bind/runs.ts +1 -3
  552. package/src/kernel/boot-bind/signal.ts +3 -10
  553. package/src/kernel/boot-bind/store.test.ts +27 -18
  554. package/src/kernel/boot-bind/store.ts +93 -52
  555. package/src/kernel/boot-bind/vault.ts +2 -8
  556. package/src/kernel/boot.test.ts +4 -10
  557. package/src/kernel/boot.ts +30 -77
  558. package/src/kernel/budget.test.ts +1 -3
  559. package/src/kernel/capability.ts +3 -10
  560. package/src/kernel/dry-run.test.ts +1 -4
  561. package/src/kernel/dry-run.ts +3 -11
  562. package/src/kernel/edge.test.ts +68 -0
  563. package/src/kernel/effects.test.ts +1 -5
  564. package/src/kernel/effects.ts +4 -11
  565. package/src/kernel/errors.registry.test.ts +2 -8
  566. package/src/kernel/errors.ts +23 -32
  567. package/src/kernel/flow.test.ts +12 -25
  568. package/src/kernel/flow.ts +13 -25
  569. package/src/kernel/fx.test.ts +31 -40
  570. package/src/kernel/fx.ts +135 -90
  571. package/src/kernel/hook-timing.test.ts +3 -6
  572. package/src/kernel/hook-timing.ts +5 -14
  573. package/src/kernel/hooks.test.ts +43 -10
  574. package/src/kernel/hooks.ts +25 -12
  575. package/src/kernel/index.ts +11 -17
  576. package/src/kernel/journal.ts +7 -31
  577. package/src/kernel/on.ts +45 -9
  578. package/src/kernel/pipeline.test.ts +10 -19
  579. package/src/kernel/pipeline.ts +5 -17
  580. package/src/kernel/plug.ts +4 -11
  581. package/src/kernel/plugin/conflicts.test.ts +13 -25
  582. package/src/kernel/plugin/decorate.test.ts +8 -13
  583. package/src/kernel/plugin/scoping.test.ts +4 -11
  584. package/src/kernel/plugin.ts +81 -27
  585. package/src/kernel/registry-isolation.test.ts +74 -0
  586. package/src/kernel/registry.ts +102 -30
  587. package/src/kernel/router.test.ts +15 -13
  588. package/src/kernel/router.ts +9 -29
  589. package/src/kernel/routing-budget.test.ts +1 -3
  590. package/src/kernel/run-telemetry.ts +1 -3
  591. package/src/kernel/triggers.ts +63 -21
  592. package/src/manifest/diff.test.ts +26 -91
  593. package/src/manifest/diff.ts +95 -225
  594. package/src/manifest/fixtures/skyport.excerpt.json +1 -1
  595. package/src/manifest/fixtures/skyport.manifest.json +1 -1
  596. package/src/manifest/index.ts +3 -10
  597. package/src/manifest/types.ts +30 -6
  598. package/src/manifest/undeclared.test.ts +4 -12
  599. package/src/manifest/undeclared.ts +1 -2
  600. package/src/manifest/validate.test.ts +2 -6
  601. package/src/manifest/validate.ts +5 -15
  602. package/src/mcp/authorization.ts +8 -27
  603. package/src/mcp/confirmation.ts +3 -10
  604. package/src/mcp/data.ts +2 -6
  605. package/src/mcp/docs-index.ts +4 -7
  606. package/src/mcp/docs-mcp.test.ts +3 -12
  607. package/src/mcp/docs-server.ts +7 -27
  608. package/src/mcp/docs-tools.ts +2 -6
  609. package/src/mcp/index.ts +1 -6
  610. package/src/mcp/injection.gate.test.ts +4 -18
  611. package/src/mcp/mcp.test.ts +18 -49
  612. package/src/mcp/protocol.ts +3 -10
  613. package/src/mcp/server.ts +11 -52
  614. package/src/mcp/session.ts +4 -14
  615. package/src/mcp/tools.ts +14 -50
  616. package/src/plugins/catalogue.test.ts +3 -7
  617. package/src/plugins/catalogue.ts +1 -3
  618. package/src/plugins/compression.test.ts +127 -0
  619. package/src/plugins/compression.ts +94 -0
  620. package/src/plugins/config-source.test.ts +204 -0
  621. package/src/plugins/config-source.ts +209 -0
  622. package/src/plugins/cors.test.ts +138 -0
  623. package/src/plugins/cors.ts +129 -0
  624. package/src/plugins/csrf.test.ts +102 -0
  625. package/src/plugins/csrf.ts +86 -0
  626. package/src/plugins/headers.ts +54 -0
  627. package/src/plugins/index.ts +26 -0
  628. package/src/plugins/ip-allowlist.test.ts +105 -0
  629. package/src/plugins/ip-allowlist.ts +76 -0
  630. package/src/plugins/maintenance-mode.test.ts +91 -0
  631. package/src/plugins/maintenance-mode.ts +85 -0
  632. package/src/plugins/node-import-scan.ts +2 -5
  633. package/src/plugins/security-headers.test.ts +243 -0
  634. package/src/plugins/security-headers.ts +255 -0
  635. package/src/plugins/supply-chain.ts +5 -17
  636. package/src/release/exports.ts +3 -8
  637. package/src/release/measure.exports.test.ts +1 -3
  638. package/src/release/measure.ts +16 -45
  639. package/src/runs/bench.test.ts +1 -3
  640. package/src/runs/collect.ts +8 -25
  641. package/src/runs/drivers/clickhouse.ts +2 -9
  642. package/src/runs/drivers/files.ts +9 -31
  643. package/src/runs/drivers/memory.ts +5 -22
  644. package/src/runs/drivers/postgres.ts +8 -20
  645. package/src/runs/duckdb.ts +2 -8
  646. package/src/runs/index.ts +3 -14
  647. package/src/runs/outlier.ts +3 -10
  648. package/src/runs/parquet.ts +8 -26
  649. package/src/runs/privacy.ts +2 -8
  650. package/src/runs/runs.test.ts +3 -9
  651. package/src/runs/runtime.ts +7 -32
  652. package/src/runs/shred.ts +10 -29
  653. package/src/runs/types.ts +1 -4
  654. package/src/runtime/bun.ts +4 -15
  655. package/src/runtime/cold-start.bench.ts +1 -3
  656. package/src/runtime/dev-request-log.test.ts +1 -4
  657. package/src/runtime/dev-request-log.ts +1 -4
  658. package/src/runtime/index.ts +1 -6
  659. package/src/runtime/primitives.ts +5 -4
  660. package/src/runtime/security.ts +3 -13
  661. package/src/runtime/serve.test.ts +4 -7
  662. package/src/runtime/types.ts +1 -4
  663. package/src/runtime/web-standard.ts +3 -15
  664. package/src/term.test.ts +4 -6
  665. package/src/term.ts +49 -98
  666. package/src/test/create-test-app.test.ts +4 -14
  667. package/src/test/create-test-app.ts +27 -33
  668. package/src/test/provisions.integration.test.ts +3 -11
  669. package/src/upgrade/codemods.test.ts +25 -6
  670. package/src/upgrade/codemods.ts +116 -3
  671. package/src/validation/standard-schema.test.ts +2 -5
  672. package/src/validation/standard-schema.ts +13 -33
  673. package/docs/spec/console.md +0 -739
  674. package/docs/spec/example.md +0 -1196
  675. package/docs/spec/four-applications.md +0 -1195
  676. package/docs/spec/unified-theory.md +0 -489
  677. package/src/cli/doc-drift.test.ts +0 -146
  678. package/src/cli/doc-drift.ts +0 -430
  679. package/src/cli/doctor-diff-examples.ts +0 -92
  680. package/src/console/ui/dist/assets/panel-vault-BbfWdox0.js +0 -1
  681. package/src/drivers/vault-sops.ts +0 -271
@@ -45,38 +45,47 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
45
45
  async query(sql, params = []) {
46
46
  const text = sql.trim();
47
47
 
48
+ const countStar =
49
+ /^SELECT\s+COUNT\(\*\)\s+AS\s+"?[a-zA-Z_][a-zA-Z0-9_]*"?\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?\s*$/i.exec(
50
+ text,
51
+ );
52
+ if (countStar) {
53
+ const table = getTable(parseIdent(countStar[1]!));
54
+ const whereClause = countStar[2]?.trim();
55
+ let rows = table.rows;
56
+ if (whereClause) {
57
+ const ast = parseWhere(whereClause);
58
+ rows = rows.filter((r) => evalWhere(ast, r, params, { i: 0 }));
59
+ }
60
+ return [{ count: rows.length }];
61
+ }
62
+
48
63
  const selectGeneric =
49
- /^SELECT\s+(.+?)\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?(?:\s+ORDER\s+BY\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?))?(?:\s+LIMIT\s+(\d+))?\s*$/i.exec(
64
+ /^SELECT\s+(.+?)\s+FROM\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(?:WHERE\s+(.+?))?(?:\s+ORDER\s+BY\s+(.+?))?(?:\s+LIMIT\s+(\d+))?(?:\s+OFFSET\s+(\d+))?\s*$/i.exec(
50
65
  text,
51
66
  );
52
67
  if (selectGeneric && !/^\s*1\s+AS\s+/i.test(selectGeneric[1]!)) {
53
68
  const table = getTable(parseIdent(selectGeneric[2]!));
54
69
  const selectList = selectGeneric[1]!.trim();
55
70
  const whereClause = selectGeneric[3]?.trim();
56
- const orderCol = selectGeneric[4]
57
- ? parseIdent(selectGeneric[4])
58
- : undefined;
59
- const limit = selectGeneric[5]
60
- ? Number(selectGeneric[5])
61
- : undefined;
71
+ const orderClause = selectGeneric[4]?.trim();
72
+ const limit = selectGeneric[5] ? Number(selectGeneric[5]) : undefined;
73
+ const offset = selectGeneric[6] ? Number(selectGeneric[6]) : undefined;
62
74
  let rows = table.rows.map((r) => ({ ...r }));
63
75
  if (whereClause) {
64
- const preds = parseWherePredicates(whereClause);
65
- rows = rows.filter((r) =>
66
- preds.every((p, i) => compareRow(r[p.column], params[i], p.op)),
67
- );
76
+ const ast = parseWhere(whereClause);
77
+ rows = rows.filter((r) => evalWhere(ast, r, params, { i: 0 }));
68
78
  }
69
- if (orderCol) {
70
- rows = [...rows].sort((a, b) =>
71
- String(a[orderCol] ?? "").localeCompare(String(b[orderCol] ?? "")),
72
- );
79
+ if (orderClause) {
80
+ const terms = parseOrderTerms(orderClause);
81
+ rows = [...rows].sort((a, b) => compareByTerms(a, b, terms));
73
82
  }
83
+ if (offset !== undefined) rows = rows.slice(offset);
74
84
  if (limit !== undefined) rows = rows.slice(0, limit);
75
85
  if (selectList === "*") return rows;
76
86
  const cols = selectList.split(",").map((part) => {
77
- const as = /^\s*("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+AS\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*$/i.exec(
78
- part,
79
- );
87
+ const as =
88
+ /^\s*("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+AS\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*$/i.exec(part);
80
89
  if (as) {
81
90
  return { sql: parseIdent(as[1]!), alias: parseIdent(as[2]!) };
82
91
  }
@@ -97,9 +106,7 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
97
106
  if (exists) {
98
107
  const table = getTable(parseIdent(exists[2]!));
99
108
  const preds = parseEqualityWhere(exists[3]!);
100
- const hit = table.rows.some((r) =>
101
- preds.every((p, i) => r[p] === params[i]),
102
- );
109
+ const hit = table.rows.some((r) => preds.every((p, i) => r[p] === params[i]));
103
110
  return hit ? [{ [parseIdent(exists[1]!)]: 1 }] : [];
104
111
  }
105
112
 
@@ -215,18 +222,14 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
215
222
  throw new Error(`memory sql: unsupported exec: ${sql}`);
216
223
  }
217
224
  const preds = parseEqualityWhere(updateIncAnd[4]!);
218
- const row = table.rows.find((r) =>
219
- preds.every((p, i) => r[p] === params[i]),
220
- );
225
+ const row = table.rows.find((r) => preds.every((p, i) => r[p] === params[i]));
221
226
  if (!row) return { changes: 0 };
222
227
  row[setCol] = Number(row[setCol] ?? 0) + 1;
223
228
  return { changes: 1 };
224
229
  }
225
230
 
226
231
  const updateSet =
227
- /^UPDATE\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+SET\s+(.+?)\s+WHERE\s+(.+)\s*$/i.exec(
228
- text,
229
- );
232
+ /^UPDATE\s+("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s+SET\s+(.+?)\s+WHERE\s+(.+)\s*$/i.exec(text);
230
233
  if (updateSet) {
231
234
  const table = getTable(parseIdent(updateSet[1]!));
232
235
  const setParts = updateSet[2]!.split(",").map((p) => p.trim());
@@ -235,12 +238,8 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
235
238
  if (!m) throw new Error(`memory sql: unsupported SET: ${part}`);
236
239
  return parseIdent(m[1]!);
237
240
  });
238
- const preds = parseWherePredicates(updateSet[3]!);
239
- const row = table.rows.find((r) =>
240
- preds.every((p, i) =>
241
- compareRow(r[p.column], params[setCols.length + i], p.op),
242
- ),
243
- );
241
+ const ast = parseWhere(updateSet[3]!);
242
+ const row = table.rows.find((r) => evalWhere(ast, r, params, { i: setCols.length }));
244
243
  if (!row) return { changes: 0 };
245
244
  setCols.forEach((col, i) => {
246
245
  row[col] = params[i];
@@ -256,60 +255,279 @@ function createMemorySqlConnection(role: "primary" | "replica"): SqlConnection {
256
255
  };
257
256
  }
258
257
 
259
- /** Parse `col = ? AND col2 = ?` into ordered column names. */
258
+ /** One comparison operator for the memory SQL driver. */
259
+ type WhereOp =
260
+ | "="
261
+ | "<"
262
+ | ">"
263
+ | "<="
264
+ | ">="
265
+ | "!="
266
+ | "like"
267
+ | "ilike"
268
+ | "in"
269
+ | "is null"
270
+ | "is not null";
271
+
272
+ /** WHERE condition AST node — leaf comparison or AND/OR group. */
273
+ type WhereNode =
274
+ | { readonly kind: "cmp"; readonly column: string; readonly op: WhereOp; readonly arity: number }
275
+ | { readonly kind: "and"; readonly children: readonly WhereNode[] }
276
+ | { readonly kind: "or"; readonly children: readonly WhereNode[] };
277
+
278
+ /** One `ORDER BY` term. */
279
+ interface OrderTerm {
280
+ readonly column: string;
281
+ readonly direction: "ASC" | "DESC";
282
+ }
283
+
284
+ /**
285
+ * Parse a WHERE clause into an AST. Supports parenthesized groups, `AND` /
286
+ * `OR`, binary comparisons, and `like` / `ilike` — the shapes the store
287
+ * session compiler emits. Anything else throws.
288
+ *
289
+ * @param clause - WHERE text (without the `WHERE` keyword)
290
+ */
291
+ function parseWhere(clause: string): WhereNode {
292
+ const tokens = tokenizeWhere(clause);
293
+ const unsupported = (): Error => new Error(`memory sql: unsupported WHERE: ${clause}`);
294
+ let pos = 0;
295
+
296
+ const peek = (): string | undefined => tokens[pos];
297
+ const parseLevel = (keyword: "AND" | "OR", down: () => WhereNode): WhereNode => {
298
+ const first = down();
299
+ if (peek()?.toUpperCase() !== keyword) return first;
300
+ const rest: WhereNode[] = [];
301
+ do {
302
+ pos++;
303
+ rest.push(down());
304
+ } while (peek()?.toUpperCase() === keyword);
305
+ const children = [first, ...rest];
306
+ return keyword === "AND" ? { kind: "and", children } : { kind: "or", children };
307
+ };
308
+ const parseFactor = (): WhereNode => {
309
+ if (peek() === "(") {
310
+ pos++;
311
+ const node = parseLevel("OR", () => parseLevel("AND", parseFactor));
312
+ if (peek() !== ")") throw unsupported();
313
+ pos++;
314
+ return node;
315
+ }
316
+ const colTok = tokens[pos++];
317
+ const opTok = tokens[pos++];
318
+ if (colTok === undefined || opTok === undefined) throw unsupported();
319
+ if (opTok.toLowerCase() === "is") {
320
+ const second = tokens[pos++]?.toLowerCase();
321
+ const nullOp =
322
+ second === "null"
323
+ ? "is null"
324
+ : second === "not" && tokens[pos++]?.toLowerCase() === "null"
325
+ ? "is not null"
326
+ : undefined;
327
+ if (nullOp === undefined) throw unsupported();
328
+ return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op: nullOp, arity: 0 };
329
+ }
330
+ if (opTok.toLowerCase() === "in") {
331
+ if (peek() !== "(") throw unsupported();
332
+ pos++;
333
+ let arity = 0;
334
+ while (peek() === "?") {
335
+ arity++;
336
+ pos++;
337
+ if (peek() === ",") pos++;
338
+ }
339
+ if (arity === 0 || peek() !== ")") throw unsupported();
340
+ pos++;
341
+ return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op: "in", arity };
342
+ }
343
+ const paramTok = tokens[pos++];
344
+ if (paramTok !== "?") throw unsupported();
345
+ const op = asWhereOp(opTok);
346
+ if (op === undefined) throw unsupported();
347
+ return { kind: "cmp", column: colTok.replaceAll('"', "").trim(), op, arity: 1 };
348
+ };
349
+
350
+ const node = parseLevel("OR", () => parseLevel("AND", parseFactor));
351
+ if (pos !== tokens.length) throw unsupported();
352
+ return node;
353
+ }
354
+
355
+ function tokenizeWhere(clause: string): string[] {
356
+ const out: string[] = [];
357
+ let i = 0;
358
+ while (i < clause.length) {
359
+ const ch = clause[i]!;
360
+ if (/\s/.test(ch)) {
361
+ i++;
362
+ continue;
363
+ }
364
+ if (ch === "(" || ch === ")" || ch === "?" || ch === ",") {
365
+ out.push(ch);
366
+ i++;
367
+ continue;
368
+ }
369
+ if (ch === '"') {
370
+ const end = clause.indexOf('"', i + 1);
371
+ if (end === -1) throw new Error(`memory sql: unsupported WHERE: ${clause}`);
372
+ out.push(clause.slice(i, end + 1));
373
+ i = end + 1;
374
+ continue;
375
+ }
376
+ const two = clause.slice(i, i + 2);
377
+ if (two === "<=" || two === ">=" || two === "<>" || two === "!=") {
378
+ out.push(two);
379
+ i += 2;
380
+ continue;
381
+ }
382
+ if (ch === "=" || ch === "<" || ch === ">") {
383
+ out.push(ch);
384
+ i++;
385
+ continue;
386
+ }
387
+ const word = /^[a-zA-Z_][a-zA-Z0-9_]*/.exec(clause.slice(i));
388
+ if (word) {
389
+ out.push(word[0]);
390
+ i += word[0].length;
391
+ continue;
392
+ }
393
+ throw new Error(`memory sql: unsupported WHERE: ${clause}`);
394
+ }
395
+ return out;
396
+ }
397
+
398
+ function asWhereOp(token: string): WhereOp | undefined {
399
+ switch (token.toLowerCase()) {
400
+ case "=":
401
+ return "=";
402
+ case "<":
403
+ return "<";
404
+ case ">":
405
+ return ">";
406
+ case "<=":
407
+ return "<=";
408
+ case ">=":
409
+ return ">=";
410
+ case "!=":
411
+ case "<>":
412
+ return "!=";
413
+ case "like":
414
+ return "like";
415
+ case "ilike":
416
+ return "ilike";
417
+ default:
418
+ return undefined;
419
+ }
420
+ }
421
+
422
+ /** Evaluate a WHERE AST against a row, consuming `?` params in order. */
423
+ function evalWhere(
424
+ node: WhereNode,
425
+ row: SqlRow,
426
+ params: readonly unknown[],
427
+ state: { i: number },
428
+ ): boolean {
429
+ if (node.kind === "and") {
430
+ return node.children.every((c) => evalWhere(c, row, params, state));
431
+ }
432
+ if (node.kind === "or") {
433
+ return node.children.some((c) => evalWhere(c, row, params, state));
434
+ }
435
+ if (node.op === "is null") {
436
+ return row[node.column] === null || row[node.column] === undefined;
437
+ }
438
+ if (node.op === "is not null") {
439
+ return row[node.column] !== null && row[node.column] !== undefined;
440
+ }
441
+ if (node.op === "in") {
442
+ const wants = params.slice(state.i, state.i + node.arity);
443
+ state.i += node.arity;
444
+ return wants.some((w) => compareRow(row[node.column], w, "="));
445
+ }
446
+ const want = params[state.i++];
447
+ return compareRow(row[node.column], want, node.op);
448
+ }
449
+
450
+ /** Parse `col = ? AND col2 = ?` into ordered column names (equality-only). */
260
451
  function parseEqualityWhere(clause: string): string[] {
261
- return parseWherePredicates(clause).map((p) => {
262
- if (p.op !== "=") {
452
+ const node = parseWhere(clause);
453
+ const cols: string[] = [];
454
+ const walk = (n: WhereNode): void => {
455
+ if (n.kind === "and") {
456
+ n.children.forEach(walk);
457
+ return;
458
+ }
459
+ if (n.kind === "or" || n.op !== "=") {
263
460
  throw new Error(`memory sql: unsupported WHERE: ${clause}`);
264
461
  }
265
- return p.column;
266
- });
462
+ cols.push(n.column);
463
+ };
464
+ walk(node);
465
+ return cols;
267
466
  }
268
467
 
269
- /** One WHERE predicate for the memory SQL driver. */
270
- interface WherePred {
271
- readonly column: string;
272
- readonly op: "=" | "<" | ">" | "<=" | ">=" | "!=";
468
+ /** Parse `"a" DESC, "b"` into ordered terms (default ASC). */
469
+ function parseOrderTerms(clause: string): OrderTerm[] {
470
+ return clause.split(",").map((part) => {
471
+ const m = /^\s*("?[a-zA-Z_][a-zA-Z0-9_]*"?)(?:\s+(ASC|DESC))?\s*$/i.exec(part);
472
+ if (!m) throw new Error(`memory sql: unsupported ORDER BY: ${clause}`);
473
+ return {
474
+ column: m[1]!.replaceAll('"', "").trim(),
475
+ direction: (m[2]?.toUpperCase() ?? "ASC") as OrderTerm["direction"],
476
+ };
477
+ });
273
478
  }
274
479
 
275
- /** Parse `col = ? AND col2 < ?` into ordered predicates. */
276
- function parseWherePredicates(clause: string): WherePred[] {
277
- return clause.split(/\s+AND\s+/i).map((part) => {
278
- const m =
279
- /^("?[a-zA-Z_][a-zA-Z0-9_]*"?)\s*(=|<=|>=|<>|!=|<|>)\s*\?$/.exec(
280
- part.trim(),
281
- );
282
- if (!m) throw new Error(`memory sql: unsupported WHERE: ${clause}`);
283
- const opRaw = m[2]!;
284
- const op: WherePred["op"] =
285
- opRaw === "<>" ? "!=" : (opRaw as WherePred["op"]);
286
- return { column: m[1]!.replaceAll('"', "").trim(), op };
287
- });
480
+ function compareByTerms(a: SqlRow, b: SqlRow, terms: readonly OrderTerm[]): number {
481
+ for (const term of terms) {
482
+ const av = a[term.column];
483
+ const bv = b[term.column];
484
+ let cmp: number;
485
+ if (typeof av === "number" && typeof bv === "number") {
486
+ cmp = av - bv;
487
+ } else {
488
+ cmp = String(av ?? "").localeCompare(String(bv ?? ""));
489
+ }
490
+ if (cmp !== 0) return term.direction === "DESC" ? -cmp : cmp;
491
+ }
492
+ return 0;
288
493
  }
289
494
 
290
- function compareRow(
291
- cell: unknown,
292
- want: unknown,
293
- op: WherePred["op"],
294
- ): boolean {
495
+ function compareRow(cell: unknown, want: unknown, op: WhereOp): boolean {
295
496
  if (op === "=") return cell === want;
296
497
  if (op === "!=") return cell !== want;
297
- const a = Number(cell ?? 0);
298
- const b = Number(want ?? 0);
498
+ // sqlite parity: LIKE is case-insensitive for ASCII; ILIKE matches it.
499
+ if (op === "like" || op === "ilike") return likeMatch(cell, want);
500
+ let cmp: number;
501
+ if (typeof cell === "number" && typeof want === "number") {
502
+ cmp = cell - want;
503
+ } else if (typeof cell === "string" && typeof want === "string") {
504
+ cmp = cell.localeCompare(want);
505
+ } else {
506
+ cmp = Number(cell ?? 0) - Number(want ?? 0);
507
+ }
299
508
  switch (op) {
300
509
  case "<":
301
- return a < b;
510
+ return cmp < 0;
302
511
  case ">":
303
- return a > b;
512
+ return cmp > 0;
304
513
  case "<=":
305
- return a <= b;
514
+ return cmp <= 0;
306
515
  case ">=":
307
- return a >= b;
516
+ return cmp >= 0;
308
517
  default:
309
518
  return false;
310
519
  }
311
520
  }
312
521
 
522
+ function likeMatch(cell: unknown, pattern: unknown): boolean {
523
+ const text = String(cell ?? "");
524
+ const source = String(pattern ?? "")
525
+ .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
526
+ .replace(/%/g, ".*")
527
+ .replace(/_/g, ".");
528
+ return new RegExp(`^${source}$`, "i").test(text);
529
+ }
530
+
313
531
  /** Memory SQL driver. */
314
532
  export const memorySqlDriver: SqlDriver = {
315
533
  id: "memory",
@@ -382,8 +600,7 @@ export const memoryFilesDriver: FilesDriver = {
382
600
  return {
383
601
  driverId: "memory",
384
602
  async put(key, data) {
385
- const bytes =
386
- typeof data === "string" ? new TextEncoder().encode(data) : data;
603
+ const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
387
604
  objects.set(prefix + key, bytes);
388
605
  },
389
606
  async get(key) {
@@ -425,17 +642,12 @@ export const memoryIndexDriver: IndexDriver = {
425
642
  id: "memory",
426
643
  facet: "index",
427
644
  async open(options: IndexOpenOptions): Promise<IndexStore> {
428
- const docs = new Map<
429
- string,
430
- { vector: number[]; meta?: Record<string, unknown> }
431
- >();
645
+ const docs = new Map<string, { vector: number[]; meta?: Record<string, unknown> }>();
432
646
  return {
433
647
  driverId: "memory",
434
648
  async upsert(id, vector, meta) {
435
649
  if (vector.length !== options.dims) {
436
- throw new Error(
437
- `vector dims ${vector.length} !== index dims ${options.dims}`,
438
- );
650
+ throw new Error(`vector dims ${vector.length} !== index dims ${options.dims}`);
439
651
  }
440
652
  docs.set(id, { vector: [...vector], meta });
441
653
  },
@@ -18,9 +18,7 @@ import type {
18
18
  *
19
19
  * @param options - Name / dims / SQL connection
20
20
  */
21
- export async function openPgvectorIndex(
22
- options: IndexOpenOptions,
23
- ): Promise<IndexStore> {
21
+ export async function openPgvectorIndex(options: IndexOpenOptions): Promise<IndexStore> {
24
22
  if (options.sql) {
25
23
  return openPgvectorSql(options.name, options.dims, options.sql);
26
24
  }
@@ -45,10 +43,11 @@ async function openPgvectorSql(
45
43
  throw new Error(`vector dims ${vector.length} !== index dims ${dims}`);
46
44
  }
47
45
  await sql.exec(`DELETE FROM "${table}" WHERE id = ?`, [id]);
48
- await sql.exec(
49
- `INSERT INTO "${table}" (id, embedding, meta) VALUES (?, ?, ?)`,
50
- [id, JSON.stringify(vector), meta ? JSON.stringify(meta) : null],
51
- );
46
+ await sql.exec(`INSERT INTO "${table}" (id, embedding, meta) VALUES (?, ?, ?)`, [
47
+ id,
48
+ JSON.stringify(vector),
49
+ meta ? JSON.stringify(meta) : null,
50
+ ]);
52
51
  },
53
52
  async search(vector, topK = 10): Promise<IndexHit[]> {
54
53
  const rows = await sql.query(`SELECT id, embedding, meta FROM "${table}"`);
@@ -78,10 +77,7 @@ async function openPgvectorSql(
78
77
  }
79
78
 
80
79
  function openPgvectorMemory(dims: number): IndexStore {
81
- const docs = new Map<
82
- string,
83
- { vector: number[]; meta?: Record<string, unknown> }
84
- >();
80
+ const docs = new Map<string, { vector: number[]; meta?: Record<string, unknown> }>();
85
81
  return {
86
82
  driverId: "pgvector",
87
83
  async upsert(id, vector, meta) {
@@ -4,16 +4,14 @@
4
4
  * Protocol-named: Neon, Supabase, RDS, Timescale all speak postgres.
5
5
  */
6
6
 
7
- import type {
8
- SqlConnectOptions,
9
- SqlConnection,
10
- SqlDriver,
11
- SqlRow,
12
- } from "./types.ts";
7
+ import type { SqlConnectOptions, SqlConnection, SqlDriver, SqlRow } from "./types.ts";
13
8
 
14
9
  /** Minimal surface we use from Bun.SQL (and test fakes). */
15
10
  export interface PostgresClientLike {
16
- unsafe(sql: string, values?: unknown[]): PromiseLike<SqlRow[] | { length: number; changes?: number } | SqlRow[]>;
11
+ unsafe(
12
+ sql: string,
13
+ values?: unknown[],
14
+ ): PromiseLike<SqlRow[] | { length: number; changes?: number } | SqlRow[]>;
17
15
  close?(options?: { timeout?: number }): Promise<void>;
18
16
  }
19
17
 
@@ -32,9 +30,7 @@ export function toPostgresParams(sql: string): string {
32
30
  *
33
31
  * @param options - URL / role / injected client
34
32
  */
35
- export async function connectPostgres(
36
- options: SqlConnectOptions = {},
37
- ): Promise<SqlConnection> {
33
+ export async function connectPostgres(options: SqlConnectOptions = {}): Promise<SqlConnection> {
38
34
  const role = options.role ?? "primary";
39
35
  const client =
40
36
  (options.client as PostgresClientLike | undefined) ??
@@ -121,9 +117,7 @@ export function createPostgresFakeClient(): PostgresClientLike & {
121
117
  if (exists) {
122
118
  const rows = tables.get(parseIdent(exists[2]!)) ?? [];
123
119
  const preds = parseEqualityWhere(exists[3]!);
124
- const hit = rows.some((r) =>
125
- preds.every((p, i) => r[p] === values[i]),
126
- );
120
+ const hit = rows.some((r) => preds.every((p, i) => r[p] === values[i]));
127
121
  return hit ? [{ [parseIdent(exists[1]!)]: 1 }] : [];
128
122
  }
129
123
 
@@ -5,24 +5,15 @@
5
5
  */
6
6
 
7
7
  import { LuaKvStore } from "./kv-lua.ts";
8
- import type {
9
- KvClientLike,
10
- KvDriver,
11
- KvNamespace,
12
- KvOpenOptions,
13
- } from "./types.ts";
8
+ import type { KvClientLike, KvDriver, KvNamespace, KvOpenOptions } from "./types.ts";
14
9
 
15
10
  /**
16
11
  * Open a KV namespace over the redis protocol.
17
12
  *
18
13
  * @param options - Name / URL / injected client
19
14
  */
20
- export async function openRedisKv(
21
- options: KvOpenOptions,
22
- ): Promise<KvNamespace> {
23
- const client: KvClientLike =
24
- options.client ??
25
- createBunRedisClient(options.url);
15
+ export async function openRedisKv(options: KvOpenOptions): Promise<KvNamespace> {
16
+ const client: KvClientLike = options.client ?? createBunRedisClient(options.url);
26
17
 
27
18
  const prefix = `oke:kv:${options.name}:`;
28
19
 
@@ -39,8 +30,7 @@ export async function openRedisKv(
39
30
  },
40
31
  async set(key, value, ttl) {
41
32
  const payload = JSON.stringify(value);
42
- const ex =
43
- ttl !== undefined ? Math.max(1, Math.ceil(ttlToSeconds(ttl))) : undefined;
33
+ const ex = ttl !== undefined ? Math.max(1, Math.ceil(ttlToSeconds(ttl))) : undefined;
44
34
  if (ex !== undefined) {
45
35
  await client.set(prefix + key, payload, { ex });
46
36
  } else {
@@ -70,11 +60,7 @@ export async function openRedisKv(
70
60
  return (await client.eval(script, prefixed.length, ...keysAndArgs)) as T;
71
61
  }
72
62
  if (client.send) {
73
- return (await client.send("EVAL", [
74
- script,
75
- String(prefixed.length),
76
- ...keysAndArgs,
77
- ])) as T;
63
+ return (await client.send("EVAL", [script, String(prefixed.length), ...keysAndArgs])) as T;
78
64
  }
79
65
  throw new Error("redis kv.eval: client lacks eval/send");
80
66
  },
@@ -90,10 +76,7 @@ export async function openRedisKv(
90
76
  * @param client - Redis-like client
91
77
  * @param match - MATCH pattern
92
78
  */
93
- async function scanAll(
94
- client: KvClientLike,
95
- match: string,
96
- ): Promise<string[]> {
79
+ async function scanAll(client: KvClientLike, match: string): Promise<string[]> {
97
80
  if (client.scan) {
98
81
  const out: string[] = [];
99
82
  let cursor = "0";
@@ -111,13 +94,10 @@ async function scanAll(
111
94
  const out: string[] = [];
112
95
  let cursor = "0";
113
96
  do {
114
- const reply = (await client.send("SCAN", [
115
- cursor,
116
- "MATCH",
117
- match,
118
- "COUNT",
119
- "100",
120
- ])) as [string, string[]];
97
+ const reply = (await client.send("SCAN", [cursor, "MATCH", match, "COUNT", "100"])) as [
98
+ string,
99
+ string[],
100
+ ];
121
101
  const next = String(reply[0]);
122
102
  const batch = reply[1] ?? [];
123
103
  out.push(...batch);
@@ -125,9 +105,7 @@ async function scanAll(
125
105
  } while (cursor !== "0");
126
106
  return out;
127
107
  }
128
- throw new Error(
129
- "redis kv.list: client lacks SCAN — key browse refused rather than KEYS *",
130
- );
108
+ throw new Error("redis kv.list: client lacks SCAN — key browse refused rather than KEYS *");
131
109
  }
132
110
 
133
111
  function ttlToSeconds(ttl: string): number {
@@ -159,8 +137,7 @@ function ttlToSeconds(ttl: string): number {
159
137
  * @param url - Optional Redis URL
160
138
  */
161
139
  export function createBunRedisClient(url?: string): KvClientLike {
162
- const redis =
163
- url !== undefined ? new Bun.RedisClient(url) : Bun.redis;
140
+ const redis = url !== undefined ? new Bun.RedisClient(url) : Bun.redis;
164
141
 
165
142
  return {
166
143
  get: (key) => redis.get(key),
@@ -224,8 +201,7 @@ export function createRedisFakeClient(nowMs?: () => number): KvClientLike & {
224
201
  },
225
202
  async scan(cursor, opts) {
226
203
  const match = opts?.match ?? "*";
227
- const prefix =
228
- match.endsWith("*") ? match.slice(0, -1) : match;
204
+ const prefix = match.endsWith("*") ? match.slice(0, -1) : match;
229
205
  const all = [...data.keys()].filter((k) =>
230
206
  match.endsWith("*") ? k.startsWith(prefix) : k === match,
231
207
  );