alepha 0.15.0 → 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (551) hide show
  1. package/README.md +43 -98
  2. package/dist/api/audits/index.d.ts +630 -653
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +12 -35
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +365 -358
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +12 -5
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +255 -248
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/jobs/index.js +10 -3
  13. package/dist/api/jobs/index.js.map +1 -1
  14. package/dist/api/keys/index.d.ts +413 -0
  15. package/dist/api/keys/index.d.ts.map +1 -0
  16. package/dist/api/keys/index.js +476 -0
  17. package/dist/api/keys/index.js.map +1 -0
  18. package/dist/api/notifications/index.browser.js +4 -4
  19. package/dist/api/notifications/index.browser.js.map +1 -1
  20. package/dist/api/notifications/index.d.ts +84 -78
  21. package/dist/api/notifications/index.d.ts.map +1 -1
  22. package/dist/api/notifications/index.js +14 -8
  23. package/dist/api/notifications/index.js.map +1 -1
  24. package/dist/api/parameters/index.d.ts +528 -535
  25. package/dist/api/parameters/index.d.ts.map +1 -1
  26. package/dist/api/parameters/index.js +30 -37
  27. package/dist/api/parameters/index.js.map +1 -1
  28. package/dist/api/users/index.d.ts +1221 -910
  29. package/dist/api/users/index.d.ts.map +1 -1
  30. package/dist/api/users/index.js +2556 -248
  31. package/dist/api/users/index.js.map +1 -1
  32. package/dist/api/verifications/index.d.ts +142 -136
  33. package/dist/api/verifications/index.d.ts.map +1 -1
  34. package/dist/api/verifications/index.js +12 -4
  35. package/dist/api/verifications/index.js.map +1 -1
  36. package/dist/batch/index.d.ts +142 -162
  37. package/dist/batch/index.d.ts.map +1 -1
  38. package/dist/batch/index.js +31 -44
  39. package/dist/batch/index.js.map +1 -1
  40. package/dist/bucket/index.d.ts +595 -171
  41. package/dist/bucket/index.d.ts.map +1 -1
  42. package/dist/bucket/index.js +1856 -12
  43. package/dist/bucket/index.js.map +1 -1
  44. package/dist/cache/core/index.d.ts +225 -53
  45. package/dist/cache/core/index.d.ts.map +1 -1
  46. package/dist/cache/core/index.js +213 -7
  47. package/dist/cache/core/index.js.map +1 -1
  48. package/dist/cache/redis/index.d.ts +1 -0
  49. package/dist/cache/redis/index.d.ts.map +1 -1
  50. package/dist/cache/redis/index.js +6 -2
  51. package/dist/cache/redis/index.js.map +1 -1
  52. package/dist/cli/index.d.ts +834 -226
  53. package/dist/cli/index.d.ts.map +1 -1
  54. package/dist/cli/index.js +2872 -417
  55. package/dist/cli/index.js.map +1 -1
  56. package/dist/command/index.d.ts +458 -310
  57. package/dist/command/index.d.ts.map +1 -1
  58. package/dist/command/index.js +2011 -76
  59. package/dist/command/index.js.map +1 -1
  60. package/dist/core/index.browser.js +309 -97
  61. package/dist/core/index.browser.js.map +1 -1
  62. package/dist/core/index.d.ts +796 -701
  63. package/dist/core/index.d.ts.map +1 -1
  64. package/dist/core/index.js +329 -97
  65. package/dist/core/index.js.map +1 -1
  66. package/dist/core/index.native.js +309 -97
  67. package/dist/core/index.native.js.map +1 -1
  68. package/dist/datetime/index.d.ts +59 -44
  69. package/dist/datetime/index.d.ts.map +1 -1
  70. package/dist/datetime/index.js +15 -0
  71. package/dist/datetime/index.js.map +1 -1
  72. package/dist/email/index.d.ts +314 -19
  73. package/dist/email/index.d.ts.map +1 -1
  74. package/dist/email/index.js +1852 -7
  75. package/dist/email/index.js.map +1 -1
  76. package/dist/fake/index.d.ts +5500 -5418
  77. package/dist/fake/index.d.ts.map +1 -1
  78. package/dist/fake/index.js +113 -42
  79. package/dist/fake/index.js.map +1 -1
  80. package/dist/lock/core/index.d.ts +219 -212
  81. package/dist/lock/core/index.d.ts.map +1 -1
  82. package/dist/lock/core/index.js +11 -4
  83. package/dist/lock/core/index.js.map +1 -1
  84. package/dist/lock/redis/index.d.ts.map +1 -1
  85. package/dist/logger/index.d.ts +41 -90
  86. package/dist/logger/index.d.ts.map +1 -1
  87. package/dist/logger/index.js +15 -68
  88. package/dist/logger/index.js.map +1 -1
  89. package/dist/mcp/index.d.ts +228 -230
  90. package/dist/mcp/index.d.ts.map +1 -1
  91. package/dist/mcp/index.js +32 -31
  92. package/dist/mcp/index.js.map +1 -1
  93. package/dist/orm/index.browser.js +12 -12
  94. package/dist/orm/index.browser.js.map +1 -1
  95. package/dist/orm/index.bun.js +90 -80
  96. package/dist/orm/index.bun.js.map +1 -1
  97. package/dist/orm/index.d.ts +1434 -1459
  98. package/dist/orm/index.d.ts.map +1 -1
  99. package/dist/orm/index.js +112 -130
  100. package/dist/orm/index.js.map +1 -1
  101. package/dist/queue/core/index.d.ts +262 -254
  102. package/dist/queue/core/index.d.ts.map +1 -1
  103. package/dist/queue/core/index.js +14 -6
  104. package/dist/queue/core/index.js.map +1 -1
  105. package/dist/queue/redis/index.d.ts.map +1 -1
  106. package/dist/react/auth/index.browser.js +108 -0
  107. package/dist/react/auth/index.browser.js.map +1 -0
  108. package/dist/react/auth/index.d.ts +100 -0
  109. package/dist/react/auth/index.d.ts.map +1 -0
  110. package/dist/react/auth/index.js +145 -0
  111. package/dist/react/auth/index.js.map +1 -0
  112. package/dist/react/core/index.d.ts +469 -0
  113. package/dist/react/core/index.d.ts.map +1 -0
  114. package/dist/react/core/index.js +464 -0
  115. package/dist/react/core/index.js.map +1 -0
  116. package/dist/react/form/index.d.ts +232 -0
  117. package/dist/react/form/index.d.ts.map +1 -0
  118. package/dist/react/form/index.js +432 -0
  119. package/dist/react/form/index.js.map +1 -0
  120. package/dist/react/head/index.browser.js +423 -0
  121. package/dist/react/head/index.browser.js.map +1 -0
  122. package/dist/react/head/index.d.ts +288 -0
  123. package/dist/react/head/index.d.ts.map +1 -0
  124. package/dist/react/head/index.js +465 -0
  125. package/dist/react/head/index.js.map +1 -0
  126. package/dist/react/i18n/index.d.ts +175 -0
  127. package/dist/react/i18n/index.d.ts.map +1 -0
  128. package/dist/react/i18n/index.js +224 -0
  129. package/dist/react/i18n/index.js.map +1 -0
  130. package/dist/react/router/index.browser.js +1980 -0
  131. package/dist/react/router/index.browser.js.map +1 -0
  132. package/dist/react/router/index.d.ts +2068 -0
  133. package/dist/react/router/index.d.ts.map +1 -0
  134. package/dist/react/router/index.js +4932 -0
  135. package/dist/react/router/index.js.map +1 -0
  136. package/dist/react/websocket/index.d.ts +117 -0
  137. package/dist/react/websocket/index.d.ts.map +1 -0
  138. package/dist/react/websocket/index.js +107 -0
  139. package/dist/react/websocket/index.js.map +1 -0
  140. package/dist/redis/index.bun.js +4 -0
  141. package/dist/redis/index.bun.js.map +1 -1
  142. package/dist/redis/index.d.ts +127 -130
  143. package/dist/redis/index.d.ts.map +1 -1
  144. package/dist/redis/index.js +16 -25
  145. package/dist/redis/index.js.map +1 -1
  146. package/dist/retry/index.d.ts +80 -71
  147. package/dist/retry/index.d.ts.map +1 -1
  148. package/dist/retry/index.js +11 -2
  149. package/dist/retry/index.js.map +1 -1
  150. package/dist/router/index.d.ts +6 -6
  151. package/dist/router/index.d.ts.map +1 -1
  152. package/dist/scheduler/index.d.ts +119 -28
  153. package/dist/scheduler/index.d.ts.map +1 -1
  154. package/dist/scheduler/index.js +404 -3
  155. package/dist/scheduler/index.js.map +1 -1
  156. package/dist/security/index.d.ts +642 -228
  157. package/dist/security/index.d.ts.map +1 -1
  158. package/dist/security/index.js +1579 -37
  159. package/dist/security/index.js.map +1 -1
  160. package/dist/server/auth/index.d.ts +1141 -111
  161. package/dist/server/auth/index.d.ts.map +1 -1
  162. package/dist/server/auth/index.js +1261 -25
  163. package/dist/server/auth/index.js.map +1 -1
  164. package/dist/server/cache/index.d.ts +63 -78
  165. package/dist/server/cache/index.d.ts.map +1 -1
  166. package/dist/server/cache/index.js +7 -22
  167. package/dist/server/cache/index.js.map +1 -1
  168. package/dist/server/compress/index.d.ts +13 -5
  169. package/dist/server/compress/index.d.ts.map +1 -1
  170. package/dist/server/compress/index.js +10 -2
  171. package/dist/server/compress/index.js.map +1 -1
  172. package/dist/server/cookies/index.d.ts +46 -22
  173. package/dist/server/cookies/index.d.ts.map +1 -1
  174. package/dist/server/cookies/index.js +7 -5
  175. package/dist/server/cookies/index.js.map +1 -1
  176. package/dist/server/core/index.d.ts +307 -196
  177. package/dist/server/core/index.d.ts.map +1 -1
  178. package/dist/server/core/index.js +271 -38
  179. package/dist/server/core/index.js.map +1 -1
  180. package/dist/server/cors/index.d.ts +24 -34
  181. package/dist/server/cors/index.d.ts.map +1 -1
  182. package/dist/server/cors/index.js +7 -21
  183. package/dist/server/cors/index.js.map +1 -1
  184. package/dist/server/health/index.d.ts +25 -19
  185. package/dist/server/health/index.d.ts.map +1 -1
  186. package/dist/server/health/index.js +8 -2
  187. package/dist/server/health/index.js.map +1 -1
  188. package/dist/server/helmet/index.d.ts +13 -5
  189. package/dist/server/helmet/index.d.ts.map +1 -1
  190. package/dist/server/helmet/index.js +11 -3
  191. package/dist/server/helmet/index.js.map +1 -1
  192. package/dist/server/links/index.browser.js +9 -1
  193. package/dist/server/links/index.browser.js.map +1 -1
  194. package/dist/server/links/index.d.ts +133 -128
  195. package/dist/server/links/index.d.ts.map +1 -1
  196. package/dist/server/links/index.js +24 -11
  197. package/dist/server/links/index.js.map +1 -1
  198. package/dist/server/metrics/index.d.ts +524 -4
  199. package/dist/server/metrics/index.d.ts.map +1 -1
  200. package/dist/server/metrics/index.js +4472 -7
  201. package/dist/server/metrics/index.js.map +1 -1
  202. package/dist/server/multipart/index.d.ts +15 -9
  203. package/dist/server/multipart/index.d.ts.map +1 -1
  204. package/dist/server/multipart/index.js +9 -3
  205. package/dist/server/multipart/index.js.map +1 -1
  206. package/dist/server/proxy/index.d.ts +110 -104
  207. package/dist/server/proxy/index.d.ts.map +1 -1
  208. package/dist/server/proxy/index.js +8 -2
  209. package/dist/server/proxy/index.js.map +1 -1
  210. package/dist/server/rate-limit/index.d.ts +46 -51
  211. package/dist/server/rate-limit/index.d.ts.map +1 -1
  212. package/dist/server/rate-limit/index.js +18 -55
  213. package/dist/server/rate-limit/index.js.map +1 -1
  214. package/dist/server/static/index.d.ts +181 -48
  215. package/dist/server/static/index.d.ts.map +1 -1
  216. package/dist/server/static/index.js +1848 -5
  217. package/dist/server/static/index.js.map +1 -1
  218. package/dist/server/swagger/index.d.ts +348 -53
  219. package/dist/server/swagger/index.d.ts.map +1 -1
  220. package/dist/server/swagger/index.js +1849 -6
  221. package/dist/server/swagger/index.js.map +1 -1
  222. package/dist/sms/index.d.ts +312 -18
  223. package/dist/sms/index.d.ts.map +1 -1
  224. package/dist/sms/index.js +1854 -10
  225. package/dist/sms/index.js.map +1 -1
  226. package/dist/system/index.browser.js +496 -0
  227. package/dist/system/index.browser.js.map +1 -0
  228. package/dist/system/index.d.ts +1158 -0
  229. package/dist/system/index.d.ts.map +1 -0
  230. package/dist/{file → system}/index.js +412 -20
  231. package/dist/system/index.js.map +1 -0
  232. package/dist/thread/index.d.ts +82 -73
  233. package/dist/thread/index.d.ts.map +1 -1
  234. package/dist/thread/index.js +13 -4
  235. package/dist/thread/index.js.map +1 -1
  236. package/dist/topic/core/index.d.ts +330 -323
  237. package/dist/topic/core/index.d.ts.map +1 -1
  238. package/dist/topic/core/index.js +12 -5
  239. package/dist/topic/core/index.js.map +1 -1
  240. package/dist/topic/redis/index.d.ts +6 -6
  241. package/dist/topic/redis/index.d.ts.map +1 -1
  242. package/dist/vite/index.d.ts +163 -5825
  243. package/dist/vite/index.d.ts.map +1 -1
  244. package/dist/vite/index.js +130 -477
  245. package/dist/vite/index.js.map +1 -1
  246. package/dist/websocket/index.browser.js +3 -3
  247. package/dist/websocket/index.browser.js.map +1 -1
  248. package/dist/websocket/index.d.ts +287 -283
  249. package/dist/websocket/index.d.ts.map +1 -1
  250. package/dist/websocket/index.js +15 -11
  251. package/dist/websocket/index.js.map +1 -1
  252. package/package.json +86 -17
  253. package/src/api/audits/index.ts +10 -33
  254. package/src/api/files/__tests__/$bucket.spec.ts +1 -1
  255. package/src/api/files/controllers/AdminFileStatsController.spec.ts +1 -1
  256. package/src/api/files/controllers/FileController.spec.ts +1 -1
  257. package/src/api/files/index.ts +10 -3
  258. package/src/api/files/jobs/FileJobs.spec.ts +1 -1
  259. package/src/api/files/services/FileService.spec.ts +1 -1
  260. package/src/api/jobs/index.ts +10 -3
  261. package/src/api/keys/controllers/AdminApiKeyController.ts +75 -0
  262. package/src/api/keys/controllers/ApiKeyController.ts +103 -0
  263. package/src/api/keys/entities/apiKeyEntity.ts +41 -0
  264. package/src/api/keys/index.ts +49 -0
  265. package/src/api/keys/schemas/adminApiKeyQuerySchema.ts +7 -0
  266. package/src/api/keys/schemas/adminApiKeyResourceSchema.ts +17 -0
  267. package/src/api/keys/schemas/createApiKeyBodySchema.ts +7 -0
  268. package/src/api/keys/schemas/createApiKeyResponseSchema.ts +11 -0
  269. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +15 -0
  270. package/src/api/keys/schemas/revokeApiKeyParamsSchema.ts +5 -0
  271. package/src/api/keys/schemas/revokeApiKeyResponseSchema.ts +5 -0
  272. package/src/api/keys/services/ApiKeyService.spec.ts +553 -0
  273. package/src/api/keys/services/ApiKeyService.ts +306 -0
  274. package/src/api/logs/TODO.md +52 -0
  275. package/src/api/notifications/index.ts +10 -4
  276. package/src/api/parameters/index.ts +9 -30
  277. package/src/api/parameters/primitives/$config.ts +12 -4
  278. package/src/api/parameters/services/ConfigStore.ts +9 -3
  279. package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1035 -0
  280. package/src/api/users/__tests__/ApiKeys.spec.ts +401 -0
  281. package/src/api/users/index.ts +14 -3
  282. package/src/api/users/primitives/$realm.ts +33 -5
  283. package/src/api/users/providers/RealmProvider.ts +1 -12
  284. package/src/api/users/services/SessionService.ts +1 -11
  285. package/src/api/verifications/controllers/VerificationController.ts +2 -0
  286. package/src/api/verifications/index.ts +10 -4
  287. package/src/batch/index.ts +9 -36
  288. package/src/batch/primitives/$batch.ts +0 -8
  289. package/src/batch/providers/BatchProvider.ts +29 -2
  290. package/src/bucket/__tests__/shared.ts +1 -1
  291. package/src/bucket/index.ts +13 -6
  292. package/src/bucket/primitives/$bucket.ts +1 -1
  293. package/src/bucket/providers/LocalFileStorageProvider.ts +1 -1
  294. package/src/bucket/providers/MemoryFileStorageProvider.ts +1 -1
  295. package/src/cache/core/__tests__/shared.ts +30 -0
  296. package/src/cache/core/index.ts +11 -6
  297. package/src/cache/core/primitives/$cache.spec.ts +5 -0
  298. package/src/cache/core/providers/CacheProvider.ts +17 -0
  299. package/src/cache/core/providers/MemoryCacheProvider.ts +300 -1
  300. package/src/cache/redis/__tests__/cache-redis.spec.ts +5 -0
  301. package/src/cache/redis/providers/RedisCacheProvider.ts +9 -0
  302. package/src/cli/apps/AlephaCli.ts +3 -16
  303. package/src/cli/apps/AlephaPackageBuilderCli.ts +10 -2
  304. package/src/cli/atoms/appEntryOptions.ts +13 -0
  305. package/src/cli/atoms/buildOptions.ts +1 -1
  306. package/src/cli/atoms/changelogOptions.ts +1 -1
  307. package/src/cli/commands/build.ts +64 -52
  308. package/src/cli/commands/db.ts +17 -11
  309. package/src/cli/commands/deploy.ts +1 -1
  310. package/src/cli/commands/dev.ts +13 -49
  311. package/src/cli/commands/gen/env.ts +6 -3
  312. package/src/cli/commands/gen/openapi.ts +5 -2
  313. package/src/cli/commands/init.spec.ts +544 -0
  314. package/src/cli/commands/init.ts +101 -58
  315. package/src/cli/commands/lint.ts +8 -2
  316. package/src/cli/commands/typecheck.ts +11 -0
  317. package/src/cli/defineConfig.ts +9 -0
  318. package/src/cli/index.ts +2 -1
  319. package/src/cli/providers/AppEntryProvider.ts +131 -0
  320. package/src/cli/providers/ViteBuildProvider.ts +40 -0
  321. package/src/cli/providers/ViteDevServerProvider.ts +378 -0
  322. package/src/cli/services/AlephaCliUtils.ts +39 -93
  323. package/src/cli/services/PackageManagerUtils.ts +140 -17
  324. package/src/cli/services/ProjectScaffolder.ts +169 -101
  325. package/src/cli/services/ViteUtils.ts +82 -0
  326. package/src/cli/{assets/claudeMd.ts → templates/agentMd.ts} +41 -28
  327. package/src/cli/{assets → templates}/apiHelloControllerTs.ts +2 -1
  328. package/src/cli/{assets → templates}/biomeJson.ts +2 -1
  329. package/src/cli/{assets → templates}/dummySpecTs.ts +2 -1
  330. package/src/cli/{assets → templates}/editorconfig.ts +2 -1
  331. package/src/cli/templates/gitignore.ts +39 -0
  332. package/src/cli/{assets → templates}/mainBrowserTs.ts +2 -1
  333. package/src/cli/templates/mainCss.ts +33 -0
  334. package/src/cli/templates/mainServerTs.ts +33 -0
  335. package/src/cli/{assets → templates}/tsconfigJson.ts +2 -1
  336. package/src/cli/templates/webAppRouterTs.ts +50 -0
  337. package/src/cli/templates/webHelloComponentTsx.ts +20 -0
  338. package/src/command/helpers/Runner.spec.ts +4 -0
  339. package/src/command/helpers/Runner.ts +3 -21
  340. package/src/command/index.ts +12 -4
  341. package/src/command/providers/CliProvider.spec.ts +1067 -0
  342. package/src/command/providers/CliProvider.ts +203 -40
  343. package/src/core/Alepha.ts +3 -9
  344. package/src/core/__tests__/Alepha-start.spec.ts +4 -4
  345. package/src/core/helpers/jsonSchemaToTypeBox.spec.ts +771 -0
  346. package/src/core/helpers/jsonSchemaToTypeBox.ts +62 -10
  347. package/src/core/index.shared.ts +1 -0
  348. package/src/core/index.ts +20 -0
  349. package/src/core/primitives/$module.ts +12 -0
  350. package/src/core/providers/EventManager.spec.ts +0 -71
  351. package/src/core/providers/EventManager.ts +3 -15
  352. package/src/core/providers/Json.ts +2 -14
  353. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +257 -0
  354. package/src/core/providers/KeylessJsonSchemaCodec.ts +396 -14
  355. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  356. package/src/datetime/index.ts +15 -0
  357. package/src/email/index.ts +10 -5
  358. package/src/email/providers/LocalEmailProvider.spec.ts +1 -1
  359. package/src/email/providers/LocalEmailProvider.ts +1 -1
  360. package/src/fake/__tests__/keyName.example.ts +1 -1
  361. package/src/fake/__tests__/keyName.spec.ts +5 -5
  362. package/src/fake/index.ts +9 -6
  363. package/src/fake/providers/FakeProvider.spec.ts +258 -40
  364. package/src/fake/providers/FakeProvider.ts +133 -19
  365. package/src/lock/core/index.ts +11 -4
  366. package/src/logger/index.ts +17 -66
  367. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  368. package/src/mcp/errors/McpError.ts +30 -0
  369. package/src/mcp/index.ts +13 -27
  370. package/src/mcp/transports/SseMcpTransport.ts +6 -7
  371. package/src/orm/__tests__/PostgresProvider.spec.ts +2 -2
  372. package/src/orm/index.browser.ts +2 -2
  373. package/src/orm/index.bun.ts +4 -2
  374. package/src/orm/index.ts +21 -47
  375. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  376. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -0
  377. package/src/orm/services/Repository.ts +18 -3
  378. package/src/queue/core/index.ts +14 -6
  379. package/src/react/auth/__tests__/$auth.spec.ts +202 -0
  380. package/src/react/auth/hooks/useAuth.ts +32 -0
  381. package/src/react/auth/index.browser.ts +13 -0
  382. package/src/react/auth/index.shared.ts +2 -0
  383. package/src/react/auth/index.ts +48 -0
  384. package/src/react/auth/providers/ReactAuthProvider.ts +16 -0
  385. package/src/react/auth/services/ReactAuth.ts +135 -0
  386. package/src/react/core/__tests__/Router.spec.tsx +169 -0
  387. package/src/react/core/components/ClientOnly.tsx +49 -0
  388. package/src/react/core/components/ErrorBoundary.tsx +73 -0
  389. package/src/react/core/contexts/AlephaContext.ts +7 -0
  390. package/src/react/core/contexts/AlephaProvider.tsx +42 -0
  391. package/src/react/core/hooks/useAction.browser.spec.tsx +569 -0
  392. package/src/react/core/hooks/useAction.ts +480 -0
  393. package/src/react/core/hooks/useAlepha.ts +26 -0
  394. package/src/react/core/hooks/useClient.ts +17 -0
  395. package/src/react/core/hooks/useEvents.ts +51 -0
  396. package/src/react/core/hooks/useInject.ts +12 -0
  397. package/src/react/core/hooks/useStore.ts +52 -0
  398. package/src/react/core/index.ts +90 -0
  399. package/src/react/form/components/FormState.tsx +17 -0
  400. package/src/react/form/errors/FormValidationError.ts +18 -0
  401. package/src/react/form/hooks/useForm.browser.spec.tsx +366 -0
  402. package/src/react/form/hooks/useForm.ts +47 -0
  403. package/src/react/form/hooks/useFormState.ts +130 -0
  404. package/src/react/form/index.ts +44 -0
  405. package/src/react/form/services/FormModel.ts +614 -0
  406. package/src/react/head/helpers/SeoExpander.spec.ts +203 -0
  407. package/src/react/head/helpers/SeoExpander.ts +142 -0
  408. package/src/react/head/hooks/useHead.spec.tsx +288 -0
  409. package/src/react/head/hooks/useHead.ts +62 -0
  410. package/src/react/head/index.browser.ts +26 -0
  411. package/src/react/head/index.ts +44 -0
  412. package/src/react/head/interfaces/Head.ts +105 -0
  413. package/src/react/head/primitives/$head.ts +25 -0
  414. package/src/react/head/providers/BrowserHeadProvider.browser.spec.ts +196 -0
  415. package/src/react/head/providers/BrowserHeadProvider.ts +212 -0
  416. package/src/react/head/providers/HeadProvider.ts +168 -0
  417. package/src/react/head/providers/ServerHeadProvider.ts +31 -0
  418. package/src/react/i18n/__tests__/integration.spec.tsx +239 -0
  419. package/src/react/i18n/components/Localize.spec.tsx +357 -0
  420. package/src/react/i18n/components/Localize.tsx +35 -0
  421. package/src/react/i18n/hooks/useI18n.browser.spec.tsx +438 -0
  422. package/src/react/i18n/hooks/useI18n.ts +18 -0
  423. package/src/react/i18n/index.ts +41 -0
  424. package/src/react/i18n/primitives/$dictionary.ts +69 -0
  425. package/src/react/i18n/providers/I18nProvider.spec.ts +389 -0
  426. package/src/react/i18n/providers/I18nProvider.ts +278 -0
  427. package/src/react/router/__tests__/page-head-browser.browser.spec.ts +95 -0
  428. package/src/react/router/__tests__/page-head.spec.ts +48 -0
  429. package/src/react/router/__tests__/seo-head.spec.ts +125 -0
  430. package/src/react/router/atoms/ssrManifestAtom.ts +58 -0
  431. package/src/react/router/components/ErrorViewer.tsx +872 -0
  432. package/src/react/router/components/Link.tsx +23 -0
  433. package/src/react/router/components/NestedView.tsx +223 -0
  434. package/src/react/router/components/NotFound.tsx +30 -0
  435. package/src/react/router/constants/PAGE_PRELOAD_KEY.ts +6 -0
  436. package/src/react/router/contexts/RouterLayerContext.ts +12 -0
  437. package/src/react/router/errors/Redirection.ts +28 -0
  438. package/src/react/router/hooks/useActive.ts +52 -0
  439. package/src/react/router/hooks/useQueryParams.ts +63 -0
  440. package/src/react/router/hooks/useRouter.ts +20 -0
  441. package/src/react/router/hooks/useRouterState.ts +11 -0
  442. package/src/react/router/index.browser.ts +45 -0
  443. package/src/react/router/index.shared.ts +19 -0
  444. package/src/react/router/index.ts +142 -0
  445. package/src/react/router/primitives/$page.browser.spec.tsx +851 -0
  446. package/src/react/router/primitives/$page.spec.tsx +708 -0
  447. package/src/react/router/primitives/$page.ts +497 -0
  448. package/src/react/router/providers/ReactBrowserProvider.ts +309 -0
  449. package/src/react/router/providers/ReactBrowserRendererProvider.ts +25 -0
  450. package/src/react/router/providers/ReactBrowserRouterProvider.ts +168 -0
  451. package/src/react/router/providers/ReactPageProvider.ts +726 -0
  452. package/src/react/router/providers/ReactServerProvider.spec.tsx +316 -0
  453. package/src/react/router/providers/ReactServerProvider.ts +558 -0
  454. package/src/react/router/providers/ReactServerTemplateProvider.ts +979 -0
  455. package/src/react/router/providers/SSRManifestProvider.ts +334 -0
  456. package/src/react/router/services/ReactPageServerService.ts +48 -0
  457. package/src/react/router/services/ReactPageService.ts +27 -0
  458. package/src/react/router/services/ReactRouter.ts +262 -0
  459. package/src/react/websocket/hooks/useRoom.tsx +242 -0
  460. package/src/react/websocket/index.ts +7 -0
  461. package/src/redis/__tests__/redis.spec.ts +13 -0
  462. package/src/redis/index.ts +9 -25
  463. package/src/redis/providers/BunRedisProvider.ts +9 -0
  464. package/src/redis/providers/NodeRedisProvider.ts +8 -0
  465. package/src/redis/providers/RedisProvider.ts +16 -0
  466. package/src/retry/index.ts +11 -2
  467. package/src/router/index.ts +15 -0
  468. package/src/scheduler/index.ts +11 -2
  469. package/src/security/__tests__/BasicAuth.spec.ts +2 -0
  470. package/src/security/__tests__/ServerSecurityProvider.spec.ts +13 -5
  471. package/src/security/index.ts +15 -10
  472. package/src/security/interfaces/IssuerResolver.ts +27 -0
  473. package/src/security/primitives/$issuer.ts +55 -0
  474. package/src/security/providers/SecurityProvider.ts +179 -0
  475. package/src/security/providers/ServerBasicAuthProvider.ts +6 -2
  476. package/src/security/providers/ServerSecurityProvider.ts +36 -22
  477. package/src/server/auth/index.ts +12 -7
  478. package/src/server/cache/index.ts +7 -22
  479. package/src/server/compress/index.ts +10 -2
  480. package/src/server/cookies/index.ts +7 -5
  481. package/src/server/cookies/primitives/$cookie.ts +33 -11
  482. package/src/server/core/index.ts +17 -7
  483. package/src/server/core/interfaces/ServerRequest.ts +83 -1
  484. package/src/server/core/primitives/$action.spec.ts +1 -1
  485. package/src/server/core/primitives/$action.ts +8 -3
  486. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  487. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  488. package/src/server/core/providers/NodeHttpServerProvider.ts +77 -22
  489. package/src/server/core/providers/ServerLoggerProvider.ts +2 -2
  490. package/src/server/core/providers/ServerProvider.ts +9 -12
  491. package/src/server/core/services/ServerRequestParser.spec.ts +520 -0
  492. package/src/server/core/services/ServerRequestParser.ts +306 -13
  493. package/src/server/cors/index.ts +7 -21
  494. package/src/server/cors/primitives/$cors.ts +6 -2
  495. package/src/server/health/index.ts +8 -2
  496. package/src/server/helmet/index.ts +11 -3
  497. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  498. package/src/server/links/index.browser.ts +2 -0
  499. package/src/server/links/index.ts +13 -6
  500. package/src/server/metrics/index.ts +10 -3
  501. package/src/server/multipart/index.ts +9 -3
  502. package/src/server/proxy/index.ts +8 -2
  503. package/src/server/rate-limit/index.ts +21 -25
  504. package/src/server/rate-limit/primitives/$rateLimit.ts +6 -2
  505. package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +38 -14
  506. package/src/server/rate-limit/providers/ServerRateLimitProvider.ts +22 -56
  507. package/src/server/static/index.ts +8 -2
  508. package/src/server/static/providers/ServerStaticProvider.ts +1 -1
  509. package/src/server/swagger/index.ts +9 -4
  510. package/src/server/swagger/providers/ServerSwaggerProvider.ts +1 -1
  511. package/src/sms/index.ts +9 -5
  512. package/src/sms/providers/LocalSmsProvider.spec.ts +1 -1
  513. package/src/sms/providers/LocalSmsProvider.ts +1 -1
  514. package/src/system/index.browser.ts +11 -0
  515. package/src/system/index.ts +62 -0
  516. package/src/{file → system}/providers/FileSystemProvider.ts +16 -0
  517. package/src/{file → system}/providers/MemoryFileSystemProvider.ts +116 -3
  518. package/src/system/providers/MemoryShellProvider.ts +164 -0
  519. package/src/{file → system}/providers/NodeFileSystemProvider.spec.ts +2 -2
  520. package/src/{file → system}/providers/NodeFileSystemProvider.ts +36 -0
  521. package/src/system/providers/NodeShellProvider.ts +184 -0
  522. package/src/system/providers/ShellProvider.ts +74 -0
  523. package/src/{file → system}/services/FileDetector.spec.ts +2 -2
  524. package/src/thread/index.ts +11 -2
  525. package/src/topic/core/index.ts +12 -5
  526. package/src/vite/index.ts +3 -2
  527. package/src/vite/tasks/buildClient.ts +2 -8
  528. package/src/vite/tasks/buildServer.ts +84 -21
  529. package/src/vite/tasks/copyAssets.ts +5 -4
  530. package/src/vite/tasks/generateSitemap.ts +64 -23
  531. package/src/vite/tasks/index.ts +0 -2
  532. package/src/vite/tasks/prerenderPages.ts +49 -24
  533. package/src/websocket/index.ts +12 -8
  534. package/dist/file/index.d.ts +0 -839
  535. package/dist/file/index.d.ts.map +0 -1
  536. package/dist/file/index.js.map +0 -1
  537. package/src/cli/assets/indexHtml.ts +0 -15
  538. package/src/cli/assets/mainServerTs.ts +0 -24
  539. package/src/cli/assets/webAppRouterTs.ts +0 -15
  540. package/src/cli/assets/webHelloComponentTsx.ts +0 -16
  541. package/src/cli/commands/format.ts +0 -23
  542. package/src/file/index.ts +0 -43
  543. package/src/vite/helpers/boot.ts +0 -117
  544. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  545. package/src/vite/tasks/devServer.ts +0 -71
  546. package/src/vite/tasks/runAlepha.ts +0 -270
  547. /package/dist/orm/{chunk-DtkW-qnP.js → chunk-DH6iiROE.js} +0 -0
  548. /package/src/cli/{assets → templates}/apiIndexTs.ts +0 -0
  549. /package/src/cli/{assets → templates}/webIndexTs.ts +0 -0
  550. /package/src/{file → system}/errors/FileError.ts +0 -0
  551. /package/src/{file → system}/services/FileDetector.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["envSchema"],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/providers/NodeRedisProvider.ts","../../src/redis/providers/NodeRedisSubscriberProvider.ts","../../src/redis/index.ts"],"sourcesContent":["/**\n * Abstract Redis provider interface.\n *\n * This abstract class defines the common interface for Redis operations.\n * Implementations include:\n * - {@link NodeRedisProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const redis = alepha.inject(RedisProvider);\n *\n * // Use common operations\n * await redis.set(\"key\", \"value\");\n * const value = await redis.get(\"key\");\n * ```\n */\nexport abstract class RedisProvider {\n /**\n * Whether the Redis client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the connection to the Redis server.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Get the value of a key.\n *\n * @param key The key to get.\n * @returns The value as a Buffer, or undefined if the key does not exist.\n */\n public abstract get(key: string): Promise<Buffer | undefined>;\n\n /**\n * Set the value of a key.\n *\n * @param key The key to set.\n * @param value The value to set (Buffer or string).\n * @param options Optional set options (EX, PX, NX, XX, etc.).\n * @returns The value as a Buffer.\n */\n public abstract set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer>;\n\n /**\n * Check if a key exists.\n *\n * @param key The key to check.\n * @returns True if the key exists.\n */\n public abstract has(key: string): Promise<boolean>;\n\n /**\n * Get all keys matching a pattern.\n *\n * @param pattern The glob-style pattern to match.\n * @returns Array of matching key names.\n */\n public abstract keys(pattern: string): Promise<string[]>;\n\n /**\n * Delete one or more keys.\n *\n * @param keys The keys to delete.\n */\n public abstract del(keys: string[]): Promise<void>;\n\n // ---------------------------------------------------------\n // Queue operations (for alepha/queue-redis)\n // ---------------------------------------------------------\n\n /**\n * Push a value to the left (head) of a list.\n *\n * @param key The list key.\n * @param value The value to push.\n */\n public abstract lpush(key: string, value: string): Promise<void>;\n\n /**\n * Pop a value from the right (tail) of a list.\n *\n * @param key The list key.\n * @returns The value, or undefined if the list is empty.\n */\n public abstract rpop(key: string): Promise<string | undefined>;\n\n // ---------------------------------------------------------\n // Pub/Sub operations (for alepha/topic-redis)\n // ---------------------------------------------------------\n\n /**\n * Publish a message to a channel.\n *\n * @param channel The channel name.\n * @param message The message to publish.\n */\n public abstract publish(channel: string, message: string): Promise<void>;\n}\n\n/**\n * Common Redis SET command options.\n * Compatible with @redis/client SetOptions format.\n */\nexport interface RedisSetOptions {\n /**\n * Set the specified expire time, in seconds.\n */\n EX?: number;\n /**\n * Set the specified expire time, in milliseconds.\n */\n PX?: number;\n /**\n * Set the specified Unix time at which the key will expire, in seconds.\n */\n EXAT?: number;\n /**\n * Set the specified Unix time at which the key will expire, in milliseconds.\n */\n PXAT?: number;\n /**\n * Only set the key if it does not already exist.\n */\n NX?: boolean;\n /**\n * Only set the key if it already exists.\n */\n XX?: boolean;\n /**\n * Retain the time to live associated with the key.\n */\n KEEPTTL?: boolean;\n /**\n * Return the old string stored at key, or nil if key did not exist.\n */\n GET?: boolean;\n /**\n * Alternative expiration format (compatible with @redis/client).\n */\n expiration?: {\n type: \"EX\" | \"PX\" | \"EXAT\" | \"PXAT\" | \"KEEPTTL\";\n value: number;\n };\n /**\n * Alternative condition format (compatible with @redis/client).\n */\n condition?: \"NX\" | \"XX\";\n}\n","import {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Bun Redis client provider using Bun's native Redis client.\n *\n * This provider uses Bun's built-in `RedisClient` class for Redis connections,\n * which provides excellent performance (7.9x faster than ioredis) on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: BunRedisProvider,\n * });\n * ```\n */\nexport class BunRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected client?: Bun.RedisClient;\n\n public get publisher(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n // Check if we're running in Bun\n if (!this.alepha.isBun()) {\n throw new AlephaError(\n \"BunRedisProvider requires the Bun runtime. Use NodeRedisProvider for Node.js.\",\n );\n }\n\n this.log.debug(\"Connecting...\");\n\n this.client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n this.client.onconnect = () => {\n this.log.trace(\"Redis connected\");\n };\n\n this.client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis connection closed\", error);\n }\n };\n\n await this.client.connect();\n\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Connection closed\");\n }\n }\n\n /**\n * Create a duplicate connection for pub/sub or other isolated operations.\n */\n public async duplicate(): Promise<Bun.RedisClient> {\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\"BunRedisProvider requires the Bun runtime.\");\n }\n\n const client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis duplicate connection closed\", error);\n }\n };\n\n await client.connect();\n\n return client;\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.getBuffer(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Build SET command arguments\n const args: string[] = [key, buf.toString(\"binary\")];\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n args.push(\"KEEPTTL\");\n } else {\n args.push(options.expiration.type, String(options.expiration.value));\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n args.push(\"EX\", String(options.EX));\n }\n if (options?.PX !== undefined) {\n args.push(\"PX\", String(options.PX));\n }\n if (options?.EXAT !== undefined) {\n args.push(\"EXAT\", String(options.EXAT));\n }\n if (options?.PXAT !== undefined) {\n args.push(\"PXAT\", String(options.PXAT));\n }\n if (options?.KEEPTTL) {\n args.push(\"KEEPTTL\");\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n args.push(\"NX\");\n } else if (options?.condition === \"XX\") {\n args.push(\"XX\");\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n args.push(\"NX\");\n }\n if (options?.XX) {\n args.push(\"XX\");\n }\n if (options?.GET) {\n args.push(\"GET\");\n }\n\n if (args.length === 2) {\n // Simple set without options\n await this.publisher.set(key, buf);\n } else {\n // Set with options via raw command\n await this.publisher.send(\"SET\", args);\n }\n\n return buf;\n }\n\n public override async has(key: string): Promise<boolean> {\n return this.publisher.exists(key);\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.send(\"KEYS\", [pattern]);\n if (!Array.isArray(keys)) {\n return [];\n }\n return keys.map((key) =>\n key instanceof Uint8Array ? Buffer.from(key).toString() : String(key),\n );\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.send(\"DEL\", keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.send(\"LPUSH\", [key, value]);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.send(\"RPOP\", [key]);\n if (value == null) {\n return undefined;\n }\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString();\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n}\n","/**\n * Abstract Redis subscriber provider interface.\n *\n * This abstract class defines the common interface for Redis pub/sub subscriptions.\n * Implementations include:\n * - {@link NodeRedisSubscriberProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisSubscriberProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * Redis requires separate connections for pub/sub operations, so this provider\n * creates a dedicated connection for subscriptions.\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n *\n * // Subscribe to a channel\n * await subscriber.subscribe(\"my-channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport abstract class RedisSubscriberProvider {\n /**\n * Whether the Redis subscriber client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the subscriber connection.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Subscribe to a channel.\n *\n * @param channel The channel name.\n * @param callback The callback to invoke when a message is received.\n */\n public abstract subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void>;\n\n /**\n * Unsubscribe from a channel.\n *\n * @param channel The channel name.\n * @param callback Optional specific callback to remove.\n */\n public abstract unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void>;\n}\n\n/**\n * Callback for subscription messages.\n */\nexport type SubscribeCallback = (message: string, channel: string) => void;\n","import { $hook, $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BunRedisProvider } from \"./BunRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Bun Redis subscriber provider for pub/sub operations.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class BunRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(BunRedisProvider);\n protected client?: Bun.RedisClient;\n\n public get subscriber(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n this.client = await this.redisProvider.duplicate();\n this.log.info(\"Subscriber connection OK\");\n }\n\n /**\n * Close the subscriber connection.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing subscriber connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Subscriber connection closed\");\n }\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, (message, ch) => {\n // Bun's callback provides Buffer or string, normalize to string\n const msg =\n typeof message === \"object\" && message !== null\n ? Buffer.from(message as Uint8Array).toString()\n : String(message);\n callback(msg, ch);\n });\n }\n\n public override async unsubscribe(\n channel: string,\n _callback?: SubscribeCallback,\n ): Promise<void> {\n // Bun's unsubscribe doesn't support callback filtering\n await this.subscriber.unsubscribe(channel);\n }\n}\n","import {\n createClient,\n RESP_TYPES,\n type RedisClientType,\n type SetOptions,\n} from \"@redis/client\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\nexport type NodeRedisClient = RedisClientType<\n {},\n {},\n {},\n 3,\n { 36: BufferConstructor }\n>;\nexport type NodeRedisClientOptions = Parameters<typeof createClient>[0];\n\n/**\n * Node.js Redis client provider using `@redis/client`.\n *\n * This provider uses the official Redis client for Node.js runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: NodeRedisProvider,\n * });\n * ```\n */\nexport class NodeRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected readonly client = this.createClient();\n\n public get publisher(): NodeRedisClient {\n if (!this.client.isReady) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client.isReady;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting...\");\n await this.client.connect();\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n this.log.debug(\"Closing connection...\");\n await this.client.close();\n this.log.info(\"Connection closed\");\n }\n\n public duplicate(options?: Partial<NodeRedisClientOptions>): NodeRedisClient {\n return this.client\n .duplicate({\n ...options,\n RESP: 3,\n })\n .withTypeMapping({\n [RESP_TYPES.BLOB_STRING]: Buffer,\n });\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.get(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Convert RedisSetOptions to @redis/client SetOptions\n const setOptions: SetOptions = {};\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n setOptions.KEEPTTL = true;\n } else {\n setOptions[options.expiration.type] = options.expiration.value;\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n setOptions.EX = options.EX;\n }\n if (options?.PX !== undefined) {\n setOptions.PX = options.PX;\n }\n if (options?.EXAT !== undefined) {\n setOptions.EXAT = options.EXAT;\n }\n if (options?.PXAT !== undefined) {\n setOptions.PXAT = options.PXAT;\n }\n if (options?.KEEPTTL) {\n setOptions.KEEPTTL = true;\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n setOptions.NX = true;\n } else if (options?.condition === \"XX\") {\n setOptions.XX = true;\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n setOptions.NX = true;\n }\n if (options?.XX) {\n setOptions.XX = true;\n }\n if (options?.GET) {\n setOptions.GET = true;\n }\n\n const resp = await this.publisher.set(\n key,\n buf,\n Object.keys(setOptions).length > 0 ? setOptions : undefined,\n );\n\n if (resp === \"OK\" || !resp) {\n return buf;\n }\n\n return Buffer.from(resp);\n }\n\n public override async has(key: string): Promise<boolean> {\n const resp = await this.publisher.exists(key);\n return resp > 0;\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.keys(pattern);\n return keys.map((key) => key.toString());\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.del(keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.LPUSH(key, value);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.RPOP(key);\n if (value == null) {\n return undefined;\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n\n /**\n * Redis client factory method.\n */\n protected createClient(): NodeRedisClient {\n const client = createClient({\n url: this.getUrl(),\n RESP: 3,\n }).withTypeMapping({\n [RESP_TYPES.BLOB_STRING]: Buffer,\n });\n\n client.on(\"error\", (error) => {\n if (this.alepha.isStarted()) {\n this.log.error(error);\n }\n });\n\n return client;\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n type NodeRedisClient,\n NodeRedisProvider,\n} from \"./NodeRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Node.js Redis subscriber provider using `@redis/client`.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class NodeRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(NodeRedisProvider);\n protected readonly client: NodeRedisClient = this.createClient();\n\n public get subscriber(): NodeRedisClient {\n if (!this.client.isReady) {\n throw new Error(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client.isReady;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n await this.client.connect();\n this.log.info(\"Subscriber connection OK\");\n }\n\n public override async close(): Promise<void> {\n this.log.debug(\"Closing subscriber connection...\");\n await this.subscriber.close();\n this.log.info(\"Subscriber connection closed\");\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, callback);\n }\n\n public override async unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.unsubscribe(channel, callback);\n }\n\n /**\n * Redis subscriber client factory method.\n */\n protected createClient(): NodeRedisClient {\n const client = this.redisProvider.duplicate();\n\n client.on(\"error\", (error) => {\n if (this.alepha.isStarted()) {\n this.log.error(error);\n }\n });\n\n return client;\n }\n}\n","import { $module, type Alepha } from \"alepha\";\nimport { BunRedisProvider } from \"./providers/BunRedisProvider.ts\";\nimport { BunRedisSubscriberProvider } from \"./providers/BunRedisSubscriberProvider.ts\";\nimport { NodeRedisProvider } from \"./providers/NodeRedisProvider.ts\";\nimport { NodeRedisSubscriberProvider } from \"./providers/NodeRedisSubscriberProvider.ts\";\nimport { RedisProvider } from \"./providers/RedisProvider.ts\";\nimport { RedisSubscriberProvider } from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BunRedisProvider.ts\";\nexport * from \"./providers/BunRedisSubscriberProvider.ts\";\nexport * from \"./providers/NodeRedisProvider.ts\";\nexport * from \"./providers/NodeRedisSubscriberProvider.ts\";\nexport * from \"./providers/RedisProvider.ts\";\nexport * from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Redis client provider for Alepha applications.\n *\n * Automatically selects the appropriate provider based on runtime:\n * - Bun: Uses `BunRedisProvider` with Bun's native Redis client (7.9x faster than ioredis)\n * - Node.js: Uses `NodeRedisProvider` with `@redis/client`\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const redis = alepha.inject(RedisProvider);\n *\n * // Use common operations\n * await redis.set(\"key\", \"value\");\n * const value = await redis.get(\"key\");\n *\n * // For pub/sub\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n *\n * @see {@link RedisProvider} - Abstract base class\n * @see {@link NodeRedisProvider} - Node.js implementation\n * @see {@link BunRedisProvider} - Bun implementation\n * @see {@link RedisSubscriberProvider} - Abstract subscriber base class\n * @see {@link NodeRedisSubscriberProvider} - Node.js subscriber implementation\n * @see {@link BunRedisSubscriberProvider} - Bun subscriber implementation\n * @module alepha.redis\n */\nexport const AlephaRedis = $module({\n name: \"alepha.redis\",\n services: [\n NodeRedisProvider,\n NodeRedisSubscriberProvider,\n BunRedisProvider,\n BunRedisSubscriberProvider,\n RedisProvider,\n RedisSubscriberProvider,\n ],\n register: (alepha: Alepha) => {\n if (alepha.isBun()) {\n alepha\n .with({\n provide: RedisProvider,\n use: BunRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: BunRedisSubscriberProvider,\n });\n } else {\n alepha\n .with({\n provide: RedisProvider,\n use: NodeRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: NodeRedisSubscriberProvider,\n });\n }\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["envSchema"],"sources":["../../src/redis/providers/RedisProvider.ts","../../src/redis/providers/BunRedisProvider.ts","../../src/redis/providers/RedisSubscriberProvider.ts","../../src/redis/providers/BunRedisSubscriberProvider.ts","../../src/redis/providers/NodeRedisProvider.ts","../../src/redis/providers/NodeRedisSubscriberProvider.ts","../../src/redis/index.ts"],"sourcesContent":["/**\n * Abstract Redis provider interface.\n *\n * This abstract class defines the common interface for Redis operations.\n * Implementations include:\n * - {@link NodeRedisProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const redis = alepha.inject(RedisProvider);\n *\n * // Use common operations\n * await redis.set(\"key\", \"value\");\n * const value = await redis.get(\"key\");\n * ```\n */\nexport abstract class RedisProvider {\n /**\n * Whether the Redis client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the connection to the Redis server.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Get the value of a key.\n *\n * @param key The key to get.\n * @returns The value as a Buffer, or undefined if the key does not exist.\n */\n public abstract get(key: string): Promise<Buffer | undefined>;\n\n /**\n * Set the value of a key.\n *\n * @param key The key to set.\n * @param value The value to set (Buffer or string).\n * @param options Optional set options (EX, PX, NX, XX, etc.).\n * @returns The value as a Buffer.\n */\n public abstract set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer>;\n\n /**\n * Check if a key exists.\n *\n * @param key The key to check.\n * @returns True if the key exists.\n */\n public abstract has(key: string): Promise<boolean>;\n\n /**\n * Get all keys matching a pattern.\n *\n * @param pattern The glob-style pattern to match.\n * @returns Array of matching key names.\n */\n public abstract keys(pattern: string): Promise<string[]>;\n\n /**\n * Delete one or more keys.\n *\n * @param keys The keys to delete.\n */\n public abstract del(keys: string[]): Promise<void>;\n\n // ---------------------------------------------------------\n // Queue operations (for alepha/queue-redis)\n // ---------------------------------------------------------\n\n /**\n * Push a value to the left (head) of a list.\n *\n * @param key The list key.\n * @param value The value to push.\n */\n public abstract lpush(key: string, value: string): Promise<void>;\n\n /**\n * Pop a value from the right (tail) of a list.\n *\n * @param key The list key.\n * @returns The value, or undefined if the list is empty.\n */\n public abstract rpop(key: string): Promise<string | undefined>;\n\n // ---------------------------------------------------------\n // Pub/Sub operations (for alepha/topic-redis)\n // ---------------------------------------------------------\n\n /**\n * Publish a message to a channel.\n *\n * @param channel The channel name.\n * @param message The message to publish.\n */\n public abstract publish(channel: string, message: string): Promise<void>;\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n /**\n * Increment the integer value of a key by the given amount.\n *\n * If the key does not exist, it is set to 0 before performing the operation.\n * This operation is atomic.\n *\n * @param key The key to increment.\n * @param amount The amount to increment by.\n * @returns The new value after incrementing.\n */\n public abstract incr(key: string, amount: number): Promise<number>;\n}\n\n/**\n * Common Redis SET command options.\n * Compatible with @redis/client SetOptions format.\n */\nexport interface RedisSetOptions {\n /**\n * Set the specified expire time, in seconds.\n */\n EX?: number;\n /**\n * Set the specified expire time, in milliseconds.\n */\n PX?: number;\n /**\n * Set the specified Unix time at which the key will expire, in seconds.\n */\n EXAT?: number;\n /**\n * Set the specified Unix time at which the key will expire, in milliseconds.\n */\n PXAT?: number;\n /**\n * Only set the key if it does not already exist.\n */\n NX?: boolean;\n /**\n * Only set the key if it already exists.\n */\n XX?: boolean;\n /**\n * Retain the time to live associated with the key.\n */\n KEEPTTL?: boolean;\n /**\n * Return the old string stored at key, or nil if key did not exist.\n */\n GET?: boolean;\n /**\n * Alternative expiration format (compatible with @redis/client).\n */\n expiration?: {\n type: \"EX\" | \"PX\" | \"EXAT\" | \"PXAT\" | \"KEEPTTL\";\n value: number;\n };\n /**\n * Alternative condition format (compatible with @redis/client).\n */\n condition?: \"NX\" | \"XX\";\n}\n","import {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\n/**\n * Bun Redis client provider using Bun's native Redis client.\n *\n * This provider uses Bun's built-in `RedisClient` class for Redis connections,\n * which provides excellent performance (7.9x faster than ioredis) on the Bun runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: BunRedisProvider,\n * });\n * ```\n */\nexport class BunRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected client?: Bun.RedisClient;\n\n public get publisher(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n // Check if we're running in Bun\n if (!this.alepha.isBun()) {\n throw new AlephaError(\n \"BunRedisProvider requires the Bun runtime. Use NodeRedisProvider for Node.js.\",\n );\n }\n\n this.log.debug(\"Connecting...\");\n\n this.client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n this.client.onconnect = () => {\n this.log.trace(\"Redis connected\");\n };\n\n this.client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis connection closed\", error);\n }\n };\n\n await this.client.connect();\n\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Connection closed\");\n }\n }\n\n /**\n * Create a duplicate connection for pub/sub or other isolated operations.\n */\n public async duplicate(): Promise<Bun.RedisClient> {\n if (typeof Bun === \"undefined\") {\n throw new AlephaError(\"BunRedisProvider requires the Bun runtime.\");\n }\n\n const client = new Bun.RedisClient(this.getUrl(), {\n autoReconnect: true,\n enableAutoPipelining: true,\n });\n\n client.onclose = (error) => {\n if (this.alepha.isStarted() && error) {\n this.log.error(\"Redis duplicate connection closed\", error);\n }\n };\n\n await client.connect();\n\n return client;\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.getBuffer(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Build SET command arguments\n const args: string[] = [key, buf.toString(\"binary\")];\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n args.push(\"KEEPTTL\");\n } else {\n args.push(options.expiration.type, String(options.expiration.value));\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n args.push(\"EX\", String(options.EX));\n }\n if (options?.PX !== undefined) {\n args.push(\"PX\", String(options.PX));\n }\n if (options?.EXAT !== undefined) {\n args.push(\"EXAT\", String(options.EXAT));\n }\n if (options?.PXAT !== undefined) {\n args.push(\"PXAT\", String(options.PXAT));\n }\n if (options?.KEEPTTL) {\n args.push(\"KEEPTTL\");\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n args.push(\"NX\");\n } else if (options?.condition === \"XX\") {\n args.push(\"XX\");\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n args.push(\"NX\");\n }\n if (options?.XX) {\n args.push(\"XX\");\n }\n if (options?.GET) {\n args.push(\"GET\");\n }\n\n if (args.length === 2) {\n // Simple set without options\n await this.publisher.set(key, buf);\n } else {\n // Set with options via raw command\n await this.publisher.send(\"SET\", args);\n }\n\n return buf;\n }\n\n public override async has(key: string): Promise<boolean> {\n return this.publisher.exists(key);\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.send(\"KEYS\", [pattern]);\n if (!Array.isArray(keys)) {\n return [];\n }\n return keys.map((key) =>\n key instanceof Uint8Array ? Buffer.from(key).toString() : String(key),\n );\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.send(\"DEL\", keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.send(\"LPUSH\", [key, value]);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.send(\"RPOP\", [key]);\n if (value == null) {\n return undefined;\n }\n if (value instanceof Uint8Array) {\n return Buffer.from(value).toString();\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n public override async incr(key: string, amount: number): Promise<number> {\n const result = await this.publisher.send(\"INCRBY\", [key, String(amount)]);\n return Number(result);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n}\n","/**\n * Abstract Redis subscriber provider interface.\n *\n * This abstract class defines the common interface for Redis pub/sub subscriptions.\n * Implementations include:\n * - {@link NodeRedisSubscriberProvider} - Uses `@redis/client` for Node.js runtime\n * - {@link BunRedisSubscriberProvider} - Uses Bun's native `RedisClient` for Bun runtime\n *\n * Redis requires separate connections for pub/sub operations, so this provider\n * creates a dedicated connection for subscriptions.\n *\n * @example\n * ```ts\n * // Inject the abstract provider - runtime selects the implementation\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n *\n * // Subscribe to a channel\n * await subscriber.subscribe(\"my-channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport abstract class RedisSubscriberProvider {\n /**\n * Whether the Redis subscriber client is ready to accept commands.\n */\n public abstract readonly isReady: boolean;\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public abstract connect(): Promise<void>;\n\n /**\n * Close the subscriber connection.\n */\n public abstract close(): Promise<void>;\n\n /**\n * Subscribe to a channel.\n *\n * @param channel The channel name.\n * @param callback The callback to invoke when a message is received.\n */\n public abstract subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void>;\n\n /**\n * Unsubscribe from a channel.\n *\n * @param channel The channel name.\n * @param callback Optional specific callback to remove.\n */\n public abstract unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void>;\n}\n\n/**\n * Callback for subscription messages.\n */\nexport type SubscribeCallback = (message: string, channel: string) => void;\n","import { $hook, $inject, Alepha, AlephaError } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { BunRedisProvider } from \"./BunRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Bun Redis subscriber provider for pub/sub operations.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class BunRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(BunRedisProvider);\n protected client?: Bun.RedisClient;\n\n public get subscriber(): Bun.RedisClient {\n if (!this.client?.connected) {\n throw new AlephaError(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client?.connected ?? false;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server for subscriptions.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n this.client = await this.redisProvider.duplicate();\n this.log.info(\"Subscriber connection OK\");\n }\n\n /**\n * Close the subscriber connection.\n */\n public override async close(): Promise<void> {\n if (this.client) {\n this.log.debug(\"Closing subscriber connection...\");\n this.client.close();\n this.client = undefined;\n this.log.info(\"Subscriber connection closed\");\n }\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, (message, ch) => {\n // Bun's callback provides Buffer or string, normalize to string\n const msg =\n typeof message === \"object\" && message !== null\n ? Buffer.from(message as Uint8Array).toString()\n : String(message);\n callback(msg, ch);\n });\n }\n\n public override async unsubscribe(\n channel: string,\n _callback?: SubscribeCallback,\n ): Promise<void> {\n // Bun's unsubscribe doesn't support callback filtering\n await this.subscriber.unsubscribe(channel);\n }\n}\n","import {\n createClient,\n RESP_TYPES,\n type RedisClientType,\n type SetOptions,\n} from \"@redis/client\";\nimport {\n $env,\n $hook,\n $inject,\n Alepha,\n AlephaError,\n type Static,\n t,\n} from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport { RedisProvider, type RedisSetOptions } from \"./RedisProvider.ts\";\n\nconst envSchema = t.object({\n REDIS_URL: t.text({\n default: \"redis://localhost:6379\",\n description: \"Redis connection URL\",\n }),\n});\n\ndeclare module \"alepha\" {\n interface Env extends Partial<Static<typeof envSchema>> {}\n}\n\nexport type NodeRedisClient = RedisClientType<\n {},\n {},\n {},\n 3,\n { 36: BufferConstructor }\n>;\nexport type NodeRedisClientOptions = Parameters<typeof createClient>[0];\n\n/**\n * Node.js Redis client provider using `@redis/client`.\n *\n * This provider uses the official Redis client for Node.js runtime.\n *\n * @example\n * ```ts\n * // Set REDIS_URL environment variable (default: redis://localhost:6379)\n * // REDIS_URL=redis://:password@myredis.example.com:6379\n *\n * // Or configure programmatically\n * alepha.with({\n * provide: RedisProvider,\n * use: NodeRedisProvider,\n * });\n * ```\n */\nexport class NodeRedisProvider extends RedisProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly env = $env(envSchema);\n protected readonly client = this.createClient();\n\n public get publisher(): NodeRedisClient {\n if (!this.client.isReady) {\n throw new AlephaError(\"Redis client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client.isReady;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n /**\n * Connect to the Redis server.\n */\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting...\");\n await this.client.connect();\n this.log.info(\"Connection OK\");\n }\n\n /**\n * Close the connection to the Redis server.\n */\n public override async close(): Promise<void> {\n this.log.debug(\"Closing connection...\");\n await this.client.close();\n this.log.info(\"Connection closed\");\n }\n\n public duplicate(options?: Partial<NodeRedisClientOptions>): NodeRedisClient {\n return this.client\n .duplicate({\n ...options,\n RESP: 3,\n })\n .withTypeMapping({\n [RESP_TYPES.BLOB_STRING]: Buffer,\n });\n }\n\n public override async get(key: string): Promise<Buffer | undefined> {\n this.log.trace(`Getting key ${key}`);\n const resp = await this.publisher.get(key);\n\n if (resp === null) {\n return undefined;\n }\n\n return Buffer.from(resp);\n }\n\n public override async set(\n key: string,\n value: Buffer | string,\n options?: RedisSetOptions,\n ): Promise<Buffer> {\n const buf = Buffer.isBuffer(value) ? value : Buffer.from(value, \"utf-8\");\n\n // Convert RedisSetOptions to @redis/client SetOptions\n const setOptions: SetOptions = {};\n\n // Handle expiration object format (from alepha/cache-redis, alepha/lock-redis)\n if (options?.expiration) {\n if (options.expiration.type === \"KEEPTTL\") {\n setOptions.KEEPTTL = true;\n } else {\n setOptions[options.expiration.type] = options.expiration.value;\n }\n }\n\n // Handle direct expiration properties\n if (options?.EX !== undefined) {\n setOptions.EX = options.EX;\n }\n if (options?.PX !== undefined) {\n setOptions.PX = options.PX;\n }\n if (options?.EXAT !== undefined) {\n setOptions.EXAT = options.EXAT;\n }\n if (options?.PXAT !== undefined) {\n setOptions.PXAT = options.PXAT;\n }\n if (options?.KEEPTTL) {\n setOptions.KEEPTTL = true;\n }\n\n // Handle condition object format\n if (options?.condition === \"NX\") {\n setOptions.NX = true;\n } else if (options?.condition === \"XX\") {\n setOptions.XX = true;\n }\n\n // Handle direct condition properties\n if (options?.NX) {\n setOptions.NX = true;\n }\n if (options?.XX) {\n setOptions.XX = true;\n }\n if (options?.GET) {\n setOptions.GET = true;\n }\n\n const resp = await this.publisher.set(\n key,\n buf,\n Object.keys(setOptions).length > 0 ? setOptions : undefined,\n );\n\n if (resp === \"OK\" || !resp) {\n return buf;\n }\n\n return Buffer.from(resp);\n }\n\n public override async has(key: string): Promise<boolean> {\n const resp = await this.publisher.exists(key);\n return resp > 0;\n }\n\n public override async keys(pattern: string): Promise<string[]> {\n const keys = await this.publisher.keys(pattern);\n return keys.map((key) => key.toString());\n }\n\n public override async del(keys: string[]): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n\n await this.publisher.del(keys);\n }\n\n // ---------------------------------------------------------\n // Queue operations\n // ---------------------------------------------------------\n\n public override async lpush(key: string, value: string): Promise<void> {\n await this.publisher.LPUSH(key, value);\n }\n\n public override async rpop(key: string): Promise<string | undefined> {\n const value = await this.publisher.RPOP(key);\n if (value == null) {\n return undefined;\n }\n return String(value);\n }\n\n // ---------------------------------------------------------\n // Pub/Sub operations\n // ---------------------------------------------------------\n\n public override async publish(\n channel: string,\n message: string,\n ): Promise<void> {\n await this.publisher.publish(channel, message);\n }\n\n // ---------------------------------------------------------\n // Counter operations\n // ---------------------------------------------------------\n\n public override async incr(key: string, amount: number): Promise<number> {\n return this.publisher.INCRBY(key, amount);\n }\n\n /**\n * Get the Redis connection URL.\n */\n protected getUrl(): string {\n return this.env.REDIS_URL;\n }\n\n /**\n * Redis client factory method.\n */\n protected createClient(): NodeRedisClient {\n const client = createClient({\n url: this.getUrl(),\n RESP: 3,\n }).withTypeMapping({\n [RESP_TYPES.BLOB_STRING]: Buffer,\n });\n\n client.on(\"error\", (error) => {\n if (this.alepha.isStarted()) {\n this.log.error(error);\n }\n });\n\n return client;\n }\n}\n","import { $hook, $inject, Alepha } from \"alepha\";\nimport { $logger } from \"alepha/logger\";\nimport {\n type NodeRedisClient,\n NodeRedisProvider,\n} from \"./NodeRedisProvider.ts\";\nimport {\n RedisSubscriberProvider,\n type SubscribeCallback,\n} from \"./RedisSubscriberProvider.ts\";\n\n/**\n * Node.js Redis subscriber provider using `@redis/client`.\n *\n * This provider creates a dedicated Redis connection for subscriptions,\n * as Redis requires separate connections for pub/sub operations.\n *\n * @example\n * ```ts\n * const subscriber = alepha.inject(RedisSubscriberProvider);\n * await subscriber.subscribe(\"channel\", (message, channel) => {\n * console.log(`Received: ${message} on ${channel}`);\n * });\n * ```\n */\nexport class NodeRedisSubscriberProvider extends RedisSubscriberProvider {\n protected readonly log = $logger();\n protected readonly alepha = $inject(Alepha);\n protected readonly redisProvider = $inject(NodeRedisProvider);\n protected readonly client: NodeRedisClient = this.createClient();\n\n public get subscriber(): NodeRedisClient {\n if (!this.client.isReady) {\n throw new Error(\"Redis subscriber client is not ready\");\n }\n\n return this.client;\n }\n\n public override get isReady(): boolean {\n return this.client.isReady;\n }\n\n protected readonly start = $hook({\n on: \"start\",\n handler: () => this.connect(),\n });\n\n protected readonly stop = $hook({\n on: \"stop\",\n handler: () => this.close(),\n });\n\n public override async connect(): Promise<void> {\n this.log.debug(\"Connecting subscriber...\");\n await this.client.connect();\n this.log.info(\"Subscriber connection OK\");\n }\n\n public override async close(): Promise<void> {\n this.log.debug(\"Closing subscriber connection...\");\n await this.subscriber.close();\n this.log.info(\"Subscriber connection closed\");\n }\n\n public override async subscribe(\n channel: string,\n callback: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.subscribe(channel, callback);\n }\n\n public override async unsubscribe(\n channel: string,\n callback?: SubscribeCallback,\n ): Promise<void> {\n await this.subscriber.unsubscribe(channel, callback);\n }\n\n /**\n * Redis subscriber client factory method.\n */\n protected createClient(): NodeRedisClient {\n const client = this.redisProvider.duplicate();\n\n client.on(\"error\", (error) => {\n if (this.alepha.isStarted()) {\n this.log.error(error);\n }\n });\n\n return client;\n }\n}\n","import { $module, type Alepha } from \"alepha\";\nimport { BunRedisProvider } from \"./providers/BunRedisProvider.ts\";\nimport { BunRedisSubscriberProvider } from \"./providers/BunRedisSubscriberProvider.ts\";\nimport { NodeRedisProvider } from \"./providers/NodeRedisProvider.ts\";\nimport { NodeRedisSubscriberProvider } from \"./providers/NodeRedisSubscriberProvider.ts\";\nimport { RedisProvider } from \"./providers/RedisProvider.ts\";\nimport { RedisSubscriberProvider } from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/BunRedisProvider.ts\";\nexport * from \"./providers/BunRedisSubscriberProvider.ts\";\nexport * from \"./providers/NodeRedisProvider.ts\";\nexport * from \"./providers/NodeRedisSubscriberProvider.ts\";\nexport * from \"./providers/RedisProvider.ts\";\nexport * from \"./providers/RedisSubscriberProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | type | quality | stability |\n * |------|---------|-----------|\n * | backend | standard | stable |\n *\n * Redis client wrapper.\n *\n * **Features:**\n * - Connection pooling\n * - Automatic reconnection\n * - Command pipelining\n * - Pub/sub support\n *\n * @module alepha.redis\n */\nexport const AlephaRedis = $module({\n name: \"alepha.redis\",\n services: [\n NodeRedisProvider,\n NodeRedisSubscriberProvider,\n BunRedisProvider,\n BunRedisSubscriberProvider,\n RedisProvider,\n RedisSubscriberProvider,\n ],\n register: (alepha: Alepha) => {\n if (alepha.isBun()) {\n alepha\n .with({\n provide: RedisProvider,\n use: BunRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: BunRedisSubscriberProvider,\n });\n } else {\n alepha\n .with({\n provide: RedisProvider,\n use: NodeRedisProvider,\n })\n .with({\n provide: RedisSubscriberProvider,\n use: NodeRedisSubscriberProvider,\n });\n }\n },\n});\n"],"mappings":"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"}
@@ -16,71 +16,71 @@ declare class RetryTimeoutError extends AlephaError {
16
16
  //#region ../../src/retry/providers/RetryProvider.d.ts
17
17
  interface RetryOptions<T extends (...args: any[]) => any> {
18
18
  /**
19
- * The function to retry.
20
- */
19
+ * The function to retry.
20
+ */
21
21
  handler: T;
22
22
  /**
23
- * The maximum number of attempts.
24
- *
25
- * @default 3
26
- */
23
+ * The maximum number of attempts.
24
+ *
25
+ * @default 3
26
+ */
27
27
  max?: number;
28
28
  /**
29
- * The backoff strategy for delays between retries.
30
- * Can be a fixed number (in ms) or a configuration object for exponential backoff.
31
- *
32
- * @default { initial: 200, factor: 2, jitter: true }
33
- */
29
+ * The backoff strategy for delays between retries.
30
+ * Can be a fixed number (in ms) or a configuration object for exponential backoff.
31
+ *
32
+ * @default { initial: 200, factor: 2, jitter: true }
33
+ */
34
34
  backoff?: number | RetryBackoffOptions;
35
35
  /**
36
- * An overall time limit for all retry attempts combined.
37
- *
38
- * e.g., `[5, 'seconds']`
39
- */
36
+ * An overall time limit for all retry attempts combined.
37
+ *
38
+ * e.g., `[5, 'seconds']`
39
+ */
40
40
  maxDuration?: DurationLike;
41
41
  /**
42
- * A function that determines if a retry should be attempted based on the error.
43
- *
44
- * @default (error) => true (retries on any error)
45
- */
42
+ * A function that determines if a retry should be attempted based on the error.
43
+ *
44
+ * @default (error) => true (retries on any error)
45
+ */
46
46
  when?: (error: Error) => boolean;
47
47
  /**
48
- * A custom callback for when a retry attempt fails.
49
- * This is called before the delay.
50
- */
48
+ * A custom callback for when a retry attempt fails.
49
+ * This is called before the delay.
50
+ */
51
51
  onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;
52
52
  /**
53
- * An AbortSignal to allow for external cancellation of the retry loop.
54
- */
53
+ * An AbortSignal to allow for external cancellation of the retry loop.
54
+ */
55
55
  signal?: AbortSignal;
56
56
  /**
57
- * An additional AbortSignal to combine with the provided signal.
58
- * Used internally by $retry to handle app lifecycle.
59
- */
57
+ * An additional AbortSignal to combine with the provided signal.
58
+ * Used internally by $retry to handle app lifecycle.
59
+ */
60
60
  additionalSignal?: AbortSignal;
61
61
  }
62
62
  interface RetryBackoffOptions {
63
63
  /**
64
- * Initial delay in milliseconds.
65
- *
66
- * @default 200
67
- */
64
+ * Initial delay in milliseconds.
65
+ *
66
+ * @default 200
67
+ */
68
68
  initial?: number;
69
69
  /**
70
- * Multiplier for each subsequent delay.
71
- *
72
- * @default 2
73
- */
70
+ * Multiplier for each subsequent delay.
71
+ *
72
+ * @default 2
73
+ */
74
74
  factor?: number;
75
75
  /**
76
- * Maximum delay in milliseconds.
77
- */
76
+ * Maximum delay in milliseconds.
77
+ */
78
78
  max?: number;
79
79
  /**
80
- * If true, adds a random jitter to the delay to prevent thundering herd.
81
- *
82
- * @default true
83
- */
80
+ * If true, adds a random jitter to the delay to prevent thundering herd.
81
+ *
82
+ * @default true
83
+ */
84
84
  jitter?: boolean;
85
85
  }
86
86
  /**
@@ -91,12 +91,12 @@ declare class RetryProvider {
91
91
  protected readonly log: alepha_logger0.Logger;
92
92
  protected readonly dateTime: DateTimeProvider;
93
93
  /**
94
- * Execute a function with automatic retry logic.
95
- */
94
+ * Execute a function with automatic retry logic.
95
+ */
96
96
  retry<T extends (...args: any[]) => any>(options: RetryOptions<T>, ...args: Parameters<T>): Promise<ReturnType<T>>;
97
97
  /**
98
- * Calculate the backoff delay for a given attempt.
99
- */
98
+ * Calculate the backoff delay for a given attempt.
99
+ */
100
100
  protected calculateBackoff(attempt: number, options?: number | RetryBackoffOptions): number;
101
101
  }
102
102
  //#endregion
@@ -111,42 +111,42 @@ declare const $retry: {
111
111
  };
112
112
  interface RetryPrimitiveOptions<T extends (...args: any[]) => any> {
113
113
  /**
114
- * The function to retry.
115
- */
114
+ * The function to retry.
115
+ */
116
116
  handler: T;
117
117
  /**
118
- * The maximum number of attempts.
119
- *
120
- * @default 3
121
- */
118
+ * The maximum number of attempts.
119
+ *
120
+ * @default 3
121
+ */
122
122
  max?: number;
123
123
  /**
124
- * The backoff strategy for delays between retries.
125
- * Can be a fixed number (in ms) or a configuration object for exponential backoff.
126
- *
127
- * @default { initial: 200, factor: 2, jitter: true }
128
- */
124
+ * The backoff strategy for delays between retries.
125
+ * Can be a fixed number (in ms) or a configuration object for exponential backoff.
126
+ *
127
+ * @default { initial: 200, factor: 2, jitter: true }
128
+ */
129
129
  backoff?: number | RetryBackoffOptions;
130
130
  /**
131
- * An overall time limit for all retry attempts combined.
132
- *
133
- * e.g., `[5, 'seconds']`
134
- */
131
+ * An overall time limit for all retry attempts combined.
132
+ *
133
+ * e.g., `[5, 'seconds']`
134
+ */
135
135
  maxDuration?: DurationLike;
136
136
  /**
137
- * A function that determines if a retry should be attempted based on the error.
138
- *
139
- * @default (error) => true (retries on any error)
140
- */
137
+ * A function that determines if a retry should be attempted based on the error.
138
+ *
139
+ * @default (error) => true (retries on any error)
140
+ */
141
141
  when?: (error: Error) => boolean;
142
142
  /**
143
- * A custom callback for when a retry attempt fails.
144
- * This is called before the delay.
145
- */
143
+ * A custom callback for when a retry attempt fails.
144
+ * This is called before the delay.
145
+ */
146
146
  onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;
147
147
  /**
148
- * An AbortSignal to allow for external cancellation of the retry loop.
149
- */
148
+ * An AbortSignal to allow for external cancellation of the retry loop.
149
+ */
150
150
  signal?: AbortSignal;
151
151
  }
152
152
  declare class RetryPrimitive<T extends (...args: any[]) => any> extends Primitive<RetryPrimitiveOptions<T>> {
@@ -161,9 +161,18 @@ interface RetryPrimitiveFn<T extends (...args: any[]) => any> extends RetryPrimi
161
161
  //#endregion
162
162
  //#region ../../src/retry/index.d.ts
163
163
  /**
164
- * Retry mechanism provider for Alepha applications.
164
+ * | type | quality | stability |
165
+ * |------|---------|-----------|
166
+ * | backend | standard | stable |
167
+ *
168
+ * Automatic retry with backoff.
169
+ *
170
+ * **Features:**
171
+ * - Retry configuration
172
+ * - Exponential backoff
173
+ * - Max retry limits
174
+ * - Custom retry predicates
165
175
  *
166
- * @see {@link RetryProvider}
167
176
  * @module alepha.retry
168
177
  */
169
178
  declare const AlephaRetry: alepha0.Service<alepha0.Module>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/retry/errors/RetryCancelError.ts","../../src/retry/errors/RetryTimeoutError.ts","../../src/retry/providers/RetryProvider.ts","../../src/retry/primitives/$retry.ts","../../src/retry/index.ts"],"mappings":";;;;;;cAEa,gBAAA,SAAyB,WAAA;EAAA,YAAA;AAAA;;;cCAzB,iBAAA,SAA0B,WAAA;EAAA,YAAA,QAAA;AAAA;;;UCItB,YAAA,eAAA,IAAA;EAAA;;;EAAA,OAAA,EAIN,CAAA;EAAA;;;;;EAAA,GAAA;EAAA;;;;;;EAAA,OAAA,YAeU,mBAAA;EAAA;;;;;EAAA,WAAA,GAOL,YAAA;EAAA;;;;;EAAA,IAAA,IAAA,KAAA,EAOC,KAAA;EAAA;;;;EAAA,OAAA,IAAA,KAAA,EAMG,KAAA,EAAA,OAAA,aAAA,IAAA,EAAiC,UAAA,CAAW,CAAA;EAAA;;;EAAA,MAAA,GAKrD,WAAA;EAAA;;;AASX;EATW,gBAAA,GAMU,WAAA;AAAA;AAAA,UAGJ,mBAAA;EAAA;AAgCjB;;;;EAhCiB,OAAA;EAAA;AAgCjB;;;;EAhCiB,MAAA;EAAA;AAgCjB;;EAhCiB,GAAA;EAAA;AAgCjB;;;;EAhCiB,MAAA;AAAA;AAAA;AAgCjB;;;AAhCiB,cAgCJ,aAAA;EAAA,mBAAA,GAAA,EAAa,cAAA,CACF,MAAA;EAAA,mBAAA,QAAA,EACK,gBAAA;EAAA;;;EAAA,KAAA,eAAA,IAAA,gBAAA,CAAA,OAAA,EAMhB,YAAA,CAAa,CAAA,MAAA,IAAA,EACb,UAAA,CAAW,CAAA,IACnB,OAAA,CAAQ,UAAA,CAAW,CAAA;EAAA;;;EAAA,UAAA,iBAAA,OAAA,UAAA,OAAA,YAgHD,mBAAA;AAAA;;;;ACtMvB;;;cAAa,MAAA;EAAA,eAAA,IAAA,iBAAA,OAAA,EACF,qBAAA,CAAsB,CAAA,IAC9B,gBAAA,CAAiB,CAAA;EAAA;;UAQH,qBAAA,eAAA,IAAA;EAAA;;;EAAA,OAAA,EAIN,CAAA;EAAA;;;;;EAAA,GAAA;EAAA;;;;;;EAAA,OAAA,YAeU,mBAAA;EAAA;;;;;EAAA,WAAA,GAOL,YAAA;EAAA;;;;;EAAA,IAAA,IAAA,KAAA,EAOC,KAAA;EAAA;;;;EAAA,OAAA,IAAA,KAAA,EAMG,KAAA,EAAA,OAAA,aAAA,IAAA,EAAiC,UAAA,CAAW,CAAA;EAAA;;;EAAA,MAAA,GAKrD,WAAA;AAAA;AAAA,cAKE,cAAA,eAAA,IAAA,yBAEH,SAAA,CAAU,qBAAA,CAAsB,CAAA;EAAA,mBAAA,aAAA,EACR,aAAA;EAAA,UAAA,kBAAA,GACD,eAAA;EAAA,YAAA,IAAA,EAEb,aAAA,CAAc,qBAAA,CAAsB,CAAA;EAAA,IAAA,GAAA,IAAA,EAQnC,UAAA,CAAW,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,CAAA;AAAA;AAAA,UAcvC,gBAAA,eAAA,IAAA,yBACP,cAAA,CAAe,CAAA;EAAA,IAAA,IAAA,EACb,UAAA,CAAW,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,CAAA;AAAA;;;;ACrF/C;;;;;cAAa,WAAA,EAAW,OAAA,CAAA,OAAA,CAItB,OAAA,CAJsB,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/retry/errors/RetryCancelError.ts","../../src/retry/errors/RetryTimeoutError.ts","../../src/retry/providers/RetryProvider.ts","../../src/retry/primitives/$retry.ts","../../src/retry/index.ts"],"mappings":";;;;;;cAEa,gBAAA,SAAyB,WAAA;EAAA,WAAA,CAAA;AAAA;;;cCAzB,iBAAA,SAA0B,WAAA;cACzB,QAAA;AAAA;;;UCGG,YAAA,eAA2B,IAAA;;;;EAI1C,OAAA,EAAS,CAAA;EFRE;;;;;EEeX,GAAA;;;ADfF;;;;ECuBE,OAAA,YAAmB,mBAAA;;;;;;EAOnB,WAAA,GAAc,YAAA;;AA1BhB;;;;EAiCE,IAAA,IAAQ,KAAA,EAAO,KAAA;EAPD;;;;EAad,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,OAAA,aAAoB,IAAA,EAAM,UAAA,CAAW,CAAA;EAKrD;;;EAAT,MAAA,GAAS,WAAA;EA5CmB;;;;EAkD5B,gBAAA,GAAmB,WAAA;AAAA;AAAA,UAGJ,mBAAA;EA3Bf;;;;;EAiCA,OAAA;EApBkB;;;;;EA2BlB,MAAA;EAtBA;;;EA2BA,GAAA;EArB8B;;AAGhC;;;EAyBE,MAAA;AAAA;;;;;cAOW,aAAA;EAAA,mBACQ,GAAA,EADK,cAAA,CACF,MAAA;EAAA,mBACH,QAAA,EAAQ,gBAAA;EAFH;;;EAOlB,KAAA,eAAoB,IAAA,gBAAA,CACxB,OAAA,EAAS,YAAA,CAAa,CAAA,MACnB,IAAA,EAAM,UAAA,CAAW,CAAA,IACnB,OAAA,CAAQ,UAAA,CAAW,CAAA;EAFX;;;EAAA,UAgHD,gBAAA,CACR,OAAA,UACA,OAAA,YAAmB,mBAAA;AAAA;;;;;AFnNvB;;cGaa,MAAA;EAAA,eAAwB,IAAA,iBAAmB,OAAA,EAC7C,qBAAA,CAAsB,CAAA,IAC9B,gBAAA,CAAiB,CAAA;EAAA;;UAQH,qBAAA,eAAoC,IAAA;;AFvBrD;;EE2BE,OAAA,EAAS,CAAA;EF3BuC;;;;;EEkChD,GAAA;;;;AD9BF;;;ECsCE,OAAA,YAAmB,mBAAA;EDnBA;;;;;EC0BnB,WAAA,GAAc,YAAA;EDDL;;;;;ECQT,IAAA,IAAQ,KAAA,EAAO,KAAA;EDhDf;;;;ECsDA,OAAA,IAAW,KAAA,EAAO,KAAA,EAAO,OAAA,aAAoB,IAAA,EAAM,UAAA,CAAW,CAAA;EDhC9D;;;ECqCA,MAAA,GAAS,WAAA;AAAA;AAAA,cAKE,cAAA,eACG,IAAA,yBACN,SAAA,CAAU,qBAAA,CAAsB,CAAA;EAAA,mBACrB,aAAA,EAAa,aAAA;EAAA,UACtB,kBAAA,GAAqB,eAAA;cAEnB,IAAA,EAAM,aAAA,CAAc,qBAAA,CAAsB,CAAA;EAQhD,GAAA,CAAA,GAAO,IAAA,EAAM,UAAA,CAAW,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,CAAA;AAAA;AAAA,UAcvC,gBAAA,eAA+B,IAAA,yBACtC,cAAA,CAAe,CAAA;EAAA,IACnB,IAAA,EAAM,UAAA,CAAW,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,CAAA;AAAA;;;;;AHtG/C;;;;;;;;ACAA;;;;;cG0Ba,WAAA,EAAW,OAAA,CAAA,OAAA,CAItB,OAAA,CAJsB,MAAA"}
@@ -125,9 +125,18 @@ $retry[KIND] = RetryPrimitive;
125
125
  //#endregion
126
126
  //#region ../../src/retry/index.ts
127
127
  /**
128
- * Retry mechanism provider for Alepha applications.
128
+ * | type | quality | stability |
129
+ * |------|---------|-----------|
130
+ * | backend | standard | stable |
131
+ *
132
+ * Automatic retry with backoff.
133
+ *
134
+ * **Features:**
135
+ * - Retry configuration
136
+ * - Exponential backoff
137
+ * - Max retry limits
138
+ * - Custom retry predicates
129
139
  *
130
- * @see {@link RetryProvider}
131
140
  * @module alepha.retry
132
141
  */
133
142
  const AlephaRetry = $module({
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/retry/errors/RetryCancelError.ts","../../src/retry/errors/RetryTimeoutError.ts","../../src/retry/providers/RetryProvider.ts","../../src/retry/primitives/$retry.ts","../../src/retry/index.ts"],"sourcesContent":["import { AlephaError } from \"alepha\";\n\nexport class RetryCancelError extends AlephaError {\n constructor() {\n super(\"Retry operation was cancelled.\");\n this.name = \"RetryCancelError\";\n }\n}\n","import { AlephaError } from \"alepha\";\n\nexport class RetryTimeoutError extends AlephaError {\n constructor(duration: number) {\n super(`Retry operation timed out after ${duration}ms.`);\n this.name = \"RetryTimeoutError\";\n }\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider, type DurationLike } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { RetryCancelError } from \"../errors/RetryCancelError.ts\";\nimport { RetryTimeoutError } from \"../errors/RetryTimeoutError.ts\";\n\nexport interface RetryOptions<T extends (...args: any[]) => any> {\n /**\n * The function to retry.\n */\n handler: T;\n\n /**\n * The maximum number of attempts.\n *\n * @default 3\n */\n max?: number;\n\n /**\n * The backoff strategy for delays between retries.\n * Can be a fixed number (in ms) or a configuration object for exponential backoff.\n *\n * @default { initial: 200, factor: 2, jitter: true }\n */\n backoff?: number | RetryBackoffOptions;\n\n /**\n * An overall time limit for all retry attempts combined.\n *\n * e.g., `[5, 'seconds']`\n */\n maxDuration?: DurationLike;\n\n /**\n * A function that determines if a retry should be attempted based on the error.\n *\n * @default (error) => true (retries on any error)\n */\n when?: (error: Error) => boolean;\n\n /**\n * A custom callback for when a retry attempt fails.\n * This is called before the delay.\n */\n onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;\n\n /**\n * An AbortSignal to allow for external cancellation of the retry loop.\n */\n signal?: AbortSignal;\n\n /**\n * An additional AbortSignal to combine with the provided signal.\n * Used internally by $retry to handle app lifecycle.\n */\n additionalSignal?: AbortSignal;\n}\n\nexport interface RetryBackoffOptions {\n /**\n * Initial delay in milliseconds.\n *\n * @default 200\n */\n initial?: number;\n\n /**\n * Multiplier for each subsequent delay.\n *\n * @default 2\n */\n factor?: number;\n\n /**\n * Maximum delay in milliseconds.\n */\n max?: number;\n\n /**\n * If true, adds a random jitter to the delay to prevent thundering herd.\n *\n * @default true\n */\n jitter?: boolean;\n}\n\n/**\n * Service for executing functions with automatic retry logic.\n * Supports exponential backoff, max duration, conditional retries, and cancellation.\n */\nexport class RetryProvider {\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n\n /**\n * Execute a function with automatic retry logic.\n */\n async retry<T extends (...args: any[]) => any>(\n options: RetryOptions<T>,\n ...args: Parameters<T>\n ): Promise<ReturnType<T>> {\n const maxAttempts = options.max ?? 3;\n const when = options.when ?? (() => true);\n const { handler, onError } = options;\n\n let lastError: Error | undefined;\n const startTime = Date.now();\n\n const maxDurationMs = options.maxDuration\n ? this.dateTime.duration(options.maxDuration).asMilliseconds()\n : Infinity;\n\n // Combine user-provided signal with additional signal (e.g., app lifecycle)\n const signals = [options.signal, options.additionalSignal].filter(Boolean);\n const onAbort = () => {\n // Always set RetryCancelError when aborted, even if another error exists\n // This ensures cancellation takes precedence over retry errors\n lastError = new RetryCancelError();\n };\n\n // Add abort listeners to all signals\n for (const signal of signals) {\n signal?.addEventListener(\"abort\", onAbort);\n }\n\n // FIX BUG #8: Create combined signal ONCE at the start instead of on each backoff\n // This prevents memory leak from creating multiple AbortSignal.any() instances\n const waitSignals = [options.signal, options.additionalSignal].filter(\n Boolean,\n ) as AbortSignal[];\n const combinedSignal =\n waitSignals.length > 0 ? AbortSignal.any(waitSignals) : undefined;\n\n try {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n // Check for cancellation\n if (signals.some((signal) => signal?.aborted)) {\n throw new RetryCancelError();\n }\n\n // Check for timeout before attempting\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n try {\n const result = await handler(...args);\n\n // Check for timeout after handler execution\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n return result;\n } catch (err) {\n lastError = err as Error;\n\n // Check for timeout after error\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n // Log the error with warning level\n this.log.warn(\"Retry attempt failed\", {\n attempt,\n maxAttempts,\n remainingAttempts: maxAttempts - attempt,\n error: lastError.message,\n errorName: lastError.name,\n });\n\n if (!(err instanceof Error) || !when(err)) {\n throw err; // don't retry if it's not an Error or `when` returns false\n }\n\n // FIX BUG #7: Call onError BEFORE checking if this is the final attempt\n // This ensures onError is called for ALL failed attempts, including the last one\n if (onError) {\n onError(err, attempt, ...args);\n }\n\n if (attempt >= maxAttempts) {\n break; // will throw lastError after the loop\n }\n\n // Calculate and wait for backoff delay\n const delay = this.calculateBackoff(attempt, options.backoff);\n if (delay > 0) {\n await this.dateTime.wait(delay, { signal: combinedSignal });\n }\n\n // Check for timeout after backoff wait before next attempt\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n }\n }\n } finally {\n // Clean up listeners to prevent memory leaks\n for (const signal of signals) {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n throw lastError;\n }\n\n /**\n * Calculate the backoff delay for a given attempt.\n */\n protected calculateBackoff(\n attempt: number,\n options?: number | RetryBackoffOptions,\n ): number {\n if (typeof options === \"number\") {\n return options;\n }\n\n const initial = options?.initial ?? 200;\n const factor = options?.factor ?? 2;\n const max = options?.max ?? 10000;\n const useJitter = options?.jitter !== false;\n\n const exponential = initial * factor ** (attempt - 1);\n let delay = Math.min(exponential, max);\n\n if (useJitter) {\n // Add a random amount of jitter (e.g., up to 50% of the delay)\n delay = delay * (1 + Math.random() * 0.5);\n }\n\n return Math.floor(delay);\n }\n}\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type PrimitiveArgs,\n} from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport type { RetryBackoffOptions } from \"../providers/RetryProvider.ts\";\nimport { RetryProvider } from \"../providers/RetryProvider.ts\";\n\n/**\n * Creates a function that automatically retries a handler upon failure,\n * with support for exponential backoff, max duration, and cancellation.\n */\nexport const $retry = <T extends (...args: any[]) => any>(\n options: RetryPrimitiveOptions<T>,\n): RetryPrimitiveFn<T> => {\n const instance = createPrimitive(RetryPrimitive, options);\n const fn = (...args: Parameters<T>) => instance.run(...args);\n return Object.setPrototypeOf(fn, instance) as RetryPrimitiveFn<T>;\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface RetryPrimitiveOptions<T extends (...args: any[]) => any> {\n /**\n * The function to retry.\n */\n handler: T;\n\n /**\n * The maximum number of attempts.\n *\n * @default 3\n */\n max?: number;\n\n /**\n * The backoff strategy for delays between retries.\n * Can be a fixed number (in ms) or a configuration object for exponential backoff.\n *\n * @default { initial: 200, factor: 2, jitter: true }\n */\n backoff?: number | RetryBackoffOptions;\n\n /**\n * An overall time limit for all retry attempts combined.\n *\n * e.g., `[5, 'seconds']`\n */\n maxDuration?: DurationLike;\n\n /**\n * A function that determines if a retry should be attempted based on the error.\n *\n * @default (error) => true (retries on any error)\n */\n when?: (error: Error) => boolean;\n\n /**\n * A custom callback for when a retry attempt fails.\n * This is called before the delay.\n */\n onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;\n\n /**\n * An AbortSignal to allow for external cancellation of the retry loop.\n */\n signal?: AbortSignal;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class RetryPrimitive<\n T extends (...args: any[]) => any,\n> extends Primitive<RetryPrimitiveOptions<T>> {\n protected readonly retryProvider = $inject(RetryProvider);\n protected appAbortController?: AbortController;\n\n constructor(args: PrimitiveArgs<RetryPrimitiveOptions<T>>) {\n super(args);\n\n this.alepha.events.on(\"stop\", () => {\n this.appAbortController?.abort();\n });\n }\n\n async run(...args: Parameters<T>): Promise<ReturnType<T>> {\n // Nov 25: Cloudflare does not like 'new AbortController' outside main handler, we can't pre-create it in the constructor.\n this.appAbortController ??= new AbortController();\n\n return this.retryProvider.retry(\n {\n ...this.options,\n additionalSignal: this.appAbortController.signal,\n },\n ...args,\n );\n }\n}\n\nexport interface RetryPrimitiveFn<T extends (...args: any[]) => any>\n extends RetryPrimitive<T> {\n (...args: Parameters<T>): Promise<ReturnType<T>>;\n}\n\n$retry[KIND] = RetryPrimitive;\n","import { $module } from \"alepha\";\nimport { $retry } from \"./primitives/$retry.ts\";\nimport { RetryProvider } from \"./providers/RetryProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./errors/RetryCancelError.ts\";\nexport * from \"./errors/RetryTimeoutError.ts\";\nexport * from \"./primitives/$retry.ts\";\nexport * from \"./providers/RetryProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Retry mechanism provider for Alepha applications.\n *\n * @see {@link RetryProvider}\n * @module alepha.retry\n */\nexport const AlephaRetry = $module({\n name: \"alepha.retry\",\n primitives: [$retry],\n services: [RetryProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/retry/errors/RetryCancelError.ts","../../src/retry/errors/RetryTimeoutError.ts","../../src/retry/providers/RetryProvider.ts","../../src/retry/primitives/$retry.ts","../../src/retry/index.ts"],"sourcesContent":["import { AlephaError } from \"alepha\";\n\nexport class RetryCancelError extends AlephaError {\n constructor() {\n super(\"Retry operation was cancelled.\");\n this.name = \"RetryCancelError\";\n }\n}\n","import { AlephaError } from \"alepha\";\n\nexport class RetryTimeoutError extends AlephaError {\n constructor(duration: number) {\n super(`Retry operation timed out after ${duration}ms.`);\n this.name = \"RetryTimeoutError\";\n }\n}\n","import { $inject } from \"alepha\";\nimport { DateTimeProvider, type DurationLike } from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { RetryCancelError } from \"../errors/RetryCancelError.ts\";\nimport { RetryTimeoutError } from \"../errors/RetryTimeoutError.ts\";\n\nexport interface RetryOptions<T extends (...args: any[]) => any> {\n /**\n * The function to retry.\n */\n handler: T;\n\n /**\n * The maximum number of attempts.\n *\n * @default 3\n */\n max?: number;\n\n /**\n * The backoff strategy for delays between retries.\n * Can be a fixed number (in ms) or a configuration object for exponential backoff.\n *\n * @default { initial: 200, factor: 2, jitter: true }\n */\n backoff?: number | RetryBackoffOptions;\n\n /**\n * An overall time limit for all retry attempts combined.\n *\n * e.g., `[5, 'seconds']`\n */\n maxDuration?: DurationLike;\n\n /**\n * A function that determines if a retry should be attempted based on the error.\n *\n * @default (error) => true (retries on any error)\n */\n when?: (error: Error) => boolean;\n\n /**\n * A custom callback for when a retry attempt fails.\n * This is called before the delay.\n */\n onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;\n\n /**\n * An AbortSignal to allow for external cancellation of the retry loop.\n */\n signal?: AbortSignal;\n\n /**\n * An additional AbortSignal to combine with the provided signal.\n * Used internally by $retry to handle app lifecycle.\n */\n additionalSignal?: AbortSignal;\n}\n\nexport interface RetryBackoffOptions {\n /**\n * Initial delay in milliseconds.\n *\n * @default 200\n */\n initial?: number;\n\n /**\n * Multiplier for each subsequent delay.\n *\n * @default 2\n */\n factor?: number;\n\n /**\n * Maximum delay in milliseconds.\n */\n max?: number;\n\n /**\n * If true, adds a random jitter to the delay to prevent thundering herd.\n *\n * @default true\n */\n jitter?: boolean;\n}\n\n/**\n * Service for executing functions with automatic retry logic.\n * Supports exponential backoff, max duration, conditional retries, and cancellation.\n */\nexport class RetryProvider {\n protected readonly log = $logger();\n protected readonly dateTime = $inject(DateTimeProvider);\n\n /**\n * Execute a function with automatic retry logic.\n */\n async retry<T extends (...args: any[]) => any>(\n options: RetryOptions<T>,\n ...args: Parameters<T>\n ): Promise<ReturnType<T>> {\n const maxAttempts = options.max ?? 3;\n const when = options.when ?? (() => true);\n const { handler, onError } = options;\n\n let lastError: Error | undefined;\n const startTime = Date.now();\n\n const maxDurationMs = options.maxDuration\n ? this.dateTime.duration(options.maxDuration).asMilliseconds()\n : Infinity;\n\n // Combine user-provided signal with additional signal (e.g., app lifecycle)\n const signals = [options.signal, options.additionalSignal].filter(Boolean);\n const onAbort = () => {\n // Always set RetryCancelError when aborted, even if another error exists\n // This ensures cancellation takes precedence over retry errors\n lastError = new RetryCancelError();\n };\n\n // Add abort listeners to all signals\n for (const signal of signals) {\n signal?.addEventListener(\"abort\", onAbort);\n }\n\n // FIX BUG #8: Create combined signal ONCE at the start instead of on each backoff\n // This prevents memory leak from creating multiple AbortSignal.any() instances\n const waitSignals = [options.signal, options.additionalSignal].filter(\n Boolean,\n ) as AbortSignal[];\n const combinedSignal =\n waitSignals.length > 0 ? AbortSignal.any(waitSignals) : undefined;\n\n try {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n // Check for cancellation\n if (signals.some((signal) => signal?.aborted)) {\n throw new RetryCancelError();\n }\n\n // Check for timeout before attempting\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n try {\n const result = await handler(...args);\n\n // Check for timeout after handler execution\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n return result;\n } catch (err) {\n lastError = err as Error;\n\n // Check for timeout after error\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n\n // Log the error with warning level\n this.log.warn(\"Retry attempt failed\", {\n attempt,\n maxAttempts,\n remainingAttempts: maxAttempts - attempt,\n error: lastError.message,\n errorName: lastError.name,\n });\n\n if (!(err instanceof Error) || !when(err)) {\n throw err; // don't retry if it's not an Error or `when` returns false\n }\n\n // FIX BUG #7: Call onError BEFORE checking if this is the final attempt\n // This ensures onError is called for ALL failed attempts, including the last one\n if (onError) {\n onError(err, attempt, ...args);\n }\n\n if (attempt >= maxAttempts) {\n break; // will throw lastError after the loop\n }\n\n // Calculate and wait for backoff delay\n const delay = this.calculateBackoff(attempt, options.backoff);\n if (delay > 0) {\n await this.dateTime.wait(delay, { signal: combinedSignal });\n }\n\n // Check for timeout after backoff wait before next attempt\n if (Date.now() - startTime >= maxDurationMs) {\n throw new RetryTimeoutError(maxDurationMs);\n }\n }\n }\n } finally {\n // Clean up listeners to prevent memory leaks\n for (const signal of signals) {\n signal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n throw lastError;\n }\n\n /**\n * Calculate the backoff delay for a given attempt.\n */\n protected calculateBackoff(\n attempt: number,\n options?: number | RetryBackoffOptions,\n ): number {\n if (typeof options === \"number\") {\n return options;\n }\n\n const initial = options?.initial ?? 200;\n const factor = options?.factor ?? 2;\n const max = options?.max ?? 10000;\n const useJitter = options?.jitter !== false;\n\n const exponential = initial * factor ** (attempt - 1);\n let delay = Math.min(exponential, max);\n\n if (useJitter) {\n // Add a random amount of jitter (e.g., up to 50% of the delay)\n delay = delay * (1 + Math.random() * 0.5);\n }\n\n return Math.floor(delay);\n }\n}\n","import {\n $inject,\n createPrimitive,\n KIND,\n Primitive,\n type PrimitiveArgs,\n} from \"alepha\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport type { RetryBackoffOptions } from \"../providers/RetryProvider.ts\";\nimport { RetryProvider } from \"../providers/RetryProvider.ts\";\n\n/**\n * Creates a function that automatically retries a handler upon failure,\n * with support for exponential backoff, max duration, and cancellation.\n */\nexport const $retry = <T extends (...args: any[]) => any>(\n options: RetryPrimitiveOptions<T>,\n): RetryPrimitiveFn<T> => {\n const instance = createPrimitive(RetryPrimitive, options);\n const fn = (...args: Parameters<T>) => instance.run(...args);\n return Object.setPrototypeOf(fn, instance) as RetryPrimitiveFn<T>;\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface RetryPrimitiveOptions<T extends (...args: any[]) => any> {\n /**\n * The function to retry.\n */\n handler: T;\n\n /**\n * The maximum number of attempts.\n *\n * @default 3\n */\n max?: number;\n\n /**\n * The backoff strategy for delays between retries.\n * Can be a fixed number (in ms) or a configuration object for exponential backoff.\n *\n * @default { initial: 200, factor: 2, jitter: true }\n */\n backoff?: number | RetryBackoffOptions;\n\n /**\n * An overall time limit for all retry attempts combined.\n *\n * e.g., `[5, 'seconds']`\n */\n maxDuration?: DurationLike;\n\n /**\n * A function that determines if a retry should be attempted based on the error.\n *\n * @default (error) => true (retries on any error)\n */\n when?: (error: Error) => boolean;\n\n /**\n * A custom callback for when a retry attempt fails.\n * This is called before the delay.\n */\n onError?: (error: Error, attempt: number, ...args: Parameters<T>) => void;\n\n /**\n * An AbortSignal to allow for external cancellation of the retry loop.\n */\n signal?: AbortSignal;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class RetryPrimitive<\n T extends (...args: any[]) => any,\n> extends Primitive<RetryPrimitiveOptions<T>> {\n protected readonly retryProvider = $inject(RetryProvider);\n protected appAbortController?: AbortController;\n\n constructor(args: PrimitiveArgs<RetryPrimitiveOptions<T>>) {\n super(args);\n\n this.alepha.events.on(\"stop\", () => {\n this.appAbortController?.abort();\n });\n }\n\n async run(...args: Parameters<T>): Promise<ReturnType<T>> {\n // Nov 25: Cloudflare does not like 'new AbortController' outside main handler, we can't pre-create it in the constructor.\n this.appAbortController ??= new AbortController();\n\n return this.retryProvider.retry(\n {\n ...this.options,\n additionalSignal: this.appAbortController.signal,\n },\n ...args,\n );\n }\n}\n\nexport interface RetryPrimitiveFn<T extends (...args: any[]) => any>\n extends RetryPrimitive<T> {\n (...args: Parameters<T>): Promise<ReturnType<T>>;\n}\n\n$retry[KIND] = RetryPrimitive;\n","import { $module } from \"alepha\";\nimport { $retry } from \"./primitives/$retry.ts\";\nimport { RetryProvider } from \"./providers/RetryProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./errors/RetryCancelError.ts\";\nexport * from \"./errors/RetryTimeoutError.ts\";\nexport * from \"./primitives/$retry.ts\";\nexport * from \"./providers/RetryProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * | type | quality | stability |\n * |------|---------|-----------|\n * | backend | standard | stable |\n *\n * Automatic retry with backoff.\n *\n * **Features:**\n * - Retry configuration\n * - Exponential backoff\n * - Max retry limits\n * - Custom retry predicates\n *\n * @module alepha.retry\n */\nexport const AlephaRetry = $module({\n name: \"alepha.retry\",\n primitives: [$retry],\n services: [RetryProvider],\n});\n"],"mappings":"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"}
@@ -17,12 +17,12 @@ interface RouteMatch<T extends Route> {
17
17
  interface Route {
18
18
  path: string;
19
19
  /**
20
- * Rename a param in the route.
21
- * This is automatically filled when you have scenarios like:
22
- * `/customers/:id` and `/customers/:userId/payments`
23
- *
24
- * In this case, `:id` will be renamed to `:userId` in the second route.
25
- */
20
+ * Rename a param in the route.
21
+ * This is automatically filled when you have scenarios like:
22
+ * `/customers/:id` and `/customers/:userId/payments`
23
+ *
24
+ * In this case, `:id` will be renamed to `:userId` in the second route.
25
+ */
26
26
  mapParams?: Record<string, string>;
27
27
  }
28
28
  interface Tree<T extends Route> {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/router/providers/RouterProvider.ts"],"mappings":";uBAEsB,cAAA,WAAyB,KAAA,GAAQ,KAAA;EAAA,UAAA,cAAA,EAC3B,MAAA;EAAA,UAAA,IAAA,EAEV,IAAA,CAAK,CAAA;EAAA,UAAA,KAAA,EACN,GAAA,SAAA,UAAA,CAAA,CAAA;EAAA,MAAA,IAAA,WAEa,UAAA,CAAW,CAAA;EAAA,UAAA,KAAA,IAAA;EAAA,UAAA,KAAA,KAAA,EAejB,CAAA;EAAA,UAAA,iBAAA,IAAA,WA8DoB,UAAA,CAAW,CAAA;EAAA,UAAA,UAAA,KAAA,EA4C1B,UAAA,CAAW,CAAA,IAAK,UAAA,CAAW,CAAA;EAAA,UAAA,YAAA,IAAA;AAAA;AAAA,UAyBvC,UAAA,WAAqB,KAAA;EAAA,KAAA,GAC5B,CAAA;EAAA,MAAA,GACC,MAAA;AAAA;AAAA,UAGM,KAAA;EAAA,IAAA;EAAA;AAajB;;;;;;EAbiB,SAAA,GAUH,MAAA;AAAA;AAAA,UAGG,IAAA,WAAe,KAAA;EAAA,KAAA,GACtB,CAAA;EAAA,QAAA;IAAA,CAAA,GAAA,WAES,IAAA,CAAK,CAAA;EAAA;EAAA,KAAA;IAAA,KAAA,GAGZ,CAAA;IAAA,IAAA;IAAA,QAAA;MAAA,CAAA,GAAA,WAGS,IAAA,CAAK,CAAA;IAAA;EAAA;EAAA,QAAA;IAAA,KAAA,EAIf,CAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/router/providers/RouterProvider.ts"],"mappings":";uBAEsB,cAAA,WAAyB,KAAA,GAAQ,KAAA;EAAA,UAC3C,cAAA,EAAgB,MAAA;EAAA,UAEhB,IAAA,EAAM,IAAA,CAAK,CAAA;EAAA,UACX,KAAA,EAAK,GAAA,SAAA,UAAA,CAAA,CAAA;EAER,KAAA,CAAM,IAAA,WAAe,UAAA,CAAW,CAAA;EAAA,UAS7B,IAAA,CAAK,IAAA;EAAA,UAML,IAAA,CAAK,KAAA,EAAO,CAAA;EAAA,UA8DZ,gBAAA,CAAiB,IAAA,WAAe,UAAA,CAAW,CAAA;EAAA,UA4C3C,SAAA,CAAU,KAAA,EAAO,UAAA,CAAW,CAAA,IAAK,UAAA,CAAW,CAAA;EAAA,UAa5C,WAAA,CAAY,IAAA;AAAA;AAAA,UAYP,UAAA,WAAqB,KAAA;EACpC,KAAA,GAAQ,CAAA;EACR,MAAA,GAAS,MAAA;AAAA;AAAA,UAGM,KAAA;EACf,IAAA;EA/BsC;;;;;;;EAwCtC,SAAA,GAAY,MAAA;AAAA;AAAA,UAGG,IAAA,WAAe,KAAA;EAC9B,KAAA,GAAQ,CAAA;EACR,QAAA;IAAA,CACG,GAAA,WAAc,IAAA,CAAK,CAAA;EAAA;EAEtB,KAAA;IACE,KAAA,GAAQ,CAAA;IACR,IAAA;IACA,QAAA;MAAA,CACG,GAAA,WAAc,IAAA,CAAK,CAAA;IAAA;EAAA;EAGxB,QAAA;IACE,KAAA,EAAO,CAAA;EAAA;AAAA"}