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
@@ -5,12 +5,12 @@ import { AlephaDateTime, DateTimeProvider } from "alepha/datetime";
5
5
  import { mkdir, stat } from "node:fs/promises";
6
6
  import { $logger } from "alepha/logger";
7
7
  import * as drizzle from "drizzle-orm";
8
- import { and, arrayContained, arrayContains, arrayOverlaps, asc, between, desc, eq, getTableName, gt, gte, ilike, inArray, isNotNull, isNull, isSQLWrapper, like, lt, lte, ne, not, notBetween, notIlike, notInArray, notLike, or, sql, sql as sql$1 } from "drizzle-orm";
8
+ import { and, arrayContained, arrayContains, arrayOverlaps, asc, avg, between, count, desc, eq, exists, getTableName, gt, gte, ilike, inArray, isNotNull, isNull, isSQLWrapper, like, lt, lte, max, min, ne, not, notBetween, notExists, notIlike, notInArray, notLike, or, sql, sql as sql$1, sum } from "drizzle-orm";
9
9
  import { alias, customType } from "drizzle-orm/pg-core";
10
10
  import { dirname } from "node:path";
11
11
  import { randomUUID } from "node:crypto";
12
12
  import * as pg from "drizzle-orm/sqlite-core";
13
- import { check, foreignKey, index, sqliteTable, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
13
+ import { check, foreignKey, index, sqliteTable, sqliteView, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
14
14
  import { isSQLWrapper as isSQLWrapper$1 } from "drizzle-orm/sql/sql";
15
15
 
16
16
  export * from "drizzle-orm/pg-core"
@@ -23,6 +23,26 @@ var DbError = class extends AlephaError {
23
23
  }
24
24
  };
25
25
 
26
+ //#endregion
27
+ //#region ../../src/orm/core/schemas/databaseEnvSchema.ts
28
+ /**
29
+ * Base database environment schema.
30
+ *
31
+ * Defines the `DATABASE_URL` connection string used by all ORM providers
32
+ * to determine the database driver and connection target.
33
+ *
34
+ * Supported URL formats:
35
+ * - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)
36
+ * - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)
37
+ * - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)
38
+ * - `d1://BINDING_NAME` — Cloudflare D1
39
+ * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive
40
+ */
41
+ const databaseEnvSchema = t.object({
42
+ DATABASE_URL: t.optional(t.text()),
43
+ DATABASE_SYNC: t.optional(t.boolean())
44
+ });
45
+
26
46
  //#endregion
27
47
  //#region ../../src/orm/core/providers/DrizzleKitProvider.ts
28
48
  var DrizzleKitProvider = class {
@@ -148,6 +168,32 @@ var DrizzleKitProvider = class {
148
168
  }
149
169
  return models;
150
170
  }
171
+ /**
172
+ * Preview schema push without executing any statements.
173
+ *
174
+ * Returns the SQL statements that would be executed, warnings, and
175
+ * whether data loss would occur. Does NOT execute any SQL.
176
+ */
177
+ async dryRunPush(provider) {
178
+ const kit = this.importDrizzleKit();
179
+ const models = this.getModels(provider);
180
+ if (Object.keys(models).length === 0) return {
181
+ statements: [],
182
+ warnings: [],
183
+ hasDataLoss: false
184
+ };
185
+ let result;
186
+ if (provider.dialect === "sqlite") result = await this.muteSpinner(() => kit.pushSQLiteSchema(models, provider.db));
187
+ else {
188
+ const wrappedDb = this.wrapDbForDrizzleKit(provider.db);
189
+ result = await this.muteSpinner(() => kit.pushSchema(models, wrappedDb, [provider.schema]));
190
+ }
191
+ return {
192
+ statements: result.statementsToExecute,
193
+ warnings: result.warnings,
194
+ hasDataLoss: result.hasDataLoss
195
+ };
196
+ }
151
197
  async pushSqlite(kit, models, provider) {
152
198
  const result = await this.muteSpinner(() => kit.pushSQLiteSchema(models, provider.db));
153
199
  await this.runPushResult(result, provider);
@@ -275,6 +321,14 @@ var DatabaseProvider = class {
275
321
  return this.dialect;
276
322
  }
277
323
  /**
324
+ * Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
325
+ *
326
+ * Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.
327
+ */
328
+ get supportsTransactions() {
329
+ return true;
330
+ }
331
+ /**
278
332
  * Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).
279
333
  * Override in providers that expose native connections for introspection.
280
334
  */
@@ -332,6 +386,9 @@ var DatabaseProvider = class {
332
386
  this.entityPrimitives.push(entity);
333
387
  this.builder.buildTable(entity, this);
334
388
  }
389
+ registerView(view) {
390
+ this.builder.buildView(view, this);
391
+ }
335
392
  registerSequence(sequence) {
336
393
  this.sequencePrimitives.push(sequence);
337
394
  this.builder.buildSequence(sequence, this);
@@ -366,6 +423,7 @@ var DatabaseProvider = class {
366
423
  */
367
424
  async transactional(fn, config) {
368
425
  if (this.alepha.get("alepha.orm.tx")) return fn();
426
+ if (!this.supportsTransactions) return fn();
369
427
  return this.db.transaction(async (tx) => {
370
428
  this.alepha.store.set("alepha.orm.tx", tx, { skipEvents: true });
371
429
  try {
@@ -376,7 +434,13 @@ var DatabaseProvider = class {
376
434
  }, config);
377
435
  }
378
436
  async run(statement, schema) {
379
- return (await this.execute(statement)).map((row) => this.alepha.codec.decode(schema, row));
437
+ const result = await this.execute(statement);
438
+ if (result == null) return [];
439
+ if (!Array.isArray(result)) {
440
+ this.log.error("Unexpected query result format", { result });
441
+ throw new DbError("Unexpected query result format, expected array of rows");
442
+ }
443
+ return result.map((row) => this.alepha.codec.decode(schema, row));
380
444
  }
381
445
  /**
382
446
  * Get migrations folder path - can be overridden
@@ -406,10 +470,17 @@ var DatabaseProvider = class {
406
470
  this.log.debug(`Migrate from '${migrationsFolder}' directory ...`);
407
471
  await this.executeMigrations(migrationsFolder);
408
472
  this.log.info("Migration OK");
409
- } else try {
410
- await this.kit.synchronize(this);
411
- } catch (error) {
412
- throw new DbError(`Failed to synchronize ${this.dialect} database schema`, error);
473
+ } else {
474
+ const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);
475
+ if (DATABASE_SYNC === false) {
476
+ this.log.info("Database synchronization disabled (DATABASE_SYNC=false)");
477
+ return;
478
+ }
479
+ try {
480
+ await this.kit.synchronize(this);
481
+ } catch (error) {
482
+ throw new DbError(`Failed to synchronize ${this.dialect} database schema`, error);
483
+ }
413
484
  }
414
485
  }
415
486
  /**
@@ -461,6 +532,7 @@ const PG_VERSION = Symbol.for("Alepha.Postgres.Version");
461
532
  const PG_IDENTITY = Symbol.for("Alepha.Postgres.Identity");
462
533
  const PG_ENUM = Symbol.for("Alepha.Postgres.Enum");
463
534
  const PG_REF = Symbol.for("Alepha.Postgres.Ref");
535
+ const PG_GENERATED = Symbol.for("Alepha.Postgres.Generated");
464
536
  /**
465
537
  * @deprecated Use `PG_IDENTITY` instead.
466
538
  */
@@ -483,6 +555,7 @@ const insertSchema = (obj) => {
483
555
  const newProperties = {};
484
556
  for (const key in obj.properties) {
485
557
  const prop = obj.properties[key];
558
+ if (PG_GENERATED in prop) continue;
486
559
  if (PG_DEFAULT in prop) newProperties[key] = t.optional(prop);
487
560
  else newProperties[key] = prop;
488
561
  }
@@ -495,6 +568,7 @@ const updateSchema = (schema) => {
495
568
  const newProperties = {};
496
569
  for (const key in schema.properties) {
497
570
  const prop = schema.properties[key];
571
+ if (PG_GENERATED in prop) continue;
498
572
  if (t.schema.isOptional(prop)) newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));
499
573
  else newProperties[key] = prop;
500
574
  }
@@ -587,6 +661,59 @@ var SequencePrimitive = class extends Primitive {
587
661
  };
588
662
  $sequence[KIND] = SequencePrimitive;
589
663
 
664
+ //#endregion
665
+ //#region ../../src/orm/core/primitives/$view.ts
666
+ /**
667
+ * Creates a database view primitive from a TypeBox schema and SQL query.
668
+ *
669
+ * Views are read-only: Repository blocks all write operations.
670
+ *
671
+ * @example
672
+ * ```ts
673
+ * import { t } from "alepha";
674
+ * import { $view } from "alepha/orm";
675
+ * import { sql } from "drizzle-orm";
676
+ *
677
+ * const userSummary = $view({
678
+ * name: "user_summary",
679
+ * schema: t.object({
680
+ * id: t.uuid(),
681
+ * fullName: t.text(),
682
+ * orderCount: t.integer(),
683
+ * }),
684
+ * 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`,
685
+ * });
686
+ *
687
+ * // Materialized view (PostgreSQL only)
688
+ * const monthlyStats = $view({
689
+ * name: "monthly_stats",
690
+ * schema: t.object({ ... }),
691
+ * query: sql`...`,
692
+ * materialized: true,
693
+ * });
694
+ * ```
695
+ */
696
+ const $view = (options) => {
697
+ return new ViewPrimitive(options);
698
+ };
699
+ var ViewPrimitive = class {
700
+ options;
701
+ isView = true;
702
+ constructor(options) {
703
+ this.options = options;
704
+ }
705
+ get name() {
706
+ return this.options.name;
707
+ }
708
+ get schema() {
709
+ return this.options.schema;
710
+ }
711
+ get materialized() {
712
+ return this.options.materialized ?? false;
713
+ }
714
+ };
715
+ $view[KIND] = ViewPrimitive;
716
+
590
717
  //#endregion
591
718
  //#region ../../src/orm/core/services/ModelBuilder.ts
592
719
  /**
@@ -622,14 +749,20 @@ var ModelBuilder = class {
622
749
  if ("column" in indexDef) {
623
750
  const columnName = this.toColumnName(indexDef.column);
624
751
  const indexName = indexDef.name || `${entity.name}_${columnName}_idx`;
625
- if (self[indexDef.column]) if (indexDef.unique) configs.push(builders.uniqueIndex(indexName).on(self[indexDef.column]));
626
- else configs.push(builders.index(indexName).on(self[indexDef.column]));
752
+ if (self[indexDef.column]) {
753
+ let idx = indexDef.unique ? builders.uniqueIndex(indexName).on(self[indexDef.column]) : builders.index(indexName).on(self[indexDef.column]);
754
+ if ("where" in indexDef && indexDef.where) idx = idx.where(indexDef.where);
755
+ configs.push(idx);
756
+ }
627
757
  } else if ("columns" in indexDef) {
628
758
  const columnNames = indexDef.columns.map((col) => this.toColumnName(col));
629
759
  const indexName = indexDef.name || `${entity.name}_${columnNames.join("_")}_idx`;
630
760
  const cols = indexDef.columns.map((col) => self[col]).filter(Boolean);
631
- if (cols.length === indexDef.columns.length) if (indexDef.unique) configs.push(builders.uniqueIndex(indexName).on(...cols));
632
- else configs.push(builders.index(indexName).on(...cols));
761
+ if (cols.length === indexDef.columns.length) {
762
+ let idx = indexDef.unique ? builders.uniqueIndex(indexName).on(...cols) : builders.index(indexName).on(...cols);
763
+ if ("where" in indexDef && indexDef.where) idx = idx.where(indexDef.where);
764
+ configs.push(idx);
765
+ }
633
766
  }
634
767
  }
635
768
  }
@@ -688,6 +821,13 @@ var SqliteModelBuilder = class extends ModelBuilder {
688
821
  const table = sqliteTable(tableName, this.schemaToSqliteColumns(tableName, entity.schema, options.enums, options.tables), this.getTableConfig(entity, options.tables));
689
822
  options.tables.set(tableName, table);
690
823
  }
824
+ buildView(view, options) {
825
+ const viewName = view.name;
826
+ if (options.tables.has(viewName)) return;
827
+ if (view.materialized) throw new AlephaError("SQLite does not support materialized views");
828
+ const drizzleView = sqliteView(viewName, this.schemaToSqliteColumns(viewName, view.schema, /* @__PURE__ */ new Map(), options.tables)).existing();
829
+ options.tables.set(viewName, drizzleView);
830
+ }
691
831
  buildSequence(sequence, options) {
692
832
  throw new AlephaError("SQLite does not support sequences");
693
833
  }
@@ -726,6 +866,10 @@ var SqliteModelBuilder = class extends ModelBuilder {
726
866
  return target;
727
867
  }, config.actions);
728
868
  }
869
+ if (PG_GENERATED in value) {
870
+ const gen = value[PG_GENERATED];
871
+ col = col.generatedAlwaysAs(gen.expression, { mode: gen.mode ?? "virtual" });
872
+ }
729
873
  if (schema.required?.includes(key)) col = col.notNull();
730
874
  return {
731
875
  ...columns,
@@ -809,7 +953,7 @@ var SqliteModelBuilder = class extends ModelBuilder {
809
953
 
810
954
  //#endregion
811
955
  //#region ../../src/orm/core/providers/drivers/BunSqliteProvider.ts
812
- const envSchema$1 = t.object({ DATABASE_URL: t.optional(t.text()) });
956
+ const envSchema$1 = databaseEnvSchema;
813
957
  /**
814
958
  * Configuration options for the Bun SQLite database provider.
815
959
  */
@@ -940,6 +1084,17 @@ var CloudflareD1Provider = class extends DatabaseProvider {
940
1084
  const { rows } = await this.db.run(query);
941
1085
  return rows;
942
1086
  }
1087
+ /**
1088
+ * D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
1089
+ * It rejects these statements and requires the JS `batch()` API for atomic
1090
+ * multi-statement operations instead.
1091
+ *
1092
+ * @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements
1093
+ * @see https://github.com/drizzle-team/drizzle-orm/issues/2463
1094
+ */
1095
+ get supportsTransactions() {
1096
+ return false;
1097
+ }
943
1098
  onStart = $hook({
944
1099
  on: "start",
945
1100
  handler: async () => {
@@ -1001,7 +1156,7 @@ var CloudflareD1Provider = class extends DatabaseProvider {
1001
1156
  };
1002
1157
  }
1003
1158
  })();
1004
- const envSchema = t.object({ DATABASE_URL: t.optional(t.text()) });
1159
+ const envSchema = databaseEnvSchema;
1005
1160
  /**
1006
1161
  * Configuration options for the Node.js SQLite database provider.
1007
1162
  */
@@ -1482,6 +1637,54 @@ const getAttrFields = (schema, name) => {
1482
1637
  return fields;
1483
1638
  };
1484
1639
 
1640
+ //#endregion
1641
+ //#region ../../src/orm/core/providers/DbCacheProvider.ts
1642
+ /**
1643
+ * Database query cache using a simple in-memory Map.
1644
+ *
1645
+ * Uses `{tableName}:{cacheKey}` as the storage key.
1646
+ * Provides per-table invalidation for write-through cache busting.
1647
+ *
1648
+ * This is intentionally self-contained (no external cache dependencies)
1649
+ * so the ORM module does not force `AlephaCache` on all consumers.
1650
+ */
1651
+ var DbCacheProvider = class {
1652
+ store = /* @__PURE__ */ new Map();
1653
+ storeKey(tableName, cacheKey) {
1654
+ return `${tableName}:${cacheKey}`;
1655
+ }
1656
+ /**
1657
+ * Get a cached query result.
1658
+ */
1659
+ async get(tableName, cacheKey) {
1660
+ const key = this.storeKey(tableName, cacheKey);
1661
+ const entry = this.store.get(key);
1662
+ if (!entry) return void 0;
1663
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
1664
+ this.store.delete(key);
1665
+ return;
1666
+ }
1667
+ return entry.value;
1668
+ }
1669
+ /**
1670
+ * Store a query result in the cache.
1671
+ */
1672
+ async set(tableName, cacheKey, value, ttl) {
1673
+ const key = this.storeKey(tableName, cacheKey);
1674
+ this.store.set(key, {
1675
+ value,
1676
+ expiresAt: ttl ? Date.now() + ttl : void 0
1677
+ });
1678
+ }
1679
+ /**
1680
+ * Invalidate all cached queries for a table.
1681
+ */
1682
+ async invalidateTable(tableName) {
1683
+ const prefix = `${tableName}:`;
1684
+ for (const key of this.store.keys()) if (key.startsWith(prefix)) this.store.delete(key);
1685
+ }
1686
+ };
1687
+
1485
1688
  //#endregion
1486
1689
  //#region ../../src/orm/core/services/PgRelationManager.ts
1487
1690
  var PgRelationManager = class {
@@ -1606,6 +1809,14 @@ var QueryManager = class {
1606
1809
  });
1607
1810
  if (where) return not(where);
1608
1811
  }
1812
+ if (key === "exists") {
1813
+ conditions.push(exists(operator));
1814
+ continue;
1815
+ }
1816
+ if (key === "notExists") {
1817
+ conditions.push(notExists(operator));
1818
+ continue;
1819
+ }
1609
1820
  if (operator) {
1610
1821
  const column = col(key);
1611
1822
  const sql = this.mapOperatorToSql(operator, column, schema, key, options.dialect);
@@ -1785,6 +1996,7 @@ var Repository = class Repository {
1785
1996
  relationManager = $inject(PgRelationManager);
1786
1997
  queryManager = $inject(QueryManager);
1787
1998
  dateTimeProvider = $inject(DateTimeProvider);
1999
+ dbCache = new DbCacheProvider();
1788
2000
  alepha = $inject(Alepha);
1789
2001
  static of(entity, provider = DatabaseProvider) {
1790
2002
  return class InlineRepository extends Repository {
@@ -1796,7 +2008,8 @@ var Repository = class Repository {
1796
2008
  constructor(entity, provider = DatabaseProvider) {
1797
2009
  this.entity = entity;
1798
2010
  this.provider = this.alepha.inject(provider);
1799
- this.provider.registerEntity(entity);
2011
+ if (entity.isView) this.provider.registerView(entity);
2012
+ else this.provider.registerEntity(entity);
1800
2013
  }
1801
2014
  /**
1802
2015
  * Represents the primary key of the table.
@@ -1821,6 +2034,12 @@ var Repository = class Repository {
1821
2034
  return this.entity.name;
1822
2035
  }
1823
2036
  /**
2037
+ * Whether this repository is backed by a view (read-only).
2038
+ */
2039
+ get isReadOnly() {
2040
+ return this.entity.isView === true;
2041
+ }
2042
+ /**
1824
2043
  * Getter for the database connection from the database provider.
1825
2044
  *
1826
2045
  * Automatically picks up a transaction from `alepha.store` if one was set
@@ -1860,6 +2079,8 @@ var Repository = class Repository {
1860
2079
  } catch (error) {
1861
2080
  throw this.handleError(error, "Custom query has failed");
1862
2081
  }
2082
+ if (rows == null) return [];
2083
+ if (!Array.isArray(rows)) throw new DbError("Invalid query result. Expected an array of rows, but got: " + JSON.stringify(rows));
1863
2084
  return rows.map((it) => {
1864
2085
  return this.clean(this.mapRawFieldsToEntity(it), schema ?? this.entity.schema);
1865
2086
  });
@@ -1893,8 +2114,8 @@ var Repository = class Repository {
1893
2114
  * Run a transaction.
1894
2115
  */
1895
2116
  async transaction(transaction, config) {
1896
- if (this.provider.driver === "pglite") {
1897
- this.log.warn("Transactions are not supported with pglite driver");
2117
+ if (!this.provider.supportsTransactions) {
2118
+ this.log.warn(`Transactions are not supported with ${this.provider.driver} driver`);
1898
2119
  return await transaction(null);
1899
2120
  }
1900
2121
  this.log.debug(`Starting transaction on table ${this.tableName}`);
@@ -1940,6 +2161,11 @@ var Repository = class Repository {
1940
2161
  * > This method is the base for `find`, `findOne`, `findById`, and `paginate`.
1941
2162
  */
1942
2163
  async findMany(query = {}, opts = {}) {
2164
+ if (opts.cache) {
2165
+ const cacheKey = opts.cache.key ?? this.buildCacheKey("findMany", query);
2166
+ const cached = await this.dbCache.get(this.tableName, cacheKey);
2167
+ if (cached) return cached;
2168
+ }
1943
2169
  await this.alepha.events.emit("repository:read:before", {
1944
2170
  tableName: this.tableName,
1945
2171
  query
@@ -1987,7 +2213,12 @@ var Repository = class Repository {
1987
2213
  query,
1988
2214
  entities: rows
1989
2215
  });
1990
- return rows;
2216
+ const result = rows;
2217
+ if (opts.cache) {
2218
+ const cacheKey = opts.cache.key ?? this.buildCacheKey("findMany", query);
2219
+ await this.dbCache.set(this.tableName, cacheKey, result, opts.cache.ttl);
2220
+ }
2221
+ return result;
1991
2222
  } catch (error) {
1992
2223
  throw this.handleError(error, "Query select has failed");
1993
2224
  }
@@ -2087,12 +2318,14 @@ var Repository = class Repository {
2087
2318
  * @returns The ID of the created entity.
2088
2319
  */
2089
2320
  async create(data, opts = {}) {
2321
+ this.assertWritable();
2090
2322
  await this.alepha.events.emit("repository:create:before", {
2091
2323
  tableName: this.tableName,
2092
2324
  data
2093
2325
  });
2094
2326
  try {
2095
2327
  const entity = await this.rawInsert(opts).values(this.cast(data ?? {}, true)).returning(this.table).then(([it]) => this.clean(it, this.entity.schema));
2328
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2096
2329
  await this.alepha.events.emit("repository:create:after", {
2097
2330
  tableName: this.tableName,
2098
2331
  data,
@@ -2113,6 +2346,7 @@ var Repository = class Repository {
2113
2346
  * @returns The created entities.
2114
2347
  */
2115
2348
  async createMany(values, opts = {}) {
2349
+ this.assertWritable();
2116
2350
  if (values.length === 0) return [];
2117
2351
  await this.alepha.events.emit("repository:create:before", {
2118
2352
  tableName: this.tableName,
@@ -2126,6 +2360,7 @@ var Repository = class Repository {
2126
2360
  const entities = await this.rawInsert(opts).values(batch.map((data) => this.cast(data, true))).returning(this.table).then((rows) => rows.map((it) => this.clean(it, this.entity.schema)));
2127
2361
  allEntities.push(...entities);
2128
2362
  }
2363
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2129
2364
  await this.alepha.events.emit("repository:create:after", {
2130
2365
  tableName: this.tableName,
2131
2366
  data: values,
@@ -2166,6 +2401,7 @@ var Repository = class Repository {
2166
2401
  * ```
2167
2402
  */
2168
2403
  async upsert(data, opts = {}) {
2404
+ this.assertWritable();
2169
2405
  await this.alepha.events.emit("repository:create:before", {
2170
2406
  tableName: this.tableName,
2171
2407
  data
@@ -2186,6 +2422,7 @@ var Repository = class Repository {
2186
2422
  target: targetColumns,
2187
2423
  set: setData
2188
2424
  }).returning(this.table).then(([it]) => this.clean(it, this.entity.schema));
2425
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2189
2426
  await this.alepha.events.emit("repository:create:after", {
2190
2427
  tableName: this.tableName,
2191
2428
  data,
@@ -2200,6 +2437,7 @@ var Repository = class Repository {
2200
2437
  * Find an entity and update it.
2201
2438
  */
2202
2439
  async updateOne(where, data, opts = {}) {
2440
+ this.assertWritable();
2203
2441
  await this.alepha.events.emit("repository:update:before", {
2204
2442
  tableName: this.tableName,
2205
2443
  where,
@@ -2217,6 +2455,7 @@ var Repository = class Repository {
2217
2455
  if (!response[0]) throw new DbEntityNotFoundError(this.tableName);
2218
2456
  try {
2219
2457
  const entity = this.clean(response[0], this.entity.schema);
2458
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2220
2459
  await this.alepha.events.emit("repository:update:after", {
2221
2460
  tableName: this.tableName,
2222
2461
  where,
@@ -2249,6 +2488,7 @@ var Repository = class Repository {
2249
2488
  * @see {@link DbVersionMismatchError}
2250
2489
  */
2251
2490
  async save(entity, opts = {}) {
2491
+ this.assertWritable();
2252
2492
  const row = entity;
2253
2493
  const id = row[this.id.key];
2254
2494
  if (id == null) throw new AlephaError("Cannot save entity without ID - missing primary key in value");
@@ -2286,6 +2526,7 @@ var Repository = class Repository {
2286
2526
  * Find many entities and update all of them.
2287
2527
  */
2288
2528
  async updateMany(where, data, opts = {}) {
2529
+ this.assertWritable();
2289
2530
  await this.alepha.events.emit("repository:update:before", {
2290
2531
  tableName: this.tableName,
2291
2532
  where,
@@ -2297,6 +2538,7 @@ var Repository = class Repository {
2297
2538
  data = this.cast(data, false);
2298
2539
  try {
2299
2540
  const entities = await this.rawUpdate(opts).set(data).where(this.toSQL(where)).returning();
2541
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2300
2542
  await this.alepha.events.emit("repository:update:after", {
2301
2543
  tableName: this.tableName,
2302
2544
  where,
@@ -2313,6 +2555,7 @@ var Repository = class Repository {
2313
2555
  * @returns Array of deleted entity IDs
2314
2556
  */
2315
2557
  async deleteMany(where = {}, opts = {}) {
2558
+ this.assertWritable();
2316
2559
  const deletedAt = this.deletedAt();
2317
2560
  if (deletedAt && !opts.force) return await this.updateMany(where, { [deletedAt.key]: opts.now ?? this.dateTimeProvider.nowISOString() }, opts);
2318
2561
  await this.alepha.events.emit("repository:delete:before", {
@@ -2321,6 +2564,7 @@ var Repository = class Repository {
2321
2564
  });
2322
2565
  try {
2323
2566
  const ids = (await this.rawDelete(opts).where(this.toSQL(where)).returning({ id: this.table[this.id.key] })).map((row) => row.id);
2567
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2324
2568
  await this.alepha.events.emit("repository:delete:after", {
2325
2569
  tableName: this.tableName,
2326
2570
  where,
@@ -2380,6 +2624,97 @@ var Repository = class Repository {
2380
2624
  where = this.withDeletedAt(where, opts);
2381
2625
  return (opts.tx === null ? this.provider.db : opts.tx ?? this.db).$count(this.table, this.toSQL(where));
2382
2626
  }
2627
+ /**
2628
+ * Execute an aggregate query with type-safe select, groupBy, and having.
2629
+ *
2630
+ * @example
2631
+ * ```ts
2632
+ * const result = await repo.aggregate({
2633
+ * select: { category: true, amount: { sum: true, avg: true } },
2634
+ * groupBy: ["category"],
2635
+ * having: { amount: { sum: { gt: 100 } } },
2636
+ * orderBy: { column: "amount.sum", direction: "desc" },
2637
+ * });
2638
+ * // result: Array<{ category: string; amount: { sum: number; avg: number } }>
2639
+ * ```
2640
+ */
2641
+ async aggregate(query, opts = {}) {
2642
+ const AGG_SEPARATOR = "___";
2643
+ const flatFields = {};
2644
+ const aggFn = (op, column) => {
2645
+ switch (op) {
2646
+ case "count": return count(column);
2647
+ case "sum": return sum(column);
2648
+ case "avg": return avg(column);
2649
+ case "min": return min(column);
2650
+ case "max": return max(column);
2651
+ }
2652
+ };
2653
+ for (const [key, select] of Object.entries(query.select)) if (select === true) flatFields[key] = this.col(key);
2654
+ else if (typeof select === "object" && select !== null) {
2655
+ for (const op of Object.keys(select)) if (select[op]) flatFields[`${key}${AGG_SEPARATOR}${op}`] = aggFn(op, this.col(key));
2656
+ }
2657
+ let builder = (opts.tx === null ? this.provider.db : opts.tx ?? this.db).select(flatFields).from(this.table);
2658
+ if (query.where) {
2659
+ const where = this.withDeletedAt(query.where, opts);
2660
+ builder = builder.where(this.toSQL(where));
2661
+ }
2662
+ if (query.groupBy) builder = builder.groupBy(...query.groupBy.map((key) => this.col(key)));
2663
+ if (query.having) {
2664
+ const havingConditions = [];
2665
+ for (const [key, ops] of Object.entries(query.having)) {
2666
+ if (!ops || typeof ops !== "object") continue;
2667
+ for (const [op, comparisons] of Object.entries(ops)) {
2668
+ if (!comparisons || typeof comparisons !== "object") continue;
2669
+ const aggExpr = aggFn(op, this.col(key));
2670
+ for (const [cmp, val] of Object.entries(comparisons)) switch (cmp) {
2671
+ case "gt":
2672
+ havingConditions.push(gt(aggExpr, val));
2673
+ break;
2674
+ case "gte":
2675
+ havingConditions.push(gte(aggExpr, val));
2676
+ break;
2677
+ case "lt":
2678
+ havingConditions.push(lt(aggExpr, val));
2679
+ break;
2680
+ case "lte":
2681
+ havingConditions.push(lte(aggExpr, val));
2682
+ break;
2683
+ case "eq":
2684
+ havingConditions.push(eq(aggExpr, val));
2685
+ break;
2686
+ case "ne":
2687
+ havingConditions.push(ne(aggExpr, val));
2688
+ break;
2689
+ }
2690
+ }
2691
+ }
2692
+ if (havingConditions.length > 0) builder = builder.having(and(...havingConditions));
2693
+ }
2694
+ if (query.orderBy) {
2695
+ const clauses = this.queryManager.normalizeOrderBy(query.orderBy);
2696
+ builder = builder.orderBy(...clauses.map((clause) => {
2697
+ const col = flatFields[clause.column.includes(".") ? clause.column.replace(".", AGG_SEPARATOR) : clause.column];
2698
+ if (!col) throw new AlephaError(`Invalid orderBy column '${clause.column}' in aggregate query`);
2699
+ return clause.direction === "desc" ? desc(col) : asc(col);
2700
+ }));
2701
+ }
2702
+ if (query.limit) builder = builder.limit(query.limit);
2703
+ if (query.offset) builder = builder.offset(query.offset);
2704
+ try {
2705
+ return (await builder.execute()).map((row) => {
2706
+ const result = {};
2707
+ for (const [flatKey, value] of Object.entries(row)) if (flatKey.includes(AGG_SEPARATOR)) {
2708
+ const [col, op] = flatKey.split(AGG_SEPARATOR);
2709
+ if (!result[col]) result[col] = {};
2710
+ result[col][op] = value != null ? Number(value) : 0;
2711
+ } else result[flatKey] = value;
2712
+ return result;
2713
+ });
2714
+ } catch (error) {
2715
+ throw this.handleError(error, "Aggregate query has failed");
2716
+ }
2717
+ }
2383
2718
  errorPatterns = {
2384
2719
  conflict: ["duplicate key value violates unique constraint", "UNIQUE constraint failed"],
2385
2720
  foreignKey: ["violates foreign key constraint", "FOREIGN KEY constraint failed"],
@@ -2455,6 +2790,25 @@ var Repository = class Repository {
2455
2790
  return entity;
2456
2791
  }
2457
2792
  /**
2793
+ * Throw if this repository is read-only (backed by a view).
2794
+ */
2795
+ assertWritable() {
2796
+ if (this.isReadOnly) throw new AlephaError(`Cannot write to view '${this.tableName}'. Views are read-only.`);
2797
+ }
2798
+ /**
2799
+ * Refresh a materialized view. PostgreSQL only.
2800
+ */
2801
+ async refresh() {
2802
+ if (!this.entity.materialized) throw new AlephaError(`Cannot refresh '${this.tableName}'. Only materialized views support refresh.`);
2803
+ await this.provider.execute(`REFRESH MATERIALIZED VIEW ${this.tableName}`);
2804
+ }
2805
+ /**
2806
+ * Build a cache key from method name and query parameters.
2807
+ */
2808
+ buildCacheKey(method, query) {
2809
+ return `${method}:${JSON.stringify(query)}`;
2810
+ }
2811
+ /**
2458
2812
  * Convert a where clause to SQL.
2459
2813
  */
2460
2814
  toSQL(where, joins) {
@@ -3021,7 +3375,7 @@ const legacyIdSchema = pgAttr(pgAttr(pgAttr(t.integer(), PG_PRIMARY_KEY), PG_SER
3021
3375
  //#endregion
3022
3376
  //#region ../../src/orm/core/primitives/$repository.ts
3023
3377
  /**
3024
- * Get the repository for the given entity.
3378
+ * Get the repository for the given entity or view.
3025
3379
  */
3026
3380
  const $repository = (entity) => {
3027
3381
  const { alepha } = $context();
@@ -3121,11 +3475,13 @@ var core_exports = /* @__PURE__ */ __exportAll({
3121
3475
  $seed: () => $seed,
3122
3476
  $sequence: () => $sequence,
3123
3477
  $transactional: () => $transactional,
3478
+ $view: () => $view,
3124
3479
  AlephaOrm: () => AlephaOrm,
3125
3480
  BunSqliteProvider: () => BunSqliteProvider,
3126
3481
  CloudflareD1Provider: () => CloudflareD1Provider,
3127
3482
  DatabaseProvider: () => DatabaseProvider,
3128
3483
  DatabaseTypeProvider: () => DatabaseTypeProvider,
3484
+ DbCacheProvider: () => DbCacheProvider,
3129
3485
  DbColumnNotFoundError: () => DbColumnNotFoundError,
3130
3486
  DbConflictError: () => DbConflictError,
3131
3487
  DbConnectionError: () => DbConnectionError,
@@ -3146,6 +3502,7 @@ var core_exports = /* @__PURE__ */ __exportAll({
3146
3502
  PG_DEFAULT: () => PG_DEFAULT,
3147
3503
  PG_DELETED_AT: () => PG_DELETED_AT,
3148
3504
  PG_ENUM: () => PG_ENUM,
3505
+ PG_GENERATED: () => PG_GENERATED,
3149
3506
  PG_IDENTITY: () => PG_IDENTITY,
3150
3507
  PG_PRIMARY_KEY: () => PG_PRIMARY_KEY,
3151
3508
  PG_REF: () => PG_REF,
@@ -3156,8 +3513,10 @@ var core_exports = /* @__PURE__ */ __exportAll({
3156
3513
  RepositoryProvider: () => RepositoryProvider,
3157
3514
  SequencePrimitive: () => SequencePrimitive,
3158
3515
  SqliteProvider: () => SqliteProvider,
3516
+ ViewPrimitive: () => ViewPrimitive,
3159
3517
  buildQueryString: () => buildQueryString,
3160
3518
  bunSqliteOptions: () => bunSqliteOptions,
3519
+ databaseEnvSchema: () => databaseEnvSchema,
3161
3520
  db: () => db,
3162
3521
  drizzle: () => drizzle,
3163
3522
  getAttrFields: () => getAttrFields,
@@ -3175,7 +3534,11 @@ var core_exports = /* @__PURE__ */ __exportAll({
3175
3534
  const SqliteProvider = NodeSqliteProvider;
3176
3535
  const AlephaOrm = $module({
3177
3536
  name: "alepha.orm",
3178
- primitives: [$sequence, $entity],
3537
+ primitives: [
3538
+ $sequence,
3539
+ $entity,
3540
+ $view
3541
+ ],
3179
3542
  services: [
3180
3543
  AlephaDateTime,
3181
3544
  DatabaseProvider,
@@ -3191,7 +3554,7 @@ const AlephaOrm = $module({
3191
3554
  DbMigrationMode
3192
3555
  ],
3193
3556
  register: (alepha) => {
3194
- const url = alepha.parseEnv(t.object({ DATABASE_URL: t.optional(t.text()) })).DATABASE_URL;
3557
+ const url = alepha.parseEnv(databaseEnvSchema).DATABASE_URL;
3195
3558
  const isBun = alepha.isBun();
3196
3559
  if (url?.startsWith("d1:")) alepha.with({
3197
3560
  optional: true,
@@ -3210,5 +3573,5 @@ const AlephaOrm = $module({
3210
3573
  });
3211
3574
 
3212
3575
  //#endregion
3213
- export { $entity, $repository, $seed, $sequence, $transactional, AlephaOrm, BunSqliteProvider, CloudflareD1Provider, DatabaseProvider, DatabaseTypeProvider, DbColumnNotFoundError, DbConflictError, DbConnectionError, DbDeadlockError, DbEntityNotFoundError, DbError, DbForeignKeyError, DbMigrationError, DbMigrationMode, DbNotNullError, DbTableNotFoundError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, ModelBuilder, NodeSqliteProvider, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_ENUM, PG_IDENTITY, PG_PRIMARY_KEY, PG_REF, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, Repository, RepositoryProvider, SequencePrimitive, SqliteProvider, buildQueryString, bunSqliteOptions, db, drizzle, getAttrFields, insertSchema, legacyIdSchema, nodeSqliteOptions, pageQuerySchema, pageSchema, parseQueryString, pgAttr, schema, sql, updateSchema };
3576
+ export { $entity, $repository, $seed, $sequence, $transactional, $view, AlephaOrm, BunSqliteProvider, CloudflareD1Provider, DatabaseProvider, DatabaseTypeProvider, DbCacheProvider, DbColumnNotFoundError, DbConflictError, DbConnectionError, DbDeadlockError, DbEntityNotFoundError, DbError, DbForeignKeyError, DbMigrationError, DbMigrationMode, DbNotNullError, DbTableNotFoundError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, ModelBuilder, NodeSqliteProvider, PG_CREATED_AT, PG_DEFAULT, PG_DELETED_AT, PG_ENUM, PG_GENERATED, PG_IDENTITY, PG_PRIMARY_KEY, PG_REF, PG_SERIAL, PG_UPDATED_AT, PG_VERSION, Repository, RepositoryProvider, SequencePrimitive, SqliteProvider, ViewPrimitive, buildQueryString, bunSqliteOptions, databaseEnvSchema, db, drizzle, getAttrFields, insertSchema, legacyIdSchema, nodeSqliteOptions, pageQuerySchema, pageSchema, parseQueryString, pgAttr, schema, sql, updateSchema };
3214
3577
  //# sourceMappingURL=index.js.map