alepha 0.14.2 → 0.14.4

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 (405) hide show
  1. package/README.md +1 -1
  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 +706 -785
  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 +58 -137
  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 +29 -108
  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 +504 -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 +277 -351
  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 +787 -852
  35. package/dist/api/users/index.d.ts.map +1 -1
  36. package/dist/api/users/index.js +827 -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 +128 -128
  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/bin/index.d.ts +1 -2
  45. package/dist/bin/index.js +0 -1
  46. package/dist/bin/index.js.map +1 -1
  47. package/dist/cli/index.d.ts +252 -131
  48. package/dist/cli/index.d.ts.map +1 -1
  49. package/dist/cli/index.js +595 -395
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/command/index.d.ts +46 -11
  52. package/dist/command/index.d.ts.map +1 -1
  53. package/dist/command/index.js +99 -19
  54. package/dist/command/index.js.map +1 -1
  55. package/dist/core/index.browser.js +40 -22
  56. package/dist/core/index.browser.js.map +1 -1
  57. package/dist/core/index.d.ts +45 -1
  58. package/dist/core/index.d.ts.map +1 -1
  59. package/dist/core/index.js +40 -22
  60. package/dist/core/index.js.map +1 -1
  61. package/dist/core/index.native.js +40 -22
  62. package/dist/core/index.native.js.map +1 -1
  63. package/dist/fake/index.js +195 -168
  64. package/dist/fake/index.js.map +1 -1
  65. package/dist/file/index.d.ts +8 -0
  66. package/dist/file/index.d.ts.map +1 -1
  67. package/dist/file/index.js +3 -0
  68. package/dist/file/index.js.map +1 -1
  69. package/dist/logger/index.d.ts +1 -1
  70. package/dist/logger/index.d.ts.map +1 -1
  71. package/dist/logger/index.js +12 -2
  72. package/dist/logger/index.js.map +1 -1
  73. package/dist/mcp/index.js +1 -1
  74. package/dist/mcp/index.js.map +1 -1
  75. package/dist/orm/index.d.ts +59 -195
  76. package/dist/orm/index.d.ts.map +1 -1
  77. package/dist/orm/index.js +201 -430
  78. package/dist/orm/index.js.map +1 -1
  79. package/dist/security/index.d.ts +1 -1
  80. package/dist/security/index.d.ts.map +1 -1
  81. package/dist/security/index.js +1 -1
  82. package/dist/security/index.js.map +1 -1
  83. package/dist/server/auth/index.d.ts +171 -155
  84. package/dist/server/auth/index.d.ts.map +1 -1
  85. package/dist/server/auth/index.js +0 -1
  86. package/dist/server/auth/index.js.map +1 -1
  87. package/dist/server/cache/index.d.ts +12 -0
  88. package/dist/server/cache/index.d.ts.map +1 -1
  89. package/dist/server/cache/index.js +55 -2
  90. package/dist/server/cache/index.js.map +1 -1
  91. package/dist/server/compress/index.d.ts +6 -0
  92. package/dist/server/compress/index.d.ts.map +1 -1
  93. package/dist/server/compress/index.js +38 -1
  94. package/dist/server/compress/index.js.map +1 -1
  95. package/dist/server/core/index.browser.js +2 -2
  96. package/dist/server/core/index.browser.js.map +1 -1
  97. package/dist/server/core/index.d.ts +10 -10
  98. package/dist/server/core/index.d.ts.map +1 -1
  99. package/dist/server/core/index.js +7 -4
  100. package/dist/server/core/index.js.map +1 -1
  101. package/dist/server/links/index.browser.js +22 -6
  102. package/dist/server/links/index.browser.js.map +1 -1
  103. package/dist/server/links/index.d.ts +46 -44
  104. package/dist/server/links/index.d.ts.map +1 -1
  105. package/dist/server/links/index.js +24 -41
  106. package/dist/server/links/index.js.map +1 -1
  107. package/dist/server/static/index.d.ts.map +1 -1
  108. package/dist/server/static/index.js +4 -0
  109. package/dist/server/static/index.js.map +1 -1
  110. package/dist/server/swagger/index.d.ts +2 -1
  111. package/dist/server/swagger/index.d.ts.map +1 -1
  112. package/dist/server/swagger/index.js +9 -5
  113. package/dist/server/swagger/index.js.map +1 -1
  114. package/dist/vite/index.d.ts +101 -106
  115. package/dist/vite/index.d.ts.map +1 -1
  116. package/dist/vite/index.js +574 -503
  117. package/dist/vite/index.js.map +1 -1
  118. package/dist/websocket/index.d.ts +7 -7
  119. package/package.json +7 -7
  120. package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
  121. package/src/api/audits/entities/audits.ts +5 -5
  122. package/src/api/audits/index.browser.ts +1 -1
  123. package/src/api/audits/index.ts +3 -3
  124. package/src/api/audits/primitives/$audit.spec.ts +276 -0
  125. package/src/api/audits/services/AuditService.spec.ts +495 -0
  126. package/src/api/files/__tests__/$bucket.spec.ts +91 -0
  127. package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
  128. package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
  129. package/src/api/files/controllers/FileController.spec.ts +558 -0
  130. package/src/api/files/controllers/FileController.ts +4 -5
  131. package/src/api/files/entities/files.ts +5 -5
  132. package/src/api/files/index.browser.ts +1 -1
  133. package/src/api/files/index.ts +4 -4
  134. package/src/api/files/jobs/FileJobs.spec.ts +52 -0
  135. package/src/api/files/services/FileService.spec.ts +109 -0
  136. package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
  137. package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
  138. package/src/api/jobs/entities/jobExecutions.ts +5 -5
  139. package/src/api/jobs/index.ts +3 -3
  140. package/src/api/jobs/primitives/$job.spec.ts +476 -0
  141. package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
  142. package/src/api/notifications/entities/notifications.ts +5 -5
  143. package/src/api/notifications/index.browser.ts +1 -1
  144. package/src/api/notifications/index.ts +4 -4
  145. package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
  146. package/src/api/parameters/entities/parameters.ts +7 -17
  147. package/src/api/parameters/index.ts +3 -3
  148. package/src/api/parameters/primitives/$config.spec.ts +356 -0
  149. package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
  150. package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
  151. package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
  152. package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
  153. package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
  154. package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
  155. package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
  156. package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
  157. package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
  158. package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
  159. package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
  160. package/src/api/parameters/schemas/index.ts +15 -0
  161. package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
  162. package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
  163. package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
  164. package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
  165. package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
  166. package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
  167. package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
  168. package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
  169. package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
  170. package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
  171. package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
  172. package/src/api/users/controllers/AdminUserController.ts +116 -0
  173. package/src/api/users/controllers/UserController.ts +4 -107
  174. package/src/api/users/controllers/UserRealmController.ts +3 -0
  175. package/src/api/users/entities/identities.ts +6 -6
  176. package/src/api/users/entities/sessions.ts +6 -6
  177. package/src/api/users/entities/users.ts +9 -9
  178. package/src/api/users/index.ts +9 -6
  179. package/src/api/users/primitives/$userRealm.ts +13 -8
  180. package/src/api/users/services/CredentialService.spec.ts +509 -0
  181. package/src/api/users/services/CredentialService.ts +46 -0
  182. package/src/api/users/services/IdentityService.ts +15 -0
  183. package/src/api/users/services/RegistrationService.spec.ts +630 -0
  184. package/src/api/users/services/RegistrationService.ts +18 -0
  185. package/src/api/users/services/SessionService.spec.ts +301 -0
  186. package/src/api/users/services/SessionService.ts +110 -1
  187. package/src/api/users/services/UserService.ts +67 -2
  188. package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
  189. package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
  190. package/src/api/verifications/entities/verifications.ts +6 -6
  191. package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
  192. package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
  193. package/src/batch/primitives/$batch.spec.ts +766 -0
  194. package/src/batch/providers/BatchProvider.spec.ts +786 -0
  195. package/src/bin/index.ts +0 -1
  196. package/src/bucket/__tests__/shared.ts +194 -0
  197. package/src/bucket/primitives/$bucket.spec.ts +104 -0
  198. package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
  199. package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
  200. package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
  201. package/src/cache/core/__tests__/shared.ts +377 -0
  202. package/src/cache/core/primitives/$cache.spec.ts +111 -0
  203. package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
  204. package/src/cli/apps/AlephaCli.ts +25 -6
  205. package/src/cli/atoms/buildOptions.ts +88 -0
  206. package/src/cli/commands/build.ts +32 -69
  207. package/src/cli/commands/db.ts +0 -4
  208. package/src/cli/commands/dev.ts +34 -10
  209. package/src/cli/commands/gen/changelog.spec.ts +315 -0
  210. package/src/cli/commands/{changelog.ts → gen/changelog.ts} +9 -9
  211. package/src/cli/commands/gen/env.ts +53 -0
  212. package/src/cli/commands/gen/openapi.ts +71 -0
  213. package/src/cli/commands/gen/resource.ts +15 -0
  214. package/src/cli/commands/gen.ts +24 -0
  215. package/src/cli/commands/init.ts +2 -1
  216. package/src/cli/commands/root.ts +12 -3
  217. package/src/cli/commands/test.ts +0 -1
  218. package/src/cli/commands/typecheck.ts +5 -0
  219. package/src/cli/commands/verify.ts +1 -1
  220. package/src/cli/defineConfig.ts +49 -7
  221. package/src/cli/index.ts +2 -2
  222. package/src/cli/services/AlephaCliUtils.ts +105 -55
  223. package/src/cli/services/GitMessageParser.ts +1 -1
  224. package/src/command/helpers/Asker.spec.ts +127 -0
  225. package/src/command/helpers/Runner.spec.ts +126 -0
  226. package/src/command/helpers/Runner.ts +1 -1
  227. package/src/command/primitives/$command.spec.ts +1588 -0
  228. package/src/command/primitives/$command.ts +0 -6
  229. package/src/command/providers/CliProvider.ts +75 -27
  230. package/src/core/Alepha.ts +87 -0
  231. package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
  232. package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
  233. package/src/core/__tests__/Alepha-has.spec.ts +41 -0
  234. package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
  235. package/src/core/__tests__/Alepha-register.spec.ts +81 -0
  236. package/src/core/__tests__/Alepha-start.spec.ts +176 -0
  237. package/src/core/__tests__/Alepha-with.spec.ts +14 -0
  238. package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
  239. package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
  240. package/src/core/__tests__/descriptor.spec.ts +34 -0
  241. package/src/core/__tests__/fixtures/A.ts +5 -0
  242. package/src/core/__tests__/pagination.spec.ts +77 -0
  243. package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
  244. package/src/core/primitives/$atom.spec.ts +43 -0
  245. package/src/core/primitives/$hook.spec.ts +130 -0
  246. package/src/core/primitives/$inject.spec.ts +175 -0
  247. package/src/core/primitives/$module.spec.ts +115 -0
  248. package/src/core/providers/CodecManager.spec.ts +740 -0
  249. package/src/core/providers/EventManager.spec.ts +762 -0
  250. package/src/core/providers/EventManager.ts +4 -0
  251. package/src/core/providers/StateManager.spec.ts +365 -0
  252. package/src/core/providers/TypeProvider.spec.ts +1607 -0
  253. package/src/core/providers/TypeProvider.ts +20 -26
  254. package/src/datetime/primitives/$interval.spec.ts +103 -0
  255. package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
  256. package/src/email/primitives/$email.spec.ts +175 -0
  257. package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
  258. package/src/fake/__tests__/keyName.example.ts +40 -0
  259. package/src/fake/__tests__/keyName.spec.ts +152 -0
  260. package/src/fake/__tests__/module.example.ts +32 -0
  261. package/src/fake/providers/FakeProvider.spec.ts +438 -0
  262. package/src/file/providers/FileSystemProvider.ts +8 -0
  263. package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
  264. package/src/file/providers/NodeFileSystemProvider.ts +5 -0
  265. package/src/file/services/FileDetector.spec.ts +591 -0
  266. package/src/lock/core/__tests__/shared.ts +190 -0
  267. package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
  268. package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
  269. package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
  270. package/src/logger/index.ts +15 -3
  271. package/src/logger/primitives/$logger.spec.ts +108 -0
  272. package/src/logger/services/Logger.spec.ts +295 -0
  273. package/src/mcp/__tests__/errors.spec.ts +175 -0
  274. package/src/mcp/__tests__/integration.spec.ts +450 -0
  275. package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
  276. package/src/mcp/primitives/$prompt.spec.ts +468 -0
  277. package/src/mcp/primitives/$resource.spec.ts +390 -0
  278. package/src/mcp/primitives/$tool.spec.ts +406 -0
  279. package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
  280. package/src/mcp/transports/StdioMcpTransport.ts +1 -1
  281. package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
  282. package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
  283. package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
  284. package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
  285. package/src/orm/__tests__/$repository-save.spec.ts +37 -0
  286. package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
  287. package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
  288. package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
  289. package/src/orm/__tests__/delete-returning.spec.ts +256 -0
  290. package/src/orm/__tests__/deletedAt.spec.ts +80 -0
  291. package/src/orm/__tests__/enums.spec.ts +315 -0
  292. package/src/orm/__tests__/execute.spec.ts +72 -0
  293. package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
  294. package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
  295. package/src/orm/__tests__/joins.spec.ts +1114 -0
  296. package/src/orm/__tests__/page.spec.ts +287 -0
  297. package/src/orm/__tests__/primaryKey.spec.ts +87 -0
  298. package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
  299. package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
  300. package/src/orm/__tests__/references.spec.ts +102 -0
  301. package/src/orm/__tests__/security.spec.ts +710 -0
  302. package/src/orm/__tests__/sqlite.spec.ts +111 -0
  303. package/src/orm/__tests__/string-operators.spec.ts +429 -0
  304. package/src/orm/__tests__/timestamps.spec.ts +388 -0
  305. package/src/orm/__tests__/validation.spec.ts +183 -0
  306. package/src/orm/__tests__/version.spec.ts +64 -0
  307. package/src/orm/helpers/parseQueryString.spec.ts +196 -0
  308. package/src/orm/index.ts +2 -8
  309. package/src/orm/primitives/$repository.spec.ts +137 -0
  310. package/src/orm/primitives/$sequence.spec.ts +29 -0
  311. package/src/orm/primitives/$transaction.spec.ts +82 -0
  312. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
  313. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  314. package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
  315. package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
  316. package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
  317. package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
  318. package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
  319. package/src/orm/services/ModelBuilder.spec.ts +575 -0
  320. package/src/orm/services/Repository.spec.ts +137 -0
  321. package/src/queue/core/__tests__/shared.ts +143 -0
  322. package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
  323. package/src/queue/core/providers/WorkerProvider.spec.ts +394 -0
  324. package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
  325. package/src/redis/__tests__/redis.spec.ts +58 -0
  326. package/src/retry/primitives/$retry.spec.ts +234 -0
  327. package/src/retry/providers/RetryProvider.spec.ts +438 -0
  328. package/src/router/__tests__/match.spec.ts +252 -0
  329. package/src/router/providers/RouterProvider.spec.ts +197 -0
  330. package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
  331. package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
  332. package/src/scheduler/__tests__/shared.ts +77 -0
  333. package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
  334. package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
  335. package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
  336. package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
  337. package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
  338. package/src/security/primitives/$permission.spec.ts +30 -0
  339. package/src/security/primitives/$permission.ts +2 -2
  340. package/src/security/primitives/$realm.spec.ts +101 -0
  341. package/src/security/primitives/$role.spec.ts +52 -0
  342. package/src/security/primitives/$serviceAccount.spec.ts +61 -0
  343. package/src/security/providers/SecurityProvider.spec.ts +350 -0
  344. package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
  345. package/src/server/cache/providers/ServerCacheProvider.spec.ts +1125 -0
  346. package/src/server/cache/providers/ServerCacheProvider.ts +94 -9
  347. package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
  348. package/src/server/compress/providers/ServerCompressProvider.ts +63 -2
  349. package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
  350. package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
  351. package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
  352. package/src/server/core/helpers/ServerReply.ts +2 -2
  353. package/src/server/core/primitives/$action.spec.ts +191 -0
  354. package/src/server/core/primitives/$route.spec.ts +65 -0
  355. package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
  356. package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
  357. package/src/server/core/providers/ServerProvider.ts +14 -2
  358. package/src/server/core/services/HttpClient.spec.ts +123 -0
  359. package/src/server/core/services/UserAgentParser.spec.ts +111 -0
  360. package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
  361. package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
  362. package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
  363. package/src/server/links/__tests__/$action.spec.ts +238 -0
  364. package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
  365. package/src/server/links/__tests__/requestId.spec.ts +120 -0
  366. package/src/server/links/primitives/$remote.spec.ts +228 -0
  367. package/src/server/links/providers/LinkProvider.spec.ts +54 -0
  368. package/src/server/links/providers/LinkProvider.ts +49 -3
  369. package/src/server/links/providers/ServerLinksProvider.ts +1 -53
  370. package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
  371. package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
  372. package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
  373. package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
  374. package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
  375. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
  376. package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
  377. package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
  378. package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
  379. package/src/server/static/primitives/$serve.spec.ts +193 -0
  380. package/src/server/static/providers/ServerStaticProvider.ts +10 -0
  381. package/src/server/swagger/__tests__/ui.spec.ts +52 -0
  382. package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
  383. package/src/server/swagger/providers/ServerSwaggerProvider.ts +19 -12
  384. package/src/sms/primitives/$sms.spec.ts +165 -0
  385. package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
  386. package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
  387. package/src/thread/primitives/$thread.spec.ts +186 -0
  388. package/src/topic/core/__tests__/shared.ts +144 -0
  389. package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
  390. package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
  391. package/src/vite/helpers/importViteReact.ts +13 -0
  392. package/src/vite/index.ts +1 -21
  393. package/src/vite/plugins/viteAlephaDev.ts +32 -5
  394. package/src/vite/plugins/viteAlephaSsrPreload.ts +222 -0
  395. package/src/vite/tasks/buildClient.ts +11 -0
  396. package/src/vite/tasks/buildServer.ts +47 -3
  397. package/src/vite/tasks/devServer.ts +69 -0
  398. package/src/vite/tasks/index.ts +2 -1
  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/assets/viteConfigTs.ts +0 -14
  403. package/src/cli/commands/run.ts +0 -24
  404. package/src/vite/plugins/viteAlepha.ts +0 -37
  405. package/src/vite/plugins/viteAlephaBuild.ts +0 -281
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/api/parameters/entities/parameters.ts","../../../src/api/parameters/services/ConfigStore.ts","../../../src/api/parameters/controllers/ConfigController.ts","../../../src/api/parameters/schedulers/ConfigActivationScheduler.ts","../../../src/api/parameters/primitives/$config.ts","../../../src/api/parameters/index.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\n\n/**\n * Parameter status values.\n *\n * - EXPIRED: Past version, no longer active\n * - CURRENT: Currently active version\n * - NEXT: Scheduled to become active (closest future date)\n * - FUTURE: Scheduled for activation after NEXT\n */\nexport type ParameterStatus = \"expired\" | \"current\" | \"next\" | \"future\";\n\n/**\n * Configuration parameter entity for versioned configuration management.\n *\n * Stores all versions of configuration parameters with:\n * - Automatic status management (expired, current, next, future)\n * - Schema versioning for migrations\n * - Activation scheduling\n * - Audit trail (creator info)\n */\nexport const parameters = $entity({\n name: \"parameters\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n\n /**\n * Configuration name using dot notation for tree hierarchy.\n * Examples: \"app.features\", \"app.pricing.tiers\", \"system.limits\"\n */\n name: t.text(),\n\n /**\n * The configuration content as JSON.\n */\n content: t.json(),\n\n /**\n * Schema version hash for detecting schema changes.\n * Used for auto-migration when schema evolves.\n */\n schemaHash: t.text(),\n\n /**\n * Current status of this parameter version.\n */\n status: pg.default(\n t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n \"future\",\n ),\n\n /**\n * When this version should become active.\n * Default is immediate (now).\n */\n activationDate: t.datetime(),\n\n /**\n * When this version was deactivated (became expired).\n * Null if still active or scheduled.\n */\n expiredAt: t.optional(t.datetime()),\n\n /**\n * Version number for this configuration.\n * Auto-incremented per config name.\n */\n version: t.integer(),\n\n /**\n * Optional description of changes in this version.\n */\n changeDescription: t.optional(t.text()),\n\n /**\n * Optional tags for filtering/categorization.\n */\n tags: t.optional(t.array(t.text())),\n\n /**\n * Creator user ID (if available).\n */\n creatorId: t.optional(t.uuid()),\n\n /**\n * Creator display name for audit trail.\n */\n creatorName: t.optional(t.text()),\n\n /**\n * Previous content before this change (for rollback reference).\n */\n previousContent: t.optional(t.json()),\n\n /**\n * Migration log if schema changed.\n */\n migrationLog: t.optional(t.text()),\n }),\n indexes: [\n { columns: [\"name\", \"status\"] },\n { columns: [\"name\", \"activationDate\"] },\n { columns: [\"name\", \"version\"], unique: true },\n { columns: [\"status\"] },\n { columns: [\"activationDate\"] },\n ],\n});\n\nexport type Parameter = Static<typeof parameters.schema>;\nexport type ParameterInsert = Omit<Parameter, \"id\" | \"createdAt\" | \"updatedAt\">;\n","import { $inject, type Static, type TObject, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { $topic } from \"alepha/topic\";\nimport {\n type Parameter,\n type ParameterStatus,\n parameters,\n} from \"../entities/parameters.ts\";\nimport type { ConfigPrimitive } from \"../primitives/$config.ts\";\n\n/**\n * Payload for config sync events across instances.\n */\nexport interface ConfigSyncPayload {\n name: string;\n version: number;\n content: unknown;\n status: ParameterStatus;\n instanceId: string;\n}\n\n/**\n * ConfigStore manages versioned configuration persistence and synchronization.\n *\n * Features:\n * - Stores all config versions in PostgreSQL\n * - Manages status transitions (future → next → current → expired)\n * - Provides cross-instance sync via topic\n * - Supports schema migrations via hash comparison\n * - Auto-activates scheduled configs\n */\nexport class ConfigStore {\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly repo = $repository(parameters);\n\n /** Unique identifier for this instance (to avoid self-updates) */\n protected readonly instanceId = crypto.randomUUID();\n\n /** In-memory cache of registered configs */\n protected readonly configs = new Map<string, ConfigPrimitive<any>>();\n\n /** Topic for cross-instance synchronization */\n public readonly syncTopic = $topic({\n name: \"config:sync\",\n schema: {\n payload: t.object({\n name: t.text(),\n version: t.integer(),\n content: t.json(),\n status: t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n instanceId: t.text(),\n }),\n },\n handler: async ({ payload }) => {\n await this.handleSyncMessage(payload as ConfigSyncPayload);\n },\n });\n\n /**\n * Register a config primitive with the store.\n */\n public register(config: ConfigPrimitive<any>): void {\n this.configs.set(config.name, config);\n }\n\n /**\n * Load the current config value from database.\n * Returns the current or next version if no current exists.\n */\n public async load<T extends TObject>(\n name: string,\n ): Promise<Static<T> | null> {\n // First try to get CURRENT\n const all = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n\n let param = all.find((p) => p.status === \"current\");\n\n // If no current, get NEXT (will become current)\n if (!param) {\n param = all\n .filter((p) => p.status === \"next\")\n .sort((a, b) => {\n return (\n new Date(a.activationDate).getTime() -\n new Date(b.activationDate).getTime()\n );\n })[0];\n }\n\n return param?.content as Static<T> | null;\n }\n\n /**\n * Save a new config version.\n *\n * @param name - Config name (e.g., \"app.features.flags\")\n * @param content - New config content\n * @param schemaHash - Hash of the schema for migration detection\n * @param options - Additional options (activation date, creator info, etc.)\n */\n public async save<T extends TObject>(\n name: string,\n content: Static<T>,\n schemaHash: string,\n options: SaveConfigOptions = {},\n ): Promise<Parameter> {\n const now = this.dateTimeProvider.now().toDate();\n const activationDate = options.activationDate ?? now;\n const isImmediate = activationDate <= now;\n\n // Get current version number for this config\n const versions = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n\n const latestVersion = versions[0];\n const newVersion = (latestVersion?.version ?? 0) + 1;\n\n // Determine initial status\n let status: ParameterStatus = \"future\";\n if (isImmediate) {\n status = \"current\";\n }\n\n // Get previous content for rollback reference\n const currentConfig = versions.find((v) => v.status === \"current\");\n const previousContent = currentConfig?.content;\n\n // Check for schema migration\n let migrationLog: string | undefined;\n if (latestVersion && latestVersion.schemaHash !== schemaHash) {\n migrationLog = `Schema changed from ${latestVersion.schemaHash} to ${schemaHash} at version ${newVersion}`;\n this.log.info(\"Config schema migration detected\", { name, migrationLog });\n }\n\n // If immediate activation, expire current and transition next to current\n if (isImmediate) {\n await this.transitionStatuses(name, now);\n }\n\n // Insert new version - convert Date to ISO string for datetime fields\n const inserted = await this.repo.create({\n name,\n content: content as Record<string, unknown>,\n schemaHash,\n status,\n activationDate: activationDate.toISOString(),\n version: newVersion,\n changeDescription: options.changeDescription,\n tags: options.tags,\n creatorId: options.creatorId,\n creatorName: options.creatorName,\n previousContent: previousContent as Record<string, unknown> | undefined,\n migrationLog,\n });\n\n // Recalculate statuses after insert\n await this.recalculateStatuses(name);\n\n // Publish sync event\n await this.publishSync(name, newVersion, content, status);\n\n this.log.info(\"Config saved\", { name, version: newVersion, status });\n\n return inserted;\n }\n\n /**\n * Get all versions of a config.\n */\n public async getHistory(name: string): Promise<Parameter[]> {\n return this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n }\n\n /**\n * Get a specific version of a config.\n */\n public async getVersion(\n name: string,\n version: number,\n ): Promise<Parameter | null> {\n const versions = await this.repo.findMany({\n where: { name, version },\n });\n return versions[0] ?? null;\n }\n\n /**\n * Rollback to a previous version by creating a new version with old content.\n */\n public async rollback(\n name: string,\n targetVersion: number,\n options: SaveConfigOptions = {},\n ): Promise<Parameter> {\n const target = await this.getVersion(name, targetVersion);\n\n if (!target) {\n throw new Error(`Config version not found: ${name}@${targetVersion}`);\n }\n\n return this.save(\n name,\n target.content as Static<TObject>,\n target.schemaHash,\n {\n ...options,\n changeDescription:\n options.changeDescription ?? `Rollback to version ${targetVersion}`,\n },\n );\n }\n\n /**\n * Get all configs by status.\n */\n public async getByStatus(status: ParameterStatus): Promise<Parameter[]> {\n return this.repo.findMany({\n where: { status },\n orderBy: { column: \"name\", direction: \"asc\" },\n });\n }\n\n /**\n * Get current config value with fallback to default from registered primitive.\n * Returns the in-memory current value which may be the default if never saved.\n */\n public getCurrentValue(\n name: string,\n ): { content: unknown; isDefault: boolean } | null {\n const config = this.configs.get(name);\n if (!config) {\n return null;\n }\n return {\n content: config.current,\n isDefault: true, // Will be updated after checking history\n };\n }\n\n /**\n * Get config info including current value with default fallback.\n */\n public async getCurrentWithDefault(name: string): Promise<{\n current: Parameter | null;\n next: Parameter | null;\n defaultValue: unknown | null;\n currentValue: unknown | null;\n schema: TObject | null;\n }> {\n const history = await this.getHistory(name);\n const current = history.find((v) => v.status === \"current\") ?? null;\n const next = history.find((v) => v.status === \"next\") ?? null;\n\n // Get default and current from registered primitive\n const config = this.configs.get(name);\n const defaultValue = config?.options.default ?? null;\n const currentValue = config?.current ?? null;\n const schema = config?.schema ?? null;\n\n return { current, next, defaultValue, currentValue, schema };\n }\n\n /**\n * Get all unique config names (for tree view).\n */\n public async getConfigNames(): Promise<string[]> {\n const results = await this.repo.findMany({\n orderBy: { column: \"name\", direction: \"asc\" },\n });\n\n const names = new Set<string>();\n for (const r of results) {\n names.add(r.name);\n }\n\n return Array.from(names);\n }\n\n /**\n * Build a tree structure from config names for UI.\n * Includes both database configs and registered (but not yet saved) configs.\n */\n public async getConfigTree(): Promise<ConfigTreeNode[]> {\n const dbNames = await this.getConfigNames();\n const registeredNames = Array.from(this.configs.keys());\n const allNames = [...new Set([...dbNames, ...registeredNames])].sort();\n return this.buildTree(allNames);\n }\n\n /**\n * Check and activate scheduled configs that are due.\n * Should be called periodically (e.g., via scheduler).\n */\n public async activateScheduledConfigs(): Promise<void> {\n const now = this.dateTimeProvider.now().toDate();\n\n // Find all NEXT configs that should be activated\n const dueConfigs = await this.repo.findMany({\n where: { status: \"next\" },\n });\n\n for (const config of dueConfigs) {\n if (new Date(config.activationDate) <= now) {\n await this.transitionStatuses(config.name, now);\n await this.recalculateStatuses(config.name);\n\n // Notify registered config primitives\n const primitive = this.configs.get(config.name);\n if (primitive) {\n await primitive.reload();\n }\n\n // Publish sync\n await this.publishSync(\n config.name,\n config.version,\n config.content,\n \"current\",\n );\n }\n }\n }\n\n /**\n * Transition config statuses when a new current is activated.\n */\n protected async transitionStatuses(name: string, now: Date): Promise<void> {\n // Find current configs and expire them\n const currentConfigs = await this.repo.findMany({\n where: { name, status: \"current\" },\n });\n\n for (const config of currentConfigs) {\n await this.repo.updateById(config.id, {\n status: \"expired\",\n expiredAt: now.toISOString(),\n });\n }\n }\n\n /**\n * Recalculate statuses based on activation dates.\n */\n protected async recalculateStatuses(name: string): Promise<void> {\n const now = this.dateTimeProvider.now().toDate();\n\n // Get all versions ordered by activation date\n const versions = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"activationDate\", direction: \"asc\" },\n });\n\n const nonExpired = versions.filter(\n (v: Parameter) => v.status !== \"expired\",\n );\n\n // Find which should be current (latest activated)\n const shouldBeCurrent = nonExpired\n .filter((v: Parameter) => new Date(v.activationDate) <= now)\n .pop();\n\n // Find which should be next (closest future)\n const futureVersions = nonExpired.filter(\n (v: Parameter) => new Date(v.activationDate) > now,\n );\n const shouldBeNext = futureVersions[0];\n\n for (const v of nonExpired) {\n let newStatus: ParameterStatus;\n\n if (shouldBeCurrent && v.id === shouldBeCurrent.id) {\n newStatus = \"current\";\n } else if (shouldBeNext && v.id === shouldBeNext.id) {\n newStatus = \"next\";\n } else if (new Date(v.activationDate) > now) {\n newStatus = \"future\";\n } else {\n newStatus = \"expired\";\n }\n\n if (v.status !== newStatus) {\n await this.repo.updateById(v.id, {\n status: newStatus,\n expiredAt: newStatus === \"expired\" ? now.toISOString() : undefined,\n });\n }\n }\n }\n\n /**\n * Publish sync event to other instances.\n */\n protected async publishSync(\n name: string,\n version: number,\n content: unknown,\n status: ParameterStatus,\n ): Promise<void> {\n await this.syncTopic.publish({\n name,\n version,\n content: content as Record<string, unknown>,\n status,\n instanceId: this.instanceId,\n });\n }\n\n /**\n * Handle incoming sync message from other instances.\n */\n protected async handleSyncMessage(payload: ConfigSyncPayload): Promise<void> {\n // Ignore messages from self\n if (payload.instanceId === this.instanceId) {\n return;\n }\n\n const config = this.configs.get(payload.name);\n if (!config) {\n return;\n }\n\n // Update config with skipEvents to avoid infinite loop\n if (payload.status === \"current\") {\n await config.updateFromSync(payload.content);\n }\n }\n\n /**\n * Build tree structure from dot-notation names.\n */\n protected buildTree(names: string[]): ConfigTreeNode[] {\n const root: ConfigTreeNode[] = [];\n\n for (const name of names) {\n const parts = name.split(\".\");\n let currentLevel = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const isLeaf = i === parts.length - 1;\n const path = parts.slice(0, i + 1).join(\".\");\n\n let existing = currentLevel.find((n) => n.name === part);\n\n if (!existing) {\n existing = {\n name: part,\n path,\n isLeaf,\n children: [],\n };\n currentLevel.push(existing);\n }\n\n if (isLeaf) {\n existing.isLeaf = true;\n }\n\n currentLevel = existing.children;\n }\n }\n\n return root;\n }\n}\n\nexport interface SaveConfigOptions {\n activationDate?: Date;\n changeDescription?: string;\n tags?: string[];\n creatorId?: string;\n creatorName?: string;\n}\n\nexport interface ConfigTreeNode {\n name: string;\n path: string;\n isLeaf: boolean;\n children: ConfigTreeNode[];\n}\n","import { $inject, t } from \"alepha\";\nimport { $action } from \"alepha/server\";\nimport type { ParameterStatus } from \"../entities/parameters.ts\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n// Define response schemas inline to avoid complex entity schema issues\nconst parameterResponseSchema = t.object({\n id: t.uuid(),\n createdAt: t.datetime(),\n updatedAt: t.datetime(),\n name: t.text(),\n content: t.json(),\n schemaHash: t.text(),\n status: t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n activationDate: t.datetime(),\n expiredAt: t.optional(t.datetime()),\n version: t.integer(),\n changeDescription: t.optional(t.text()),\n tags: t.optional(t.array(t.text())),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n previousContent: t.optional(t.json()),\n migrationLog: t.optional(t.text()),\n});\n\nconst treeNodeSchema: any = t.object({\n name: t.text(),\n path: t.text(),\n isLeaf: t.boolean(),\n children: t.array(t.any()),\n});\n\n/**\n * REST API controller for versioned configuration management.\n *\n * Provides endpoints for:\n * - Listing all configurations (tree view support)\n * - Getting configuration history (all versions)\n * - Getting current/next configuration values\n * - Creating new configuration versions (immediate or scheduled)\n * - Rolling back to previous versions\n * - Activating scheduled versions immediately\n */\nexport class ConfigController {\n protected readonly store = $inject(ConfigStore);\n\n /**\n * Get tree structure of all configuration names.\n * Useful for admin UI navigation.\n */\n getConfigTree = $action({\n description:\n \"Get tree structure of all configuration names for navigation.\",\n path: \"/configs/tree\",\n method: \"GET\",\n schema: {\n response: t.array(treeNodeSchema),\n },\n handler: async () => {\n return this.store.getConfigTree();\n },\n });\n\n /**\n * List all unique configuration names.\n */\n listConfigNames = $action({\n description: \"List all unique configuration names.\",\n path: \"/configs\",\n method: \"GET\",\n schema: {\n response: t.object({\n names: t.array(t.text()),\n }),\n },\n handler: async () => {\n const names = await this.store.getConfigNames();\n return { names };\n },\n });\n\n /**\n * Get configurations by status.\n */\n getByStatus = $action({\n description: \"Get all configurations with a specific status.\",\n path: \"/configs/status/:status\",\n method: \"GET\",\n schema: {\n params: t.object({\n status: t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n }),\n response: t.object({\n configs: t.array(parameterResponseSchema),\n }),\n },\n handler: async ({ params }) => {\n const configs = await this.store.getByStatus(\n params.status as ParameterStatus,\n );\n return { configs };\n },\n });\n\n /**\n * Get version history for a specific configuration.\n */\n getHistory = $action({\n description: \"Get all versions of a specific configuration.\",\n path: \"/configs/:name/history\",\n method: \"GET\",\n schema: {\n params: t.object({\n name: t.text({\n description: \"Configuration name (e.g., app.features.flags)\",\n }),\n }),\n response: t.object({\n versions: t.array(parameterResponseSchema),\n }),\n },\n handler: async ({ params }) => {\n const versions = await this.store.getHistory(params.name);\n return { versions };\n },\n });\n\n /**\n * Get current and next values for a configuration.\n * Includes defaultValue and currentValue from the registered primitive\n * even if no versions exist in the database yet.\n */\n getCurrent = $action({\n description: \"Get current and next scheduled values for a configuration.\",\n path: \"/configs/:name\",\n method: \"GET\",\n schema: {\n params: t.object({\n name: t.text({\n description: \"Configuration name (e.g., app.features.flags)\",\n }),\n }),\n response: t.object({\n current: t.optional(parameterResponseSchema),\n next: t.optional(parameterResponseSchema),\n defaultValue: t.optional(t.json()),\n currentValue: t.optional(t.json()),\n schema: t.optional(t.json()),\n }),\n },\n handler: async ({ params }) => {\n const result = await this.store.getCurrentWithDefault(params.name);\n return {\n current: result.current ?? undefined,\n next: result.next ?? undefined,\n defaultValue: result.defaultValue ?? undefined,\n currentValue: result.currentValue ?? undefined,\n schema: result.schema ?? undefined,\n };\n },\n });\n\n /**\n * Get a specific version of a configuration.\n */\n getVersion = $action({\n description: \"Get a specific version of a configuration.\",\n path: \"/configs/:name/versions/:version\",\n method: \"GET\",\n schema: {\n params: t.object({\n name: t.text(),\n version: t.integer(),\n }),\n response: t.object({\n config: t.optional(parameterResponseSchema),\n }),\n },\n handler: async ({ params }) => {\n const config = await this.store.getVersion(params.name, params.version);\n return { config: config ?? undefined };\n },\n });\n\n /**\n * Create a new configuration version.\n */\n createVersion = $action({\n description:\n \"Create a new version of a configuration (immediate or scheduled).\",\n path: \"/configs/:name\",\n method: \"POST\",\n schema: {\n params: t.object({\n name: t.text({\n description: \"Configuration name (e.g., app.features.flags)\",\n }),\n }),\n body: t.object({\n content: t.json({ description: \"New configuration content\" }),\n schemaHash: t.text({\n description: \"Hash of the schema for migration detection\",\n }),\n activationDate: t.optional(\n t.datetime({ description: \"When to activate (default: now)\" }),\n ),\n changeDescription: t.optional(\n t.text({ description: \"Description of changes\" }),\n ),\n tags: t.optional(t.array(t.text())),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n }),\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n return this.store.save(params.name, body.content, body.schemaHash, {\n activationDate: body.activationDate\n ? new Date(body.activationDate)\n : undefined,\n changeDescription: body.changeDescription,\n tags: body.tags,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Rollback to a previous version.\n */\n rollback = $action({\n description:\n \"Rollback a configuration to a previous version (creates new version with old content).\",\n path: \"/configs/:name/rollback\",\n method: \"POST\",\n schema: {\n params: t.object({\n name: t.text(),\n }),\n body: t.object({\n targetVersion: t.integer({\n description: \"Version number to rollback to\",\n }),\n changeDescription: t.optional(t.text()),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n }),\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n return this.store.rollback(params.name, body.targetVersion, {\n changeDescription: body.changeDescription,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Activate a scheduled version immediately.\n */\n activateNow = $action({\n description: \"Activate a future/next configuration version immediately.\",\n path: \"/configs/:name/activate\",\n method: \"POST\",\n schema: {\n params: t.object({\n name: t.text(),\n }),\n body: t.object({\n version: t.integer({ description: \"Version number to activate\" }),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n }),\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n const target = await this.store.getVersion(params.name, body.version);\n if (!target) {\n throw new Error(\n `Version ${body.version} not found for config ${params.name}`,\n );\n }\n\n if (target.status === \"current\") {\n return target; // Already current\n }\n\n if (target.status === \"expired\") {\n throw new Error(\n \"Cannot activate an expired version. Use rollback instead.\",\n );\n }\n\n // Create new version with same content but immediate activation\n return this.store.save(params.name, target.content, target.schemaHash, {\n changeDescription: `Early activation of version ${body.version}`,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Trigger activation check for all scheduled configs.\n * Normally called by a scheduler, but exposed for manual triggering.\n */\n checkScheduled = $action({\n description:\n \"Manually trigger activation check for all scheduled configurations.\",\n path: \"/configs/activate-scheduled\",\n method: \"POST\",\n schema: {\n response: t.object({\n message: t.text(),\n }),\n },\n handler: async () => {\n await this.store.activateScheduledConfigs();\n return { message: \"Scheduled configuration activation check completed\" };\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n/**\n * Scheduler that periodically checks for scheduled configurations\n * that should be activated.\n *\n * Runs every minute to check if any NEXT configurations have reached\n * their activation date and need to be promoted to CURRENT.\n */\nexport class ConfigActivationScheduler {\n protected readonly log = $logger();\n protected readonly store = $inject(ConfigStore);\n\n /**\n * Check for scheduled configurations every minute.\n */\n checkActivations = $scheduler({\n name: \"config-activation-check\",\n description: \"Checks for scheduled configurations that should be activated\",\n interval: [1, \"minute\"],\n lock: true,\n handler: async () => {\n this.log.debug(\"Checking for scheduled config activations\");\n await this.store.activateScheduledConfigs();\n },\n });\n}\n","import {\n $hook,\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type TObject,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { UserAccount } from \"alepha/security\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n/**\n * Creates a versioned configuration primitive for managing application settings.\n *\n * Provides type-safe, versioned configuration with:\n * - Schema validation with auto-migration detection\n * - Default values for initial state\n * - Scheduled activation (FUTURE, NEXT, CURRENT, EXPIRED statuses)\n * - PostgreSQL persistence with full version history\n * - Cross-instance synchronization via topic\n * - Tree view support via dot-notation naming (e.g., \"app.features.flags\")\n *\n * Integrates with Alepha's atom system for state management:\n * - Uses `alepha.set(atom, value)` for mutations\n * - Listens to `state:mutate` events to detect changes\n * - Auto-persists changes to database\n * - Syncs across instances via topic\n *\n * @example\n * ```ts\n * class AppConfig {\n * features = $config({\n * name: \"app.features.flags\",\n * schema: t.object({\n * enableBeta: t.boolean(),\n * maxUploadSize: t.number()\n * }),\n * default: { enableBeta: false, maxUploadSize: 10485760 }\n * });\n *\n * async enableBeta() {\n * // Immediate activation\n * await this.features.set({ enableBeta: true, maxUploadSize: 20971520 });\n * }\n *\n * async scheduleBetaRelease() {\n * // Schedule for future activation\n * await this.features.set(\n * { enableBeta: true, maxUploadSize: 20971520 },\n * { activationDate: new Date('2024-03-01') }\n * );\n * }\n * }\n * ```\n */\nexport interface ConfigPrimitiveOptions<T extends TObject> {\n /**\n * Configuration name using dot notation for tree hierarchy.\n * Examples: \"app.features\", \"app.pricing.tiers\", \"system.limits\"\n */\n name?: string;\n\n /**\n * Human-readable description of the configuration.\n */\n description?: string;\n\n /**\n * TypeBox schema defining the configuration structure.\n */\n schema: T;\n\n /**\n * Default value used when no configuration exists in database.\n */\n default: Static<T>;\n}\n\nexport class ConfigPrimitive<T extends TObject> extends Primitive<\n ConfigPrimitiveOptions<T>\n> {\n protected readonly log = $logger();\n protected readonly store = $inject(ConfigStore);\n\n /** Internal atom key for state management */\n protected atomKey!: string;\n\n /** Schema hash for migration detection */\n protected schemaHash!: string;\n\n /** Whether we're currently syncing (to avoid loops) */\n protected syncing = false;\n\n /** Whether initial load has completed */\n protected loaded = false;\n\n /**\n * Configuration name (uses property key if not specified).\n */\n public get name(): string {\n return this.options.name || this.config.propertyKey;\n }\n\n /**\n * The TypeBox schema for this configuration.\n */\n public get schema(): T {\n return this.options.schema;\n }\n\n /**\n * Get the current configuration value.\n */\n public get current(): Static<T> {\n return (\n (this.alepha.store.get(this.atomKey as any) as Static<T>) ??\n this.options.default\n );\n }\n\n /**\n * Get a specific field from the current configuration.\n */\n public get<Key extends keyof Static<T>>(key: Key): Static<T>[Key] {\n return this.current[key];\n }\n\n /**\n * Set a new configuration value.\n *\n * @param value - The new configuration value\n * @param options - Optional settings (activation date, creator info, etc.)\n */\n public async set(\n value: Static<T>,\n options: SetConfigOptions = {},\n ): Promise<void> {\n // Save to database\n await this.store.save(this.name, value, this.schemaHash, {\n activationDate: options.activationDate,\n changeDescription: options.changeDescription,\n tags: options.tags,\n creatorId: options.user?.id,\n creatorName: options.user?.name ?? options.user?.email,\n });\n\n // If immediate activation (no future date), update state\n const now = new Date();\n if (!options.activationDate || options.activationDate <= now) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value);\n } finally {\n this.syncing = false;\n }\n }\n }\n\n /**\n * Subscribe to configuration changes.\n */\n public sub(fn: (curr: Static<T>) => void): () => void {\n return this.alepha.events.on(\"state:mutate\", {\n callback: ({ key, value }) => {\n if (key === this.atomKey) {\n fn(value as Static<T>);\n }\n },\n });\n }\n\n /**\n * Reload configuration from database.\n * Called when scheduled config activates or sync message received.\n */\n public async reload(): Promise<void> {\n const value = await this.store.load<T>(this.name);\n if (value !== null) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value, { skipEvents: true });\n } finally {\n this.syncing = false;\n }\n }\n }\n\n /**\n * Update from sync message (called by ConfigStore).\n * Uses skipEvents to avoid infinite loops.\n */\n public async updateFromSync(content: unknown): Promise<void> {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, content as Static<T>, {\n skipEvents: true,\n });\n } finally {\n this.syncing = false;\n }\n }\n\n /**\n * Get version history for this configuration.\n */\n public async getHistory() {\n return this.store.getHistory(this.name);\n }\n\n /**\n * Rollback to a specific version.\n */\n public async rollback(\n version: number,\n options?: SetConfigOptions,\n ): Promise<void> {\n await this.store.rollback(this.name, version, {\n changeDescription: options?.changeDescription,\n creatorId: options?.user?.id,\n creatorName: options?.user?.name ?? options?.user?.email,\n });\n await this.reload();\n }\n\n /**\n * Hook to load initial value from database on start.\n */\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n await this.loadInitial();\n },\n });\n\n /**\n * Called after primitive creation to initialize.\n */\n protected onInit(): void {\n // Create unique key for state management\n this.atomKey = `config:${this.name}`;\n\n // Calculate schema hash for migration detection\n this.schemaHash = this.calculateSchemaHash();\n\n // Register with store\n this.store.register(this);\n\n // Set initial default using key-based state\n this.alepha.store.set(this.atomKey as any, this.options.default, {\n skipEvents: true,\n });\n\n // Listen for state mutations to detect external changes via alepha.set()\n // Note: state:mutate is not in Hooks interface, so we use events.on() directly\n this.alepha.events.on(\"state:mutate\", {\n caller: this.config.service,\n callback: async ({ key, value, prevValue }) => {\n // Only handle our key\n if (key !== this.atomKey) {\n return;\n }\n\n // Skip if we're syncing (to avoid infinite loop)\n if (this.syncing) {\n return;\n }\n\n // Skip if value hasn't actually changed\n if (JSON.stringify(value) === JSON.stringify(prevValue)) {\n return;\n }\n\n // Auto-save to database when state is mutated via alepha.set()\n this.log.debug(\"Config state mutated, persisting to database\", {\n name: this.name,\n });\n await this.store.save(this.name, value as Static<T>, this.schemaHash);\n },\n });\n }\n\n /**\n * Load initial value from database.\n */\n protected async loadInitial(): Promise<void> {\n if (this.loaded) {\n return;\n }\n\n const value = await this.store.load<T>(this.name);\n\n if (value !== null) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value, { skipEvents: true });\n } finally {\n this.syncing = false;\n }\n }\n\n this.loaded = true;\n }\n\n /**\n * Calculate a hash of the schema for migration detection.\n */\n protected calculateSchemaHash(): string {\n const schemaJson = JSON.stringify(this.options.schema);\n // Simple hash - in production you might want a proper hash function\n let hash = 0;\n for (let i = 0; i < schemaJson.length; i++) {\n const char = schemaJson.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash.toString(16);\n }\n}\n\nexport const $config = <T extends TObject>(\n options: ConfigPrimitiveOptions<T>,\n) => {\n return createPrimitive(ConfigPrimitive<T>, options);\n};\n\n$config[KIND] = ConfigPrimitive;\n\nexport interface SetConfigOptions {\n /**\n * User making the change (for audit trail).\n */\n user?: Pick<UserAccount, \"id\" | \"email\" | \"name\">;\n\n /**\n * When this configuration should become active.\n * Default is immediate (now).\n */\n activationDate?: Date;\n\n /**\n * Description of the change.\n */\n changeDescription?: string;\n\n /**\n * Tags for filtering/categorization.\n */\n tags?: string[];\n}\n","import { $module } from \"alepha\";\nimport { ConfigController } from \"./controllers/ConfigController.ts\";\nimport { ConfigActivationScheduler } from \"./schedulers/ConfigActivationScheduler.ts\";\nimport { ConfigStore } from \"./services/ConfigStore.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n// Controller exports\nexport * from \"./controllers/ConfigController.ts\";\n// Entity exports\nexport * from \"./entities/parameters.ts\";\n// Primitive exports\nexport * from \"./primitives/$config.ts\";\n// Scheduler exports\nexport * from \"./schedulers/ConfigActivationScheduler.ts\";\n// Service exports\nexport * from \"./services/ConfigStore.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides versioned configuration management for Alepha applications.\n *\n * Features:\n * - Type-safe, versioned configuration with `$config` primitive\n * - Schema validation with auto-migration detection\n * - Scheduled activation (FUTURE, NEXT, CURRENT, EXPIRED statuses)\n * - PostgreSQL persistence with full version history\n * - Cross-instance synchronization via topic\n * - Tree view support via dot-notation naming\n * - REST API for configuration management\n * - Automatic activation scheduler\n *\n * @example\n * ```ts\n * import { Alepha } from \"alepha\";\n * import { AlephaApiParameters } from \"alepha/api/parameters\";\n *\n * const alepha = Alepha.create();\n * alepha.with(AlephaApiParameters);\n *\n * // Then use $config in your services:\n * class AppConfig {\n * features = $config({\n * name: \"app.features.flags\",\n * schema: t.object({\n * enableBeta: t.boolean(),\n * maxUploadSize: t.number()\n * }),\n * default: { enableBeta: false, maxUploadSize: 10485760 }\n * });\n * }\n * ```\n *\n * @module alepha.api.parameters\n */\nexport const AlephaApiParameters = $module({\n name: \"alepha.api.parameters\",\n services: [ConfigStore, ConfigController, ConfigActivationScheduler],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/api/parameters/schemas/activateConfigBodySchema.ts","../../../src/api/parameters/schemas/checkScheduledResponseSchema.ts","../../../src/api/parameters/schemas/parameterStatusSchema.ts","../../../src/api/parameters/schemas/parameterResponseSchema.ts","../../../src/api/parameters/schemas/configCurrentResponseSchema.ts","../../../src/api/parameters/schemas/configHistoryResponseSchema.ts","../../../src/api/parameters/schemas/configNameParamSchema.ts","../../../src/api/parameters/schemas/configNamesResponseSchema.ts","../../../src/api/parameters/schemas/configsByStatusResponseSchema.ts","../../../src/api/parameters/schemas/configTreeNodeSchema.ts","../../../src/api/parameters/schemas/configVersionParamSchema.ts","../../../src/api/parameters/schemas/configVersionResponseSchema.ts","../../../src/api/parameters/schemas/createConfigVersionBodySchema.ts","../../../src/api/parameters/schemas/rollbackConfigBodySchema.ts","../../../src/api/parameters/schemas/statusParamSchema.ts","../../../src/api/parameters/entities/parameters.ts","../../../src/api/parameters/services/ConfigStore.ts","../../../src/api/parameters/controllers/AdminConfigController.ts","../../../src/api/parameters/schedulers/ConfigActivationScheduler.ts","../../../src/api/parameters/primitives/$config.ts","../../../src/api/parameters/index.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\n\n/**\n * Activate config body schema.\n */\nexport const activateConfigBodySchema = t.object({\n version: t.integer({ description: \"Version number to activate\" }),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n});\n\nexport type ActivateConfigBody = Static<typeof activateConfigBodySchema>;\n","import { t } from \"alepha\";\n\n/**\n * Check scheduled response schema.\n */\nexport const checkScheduledResponseSchema = t.object({\n message: t.text(),\n});\n","import { type Static, t } from \"alepha\";\n\n/**\n * Parameter status enum schema.\n */\nexport const parameterStatusSchema = t.enum([\n \"expired\",\n \"current\",\n \"next\",\n \"future\",\n]);\n\nexport type ParameterStatus = Static<typeof parameterStatusSchema>;\n","import { type Static, t } from \"alepha\";\nimport { parameterStatusSchema } from \"./parameterStatusSchema.ts\";\n\n/**\n * Parameter response schema for API responses.\n */\nexport const parameterResponseSchema = t.object({\n id: t.uuid(),\n createdAt: t.datetime(),\n updatedAt: t.datetime(),\n name: t.text(),\n content: t.json(),\n schemaHash: t.text(),\n status: parameterStatusSchema,\n activationDate: t.datetime(),\n expiredAt: t.optional(t.datetime()),\n version: t.integer(),\n changeDescription: t.optional(t.text()),\n tags: t.optional(t.array(t.text())),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n previousContent: t.optional(t.json()),\n migrationLog: t.optional(t.text()),\n});\n\nexport type ParameterResponse = Static<typeof parameterResponseSchema>;\n","import { t } from \"alepha\";\nimport { parameterResponseSchema } from \"./parameterResponseSchema.ts\";\n\n/**\n * Current config response schema.\n */\nexport const configCurrentResponseSchema = t.object({\n current: t.optional(parameterResponseSchema),\n next: t.optional(parameterResponseSchema),\n defaultValue: t.optional(t.json()),\n currentValue: t.optional(t.json()),\n schema: t.optional(t.json()),\n});\n","import { t } from \"alepha\";\nimport { parameterResponseSchema } from \"./parameterResponseSchema.ts\";\n\n/**\n * Config history response schema.\n */\nexport const configHistoryResponseSchema = t.object({\n versions: t.array(parameterResponseSchema),\n});\n","import { t } from \"alepha\";\n\n/**\n * Config name param schema.\n */\nexport const configNameParamSchema = t.object({\n name: t.text({\n description: \"Configuration name (e.g., app.features.flags)\",\n }),\n});\n","import { t } from \"alepha\";\n\n/**\n * Config names list response schema.\n */\nexport const configNamesResponseSchema = t.object({\n names: t.array(t.text()),\n});\n","import { t } from \"alepha\";\nimport { parameterResponseSchema } from \"./parameterResponseSchema.ts\";\n\n/**\n * Configs by status response schema.\n */\nexport const configsByStatusResponseSchema = t.object({\n configs: t.array(parameterResponseSchema),\n});\n","import { type Static, t } from \"alepha\";\n\n/**\n * Tree node schema for configuration tree navigation.\n */\nexport const configTreeNodeSchema = t.object({\n name: t.text(),\n path: t.text(),\n isLeaf: t.boolean(),\n children: t.array(t.any()),\n});\n\nexport type ConfigTreeNode = Static<typeof configTreeNodeSchema>;\n","import { t } from \"alepha\";\n\n/**\n * Config name and version param schema.\n */\nexport const configVersionParamSchema = t.object({\n name: t.text(),\n version: t.integer(),\n});\n","import { t } from \"alepha\";\nimport { parameterResponseSchema } from \"./parameterResponseSchema.ts\";\n\n/**\n * Config version response schema.\n */\nexport const configVersionResponseSchema = t.object({\n config: t.optional(parameterResponseSchema),\n});\n","import { type Static, t } from \"alepha\";\n\n/**\n * Create config version body schema.\n */\nexport const createConfigVersionBodySchema = t.object({\n content: t.json({ description: \"New configuration content\" }),\n schemaHash: t.text({\n description: \"Hash of the schema for migration detection\",\n }),\n activationDate: t.optional(\n t.datetime({ description: \"When to activate (default: now)\" }),\n ),\n changeDescription: t.optional(\n t.text({ description: \"Description of changes\" }),\n ),\n tags: t.optional(t.array(t.text())),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n});\n\nexport type CreateConfigVersionBody = Static<\n typeof createConfigVersionBodySchema\n>;\n","import { type Static, t } from \"alepha\";\n\n/**\n * Rollback config body schema.\n */\nexport const rollbackConfigBodySchema = t.object({\n targetVersion: t.integer({\n description: \"Version number to rollback to\",\n }),\n changeDescription: t.optional(t.text()),\n creatorId: t.optional(t.uuid()),\n creatorName: t.optional(t.text()),\n});\n\nexport type RollbackConfigBody = Static<typeof rollbackConfigBodySchema>;\n","import { t } from \"alepha\";\nimport { parameterStatusSchema } from \"./parameterStatusSchema.ts\";\n\n/**\n * Status param schema.\n */\nexport const statusParamSchema = t.object({\n status: parameterStatusSchema,\n});\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\nimport { parameterStatusSchema } from \"../schemas/index.ts\";\n\nexport type { ParameterStatus } from \"../schemas/index.ts\";\n\n/**\n * Configuration parameter entity for versioned configuration management.\n *\n * Stores all versions of configuration parameters with:\n * - Automatic status management (expired, current, next, future)\n * - Schema versioning for migrations\n * - Activation scheduling\n * - Audit trail (creator info)\n */\nexport const parameters = $entity({\n name: \"parameters\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n\n /**\n * Configuration name using dot notation for tree hierarchy.\n * Examples: \"app.features\", \"app.pricing.tiers\", \"system.limits\"\n */\n name: t.text(),\n\n /**\n * The configuration content as JSON.\n */\n content: t.json(),\n\n /**\n * Schema version hash for detecting schema changes.\n * Used for auto-migration when schema evolves.\n */\n schemaHash: t.text(),\n\n /**\n * Current status of this parameter version.\n */\n status: db.default(parameterStatusSchema, \"future\"),\n\n /**\n * When this version should become active.\n * Default is immediate (now).\n */\n activationDate: t.datetime(),\n\n /**\n * When this version was deactivated (became expired).\n * Null if still active or scheduled.\n */\n expiredAt: t.optional(t.datetime()),\n\n /**\n * Version number for this configuration.\n * Auto-incremented per config name.\n */\n version: t.integer(),\n\n /**\n * Optional description of changes in this version.\n */\n changeDescription: t.optional(t.text()),\n\n /**\n * Optional tags for filtering/categorization.\n */\n tags: t.optional(t.array(t.text())),\n\n /**\n * Creator user ID (if available).\n */\n creatorId: t.optional(t.uuid()),\n\n /**\n * Creator display name for audit trail.\n */\n creatorName: t.optional(t.text()),\n\n /**\n * Previous content before this change (for rollback reference).\n */\n previousContent: t.optional(t.json()),\n\n /**\n * Migration log if schema changed.\n */\n migrationLog: t.optional(t.text()),\n }),\n indexes: [\n { columns: [\"name\", \"status\"] },\n { columns: [\"name\", \"activationDate\"] },\n { columns: [\"name\", \"version\"], unique: true },\n { columns: [\"status\"] },\n { columns: [\"activationDate\"] },\n ],\n});\n\nexport type Parameter = Static<typeof parameters.schema>;\nexport type ParameterInsert = Omit<Parameter, \"id\" | \"createdAt\" | \"updatedAt\">;\n","import { $inject, type Static, type TObject, t } from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository } from \"alepha/orm\";\nimport { $topic } from \"alepha/topic\";\nimport {\n type Parameter,\n type ParameterStatus,\n parameters,\n} from \"../entities/parameters.ts\";\nimport type { ConfigPrimitive } from \"../primitives/$config.ts\";\n\n/**\n * Payload for config sync events across instances.\n */\nexport interface ConfigSyncPayload {\n name: string;\n version: number;\n content: unknown;\n status: ParameterStatus;\n instanceId: string;\n}\n\n/**\n * ConfigStore manages versioned configuration persistence and synchronization.\n *\n * Features:\n * - Stores all config versions in PostgreSQL\n * - Manages status transitions (future → next → current → expired)\n * - Provides cross-instance sync via topic\n * - Supports schema migrations via hash comparison\n * - Auto-activates scheduled configs\n */\nexport class ConfigStore {\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly repo = $repository(parameters);\n\n /** Unique identifier for this instance (to avoid self-updates) */\n protected readonly instanceId = crypto.randomUUID();\n\n /** In-memory cache of registered configs */\n protected readonly configs = new Map<string, ConfigPrimitive<any>>();\n\n /** Topic for cross-instance synchronization */\n public readonly syncTopic = $topic({\n name: \"config:sync\",\n schema: {\n payload: t.object({\n name: t.text(),\n version: t.integer(),\n content: t.json(),\n status: t.enum([\"expired\", \"current\", \"next\", \"future\"]),\n instanceId: t.text(),\n }),\n },\n handler: async ({ payload }) => {\n await this.handleSyncMessage(payload as ConfigSyncPayload);\n },\n });\n\n /**\n * Register a config primitive with the store.\n */\n public register(config: ConfigPrimitive<any>): void {\n this.configs.set(config.name, config);\n }\n\n /**\n * Load the current config value from database.\n * Returns the current or next version if no current exists.\n */\n public async load<T extends TObject>(\n name: string,\n ): Promise<Static<T> | null> {\n // First try to get CURRENT\n const all = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n\n let param = all.find((p) => p.status === \"current\");\n\n // If no current, get NEXT (will become current)\n if (!param) {\n param = all\n .filter((p) => p.status === \"next\")\n .sort((a, b) => {\n return (\n new Date(a.activationDate).getTime() -\n new Date(b.activationDate).getTime()\n );\n })[0];\n }\n\n return param?.content as Static<T> | null;\n }\n\n /**\n * Save a new config version.\n *\n * @param name - Config name (e.g., \"app.features.flags\")\n * @param content - New config content\n * @param schemaHash - Hash of the schema for migration detection\n * @param options - Additional options (activation date, creator info, etc.)\n */\n public async save<T extends TObject>(\n name: string,\n content: Static<T>,\n schemaHash: string,\n options: SaveConfigOptions = {},\n ): Promise<Parameter> {\n const now = this.dateTimeProvider.now().toDate();\n const activationDate = options.activationDate ?? now;\n const isImmediate = activationDate <= now;\n\n // Get current version number for this config\n const versions = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n\n const latestVersion = versions[0];\n const newVersion = (latestVersion?.version ?? 0) + 1;\n\n // Determine initial status\n let status: ParameterStatus = \"future\";\n if (isImmediate) {\n status = \"current\";\n }\n\n // Get previous content for rollback reference\n const currentConfig = versions.find((v) => v.status === \"current\");\n const previousContent = currentConfig?.content;\n\n // Check for schema migration\n let migrationLog: string | undefined;\n if (latestVersion && latestVersion.schemaHash !== schemaHash) {\n migrationLog = `Schema changed from ${latestVersion.schemaHash} to ${schemaHash} at version ${newVersion}`;\n this.log.info(\"Config schema migration detected\", { name, migrationLog });\n }\n\n // If immediate activation, expire current and transition next to current\n if (isImmediate) {\n await this.transitionStatuses(name, now);\n }\n\n // Insert new version - convert Date to ISO string for datetime fields\n const inserted = await this.repo.create({\n name,\n content: content as Record<string, unknown>,\n schemaHash,\n status,\n activationDate: activationDate.toISOString(),\n version: newVersion,\n changeDescription: options.changeDescription,\n tags: options.tags,\n creatorId: options.creatorId,\n creatorName: options.creatorName,\n previousContent: previousContent as Record<string, unknown> | undefined,\n migrationLog,\n });\n\n // Recalculate statuses after insert\n await this.recalculateStatuses(name);\n\n // Publish sync event\n await this.publishSync(name, newVersion, content, status);\n\n this.log.info(\"Config saved\", { name, version: newVersion, status });\n\n return inserted;\n }\n\n /**\n * Get all versions of a config.\n */\n public async getHistory(name: string): Promise<Parameter[]> {\n return this.repo.findMany({\n where: { name },\n orderBy: { column: \"version\", direction: \"desc\" },\n });\n }\n\n /**\n * Get a specific version of a config.\n */\n public async getVersion(\n name: string,\n version: number,\n ): Promise<Parameter | null> {\n const versions = await this.repo.findMany({\n where: { name, version },\n });\n return versions[0] ?? null;\n }\n\n /**\n * Rollback to a previous version by creating a new version with old content.\n */\n public async rollback(\n name: string,\n targetVersion: number,\n options: SaveConfigOptions = {},\n ): Promise<Parameter> {\n const target = await this.getVersion(name, targetVersion);\n\n if (!target) {\n throw new Error(`Config version not found: ${name}@${targetVersion}`);\n }\n\n return this.save(\n name,\n target.content as Static<TObject>,\n target.schemaHash,\n {\n ...options,\n changeDescription:\n options.changeDescription ?? `Rollback to version ${targetVersion}`,\n },\n );\n }\n\n /**\n * Get all configs by status.\n */\n public async getByStatus(status: ParameterStatus): Promise<Parameter[]> {\n return this.repo.findMany({\n where: { status },\n orderBy: { column: \"name\", direction: \"asc\" },\n });\n }\n\n /**\n * Get current config value with fallback to default from registered primitive.\n * Returns the in-memory current value which may be the default if never saved.\n */\n public getCurrentValue(\n name: string,\n ): { content: unknown; isDefault: boolean } | null {\n const config = this.configs.get(name);\n if (!config) {\n return null;\n }\n return {\n content: config.current,\n isDefault: true, // Will be updated after checking history\n };\n }\n\n /**\n * Get config info including current value with default fallback.\n */\n public async getCurrentWithDefault(name: string): Promise<{\n current: Parameter | null;\n next: Parameter | null;\n defaultValue: unknown | null;\n currentValue: unknown | null;\n schema: TObject | null;\n }> {\n const history = await this.getHistory(name);\n const current = history.find((v) => v.status === \"current\") ?? null;\n const next = history.find((v) => v.status === \"next\") ?? null;\n\n // Get default and current from registered primitive\n const config = this.configs.get(name);\n const defaultValue = config?.options.default ?? null;\n const currentValue = config?.current ?? null;\n const schema = config?.schema ?? null;\n\n return { current, next, defaultValue, currentValue, schema };\n }\n\n /**\n * Get all unique config names (for tree view).\n */\n public async getConfigNames(): Promise<string[]> {\n const results = await this.repo.findMany({\n orderBy: { column: \"name\", direction: \"asc\" },\n });\n\n const names = new Set<string>();\n for (const r of results) {\n names.add(r.name);\n }\n\n return Array.from(names);\n }\n\n /**\n * Build a tree structure from config names for UI.\n * Includes both database configs and registered (but not yet saved) configs.\n */\n public async getConfigTree(): Promise<ConfigTreeNode[]> {\n const dbNames = await this.getConfigNames();\n const registeredNames = Array.from(this.configs.keys());\n const allNames = [...new Set([...dbNames, ...registeredNames])].sort();\n return this.buildTree(allNames);\n }\n\n /**\n * Check and activate scheduled configs that are due.\n * Should be called periodically (e.g., via scheduler).\n */\n public async activateScheduledConfigs(): Promise<void> {\n const now = this.dateTimeProvider.now().toDate();\n\n // Find all NEXT configs that should be activated\n const dueConfigs = await this.repo.findMany({\n where: { status: \"next\" },\n });\n\n for (const config of dueConfigs) {\n if (new Date(config.activationDate) <= now) {\n await this.transitionStatuses(config.name, now);\n await this.recalculateStatuses(config.name);\n\n // Notify registered config primitives\n const primitive = this.configs.get(config.name);\n if (primitive) {\n await primitive.reload();\n }\n\n // Publish sync\n await this.publishSync(\n config.name,\n config.version,\n config.content,\n \"current\",\n );\n }\n }\n }\n\n /**\n * Transition config statuses when a new current is activated.\n */\n protected async transitionStatuses(name: string, now: Date): Promise<void> {\n // Find current configs and expire them\n const currentConfigs = await this.repo.findMany({\n where: { name, status: \"current\" },\n });\n\n for (const config of currentConfigs) {\n await this.repo.updateById(config.id, {\n status: \"expired\",\n expiredAt: now.toISOString(),\n });\n }\n }\n\n /**\n * Recalculate statuses based on activation dates.\n */\n protected async recalculateStatuses(name: string): Promise<void> {\n const now = this.dateTimeProvider.now().toDate();\n\n // Get all versions ordered by activation date\n const versions = await this.repo.findMany({\n where: { name },\n orderBy: { column: \"activationDate\", direction: \"asc\" },\n });\n\n const nonExpired = versions.filter(\n (v: Parameter) => v.status !== \"expired\",\n );\n\n // Find which should be current (latest activated)\n const shouldBeCurrent = nonExpired\n .filter((v: Parameter) => new Date(v.activationDate) <= now)\n .pop();\n\n // Find which should be next (closest future)\n const futureVersions = nonExpired.filter(\n (v: Parameter) => new Date(v.activationDate) > now,\n );\n const shouldBeNext = futureVersions[0];\n\n for (const v of nonExpired) {\n let newStatus: ParameterStatus;\n\n if (shouldBeCurrent && v.id === shouldBeCurrent.id) {\n newStatus = \"current\";\n } else if (shouldBeNext && v.id === shouldBeNext.id) {\n newStatus = \"next\";\n } else if (new Date(v.activationDate) > now) {\n newStatus = \"future\";\n } else {\n newStatus = \"expired\";\n }\n\n if (v.status !== newStatus) {\n await this.repo.updateById(v.id, {\n status: newStatus,\n expiredAt: newStatus === \"expired\" ? now.toISOString() : undefined,\n });\n }\n }\n }\n\n /**\n * Publish sync event to other instances.\n */\n protected async publishSync(\n name: string,\n version: number,\n content: unknown,\n status: ParameterStatus,\n ): Promise<void> {\n await this.syncTopic.publish({\n name,\n version,\n content: content as Record<string, unknown>,\n status,\n instanceId: this.instanceId,\n });\n }\n\n /**\n * Handle incoming sync message from other instances.\n */\n protected async handleSyncMessage(payload: ConfigSyncPayload): Promise<void> {\n // Ignore messages from self\n if (payload.instanceId === this.instanceId) {\n return;\n }\n\n const config = this.configs.get(payload.name);\n if (!config) {\n return;\n }\n\n // Update config with skipEvents to avoid infinite loop\n if (payload.status === \"current\") {\n await config.updateFromSync(payload.content);\n }\n }\n\n /**\n * Build tree structure from dot-notation names.\n */\n protected buildTree(names: string[]): ConfigTreeNode[] {\n const root: ConfigTreeNode[] = [];\n\n for (const name of names) {\n const parts = name.split(\".\");\n let currentLevel = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const isLeaf = i === parts.length - 1;\n const path = parts.slice(0, i + 1).join(\".\");\n\n let existing = currentLevel.find((n) => n.name === part);\n\n if (!existing) {\n existing = {\n name: part,\n path,\n isLeaf,\n children: [],\n };\n currentLevel.push(existing);\n }\n\n if (isLeaf) {\n existing.isLeaf = true;\n }\n\n currentLevel = existing.children;\n }\n }\n\n return root;\n }\n}\n\nexport interface SaveConfigOptions {\n activationDate?: Date;\n changeDescription?: string;\n tags?: string[];\n creatorId?: string;\n creatorName?: string;\n}\n\nexport interface ConfigTreeNode {\n name: string;\n path: string;\n isLeaf: boolean;\n children: ConfigTreeNode[];\n}\n","import { $inject, t } from \"alepha\";\nimport { $action } from \"alepha/server\";\nimport type { ParameterStatus } from \"../entities/parameters.ts\";\nimport {\n activateConfigBodySchema,\n checkScheduledResponseSchema,\n configCurrentResponseSchema,\n configHistoryResponseSchema,\n configNameParamSchema,\n configNamesResponseSchema,\n configsByStatusResponseSchema,\n configTreeNodeSchema,\n configVersionParamSchema,\n configVersionResponseSchema,\n createConfigVersionBodySchema,\n parameterResponseSchema,\n rollbackConfigBodySchema,\n statusParamSchema,\n} from \"../schemas/index.ts\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n/**\n * REST API controller for versioned configuration management.\n *\n * Provides endpoints for:\n * - Listing all configurations (tree view support)\n * - Getting configuration history (all versions)\n * - Getting current/next configuration values\n * - Creating new configuration versions (immediate or scheduled)\n * - Rolling back to previous versions\n * - Activating scheduled versions immediately\n */\nexport class AdminConfigController {\n protected readonly url = \"/configs\";\n protected readonly group = \"admin:configs\";\n protected readonly store = $inject(ConfigStore);\n\n /**\n * Get tree structure of all configuration names.\n * Useful for admin UI navigation.\n */\n getConfigTree = $action({\n group: this.group,\n description:\n \"Get tree structure of all configuration names for navigation.\",\n path: \"/configs/tree\",\n method: \"GET\",\n schema: {\n response: t.array(configTreeNodeSchema),\n },\n handler: async () => {\n return this.store.getConfigTree();\n },\n });\n\n /**\n * List all unique configuration names.\n */\n listConfigNames = $action({\n group: this.group,\n description: \"List all unique configuration names.\",\n path: \"/configs\",\n method: \"GET\",\n schema: {\n response: configNamesResponseSchema,\n },\n handler: async () => {\n const names = await this.store.getConfigNames();\n return { names };\n },\n });\n\n /**\n * Get configurations by status.\n */\n getByStatus = $action({\n group: this.group,\n description: \"Get all configurations with a specific status.\",\n path: \"/configs/status/:status\",\n method: \"GET\",\n schema: {\n params: statusParamSchema,\n response: configsByStatusResponseSchema,\n },\n handler: async ({ params }) => {\n const configs = await this.store.getByStatus(\n params.status as ParameterStatus,\n );\n return { configs };\n },\n });\n\n /**\n * Get version history for a specific configuration.\n */\n getHistory = $action({\n group: this.group,\n description: \"Get all versions of a specific configuration.\",\n path: \"/configs/:name/history\",\n method: \"GET\",\n schema: {\n params: configNameParamSchema,\n response: configHistoryResponseSchema,\n },\n handler: async ({ params }) => {\n const versions = await this.store.getHistory(params.name);\n return { versions };\n },\n });\n\n /**\n * Get current and next values for a configuration.\n * Includes defaultValue and currentValue from the registered primitive\n * even if no versions exist in the database yet.\n */\n getCurrent = $action({\n group: this.group,\n description: \"Get current and next scheduled values for a configuration.\",\n path: \"/configs/:name\",\n method: \"GET\",\n schema: {\n params: configNameParamSchema,\n response: configCurrentResponseSchema,\n },\n handler: async ({ params }) => {\n const result = await this.store.getCurrentWithDefault(params.name);\n return {\n current: result.current ?? undefined,\n next: result.next ?? undefined,\n defaultValue: result.defaultValue ?? undefined,\n currentValue: result.currentValue ?? undefined,\n schema: result.schema ?? undefined,\n };\n },\n });\n\n /**\n * Get a specific version of a configuration.\n */\n getVersion = $action({\n group: this.group,\n description: \"Get a specific version of a configuration.\",\n path: \"/configs/:name/versions/:version\",\n method: \"GET\",\n schema: {\n params: configVersionParamSchema,\n response: configVersionResponseSchema,\n },\n handler: async ({ params }) => {\n const config = await this.store.getVersion(params.name, params.version);\n return { config: config ?? undefined };\n },\n });\n\n /**\n * Create a new configuration version.\n */\n createVersion = $action({\n group: this.group,\n description:\n \"Create a new version of a configuration (immediate or scheduled).\",\n path: \"/configs/:name\",\n method: \"POST\",\n schema: {\n params: configNameParamSchema,\n body: createConfigVersionBodySchema,\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n return this.store.save(params.name, body.content, body.schemaHash, {\n activationDate: body.activationDate\n ? new Date(body.activationDate)\n : undefined,\n changeDescription: body.changeDescription,\n tags: body.tags,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Rollback to a previous version.\n */\n rollback = $action({\n group: this.group,\n description:\n \"Rollback a configuration to a previous version (creates new version with old content).\",\n path: \"/configs/:name/rollback\",\n method: \"POST\",\n schema: {\n params: configNameParamSchema,\n body: rollbackConfigBodySchema,\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n return this.store.rollback(params.name, body.targetVersion, {\n changeDescription: body.changeDescription,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Activate a scheduled version immediately.\n */\n activateNow = $action({\n group: this.group,\n description: \"Activate a future/next configuration version immediately.\",\n path: \"/configs/:name/activate\",\n method: \"POST\",\n schema: {\n params: configNameParamSchema,\n body: activateConfigBodySchema,\n response: parameterResponseSchema,\n },\n handler: async ({ params, body }) => {\n const target = await this.store.getVersion(params.name, body.version);\n if (!target) {\n throw new Error(\n `Version ${body.version} not found for config ${params.name}`,\n );\n }\n\n if (target.status === \"current\") {\n return target; // Already current\n }\n\n if (target.status === \"expired\") {\n throw new Error(\n \"Cannot activate an expired version. Use rollback instead.\",\n );\n }\n\n // Create new version with same content but immediate activation\n return this.store.save(params.name, target.content, target.schemaHash, {\n changeDescription: `Early activation of version ${body.version}`,\n creatorId: body.creatorId,\n creatorName: body.creatorName,\n });\n },\n });\n\n /**\n * Trigger activation check for all scheduled configs.\n * Normally called by a scheduler, but exposed for manual triggering.\n */\n checkScheduled = $action({\n group: this.group,\n description:\n \"Manually trigger activation check for all scheduled configurations.\",\n path: \"/configs/activate-scheduled\",\n method: \"POST\",\n schema: {\n response: checkScheduledResponseSchema,\n },\n handler: async () => {\n await this.store.activateScheduledConfigs();\n return { message: \"Scheduled configuration activation check completed\" };\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n/**\n * Scheduler that periodically checks for scheduled configurations\n * that should be activated.\n *\n * Runs every minute to check if any NEXT configurations have reached\n * their activation date and need to be promoted to CURRENT.\n */\nexport class ConfigActivationScheduler {\n protected readonly log = $logger();\n protected readonly store = $inject(ConfigStore);\n\n /**\n * Check for scheduled configurations every minute.\n */\n checkActivations = $scheduler({\n name: \"config-activation-check\",\n description: \"Checks for scheduled configurations that should be activated\",\n interval: [1, \"minute\"],\n lock: true,\n handler: async () => {\n this.log.debug(\"Checking for scheduled config activations\");\n await this.store.activateScheduledConfigs();\n },\n });\n}\n","import {\n $hook,\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type Static,\n type TObject,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport type { UserAccount } from \"alepha/security\";\nimport { ConfigStore } from \"../services/ConfigStore.ts\";\n\n/**\n * Creates a versioned configuration primitive for managing application settings.\n *\n * Provides type-safe, versioned configuration with:\n * - Schema validation with auto-migration detection\n * - Default values for initial state\n * - Scheduled activation (FUTURE, NEXT, CURRENT, EXPIRED statuses)\n * - PostgreSQL persistence with full version history\n * - Cross-instance synchronization via topic\n * - Tree view support via dot-notation naming (e.g., \"app.features.flags\")\n *\n * Integrates with Alepha's atom system for state management:\n * - Uses `alepha.set(atom, value)` for mutations\n * - Listens to `state:mutate` events to detect changes\n * - Auto-persists changes to database\n * - Syncs across instances via topic\n *\n * @example\n * ```ts\n * class AppConfig {\n * features = $config({\n * name: \"app.features.flags\",\n * schema: t.object({\n * enableBeta: t.boolean(),\n * maxUploadSize: t.number()\n * }),\n * default: { enableBeta: false, maxUploadSize: 10485760 }\n * });\n *\n * async enableBeta() {\n * // Immediate activation\n * await this.features.set({ enableBeta: true, maxUploadSize: 20971520 });\n * }\n *\n * async scheduleBetaRelease() {\n * // Schedule for future activation\n * await this.features.set(\n * { enableBeta: true, maxUploadSize: 20971520 },\n * { activationDate: new Date('2024-03-01') }\n * );\n * }\n * }\n * ```\n */\nexport interface ConfigPrimitiveOptions<T extends TObject> {\n /**\n * Configuration name using dot notation for tree hierarchy.\n * Examples: \"app.features\", \"app.pricing.tiers\", \"system.limits\"\n */\n name?: string;\n\n /**\n * Human-readable description of the configuration.\n */\n description?: string;\n\n /**\n * TypeBox schema defining the configuration structure.\n */\n schema: T;\n\n /**\n * Default value used when no configuration exists in database.\n */\n default: Static<T>;\n}\n\nexport class ConfigPrimitive<T extends TObject> extends Primitive<\n ConfigPrimitiveOptions<T>\n> {\n protected readonly log = $logger();\n protected readonly store = $inject(ConfigStore);\n\n /** Internal atom key for state management */\n protected atomKey!: string;\n\n /** Schema hash for migration detection */\n protected schemaHash!: string;\n\n /** Whether we're currently syncing (to avoid loops) */\n protected syncing = false;\n\n /** Whether initial load has completed */\n protected loaded = false;\n\n /**\n * Configuration name (uses property key if not specified).\n */\n public get name(): string {\n return this.options.name || this.config.propertyKey;\n }\n\n /**\n * The TypeBox schema for this configuration.\n */\n public get schema(): T {\n return this.options.schema;\n }\n\n /**\n * Get the current configuration value.\n */\n public get current(): Static<T> {\n return (\n (this.alepha.store.get(this.atomKey as any) as Static<T>) ??\n this.options.default\n );\n }\n\n /**\n * Get a specific field from the current configuration.\n */\n public get<Key extends keyof Static<T>>(key: Key): Static<T>[Key] {\n return this.current[key];\n }\n\n /**\n * Set a new configuration value.\n *\n * @param value - The new configuration value\n * @param options - Optional settings (activation date, creator info, etc.)\n */\n public async set(\n value: Static<T>,\n options: SetConfigOptions = {},\n ): Promise<void> {\n // Save to database\n await this.store.save(this.name, value, this.schemaHash, {\n activationDate: options.activationDate,\n changeDescription: options.changeDescription,\n tags: options.tags,\n creatorId: options.user?.id,\n creatorName: options.user?.name ?? options.user?.email,\n });\n\n // If immediate activation (no future date), update state\n const now = new Date();\n if (!options.activationDate || options.activationDate <= now) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value);\n } finally {\n this.syncing = false;\n }\n }\n }\n\n /**\n * Subscribe to configuration changes.\n */\n public sub(fn: (curr: Static<T>) => void): () => void {\n return this.alepha.events.on(\"state:mutate\", {\n callback: ({ key, value }) => {\n if (key === this.atomKey) {\n fn(value as Static<T>);\n }\n },\n });\n }\n\n /**\n * Reload configuration from database.\n * Called when scheduled config activates or sync message received.\n */\n public async reload(): Promise<void> {\n const value = await this.store.load<T>(this.name);\n if (value !== null) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value, { skipEvents: true });\n } finally {\n this.syncing = false;\n }\n }\n }\n\n /**\n * Update from sync message (called by ConfigStore).\n * Uses skipEvents to avoid infinite loops.\n */\n public async updateFromSync(content: unknown): Promise<void> {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, content as Static<T>, {\n skipEvents: true,\n });\n } finally {\n this.syncing = false;\n }\n }\n\n /**\n * Get version history for this configuration.\n */\n public async getHistory() {\n return this.store.getHistory(this.name);\n }\n\n /**\n * Rollback to a specific version.\n */\n public async rollback(\n version: number,\n options?: SetConfigOptions,\n ): Promise<void> {\n await this.store.rollback(this.name, version, {\n changeDescription: options?.changeDescription,\n creatorId: options?.user?.id,\n creatorName: options?.user?.name ?? options?.user?.email,\n });\n await this.reload();\n }\n\n /**\n * Hook to load initial value from database on start.\n */\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n await this.loadInitial();\n },\n });\n\n /**\n * Called after primitive creation to initialize.\n */\n protected onInit(): void {\n // Create unique key for state management\n this.atomKey = `config:${this.name}`;\n\n // Calculate schema hash for migration detection\n this.schemaHash = this.calculateSchemaHash();\n\n // Register with store\n this.store.register(this);\n\n // Set initial default using key-based state\n this.alepha.store.set(this.atomKey as any, this.options.default, {\n skipEvents: true,\n });\n\n // Listen for state mutations to detect external changes via alepha.set()\n // Note: state:mutate is not in Hooks interface, so we use events.on() directly\n this.alepha.events.on(\"state:mutate\", {\n caller: this.config.service,\n callback: async ({ key, value, prevValue }) => {\n // Only handle our key\n if (key !== this.atomKey) {\n return;\n }\n\n // Skip if we're syncing (to avoid infinite loop)\n if (this.syncing) {\n return;\n }\n\n // Skip if value hasn't actually changed\n if (JSON.stringify(value) === JSON.stringify(prevValue)) {\n return;\n }\n\n // Auto-save to database when state is mutated via alepha.set()\n this.log.debug(\"Config state mutated, persisting to database\", {\n name: this.name,\n });\n await this.store.save(this.name, value as Static<T>, this.schemaHash);\n },\n });\n }\n\n /**\n * Load initial value from database.\n */\n protected async loadInitial(): Promise<void> {\n if (this.loaded) {\n return;\n }\n\n const value = await this.store.load<T>(this.name);\n\n if (value !== null) {\n this.syncing = true;\n try {\n this.alepha.store.set(this.atomKey as any, value, { skipEvents: true });\n } finally {\n this.syncing = false;\n }\n }\n\n this.loaded = true;\n }\n\n /**\n * Calculate a hash of the schema for migration detection.\n */\n protected calculateSchemaHash(): string {\n const schemaJson = JSON.stringify(this.options.schema);\n // Simple hash - in production you might want a proper hash function\n let hash = 0;\n for (let i = 0; i < schemaJson.length; i++) {\n const char = schemaJson.charCodeAt(i);\n hash = (hash << 5) - hash + char;\n hash = hash & hash; // Convert to 32bit integer\n }\n return hash.toString(16);\n }\n}\n\nexport const $config = <T extends TObject>(\n options: ConfigPrimitiveOptions<T>,\n) => {\n return createPrimitive(ConfigPrimitive<T>, options);\n};\n\n$config[KIND] = ConfigPrimitive;\n\nexport interface SetConfigOptions {\n /**\n * User making the change (for audit trail).\n */\n user?: Pick<UserAccount, \"id\" | \"email\" | \"name\">;\n\n /**\n * When this configuration should become active.\n * Default is immediate (now).\n */\n activationDate?: Date;\n\n /**\n * Description of the change.\n */\n changeDescription?: string;\n\n /**\n * Tags for filtering/categorization.\n */\n tags?: string[];\n}\n","import { $module } from \"alepha\";\nimport { AdminConfigController } from \"./controllers/AdminConfigController.ts\";\nimport { ConfigActivationScheduler } from \"./schedulers/ConfigActivationScheduler.ts\";\nimport { ConfigStore } from \"./services/ConfigStore.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n// Controller exports\nexport * from \"./controllers/AdminConfigController.ts\";\n// Entity exports\nexport * from \"./entities/parameters.ts\";\n// Primitive exports\nexport * from \"./primitives/$config.ts\";\n// Scheduler exports\nexport * from \"./schedulers/ConfigActivationScheduler.ts\";\n// Service exports\nexport * from \"./services/ConfigStore.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides versioned configuration management for Alepha applications.\n *\n * Features:\n * - Type-safe, versioned configuration with `$config` primitive\n * - Schema validation with auto-migration detection\n * - Scheduled activation (FUTURE, NEXT, CURRENT, EXPIRED statuses)\n * - PostgreSQL persistence with full version history\n * - Cross-instance synchronization via topic\n * - Tree view support via dot-notation naming\n * - REST API for configuration management\n * - Automatic activation scheduler\n *\n * @example\n * ```ts\n * import { Alepha } from \"alepha\";\n * import { AlephaApiParameters } from \"alepha/api/parameters\";\n *\n * const alepha = Alepha.create();\n * alepha.with(AlephaApiParameters);\n *\n * // Then use $config in your services:\n * class AppConfig {\n * features = $config({\n * name: \"app.features.flags\",\n * schema: t.object({\n * enableBeta: t.boolean(),\n * maxUploadSize: t.number()\n * }),\n * default: { enableBeta: false, maxUploadSize: 10485760 }\n * });\n * }\n * ```\n *\n * @module alepha.api.parameters\n */\nexport const AlephaApiParameters = $module({\n name: \"alepha.api.parameters\",\n services: [ConfigStore, AdminConfigController, ConfigActivationScheduler],\n});\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
1
  import { $module, t } from "alepha";
2
- import { $entity, pg } from "alepha/orm";
2
+ import { $entity, db } from "alepha/orm";
3
3
 
4
4
  //#region ../../src/api/users/entities/users.ts
5
5
  const DEFAULT_USER_REALM_NAME = "default";
6
6
  const users = $entity({
7
7
  name: "users",
8
8
  schema: t.object({
9
- id: pg.primaryKey(t.uuid()),
10
- version: pg.version(),
11
- createdAt: pg.createdAt(),
12
- updatedAt: pg.updatedAt(),
13
- realm: pg.default(t.text(), DEFAULT_USER_REALM_NAME),
9
+ id: db.primaryKey(t.uuid()),
10
+ version: db.version(),
11
+ createdAt: db.createdAt(),
12
+ updatedAt: db.updatedAt(),
13
+ realm: db.default(t.text(), DEFAULT_USER_REALM_NAME),
14
14
  username: t.optional(t.shortText({
15
15
  minLength: 3,
16
16
  maxLength: 50,
@@ -18,12 +18,12 @@ const users = $entity({
18
18
  })),
19
19
  email: t.optional(t.string({ format: "email" })),
20
20
  phoneNumber: t.optional(t.e164()),
21
- roles: pg.default(t.array(t.string()), []),
21
+ roles: db.default(t.array(t.string()), []),
22
22
  firstName: t.optional(t.string()),
23
23
  lastName: t.optional(t.string()),
24
24
  picture: t.optional(t.string()),
25
- enabled: pg.default(t.boolean(), true),
26
- emailVerified: pg.default(t.boolean(), false)
25
+ enabled: db.default(t.boolean(), true),
26
+ emailVerified: db.default(t.boolean(), false)
27
27
  }),
28
28
  indexes: [
29
29
  {
@@ -46,11 +46,11 @@ const users = $entity({
46
46
  const identities = $entity({
47
47
  name: "identities",
48
48
  schema: t.object({
49
- id: pg.primaryKey(t.uuid()),
50
- version: pg.version(),
51
- createdAt: pg.createdAt(),
52
- updatedAt: pg.updatedAt(),
53
- userId: pg.ref(t.uuid(), () => users.cols.id),
49
+ id: db.primaryKey(t.uuid()),
50
+ version: db.version(),
51
+ createdAt: db.createdAt(),
52
+ updatedAt: db.updatedAt(),
53
+ userId: db.ref(t.uuid(), () => users.cols.id),
54
54
  password: t.optional(t.text()),
55
55
  provider: t.text(),
56
56
  providerUserId: t.optional(t.text()),
@@ -63,12 +63,12 @@ const identities = $entity({
63
63
  const sessions = $entity({
64
64
  name: "sessions",
65
65
  schema: t.object({
66
- id: pg.primaryKey(t.uuid()),
67
- version: pg.version(),
68
- createdAt: pg.createdAt(),
69
- updatedAt: pg.updatedAt(),
66
+ id: db.primaryKey(t.uuid()),
67
+ version: db.version(),
68
+ createdAt: db.createdAt(),
69
+ updatedAt: db.updatedAt(),
70
70
  refreshToken: t.uuid(),
71
- userId: pg.ref(t.uuid(), () => users.cols.id),
71
+ userId: db.ref(t.uuid(), () => users.cols.id),
72
72
  expiresAt: t.datetime(),
73
73
  ip: t.optional(t.text()),
74
74
  userAgent: t.optional(t.object({
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/api/users/entities/users.ts","../../../src/api/users/entities/identities.ts","../../../src/api/users/entities/sessions.ts","../../../src/api/users/schemas/registerSchema.ts","../../../src/api/users/schemas/resetPasswordSchema.ts","../../../src/api/users/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\n\nexport const DEFAULT_USER_REALM_NAME = \"default\";\n\nexport const users = $entity({\n name: \"users\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n version: pg.version(),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n\n realm: pg.default(t.text(), DEFAULT_USER_REALM_NAME),\n\n username: t.optional(\n t.shortText({\n minLength: 3,\n maxLength: 50,\n pattern: \"^[a-zA-Z0-9._-]+$\",\n }),\n ),\n\n email: t.optional(t.string({ format: \"email\" })),\n\n phoneNumber: t.optional(t.e164()),\n\n roles: pg.default(t.array(t.string()), []),\n firstName: t.optional(t.string()),\n lastName: t.optional(t.string()),\n picture: t.optional(t.string()),\n enabled: pg.default(t.boolean(), true),\n\n emailVerified: pg.default(t.boolean(), false),\n }),\n indexes: [\n { columns: [\"realm\", \"username\"], unique: true },\n { columns: [\"realm\", \"email\"], unique: true },\n { columns: [\"realm\", \"phoneNumber\"], unique: true },\n ],\n});\n\nexport type UserEntity = Static<typeof users.schema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\nimport { users } from \"./users.ts\";\n\nexport const identities = $entity({\n name: \"identities\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n version: pg.version(),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n userId: pg.ref(t.uuid(), () => users.cols.id),\n password: t.optional(t.text()),\n provider: t.text(),\n providerUserId: t.optional(t.text()),\n providerData: t.optional(t.json()),\n }),\n});\n\nexport type IdentityEntity = Static<typeof identities.schema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, pg } from \"alepha/orm\";\nimport { users } from \"./users.ts\";\n\nexport const sessions = $entity({\n name: \"sessions\",\n schema: t.object({\n id: pg.primaryKey(t.uuid()),\n version: pg.version(),\n createdAt: pg.createdAt(),\n updatedAt: pg.updatedAt(),\n refreshToken: t.uuid(),\n userId: pg.ref(t.uuid(), () => users.cols.id),\n expiresAt: t.datetime(),\n ip: t.optional(t.text()),\n userAgent: t.optional(\n t.object({\n os: t.text(),\n browser: t.text(),\n device: t.enum([\"MOBILE\", \"DESKTOP\", \"TABLET\"]),\n }),\n ),\n }),\n});\n\nexport type SessionEntity = Static<typeof sessions.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const registerSchema = t.object({\n username: t.string({\n minLength: 3,\n maxLength: 20,\n pattern: /^[a-zA-Z0-9_]+$/,\n description: \"Username for the new account\",\n }),\n email: t.email({\n description: \"Email address for the new account\",\n }),\n password: t.string({\n minLength: 8,\n description: \"Password for the new account\",\n }),\n confirmPassword: t.string({\n minLength: 8,\n description: \"Confirmation of the password\",\n }),\n firstName: t.optional(\n t.string({\n maxLength: 100,\n description: \"User's first name\",\n }),\n ),\n lastName: t.optional(\n t.string({\n maxLength: 100,\n description: \"User's last name\",\n }),\n ),\n});\n\nexport type RegisterInput = Static<typeof registerSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const resetPasswordRequestSchema = t.object({\n email: t.email({\n description: \"Email address to send password reset link\",\n }),\n});\n\nexport const resetPasswordSchema = t.object({\n token: t.string({\n description: \"Password reset token from email\",\n }),\n password: t.string({\n minLength: 8,\n description: \"New password\",\n }),\n confirmPassword: t.string({\n minLength: 8,\n description: \"Confirmation of the new password\",\n }),\n});\n\nexport type ResetPasswordRequest = Static<typeof resetPasswordRequestSchema>;\nexport type ResetPasswordInput = Static<typeof resetPasswordSchema>;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./entities/identities.ts\";\nexport * from \"./entities/sessions.ts\";\nexport * from \"./entities/users.ts\";\nexport * from \"./schemas/registerSchema.ts\";\nexport * from \"./schemas/resetPasswordSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiUsers = $module({\n name: \"alepha.api.users\",\n services: [],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.browser.js","names":[],"sources":["../../../src/api/users/entities/users.ts","../../../src/api/users/entities/identities.ts","../../../src/api/users/entities/sessions.ts","../../../src/api/users/schemas/registerSchema.ts","../../../src/api/users/schemas/resetPasswordSchema.ts","../../../src/api/users/index.browser.ts"],"sourcesContent":["import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const DEFAULT_USER_REALM_NAME = \"default\";\n\nexport const users = $entity({\n name: \"users\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n\n realm: db.default(t.text(), DEFAULT_USER_REALM_NAME),\n\n username: t.optional(\n t.shortText({\n minLength: 3,\n maxLength: 50,\n pattern: \"^[a-zA-Z0-9._-]+$\",\n }),\n ),\n\n email: t.optional(t.string({ format: \"email\" })),\n\n phoneNumber: t.optional(t.e164()),\n\n roles: db.default(t.array(t.string()), []),\n firstName: t.optional(t.string()),\n lastName: t.optional(t.string()),\n picture: t.optional(t.string()),\n enabled: db.default(t.boolean(), true),\n\n emailVerified: db.default(t.boolean(), false),\n }),\n indexes: [\n { columns: [\"realm\", \"username\"], unique: true },\n { columns: [\"realm\", \"email\"], unique: true },\n { columns: [\"realm\", \"phoneNumber\"], unique: true },\n ],\n});\n\nexport type UserEntity = Static<typeof users.schema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\nimport { users } from \"./users.ts\";\n\nexport const identities = $entity({\n name: \"identities\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n userId: db.ref(t.uuid(), () => users.cols.id),\n password: t.optional(t.text()),\n provider: t.text(),\n providerUserId: t.optional(t.text()),\n providerData: t.optional(t.json()),\n }),\n});\n\nexport type IdentityEntity = Static<typeof identities.schema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\nimport { users } from \"./users.ts\";\n\nexport const sessions = $entity({\n name: \"sessions\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n refreshToken: t.uuid(),\n userId: db.ref(t.uuid(), () => users.cols.id),\n expiresAt: t.datetime(),\n ip: t.optional(t.text()),\n userAgent: t.optional(\n t.object({\n os: t.text(),\n browser: t.text(),\n device: t.enum([\"MOBILE\", \"DESKTOP\", \"TABLET\"]),\n }),\n ),\n }),\n});\n\nexport type SessionEntity = Static<typeof sessions.schema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const registerSchema = t.object({\n username: t.string({\n minLength: 3,\n maxLength: 20,\n pattern: /^[a-zA-Z0-9_]+$/,\n description: \"Username for the new account\",\n }),\n email: t.email({\n description: \"Email address for the new account\",\n }),\n password: t.string({\n minLength: 8,\n description: \"Password for the new account\",\n }),\n confirmPassword: t.string({\n minLength: 8,\n description: \"Confirmation of the password\",\n }),\n firstName: t.optional(\n t.string({\n maxLength: 100,\n description: \"User's first name\",\n }),\n ),\n lastName: t.optional(\n t.string({\n maxLength: 100,\n description: \"User's last name\",\n }),\n ),\n});\n\nexport type RegisterInput = Static<typeof registerSchema>;\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const resetPasswordRequestSchema = t.object({\n email: t.email({\n description: \"Email address to send password reset link\",\n }),\n});\n\nexport const resetPasswordSchema = t.object({\n token: t.string({\n description: \"Password reset token from email\",\n }),\n password: t.string({\n minLength: 8,\n description: \"New password\",\n }),\n confirmPassword: t.string({\n minLength: 8,\n description: \"Confirmation of the new password\",\n }),\n});\n\nexport type ResetPasswordRequest = Static<typeof resetPasswordRequestSchema>;\nexport type ResetPasswordInput = Static<typeof resetPasswordSchema>;\n","import { $module } from \"alepha\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./entities/identities.ts\";\nexport * from \"./entities/sessions.ts\";\nexport * from \"./entities/users.ts\";\nexport * from \"./schemas/registerSchema.ts\";\nexport * from \"./schemas/resetPasswordSchema.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaApiUsers = $module({\n name: \"alepha.api.users\",\n services: [],\n});\n"],"mappings":"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"}