alepha 0.18.2 → 0.18.3

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 (397) hide show
  1. package/assets/devtools-ui/200.html +2 -2
  2. package/assets/devtools-ui/200.html.br +0 -0
  3. package/assets/devtools-ui/404.html +2 -2
  4. package/assets/devtools-ui/404.html.br +0 -0
  5. package/assets/devtools-ui/{asset.BfSBZ5Dd.css → asset.hG_f8HuK.css} +1 -1
  6. package/assets/devtools-ui/asset.hG_f8HuK.css.br +0 -0
  7. package/assets/devtools-ui/chunk.B3au4Lhg.js +1 -0
  8. package/assets/devtools-ui/chunk.B3au4Lhg.js.br +0 -0
  9. package/assets/devtools-ui/chunk.BLOrlnMB.js +1 -0
  10. package/assets/devtools-ui/chunk.BLOrlnMB.js.br +0 -0
  11. package/assets/devtools-ui/chunk.BLR01ljW.js +1 -0
  12. package/assets/devtools-ui/chunk.BLR01ljW.js.br +0 -0
  13. package/assets/devtools-ui/chunk.BTXaIUlA.js +1 -0
  14. package/assets/devtools-ui/chunk.BTXaIUlA.js.br +0 -0
  15. package/assets/devtools-ui/{chunk.lJL-lgnW.js → chunk.BhJaxmm8.js} +1 -1
  16. package/assets/devtools-ui/chunk.BhJaxmm8.js.br +0 -0
  17. package/assets/devtools-ui/chunk.BtoNxFuL.js +1 -0
  18. package/assets/devtools-ui/chunk.BtoNxFuL.js.br +0 -0
  19. package/assets/devtools-ui/chunk.C8YUV2Wd.js +1 -0
  20. package/assets/devtools-ui/chunk.C8YUV2Wd.js.br +0 -0
  21. package/assets/devtools-ui/{chunk.M6wyKO_3.js → chunk.CBbIgDzE.js} +2 -2
  22. package/assets/devtools-ui/chunk.CBbIgDzE.js.br +0 -0
  23. package/assets/devtools-ui/chunk.CFqIniwA.js +1 -0
  24. package/assets/devtools-ui/chunk.CFqIniwA.js.br +0 -0
  25. package/assets/devtools-ui/chunk.CLFF7f7-.js +1 -0
  26. package/assets/devtools-ui/chunk.CLFF7f7-.js.br +0 -0
  27. package/assets/devtools-ui/chunk.CRsBbA10.js +1 -0
  28. package/assets/devtools-ui/chunk.CRsBbA10.js.br +0 -0
  29. package/assets/devtools-ui/{chunk.DbEH1oOB.js → chunk.CZPo6v95.js} +1 -1
  30. package/assets/devtools-ui/chunk.CZPo6v95.js.br +0 -0
  31. package/assets/devtools-ui/chunk.D0fWgNos.js +1 -0
  32. package/assets/devtools-ui/chunk.D0fWgNos.js.br +1 -0
  33. package/assets/devtools-ui/chunk.D7-0ziQ6.js +1 -0
  34. package/assets/devtools-ui/chunk.D7-0ziQ6.js.br +0 -0
  35. package/assets/devtools-ui/chunk.DAewe0vm.js +1 -0
  36. package/assets/devtools-ui/chunk.DAewe0vm.js.br +0 -0
  37. package/assets/devtools-ui/chunk.DJRQEYqK.js +1 -0
  38. package/assets/devtools-ui/chunk.DJRQEYqK.js.br +0 -0
  39. package/assets/devtools-ui/{chunk.CZl6J9DF.js → chunk.DMAxv14p.js} +1 -1
  40. package/assets/devtools-ui/chunk.DMAxv14p.js.br +0 -0
  41. package/assets/devtools-ui/{chunk.BT2IiBkZ.js → chunk.DMImnNjU.js} +1 -1
  42. package/assets/devtools-ui/chunk.DMImnNjU.js.br +0 -0
  43. package/assets/devtools-ui/chunk.DeeQsidk.js +9 -0
  44. package/assets/devtools-ui/chunk.DeeQsidk.js.br +0 -0
  45. package/assets/devtools-ui/chunk.DqEwn9Vj.js +7 -0
  46. package/assets/devtools-ui/chunk.DqEwn9Vj.js.br +0 -0
  47. package/assets/devtools-ui/chunk.Dt8OsQey.js +1 -0
  48. package/assets/devtools-ui/chunk.Dt8OsQey.js.br +0 -0
  49. package/assets/devtools-ui/{chunk.B9pX3zit.js → chunk.Dtp8oa_f.js} +1 -1
  50. package/assets/devtools-ui/chunk.Dtp8oa_f.js.br +0 -0
  51. package/assets/devtools-ui/chunk.Dx3JzAYM.js +1 -0
  52. package/assets/devtools-ui/chunk.Dx3JzAYM.js.br +0 -0
  53. package/assets/devtools-ui/chunk.GCOj1-5E.js +1 -0
  54. package/assets/devtools-ui/chunk.GCOj1-5E.js.br +0 -0
  55. package/assets/devtools-ui/chunk.IC1LD8BH.js +1 -0
  56. package/assets/devtools-ui/chunk.IC1LD8BH.js.br +0 -0
  57. package/assets/devtools-ui/chunk.IwuB_TqW.js +1 -0
  58. package/assets/devtools-ui/chunk.IwuB_TqW.js.br +0 -0
  59. package/assets/devtools-ui/chunk.Qqapj2zq.js +1 -0
  60. package/assets/devtools-ui/chunk.Qqapj2zq.js.br +0 -0
  61. package/assets/devtools-ui/{chunk.C79YouPp.js → chunk.TKKKndOy.js} +1 -1
  62. package/assets/devtools-ui/chunk.TKKKndOy.js.br +0 -0
  63. package/assets/devtools-ui/chunk.YHTVhFQT.js +1 -0
  64. package/assets/devtools-ui/chunk.YHTVhFQT.js.br +0 -0
  65. package/assets/devtools-ui/chunk.fnod6uEi.js +1 -0
  66. package/assets/devtools-ui/chunk.fnod6uEi.js.br +0 -0
  67. package/assets/devtools-ui/chunk.mOCRmXjo.js +1 -0
  68. package/assets/devtools-ui/chunk.mOCRmXjo.js.br +0 -0
  69. package/assets/devtools-ui/chunk.qZTNEAK0.js +1 -0
  70. package/assets/devtools-ui/chunk.qZTNEAK0.js.br +0 -0
  71. package/assets/devtools-ui/chunk.rc9m0y4-.js +1 -0
  72. package/assets/devtools-ui/chunk.rc9m0y4-.js.br +0 -0
  73. package/assets/devtools-ui/entry.Cxc5QLCU.js +80 -0
  74. package/assets/devtools-ui/entry.Cxc5QLCU.js.br +0 -0
  75. package/assets/devtools-ui/index.html +2 -2
  76. package/assets/devtools-ui/index.html.br +0 -0
  77. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  78. package/assets/swagger-ui/swagger-ui.css +1 -1
  79. package/dist/api/audits/index.d.ts +61 -5
  80. package/dist/api/audits/index.d.ts.map +1 -1
  81. package/dist/api/files/index.d.ts +61 -5
  82. package/dist/api/files/index.d.ts.map +1 -1
  83. package/dist/api/jobs/index.d.ts +61 -5
  84. package/dist/api/jobs/index.d.ts.map +1 -1
  85. package/dist/api/jobs/index.js +4 -2
  86. package/dist/api/jobs/index.js.map +1 -1
  87. package/dist/api/keys/index.d.ts +5 -5
  88. package/dist/api/notifications/index.browser.js +44 -1
  89. package/dist/api/notifications/index.browser.js.map +1 -1
  90. package/dist/api/notifications/index.d.ts +187 -2
  91. package/dist/api/notifications/index.d.ts.map +1 -1
  92. package/dist/api/notifications/index.js +143 -8
  93. package/dist/api/notifications/index.js.map +1 -1
  94. package/dist/api/parameters/index.d.ts +61 -5
  95. package/dist/api/parameters/index.d.ts.map +1 -1
  96. package/dist/api/users/index.d.ts +330 -93
  97. package/dist/api/users/index.d.ts.map +1 -1
  98. package/dist/api/users/index.js +27 -36
  99. package/dist/api/users/index.js.map +1 -1
  100. package/dist/cli/config/index.d.ts +46 -0
  101. package/dist/cli/config/index.d.ts.map +1 -0
  102. package/dist/cli/config/index.js +20 -0
  103. package/dist/cli/config/index.js.map +1 -0
  104. package/dist/cli/core/index.d.ts +69 -66
  105. package/dist/cli/core/index.d.ts.map +1 -1
  106. package/dist/cli/core/index.js +329 -196
  107. package/dist/cli/core/index.js.map +1 -1
  108. package/dist/cli/platform/index.d.ts +302 -63
  109. package/dist/cli/platform/index.d.ts.map +1 -1
  110. package/dist/cli/platform/index.js +455 -25
  111. package/dist/cli/platform/index.js.map +1 -1
  112. package/dist/core/index.browser.js +125 -87
  113. package/dist/core/index.browser.js.map +1 -1
  114. package/dist/core/index.d.ts +62 -53
  115. package/dist/core/index.d.ts.map +1 -1
  116. package/dist/core/index.js +125 -87
  117. package/dist/core/index.js.map +1 -1
  118. package/dist/core/index.native.js +125 -87
  119. package/dist/core/index.native.js.map +1 -1
  120. package/dist/core/index.workerd.js +125 -87
  121. package/dist/core/index.workerd.js.map +1 -1
  122. package/dist/crypto/index.d.ts +18 -1
  123. package/dist/crypto/index.d.ts.map +1 -1
  124. package/dist/crypto/index.js +29 -3
  125. package/dist/crypto/index.js.map +1 -1
  126. package/dist/devtools/index.js +3 -12
  127. package/dist/devtools/index.js.map +1 -1
  128. package/dist/logger/index.d.ts +10 -1
  129. package/dist/logger/index.d.ts.map +1 -1
  130. package/dist/logger/index.js +19 -9
  131. package/dist/logger/index.js.map +1 -1
  132. package/dist/orm/core/index.browser.js +57 -1
  133. package/dist/orm/core/index.browser.js.map +1 -1
  134. package/dist/orm/core/index.bun.js +378 -19
  135. package/dist/orm/core/index.bun.js.map +1 -1
  136. package/dist/orm/core/index.d.ts +328 -9
  137. package/dist/orm/core/index.d.ts.map +1 -1
  138. package/dist/orm/core/index.js +384 -21
  139. package/dist/orm/core/index.js.map +1 -1
  140. package/dist/orm/postgres/index.bun.js +49 -17
  141. package/dist/orm/postgres/index.bun.js.map +1 -1
  142. package/dist/orm/postgres/index.d.ts +47 -21
  143. package/dist/orm/postgres/index.d.ts.map +1 -1
  144. package/dist/orm/postgres/index.js +52 -17
  145. package/dist/orm/postgres/index.js.map +1 -1
  146. package/dist/react/core/index.d.ts +1 -1
  147. package/dist/react/core/index.d.ts.map +1 -1
  148. package/dist/react/core/index.js +6 -1
  149. package/dist/react/core/index.js.map +1 -1
  150. package/dist/react/form/index.d.ts +28 -18
  151. package/dist/react/form/index.d.ts.map +1 -1
  152. package/dist/react/form/index.js +92 -56
  153. package/dist/react/form/index.js.map +1 -1
  154. package/dist/react/router/index.browser.js +448 -116
  155. package/dist/react/router/index.browser.js.map +1 -1
  156. package/dist/react/router/index.d.ts +102 -40
  157. package/dist/react/router/index.d.ts.map +1 -1
  158. package/dist/react/router/index.js +453 -92
  159. package/dist/react/router/index.js.map +1 -1
  160. package/dist/security/index.d.ts +3 -11
  161. package/dist/security/index.d.ts.map +1 -1
  162. package/dist/security/index.js +6 -11
  163. package/dist/security/index.js.map +1 -1
  164. package/dist/server/auth/index.d.ts +22 -24
  165. package/dist/server/auth/index.d.ts.map +1 -1
  166. package/dist/server/auth/index.js +102 -82
  167. package/dist/server/auth/index.js.map +1 -1
  168. package/dist/server/cookies/index.d.ts +7 -4
  169. package/dist/server/cookies/index.d.ts.map +1 -1
  170. package/dist/server/cookies/index.js +13 -12
  171. package/dist/server/cookies/index.js.map +1 -1
  172. package/dist/server/core/index.d.ts +288 -4
  173. package/dist/server/core/index.d.ts.map +1 -1
  174. package/dist/server/core/index.js +375 -2
  175. package/dist/server/core/index.js.map +1 -1
  176. package/dist/server/links/index.browser.js +10 -71
  177. package/dist/server/links/index.browser.js.map +1 -1
  178. package/dist/server/links/index.d.ts +32 -49
  179. package/dist/server/links/index.d.ts.map +1 -1
  180. package/dist/server/links/index.js +73 -100
  181. package/dist/server/links/index.js.map +1 -1
  182. package/dist/system/index.browser.js +221 -2
  183. package/dist/system/index.browser.js.map +1 -1
  184. package/dist/system/index.d.ts +63 -1
  185. package/dist/system/index.d.ts.map +1 -1
  186. package/dist/system/index.js +221 -1
  187. package/dist/system/index.js.map +1 -1
  188. package/dist/system/index.workerd.js +224 -4
  189. package/dist/system/index.workerd.js.map +1 -1
  190. package/package.json +10 -5
  191. package/src/api/jobs/providers/JobProvider.ts +6 -3
  192. package/src/api/notifications/controllers/AdminNotificationController.ts +83 -0
  193. package/src/api/notifications/index.browser.ts +3 -0
  194. package/src/api/notifications/index.ts +14 -2
  195. package/src/api/notifications/jobs/NotificationJobs.ts +11 -2
  196. package/src/api/notifications/schemas/notificationDetailResourceSchema.ts +20 -0
  197. package/src/api/notifications/schemas/notificationQuerySchema.ts +19 -0
  198. package/src/api/notifications/schemas/notificationResourceSchema.ts +18 -0
  199. package/src/api/notifications/services/NotificationSenderService.ts +15 -2
  200. package/src/api/users/atoms/realmAuthSettingsAtom.ts +28 -32
  201. package/src/api/users/buckets/UserBuckets.ts +1 -1
  202. package/src/api/users/jobs/UserJobs.ts +1 -1
  203. package/src/api/users/primitives/$realm.ts +8 -49
  204. package/src/api/users/providers/RealmProvider.ts +2 -3
  205. package/src/api/users/services/RegistrationService.spec.ts +7 -7
  206. package/src/api/users/services/RegistrationService.ts +3 -3
  207. package/src/api/users/services/SessionService.spec.ts +4 -4
  208. package/src/api/users/services/SessionService.ts +3 -3
  209. package/src/cli/{core → config}/defineConfig.ts +14 -20
  210. package/src/cli/config/index.ts +1 -0
  211. package/src/cli/core/commands/db.ts +65 -1
  212. package/src/cli/core/commands/dev.ts +1 -0
  213. package/src/cli/core/commands/init.ts +2 -192
  214. package/src/cli/core/index.ts +34 -11
  215. package/src/cli/core/providers/ViteDevServerProvider.ts +52 -13
  216. package/src/cli/core/services/PackageManagerUtils.ts +43 -21
  217. package/src/cli/core/services/ProjectScaffolder.ts +214 -2
  218. package/src/cli/core/services/ViteUtils.ts +57 -0
  219. package/src/cli/core/tasks/BuildClientTask.ts +7 -2
  220. package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -12
  221. package/src/cli/core/tasks/BuildServerTask.ts +2 -0
  222. package/src/cli/core/tasks/BuildVercelTask.ts +165 -168
  223. package/src/cli/core/templates/alephaConfigTs.ts +1 -1
  224. package/src/cli/core/templates/apiAppSecurityTs.ts +5 -8
  225. package/src/cli/core/templates/tsconfigJson.ts +6 -1
  226. package/src/cli/platform/adapters/CloudflareAdapter.spec.ts +1 -1
  227. package/src/cli/platform/adapters/CloudflareAdapter.ts +30 -29
  228. package/src/cli/platform/atoms/platformOptions.ts +21 -0
  229. package/src/cli/platform/commands/SecretsCommand.spec.ts +298 -0
  230. package/src/cli/platform/commands/SecretsCommand.ts +283 -0
  231. package/src/cli/platform/commands/platform.ts +12 -0
  232. package/src/cli/platform/index.ts +14 -28
  233. package/src/cli/platform/providers/GitHubSecretStore.spec.ts +153 -0
  234. package/src/cli/platform/providers/GitHubSecretStore.ts +112 -0
  235. package/src/cli/platform/providers/MemorySecretStore.ts +114 -0
  236. package/src/cli/platform/providers/SecretStoreProvider.ts +39 -0
  237. package/src/cli/platform/schemas/cloudflare.ts +2 -0
  238. package/src/cli/platform/services/CloudflareApi.ts +5 -2
  239. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +115 -0
  240. package/src/cli/platform/services/DockerComposeGenerator.ts +46 -1
  241. package/src/cli/platform/services/SecretFilterService.spec.ts +111 -0
  242. package/src/cli/platform/services/SecretFilterService.ts +54 -0
  243. package/src/core/Alepha.ts +94 -25
  244. package/src/core/__tests__/Alepha-parseEnv.spec.ts +20 -0
  245. package/src/core/primitives/$memoize.ts +38 -26
  246. package/src/core/providers/AlsProvider.ts +2 -0
  247. package/src/core/providers/EventManager.ts +4 -0
  248. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +1 -4
  249. package/src/core/providers/KeylessJsonSchemaCodec.ts +19 -125
  250. package/src/core/providers/SchemaValidator.spec.ts +36 -0
  251. package/src/core/providers/SchemaValidator.ts +9 -0
  252. package/src/crypto/index.ts +6 -1
  253. package/src/crypto/providers/SecretProvider.ts +36 -0
  254. package/src/devtools/providers/DevToolsProvider.ts +3 -12
  255. package/src/logger/index.ts +33 -6
  256. package/src/logger/providers/PrettyFormatterProvider.ts +5 -3
  257. package/src/orm/__tests__/orm-next-tests.ts +492 -0
  258. package/src/orm/__tests__/orm-next.spec.ts +140 -0
  259. package/src/orm/core/constants/PG_SYMBOLS.ts +17 -0
  260. package/src/orm/core/index.bun.ts +3 -6
  261. package/src/orm/core/index.shared-server.ts +2 -0
  262. package/src/orm/core/index.shared.ts +2 -0
  263. package/src/orm/core/index.ts +5 -7
  264. package/src/orm/core/interfaces/AggregateQuery.ts +103 -0
  265. package/src/orm/core/interfaces/PgQueryWhere.ts +7 -0
  266. package/src/orm/core/primitives/$entity.ts +8 -0
  267. package/src/orm/core/primitives/$repository.ts +6 -3
  268. package/src/orm/core/primitives/$view.ts +88 -0
  269. package/src/orm/core/providers/DbCacheProvider.ts +66 -0
  270. package/src/orm/core/providers/DrizzleKitProvider.ts +42 -0
  271. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -3
  272. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +12 -0
  273. package/src/orm/core/providers/drivers/DatabaseProvider.ts +39 -0
  274. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +2 -3
  275. package/src/orm/core/schemas/databaseEnvSchema.ts +31 -0
  276. package/src/orm/core/schemas/insertSchema.ts +13 -3
  277. package/src/orm/core/schemas/updateSchema.ts +14 -3
  278. package/src/orm/core/services/ModelBuilder.ts +26 -14
  279. package/src/orm/core/services/QueryManager.ts +13 -0
  280. package/src/orm/core/services/Repository.ts +307 -5
  281. package/src/orm/core/services/SqliteModelBuilder.ts +38 -0
  282. package/src/orm/postgres/index.bun.ts +4 -7
  283. package/src/orm/postgres/index.ts +4 -7
  284. package/src/orm/postgres/providers/BunPostgresProvider.ts +12 -2
  285. package/src/orm/postgres/providers/NodePostgresProvider.ts +7 -0
  286. package/src/orm/postgres/providers/PglitePostgresProvider.ts +10 -17
  287. package/src/orm/postgres/providers/PostgresProvider.ts +7 -36
  288. package/src/orm/postgres/schemas/postgresEnvSchema.ts +32 -0
  289. package/src/orm/postgres/services/PostgresModelBuilder.ts +40 -0
  290. package/src/react/core/components/ErrorBoundary.tsx +5 -2
  291. package/src/react/form/hooks/useFieldValue.ts +34 -0
  292. package/src/react/form/hooks/useForm.browser.spec.tsx +94 -9
  293. package/src/react/form/hooks/useForm.ts +14 -2
  294. package/src/react/form/hooks/useFormState.ts +10 -10
  295. package/src/react/form/hooks/useFormValues.ts +29 -0
  296. package/src/react/form/index.ts +3 -1
  297. package/src/react/form/services/FormModel.ts +53 -122
  298. package/src/react/router/components/ErrorViewer.tsx +333 -34
  299. package/src/react/router/components/NestedView.tsx +10 -3
  300. package/src/react/router/primitives/$page.browser.spec.tsx +34 -0
  301. package/src/react/router/primitives/$page.spec.tsx +20 -0
  302. package/src/react/router/primitives/$page.ts +24 -0
  303. package/src/react/router/providers/ReactBrowserRouterProvider.ts +14 -2
  304. package/src/react/router/providers/ReactPageProvider.ts +156 -73
  305. package/src/react/router/providers/ReactServerProvider.ts +40 -2
  306. package/src/react/router/providers/ReactServerTemplateProvider.ts +13 -1
  307. package/src/security/providers/SecurityProvider.ts +5 -27
  308. package/src/server/auth/primitives/$auth.ts +52 -19
  309. package/src/server/auth/providers/ServerAuthProvider.ts +145 -139
  310. package/src/server/cookies/providers/ServerCookiesProvider.ts +12 -24
  311. package/src/server/core/index.ts +3 -1
  312. package/src/server/core/primitives/$sse.spec.ts +315 -0
  313. package/src/server/core/primitives/$sse.ts +715 -0
  314. package/src/server/links/index.browser.ts +1 -3
  315. package/src/server/links/index.ts +0 -3
  316. package/src/server/links/providers/LinkProvider.spec.ts +12 -21
  317. package/src/server/links/providers/LinkProvider.ts +20 -52
  318. package/src/server/links/providers/ServerLinksProvider.spec.ts +106 -0
  319. package/src/server/links/providers/ServerLinksProvider.ts +113 -73
  320. package/src/server/links/schemas/apiLinksResponseSchema.ts +4 -21
  321. package/src/server/links/services/BatchCollector.ts +5 -3
  322. package/src/system/index.browser.ts +1 -0
  323. package/src/system/index.ts +3 -0
  324. package/src/system/index.workerd.ts +39 -1
  325. package/src/system/providers/WorkerdFileSystemProvider.ts +365 -0
  326. package/assets/devtools-ui/asset.BfSBZ5Dd.css.br +0 -0
  327. package/assets/devtools-ui/chunk.2NYaoqWt.js +0 -1
  328. package/assets/devtools-ui/chunk.2NYaoqWt.js.br +0 -0
  329. package/assets/devtools-ui/chunk.B052Z_xQ.js +0 -1
  330. package/assets/devtools-ui/chunk.B052Z_xQ.js.br +0 -0
  331. package/assets/devtools-ui/chunk.B4kVY90C.js +0 -1
  332. package/assets/devtools-ui/chunk.B4kVY90C.js.br +0 -0
  333. package/assets/devtools-ui/chunk.B7QJXctB.js +0 -1
  334. package/assets/devtools-ui/chunk.B7QJXctB.js.br +0 -0
  335. package/assets/devtools-ui/chunk.B9pX3zit.js.br +0 -0
  336. package/assets/devtools-ui/chunk.BKF9JxIo.js +0 -1
  337. package/assets/devtools-ui/chunk.BKF9JxIo.js.br +0 -0
  338. package/assets/devtools-ui/chunk.BOHgdTP-.js +0 -1
  339. package/assets/devtools-ui/chunk.BOHgdTP-.js.br +0 -0
  340. package/assets/devtools-ui/chunk.BOVFxkYC.js +0 -1
  341. package/assets/devtools-ui/chunk.BOVFxkYC.js.br +0 -0
  342. package/assets/devtools-ui/chunk.BR842zj5.js +0 -1
  343. package/assets/devtools-ui/chunk.BR842zj5.js.br +0 -0
  344. package/assets/devtools-ui/chunk.BT2IiBkZ.js.br +0 -0
  345. package/assets/devtools-ui/chunk.C79YouPp.js.br +0 -0
  346. package/assets/devtools-ui/chunk.C8mlBrjW.js +0 -9
  347. package/assets/devtools-ui/chunk.C8mlBrjW.js.br +0 -0
  348. package/assets/devtools-ui/chunk.CK0ow3AZ.js +0 -1
  349. package/assets/devtools-ui/chunk.CK0ow3AZ.js.br +0 -0
  350. package/assets/devtools-ui/chunk.CZl6J9DF.js.br +0 -0
  351. package/assets/devtools-ui/chunk.CdNr0YzS.js +0 -1
  352. package/assets/devtools-ui/chunk.CdNr0YzS.js.br +0 -0
  353. package/assets/devtools-ui/chunk.Ce6_6iIF.js +0 -1
  354. package/assets/devtools-ui/chunk.Ce6_6iIF.js.br +0 -0
  355. package/assets/devtools-ui/chunk.CpyDMr6O.js +0 -1
  356. package/assets/devtools-ui/chunk.CpyDMr6O.js.br +0 -0
  357. package/assets/devtools-ui/chunk.CyPmvPnY.js +0 -1
  358. package/assets/devtools-ui/chunk.CyPmvPnY.js.br +0 -0
  359. package/assets/devtools-ui/chunk.DTI_geWu.js +0 -1
  360. package/assets/devtools-ui/chunk.DTI_geWu.js.br +0 -0
  361. package/assets/devtools-ui/chunk.DbEH1oOB.js.br +0 -0
  362. package/assets/devtools-ui/chunk.Ddeqj5gv.js +0 -1
  363. package/assets/devtools-ui/chunk.Ddeqj5gv.js.br +0 -0
  364. package/assets/devtools-ui/chunk.DpRnB4vJ.js +0 -1
  365. package/assets/devtools-ui/chunk.DpRnB4vJ.js.br +0 -0
  366. package/assets/devtools-ui/chunk.DxPGTlsg.js +0 -1
  367. package/assets/devtools-ui/chunk.DxPGTlsg.js.br +0 -0
  368. package/assets/devtools-ui/chunk.G7_MMBJS.js +0 -1
  369. package/assets/devtools-ui/chunk.G7_MMBJS.js.br +0 -0
  370. package/assets/devtools-ui/chunk.M6wyKO_3.js.br +0 -0
  371. package/assets/devtools-ui/chunk.OUxNGmQ6.js +0 -1
  372. package/assets/devtools-ui/chunk.OUxNGmQ6.js.br +0 -0
  373. package/assets/devtools-ui/chunk.T1kle-fF.js +0 -1
  374. package/assets/devtools-ui/chunk.T1kle-fF.js.br +0 -0
  375. package/assets/devtools-ui/chunk.WjpsbQAv.js +0 -1
  376. package/assets/devtools-ui/chunk.WjpsbQAv.js.br +0 -0
  377. package/assets/devtools-ui/chunk.c6YgVx86.js +0 -1
  378. package/assets/devtools-ui/chunk.c6YgVx86.js.br +0 -0
  379. package/assets/devtools-ui/chunk.dwU3E_MU.js +0 -1
  380. package/assets/devtools-ui/chunk.dwU3E_MU.js.br +0 -0
  381. package/assets/devtools-ui/chunk.lJL-lgnW.js.br +0 -0
  382. package/assets/devtools-ui/chunk.lPWRmvA-.js +0 -7
  383. package/assets/devtools-ui/chunk.lPWRmvA-.js.br +0 -0
  384. package/assets/devtools-ui/chunk.p3HJvugM.js +0 -1
  385. package/assets/devtools-ui/chunk.p3HJvugM.js.br +0 -0
  386. package/assets/devtools-ui/chunk.r_Xoa_CI.js +0 -1
  387. package/assets/devtools-ui/chunk.r_Xoa_CI.js.br +0 -0
  388. package/assets/devtools-ui/chunk.sRNuTYXb.js +0 -1
  389. package/assets/devtools-ui/chunk.sRNuTYXb.js.br +0 -0
  390. package/assets/devtools-ui/chunk.tUjcyX5C.js +0 -1
  391. package/assets/devtools-ui/chunk.tUjcyX5C.js.br +0 -0
  392. package/assets/devtools-ui/chunk.thjBxvCA.js +0 -1
  393. package/assets/devtools-ui/chunk.thjBxvCA.js.br +0 -0
  394. package/assets/devtools-ui/entry.GYhBVRpC.js +0 -78
  395. package/assets/devtools-ui/entry.GYhBVRpC.js.br +0 -0
  396. package/src/server/links/services/DefinitionsPool.spec.ts +0 -86
  397. package/src/server/links/services/DefinitionsPool.ts +0 -43
@@ -13,10 +13,12 @@ export * from "./primitives/$repository.ts";
13
13
  export * from "./primitives/$seed.ts";
14
14
  export * from "./primitives/$sequence.ts";
15
15
  export * from "./primitives/$transactional.ts";
16
+ export * from "./providers/DbCacheProvider.ts";
16
17
  export * from "./providers/DrizzleKitProvider.ts";
17
18
  export * from "./providers/drivers/CloudflareD1Provider.ts";
18
19
  export * from "./providers/drivers/DatabaseProvider.ts";
19
20
  export * from "./providers/RepositoryProvider.ts";
21
+ export * from "./schemas/databaseEnvSchema.ts";
20
22
  export * from "./schemas/insertSchema.ts";
21
23
  export * from "./schemas/updateSchema.ts";
22
24
  export * from "./services/ModelBuilder.ts";
@@ -13,9 +13,11 @@ export * from "./errors/DbNotNullError.ts";
13
13
  export * from "./errors/DbTableNotFoundError.ts";
14
14
  export * from "./helpers/parseQueryString.ts";
15
15
  export * from "./helpers/pgAttr.ts";
16
+ export * from "./interfaces/AggregateQuery.ts";
16
17
  export * from "./interfaces/FilterOperators.ts";
17
18
  export * from "./interfaces/PgQuery.ts";
18
19
  export * from "./interfaces/PgQueryWhere.ts";
19
20
  export * from "./primitives/$entity.ts";
21
+ export * from "./primitives/$view.ts";
20
22
  export * from "./providers/DatabaseTypeProvider.ts";
21
23
  export * from "./schemas/legacyIdSchema.ts";
@@ -1,15 +1,17 @@
1
- import { $module, type Alepha, t } from "alepha";
1
+ import { $module, type Alepha } from "alepha";
2
2
  import { AlephaDateTime } from "alepha/datetime";
3
3
  import type { PgTransaction } from "drizzle-orm/pg-core";
4
4
  import { DbMigrationMode } from "./modes/DbMigrationMode.ts";
5
5
  import { $entity } from "./primitives/$entity.ts";
6
6
  import { $sequence } from "./primitives/$sequence.ts";
7
+ import { $view } from "./primitives/$view.ts";
7
8
  import { DrizzleKitProvider } from "./providers/DrizzleKitProvider.ts";
8
9
  import { BunSqliteProvider } from "./providers/drivers/BunSqliteProvider.ts";
9
10
  import { CloudflareD1Provider } from "./providers/drivers/CloudflareD1Provider.ts";
10
11
  import { DatabaseProvider } from "./providers/drivers/DatabaseProvider.ts";
11
12
  import { NodeSqliteProvider } from "./providers/drivers/NodeSqliteProvider.ts";
12
13
  import { RepositoryProvider } from "./providers/RepositoryProvider.ts";
14
+ import { databaseEnvSchema } from "./schemas/databaseEnvSchema.ts";
13
15
  import { PgRelationManager } from "./services/PgRelationManager.ts";
14
16
  import { QueryManager } from "./services/QueryManager.ts";
15
17
  import { Repository } from "./services/Repository.ts";
@@ -100,7 +102,7 @@ export const SqliteProvider = NodeSqliteProvider;
100
102
 
101
103
  export const AlephaOrm = $module({
102
104
  name: "alepha.orm",
103
- primitives: [$sequence, $entity],
105
+ primitives: [$sequence, $entity, $view],
104
106
  services: [
105
107
  AlephaDateTime,
106
108
  DatabaseProvider,
@@ -116,11 +118,7 @@ export const AlephaOrm = $module({
116
118
  DbMigrationMode,
117
119
  ],
118
120
  register: (alepha: Alepha) => {
119
- const env = alepha.parseEnv(
120
- t.object({
121
- DATABASE_URL: t.optional(t.text()),
122
- }),
123
- );
121
+ const env = alepha.parseEnv(databaseEnvSchema);
124
122
 
125
123
  const url = env.DATABASE_URL;
126
124
  const isBun = alepha.isBun();
@@ -0,0 +1,103 @@
1
+ import type { Static, TObject } from "alepha";
2
+ import type { PgQueryWhereOrSQL } from "./PgQueryWhere.ts";
3
+
4
+ export type AggregateOp = "count" | "sum" | "avg" | "min" | "max";
5
+
6
+ /**
7
+ * Select definition for aggregate queries.
8
+ * - `true` means select the column value as-is (used for groupBy columns).
9
+ * - `{ sum: true, avg: true, ... }` means compute those aggregations.
10
+ */
11
+ export type AggregateColumnSelect = true | Partial<Record<AggregateOp, true>>;
12
+
13
+ export type AggregateSelect<T extends TObject> = {
14
+ [K in keyof Static<T>]?: AggregateColumnSelect;
15
+ };
16
+
17
+ /**
18
+ * Maps a single column's select definition to its result type.
19
+ * - `true` → original column type
20
+ * - `{ sum: true, avg: true }` → `{ sum: number; avg: number }`
21
+ */
22
+ export type AggregateColumnResult<TValue, TSelect> = TSelect extends true
23
+ ? TValue
24
+ : {
25
+ [Op in AggregateOp as TSelect extends Record<Op, true>
26
+ ? Op
27
+ : never]: number;
28
+ };
29
+
30
+ /**
31
+ * Result type for an aggregate query.
32
+ */
33
+ export type AggregateResult<T extends TObject, S extends AggregateSelect<T>> = {
34
+ [K in keyof S & keyof Static<T>]: AggregateColumnResult<
35
+ Static<T>[K],
36
+ NonNullable<S[K]>
37
+ >;
38
+ };
39
+
40
+ /**
41
+ * HAVING clause for aggregate queries.
42
+ * Only applies to columns with aggregate operations (not `true`).
43
+ */
44
+ export type AggregateHaving<T extends TObject, S extends AggregateSelect<T>> = {
45
+ [K in keyof S & keyof Static<T>]?: S[K] extends true
46
+ ? never
47
+ : {
48
+ [Op in AggregateOp as S[K] extends Record<Op, true> ? Op : never]?: {
49
+ gt?: number;
50
+ gte?: number;
51
+ lt?: number;
52
+ lte?: number;
53
+ eq?: number;
54
+ ne?: number;
55
+ };
56
+ };
57
+ };
58
+
59
+ /**
60
+ * Full aggregate query definition.
61
+ */
62
+ export interface AggregateQuery<
63
+ T extends TObject,
64
+ S extends AggregateSelect<T>,
65
+ > {
66
+ /**
67
+ * Columns and aggregate operations to select.
68
+ */
69
+ select: S;
70
+
71
+ /**
72
+ * WHERE clause to filter rows before aggregation.
73
+ */
74
+ where?: PgQueryWhereOrSQL<T>;
75
+
76
+ /**
77
+ * Columns to group by.
78
+ */
79
+ groupBy?: (keyof Static<T>)[];
80
+
81
+ /**
82
+ * HAVING clause to filter groups after aggregation.
83
+ */
84
+ having?: AggregateHaving<T, S>;
85
+
86
+ /**
87
+ * Order results. Supports dot notation for aggregate columns (e.g. "amount.sum").
88
+ */
89
+ orderBy?:
90
+ | string
91
+ | { column: string; direction: "asc" | "desc" }
92
+ | Array<{ column: string; direction: "asc" | "desc" }>;
93
+
94
+ /**
95
+ * Limit the number of results.
96
+ */
97
+ limit?: number;
98
+
99
+ /**
100
+ * Offset for pagination.
101
+ */
102
+ offset?: number;
103
+ }
@@ -97,6 +97,13 @@ type PgQueryWhereConditions<
97
97
  * @see notExists for the inverse of this test
98
98
  */
99
99
  exists?: SQLWrapper;
100
+
101
+ /**
102
+ * Test whether a subquery evaluates to have no rows.
103
+ *
104
+ * @see exists for the inverse of this test
105
+ */
106
+ notExists?: SQLWrapper;
100
107
  };
101
108
 
102
109
  type PgQueryWhereRelations<
@@ -67,6 +67,10 @@ export interface EntityPrimitiveOptions<
67
67
  * Custom name for the index. If not provided, generates name automatically.
68
68
  */
69
69
  name?: string;
70
+ /**
71
+ * Partial index condition. Only rows matching this SQL expression are indexed.
72
+ */
73
+ where?: SQL;
70
74
  }
71
75
  | {
72
76
  /**
@@ -81,6 +85,10 @@ export interface EntityPrimitiveOptions<
81
85
  * Custom name for the index. If not provided, generates name automatically.
82
86
  */
83
87
  name?: string;
88
+ /**
89
+ * Partial index condition. Only rows matching this SQL expression are indexed.
90
+ */
91
+ where?: SQL;
84
92
  }
85
93
  )[];
86
94
 
@@ -2,14 +2,17 @@ import { $context, $inject, type TObject } from "alepha";
2
2
  import { RepositoryProvider } from "../providers/RepositoryProvider.ts";
3
3
  import type { Repository } from "../services/Repository.ts";
4
4
  import type { EntityPrimitive } from "./$entity.ts";
5
+ import type { ViewPrimitive } from "./$view.ts";
5
6
 
6
7
  /**
7
- * Get the repository for the given entity.
8
+ * Get the repository for the given entity or view.
8
9
  */
9
10
  export const $repository = <T extends TObject>(
10
- entity: EntityPrimitive<T>,
11
+ entity: EntityPrimitive<T> | ViewPrimitive<T>,
11
12
  ): Repository<T> => {
12
13
  const { alepha } = $context();
13
14
  const repositoryProvider = alepha.inject(RepositoryProvider);
14
- return $inject(repositoryProvider.createClassRepository(entity));
15
+ return $inject(
16
+ repositoryProvider.createClassRepository(entity as EntityPrimitive<T>),
17
+ );
15
18
  };
@@ -0,0 +1,88 @@
1
+ import { KIND, type TObject } from "alepha";
2
+ import type { SQL } from "drizzle-orm";
3
+
4
+ /**
5
+ * Creates a database view primitive from a TypeBox schema and SQL query.
6
+ *
7
+ * Views are read-only: Repository blocks all write operations.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { t } from "alepha";
12
+ * import { $view } from "alepha/orm";
13
+ * import { sql } from "drizzle-orm";
14
+ *
15
+ * const userSummary = $view({
16
+ * name: "user_summary",
17
+ * schema: t.object({
18
+ * id: t.uuid(),
19
+ * fullName: t.text(),
20
+ * orderCount: t.integer(),
21
+ * }),
22
+ * query: sql`SELECT u.id, u.first_name || ' ' || u.last_name AS full_name, COUNT(o.id) AS order_count FROM users u LEFT JOIN orders o ON o.user_id = u.id GROUP BY u.id`,
23
+ * });
24
+ *
25
+ * // Materialized view (PostgreSQL only)
26
+ * const monthlyStats = $view({
27
+ * name: "monthly_stats",
28
+ * schema: t.object({ ... }),
29
+ * query: sql`...`,
30
+ * materialized: true,
31
+ * });
32
+ * ```
33
+ */
34
+ export const $view = <TSchema extends TObject>(
35
+ options: ViewPrimitiveOptions<TSchema>,
36
+ ): ViewPrimitive<TSchema> => {
37
+ return new ViewPrimitive<TSchema>(options);
38
+ };
39
+
40
+ // ---------------------------------------------------------------------------------------------------------------------
41
+
42
+ export interface ViewPrimitiveOptions<T extends TObject> {
43
+ /**
44
+ * The database view name.
45
+ */
46
+ name: string;
47
+
48
+ /**
49
+ * TypeBox schema defining the view's columns.
50
+ */
51
+ schema: T;
52
+
53
+ /**
54
+ * SQL query that defines the view.
55
+ */
56
+ query: SQL;
57
+
58
+ /**
59
+ * Whether this is a materialized view (PostgreSQL only).
60
+ * Materialized views store results on disk and can be refreshed.
61
+ */
62
+ materialized?: boolean;
63
+ }
64
+
65
+ // ---------------------------------------------------------------------------------------------------------------------
66
+
67
+ export class ViewPrimitive<T extends TObject = TObject> {
68
+ public readonly options: ViewPrimitiveOptions<T>;
69
+ public readonly isView = true;
70
+
71
+ constructor(options: ViewPrimitiveOptions<T>) {
72
+ this.options = options;
73
+ }
74
+
75
+ get name(): string {
76
+ return this.options.name;
77
+ }
78
+
79
+ get schema(): T {
80
+ return this.options.schema;
81
+ }
82
+
83
+ get materialized(): boolean {
84
+ return this.options.materialized ?? false;
85
+ }
86
+ }
87
+
88
+ $view[KIND] = ViewPrimitive;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Database query cache using a simple in-memory Map.
3
+ *
4
+ * Uses `{tableName}:{cacheKey}` as the storage key.
5
+ * Provides per-table invalidation for write-through cache busting.
6
+ *
7
+ * This is intentionally self-contained (no external cache dependencies)
8
+ * so the ORM module does not force `AlephaCache` on all consumers.
9
+ */
10
+ export class DbCacheProvider {
11
+ protected readonly store = new Map<
12
+ string,
13
+ { value: unknown; expiresAt?: number }
14
+ >();
15
+
16
+ protected storeKey(tableName: string, cacheKey: string): string {
17
+ return `${tableName}:${cacheKey}`;
18
+ }
19
+
20
+ /**
21
+ * Get a cached query result.
22
+ */
23
+ public async get<T>(
24
+ tableName: string,
25
+ cacheKey: string,
26
+ ): Promise<T | undefined> {
27
+ const key = this.storeKey(tableName, cacheKey);
28
+ const entry = this.store.get(key);
29
+
30
+ if (!entry) return undefined;
31
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
32
+ this.store.delete(key);
33
+ return undefined;
34
+ }
35
+
36
+ return entry.value as T;
37
+ }
38
+
39
+ /**
40
+ * Store a query result in the cache.
41
+ */
42
+ public async set<T>(
43
+ tableName: string,
44
+ cacheKey: string,
45
+ value: T,
46
+ ttl?: number,
47
+ ): Promise<void> {
48
+ const key = this.storeKey(tableName, cacheKey);
49
+ this.store.set(key, {
50
+ value,
51
+ expiresAt: ttl ? Date.now() + ttl : undefined,
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Invalidate all cached queries for a table.
57
+ */
58
+ public async invalidateTable(tableName: string): Promise<void> {
59
+ const prefix = `${tableName}:`;
60
+ for (const key of this.store.keys()) {
61
+ if (key.startsWith(prefix)) {
62
+ this.store.delete(key);
63
+ }
64
+ }
65
+ }
66
+ }
@@ -203,6 +203,48 @@ export class DrizzleKitProvider {
203
203
  return models;
204
204
  }
205
205
 
206
+ /**
207
+ * Preview schema push without executing any statements.
208
+ *
209
+ * Returns the SQL statements that would be executed, warnings, and
210
+ * whether data loss would occur. Does NOT execute any SQL.
211
+ */
212
+ public async dryRunPush(provider: DatabaseProvider): Promise<{
213
+ statements: string[];
214
+ warnings: string[];
215
+ hasDataLoss: boolean;
216
+ }> {
217
+ const kit = this.importDrizzleKit();
218
+ const models = this.getModels(provider);
219
+
220
+ if (Object.keys(models).length === 0) {
221
+ return { statements: [], warnings: [], hasDataLoss: false };
222
+ }
223
+
224
+ let result: {
225
+ statementsToExecute: string[];
226
+ warnings: string[];
227
+ hasDataLoss: boolean;
228
+ };
229
+
230
+ if (provider.dialect === "sqlite") {
231
+ result = await this.muteSpinner(() =>
232
+ kit.pushSQLiteSchema(models, provider.db as any),
233
+ );
234
+ } else {
235
+ const wrappedDb = this.wrapDbForDrizzleKit(provider.db);
236
+ result = await this.muteSpinner(() =>
237
+ kit.pushSchema(models, wrappedDb, [provider.schema]),
238
+ );
239
+ }
240
+
241
+ return {
242
+ statements: result.statementsToExecute,
243
+ warnings: result.warnings,
244
+ hasDataLoss: result.hasDataLoss,
245
+ };
246
+ }
247
+
206
248
  // -------------------------------------------------------------------------------------------------------------------
207
249
 
208
250
  protected async pushSqlite(
@@ -13,14 +13,13 @@ import {
13
13
  } from "alepha";
14
14
  import type { BunSQLiteDatabase } from "drizzle-orm/bun-sqlite";
15
15
  import type { PgDatabase } from "drizzle-orm/pg-core";
16
+ import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
16
17
  import { SqliteModelBuilder } from "../../services/SqliteModelBuilder.ts";
17
18
  import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
18
19
 
19
20
  // ---------------------------------------------------------------------------------------------------------------------
20
21
 
21
- const envSchema = t.object({
22
- DATABASE_URL: t.optional(t.text()),
23
- });
22
+ const envSchema = databaseEnvSchema;
24
23
 
25
24
  /**
26
25
  * Configuration options for the Bun SQLite database provider.
@@ -88,6 +88,18 @@ export class CloudflareD1Provider extends DatabaseProvider {
88
88
  return rows;
89
89
  }
90
90
 
91
+ /**
92
+ * D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
93
+ * It rejects these statements and requires the JS `batch()` API for atomic
94
+ * multi-statement operations instead.
95
+ *
96
+ * @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements
97
+ * @see https://github.com/drizzle-team/drizzle-orm/issues/2463
98
+ */
99
+ public override get supportsTransactions(): boolean {
100
+ return false;
101
+ }
102
+
91
103
  protected readonly onStart = $hook({
92
104
  on: "start",
93
105
  handler: async () => {
@@ -21,6 +21,8 @@ import type {
21
21
  SchemaToTableConfig,
22
22
  } from "../../primitives/$entity.ts";
23
23
  import type { SequencePrimitive } from "../../primitives/$sequence.ts";
24
+ import type { ViewPrimitive } from "../../primitives/$view.ts";
25
+ import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
24
26
  import type { ModelBuilder } from "../../services/ModelBuilder.ts";
25
27
  import { DrizzleKitProvider } from "../DrizzleKitProvider.ts";
26
28
 
@@ -51,6 +53,15 @@ export abstract class DatabaseProvider {
51
53
  return this.dialect;
52
54
  }
53
55
 
56
+ /**
57
+ * Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
58
+ *
59
+ * Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.
60
+ */
61
+ public get supportsTransactions(): boolean {
62
+ return true;
63
+ }
64
+
54
65
  /**
55
66
  * Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).
56
67
  * Override in providers that expose native connections for introspection.
@@ -143,6 +154,10 @@ export abstract class DatabaseProvider {
143
154
  this.builder.buildTable(entity, this);
144
155
  }
145
156
 
157
+ public registerView(view: ViewPrimitive) {
158
+ this.builder.buildView(view, this);
159
+ }
160
+
146
161
  public registerSequence(sequence: SequencePrimitive) {
147
162
  this.sequencePrimitives.push(sequence);
148
163
  this.builder.buildSequence(sequence, this);
@@ -197,6 +212,10 @@ export abstract class DatabaseProvider {
197
212
  return fn();
198
213
  }
199
214
 
215
+ if (!this.supportsTransactions) {
216
+ return fn();
217
+ }
218
+
200
219
  return this.db.transaction(async (tx) => {
201
220
  this.alepha.store.set("alepha.orm.tx", tx as PgTransaction<any>, {
202
221
  skipEvents: true,
@@ -218,6 +237,18 @@ export abstract class DatabaseProvider {
218
237
  schema: T,
219
238
  ): Promise<Array<Static<T>>> {
220
239
  const result = await this.execute(statement);
240
+
241
+ if (result == null) {
242
+ return [];
243
+ }
244
+
245
+ if (!Array.isArray(result)) {
246
+ this.log.error("Unexpected query result format", { result });
247
+ throw new DbError(
248
+ "Unexpected query result format, expected array of rows",
249
+ );
250
+ }
251
+
221
252
  return result.map((row) => this.alepha.codec.decode(schema, row));
222
253
  }
223
254
 
@@ -263,6 +294,14 @@ export abstract class DatabaseProvider {
263
294
  await this.executeMigrations(migrationsFolder);
264
295
  this.log.info("Migration OK");
265
296
  } else {
297
+ const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);
298
+ if (DATABASE_SYNC === false) {
299
+ this.log.info(
300
+ "Database synchronization disabled (DATABASE_SYNC=false)",
301
+ );
302
+ return;
303
+ }
304
+
266
305
  try {
267
306
  await this.kit.synchronize(this);
268
307
  } catch (error) {
@@ -13,6 +13,7 @@ import {
13
13
  t,
14
14
  } from "alepha";
15
15
  import type { PgDatabase } from "drizzle-orm/pg-core";
16
+ import { databaseEnvSchema } from "../../schemas/databaseEnvSchema.ts";
16
17
  import { SqliteModelBuilder } from "../../services/SqliteModelBuilder.ts";
17
18
  import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
18
19
 
@@ -39,9 +40,7 @@ import { DatabaseProvider, type SQLLike } from "./DatabaseProvider.ts";
39
40
 
40
41
  // ---------------------------------------------------------------------------------------------------------------------
41
42
 
42
- const envSchema = t.object({
43
- DATABASE_URL: t.optional(t.text()),
44
- });
43
+ const envSchema = databaseEnvSchema;
45
44
 
46
45
  /**
47
46
  * Configuration options for the Node.js SQLite database provider.
@@ -0,0 +1,31 @@
1
+ import { type Static, t } from "alepha";
2
+
3
+ /**
4
+ * Base database environment schema.
5
+ *
6
+ * Defines the `DATABASE_URL` connection string used by all ORM providers
7
+ * to determine the database driver and connection target.
8
+ *
9
+ * Supported URL formats:
10
+ * - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)
11
+ * - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)
12
+ * - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)
13
+ * - `d1://BINDING_NAME` — Cloudflare D1
14
+ * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive
15
+ */
16
+ export const databaseEnvSchema = t.object({
17
+ DATABASE_URL: t.optional(t.text()),
18
+
19
+ /**
20
+ * Enable or disable push-based schema synchronization (drizzle-kit push).
21
+ *
22
+ * Defaults to `true` in development and test, `false` in production.
23
+ * Set to `false` in development to skip automatic schema sync
24
+ * (e.g. when managing migrations manually).
25
+ */
26
+ DATABASE_SYNC: t.optional(t.boolean()),
27
+ });
28
+
29
+ declare module "alepha" {
30
+ interface Env extends Partial<Static<typeof databaseEnvSchema>> {}
31
+ }
@@ -1,18 +1,23 @@
1
1
  import type { TObject, TOptional } from "alepha";
2
2
  import { t } from "alepha";
3
- import { PG_DEFAULT } from "../constants/PG_SYMBOLS.ts";
3
+ import { PG_DEFAULT, PG_GENERATED } from "../constants/PG_SYMBOLS.ts";
4
4
  import { schema } from "../types/schema.ts";
5
5
 
6
6
  /**
7
7
  * Transforms a TObject schema for insert operations.
8
8
  * All default properties at the root level are made optional.
9
+ * Generated columns are excluded entirely.
9
10
  *
10
11
  * @example
11
- * Before: { name: string; age: number(default=0); }
12
+ * Before: { name: string; age: number(default=0); fullName: generated }
12
13
  * After: { name: string; age?: number; }
13
14
  */
14
15
  export type TObjectInsert<T extends TObject> = TObject<{
15
- [K in keyof T["properties"]]: T["properties"][K] extends
16
+ [K in keyof T["properties"] as T["properties"][K] extends {
17
+ [PG_GENERATED]: any;
18
+ }
19
+ ? never
20
+ : K]: T["properties"][K] extends
16
21
  | { [PG_DEFAULT]: any }
17
22
  | { "~optional": true }
18
23
  ? TOptional<T["properties"][K]>
@@ -25,6 +30,11 @@ export const insertSchema = <T extends TObject>(obj: T): TObjectInsert<T> => {
25
30
  for (const key in obj.properties) {
26
31
  const prop = obj.properties[key];
27
32
 
33
+ // Skip generated columns — they are computed by the database
34
+ if (PG_GENERATED in prop) {
35
+ continue;
36
+ }
37
+
28
38
  if (PG_DEFAULT in prop) {
29
39
  newProperties[key] = t.optional(prop);
30
40
  } else {
@@ -5,18 +5,23 @@ import {
5
5
  type TUnion,
6
6
  t,
7
7
  } from "alepha";
8
+ import { PG_GENERATED } from "../constants/PG_SYMBOLS.ts";
8
9
 
9
10
  /**
10
11
  * Transforms a TObject schema for update operations.
11
12
  * All optional properties at the root level are made nullable (i.e., `T | null`).
12
- * This allows an API endpoint to explicitly accept `null` to clear an optional field in the database.
13
+ * Generated columns are excluded entirely.
13
14
  *
14
15
  * @example
15
- * Before: { name?: string; age: number; }
16
+ * Before: { name?: string; age: number; fullName: generated }
16
17
  * After: { name?: string | null; age: number; }
17
18
  */
18
19
  export type TObjectUpdate<T extends TObject> = TObject<{
19
- [K in keyof T["properties"]]: T["properties"][K] extends TOptional<infer U>
20
+ [K in keyof T["properties"] as T["properties"][K] extends {
21
+ [PG_GENERATED]: any;
22
+ }
23
+ ? never
24
+ : K]: T["properties"][K] extends TOptional<infer U>
20
25
  ? TOptional<TUnion<[U, TNull]>>
21
26
  : T["properties"][K];
22
27
  }>;
@@ -28,6 +33,12 @@ export const updateSchema = <T extends TObject>(
28
33
 
29
34
  for (const key in schema.properties) {
30
35
  const prop = schema.properties[key];
36
+
37
+ // Skip generated columns — they are computed by the database
38
+ if (PG_GENERATED in prop) {
39
+ continue;
40
+ }
41
+
31
42
  if (t.schema.isOptional(prop)) {
32
43
  newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));
33
44
  } else {