alepha 0.14.1 → 0.14.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 (402) hide show
  1. package/README.md +3 -3
  2. package/dist/api/audits/index.browser.js +5 -5
  3. package/dist/api/audits/index.browser.js.map +1 -1
  4. package/dist/api/audits/index.d.ts +784 -784
  5. package/dist/api/audits/index.d.ts.map +1 -1
  6. package/dist/api/audits/index.js +13 -13
  7. package/dist/api/audits/index.js.map +1 -1
  8. package/dist/api/files/index.browser.js +5 -5
  9. package/dist/api/files/index.browser.js.map +1 -1
  10. package/dist/api/files/index.d.ts +57 -57
  11. package/dist/api/files/index.d.ts.map +1 -1
  12. package/dist/api/files/index.js +71 -71
  13. package/dist/api/files/index.js.map +1 -1
  14. package/dist/api/jobs/index.browser.js +5 -5
  15. package/dist/api/jobs/index.browser.js.map +1 -1
  16. package/dist/api/jobs/index.d.ts +165 -165
  17. package/dist/api/jobs/index.d.ts.map +1 -1
  18. package/dist/api/jobs/index.js +10 -10
  19. package/dist/api/jobs/index.js.map +1 -1
  20. package/dist/api/notifications/index.browser.js +10 -10
  21. package/dist/api/notifications/index.browser.js.map +1 -1
  22. package/dist/api/notifications/index.d.ts +583 -171
  23. package/dist/api/notifications/index.d.ts.map +1 -1
  24. package/dist/api/notifications/index.js +12 -12
  25. package/dist/api/notifications/index.js.map +1 -1
  26. package/dist/api/parameters/index.browser.js +163 -10
  27. package/dist/api/parameters/index.browser.js.map +1 -1
  28. package/dist/api/parameters/index.d.ts +281 -276
  29. package/dist/api/parameters/index.d.ts.map +1 -1
  30. package/dist/api/parameters/index.js +196 -91
  31. package/dist/api/parameters/index.js.map +1 -1
  32. package/dist/api/users/index.browser.js +19 -19
  33. package/dist/api/users/index.browser.js.map +1 -1
  34. package/dist/api/users/index.d.ts +778 -764
  35. package/dist/api/users/index.d.ts.map +1 -1
  36. package/dist/api/users/index.js +831 -596
  37. package/dist/api/users/index.js.map +1 -1
  38. package/dist/api/verifications/index.browser.js +6 -6
  39. package/dist/api/verifications/index.browser.js.map +1 -1
  40. package/dist/api/verifications/index.d.ts +125 -125
  41. package/dist/api/verifications/index.d.ts.map +1 -1
  42. package/dist/api/verifications/index.js +6 -6
  43. package/dist/api/verifications/index.js.map +1 -1
  44. package/dist/batch/index.js.map +1 -1
  45. package/dist/bin/index.d.ts +1 -2
  46. package/dist/bin/index.js +0 -1
  47. package/dist/bin/index.js.map +1 -1
  48. package/dist/cache/core/index.js.map +1 -1
  49. package/dist/cli/index.d.ts +249 -218
  50. package/dist/cli/index.d.ts.map +1 -1
  51. package/dist/cli/index.js +951 -821
  52. package/dist/cli/index.js.map +1 -1
  53. package/dist/command/index.d.ts +40 -0
  54. package/dist/command/index.d.ts.map +1 -1
  55. package/dist/command/index.js +97 -17
  56. package/dist/command/index.js.map +1 -1
  57. package/dist/core/index.browser.js +14 -18
  58. package/dist/core/index.browser.js.map +1 -1
  59. package/dist/core/index.d.ts +29 -0
  60. package/dist/core/index.d.ts.map +1 -1
  61. package/dist/core/index.js +21 -24
  62. package/dist/core/index.js.map +1 -1
  63. package/dist/core/index.native.js +21 -24
  64. package/dist/core/index.native.js.map +1 -1
  65. package/dist/datetime/index.js.map +1 -1
  66. package/dist/fake/index.js +195 -168
  67. package/dist/fake/index.js.map +1 -1
  68. package/dist/file/index.d.ts +8 -0
  69. package/dist/file/index.d.ts.map +1 -1
  70. package/dist/file/index.js +3 -0
  71. package/dist/file/index.js.map +1 -1
  72. package/dist/lock/redis/index.js.map +1 -1
  73. package/dist/logger/index.js.map +1 -1
  74. package/dist/mcp/index.d.ts.map +1 -1
  75. package/dist/mcp/index.js.map +1 -1
  76. package/dist/orm/index.browser.js +26 -5
  77. package/dist/orm/index.browser.js.map +1 -1
  78. package/dist/orm/index.d.ts +146 -121
  79. package/dist/orm/index.d.ts.map +1 -1
  80. package/dist/orm/index.js +49 -24
  81. package/dist/orm/index.js.map +1 -1
  82. package/dist/redis/index.js.map +1 -1
  83. package/dist/retry/index.js.map +1 -1
  84. package/dist/router/index.js.map +1 -1
  85. package/dist/scheduler/index.d.ts +6 -6
  86. package/dist/scheduler/index.js.map +1 -1
  87. package/dist/security/index.d.ts +29 -29
  88. package/dist/security/index.d.ts.map +1 -1
  89. package/dist/security/index.js +1 -1
  90. package/dist/security/index.js.map +1 -1
  91. package/dist/server/auth/index.d.ts +171 -155
  92. package/dist/server/auth/index.d.ts.map +1 -1
  93. package/dist/server/auth/index.js +0 -1
  94. package/dist/server/auth/index.js.map +1 -1
  95. package/dist/server/cache/index.js.map +1 -1
  96. package/dist/server/compress/index.d.ts.map +1 -1
  97. package/dist/server/compress/index.js +2 -0
  98. package/dist/server/compress/index.js.map +1 -1
  99. package/dist/server/cookies/index.browser.js.map +1 -1
  100. package/dist/server/cookies/index.js.map +1 -1
  101. package/dist/server/core/index.browser.js.map +1 -1
  102. package/dist/server/core/index.d.ts.map +1 -1
  103. package/dist/server/core/index.js +1 -1
  104. package/dist/server/core/index.js.map +1 -1
  105. package/dist/server/health/index.d.ts +17 -17
  106. package/dist/server/helmet/index.js.map +1 -1
  107. package/dist/server/links/index.browser.js +22 -6
  108. package/dist/server/links/index.browser.js.map +1 -1
  109. package/dist/server/links/index.d.ts +46 -44
  110. package/dist/server/links/index.d.ts.map +1 -1
  111. package/dist/server/links/index.js +24 -41
  112. package/dist/server/links/index.js.map +1 -1
  113. package/dist/server/multipart/index.js.map +1 -1
  114. package/dist/server/rate-limit/index.js.map +1 -1
  115. package/dist/server/security/index.js.map +1 -1
  116. package/dist/server/swagger/index.d.ts +2 -1
  117. package/dist/server/swagger/index.d.ts.map +1 -1
  118. package/dist/server/swagger/index.js +8 -3
  119. package/dist/server/swagger/index.js.map +1 -1
  120. package/dist/thread/index.js.map +1 -1
  121. package/dist/topic/core/index.js.map +1 -1
  122. package/dist/vite/index.d.ts.map +1 -1
  123. package/dist/vite/index.js +12 -4
  124. package/dist/vite/index.js.map +1 -1
  125. package/dist/websocket/index.browser.js.map +1 -1
  126. package/dist/websocket/index.js.map +1 -1
  127. package/package.json +7 -7
  128. package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
  129. package/src/api/audits/entities/audits.ts +5 -5
  130. package/src/api/audits/index.browser.ts +1 -1
  131. package/src/api/audits/index.ts +3 -3
  132. package/src/api/audits/primitives/$audit.spec.ts +276 -0
  133. package/src/api/audits/services/AuditService.spec.ts +495 -0
  134. package/src/api/files/__tests__/$bucket.spec.ts +91 -0
  135. package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
  136. package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
  137. package/src/api/files/controllers/FileController.spec.ts +558 -0
  138. package/src/api/files/controllers/FileController.ts +4 -5
  139. package/src/api/files/entities/files.ts +5 -5
  140. package/src/api/files/index.browser.ts +1 -1
  141. package/src/api/files/index.ts +4 -4
  142. package/src/api/files/jobs/FileJobs.spec.ts +52 -0
  143. package/src/api/files/services/FileService.spec.ts +109 -0
  144. package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
  145. package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
  146. package/src/api/jobs/entities/jobExecutions.ts +5 -5
  147. package/src/api/jobs/index.ts +3 -3
  148. package/src/api/jobs/primitives/$job.spec.ts +476 -0
  149. package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
  150. package/src/api/notifications/entities/notifications.ts +5 -5
  151. package/src/api/notifications/index.browser.ts +1 -1
  152. package/src/api/notifications/index.ts +4 -4
  153. package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
  154. package/src/api/parameters/entities/parameters.ts +7 -17
  155. package/src/api/parameters/index.ts +3 -3
  156. package/src/api/parameters/primitives/$config.spec.ts +356 -0
  157. package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
  158. package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
  159. package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
  160. package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
  161. package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
  162. package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
  163. package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
  164. package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
  165. package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
  166. package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
  167. package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
  168. package/src/api/parameters/schemas/index.ts +15 -0
  169. package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
  170. package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
  171. package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
  172. package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
  173. package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
  174. package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
  175. package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
  176. package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
  177. package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
  178. package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
  179. package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
  180. package/src/api/users/controllers/AdminUserController.ts +116 -0
  181. package/src/api/users/controllers/UserController.ts +4 -107
  182. package/src/api/users/controllers/UserRealmController.ts +3 -0
  183. package/src/api/users/entities/identities.ts +6 -6
  184. package/src/api/users/entities/sessions.ts +6 -6
  185. package/src/api/users/entities/users.ts +9 -9
  186. package/src/api/users/index.ts +13 -6
  187. package/src/api/users/primitives/$userRealm.ts +13 -8
  188. package/src/api/users/services/CredentialService.spec.ts +509 -0
  189. package/src/api/users/services/CredentialService.ts +46 -0
  190. package/src/api/users/services/IdentityService.ts +15 -0
  191. package/src/api/users/services/RegistrationService.spec.ts +630 -0
  192. package/src/api/users/services/RegistrationService.ts +18 -0
  193. package/src/api/users/services/SessionService.spec.ts +301 -0
  194. package/src/api/users/services/SessionService.ts +110 -1
  195. package/src/api/users/services/UserService.ts +67 -2
  196. package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
  197. package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
  198. package/src/api/verifications/entities/verifications.ts +6 -6
  199. package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
  200. package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
  201. package/src/batch/primitives/$batch.spec.ts +766 -0
  202. package/src/batch/providers/BatchProvider.spec.ts +786 -0
  203. package/src/bin/index.ts +0 -1
  204. package/src/bucket/__tests__/shared.ts +194 -0
  205. package/src/bucket/primitives/$bucket.spec.ts +104 -0
  206. package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
  207. package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
  208. package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
  209. package/src/cache/core/__tests__/shared.ts +377 -0
  210. package/src/cache/core/primitives/$cache.spec.ts +111 -0
  211. package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
  212. package/src/cli/apps/AlephaCli.ts +54 -16
  213. package/src/cli/apps/AlephaPackageBuilderCli.ts +2 -1
  214. package/src/cli/assets/appRouterTs.ts +1 -1
  215. package/src/cli/commands/{ViteCommands.ts → build.ts} +2 -105
  216. package/src/cli/commands/clean.ts +14 -0
  217. package/src/cli/commands/{DrizzleCommands.ts → db.ts} +10 -117
  218. package/src/cli/commands/{DeployCommands.ts → deploy.ts} +1 -1
  219. package/src/cli/commands/dev.ts +69 -0
  220. package/src/cli/commands/format.ts +17 -0
  221. package/src/cli/commands/gen/changelog.spec.ts +315 -0
  222. package/src/cli/commands/{ChangelogCommands.ts → gen/changelog.ts} +16 -31
  223. package/src/cli/commands/gen/openapi.ts +71 -0
  224. package/src/cli/commands/gen.ts +18 -0
  225. package/src/cli/commands/{CoreCommands.ts → init.ts} +4 -40
  226. package/src/cli/commands/lint.ts +17 -0
  227. package/src/cli/commands/root.ts +41 -0
  228. package/src/cli/commands/run.ts +24 -0
  229. package/src/cli/commands/test.ts +42 -0
  230. package/src/cli/commands/typecheck.ts +24 -0
  231. package/src/cli/commands/{VerifyCommands.ts → verify.ts} +1 -13
  232. package/src/cli/defineConfig.ts +10 -1
  233. package/src/cli/index.ts +17 -7
  234. package/src/cli/services/AlephaCliUtils.ts +71 -32
  235. package/src/cli/services/GitMessageParser.ts +1 -1
  236. package/src/command/helpers/Asker.spec.ts +127 -0
  237. package/src/command/helpers/Runner.spec.ts +126 -0
  238. package/src/command/primitives/$command.spec.ts +1588 -0
  239. package/src/command/providers/CliProvider.ts +74 -24
  240. package/src/core/Alepha.ts +52 -4
  241. package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
  242. package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
  243. package/src/core/__tests__/Alepha-has.spec.ts +41 -0
  244. package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
  245. package/src/core/__tests__/Alepha-register.spec.ts +81 -0
  246. package/src/core/__tests__/Alepha-start.spec.ts +176 -0
  247. package/src/core/__tests__/Alepha-with.spec.ts +14 -0
  248. package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
  249. package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
  250. package/src/core/__tests__/descriptor.spec.ts +34 -0
  251. package/src/core/__tests__/fixtures/A.ts +5 -0
  252. package/src/core/__tests__/pagination.spec.ts +77 -0
  253. package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
  254. package/src/core/primitives/$atom.spec.ts +43 -0
  255. package/src/core/primitives/$hook.spec.ts +130 -0
  256. package/src/core/primitives/$inject.spec.ts +175 -0
  257. package/src/core/primitives/$module.spec.ts +115 -0
  258. package/src/core/providers/CodecManager.spec.ts +740 -0
  259. package/src/core/providers/EventManager.spec.ts +762 -0
  260. package/src/core/providers/EventManager.ts +4 -0
  261. package/src/core/providers/StateManager.spec.ts +365 -0
  262. package/src/core/providers/TypeProvider.spec.ts +1607 -0
  263. package/src/core/providers/TypeProvider.ts +20 -26
  264. package/src/datetime/primitives/$interval.spec.ts +103 -0
  265. package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
  266. package/src/email/primitives/$email.spec.ts +175 -0
  267. package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
  268. package/src/fake/__tests__/keyName.example.ts +40 -0
  269. package/src/fake/__tests__/keyName.spec.ts +152 -0
  270. package/src/fake/__tests__/module.example.ts +32 -0
  271. package/src/fake/providers/FakeProvider.spec.ts +438 -0
  272. package/src/file/providers/FileSystemProvider.ts +8 -0
  273. package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
  274. package/src/file/providers/NodeFileSystemProvider.ts +5 -0
  275. package/src/file/services/FileDetector.spec.ts +591 -0
  276. package/src/lock/core/__tests__/shared.ts +190 -0
  277. package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
  278. package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
  279. package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
  280. package/src/logger/primitives/$logger.spec.ts +108 -0
  281. package/src/logger/services/Logger.spec.ts +295 -0
  282. package/src/mcp/__tests__/errors.spec.ts +175 -0
  283. package/src/mcp/__tests__/integration.spec.ts +450 -0
  284. package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
  285. package/src/mcp/primitives/$prompt.spec.ts +468 -0
  286. package/src/mcp/primitives/$resource.spec.ts +390 -0
  287. package/src/mcp/primitives/$tool.spec.ts +406 -0
  288. package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
  289. package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
  290. package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
  291. package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
  292. package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
  293. package/src/orm/__tests__/$repository-save.spec.ts +37 -0
  294. package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
  295. package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
  296. package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
  297. package/src/orm/__tests__/delete-returning.spec.ts +256 -0
  298. package/src/orm/__tests__/deletedAt.spec.ts +80 -0
  299. package/src/orm/__tests__/enums.spec.ts +315 -0
  300. package/src/orm/__tests__/execute.spec.ts +72 -0
  301. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
  302. package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
  303. package/src/orm/__tests__/joins.spec.ts +1114 -0
  304. package/src/orm/__tests__/page.spec.ts +287 -0
  305. package/src/orm/__tests__/primaryKey.spec.ts +87 -0
  306. package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
  307. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
  308. package/src/orm/__tests__/references.spec.ts +102 -0
  309. package/src/orm/__tests__/security.spec.ts +710 -0
  310. package/src/orm/__tests__/sqlite.spec.ts +111 -0
  311. package/src/orm/__tests__/string-operators.spec.ts +429 -0
  312. package/src/orm/__tests__/timestamps.spec.ts +388 -0
  313. package/src/orm/__tests__/validation.spec.ts +183 -0
  314. package/src/orm/__tests__/version.spec.ts +64 -0
  315. package/src/orm/helpers/parseQueryString.spec.ts +196 -0
  316. package/src/orm/index.browser.ts +1 -1
  317. package/src/orm/index.ts +10 -6
  318. package/src/orm/primitives/$repository.spec.ts +137 -0
  319. package/src/orm/primitives/$sequence.spec.ts +29 -0
  320. package/src/orm/primitives/$transaction.spec.ts +82 -0
  321. package/src/orm/providers/{PostgresTypeProvider.ts → DatabaseTypeProvider.ts} +25 -3
  322. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
  323. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  324. package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
  325. package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
  326. package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
  327. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  328. package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
  329. package/src/orm/services/ModelBuilder.spec.ts +575 -0
  330. package/src/orm/services/Repository.spec.ts +137 -0
  331. package/src/queue/core/__tests__/shared.ts +143 -0
  332. package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
  333. package/src/queue/core/providers/WorkerProvider.spec.ts +378 -0
  334. package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
  335. package/src/redis/__tests__/redis.spec.ts +58 -0
  336. package/src/retry/primitives/$retry.spec.ts +234 -0
  337. package/src/retry/providers/RetryProvider.spec.ts +438 -0
  338. package/src/router/__tests__/match.spec.ts +252 -0
  339. package/src/router/providers/RouterProvider.spec.ts +197 -0
  340. package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
  341. package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
  342. package/src/scheduler/__tests__/shared.ts +77 -0
  343. package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
  344. package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
  345. package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
  346. package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
  347. package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
  348. package/src/security/primitives/$permission.spec.ts +30 -0
  349. package/src/security/primitives/$permission.ts +2 -2
  350. package/src/security/primitives/$realm.spec.ts +101 -0
  351. package/src/security/primitives/$role.spec.ts +52 -0
  352. package/src/security/primitives/$serviceAccount.spec.ts +61 -0
  353. package/src/security/providers/SecurityProvider.spec.ts +350 -0
  354. package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
  355. package/src/server/cache/providers/ServerCacheProvider.spec.ts +942 -0
  356. package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
  357. package/src/server/compress/providers/ServerCompressProvider.ts +2 -0
  358. package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
  359. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
  360. package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
  361. package/src/server/core/primitives/$action.spec.ts +191 -0
  362. package/src/server/core/primitives/$route.spec.ts +65 -0
  363. package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
  364. package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
  365. package/src/server/core/providers/ServerProvider.ts +3 -1
  366. package/src/server/core/services/HttpClient.spec.ts +123 -0
  367. package/src/server/core/services/UserAgentParser.spec.ts +111 -0
  368. package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
  369. package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
  370. package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
  371. package/src/server/links/__tests__/$action.spec.ts +238 -0
  372. package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
  373. package/src/server/links/__tests__/requestId.spec.ts +120 -0
  374. package/src/server/links/primitives/$remote.spec.ts +228 -0
  375. package/src/server/links/providers/LinkProvider.spec.ts +54 -0
  376. package/src/server/links/providers/LinkProvider.ts +49 -3
  377. package/src/server/links/providers/ServerLinksProvider.ts +1 -53
  378. package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
  379. package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
  380. package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
  381. package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
  382. package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
  383. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
  384. package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
  385. package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
  386. package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
  387. package/src/server/static/primitives/$serve.spec.ts +193 -0
  388. package/src/server/swagger/__tests__/ui.spec.ts +52 -0
  389. package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
  390. package/src/server/swagger/providers/ServerSwaggerProvider.ts +18 -8
  391. package/src/sms/primitives/$sms.spec.ts +165 -0
  392. package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
  393. package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
  394. package/src/thread/primitives/$thread.spec.ts +186 -0
  395. package/src/topic/core/__tests__/shared.ts +144 -0
  396. package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
  397. package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
  398. package/src/vite/plugins/viteAlephaDev.ts +16 -4
  399. package/src/vite/tasks/runAlepha.ts +7 -1
  400. package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
  401. package/src/websocket/primitives/$channel.spec.ts +30 -0
  402. package/src/cli/commands/BiomeCommands.ts +0 -29
@@ -0,0 +1,490 @@
1
+ import { Alepha, t } from "alepha";
2
+ import { sql } from "drizzle-orm";
3
+ import { describe, expect, it } from "vitest";
4
+ import { $entity, $repository } from "../index.ts";
5
+ import { pg } from "../providers/DatabaseTypeProvider.ts";
6
+
7
+ // Define test entities with all features
8
+ const roleEntity = $entity({
9
+ name: "roles",
10
+ schema: t.object({
11
+ id: pg.primaryKey(),
12
+ name: t.string(),
13
+ description: t.optional(t.string()),
14
+ }),
15
+ indexes: ["name"],
16
+ constraints: [
17
+ {
18
+ columns: ["name"],
19
+ unique: true,
20
+ name: "unique_role_name",
21
+ },
22
+ ],
23
+ });
24
+
25
+ const userEntity = $entity({
26
+ name: "users",
27
+ schema: t.object({
28
+ id: pg.primaryKey(),
29
+ email: t.email(),
30
+ username: t.string(),
31
+ age: t.integer(),
32
+ roleId: t.integer(),
33
+ status: t.string(),
34
+ }),
35
+ indexes: [
36
+ // Simple index
37
+ "email",
38
+ // Unique index with name
39
+ {
40
+ column: "username",
41
+ unique: true,
42
+ name: "unique_username_idx",
43
+ },
44
+ // Composite index
45
+ {
46
+ columns: ["roleId", "status"],
47
+ name: "role_status_idx",
48
+ },
49
+ ],
50
+ foreignKeys: [
51
+ {
52
+ columns: ["roleId"],
53
+ foreignColumns: [() => roleEntity.cols.id],
54
+ },
55
+ ],
56
+ constraints: [
57
+ // Check constraint
58
+ {
59
+ columns: ["age"],
60
+ check: sql`age >= 18 AND age <= 120`,
61
+ name: "valid_age_range",
62
+ },
63
+ // Composite unique constraint
64
+ {
65
+ columns: ["email", "username"],
66
+ unique: true,
67
+ name: "unique_email_username",
68
+ },
69
+ ],
70
+ });
71
+
72
+ const postEntity = $entity({
73
+ name: "posts",
74
+ schema: t.object({
75
+ id: pg.primaryKey(),
76
+ userId: t.integer(),
77
+ title: t.string(),
78
+ content: t.text(),
79
+ published: t.boolean(),
80
+ views: t.integer(),
81
+ tags: t.optional(t.array(t.string())),
82
+ }),
83
+ indexes: [
84
+ // Multiple indexes
85
+ "title",
86
+ {
87
+ column: "published",
88
+ name: "published_idx",
89
+ },
90
+ {
91
+ columns: ["userId", "published"],
92
+ name: "user_published_idx",
93
+ },
94
+ {
95
+ columns: ["userId", "views"],
96
+ unique: true,
97
+ name: "unique_user_views",
98
+ },
99
+ ],
100
+ foreignKeys: [
101
+ {
102
+ name: "posts_user_fk",
103
+ columns: ["userId"],
104
+ foreignColumns: [() => userEntity.cols.id],
105
+ },
106
+ ],
107
+ constraints: [
108
+ {
109
+ columns: ["views"],
110
+ check: sql`views >= 0`,
111
+ name: "positive_views",
112
+ },
113
+ ],
114
+ });
115
+
116
+ // Test app with repositories
117
+ class TestApp {
118
+ roles = $repository(roleEntity);
119
+ users = $repository(userEntity);
120
+ posts = $repository(postEntity);
121
+ }
122
+
123
+ /**
124
+ * Shared test function that runs on both PostgreSQL and SQLite
125
+ */
126
+ const testModelBuilderFeatures = async (alepha: Alepha) => {
127
+ const app = alepha.inject(TestApp);
128
+ await alepha.start();
129
+
130
+ // Test 1: Create roles (tests unique constraint on name)
131
+ const adminRole = await app.roles.create({
132
+ name: "admin",
133
+ description: "Administrator role",
134
+ });
135
+ expect(adminRole.id).toBeDefined();
136
+ expect(adminRole.name).toBe("admin");
137
+
138
+ const userRole = await app.roles.create({
139
+ name: "user",
140
+ description: "Regular user role",
141
+ });
142
+ expect(userRole.id).toBeDefined();
143
+
144
+ // Test unique constraint violation
145
+ try {
146
+ await app.roles.create({
147
+ name: "admin", // Duplicate name
148
+ description: "Another admin",
149
+ });
150
+ expect.fail("Should have thrown unique constraint error");
151
+ } catch (error: any) {
152
+ // Expected: unique constraint violation
153
+ expect(error).toBeDefined();
154
+ }
155
+
156
+ // Test 2: Create users (tests foreign key, check constraint, and unique indexes)
157
+ const user1 = await app.users.create({
158
+ email: "alice@example.com",
159
+ username: "alice",
160
+ age: 25,
161
+ roleId: adminRole.id,
162
+ status: "active",
163
+ });
164
+ expect(user1.id).toBeDefined();
165
+ expect(user1.username).toBe("alice");
166
+
167
+ const user2 = await app.users.create({
168
+ email: "bob@example.com",
169
+ username: "bob",
170
+ age: 30,
171
+ roleId: userRole.id,
172
+ status: "active",
173
+ });
174
+ expect(user2.id).toBeDefined();
175
+
176
+ // Test unique index on username
177
+ try {
178
+ await app.users.create({
179
+ email: "charlie@example.com",
180
+ username: "alice", // Duplicate username
181
+ age: 28,
182
+ roleId: userRole.id,
183
+ status: "active",
184
+ });
185
+ expect.fail("Should have thrown unique constraint error on username");
186
+ } catch (error: any) {
187
+ // Expected: unique constraint violation
188
+ expect(error).toBeDefined();
189
+ }
190
+
191
+ // Test check constraint (age must be >= 18)
192
+ try {
193
+ await app.users.create({
194
+ email: "young@example.com",
195
+ username: "younguser",
196
+ age: 15, // Below minimum age
197
+ roleId: userRole.id,
198
+ status: "pending",
199
+ });
200
+ expect.fail("Should have thrown check constraint error for age");
201
+ } catch (error: any) {
202
+ // Expected: check constraint violation
203
+ expect(error).toBeDefined();
204
+ }
205
+
206
+ // Test composite unique constraint (email + username)
207
+ try {
208
+ await app.users.create({
209
+ email: "alice@example.com", // Same email as user1
210
+ username: "alice", // Same username as user1
211
+ age: 22,
212
+ roleId: userRole.id,
213
+ status: "inactive",
214
+ });
215
+ expect.fail("Should have thrown composite unique constraint error");
216
+ } catch (error: any) {
217
+ // Expected: composite unique constraint violation
218
+ expect(error).toBeDefined();
219
+ }
220
+
221
+ // Test 3: Create posts (tests multiple indexes and foreign key)
222
+ const post1 = await app.posts.create({
223
+ userId: user1.id,
224
+ title: "First Post",
225
+ content: "This is the first post",
226
+ published: true,
227
+ views: 100,
228
+ });
229
+ expect(post1.id).toBeDefined();
230
+ expect(post1.views).toBe(100);
231
+
232
+ const post2 = await app.posts.create({
233
+ userId: user1.id,
234
+ title: "Second Post",
235
+ content: "This is the second post",
236
+ published: false,
237
+ views: 50,
238
+ tags: ["tech", "tutorial"],
239
+ });
240
+ expect(post2.id).toBeDefined();
241
+ expect(post2.tags).toEqual(["tech", "tutorial"]);
242
+
243
+ // Test check constraint (views must be >= 0)
244
+ try {
245
+ await app.posts.create({
246
+ userId: user2.id,
247
+ title: "Invalid Post",
248
+ content: "This post has negative views",
249
+ published: true,
250
+ views: -10, // Negative views
251
+ });
252
+ expect.fail("Should have thrown check constraint error for views");
253
+ } catch (error: any) {
254
+ // Expected: check constraint violation
255
+ expect(error).toBeDefined();
256
+ }
257
+
258
+ // Test unique index on (userId, views) - only for testing unique composite index
259
+ try {
260
+ await app.posts.create({
261
+ userId: user1.id,
262
+ title: "Duplicate Views Post",
263
+ content: "This has the same userId and views",
264
+ published: true,
265
+ views: 100, // Same views as post1 for same user
266
+ });
267
+ expect.fail(
268
+ "Should have thrown unique constraint error on (userId, views)",
269
+ );
270
+ } catch (error: any) {
271
+ // Expected: unique constraint violation
272
+ expect(error).toBeDefined();
273
+ }
274
+
275
+ // Test 4: Query using indexes (verify they improve query performance)
276
+ // Find users by email (uses email index)
277
+ const usersByEmail = await app.users.findMany({
278
+ where: { email: { eq: "alice@example.com" } },
279
+ });
280
+ expect(usersByEmail.length).toBe(1);
281
+ expect(usersByEmail[0].username).toBe("alice");
282
+
283
+ // Find users by roleId and status (uses composite index)
284
+ const adminUsers = await app.users.findMany({
285
+ where: { roleId: { eq: adminRole.id } },
286
+ orderBy: "status",
287
+ });
288
+ expect(adminUsers.length).toBeGreaterThan(0);
289
+ expect(adminUsers[0].roleId).toBe(adminRole.id);
290
+
291
+ // Find posts by userId and published status (uses composite index)
292
+ const publishedPosts = await app.posts.findMany({
293
+ where: {
294
+ userId: { eq: user1.id },
295
+ published: { eq: true },
296
+ },
297
+ });
298
+ expect(publishedPosts.length).toBeGreaterThan(0);
299
+ expect(publishedPosts[0].published).toBe(true);
300
+
301
+ // Test 5: Foreign key cascade behavior
302
+ // When we delete a user, their posts should be affected based on FK settings
303
+ // (Note: The actual cascade behavior depends on the FK configuration)
304
+
305
+ // Clean up
306
+ await app.posts.clear({ force: true });
307
+ await app.users.clear({ force: true });
308
+ await app.roles.clear({ force: true });
309
+ };
310
+
311
+ describe("ModelBuilder Integration Tests", () => {
312
+ it("should handle all entity options correctly in PostgreSQL", async () => {
313
+ await testModelBuilderFeatures(Alepha.create());
314
+ });
315
+
316
+ it("should handle all entity options correctly in SQLite", async () => {
317
+ await testModelBuilderFeatures(
318
+ Alepha.create({
319
+ env: {
320
+ DATABASE_URL: "sqlite://:memory:",
321
+ },
322
+ }),
323
+ );
324
+ });
325
+
326
+ it("should handle entities with custom config in PostgreSQL", async () => {
327
+ // Test entity with custom config function
328
+ const customEntity = $entity({
329
+ name: "custom_table",
330
+ schema: t.object({
331
+ id: pg.primaryKey(),
332
+ data: t.string(),
333
+ }),
334
+ config: (self) => {
335
+ // Custom config could add additional indexes, constraints, etc.
336
+ // This is called during table creation
337
+ return [];
338
+ },
339
+ });
340
+
341
+ class CustomApp {
342
+ custom = $repository(customEntity);
343
+ }
344
+
345
+ const alepha = Alepha.create();
346
+ const app = alepha.inject(CustomApp);
347
+ await alepha.start();
348
+
349
+ const record = await app.custom.create({
350
+ data: "test data",
351
+ });
352
+ expect(record.id).toBeDefined();
353
+ expect(record.data).toBe("test data");
354
+
355
+ await app.custom.clear({ force: true });
356
+ });
357
+
358
+ it("should handle entities with custom config in SQLite", async () => {
359
+ // Test entity with custom config function
360
+ const customEntity = $entity({
361
+ name: "custom_table_sqlite",
362
+ schema: t.object({
363
+ id: pg.primaryKey(),
364
+ data: t.string(),
365
+ }),
366
+ config: (self) => {
367
+ // Custom config for SQLite
368
+ return [];
369
+ },
370
+ });
371
+
372
+ class CustomApp {
373
+ custom = $repository(customEntity);
374
+ }
375
+
376
+ const alepha = Alepha.create({
377
+ env: {
378
+ DATABASE_URL: "sqlite://:memory:",
379
+ },
380
+ });
381
+ const app = alepha.inject(CustomApp);
382
+ await alepha.start();
383
+
384
+ const record = await app.custom.create({
385
+ data: "test data sqlite",
386
+ });
387
+ expect(record.id).toBeDefined();
388
+ expect(record.data).toBe("test data sqlite");
389
+
390
+ await app.custom.clear({ force: true });
391
+ });
392
+
393
+ it("should handle complex nested relationships", async () => {
394
+ const testComplexRelationships = async (alepha: Alepha) => {
395
+ // Category -> Product -> OrderItem -> Order -> User
396
+ const categoryEntity = $entity({
397
+ name: "categories",
398
+ schema: t.object({
399
+ id: pg.primaryKey(),
400
+ name: t.string(),
401
+ }),
402
+ indexes: [
403
+ {
404
+ column: "name",
405
+ unique: true,
406
+ },
407
+ ],
408
+ });
409
+
410
+ const productEntity = $entity({
411
+ name: "products",
412
+ schema: t.object({
413
+ id: pg.primaryKey(),
414
+ name: t.string(),
415
+ categoryId: t.integer(),
416
+ price: t.number(),
417
+ }),
418
+ indexes: [
419
+ "name",
420
+ {
421
+ columns: ["categoryId", "price"],
422
+ name: "category_price_idx",
423
+ },
424
+ ],
425
+ foreignKeys: [
426
+ {
427
+ columns: ["categoryId"],
428
+ foreignColumns: [() => categoryEntity.cols.id],
429
+ },
430
+ ],
431
+ constraints: [
432
+ {
433
+ columns: ["price"],
434
+ check: sql`price > 0`,
435
+ name: "positive_price",
436
+ },
437
+ ],
438
+ });
439
+
440
+ class ComplexApp {
441
+ categories = $repository(categoryEntity);
442
+ products = $repository(productEntity);
443
+ }
444
+
445
+ const app = alepha.inject(ComplexApp);
446
+ await alepha.start();
447
+
448
+ // Create test data
449
+ const electronics = await app.categories.create({
450
+ name: "Electronics",
451
+ });
452
+
453
+ const laptop = await app.products.create({
454
+ name: "Laptop",
455
+ categoryId: electronics.id,
456
+ price: 999.99,
457
+ });
458
+
459
+ expect(laptop.categoryId).toBe(electronics.id);
460
+ expect(laptop.price).toBe(999.99);
461
+
462
+ // Test constraint
463
+ try {
464
+ await app.products.create({
465
+ name: "Invalid Product",
466
+ categoryId: electronics.id,
467
+ price: -10, // Invalid price
468
+ });
469
+ expect.fail("Should have thrown check constraint error");
470
+ } catch (error) {
471
+ // Expected
472
+ expect(error).toBeDefined();
473
+ }
474
+
475
+ // Clean up
476
+ await app.products.clear({ force: true });
477
+ await app.categories.clear({ force: true });
478
+ };
479
+
480
+ // Test on both databases
481
+ await testComplexRelationships(Alepha.create());
482
+ await testComplexRelationships(
483
+ Alepha.create({
484
+ env: {
485
+ DATABASE_URL: "sqlite://:memory:",
486
+ },
487
+ }),
488
+ );
489
+ });
490
+ });
@@ -0,0 +1,186 @@
1
+ import { t } from "alepha";
2
+ import { describe, expect, it } from "vitest";
3
+ import { $entity } from "../primitives/$entity.ts";
4
+ import { pg } from "../providers/DatabaseTypeProvider.ts";
5
+
6
+ describe("ModelBuilder Type Safety", () => {
7
+ it("should enforce type-safe foreign key references", () => {
8
+ const roleEntity = $entity({
9
+ name: "roles",
10
+ schema: t.object({
11
+ id: pg.primaryKey(),
12
+ name: t.string(),
13
+ }),
14
+ });
15
+
16
+ const userEntity = $entity({
17
+ name: "users",
18
+ schema: t.object({
19
+ id: pg.primaryKey(),
20
+ email: t.email(),
21
+ roleId: t.integer(),
22
+ }),
23
+ foreignKeys: [
24
+ {
25
+ columns: ["roleId"],
26
+ // This should reference an EntityColumn from roleEntity
27
+ foreignColumns: [() => roleEntity.cols.id],
28
+ },
29
+ ],
30
+ });
31
+
32
+ // Test that we can access the column references
33
+ expect(roleEntity.cols.id).toBeDefined();
34
+ expect(roleEntity.cols.id.name).toBe("id");
35
+ expect(roleEntity.cols.id.entity).toBe(roleEntity);
36
+
37
+ expect(userEntity.cols.email).toBeDefined();
38
+ expect(userEntity.cols.email.name).toBe("email");
39
+
40
+ // Test that foreign key references work
41
+ const fkDef = userEntity.options.foreignKeys![0];
42
+ expect(fkDef.columns).toEqual(["roleId"]);
43
+
44
+ // Execute the foreign column reference function
45
+ const foreignCol = fkDef.foreignColumns[0]();
46
+ expect(foreignCol).toBeDefined();
47
+ expect(foreignCol.name).toBe("id");
48
+ expect(foreignCol.entity.name).toBe("roles");
49
+ });
50
+
51
+ it("should support multiple foreign key references", () => {
52
+ const categoryEntity = $entity({
53
+ name: "categories",
54
+ schema: t.object({
55
+ id: pg.primaryKey(),
56
+ name: t.string(),
57
+ }),
58
+ });
59
+
60
+ const userEntity = $entity({
61
+ name: "users",
62
+ schema: t.object({
63
+ id: pg.primaryKey(),
64
+ username: t.string(),
65
+ }),
66
+ });
67
+
68
+ const postEntity = $entity({
69
+ name: "posts",
70
+ schema: t.object({
71
+ id: pg.primaryKey(),
72
+ title: t.string(),
73
+ userId: t.integer(),
74
+ categoryId: t.integer(),
75
+ }),
76
+ foreignKeys: [
77
+ {
78
+ columns: ["userId"],
79
+ foreignColumns: [() => userEntity.cols.id],
80
+ },
81
+ {
82
+ columns: ["categoryId"],
83
+ foreignColumns: [() => categoryEntity.cols.id],
84
+ },
85
+ ],
86
+ });
87
+
88
+ const fks = postEntity.options.foreignKeys!;
89
+ expect(fks).toHaveLength(2);
90
+
91
+ // Check first foreign key (userId -> users.id)
92
+ const userFk = fks[0];
93
+ const userForeignCol = userFk.foreignColumns[0]();
94
+ expect(userForeignCol.entity.name).toBe("users");
95
+ expect(userForeignCol.name).toBe("id");
96
+
97
+ // Check second foreign key (categoryId -> categories.id)
98
+ const categoryFk = fks[1];
99
+ const categoryForeignCol = categoryFk.foreignColumns[0]();
100
+ expect(categoryForeignCol.entity.name).toBe("categories");
101
+ expect(categoryForeignCol.name).toBe("id");
102
+ });
103
+
104
+ it("should support composite foreign keys", () => {
105
+ const tenantEntity = $entity({
106
+ name: "tenants",
107
+ schema: t.object({
108
+ id: pg.primaryKey(),
109
+ code: t.string(),
110
+ name: t.string(),
111
+ }),
112
+ });
113
+
114
+ const userEntity = $entity({
115
+ name: "users",
116
+ schema: t.object({
117
+ id: pg.primaryKey(),
118
+ tenantId: t.integer(),
119
+ tenantCode: t.string(),
120
+ username: t.string(),
121
+ }),
122
+ foreignKeys: [
123
+ {
124
+ columns: ["tenantId", "tenantCode"],
125
+ foreignColumns: [
126
+ () => tenantEntity.cols.id,
127
+ () => tenantEntity.cols.code,
128
+ ],
129
+ },
130
+ ],
131
+ });
132
+
133
+ const fk = userEntity.options.foreignKeys![0];
134
+ expect(fk.columns).toEqual(["tenantId", "tenantCode"]);
135
+ expect(fk.foreignColumns).toHaveLength(2);
136
+
137
+ const foreignCol1 = fk.foreignColumns[0]();
138
+ const foreignCol2 = fk.foreignColumns[1]();
139
+
140
+ expect(foreignCol1.name).toBe("id");
141
+ expect(foreignCol2.name).toBe("code");
142
+ expect(foreignCol1.entity.name).toBe("tenants");
143
+ expect(foreignCol2.entity.name).toBe("tenants");
144
+ });
145
+
146
+ it("should maintain referential integrity through EntityColumn", () => {
147
+ const entity1 = $entity({
148
+ name: "entity1",
149
+ schema: t.object({
150
+ id: pg.primaryKey(),
151
+ value: t.string(),
152
+ }),
153
+ });
154
+
155
+ const entity2 = $entity({
156
+ name: "entity2",
157
+ schema: t.object({
158
+ id: pg.primaryKey(),
159
+ entity1Id: t.integer(),
160
+ entity1Value: t.string(),
161
+ }),
162
+ foreignKeys: [
163
+ {
164
+ name: "entity2_entity1_fk",
165
+ columns: ["entity1Id", "entity1Value"],
166
+ foreignColumns: [() => entity1.cols.id, () => entity1.cols.value],
167
+ },
168
+ ],
169
+ });
170
+
171
+ // Verify that the foreign key correctly references entity1's columns
172
+ const fk = entity2.options.foreignKeys![0];
173
+ expect(fk.name).toBe("entity2_entity1_fk");
174
+
175
+ const idRef = fk.foreignColumns[0]();
176
+ const valueRef = fk.foreignColumns[1]();
177
+
178
+ // Both columns should reference the same entity
179
+ expect(idRef.entity).toBe(valueRef.entity);
180
+ expect(idRef.entity.name).toBe("entity1");
181
+
182
+ // But different columns
183
+ expect(idRef.name).toBe("id");
184
+ expect(valueRef.name).toBe("value");
185
+ });
186
+ });
@@ -0,0 +1,46 @@
1
+ import { Alepha } from "alepha";
2
+ import { describe, expect, it } from "vitest";
3
+ import { $repository, AlephaPostgres } from "../index.ts";
4
+ import { userEntity } from "./fixtures/userEntitySchema.ts";
5
+
6
+ describe("PostgresProvider", () => {
7
+ it("should handle basic CRUD operations with timestamps", async () => {
8
+ class UserService {
9
+ users = $repository(userEntity);
10
+ }
11
+
12
+ const alepha = Alepha.create().with(AlephaPostgres);
13
+
14
+ const userService = alepha.inject(UserService);
15
+
16
+ await alepha.start();
17
+
18
+ await userService.users.create({
19
+ name: "John",
20
+ profile: {
21
+ age: 30,
22
+ },
23
+ });
24
+
25
+ const [r1] = await userService.users.findMany({
26
+ where: { name: { eq: "John" } },
27
+ });
28
+
29
+ expect(r1.name).toEqual("John");
30
+ expect(r1.createdAt).toBe(r1.updatedAt);
31
+
32
+ await new Promise((resolve) => setTimeout(resolve, 1));
33
+
34
+ const r2 = await userService.users.updateOne(
35
+ { name: { eq: "John" } },
36
+ {
37
+ profile: { age: 31 },
38
+ },
39
+ );
40
+
41
+ expect(r2.name).toEqual("John");
42
+ expect(r2.profile.age).toEqual(31);
43
+ expect(r2.createdAt).toBe(r1.createdAt);
44
+ expect(r2.updatedAt).not.toBe(r1.updatedAt);
45
+ });
46
+ });