alepha 0.19.1 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -9
  3. package/dist/api/audits/index.d.ts +378 -346
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/files/index.d.ts +216 -184
  6. package/dist/api/files/index.d.ts.map +1 -1
  7. package/dist/api/jobs/index.d.ts +528 -496
  8. package/dist/api/jobs/index.d.ts.map +1 -1
  9. package/dist/api/jobs/index.js +3 -3
  10. package/dist/api/jobs/index.js.map +1 -1
  11. package/dist/api/keys/index.d.ts +207 -207
  12. package/dist/api/keys/index.d.ts.map +1 -1
  13. package/dist/api/notifications/index.d.ts +152 -152
  14. package/dist/api/notifications/index.d.ts.map +1 -1
  15. package/dist/api/organizations/index.browser.js +48 -0
  16. package/dist/api/organizations/index.browser.js.map +1 -0
  17. package/dist/api/organizations/index.d.ts +516 -0
  18. package/dist/api/organizations/index.d.ts.map +1 -0
  19. package/dist/api/organizations/index.js +202 -0
  20. package/dist/api/organizations/index.js.map +1 -0
  21. package/dist/api/parameters/index.d.ts +391 -358
  22. package/dist/api/parameters/index.d.ts.map +1 -1
  23. package/dist/api/parameters/index.js +5 -1
  24. package/dist/api/parameters/index.js.map +1 -1
  25. package/dist/api/users/index.browser.js +7 -5
  26. package/dist/api/users/index.browser.js.map +1 -1
  27. package/dist/api/users/index.d.ts +978 -913
  28. package/dist/api/users/index.d.ts.map +1 -1
  29. package/dist/api/users/index.js +160 -112
  30. package/dist/api/users/index.js.map +1 -1
  31. package/dist/api/verifications/index.d.ts +135 -135
  32. package/dist/api/verifications/index.d.ts.map +1 -1
  33. package/dist/api/verifications/index.js +2 -2
  34. package/dist/api/verifications/index.js.map +1 -1
  35. package/dist/batch/index.d.ts +6 -6
  36. package/dist/batch/index.d.ts.map +1 -1
  37. package/dist/billing/index.d.ts +1048 -0
  38. package/dist/billing/index.d.ts.map +1 -0
  39. package/dist/billing/index.js +713 -0
  40. package/dist/billing/index.js.map +1 -0
  41. package/dist/bin/index.js +0 -2
  42. package/dist/bin/index.js.map +1 -1
  43. package/dist/bucket/index.d.ts +10 -10
  44. package/dist/bucket/index.d.ts.map +1 -1
  45. package/dist/bucket/index.js +2 -2
  46. package/dist/bucket/index.js.map +1 -1
  47. package/dist/cache/core/index.d.ts +9 -9
  48. package/dist/cache/core/index.d.ts.map +1 -1
  49. package/dist/cache/core/index.js +2 -2
  50. package/dist/cache/core/index.js.map +1 -1
  51. package/dist/cache/core/index.workerd.js +2 -2
  52. package/dist/cache/core/index.workerd.js.map +1 -1
  53. package/dist/cache/redis/index.d.ts +6 -6
  54. package/dist/cache/redis/index.d.ts.map +1 -1
  55. package/dist/cache/redis/index.js +2 -2
  56. package/dist/cache/redis/index.js.map +1 -1
  57. package/dist/cli/config/index.d.ts +12 -2
  58. package/dist/cli/config/index.d.ts.map +1 -1
  59. package/dist/cli/config/index.js +4 -0
  60. package/dist/cli/config/index.js.map +1 -1
  61. package/dist/cli/core/index.d.ts +183 -140
  62. package/dist/cli/core/index.d.ts.map +1 -1
  63. package/dist/cli/core/index.js +279 -89
  64. package/dist/cli/core/index.js.map +1 -1
  65. package/dist/cli/devtools/index.d.ts +45 -0
  66. package/dist/cli/devtools/index.d.ts.map +1 -0
  67. package/dist/cli/devtools/index.js +170 -0
  68. package/dist/cli/devtools/index.js.map +1 -0
  69. package/dist/cli/platform/index.d.ts +383 -492
  70. package/dist/cli/platform/index.d.ts.map +1 -1
  71. package/dist/cli/platform/index.js +42 -511
  72. package/dist/cli/platform/index.js.map +1 -1
  73. package/dist/cli/vendor/index.d.ts +196 -0
  74. package/dist/cli/vendor/index.d.ts.map +1 -0
  75. package/dist/cli/vendor/index.js +384 -0
  76. package/dist/cli/vendor/index.js.map +1 -0
  77. package/dist/command/index.d.ts +18 -18
  78. package/dist/command/index.d.ts.map +1 -1
  79. package/dist/command/index.js +2 -2
  80. package/dist/command/index.js.map +1 -1
  81. package/dist/core/index.browser.js +4 -4
  82. package/dist/core/index.browser.js.map +1 -1
  83. package/dist/core/index.d.ts +10 -10
  84. package/dist/core/index.d.ts.map +1 -1
  85. package/dist/core/index.js +4 -4
  86. package/dist/core/index.js.map +1 -1
  87. package/dist/core/index.native.js +4 -4
  88. package/dist/core/index.native.js.map +1 -1
  89. package/dist/core/index.workerd.js +4 -4
  90. package/dist/core/index.workerd.js.map +1 -1
  91. package/dist/crypto/index.d.ts +7 -7
  92. package/dist/crypto/index.d.ts.map +1 -1
  93. package/dist/datetime/index.d.ts +4 -4
  94. package/dist/datetime/index.d.ts.map +1 -1
  95. package/dist/email/brevo/index.d.ts +4 -4
  96. package/dist/email/brevo/index.d.ts.map +1 -1
  97. package/dist/email/core/index.d.ts +15 -11
  98. package/dist/email/core/index.d.ts.map +1 -1
  99. package/dist/email/core/index.js +12 -35
  100. package/dist/email/core/index.js.map +1 -1
  101. package/dist/email/smtp/index.d.ts +12 -12
  102. package/dist/email/smtp/index.d.ts.map +1 -1
  103. package/dist/email/smtp/index.js +7 -4
  104. package/dist/email/smtp/index.js.map +1 -1
  105. package/dist/fake/index.d.ts +4 -8
  106. package/dist/fake/index.d.ts.map +1 -1
  107. package/dist/fake/index.js +55 -889
  108. package/dist/fake/index.js.map +1 -1
  109. package/dist/lock/core/index.d.ts +13 -13
  110. package/dist/lock/core/index.d.ts.map +1 -1
  111. package/dist/lock/core/index.js +2 -2
  112. package/dist/lock/core/index.js.map +1 -1
  113. package/dist/lock/redis/index.d.ts +4 -4
  114. package/dist/lock/redis/index.d.ts.map +1 -1
  115. package/dist/logger/index.d.ts +16 -15
  116. package/dist/logger/index.d.ts.map +1 -1
  117. package/dist/logger/index.js +5 -2
  118. package/dist/logger/index.js.map +1 -1
  119. package/dist/mcp/index.d.ts +11 -11
  120. package/dist/mcp/index.d.ts.map +1 -1
  121. package/dist/mcp/index.js +2 -2
  122. package/dist/mcp/index.js.map +1 -1
  123. package/dist/orm/core/index.browser.js +11 -1
  124. package/dist/orm/core/index.browser.js.map +1 -1
  125. package/dist/orm/core/index.bun.js +53 -16
  126. package/dist/orm/core/index.bun.js.map +1 -1
  127. package/dist/orm/core/index.d.ts +95 -51
  128. package/dist/orm/core/index.d.ts.map +1 -1
  129. package/dist/orm/core/index.js +55 -14
  130. package/dist/orm/core/index.js.map +1 -1
  131. package/dist/orm/postgres/index.d.ts +18 -17
  132. package/dist/orm/postgres/index.d.ts.map +1 -1
  133. package/dist/queue/core/index.d.ts +14 -14
  134. package/dist/queue/core/index.d.ts.map +1 -1
  135. package/dist/queue/core/index.js +2 -2
  136. package/dist/queue/core/index.js.map +1 -1
  137. package/dist/queue/core/index.workerd.js +2 -2
  138. package/dist/queue/core/index.workerd.js.map +1 -1
  139. package/dist/queue/redis/index.d.ts +4 -4
  140. package/dist/queue/redis/index.d.ts.map +1 -1
  141. package/dist/queue/redis/index.js +2 -2
  142. package/dist/queue/redis/index.js.map +1 -1
  143. package/dist/react/auth/index.d.ts +9 -9
  144. package/dist/react/auth/index.d.ts.map +1 -1
  145. package/dist/react/core/index.d.ts +6 -6
  146. package/dist/react/core/index.d.ts.map +1 -1
  147. package/dist/react/core/index.js +5 -4
  148. package/dist/react/core/index.js.map +1 -1
  149. package/dist/react/form/index.d.ts +4 -4
  150. package/dist/react/form/index.d.ts.map +1 -1
  151. package/dist/react/head/index.d.ts +4 -4
  152. package/dist/react/head/index.d.ts.map +1 -1
  153. package/dist/react/i18n/index.d.ts +9 -9
  154. package/dist/react/i18n/index.d.ts.map +1 -1
  155. package/dist/react/intro/index.d.ts +2 -2
  156. package/dist/react/intro/index.d.ts.map +1 -1
  157. package/dist/react/intro/index.js +1 -1
  158. package/dist/react/intro/index.js.map +1 -1
  159. package/dist/react/router/index.browser.js +4 -5
  160. package/dist/react/router/index.browser.js.map +1 -1
  161. package/dist/react/router/index.d.ts +215 -215
  162. package/dist/react/router/index.d.ts.map +1 -1
  163. package/dist/react/router/index.js +6 -7
  164. package/dist/react/router/index.js.map +1 -1
  165. package/dist/react/testing/index.d.ts +2 -2
  166. package/dist/react/testing/index.d.ts.map +1 -1
  167. package/dist/react/testing/index.js +2 -4
  168. package/dist/react/testing/index.js.map +1 -1
  169. package/dist/redis/index.d.ts +19 -19
  170. package/dist/redis/index.d.ts.map +1 -1
  171. package/dist/retry/index.d.ts +4 -4
  172. package/dist/retry/index.d.ts.map +1 -1
  173. package/dist/scheduler/index.d.ts +13 -13
  174. package/dist/scheduler/index.d.ts.map +1 -1
  175. package/dist/scheduler/index.js +2 -2
  176. package/dist/scheduler/index.js.map +1 -1
  177. package/dist/scheduler/index.workerd.js +2 -2
  178. package/dist/scheduler/index.workerd.js.map +1 -1
  179. package/dist/security/index.browser.js +1 -1
  180. package/dist/security/index.browser.js.map +1 -1
  181. package/dist/security/index.d.ts +47 -47
  182. package/dist/security/index.d.ts.map +1 -1
  183. package/dist/security/index.js +9 -12
  184. package/dist/security/index.js.map +1 -1
  185. package/dist/server/auth/index.d.ts +170 -169
  186. package/dist/server/auth/index.d.ts.map +1 -1
  187. package/dist/server/auth/index.js +16 -2
  188. package/dist/server/auth/index.js.map +1 -1
  189. package/dist/server/cookies/index.d.ts +7 -7
  190. package/dist/server/cookies/index.d.ts.map +1 -1
  191. package/dist/server/core/index.d.ts +76 -76
  192. package/dist/server/core/index.d.ts.map +1 -1
  193. package/dist/server/core/index.js +23 -17
  194. package/dist/server/core/index.js.map +1 -1
  195. package/dist/server/cors/index.d.ts +13 -13
  196. package/dist/server/cors/index.d.ts.map +1 -1
  197. package/dist/server/cors/index.js +2 -2
  198. package/dist/server/cors/index.js.map +1 -1
  199. package/dist/server/etag/index.d.ts +9 -9
  200. package/dist/server/etag/index.d.ts.map +1 -1
  201. package/dist/server/health/index.d.ts +20 -20
  202. package/dist/server/health/index.d.ts.map +1 -1
  203. package/dist/server/links/index.browser.js +2 -2
  204. package/dist/server/links/index.browser.js.map +1 -1
  205. package/dist/server/links/index.d.ts +66 -66
  206. package/dist/server/links/index.d.ts.map +1 -1
  207. package/dist/server/links/index.js +4 -4
  208. package/dist/server/links/index.js.map +1 -1
  209. package/dist/server/metrics/index.d.ts +7 -7
  210. package/dist/server/metrics/index.d.ts.map +1 -1
  211. package/dist/server/proxy/index.d.ts +5 -5
  212. package/dist/server/proxy/index.d.ts.map +1 -1
  213. package/dist/server/rate-limit/index.d.ts +12 -12
  214. package/dist/server/rate-limit/index.d.ts.map +1 -1
  215. package/dist/server/rate-limit/index.js +2 -2
  216. package/dist/server/rate-limit/index.js.map +1 -1
  217. package/dist/server/static/index.d.ts +5 -5
  218. package/dist/server/static/index.d.ts.map +1 -1
  219. package/dist/server/swagger/index.d.ts +7 -7
  220. package/dist/server/swagger/index.d.ts.map +1 -1
  221. package/dist/server/swagger/index.js +2 -2
  222. package/dist/server/swagger/index.js.map +1 -1
  223. package/dist/sms/index.d.ts +11 -7
  224. package/dist/sms/index.d.ts.map +1 -1
  225. package/dist/sms/index.js +9 -15
  226. package/dist/sms/index.js.map +1 -1
  227. package/dist/system/index.d.ts +4 -4
  228. package/dist/system/index.d.ts.map +1 -1
  229. package/dist/topic/core/index.d.ts +6 -6
  230. package/dist/topic/core/index.d.ts.map +1 -1
  231. package/dist/topic/redis/index.d.ts +7 -7
  232. package/dist/topic/redis/index.d.ts.map +1 -1
  233. package/dist/topic/redis/index.js +2 -2
  234. package/dist/topic/redis/index.js.map +1 -1
  235. package/dist/websocket/index.d.ts +36 -36
  236. package/dist/websocket/index.d.ts.map +1 -1
  237. package/dist/websocket/index.js +2 -2
  238. package/dist/websocket/index.js.map +1 -1
  239. package/package.json +36 -14
  240. package/src/api/jobs/{services → __tests__}/JobService.spec.ts +1 -1
  241. package/src/api/jobs/providers/JobProvider.ts +3 -3
  242. package/src/api/keys/{services → __tests__}/ApiKeyService.spec.ts +1 -1
  243. package/src/api/organizations/__tests__/OrganizationService.spec.ts +193 -0
  244. package/src/api/organizations/controllers/AdminOrganizationController.ts +103 -0
  245. package/src/api/organizations/entities/organizations.ts +20 -0
  246. package/src/api/organizations/index.browser.ts +10 -0
  247. package/src/api/organizations/index.ts +31 -0
  248. package/src/api/organizations/schemas/createOrganizationSchema.ts +10 -0
  249. package/src/api/organizations/schemas/organizationQuerySchema.ts +10 -0
  250. package/src/api/organizations/schemas/organizationResourceSchema.ts +6 -0
  251. package/src/api/organizations/schemas/updateOrganizationSchema.ts +7 -0
  252. package/src/api/organizations/services/OrganizationService.ts +75 -0
  253. package/src/api/parameters/services/ParameterProvider.ts +6 -1
  254. package/src/api/users/{services → __tests__}/SessionService.spec.ts +67 -0
  255. package/src/api/users/{jobs → __tests__}/UserJobs.spec.ts +1 -1
  256. package/src/api/users/entities/users.ts +9 -3
  257. package/src/api/users/index.ts +23 -4
  258. package/src/api/users/primitives/$realm.ts +6 -4
  259. package/src/api/users/providers/RealmProvider.ts +1 -1
  260. package/src/api/users/services/RegistrationService.ts +1 -1
  261. package/src/api/users/services/SessionService.ts +92 -5
  262. package/src/api/users/services/UserService.ts +1 -1
  263. package/src/api/verifications/{jobs → __tests__}/VerificationJobs.spec.ts +4 -2
  264. package/src/api/verifications/parameters/VerificationParameters.ts +2 -2
  265. package/src/billing/__tests__/BillingService.spec.ts +136 -0
  266. package/src/billing/__tests__/PaymentMethodService.spec.ts +78 -0
  267. package/src/billing/controllers/AdminBillingController.ts +149 -0
  268. package/src/billing/controllers/BillingController.ts +108 -0
  269. package/src/billing/entities/paymentIntents.ts +34 -0
  270. package/src/billing/entities/paymentMethods.ts +24 -0
  271. package/src/billing/entities/refunds.ts +22 -0
  272. package/src/billing/errors/BillingError.ts +5 -0
  273. package/src/billing/index.ts +76 -0
  274. package/src/billing/providers/BillingProvider.ts +79 -0
  275. package/src/billing/providers/MemoryBillingProvider.ts +139 -0
  276. package/src/billing/schemas/intentSchemas.ts +60 -0
  277. package/src/billing/schemas/paymentMethodSchemas.ts +13 -0
  278. package/src/billing/schemas/refundSchemas.ts +6 -0
  279. package/src/billing/services/BillingService.ts +325 -0
  280. package/src/billing/services/PaymentMethodService.ts +82 -0
  281. package/src/bin/index.ts +0 -2
  282. package/src/bucket/providers/LocalFileStorageProvider.ts +2 -2
  283. package/src/cache/core/{primitives → __tests__}/$cache.middleware.spec.ts +1 -1
  284. package/src/cache/core/{providers → __tests__}/MemoryCacheProvider.spec.ts +1 -1
  285. package/src/cache/core/primitives/$cache.ts +2 -2
  286. package/src/cache/redis/providers/RedisCacheProvider.ts +2 -2
  287. package/src/cli/config/defineConfig.ts +20 -0
  288. package/src/cli/core/{services → __tests__}/ProjectScaffolder.spec.ts +1 -1
  289. package/src/cli/core/{commands/gen → __tests__}/changelog.spec.ts +1 -1
  290. package/src/cli/core/{commands → __tests__}/init.spec.ts +2 -8
  291. package/src/cli/core/atoms/devOptions.ts +0 -5
  292. package/src/cli/core/commands/build.ts +2 -2
  293. package/src/cli/core/commands/dev.ts +165 -30
  294. package/src/cli/core/commands/gen/changelog.ts +2 -2
  295. package/src/cli/core/commands/init.ts +2 -7
  296. package/src/cli/core/commands/verify.ts +0 -1
  297. package/src/cli/core/providers/AppEntryProvider.ts +2 -2
  298. package/src/cli/core/providers/ViteDevServerProvider.ts +54 -66
  299. package/src/cli/core/services/PackageManagerUtils.ts +8 -3
  300. package/src/cli/core/services/ProjectScaffolder.ts +18 -18
  301. package/src/cli/core/tasks/BuildClientTask.ts +8 -0
  302. package/src/cli/core/tasks/BuildServerTask.ts +17 -4
  303. package/src/cli/core/templates/alephaConfigTs.ts +0 -6
  304. package/src/cli/core/templates/webAdminDashboardTsx.ts +17 -0
  305. package/src/cli/core/templates/webAppRouterTs.ts +85 -2
  306. package/src/cli/devtools/atoms/devtoolsOptions.ts +26 -0
  307. package/src/cli/devtools/index.ts +194 -0
  308. package/src/cli/platform/{adapters → __tests__}/CloudflareAdapter.spec.ts +2 -2
  309. package/src/cli/platform/{providers → __tests__}/GitHubSecretStore.spec.ts +1 -1
  310. package/src/cli/platform/{services → __tests__}/NamingService.spec.ts +1 -1
  311. package/src/cli/platform/{providers → __tests__}/PlatformCacheProvider.spec.ts +1 -1
  312. package/src/cli/platform/{services → __tests__}/PlatformInspector.spec.ts +1 -1
  313. package/src/cli/platform/{services → __tests__}/PlatformOrchestrator.spec.ts +3 -3
  314. package/src/cli/platform/{services → __tests__}/SecretFilterService.spec.ts +1 -1
  315. package/src/cli/platform/{commands → __tests__}/SecretsCommand.spec.ts +1 -1
  316. package/src/cli/platform/{adapters → __tests__}/VercelAdapter.spec.ts +2 -2
  317. package/src/cli/platform/atoms/platformOptions.ts +2 -10
  318. package/src/cli/platform/commands/SecretsCommand.ts +2 -2
  319. package/src/cli/platform/commands/platform.ts +2 -11
  320. package/src/cli/platform/index.ts +34 -11
  321. package/src/cli/platform/services/PlatformInspector.ts +2 -2
  322. package/src/cli/platform/services/PlatformOrchestrator.ts +0 -9
  323. package/src/cli/vendor/__tests__/VendorService.spec.ts +407 -0
  324. package/src/cli/vendor/atoms/vendorOptions.ts +41 -0
  325. package/src/cli/vendor/commands/VendorCommand.ts +204 -0
  326. package/src/cli/vendor/index.ts +43 -0
  327. package/src/cli/vendor/services/VendorService.ts +338 -0
  328. package/src/command/{providers → __tests__}/CliProvider.spec.ts +1 -1
  329. package/src/command/{helpers → __tests__}/EnvUtils.spec.ts +1 -1
  330. package/src/command/providers/CliProvider.ts +2 -2
  331. package/src/core/{primitives → __tests__}/$atom.spec.ts +2 -2
  332. package/src/core/{primitives → __tests__}/$memoize.spec.ts +1 -1
  333. package/src/core/{primitives → __tests__}/$mode.spec.ts +1 -1
  334. package/src/core/{primitives → __tests__}/$pipeline.spec.ts +1 -1
  335. package/src/core/{primitives → __tests__}/$scope.spec.ts +2 -2
  336. package/src/core/{providers → __tests__}/KeylessJsonSchemaCodec.spec.ts +1 -1
  337. package/src/core/{providers → __tests__}/SchemaValidator.spec.ts +1 -1
  338. package/src/core/{helpers → __tests__}/jsonSchemaToTypeBox.spec.ts +1 -1
  339. package/src/core/index.shared.ts +1 -1
  340. package/src/core/primitives/{$use.ts → $state.ts} +4 -4
  341. package/src/crypto/{providers → __tests__}/BrowserCryptoProvider.browser.spec.ts +1 -1
  342. package/src/crypto/{providers → __tests__}/CryptoProvider.spec.ts +1 -1
  343. package/src/datetime/{primitives → __tests__}/$debounce.spec.ts +1 -1
  344. package/src/datetime/{primitives → __tests__}/$throttle.spec.ts +1 -1
  345. package/src/datetime/{primitives → __tests__}/$timeout.spec.ts +1 -1
  346. package/src/email/brevo/{providers → __tests__}/BrevoEmailProvider.spec.ts +1 -1
  347. package/src/email/core/{providers → __tests__}/LocalEmailProvider.spec.ts +39 -150
  348. package/src/email/core/providers/LocalEmailProvider.ts +13 -51
  349. package/src/email/smtp/providers/NodemailerEmailProvider.ts +2 -2
  350. package/src/lock/core/{primitives → __tests__}/$lock.middleware.spec.ts +1 -1
  351. package/src/lock/core/primitives/$lock.ts +2 -2
  352. package/src/logger/index.ts +10 -4
  353. package/src/mcp/transports/SseMcpTransport.ts +2 -2
  354. package/src/orm/__tests__/ModelBuilder-tests.ts +53 -0
  355. package/src/orm/__tests__/ModelBuilder.spec.ts +80 -0
  356. package/src/orm/__tests__/organization-tests.ts +200 -0
  357. package/src/orm/__tests__/organization.spec.ts +103 -0
  358. package/src/orm/core/{providers/drivers → __tests__}/BunSqliteProvider.bun.spec.ts +5 -2
  359. package/src/orm/core/constants/PG_SYMBOLS.ts +2 -0
  360. package/src/orm/core/index.shared.ts +1 -0
  361. package/src/orm/core/primitives/$entity.ts +31 -0
  362. package/src/orm/core/providers/DatabaseTypeProvider.ts +11 -0
  363. package/src/orm/core/providers/DrizzleKitProvider.ts +1 -1
  364. package/src/orm/core/providers/drivers/BunSqliteProvider.ts +2 -2
  365. package/src/orm/core/providers/drivers/NodeSqliteProvider.ts +3 -3
  366. package/src/orm/core/services/ModelBuilder.ts +11 -0
  367. package/src/orm/core/services/QueryManager.ts +16 -2
  368. package/src/orm/core/services/Repository.ts +70 -10
  369. package/src/orm/postgres/{providers → __tests__}/BunPostgresProvider.bun.spec.ts +1 -1
  370. package/src/queue/core/providers/WorkerProvider.ts +2 -2
  371. package/src/queue/redis/providers/RedisQueueProvider.ts +2 -2
  372. package/src/react/core/{hooks → __tests__}/useAction.browser.spec.tsx +1 -1
  373. package/src/react/core/hooks/useAction.ts +7 -6
  374. package/src/react/head/{providers → __tests__}/BrowserHeadProvider.browser.spec.ts +1 -1
  375. package/src/react/head/{helpers → __tests__}/SeoExpander.spec.ts +1 -1
  376. package/src/react/i18n/{providers → __tests__}/I18nProvider.spec.ts +1 -1
  377. package/src/react/i18n/{hooks → __tests__}/useI18n.browser.spec.tsx +1 -1
  378. package/src/react/intro/components/GettingStartedDevtoolsSlide.tsx +1 -1
  379. package/src/react/router/{providers → __tests__}/ReactBrowserProvider.browser.spec.ts +1 -1
  380. package/src/react/router/providers/ReactBrowserProvider.ts +2 -2
  381. package/src/react/router/providers/ReactPageProvider.ts +2 -2
  382. package/src/react/router/providers/ReactServerProvider.ts +3 -3
  383. package/src/redis/{providers → __tests__}/BunRedisProvider.bun.spec.ts +4 -4
  384. package/src/retry/{primitives → __tests__}/$retry.middleware.spec.ts +1 -1
  385. package/src/router/{TemplatedPathParser.spec.ts → __tests__/TemplatedPathParser.spec.ts} +1 -1
  386. package/src/scheduler/primitives/$scheduler.ts +2 -2
  387. package/src/security/{primitives → __tests__}/$secure-browser.spec.ts +1 -1
  388. package/src/security/{primitives → __tests__}/$secure.spec.ts +1 -1
  389. package/src/security/primitives/$issuer.ts +1 -1
  390. package/src/security/providers/JwtProvider.ts +6 -10
  391. package/src/security/providers/SecurityProvider.ts +6 -11
  392. package/src/security/schemas/userAccountInfoSchema.ts +3 -3
  393. package/src/server/auth/providers/ServerAuthProvider.ts +24 -2
  394. package/src/server/cookies/{services → __tests__}/CookieParser.spec.ts +1 -1
  395. package/src/server/core/{primitives → __tests__}/$circuit.spec.ts +1 -1
  396. package/src/server/core/{providers → __tests__}/NodeHttpServerProvider.spec.ts +1 -1
  397. package/src/server/core/{providers → __tests__}/ServerBodyParserProvider.spec.ts +31 -1
  398. package/src/server/core/{providers → __tests__}/ServerCompressProvider.spec.ts +1 -1
  399. package/src/server/core/{providers → __tests__}/ServerHelmetProvider.spec.ts +4 -1
  400. package/src/server/core/{providers → __tests__}/ServerMultipartProvider.spec.ts +1 -1
  401. package/src/server/core/{services → __tests__}/ServerRequestParser.spec.ts +1 -1
  402. package/src/server/core/primitives/$action.ts +2 -2
  403. package/src/server/core/primitives/$sse.ts +2 -2
  404. package/src/server/core/providers/ServerBodyParserProvider.ts +21 -12
  405. package/src/server/core/providers/ServerCompressProvider.ts +2 -2
  406. package/src/server/core/providers/ServerHelmetProvider.ts +2 -2
  407. package/src/server/core/providers/ServerMultipartProvider.ts +2 -2
  408. package/src/server/core/providers/ServerRouterProvider.ts +1 -5
  409. package/src/server/cors/{primitives → __tests__}/$cors.spec.ts +1 -1
  410. package/src/server/cors/providers/ServerCorsProvider.ts +2 -2
  411. package/src/server/links/{services → __tests__}/BatchCollector.spec.ts +1 -1
  412. package/src/server/links/providers/LinkProvider.ts +2 -2
  413. package/src/server/links/providers/RemotePrimitiveProvider.ts +2 -2
  414. package/src/server/links/providers/ServerLinksProvider.ts +2 -2
  415. package/src/server/rate-limit/{primitives → __tests__}/$rateLimit.spec.ts +1 -1
  416. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +2 -2
  417. package/src/server/swagger/providers/ServerSwaggerProvider.ts +2 -2
  418. package/src/sms/{providers → __tests__}/LocalSmsProvider.spec.ts +35 -29
  419. package/src/sms/providers/LocalSmsProvider.ts +13 -24
  420. package/src/system/{providers → __tests__}/MemoryFileSystemProvider.spec.ts +1 -1
  421. package/src/system/{providers → __tests__}/MemoryShellProvider.spec.ts +1 -1
  422. package/src/topic/redis/providers/RedisTopicProvider.ts +2 -2
  423. package/src/websocket/{services → __tests__}/RoomManager.spec.ts +1 -1
  424. package/src/websocket/providers/NodeWebSocketServerProvider.ts +2 -2
  425. package/tsconfig.base.json +1 -0
  426. package/src/cli/platform/adapters/DockerAdapter.spec.ts +0 -378
  427. package/src/cli/platform/adapters/DockerAdapter.ts +0 -417
  428. package/src/cli/platform/services/DockerComposeGenerator.spec.ts +0 -490
  429. package/src/cli/platform/services/DockerComposeGenerator.ts +0 -353
  430. package/src/cli/platform/services/DockerSshService.spec.ts +0 -47
  431. package/src/cli/platform/services/DockerSshService.ts +0 -61
  432. /package/src/api/audits/{primitives → __tests__}/$audit.spec.ts +0 -0
  433. /package/src/api/audits/{services → __tests__}/AuditService.spec.ts +0 -0
  434. /package/src/api/files/{controllers → __tests__}/AdminFileStatsController.spec.ts +0 -0
  435. /package/src/api/files/{controllers → __tests__}/FileController.spec.ts +0 -0
  436. /package/src/api/files/{jobs → __tests__}/FileJobs.spec.ts +0 -0
  437. /package/src/api/files/{services → __tests__}/FileService.spec.ts +0 -0
  438. /package/src/api/jobs/{primitives → __tests__}/$job-middleware.spec.ts +0 -0
  439. /package/src/api/parameters/{primitives → __tests__}/$parameter.spec.ts +0 -0
  440. /package/src/api/users/{primitives → __tests__}/$realm.spec.ts +0 -0
  441. /package/src/api/users/{controllers → __tests__}/AdminIdentityController.spec.ts +0 -0
  442. /package/src/api/users/{controllers → __tests__}/AdminSessionController.spec.ts +0 -0
  443. /package/src/api/users/{controllers → __tests__}/AdminUserController.spec.ts +0 -0
  444. /package/src/api/users/{services → __tests__}/CredentialService.spec.ts +0 -0
  445. /package/src/api/users/{providers → __tests__}/RealmProvider.spec.ts +0 -0
  446. /package/src/api/users/{services → __tests__}/RegistrationService.spec.ts +0 -0
  447. /package/src/batch/{primitives → __tests__}/$batch.spec.ts +0 -0
  448. /package/src/batch/{providers → __tests__}/BatchProvider.spec.ts +0 -0
  449. /package/src/bucket/{primitives → __tests__}/$bucket.spec.ts +0 -0
  450. /package/src/bucket/{providers → __tests__}/FileStorageProvider.spec.ts +0 -0
  451. /package/src/bucket/{providers → __tests__}/LocalFileStorageProvider.spec.ts +0 -0
  452. /package/src/bucket/{providers → __tests__}/MemoryFileStorageProvider.spec.ts +0 -0
  453. /package/src/cache/core/{primitives → __tests__}/$cache.spec.ts +0 -0
  454. /package/src/cache/redis/{providers → __tests__}/RedisCacheProvider.spec.ts +0 -0
  455. /package/src/command/{primitives → __tests__}/$command.spec.ts +0 -0
  456. /package/src/command/{helpers → __tests__}/Asker.spec.ts +0 -0
  457. /package/src/command/{helpers → __tests__}/Runner.spec.ts +0 -0
  458. /package/src/core/{primitives → __tests__}/$context.spec.ts +0 -0
  459. /package/src/core/{primitives → __tests__}/$env.spec.ts +0 -0
  460. /package/src/core/{primitives → __tests__}/$hook.spec.ts +0 -0
  461. /package/src/core/{primitives → __tests__}/$inject.spec.ts +0 -0
  462. /package/src/core/{primitives → __tests__}/$module.spec.ts +0 -0
  463. /package/src/core/{providers → __tests__}/CodecManager.spec.ts +0 -0
  464. /package/src/core/{providers → __tests__}/EventManager.spec.ts +0 -0
  465. /package/src/core/{providers → __tests__}/StateManager.spec.ts +0 -0
  466. /package/src/core/{providers → __tests__}/TypeProvider.spec.ts +0 -0
  467. /package/src/datetime/{primitives → __tests__}/$interval.spec.ts +0 -0
  468. /package/src/datetime/{providers → __tests__}/DateTimeProvider.spec.ts +0 -0
  469. /package/src/email/core/{primitives → __tests__}/$email.spec.ts +0 -0
  470. /package/src/fake/{providers → __tests__}/FakeProvider.spec.ts +0 -0
  471. /package/src/lock/core/{providers → __tests__}/MemoryLockProvider.spec.ts +0 -0
  472. /package/src/lock/redis/{providers → __tests__}/RedisLockProvider.spec.ts +0 -0
  473. /package/src/logger/{primitives → __tests__}/$logger.spec.ts +0 -0
  474. /package/src/logger/{services → __tests__}/Logger.spec.ts +0 -0
  475. /package/src/mcp/{primitives → __tests__}/$prompt.spec.ts +0 -0
  476. /package/src/mcp/{primitives → __tests__}/$resource.spec.ts +0 -0
  477. /package/src/mcp/{primitives → __tests__}/$tool.spec.ts +0 -0
  478. /package/src/mcp/{providers → __tests__}/McpServerProvider.spec.ts +0 -0
  479. /package/src/mcp/{helpers → __tests__}/jsonrpc.spec.ts +0 -0
  480. /package/src/orm/core/{helpers → __tests__}/parseQueryString.spec.ts +0 -0
  481. /package/src/queue/core/{primitives → __tests__}/$consumer.spec.ts +0 -0
  482. /package/src/queue/core/{providers → __tests__}/MemoryQueueProvider.spec.ts +0 -0
  483. /package/src/queue/core/{providers → __tests__}/WorkerProvider.spec.ts +0 -0
  484. /package/src/queue/redis/{providers → __tests__}/RedisQueueProvider.spec.ts +0 -0
  485. /package/src/react/form/{hooks → __tests__}/useForm.browser.spec.tsx +0 -0
  486. /package/src/react/head/{hooks → __tests__}/useHead.spec.tsx +0 -0
  487. /package/src/react/i18n/{components → __tests__}/Localize.spec.tsx +0 -0
  488. /package/src/react/router/{primitives → __tests__}/$page.browser.spec.tsx +0 -0
  489. /package/src/react/router/{primitives → __tests__}/$page.middleware.spec.tsx +0 -0
  490. /package/src/react/router/{primitives → __tests__}/$page.spec.tsx +0 -0
  491. /package/src/react/router/{providers → __tests__}/ReactPreloadProvider.spec.ts +0 -0
  492. /package/src/react/router/{providers → __tests__}/ReactServerProvider.spec.tsx +0 -0
  493. /package/src/react/router/{providers → __tests__}/ReactServerTemplateProvider.spec.ts +0 -0
  494. /package/src/retry/{primitives → __tests__}/$retry.spec.ts +0 -0
  495. /package/src/retry/{providers → __tests__}/RetryProvider.spec.ts +0 -0
  496. /package/src/router/{providers → __tests__}/RouterProvider.spec.ts +0 -0
  497. /package/src/security/{primitives → __tests__}/$issuer.spec.ts +0 -0
  498. /package/src/security/{primitives → __tests__}/$permission.spec.ts +0 -0
  499. /package/src/security/{primitives → __tests__}/$role.spec.ts +0 -0
  500. /package/src/security/{primitives → __tests__}/$serviceAccount.spec.ts +0 -0
  501. /package/src/security/{providers → __tests__}/SecurityProvider.spec.ts +0 -0
  502. /package/src/server/cookies/{providers → __tests__}/ServerCookiesProvider.spec.ts +0 -0
  503. /package/src/server/core/{primitives → __tests__}/$action.spec.ts +0 -0
  504. /package/src/server/core/{primitives → __tests__}/$middleware.spec.ts +0 -0
  505. /package/src/server/core/{primitives → __tests__}/$route.spec.ts +0 -0
  506. /package/src/server/core/{primitives → __tests__}/$sse.spec.ts +0 -0
  507. /package/src/server/core/{providers → __tests__}/BunHttpServerProvider.bun.spec.ts +0 -0
  508. /package/src/server/core/{services → __tests__}/HttpClient.spec.ts +0 -0
  509. /package/src/server/core/{providers → __tests__}/ServerLoggerProvider.spec.ts +0 -0
  510. /package/src/server/core/{services → __tests__}/UserAgentParser.spec.ts +0 -0
  511. /package/src/server/cors/{providers → __tests__}/ServerCorsProvider.spec.ts +0 -0
  512. /package/src/server/etag/{providers → __tests__}/ServerEtagProvider.spec.ts +0 -0
  513. /package/src/server/health/{providers → __tests__}/ServerHealthProvider.spec.ts +0 -0
  514. /package/src/server/links/{primitives → __tests__}/$remote.spec.ts +0 -0
  515. /package/src/server/links/{services → __tests__}/BatchEndpoint.spec.ts +0 -0
  516. /package/src/server/links/{providers → __tests__}/LinkProvider.spec.ts +0 -0
  517. /package/src/server/links/{providers → __tests__}/ServerLinksProvider.spec.ts +0 -0
  518. /package/src/server/metrics/{providers → __tests__}/ServerMetricsProvider.spec.ts +0 -0
  519. /package/src/server/proxy/{primitives → __tests__}/$proxy.spec.ts +0 -0
  520. /package/src/server/rate-limit/{providers → __tests__}/ServerRateLimitProvider.spec.ts +0 -0
  521. /package/src/server/static/{primitives → __tests__}/$serve.spec.ts +0 -0
  522. /package/src/server/swagger/{primitives → __tests__}/$swagger.spec.ts +0 -0
  523. /package/src/sms/{primitives → __tests__}/$sms.spec.ts +0 -0
  524. /package/src/sms/{providers → __tests__}/MemorySmsProvider.spec.ts +0 -0
  525. /package/src/system/{services → __tests__}/FileDetector.spec.ts +0 -0
  526. /package/src/system/{providers → __tests__}/NodeFileSystemProvider.spec.ts +0 -0
  527. /package/src/topic/core/{primitives → __tests__}/$subscriber.spec.ts +0 -0
  528. /package/src/topic/core/{providers → __tests__}/MemoryTopicProvider.spec.ts +0 -0
  529. /package/src/topic/redis/{providers → __tests__}/RedisTopicProvider.spec.ts +0 -0
  530. /package/src/websocket/{primitives → __tests__}/$channel.spec.ts +0 -0
@@ -0,0 +1,200 @@
1
+ import { type Alepha, t } from "alepha";
2
+ import { currentUserAtom } from "alepha/security";
3
+ import { expect } from "vitest";
4
+ import { $entity, $repository, db } from "../core/index.ts";
5
+
6
+ const entity = $entity({
7
+ name: "test_org_entity",
8
+ schema: t.object({
9
+ id: db.primaryKey(),
10
+ organization: db.organization(),
11
+ name: t.optional(t.text()),
12
+ }),
13
+ });
14
+
15
+ class App {
16
+ repository = $repository(entity);
17
+ }
18
+
19
+ const setup = async (alepha: Alepha) => {
20
+ const app = alepha.inject(App);
21
+ await alepha.start();
22
+ return { repository: app.repository, alepha };
23
+ };
24
+
25
+ export const testOrgUserSeesOwnAndGlobalRows = async (alepha: Alepha) => {
26
+ const { repository, alepha: app } = await setup(alepha);
27
+
28
+ // Create rows for org-a, org-b, and global (null)
29
+ await repository.create({
30
+ name: "org-a-row",
31
+ organization: "a0000000-0000-0000-0000-000000000001",
32
+ });
33
+ await repository.create({
34
+ name: "org-b-row",
35
+ organization: "b0000000-0000-0000-0000-000000000002",
36
+ });
37
+ await repository.create({ name: "global-row" });
38
+
39
+ // User in org-a should see org-a + global
40
+ app.store.set(currentUserAtom, {
41
+ id: "user-1",
42
+ organization: "a0000000-0000-0000-0000-000000000001",
43
+ });
44
+
45
+ const results = await repository.findMany();
46
+ expect(results).toHaveLength(2);
47
+ expect(results.map((r: any) => r.name).sort()).toEqual([
48
+ "global-row",
49
+ "org-a-row",
50
+ ]);
51
+
52
+ // Count should also be filtered
53
+ expect(await repository.count()).toEqual(2);
54
+ };
55
+
56
+ export const testMasterUserSeesEverything = async (alepha: Alepha) => {
57
+ const { repository, alepha: app } = await setup(alepha);
58
+
59
+ await repository.create({
60
+ name: "org-a-row",
61
+ organization: "a0000000-0000-0000-0000-000000000001",
62
+ });
63
+ await repository.create({
64
+ name: "org-b-row",
65
+ organization: "b0000000-0000-0000-0000-000000000002",
66
+ });
67
+ await repository.create({ name: "global-row" });
68
+
69
+ // Master user (no org) sees everything
70
+ app.store.set(currentUserAtom, {
71
+ id: "master-user",
72
+ });
73
+
74
+ const results = await repository.findMany();
75
+ expect(results).toHaveLength(3);
76
+ expect(await repository.count()).toEqual(3);
77
+ };
78
+
79
+ export const testNoUserSeesEverything = async (alepha: Alepha) => {
80
+ const { repository } = await setup(alepha);
81
+
82
+ await repository.create({
83
+ name: "org-a-row",
84
+ organization: "a0000000-0000-0000-0000-000000000001",
85
+ });
86
+ await repository.create({ name: "global-row" });
87
+
88
+ // No user in context = no filter
89
+ const results = await repository.findMany();
90
+ expect(results).toHaveLength(2);
91
+ };
92
+
93
+ export const testAutoStampOnCreate = async (alepha: Alepha) => {
94
+ const { repository, alepha: app } = await setup(alepha);
95
+
96
+ app.store.set(currentUserAtom, {
97
+ id: "user-1",
98
+ organization: "a0000000-0000-0000-0000-000000000001",
99
+ });
100
+
101
+ // Create without specifying organization — should be auto-stamped
102
+ const entity = await repository.create({ name: "auto-stamped" });
103
+ expect(entity.organization).toEqual("a0000000-0000-0000-0000-000000000001");
104
+ };
105
+
106
+ export const testAutoStampNullForMasterUser = async (alepha: Alepha) => {
107
+ const { repository, alepha: app } = await setup(alepha);
108
+
109
+ app.store.set(currentUserAtom, {
110
+ id: "master-user",
111
+ });
112
+
113
+ // Master user creates a row — org stays null (global)
114
+ const entity = await repository.create({ name: "master-row" });
115
+ expect(entity.organization).toBeUndefined();
116
+ };
117
+
118
+ export const testAutoStampDoesNotOverrideExplicit = async (alepha: Alepha) => {
119
+ const { repository, alepha: app } = await setup(alepha);
120
+
121
+ app.store.set(currentUserAtom, {
122
+ id: "user-1",
123
+ organization: "a0000000-0000-0000-0000-000000000001",
124
+ });
125
+
126
+ // Explicitly set organization — should not be overridden
127
+ const entity = await repository.create({
128
+ name: "explicit-org",
129
+ organization: "b0000000-0000-0000-0000-000000000002",
130
+ });
131
+ expect(entity.organization).toEqual("b0000000-0000-0000-0000-000000000002");
132
+ };
133
+
134
+ export const testAutoStampOnCreateMany = async (alepha: Alepha) => {
135
+ const { repository, alepha: app } = await setup(alepha);
136
+
137
+ app.store.set(currentUserAtom, {
138
+ id: "user-1",
139
+ organization: "a0000000-0000-0000-0000-000000000001",
140
+ });
141
+
142
+ const entities = await repository.createMany([
143
+ { name: "row-1" },
144
+ { name: "row-2" },
145
+ ]);
146
+ expect(entities[0].organization).toEqual(
147
+ "a0000000-0000-0000-0000-000000000001",
148
+ );
149
+ expect(entities[1].organization).toEqual(
150
+ "a0000000-0000-0000-0000-000000000001",
151
+ );
152
+ };
153
+
154
+ export const testOrgFilterOnUpdateOne = async (alepha: Alepha) => {
155
+ const { repository, alepha: app } = await setup(alepha);
156
+
157
+ const row = await repository.create({
158
+ name: "org-b-row",
159
+ organization: "b0000000-0000-0000-0000-000000000002",
160
+ });
161
+
162
+ // User in org-a cannot update org-b row
163
+ app.store.set(currentUserAtom, {
164
+ id: "user-1",
165
+ organization: "a0000000-0000-0000-0000-000000000001",
166
+ });
167
+
168
+ const updated = await repository.updateMany(
169
+ { id: { eq: row.id } },
170
+ { name: "hacked" },
171
+ );
172
+ expect(updated).toHaveLength(0);
173
+
174
+ // Verify row is unchanged (read as master)
175
+ app.store.set(currentUserAtom, { id: "master" });
176
+ const check = await repository.getById(row.id);
177
+ expect(check.name).toEqual("org-b-row");
178
+ };
179
+
180
+ export const testOrgFilterOnDelete = async (alepha: Alepha) => {
181
+ const { repository, alepha: app } = await setup(alepha);
182
+
183
+ const row = await repository.create({
184
+ name: "org-b-row",
185
+ organization: "b0000000-0000-0000-0000-000000000002",
186
+ });
187
+
188
+ // User in org-a cannot delete org-b row
189
+ app.store.set(currentUserAtom, {
190
+ id: "user-1",
191
+ organization: "a0000000-0000-0000-0000-000000000001",
192
+ });
193
+
194
+ const deleted = await repository.deleteMany({ id: { eq: row.id } });
195
+ expect(deleted).toHaveLength(0);
196
+
197
+ // Verify row still exists
198
+ app.store.set(currentUserAtom, { id: "master" });
199
+ expect(await repository.count()).toEqual(1);
200
+ };
@@ -0,0 +1,103 @@
1
+ import { Alepha } from "alepha";
2
+ import { describe, it } from "vitest";
3
+ import { AlephaOrmPostgres } from "../postgres/index.ts";
4
+ import {
5
+ testAutoStampDoesNotOverrideExplicit,
6
+ testAutoStampNullForMasterUser,
7
+ testAutoStampOnCreate,
8
+ testAutoStampOnCreateMany,
9
+ testMasterUserSeesEverything,
10
+ testNoUserSeesEverything,
11
+ testOrgFilterOnDelete,
12
+ testOrgFilterOnUpdateOne,
13
+ testOrgUserSeesOwnAndGlobalRows,
14
+ } from "./organization-tests.ts";
15
+
16
+ describe("organization", () => {
17
+ it("org user sees own + global rows (sqlite)", async () => {
18
+ await testOrgUserSeesOwnAndGlobalRows(
19
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
20
+ );
21
+ });
22
+ it("org user sees own + global rows (postgres)", async () => {
23
+ await testOrgUserSeesOwnAndGlobalRows(
24
+ Alepha.create().with(AlephaOrmPostgres),
25
+ );
26
+ });
27
+
28
+ it("master user sees everything (sqlite)", async () => {
29
+ await testMasterUserSeesEverything(
30
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
31
+ );
32
+ });
33
+ it("master user sees everything (postgres)", async () => {
34
+ await testMasterUserSeesEverything(Alepha.create().with(AlephaOrmPostgres));
35
+ });
36
+
37
+ it("no user sees everything (sqlite)", async () => {
38
+ await testNoUserSeesEverything(
39
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
40
+ );
41
+ });
42
+ it("no user sees everything (postgres)", async () => {
43
+ await testNoUserSeesEverything(Alepha.create().with(AlephaOrmPostgres));
44
+ });
45
+
46
+ it("auto-stamps organization on create (sqlite)", async () => {
47
+ await testAutoStampOnCreate(
48
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
49
+ );
50
+ });
51
+ it("auto-stamps organization on create (postgres)", async () => {
52
+ await testAutoStampOnCreate(Alepha.create().with(AlephaOrmPostgres));
53
+ });
54
+
55
+ it("auto-stamps null for master user (sqlite)", async () => {
56
+ await testAutoStampNullForMasterUser(
57
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
58
+ );
59
+ });
60
+ it("auto-stamps null for master user (postgres)", async () => {
61
+ await testAutoStampNullForMasterUser(
62
+ Alepha.create().with(AlephaOrmPostgres),
63
+ );
64
+ });
65
+
66
+ it("does not override explicit organization (sqlite)", async () => {
67
+ await testAutoStampDoesNotOverrideExplicit(
68
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
69
+ );
70
+ });
71
+ it("does not override explicit organization (postgres)", async () => {
72
+ await testAutoStampDoesNotOverrideExplicit(
73
+ Alepha.create().with(AlephaOrmPostgres),
74
+ );
75
+ });
76
+
77
+ it("auto-stamps on createMany (sqlite)", async () => {
78
+ await testAutoStampOnCreateMany(
79
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
80
+ );
81
+ });
82
+ it("auto-stamps on createMany (postgres)", async () => {
83
+ await testAutoStampOnCreateMany(Alepha.create().with(AlephaOrmPostgres));
84
+ });
85
+
86
+ it("org filter on updateMany (sqlite)", async () => {
87
+ await testOrgFilterOnUpdateOne(
88
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
89
+ );
90
+ });
91
+ it("org filter on updateMany (postgres)", async () => {
92
+ await testOrgFilterOnUpdateOne(Alepha.create().with(AlephaOrmPostgres));
93
+ });
94
+
95
+ it("org filter on delete (sqlite)", async () => {
96
+ await testOrgFilterOnDelete(
97
+ Alepha.create({ env: { DATABASE_URL: "sqlite://:memory:" } }),
98
+ );
99
+ });
100
+ it("org filter on delete (postgres)", async () => {
101
+ await testOrgFilterOnDelete(Alepha.create().with(AlephaOrmPostgres));
102
+ });
103
+ });
@@ -1,7 +1,10 @@
1
1
  import { afterEach, describe, expect, it } from "bun:test";
2
2
  import { Alepha, t } from "alepha";
3
- import { $entity, $repository, DatabaseProvider, db } from "../../index.ts";
4
- import { BunSqliteProvider, bunSqliteOptions } from "./BunSqliteProvider.ts";
3
+ import { $entity, $repository, DatabaseProvider, db } from "../index.ts";
4
+ import {
5
+ BunSqliteProvider,
6
+ bunSqliteOptions,
7
+ } from "../providers/drivers/BunSqliteProvider.ts";
5
8
 
6
9
  // -------------------------------------------------------------------------------------------------------------------
7
10
 
@@ -15,6 +15,7 @@ export const PG_IDENTITY = Symbol.for("Alepha.Postgres.Identity");
15
15
  export const PG_ENUM = Symbol.for("Alepha.Postgres.Enum");
16
16
  export const PG_REF = Symbol.for("Alepha.Postgres.Ref");
17
17
  export const PG_GENERATED = Symbol.for("Alepha.Postgres.Generated");
18
+ export const PG_ORGANIZATION = Symbol.for("Alepha.Postgres.Organization");
18
19
 
19
20
  /**
20
21
  * @deprecated Use `PG_IDENTITY` instead.
@@ -36,6 +37,7 @@ export type PgSymbols = {
36
37
  [PG_REF]: PgRefOptions;
37
38
  [PG_ENUM]: PgEnumOptions;
38
39
  [PG_GENERATED]: PgGeneratedOptions;
40
+ [PG_ORGANIZATION]: {};
39
41
 
40
42
  /**
41
43
  * @deprecated Use `PG_IDENTITY` instead.
@@ -4,6 +4,7 @@ export {
4
4
  pageQuerySchema,
5
5
  pageSchema,
6
6
  } from "alepha";
7
+ export { sql } from "drizzle-orm";
7
8
  export * from "./errors/DbColumnNotFoundError.ts";
8
9
  export * from "./errors/DbConnectionError.ts";
9
10
  export * from "./errors/DbDeadlockError.ts";
@@ -90,6 +90,37 @@ export interface EntityPrimitiveOptions<
90
90
  */
91
91
  where?: SQL;
92
92
  }
93
+ | {
94
+ /**
95
+ * SQL expressions for expression-based indexes.
96
+ *
97
+ * Can include column references and SQL functions like `LOWER()`, `UPPER()`, etc.
98
+ * Columns and expressions can be mixed together.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // Case-insensitive unique username per realm
103
+ * indexes: [{
104
+ * expressions: (self) => [self.realm, sql`LOWER(${self.username})`],
105
+ * unique: true,
106
+ * name: "users_realm_username_lower_idx",
107
+ * }]
108
+ * ```
109
+ */
110
+ expressions: (self: Record<Keys & string, any>) => (SQL | any)[];
111
+ /**
112
+ * Whether this should be a unique index (enforces uniqueness constraint).
113
+ */
114
+ unique?: boolean;
115
+ /**
116
+ * Custom name for the index. If not provided, generates name automatically.
117
+ */
118
+ name: string;
119
+ /**
120
+ * Partial index condition. Only rows matching this SQL expression are indexed.
121
+ */
122
+ where?: SQL;
123
+ }
93
124
  )[];
94
125
 
95
126
  /**
@@ -22,6 +22,7 @@ import {
22
22
  PG_DELETED_AT,
23
23
  PG_ENUM,
24
24
  PG_IDENTITY,
25
+ PG_ORGANIZATION,
25
26
  PG_PRIMARY_KEY,
26
27
  PG_REF,
27
28
  PG_UPDATED_AT,
@@ -187,6 +188,16 @@ export class DatabaseTypeProvider {
187
188
  public readonly deletedAt = (options?: TStringOptions) =>
188
189
  pgAttr(t.optional(t.datetime(options)), PG_DELETED_AT);
189
190
 
191
+ /**
192
+ * Creates an organization column for multi-tenant row scoping.
193
+ *
194
+ * When present, queries are automatically filtered by the current user's organization.
195
+ * Rows with `null` organization are considered global and visible to everyone.
196
+ * On create, the column is auto-stamped with the current user's organization.
197
+ */
198
+ public readonly organization = () =>
199
+ pgAttr(t.optional(t.uuid()), PG_ORGANIZATION);
200
+
190
201
  /**
191
202
  * Creates a Postgres ENUM type.
192
203
  *
@@ -63,7 +63,7 @@ export class DrizzleKitProvider {
63
63
  }
64
64
 
65
65
  this.log.info(
66
- `Sync with '${provider.name}' OK [${this.dateTime.nowMillis() - now}ms]`,
66
+ `Synchronization of '${provider.name}' OK [${this.dateTime.nowMillis() - now}ms]`,
67
67
  );
68
68
  }
69
69
 
@@ -6,7 +6,7 @@ import {
6
6
  $env,
7
7
  $hook,
8
8
  $inject,
9
- $use,
9
+ $state,
10
10
  AlephaError,
11
11
  type Static,
12
12
  t,
@@ -74,7 +74,7 @@ declare module "alepha" {
74
74
  export class BunSqliteProvider extends DatabaseProvider {
75
75
  protected readonly env = $env(envSchema);
76
76
  protected readonly builder = $inject(SqliteModelBuilder);
77
- protected readonly options = $use(bunSqliteOptions);
77
+ protected readonly options = $state(bunSqliteOptions);
78
78
 
79
79
  protected sqlite?: Database;
80
80
  protected bunDb?: BunSQLiteDatabase;
@@ -7,7 +7,7 @@ import {
7
7
  $env,
8
8
  $hook,
9
9
  $inject,
10
- $use,
10
+ $state,
11
11
  AlephaError,
12
12
  type Static,
13
13
  t,
@@ -81,7 +81,7 @@ declare module "alepha" {
81
81
  export class NodeSqliteProvider extends DatabaseProvider {
82
82
  protected readonly env = $env(envSchema);
83
83
  protected readonly builder = $inject(SqliteModelBuilder);
84
- protected readonly options = $use(nodeSqliteOptions);
84
+ protected readonly options = $state(nodeSqliteOptions);
85
85
 
86
86
  protected sqlite!: DatabaseSync;
87
87
  protected drizzleDb!: any;
@@ -182,7 +182,7 @@ export class NodeSqliteProvider extends DatabaseProvider {
182
182
  await this.migrate();
183
183
  }
184
184
 
185
- this.log.info(`SQLite database OK`, { at: filepath });
185
+ this.log.info(`Sqlite connection OK`, { at: filepath });
186
186
  },
187
187
  });
188
188
 
@@ -136,6 +136,17 @@ export abstract class ModelBuilder {
136
136
  }
137
137
  configs.push(idx);
138
138
  }
139
+ } else if ("expressions" in indexDef) {
140
+ const parts = indexDef.expressions(self as any);
141
+ if (parts.length > 0) {
142
+ let idx = indexDef.unique
143
+ ? builders.uniqueIndex(indexDef.name).on(...parts)
144
+ : builders.index(indexDef.name).on(...parts);
145
+ if ("where" in indexDef && indexDef.where) {
146
+ idx = (idx as any).where(indexDef.where);
147
+ }
148
+ configs.push(idx);
149
+ }
139
150
  } else if ("columns" in indexDef) {
140
151
  const columnNames = indexDef.columns.map((col: any) =>
141
152
  this.toColumnName(col as string),
@@ -338,11 +338,25 @@ export class QueryManager {
338
338
  }
339
339
 
340
340
  if (operator?.ilike != null) {
341
- conditions.push(ilike(column, encodeValue(operator.ilike)));
341
+ if (dialect === "sqlite") {
342
+ // SQLite doesn't have ilike, use LOWER() for case-insensitive matching
343
+ conditions.push(
344
+ sql`LOWER(${column}) LIKE LOWER(${encodeValue(operator.ilike)})`,
345
+ );
346
+ } else {
347
+ conditions.push(ilike(column, encodeValue(operator.ilike)));
348
+ }
342
349
  }
343
350
 
344
351
  if (operator?.notIlike != null) {
345
- conditions.push(notIlike(column, encodeValue(operator.notIlike)));
352
+ if (dialect === "sqlite") {
353
+ // SQLite doesn't have ilike, use LOWER() for case-insensitive matching
354
+ conditions.push(
355
+ sql`LOWER(${column}) NOT LIKE LOWER(${encodeValue(operator.notIlike)})`,
356
+ );
357
+ } else {
358
+ conditions.push(notIlike(column, encodeValue(operator.notIlike)));
359
+ }
346
360
  }
347
361
 
348
362
  if (operator?.contains != null) {
@@ -12,6 +12,7 @@ import {
12
12
  } from "alepha";
13
13
  import { type DateTime, DateTimeProvider } from "alepha/datetime";
14
14
  import { $logger } from "alepha/logger";
15
+ import { currentUserAtom } from "alepha/security";
15
16
  import {
16
17
  asc,
17
18
  avg,
@@ -43,6 +44,7 @@ import type {
43
44
  import type { PgTransactionConfig } from "drizzle-orm/pg-core/session";
44
45
  import {
45
46
  PG_DELETED_AT,
47
+ PG_ORGANIZATION,
46
48
  PG_PRIMARY_KEY,
47
49
  PG_UPDATED_AT,
48
50
  PG_VERSION,
@@ -388,9 +390,8 @@ export abstract class Repository<T extends TObject> {
388
390
  );
389
391
  }
390
392
 
391
- const where = this.withDeletedAt(
392
- (query.where ?? {}) as PgQueryWhere<T>,
393
- opts,
393
+ const where = this.withOrganization(
394
+ this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),
394
395
  );
395
396
 
396
397
  builder.where(() => this.toSQL(where, joins));
@@ -565,9 +566,8 @@ export abstract class Repository<T extends TObject> {
565
566
  );
566
567
 
567
568
  if (opts.count) {
568
- const countWhere = this.withDeletedAt(
569
- (query.where ?? {}) as PgQueryWhere<T>,
570
- opts,
569
+ const countWhere = this.withOrganization(
570
+ this.withDeletedAt((query.where ?? {}) as PgQueryWhere<T>, opts),
571
571
  );
572
572
 
573
573
  tasks.push(
@@ -662,6 +662,7 @@ export abstract class Repository<T extends TObject> {
662
662
  opts: StatementOptions = {},
663
663
  ): Promise<Static<T>> {
664
664
  this.assertWritable();
665
+ this.stampOrganization(data);
665
666
  await this.alepha.events.emit("repository:create:before", {
666
667
  tableName: this.tableName,
667
668
  data,
@@ -705,6 +706,10 @@ export abstract class Repository<T extends TObject> {
705
706
  return [];
706
707
  }
707
708
 
709
+ for (const value of values) {
710
+ this.stampOrganization(value);
711
+ }
712
+
708
713
  await this.alepha.events.emit("repository:create:before", {
709
714
  tableName: this.tableName,
710
715
  data: values,
@@ -774,6 +779,7 @@ export abstract class Repository<T extends TObject> {
774
779
  } = {},
775
780
  ): Promise<Static<T>> {
776
781
  this.assertWritable();
782
+ this.stampOrganization(data);
777
783
  await this.alepha.events.emit("repository:create:before", {
778
784
  tableName: this.tableName,
779
785
  data,
@@ -862,7 +868,7 @@ export abstract class Repository<T extends TObject> {
862
868
  opts.now ?? this.dateTimeProvider.nowISOString();
863
869
  }
864
870
 
865
- where = this.withDeletedAt(where, opts);
871
+ where = this.withOrganization(this.withDeletedAt(where, opts));
866
872
  row = this.cast(row, false) as any;
867
873
 
868
874
  // do not update the ID field
@@ -1025,7 +1031,7 @@ export abstract class Repository<T extends TObject> {
1025
1031
  opts.now ?? this.dateTimeProvider.nowISOString();
1026
1032
  }
1027
1033
 
1028
- where = this.withDeletedAt(where, opts);
1034
+ where = this.withOrganization(this.withDeletedAt(where, opts));
1029
1035
  data = this.cast(data, false) as any;
1030
1036
  try {
1031
1037
  const entities = await this.rawUpdate(opts)
@@ -1070,6 +1076,8 @@ export abstract class Repository<T extends TObject> {
1070
1076
  );
1071
1077
  }
1072
1078
 
1079
+ where = this.withOrganization(where);
1080
+
1073
1081
  await this.alepha.events.emit("repository:delete:before", {
1074
1082
  tableName: this.tableName,
1075
1083
  where,
@@ -1170,7 +1178,7 @@ export abstract class Repository<T extends TObject> {
1170
1178
  where: PgQueryWhereOrSQL<T> = {},
1171
1179
  opts: StatementOptions = {},
1172
1180
  ): Promise<number> {
1173
- where = this.withDeletedAt(where, opts);
1181
+ where = this.withOrganization(this.withDeletedAt(where, opts));
1174
1182
  const db = opts.tx === null ? this.provider.db : (opts.tx ?? this.db);
1175
1183
  return db.$count(this.table, this.toSQL(where));
1176
1184
  }
@@ -1234,7 +1242,9 @@ export abstract class Repository<T extends TObject> {
1234
1242
 
1235
1243
  // WHERE
1236
1244
  if (query.where) {
1237
- const where = this.withDeletedAt(query.where as any, opts);
1245
+ const where = this.withOrganization(
1246
+ this.withDeletedAt(query.where as any, opts),
1247
+ );
1238
1248
  builder = builder.where(this.toSQL(where)) as any;
1239
1249
  }
1240
1250
 
@@ -1458,6 +1468,56 @@ export abstract class Repository<T extends TObject> {
1458
1468
  return undefined;
1459
1469
  }
1460
1470
 
1471
+ protected withOrganization(
1472
+ where: PgQueryWhereOrSQL<T>,
1473
+ ): PgQueryWhereOrSQL<T> {
1474
+ const orgField = this.organizationField();
1475
+ if (!orgField) {
1476
+ return where;
1477
+ }
1478
+
1479
+ const user = this.alepha.store.get(currentUserAtom);
1480
+ if (!user?.organization) {
1481
+ return where;
1482
+ }
1483
+
1484
+ return {
1485
+ and: [
1486
+ where,
1487
+ {
1488
+ or: [
1489
+ { [orgField.key]: { eq: user.organization } },
1490
+ { [orgField.key]: { isNull: true } },
1491
+ ],
1492
+ } as any,
1493
+ ],
1494
+ } as PgQueryWhereOrSQL<T>;
1495
+ }
1496
+
1497
+ protected stampOrganization(data: any): void {
1498
+ const orgField = this.organizationField();
1499
+ if (!orgField) {
1500
+ return;
1501
+ }
1502
+
1503
+ if (data[orgField.key] != null) {
1504
+ return;
1505
+ }
1506
+
1507
+ const user = this.alepha.store.get(currentUserAtom);
1508
+ if (user?.organization) {
1509
+ data[orgField.key] = user.organization;
1510
+ }
1511
+ }
1512
+
1513
+ protected organizationField(): PgAttrField | undefined {
1514
+ const fields = getAttrFields(this.entity.schema, PG_ORGANIZATION);
1515
+ if (fields.length > 0) {
1516
+ return fields[0];
1517
+ }
1518
+ return undefined;
1519
+ }
1520
+
1461
1521
  /**
1462
1522
  * Convert something to valid Pg Insert Value.
1463
1523
  */
@@ -1,7 +1,7 @@
1
1
  import { afterEach, describe, expect, it } from "bun:test";
2
2
  import { Alepha, t } from "alepha";
3
3
  import { $entity, $repository, DatabaseProvider, db } from "alepha/orm";
4
- import { BunPostgresProvider } from "./BunPostgresProvider.ts";
4
+ import { BunPostgresProvider } from "../providers/BunPostgresProvider.ts";
5
5
 
6
6
  // -------------------------------------------------------------------------------------------------------------------
7
7