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
@@ -3,13 +3,13 @@ import { $atom, $context, $env, $hook, $inject, $mode, $module, $use, Alepha, Al
3
3
  import { AlephaDateTime, DateTimeProvider } from "alepha/datetime";
4
4
  import { alias, customType } from "drizzle-orm/pg-core";
5
5
  import * as drizzle from "drizzle-orm";
6
- 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";
6
+ 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";
7
7
  import { mkdir, stat } from "node:fs/promises";
8
8
  import { $logger } from "alepha/logger";
9
9
  import { dirname } from "node:path";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import * as pg from "drizzle-orm/sqlite-core";
12
- import { check, foreignKey, index, sqliteTable, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
12
+ import { check, foreignKey, index, sqliteTable, sqliteView, unique, uniqueIndex } from "drizzle-orm/sqlite-core";
13
13
  import { isSQLWrapper as isSQLWrapper$1 } from "drizzle-orm/sql/sql";
14
14
 
15
15
  export * from "drizzle-orm/pg-core"
@@ -59,6 +59,7 @@ const PG_VERSION = Symbol.for("Alepha.Postgres.Version");
59
59
  const PG_IDENTITY = Symbol.for("Alepha.Postgres.Identity");
60
60
  const PG_ENUM = Symbol.for("Alepha.Postgres.Enum");
61
61
  const PG_REF = Symbol.for("Alepha.Postgres.Ref");
62
+ const PG_GENERATED = Symbol.for("Alepha.Postgres.Generated");
62
63
  /**
63
64
  * @deprecated Use `PG_IDENTITY` instead.
64
65
  */
@@ -81,6 +82,7 @@ const insertSchema = (obj) => {
81
82
  const newProperties = {};
82
83
  for (const key in obj.properties) {
83
84
  const prop = obj.properties[key];
85
+ if (PG_GENERATED in prop) continue;
84
86
  if (PG_DEFAULT in prop) newProperties[key] = t.optional(prop);
85
87
  else newProperties[key] = prop;
86
88
  }
@@ -93,6 +95,7 @@ const updateSchema = (schema) => {
93
95
  const newProperties = {};
94
96
  for (const key in schema.properties) {
95
97
  const prop = schema.properties[key];
98
+ if (PG_GENERATED in prop) continue;
96
99
  if (t.schema.isOptional(prop)) newProperties[key] = t.optional(t.union([prop, t.raw.Null()]));
97
100
  else newProperties[key] = prop;
98
101
  }
@@ -166,6 +169,26 @@ var DbError = class extends AlephaError {
166
169
  }
167
170
  };
168
171
 
172
+ //#endregion
173
+ //#region ../../src/orm/core/schemas/databaseEnvSchema.ts
174
+ /**
175
+ * Base database environment schema.
176
+ *
177
+ * Defines the `DATABASE_URL` connection string used by all ORM providers
178
+ * to determine the database driver and connection target.
179
+ *
180
+ * Supported URL formats:
181
+ * - `sqlite://:memory:` or `sqlite://./path/to/db` — SQLite (Node.js or Bun)
182
+ * - `postgres://user:password@host:port/database` — PostgreSQL (Node.js or Bun)
183
+ * - `pglite://:memory:` or `pglite://./path` — PGlite (embedded Postgres)
184
+ * - `d1://BINDING_NAME` — Cloudflare D1
185
+ * - `hyperdrive://BINDING_NAME` — Cloudflare Hyperdrive
186
+ */
187
+ const databaseEnvSchema = t.object({
188
+ DATABASE_URL: t.optional(t.text()),
189
+ DATABASE_SYNC: t.optional(t.boolean())
190
+ });
191
+
169
192
  //#endregion
170
193
  //#region ../../src/orm/core/providers/DrizzleKitProvider.ts
171
194
  var DrizzleKitProvider = class {
@@ -291,6 +314,32 @@ var DrizzleKitProvider = class {
291
314
  }
292
315
  return models;
293
316
  }
317
+ /**
318
+ * Preview schema push without executing any statements.
319
+ *
320
+ * Returns the SQL statements that would be executed, warnings, and
321
+ * whether data loss would occur. Does NOT execute any SQL.
322
+ */
323
+ async dryRunPush(provider) {
324
+ const kit = this.importDrizzleKit();
325
+ const models = this.getModels(provider);
326
+ if (Object.keys(models).length === 0) return {
327
+ statements: [],
328
+ warnings: [],
329
+ hasDataLoss: false
330
+ };
331
+ let result;
332
+ if (provider.dialect === "sqlite") result = await this.muteSpinner(() => kit.pushSQLiteSchema(models, provider.db));
333
+ else {
334
+ const wrappedDb = this.wrapDbForDrizzleKit(provider.db);
335
+ result = await this.muteSpinner(() => kit.pushSchema(models, wrappedDb, [provider.schema]));
336
+ }
337
+ return {
338
+ statements: result.statementsToExecute,
339
+ warnings: result.warnings,
340
+ hasDataLoss: result.hasDataLoss
341
+ };
342
+ }
294
343
  async pushSqlite(kit, models, provider) {
295
344
  const result = await this.muteSpinner(() => kit.pushSQLiteSchema(models, provider.db));
296
345
  await this.runPushResult(result, provider);
@@ -418,6 +467,14 @@ var DatabaseProvider = class {
418
467
  return this.dialect;
419
468
  }
420
469
  /**
470
+ * Whether this driver supports SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
471
+ *
472
+ * Drivers that do not (e.g. PGlite, Cloudflare D1) should override to `false`.
473
+ */
474
+ get supportsTransactions() {
475
+ return true;
476
+ }
477
+ /**
421
478
  * Raw database connection handle (e.g. DatabaseSync, bun:sqlite Database).
422
479
  * Override in providers that expose native connections for introspection.
423
480
  */
@@ -475,6 +532,9 @@ var DatabaseProvider = class {
475
532
  this.entityPrimitives.push(entity);
476
533
  this.builder.buildTable(entity, this);
477
534
  }
535
+ registerView(view) {
536
+ this.builder.buildView(view, this);
537
+ }
478
538
  registerSequence(sequence) {
479
539
  this.sequencePrimitives.push(sequence);
480
540
  this.builder.buildSequence(sequence, this);
@@ -509,6 +569,7 @@ var DatabaseProvider = class {
509
569
  */
510
570
  async transactional(fn, config) {
511
571
  if (this.alepha.get("alepha.orm.tx")) return fn();
572
+ if (!this.supportsTransactions) return fn();
512
573
  return this.db.transaction(async (tx) => {
513
574
  this.alepha.store.set("alepha.orm.tx", tx, { skipEvents: true });
514
575
  try {
@@ -519,7 +580,13 @@ var DatabaseProvider = class {
519
580
  }, config);
520
581
  }
521
582
  async run(statement, schema) {
522
- return (await this.execute(statement)).map((row) => this.alepha.codec.decode(schema, row));
583
+ const result = await this.execute(statement);
584
+ if (result == null) return [];
585
+ if (!Array.isArray(result)) {
586
+ this.log.error("Unexpected query result format", { result });
587
+ throw new DbError("Unexpected query result format, expected array of rows");
588
+ }
589
+ return result.map((row) => this.alepha.codec.decode(schema, row));
523
590
  }
524
591
  /**
525
592
  * Get migrations folder path - can be overridden
@@ -549,10 +616,17 @@ var DatabaseProvider = class {
549
616
  this.log.debug(`Migrate from '${migrationsFolder}' directory ...`);
550
617
  await this.executeMigrations(migrationsFolder);
551
618
  this.log.info("Migration OK");
552
- } else try {
553
- await this.kit.synchronize(this);
554
- } catch (error) {
555
- throw new DbError(`Failed to synchronize ${this.dialect} database schema`, error);
619
+ } else {
620
+ const { DATABASE_SYNC } = this.alepha.parseEnv(databaseEnvSchema);
621
+ if (DATABASE_SYNC === false) {
622
+ this.log.info("Database synchronization disabled (DATABASE_SYNC=false)");
623
+ return;
624
+ }
625
+ try {
626
+ await this.kit.synchronize(this);
627
+ } catch (error) {
628
+ throw new DbError(`Failed to synchronize ${this.dialect} database schema`, error);
629
+ }
556
630
  }
557
631
  }
558
632
  /**
@@ -629,14 +703,20 @@ var ModelBuilder = class {
629
703
  if ("column" in indexDef) {
630
704
  const columnName = this.toColumnName(indexDef.column);
631
705
  const indexName = indexDef.name || `${entity.name}_${columnName}_idx`;
632
- if (self[indexDef.column]) if (indexDef.unique) configs.push(builders.uniqueIndex(indexName).on(self[indexDef.column]));
633
- else configs.push(builders.index(indexName).on(self[indexDef.column]));
706
+ if (self[indexDef.column]) {
707
+ let idx = indexDef.unique ? builders.uniqueIndex(indexName).on(self[indexDef.column]) : builders.index(indexName).on(self[indexDef.column]);
708
+ if ("where" in indexDef && indexDef.where) idx = idx.where(indexDef.where);
709
+ configs.push(idx);
710
+ }
634
711
  } else if ("columns" in indexDef) {
635
712
  const columnNames = indexDef.columns.map((col) => this.toColumnName(col));
636
713
  const indexName = indexDef.name || `${entity.name}_${columnNames.join("_")}_idx`;
637
714
  const cols = indexDef.columns.map((col) => self[col]).filter(Boolean);
638
- if (cols.length === indexDef.columns.length) if (indexDef.unique) configs.push(builders.uniqueIndex(indexName).on(...cols));
639
- else configs.push(builders.index(indexName).on(...cols));
715
+ if (cols.length === indexDef.columns.length) {
716
+ let idx = indexDef.unique ? builders.uniqueIndex(indexName).on(...cols) : builders.index(indexName).on(...cols);
717
+ if ("where" in indexDef && indexDef.where) idx = idx.where(indexDef.where);
718
+ configs.push(idx);
719
+ }
640
720
  }
641
721
  }
642
722
  }
@@ -695,6 +775,13 @@ var SqliteModelBuilder = class extends ModelBuilder {
695
775
  const table = sqliteTable(tableName, this.schemaToSqliteColumns(tableName, entity.schema, options.enums, options.tables), this.getTableConfig(entity, options.tables));
696
776
  options.tables.set(tableName, table);
697
777
  }
778
+ buildView(view, options) {
779
+ const viewName = view.name;
780
+ if (options.tables.has(viewName)) return;
781
+ if (view.materialized) throw new AlephaError("SQLite does not support materialized views");
782
+ const drizzleView = sqliteView(viewName, this.schemaToSqliteColumns(viewName, view.schema, /* @__PURE__ */ new Map(), options.tables)).existing();
783
+ options.tables.set(viewName, drizzleView);
784
+ }
698
785
  buildSequence(sequence, options) {
699
786
  throw new AlephaError("SQLite does not support sequences");
700
787
  }
@@ -733,6 +820,10 @@ var SqliteModelBuilder = class extends ModelBuilder {
733
820
  return target;
734
821
  }, config.actions);
735
822
  }
823
+ if (PG_GENERATED in value) {
824
+ const gen = value[PG_GENERATED];
825
+ col = col.generatedAlwaysAs(gen.expression, { mode: gen.mode ?? "virtual" });
826
+ }
736
827
  if (schema.required?.includes(key)) col = col.notNull();
737
828
  return {
738
829
  ...columns,
@@ -816,7 +907,7 @@ var SqliteModelBuilder = class extends ModelBuilder {
816
907
 
817
908
  //#endregion
818
909
  //#region ../../src/orm/core/providers/drivers/BunSqliteProvider.ts
819
- const envSchema = t.object({ DATABASE_URL: t.optional(t.text()) });
910
+ const envSchema = databaseEnvSchema;
820
911
  /**
821
912
  * Configuration options for the Bun SQLite database provider.
822
913
  */
@@ -947,6 +1038,17 @@ var CloudflareD1Provider = class extends DatabaseProvider {
947
1038
  const { rows } = await this.db.run(query);
948
1039
  return rows;
949
1040
  }
1041
+ /**
1042
+ * D1 does not support SQL-level transactions (BEGIN/COMMIT/ROLLBACK).
1043
+ * It rejects these statements and requires the JS `batch()` API for atomic
1044
+ * multi-statement operations instead.
1045
+ *
1046
+ * @see https://developers.cloudflare.com/d1/worker-api/d1-database/#batch-statements
1047
+ * @see https://github.com/drizzle-team/drizzle-orm/issues/2463
1048
+ */
1049
+ get supportsTransactions() {
1050
+ return false;
1051
+ }
950
1052
  onStart = $hook({
951
1053
  on: "start",
952
1054
  handler: async () => {
@@ -1278,6 +1380,54 @@ const getAttrFields = (schema, name) => {
1278
1380
  return fields;
1279
1381
  };
1280
1382
 
1383
+ //#endregion
1384
+ //#region ../../src/orm/core/providers/DbCacheProvider.ts
1385
+ /**
1386
+ * Database query cache using a simple in-memory Map.
1387
+ *
1388
+ * Uses `{tableName}:{cacheKey}` as the storage key.
1389
+ * Provides per-table invalidation for write-through cache busting.
1390
+ *
1391
+ * This is intentionally self-contained (no external cache dependencies)
1392
+ * so the ORM module does not force `AlephaCache` on all consumers.
1393
+ */
1394
+ var DbCacheProvider = class {
1395
+ store = /* @__PURE__ */ new Map();
1396
+ storeKey(tableName, cacheKey) {
1397
+ return `${tableName}:${cacheKey}`;
1398
+ }
1399
+ /**
1400
+ * Get a cached query result.
1401
+ */
1402
+ async get(tableName, cacheKey) {
1403
+ const key = this.storeKey(tableName, cacheKey);
1404
+ const entry = this.store.get(key);
1405
+ if (!entry) return void 0;
1406
+ if (entry.expiresAt && Date.now() > entry.expiresAt) {
1407
+ this.store.delete(key);
1408
+ return;
1409
+ }
1410
+ return entry.value;
1411
+ }
1412
+ /**
1413
+ * Store a query result in the cache.
1414
+ */
1415
+ async set(tableName, cacheKey, value, ttl) {
1416
+ const key = this.storeKey(tableName, cacheKey);
1417
+ this.store.set(key, {
1418
+ value,
1419
+ expiresAt: ttl ? Date.now() + ttl : void 0
1420
+ });
1421
+ }
1422
+ /**
1423
+ * Invalidate all cached queries for a table.
1424
+ */
1425
+ async invalidateTable(tableName) {
1426
+ const prefix = `${tableName}:`;
1427
+ for (const key of this.store.keys()) if (key.startsWith(prefix)) this.store.delete(key);
1428
+ }
1429
+ };
1430
+
1281
1431
  //#endregion
1282
1432
  //#region ../../src/orm/core/services/PgRelationManager.ts
1283
1433
  var PgRelationManager = class {
@@ -1402,6 +1552,14 @@ var QueryManager = class {
1402
1552
  });
1403
1553
  if (where) return not(where);
1404
1554
  }
1555
+ if (key === "exists") {
1556
+ conditions.push(exists(operator));
1557
+ continue;
1558
+ }
1559
+ if (key === "notExists") {
1560
+ conditions.push(notExists(operator));
1561
+ continue;
1562
+ }
1405
1563
  if (operator) {
1406
1564
  const column = col(key);
1407
1565
  const sql = this.mapOperatorToSql(operator, column, schema, key, options.dialect);
@@ -1581,6 +1739,7 @@ var Repository = class Repository {
1581
1739
  relationManager = $inject(PgRelationManager);
1582
1740
  queryManager = $inject(QueryManager);
1583
1741
  dateTimeProvider = $inject(DateTimeProvider);
1742
+ dbCache = new DbCacheProvider();
1584
1743
  alepha = $inject(Alepha);
1585
1744
  static of(entity, provider = DatabaseProvider) {
1586
1745
  return class InlineRepository extends Repository {
@@ -1592,7 +1751,8 @@ var Repository = class Repository {
1592
1751
  constructor(entity, provider = DatabaseProvider) {
1593
1752
  this.entity = entity;
1594
1753
  this.provider = this.alepha.inject(provider);
1595
- this.provider.registerEntity(entity);
1754
+ if (entity.isView) this.provider.registerView(entity);
1755
+ else this.provider.registerEntity(entity);
1596
1756
  }
1597
1757
  /**
1598
1758
  * Represents the primary key of the table.
@@ -1617,6 +1777,12 @@ var Repository = class Repository {
1617
1777
  return this.entity.name;
1618
1778
  }
1619
1779
  /**
1780
+ * Whether this repository is backed by a view (read-only).
1781
+ */
1782
+ get isReadOnly() {
1783
+ return this.entity.isView === true;
1784
+ }
1785
+ /**
1620
1786
  * Getter for the database connection from the database provider.
1621
1787
  *
1622
1788
  * Automatically picks up a transaction from `alepha.store` if one was set
@@ -1656,6 +1822,8 @@ var Repository = class Repository {
1656
1822
  } catch (error) {
1657
1823
  throw this.handleError(error, "Custom query has failed");
1658
1824
  }
1825
+ if (rows == null) return [];
1826
+ if (!Array.isArray(rows)) throw new DbError("Invalid query result. Expected an array of rows, but got: " + JSON.stringify(rows));
1659
1827
  return rows.map((it) => {
1660
1828
  return this.clean(this.mapRawFieldsToEntity(it), schema ?? this.entity.schema);
1661
1829
  });
@@ -1689,8 +1857,8 @@ var Repository = class Repository {
1689
1857
  * Run a transaction.
1690
1858
  */
1691
1859
  async transaction(transaction, config) {
1692
- if (this.provider.driver === "pglite") {
1693
- this.log.warn("Transactions are not supported with pglite driver");
1860
+ if (!this.provider.supportsTransactions) {
1861
+ this.log.warn(`Transactions are not supported with ${this.provider.driver} driver`);
1694
1862
  return await transaction(null);
1695
1863
  }
1696
1864
  this.log.debug(`Starting transaction on table ${this.tableName}`);
@@ -1736,6 +1904,11 @@ var Repository = class Repository {
1736
1904
  * > This method is the base for `find`, `findOne`, `findById`, and `paginate`.
1737
1905
  */
1738
1906
  async findMany(query = {}, opts = {}) {
1907
+ if (opts.cache) {
1908
+ const cacheKey = opts.cache.key ?? this.buildCacheKey("findMany", query);
1909
+ const cached = await this.dbCache.get(this.tableName, cacheKey);
1910
+ if (cached) return cached;
1911
+ }
1739
1912
  await this.alepha.events.emit("repository:read:before", {
1740
1913
  tableName: this.tableName,
1741
1914
  query
@@ -1783,7 +1956,12 @@ var Repository = class Repository {
1783
1956
  query,
1784
1957
  entities: rows
1785
1958
  });
1786
- return rows;
1959
+ const result = rows;
1960
+ if (opts.cache) {
1961
+ const cacheKey = opts.cache.key ?? this.buildCacheKey("findMany", query);
1962
+ await this.dbCache.set(this.tableName, cacheKey, result, opts.cache.ttl);
1963
+ }
1964
+ return result;
1787
1965
  } catch (error) {
1788
1966
  throw this.handleError(error, "Query select has failed");
1789
1967
  }
@@ -1883,12 +2061,14 @@ var Repository = class Repository {
1883
2061
  * @returns The ID of the created entity.
1884
2062
  */
1885
2063
  async create(data, opts = {}) {
2064
+ this.assertWritable();
1886
2065
  await this.alepha.events.emit("repository:create:before", {
1887
2066
  tableName: this.tableName,
1888
2067
  data
1889
2068
  });
1890
2069
  try {
1891
2070
  const entity = await this.rawInsert(opts).values(this.cast(data ?? {}, true)).returning(this.table).then(([it]) => this.clean(it, this.entity.schema));
2071
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
1892
2072
  await this.alepha.events.emit("repository:create:after", {
1893
2073
  tableName: this.tableName,
1894
2074
  data,
@@ -1909,6 +2089,7 @@ var Repository = class Repository {
1909
2089
  * @returns The created entities.
1910
2090
  */
1911
2091
  async createMany(values, opts = {}) {
2092
+ this.assertWritable();
1912
2093
  if (values.length === 0) return [];
1913
2094
  await this.alepha.events.emit("repository:create:before", {
1914
2095
  tableName: this.tableName,
@@ -1922,6 +2103,7 @@ var Repository = class Repository {
1922
2103
  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)));
1923
2104
  allEntities.push(...entities);
1924
2105
  }
2106
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
1925
2107
  await this.alepha.events.emit("repository:create:after", {
1926
2108
  tableName: this.tableName,
1927
2109
  data: values,
@@ -1962,6 +2144,7 @@ var Repository = class Repository {
1962
2144
  * ```
1963
2145
  */
1964
2146
  async upsert(data, opts = {}) {
2147
+ this.assertWritable();
1965
2148
  await this.alepha.events.emit("repository:create:before", {
1966
2149
  tableName: this.tableName,
1967
2150
  data
@@ -1982,6 +2165,7 @@ var Repository = class Repository {
1982
2165
  target: targetColumns,
1983
2166
  set: setData
1984
2167
  }).returning(this.table).then(([it]) => this.clean(it, this.entity.schema));
2168
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
1985
2169
  await this.alepha.events.emit("repository:create:after", {
1986
2170
  tableName: this.tableName,
1987
2171
  data,
@@ -1996,6 +2180,7 @@ var Repository = class Repository {
1996
2180
  * Find an entity and update it.
1997
2181
  */
1998
2182
  async updateOne(where, data, opts = {}) {
2183
+ this.assertWritable();
1999
2184
  await this.alepha.events.emit("repository:update:before", {
2000
2185
  tableName: this.tableName,
2001
2186
  where,
@@ -2013,6 +2198,7 @@ var Repository = class Repository {
2013
2198
  if (!response[0]) throw new DbEntityNotFoundError(this.tableName);
2014
2199
  try {
2015
2200
  const entity = this.clean(response[0], this.entity.schema);
2201
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2016
2202
  await this.alepha.events.emit("repository:update:after", {
2017
2203
  tableName: this.tableName,
2018
2204
  where,
@@ -2045,6 +2231,7 @@ var Repository = class Repository {
2045
2231
  * @see {@link DbVersionMismatchError}
2046
2232
  */
2047
2233
  async save(entity, opts = {}) {
2234
+ this.assertWritable();
2048
2235
  const row = entity;
2049
2236
  const id = row[this.id.key];
2050
2237
  if (id == null) throw new AlephaError("Cannot save entity without ID - missing primary key in value");
@@ -2082,6 +2269,7 @@ var Repository = class Repository {
2082
2269
  * Find many entities and update all of them.
2083
2270
  */
2084
2271
  async updateMany(where, data, opts = {}) {
2272
+ this.assertWritable();
2085
2273
  await this.alepha.events.emit("repository:update:before", {
2086
2274
  tableName: this.tableName,
2087
2275
  where,
@@ -2093,6 +2281,7 @@ var Repository = class Repository {
2093
2281
  data = this.cast(data, false);
2094
2282
  try {
2095
2283
  const entities = await this.rawUpdate(opts).set(data).where(this.toSQL(where)).returning();
2284
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2096
2285
  await this.alepha.events.emit("repository:update:after", {
2097
2286
  tableName: this.tableName,
2098
2287
  where,
@@ -2109,6 +2298,7 @@ var Repository = class Repository {
2109
2298
  * @returns Array of deleted entity IDs
2110
2299
  */
2111
2300
  async deleteMany(where = {}, opts = {}) {
2301
+ this.assertWritable();
2112
2302
  const deletedAt = this.deletedAt();
2113
2303
  if (deletedAt && !opts.force) return await this.updateMany(where, { [deletedAt.key]: opts.now ?? this.dateTimeProvider.nowISOString() }, opts);
2114
2304
  await this.alepha.events.emit("repository:delete:before", {
@@ -2117,6 +2307,7 @@ var Repository = class Repository {
2117
2307
  });
2118
2308
  try {
2119
2309
  const ids = (await this.rawDelete(opts).where(this.toSQL(where)).returning({ id: this.table[this.id.key] })).map((row) => row.id);
2310
+ this.dbCache.invalidateTable(this.tableName).catch(() => {});
2120
2311
  await this.alepha.events.emit("repository:delete:after", {
2121
2312
  tableName: this.tableName,
2122
2313
  where,
@@ -2176,6 +2367,97 @@ var Repository = class Repository {
2176
2367
  where = this.withDeletedAt(where, opts);
2177
2368
  return (opts.tx === null ? this.provider.db : opts.tx ?? this.db).$count(this.table, this.toSQL(where));
2178
2369
  }
2370
+ /**
2371
+ * Execute an aggregate query with type-safe select, groupBy, and having.
2372
+ *
2373
+ * @example
2374
+ * ```ts
2375
+ * const result = await repo.aggregate({
2376
+ * select: { category: true, amount: { sum: true, avg: true } },
2377
+ * groupBy: ["category"],
2378
+ * having: { amount: { sum: { gt: 100 } } },
2379
+ * orderBy: { column: "amount.sum", direction: "desc" },
2380
+ * });
2381
+ * // result: Array<{ category: string; amount: { sum: number; avg: number } }>
2382
+ * ```
2383
+ */
2384
+ async aggregate(query, opts = {}) {
2385
+ const AGG_SEPARATOR = "___";
2386
+ const flatFields = {};
2387
+ const aggFn = (op, column) => {
2388
+ switch (op) {
2389
+ case "count": return count(column);
2390
+ case "sum": return sum(column);
2391
+ case "avg": return avg(column);
2392
+ case "min": return min(column);
2393
+ case "max": return max(column);
2394
+ }
2395
+ };
2396
+ for (const [key, select] of Object.entries(query.select)) if (select === true) flatFields[key] = this.col(key);
2397
+ else if (typeof select === "object" && select !== null) {
2398
+ for (const op of Object.keys(select)) if (select[op]) flatFields[`${key}${AGG_SEPARATOR}${op}`] = aggFn(op, this.col(key));
2399
+ }
2400
+ let builder = (opts.tx === null ? this.provider.db : opts.tx ?? this.db).select(flatFields).from(this.table);
2401
+ if (query.where) {
2402
+ const where = this.withDeletedAt(query.where, opts);
2403
+ builder = builder.where(this.toSQL(where));
2404
+ }
2405
+ if (query.groupBy) builder = builder.groupBy(...query.groupBy.map((key) => this.col(key)));
2406
+ if (query.having) {
2407
+ const havingConditions = [];
2408
+ for (const [key, ops] of Object.entries(query.having)) {
2409
+ if (!ops || typeof ops !== "object") continue;
2410
+ for (const [op, comparisons] of Object.entries(ops)) {
2411
+ if (!comparisons || typeof comparisons !== "object") continue;
2412
+ const aggExpr = aggFn(op, this.col(key));
2413
+ for (const [cmp, val] of Object.entries(comparisons)) switch (cmp) {
2414
+ case "gt":
2415
+ havingConditions.push(gt(aggExpr, val));
2416
+ break;
2417
+ case "gte":
2418
+ havingConditions.push(gte(aggExpr, val));
2419
+ break;
2420
+ case "lt":
2421
+ havingConditions.push(lt(aggExpr, val));
2422
+ break;
2423
+ case "lte":
2424
+ havingConditions.push(lte(aggExpr, val));
2425
+ break;
2426
+ case "eq":
2427
+ havingConditions.push(eq(aggExpr, val));
2428
+ break;
2429
+ case "ne":
2430
+ havingConditions.push(ne(aggExpr, val));
2431
+ break;
2432
+ }
2433
+ }
2434
+ }
2435
+ if (havingConditions.length > 0) builder = builder.having(and(...havingConditions));
2436
+ }
2437
+ if (query.orderBy) {
2438
+ const clauses = this.queryManager.normalizeOrderBy(query.orderBy);
2439
+ builder = builder.orderBy(...clauses.map((clause) => {
2440
+ const col = flatFields[clause.column.includes(".") ? clause.column.replace(".", AGG_SEPARATOR) : clause.column];
2441
+ if (!col) throw new AlephaError(`Invalid orderBy column '${clause.column}' in aggregate query`);
2442
+ return clause.direction === "desc" ? desc(col) : asc(col);
2443
+ }));
2444
+ }
2445
+ if (query.limit) builder = builder.limit(query.limit);
2446
+ if (query.offset) builder = builder.offset(query.offset);
2447
+ try {
2448
+ return (await builder.execute()).map((row) => {
2449
+ const result = {};
2450
+ for (const [flatKey, value] of Object.entries(row)) if (flatKey.includes(AGG_SEPARATOR)) {
2451
+ const [col, op] = flatKey.split(AGG_SEPARATOR);
2452
+ if (!result[col]) result[col] = {};
2453
+ result[col][op] = value != null ? Number(value) : 0;
2454
+ } else result[flatKey] = value;
2455
+ return result;
2456
+ });
2457
+ } catch (error) {
2458
+ throw this.handleError(error, "Aggregate query has failed");
2459
+ }
2460
+ }
2179
2461
  errorPatterns = {
2180
2462
  conflict: ["duplicate key value violates unique constraint", "UNIQUE constraint failed"],
2181
2463
  foreignKey: ["violates foreign key constraint", "FOREIGN KEY constraint failed"],
@@ -2251,6 +2533,25 @@ var Repository = class Repository {
2251
2533
  return entity;
2252
2534
  }
2253
2535
  /**
2536
+ * Throw if this repository is read-only (backed by a view).
2537
+ */
2538
+ assertWritable() {
2539
+ if (this.isReadOnly) throw new AlephaError(`Cannot write to view '${this.tableName}'. Views are read-only.`);
2540
+ }
2541
+ /**
2542
+ * Refresh a materialized view. PostgreSQL only.
2543
+ */
2544
+ async refresh() {
2545
+ if (!this.entity.materialized) throw new AlephaError(`Cannot refresh '${this.tableName}'. Only materialized views support refresh.`);
2546
+ await this.provider.execute(`REFRESH MATERIALIZED VIEW ${this.tableName}`);
2547
+ }
2548
+ /**
2549
+ * Build a cache key from method name and query parameters.
2550
+ */
2551
+ buildCacheKey(method, query) {
2552
+ return `${method}:${JSON.stringify(query)}`;
2553
+ }
2554
+ /**
2254
2555
  * Convert a where clause to SQL.
2255
2556
  */
2256
2557
  toSQL(where, joins) {
@@ -2697,6 +2998,59 @@ function buildQueryString(where) {
2697
2998
  return parts.join("&");
2698
2999
  }
2699
3000
 
3001
+ //#endregion
3002
+ //#region ../../src/orm/core/primitives/$view.ts
3003
+ /**
3004
+ * Creates a database view primitive from a TypeBox schema and SQL query.
3005
+ *
3006
+ * Views are read-only: Repository blocks all write operations.
3007
+ *
3008
+ * @example
3009
+ * ```ts
3010
+ * import { t } from "alepha";
3011
+ * import { $view } from "alepha/orm";
3012
+ * import { sql } from "drizzle-orm";
3013
+ *
3014
+ * const userSummary = $view({
3015
+ * name: "user_summary",
3016
+ * schema: t.object({
3017
+ * id: t.uuid(),
3018
+ * fullName: t.text(),
3019
+ * orderCount: t.integer(),
3020
+ * }),
3021
+ * 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`,
3022
+ * });
3023
+ *
3024
+ * // Materialized view (PostgreSQL only)
3025
+ * const monthlyStats = $view({
3026
+ * name: "monthly_stats",
3027
+ * schema: t.object({ ... }),
3028
+ * query: sql`...`,
3029
+ * materialized: true,
3030
+ * });
3031
+ * ```
3032
+ */
3033
+ const $view = (options) => {
3034
+ return new ViewPrimitive(options);
3035
+ };
3036
+ var ViewPrimitive = class {
3037
+ options;
3038
+ isView = true;
3039
+ constructor(options) {
3040
+ this.options = options;
3041
+ }
3042
+ get name() {
3043
+ return this.options.name;
3044
+ }
3045
+ get schema() {
3046
+ return this.options.schema;
3047
+ }
3048
+ get materialized() {
3049
+ return this.options.materialized ?? false;
3050
+ }
3051
+ };
3052
+ $view[KIND] = ViewPrimitive;
3053
+
2700
3054
  //#endregion
2701
3055
  //#region ../../src/orm/core/providers/DatabaseTypeProvider.ts
2702
3056
  var DatabaseTypeProvider = class {
@@ -2817,7 +3171,7 @@ const legacyIdSchema = pgAttr(pgAttr(pgAttr(t.integer(), PG_PRIMARY_KEY), PG_SER
2817
3171
  //#endregion
2818
3172
  //#region ../../src/orm/core/primitives/$repository.ts
2819
3173
  /**
2820
- * Get the repository for the given entity.
3174
+ * Get the repository for the given entity or view.
2821
3175
  */
2822
3176
  const $repository = (entity) => {
2823
3177
  const { alepha } = $context();
@@ -2917,11 +3271,13 @@ var index_bun_exports = /* @__PURE__ */ __exportAll({
2917
3271
  $seed: () => $seed,
2918
3272
  $sequence: () => $sequence,
2919
3273
  $transactional: () => $transactional,
3274
+ $view: () => $view,
2920
3275
  AlephaOrm: () => AlephaOrm,
2921
3276
  BunSqliteProvider: () => BunSqliteProvider,
2922
3277
  CloudflareD1Provider: () => CloudflareD1Provider,
2923
3278
  DatabaseProvider: () => DatabaseProvider,
2924
3279
  DatabaseTypeProvider: () => DatabaseTypeProvider,
3280
+ DbCacheProvider: () => DbCacheProvider,
2925
3281
  DbColumnNotFoundError: () => DbColumnNotFoundError,
2926
3282
  DbConflictError: () => DbConflictError,
2927
3283
  DbConnectionError: () => DbConnectionError,
@@ -2940,6 +3296,7 @@ var index_bun_exports = /* @__PURE__ */ __exportAll({
2940
3296
  PG_DEFAULT: () => PG_DEFAULT,
2941
3297
  PG_DELETED_AT: () => PG_DELETED_AT,
2942
3298
  PG_ENUM: () => PG_ENUM,
3299
+ PG_GENERATED: () => PG_GENERATED,
2943
3300
  PG_IDENTITY: () => PG_IDENTITY,
2944
3301
  PG_PRIMARY_KEY: () => PG_PRIMARY_KEY,
2945
3302
  PG_REF: () => PG_REF,
@@ -2950,8 +3307,10 @@ var index_bun_exports = /* @__PURE__ */ __exportAll({
2950
3307
  RepositoryProvider: () => RepositoryProvider,
2951
3308
  SequencePrimitive: () => SequencePrimitive,
2952
3309
  SqliteProvider: () => SqliteProvider,
3310
+ ViewPrimitive: () => ViewPrimitive,
2953
3311
  buildQueryString: () => buildQueryString,
2954
3312
  bunSqliteOptions: () => bunSqliteOptions,
3313
+ databaseEnvSchema: () => databaseEnvSchema,
2955
3314
  db: () => db,
2956
3315
  drizzle: () => drizzle,
2957
3316
  getAttrFields: () => getAttrFields,
@@ -2982,7 +3341,7 @@ const AlephaOrm = $module({
2982
3341
  QueryManager
2983
3342
  ],
2984
3343
  register: (alepha) => {
2985
- const env = alepha.parseEnv(t.object({ DATABASE_URL: t.optional(t.text()) }));
3344
+ const env = alepha.parseEnv(databaseEnvSchema);
2986
3345
  alepha.with(DrizzleKitProvider);
2987
3346
  alepha.with(RepositoryProvider);
2988
3347
  const url = env.DATABASE_URL;
@@ -3004,5 +3363,5 @@ const AlephaOrm = $module({
3004
3363
  });
3005
3364
 
3006
3365
  //#endregion
3007
- export { $entity, $repository, $seed, $sequence, $transactional, AlephaOrm, BunSqliteProvider, CloudflareD1Provider, DatabaseProvider, DatabaseTypeProvider, DbColumnNotFoundError, DbConflictError, DbConnectionError, DbDeadlockError, DbEntityNotFoundError, DbError, DbForeignKeyError, DbMigrationError, DbNotNullError, DbTableNotFoundError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, ModelBuilder, 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, pageQuerySchema, pageSchema, parseQueryString, pgAttr, schema, sql, updateSchema };
3366
+ export { $entity, $repository, $seed, $sequence, $transactional, $view, AlephaOrm, BunSqliteProvider, CloudflareD1Provider, DatabaseProvider, DatabaseTypeProvider, DbCacheProvider, DbColumnNotFoundError, DbConflictError, DbConnectionError, DbDeadlockError, DbEntityNotFoundError, DbError, DbForeignKeyError, DbMigrationError, DbNotNullError, DbTableNotFoundError, DbVersionMismatchError, DrizzleKitProvider, EntityPrimitive, ModelBuilder, 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, pageQuerySchema, pageSchema, parseQueryString, pgAttr, schema, sql, updateSchema };
3008
3367
  //# sourceMappingURL=index.bun.js.map