alepha 0.14.4 → 0.15.1

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 (322) hide show
  1. package/README.md +44 -102
  2. package/dist/api/audits/index.d.ts +331 -443
  3. package/dist/api/audits/index.d.ts.map +1 -1
  4. package/dist/api/audits/index.js +2 -2
  5. package/dist/api/audits/index.js.map +1 -1
  6. package/dist/api/files/index.d.ts +0 -113
  7. package/dist/api/files/index.d.ts.map +1 -1
  8. package/dist/api/files/index.js +2 -3
  9. package/dist/api/files/index.js.map +1 -1
  10. package/dist/api/jobs/index.d.ts +151 -262
  11. package/dist/api/jobs/index.d.ts.map +1 -1
  12. package/dist/api/notifications/index.browser.js +4 -4
  13. package/dist/api/notifications/index.browser.js.map +1 -1
  14. package/dist/api/notifications/index.d.ts +164 -276
  15. package/dist/api/notifications/index.d.ts.map +1 -1
  16. package/dist/api/notifications/index.js +4 -4
  17. package/dist/api/notifications/index.js.map +1 -1
  18. package/dist/api/parameters/index.d.ts +265 -377
  19. package/dist/api/parameters/index.d.ts.map +1 -1
  20. package/dist/api/users/index.browser.js +1 -2
  21. package/dist/api/users/index.browser.js.map +1 -1
  22. package/dist/api/users/index.d.ts +195 -301
  23. package/dist/api/users/index.d.ts.map +1 -1
  24. package/dist/api/users/index.js +203 -184
  25. package/dist/api/users/index.js.map +1 -1
  26. package/dist/api/verifications/index.d.ts.map +1 -1
  27. package/dist/batch/index.d.ts.map +1 -1
  28. package/dist/batch/index.js +1 -2
  29. package/dist/batch/index.js.map +1 -1
  30. package/dist/bucket/index.d.ts.map +1 -1
  31. package/dist/cache/core/index.d.ts.map +1 -1
  32. package/dist/cache/redis/index.d.ts.map +1 -1
  33. package/dist/cache/redis/index.js +2 -2
  34. package/dist/cache/redis/index.js.map +1 -1
  35. package/dist/cli/index.d.ts +5900 -165
  36. package/dist/cli/index.d.ts.map +1 -1
  37. package/dist/cli/index.js +1481 -639
  38. package/dist/cli/index.js.map +1 -1
  39. package/dist/command/index.d.ts +8 -4
  40. package/dist/command/index.d.ts.map +1 -1
  41. package/dist/command/index.js +29 -25
  42. package/dist/command/index.js.map +1 -1
  43. package/dist/core/index.browser.js +563 -54
  44. package/dist/core/index.browser.js.map +1 -1
  45. package/dist/core/index.d.ts +175 -8
  46. package/dist/core/index.d.ts.map +1 -1
  47. package/dist/core/index.js +564 -54
  48. package/dist/core/index.js.map +1 -1
  49. package/dist/core/index.native.js +563 -54
  50. package/dist/core/index.native.js.map +1 -1
  51. package/dist/datetime/index.d.ts.map +1 -1
  52. package/dist/datetime/index.js +4 -4
  53. package/dist/datetime/index.js.map +1 -1
  54. package/dist/email/index.d.ts +89 -42
  55. package/dist/email/index.d.ts.map +1 -1
  56. package/dist/email/index.js +129 -33
  57. package/dist/email/index.js.map +1 -1
  58. package/dist/fake/index.d.ts +7969 -2
  59. package/dist/fake/index.d.ts.map +1 -1
  60. package/dist/fake/index.js +22 -22
  61. package/dist/fake/index.js.map +1 -1
  62. package/dist/file/index.d.ts +134 -1
  63. package/dist/file/index.d.ts.map +1 -1
  64. package/dist/file/index.js +253 -1
  65. package/dist/file/index.js.map +1 -1
  66. package/dist/lock/core/index.d.ts.map +1 -1
  67. package/dist/lock/redis/index.d.ts.map +1 -1
  68. package/dist/logger/index.d.ts +1 -2
  69. package/dist/logger/index.d.ts.map +1 -1
  70. package/dist/logger/index.js +1 -5
  71. package/dist/logger/index.js.map +1 -1
  72. package/dist/mcp/index.d.ts +19 -1
  73. package/dist/mcp/index.d.ts.map +1 -1
  74. package/dist/mcp/index.js +28 -4
  75. package/dist/mcp/index.js.map +1 -1
  76. package/dist/orm/chunk-DH6iiROE.js +38 -0
  77. package/dist/orm/index.browser.js +9 -9
  78. package/dist/orm/index.browser.js.map +1 -1
  79. package/dist/orm/index.bun.js +2821 -0
  80. package/dist/orm/index.bun.js.map +1 -0
  81. package/dist/orm/index.d.ts +318 -169
  82. package/dist/orm/index.d.ts.map +1 -1
  83. package/dist/orm/index.js +2086 -1776
  84. package/dist/orm/index.js.map +1 -1
  85. package/dist/queue/core/index.d.ts +4 -4
  86. package/dist/queue/core/index.d.ts.map +1 -1
  87. package/dist/queue/redis/index.d.ts.map +1 -1
  88. package/dist/redis/index.bun.js +285 -0
  89. package/dist/redis/index.bun.js.map +1 -0
  90. package/dist/redis/index.d.ts +13 -31
  91. package/dist/redis/index.d.ts.map +1 -1
  92. package/dist/redis/index.js +18 -38
  93. package/dist/redis/index.js.map +1 -1
  94. package/dist/retry/index.d.ts.map +1 -1
  95. package/dist/router/index.d.ts.map +1 -1
  96. package/dist/scheduler/index.d.ts +83 -1
  97. package/dist/scheduler/index.d.ts.map +1 -1
  98. package/dist/scheduler/index.js +393 -1
  99. package/dist/scheduler/index.js.map +1 -1
  100. package/dist/security/index.browser.js +5 -1
  101. package/dist/security/index.browser.js.map +1 -1
  102. package/dist/security/index.d.ts +598 -112
  103. package/dist/security/index.d.ts.map +1 -1
  104. package/dist/security/index.js +1808 -97
  105. package/dist/security/index.js.map +1 -1
  106. package/dist/server/auth/index.d.ts +1200 -175
  107. package/dist/server/auth/index.d.ts.map +1 -1
  108. package/dist/server/auth/index.js +1268 -37
  109. package/dist/server/auth/index.js.map +1 -1
  110. package/dist/server/cache/index.d.ts +6 -3
  111. package/dist/server/cache/index.d.ts.map +1 -1
  112. package/dist/server/cache/index.js +1 -1
  113. package/dist/server/cache/index.js.map +1 -1
  114. package/dist/server/compress/index.d.ts.map +1 -1
  115. package/dist/server/cookies/index.d.ts.map +1 -1
  116. package/dist/server/cookies/index.js +3 -3
  117. package/dist/server/cookies/index.js.map +1 -1
  118. package/dist/server/core/index.d.ts +115 -13
  119. package/dist/server/core/index.d.ts.map +1 -1
  120. package/dist/server/core/index.js +321 -139
  121. package/dist/server/core/index.js.map +1 -1
  122. package/dist/server/cors/index.d.ts +0 -1
  123. package/dist/server/cors/index.d.ts.map +1 -1
  124. package/dist/server/health/index.d.ts +0 -1
  125. package/dist/server/health/index.d.ts.map +1 -1
  126. package/dist/server/helmet/index.d.ts.map +1 -1
  127. package/dist/server/links/index.browser.js +9 -1
  128. package/dist/server/links/index.browser.js.map +1 -1
  129. package/dist/server/links/index.d.ts +1 -2
  130. package/dist/server/links/index.d.ts.map +1 -1
  131. package/dist/server/links/index.js +14 -7
  132. package/dist/server/links/index.js.map +1 -1
  133. package/dist/server/metrics/index.d.ts +514 -1
  134. package/dist/server/metrics/index.d.ts.map +1 -1
  135. package/dist/server/metrics/index.js +4462 -4
  136. package/dist/server/metrics/index.js.map +1 -1
  137. package/dist/server/multipart/index.d.ts.map +1 -1
  138. package/dist/server/proxy/index.d.ts +0 -1
  139. package/dist/server/proxy/index.d.ts.map +1 -1
  140. package/dist/server/rate-limit/index.d.ts.map +1 -1
  141. package/dist/server/static/index.d.ts.map +1 -1
  142. package/dist/server/swagger/index.d.ts +1 -2
  143. package/dist/server/swagger/index.d.ts.map +1 -1
  144. package/dist/server/swagger/index.js +1 -2
  145. package/dist/server/swagger/index.js.map +1 -1
  146. package/dist/sms/index.d.ts +3 -1
  147. package/dist/sms/index.d.ts.map +1 -1
  148. package/dist/sms/index.js +10 -10
  149. package/dist/sms/index.js.map +1 -1
  150. package/dist/thread/index.d.ts +0 -1
  151. package/dist/thread/index.d.ts.map +1 -1
  152. package/dist/thread/index.js +2 -2
  153. package/dist/thread/index.js.map +1 -1
  154. package/dist/topic/core/index.d.ts.map +1 -1
  155. package/dist/topic/redis/index.d.ts.map +1 -1
  156. package/dist/vite/index.d.ts +6315 -149
  157. package/dist/vite/index.d.ts.map +1 -1
  158. package/dist/vite/index.js +140 -469
  159. package/dist/vite/index.js.map +1 -1
  160. package/dist/websocket/index.browser.js +9 -9
  161. package/dist/websocket/index.browser.js.map +1 -1
  162. package/dist/websocket/index.d.ts +28 -28
  163. package/dist/websocket/index.d.ts.map +1 -1
  164. package/dist/websocket/index.js +9 -9
  165. package/dist/websocket/index.js.map +1 -1
  166. package/package.json +13 -18
  167. package/src/api/files/controllers/AdminFileStatsController.ts +0 -1
  168. package/src/api/users/atoms/realmAuthSettingsAtom.ts +5 -0
  169. package/src/api/users/controllers/{UserRealmController.ts → RealmController.ts} +11 -11
  170. package/src/api/users/entities/users.ts +1 -1
  171. package/src/api/users/index.ts +8 -8
  172. package/src/api/users/primitives/{$userRealm.ts → $realm.ts} +17 -19
  173. package/src/api/users/providers/{UserRealmProvider.ts → RealmProvider.ts} +26 -30
  174. package/src/api/users/schemas/{userRealmConfigSchema.ts → realmConfigSchema.ts} +2 -2
  175. package/src/api/users/services/CredentialService.ts +7 -7
  176. package/src/api/users/services/IdentityService.ts +4 -4
  177. package/src/api/users/services/RegistrationService.spec.ts +25 -27
  178. package/src/api/users/services/RegistrationService.ts +38 -27
  179. package/src/api/users/services/SessionCrudService.ts +3 -3
  180. package/src/api/users/services/SessionService.spec.ts +3 -3
  181. package/src/api/users/services/SessionService.ts +27 -18
  182. package/src/api/users/services/UserService.ts +7 -7
  183. package/src/batch/providers/BatchProvider.ts +1 -2
  184. package/src/cli/apps/AlephaCli.ts +2 -2
  185. package/src/cli/apps/AlephaPackageBuilderCli.ts +47 -20
  186. package/src/cli/assets/apiHelloControllerTs.ts +19 -0
  187. package/src/cli/assets/apiIndexTs.ts +16 -0
  188. package/src/cli/assets/biomeJson.ts +2 -1
  189. package/src/cli/assets/claudeMd.ts +308 -0
  190. package/src/cli/assets/dummySpecTs.ts +2 -1
  191. package/src/cli/assets/editorconfig.ts +2 -1
  192. package/src/cli/assets/mainBrowserTs.ts +4 -3
  193. package/src/cli/assets/mainCss.ts +24 -0
  194. package/src/cli/assets/mainServerTs.ts +24 -0
  195. package/src/cli/assets/tsconfigJson.ts +2 -1
  196. package/src/cli/assets/webAppRouterTs.ts +16 -0
  197. package/src/cli/assets/webHelloComponentTsx.ts +20 -0
  198. package/src/cli/assets/webIndexTs.ts +16 -0
  199. package/src/cli/atoms/appEntryOptions.ts +13 -0
  200. package/src/cli/atoms/buildOptions.ts +1 -1
  201. package/src/cli/atoms/changelogOptions.ts +1 -1
  202. package/src/cli/commands/build.ts +97 -61
  203. package/src/cli/commands/db.ts +21 -18
  204. package/src/cli/commands/deploy.ts +17 -5
  205. package/src/cli/commands/dev.ts +26 -47
  206. package/src/cli/commands/gen/env.ts +1 -1
  207. package/src/cli/commands/init.ts +79 -25
  208. package/src/cli/commands/lint.ts +9 -3
  209. package/src/cli/commands/test.ts +8 -2
  210. package/src/cli/commands/typecheck.ts +5 -1
  211. package/src/cli/commands/verify.ts +4 -2
  212. package/src/cli/defineConfig.ts +9 -0
  213. package/src/cli/index.ts +2 -1
  214. package/src/cli/providers/AppEntryProvider.ts +131 -0
  215. package/src/cli/providers/ViteBuildProvider.ts +82 -0
  216. package/src/cli/providers/ViteDevServerProvider.ts +350 -0
  217. package/src/cli/providers/ViteTemplateProvider.ts +27 -0
  218. package/src/cli/services/AlephaCliUtils.ts +72 -602
  219. package/src/cli/services/PackageManagerUtils.ts +308 -0
  220. package/src/cli/services/ProjectScaffolder.ts +329 -0
  221. package/src/command/helpers/Runner.ts +15 -3
  222. package/src/core/Alepha.ts +2 -8
  223. package/src/core/__tests__/Alepha-graph.spec.ts +4 -0
  224. package/src/core/index.shared.ts +1 -0
  225. package/src/core/index.ts +2 -0
  226. package/src/core/primitives/$hook.ts +6 -2
  227. package/src/core/primitives/$module.spec.ts +4 -0
  228. package/src/core/primitives/$module.ts +12 -0
  229. package/src/core/providers/AlsProvider.ts +1 -1
  230. package/src/core/providers/CodecManager.spec.ts +12 -6
  231. package/src/core/providers/CodecManager.ts +26 -6
  232. package/src/core/providers/EventManager.ts +169 -13
  233. package/src/core/providers/KeylessJsonSchemaCodec.spec.ts +878 -0
  234. package/src/core/providers/KeylessJsonSchemaCodec.ts +789 -0
  235. package/src/core/providers/SchemaValidator.spec.ts +236 -0
  236. package/src/core/providers/StateManager.spec.ts +27 -16
  237. package/src/email/providers/LocalEmailProvider.spec.ts +111 -87
  238. package/src/email/providers/LocalEmailProvider.ts +52 -15
  239. package/src/email/providers/NodemailerEmailProvider.ts +167 -56
  240. package/src/file/errors/FileError.ts +7 -0
  241. package/src/file/index.ts +9 -1
  242. package/src/file/providers/MemoryFileSystemProvider.ts +393 -0
  243. package/src/logger/providers/PrettyFormatterProvider.ts +0 -9
  244. package/src/mcp/errors/McpError.ts +30 -0
  245. package/src/mcp/index.ts +3 -0
  246. package/src/mcp/transports/SseMcpTransport.ts +16 -6
  247. package/src/orm/index.browser.ts +1 -19
  248. package/src/orm/index.bun.ts +77 -0
  249. package/src/orm/index.shared-server.ts +22 -0
  250. package/src/orm/index.shared.ts +15 -0
  251. package/src/orm/index.ts +19 -39
  252. package/src/orm/providers/DrizzleKitProvider.ts +3 -5
  253. package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -5
  254. package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
  255. package/src/orm/providers/drivers/CloudflareD1Provider.ts +4 -0
  256. package/src/orm/providers/drivers/DatabaseProvider.ts +4 -0
  257. package/src/orm/providers/drivers/PglitePostgresProvider.ts +4 -0
  258. package/src/orm/services/Repository.ts +19 -0
  259. package/src/redis/index.bun.ts +35 -0
  260. package/src/redis/providers/BunRedisProvider.ts +12 -43
  261. package/src/redis/providers/BunRedisSubscriberProvider.ts +2 -3
  262. package/src/redis/providers/NodeRedisProvider.ts +16 -34
  263. package/src/{server/security → security}/__tests__/BasicAuth.spec.ts +11 -11
  264. package/src/{server/security → security}/__tests__/ServerSecurityProvider-realm.spec.ts +21 -16
  265. package/src/{server/security/providers → security/__tests__}/ServerSecurityProvider.spec.ts +5 -5
  266. package/src/security/index.browser.ts +5 -0
  267. package/src/security/index.ts +90 -7
  268. package/src/security/primitives/{$realm.spec.ts → $issuer.spec.ts} +11 -11
  269. package/src/security/primitives/{$realm.ts → $issuer.ts} +20 -17
  270. package/src/security/primitives/$role.ts +5 -5
  271. package/src/security/primitives/$serviceAccount.spec.ts +5 -5
  272. package/src/security/primitives/$serviceAccount.ts +3 -3
  273. package/src/{server/security → security}/providers/ServerSecurityProvider.ts +5 -7
  274. package/src/server/auth/primitives/$auth.ts +10 -10
  275. package/src/server/auth/primitives/$authCredentials.ts +3 -3
  276. package/src/server/auth/primitives/$authGithub.ts +3 -3
  277. package/src/server/auth/primitives/$authGoogle.ts +3 -3
  278. package/src/server/auth/providers/ServerAuthProvider.ts +13 -13
  279. package/src/server/cache/providers/ServerCacheProvider.ts +1 -1
  280. package/src/server/cookies/providers/ServerCookiesProvider.ts +3 -3
  281. package/src/server/core/index.ts +1 -1
  282. package/src/server/core/providers/BunHttpServerProvider.ts +1 -1
  283. package/src/server/core/providers/NodeHttpServerProvider.spec.ts +125 -0
  284. package/src/server/core/providers/NodeHttpServerProvider.ts +92 -24
  285. package/src/server/core/providers/ServerBodyParserProvider.ts +19 -23
  286. package/src/server/core/providers/ServerLoggerProvider.ts +23 -19
  287. package/src/server/core/providers/ServerProvider.ts +144 -24
  288. package/src/server/core/providers/ServerRouterProvider.ts +259 -115
  289. package/src/server/core/providers/ServerTimingProvider.ts +2 -2
  290. package/src/server/links/atoms/apiLinksAtom.ts +7 -0
  291. package/src/server/links/index.browser.ts +2 -0
  292. package/src/server/links/index.ts +3 -1
  293. package/src/server/links/providers/LinkProvider.ts +1 -1
  294. package/src/server/swagger/index.ts +1 -1
  295. package/src/sms/providers/LocalSmsProvider.spec.ts +153 -111
  296. package/src/sms/providers/LocalSmsProvider.ts +8 -7
  297. package/src/vite/index.ts +3 -2
  298. package/src/vite/tasks/buildClient.ts +0 -1
  299. package/src/vite/tasks/buildServer.ts +80 -22
  300. package/src/vite/tasks/copyAssets.ts +5 -4
  301. package/src/vite/tasks/generateCloudflare.ts +7 -0
  302. package/src/vite/tasks/generateSitemap.ts +64 -23
  303. package/src/vite/tasks/index.ts +0 -2
  304. package/src/vite/tasks/prerenderPages.ts +49 -24
  305. package/dist/server/security/index.browser.js +0 -13
  306. package/dist/server/security/index.browser.js.map +0 -1
  307. package/dist/server/security/index.d.ts +0 -173
  308. package/dist/server/security/index.d.ts.map +0 -1
  309. package/dist/server/security/index.js +0 -311
  310. package/dist/server/security/index.js.map +0 -1
  311. package/src/cli/assets/appRouterTs.ts +0 -9
  312. package/src/cli/assets/indexHtml.ts +0 -15
  313. package/src/cli/assets/mainTs.ts +0 -13
  314. package/src/cli/commands/format.ts +0 -17
  315. package/src/server/security/index.browser.ts +0 -10
  316. package/src/server/security/index.ts +0 -94
  317. package/src/vite/helpers/boot.ts +0 -106
  318. package/src/vite/plugins/viteAlephaDev.ts +0 -177
  319. package/src/vite/tasks/devServer.ts +0 -69
  320. package/src/vite/tasks/runAlepha.ts +0 -270
  321. /package/src/{server/security → security}/primitives/$basicAuth.ts +0 -0
  322. /package/src/{server/security → security}/providers/ServerBasicAuthProvider.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/datetime/providers/DateTimeProvider.ts","../../src/datetime/primitives/$interval.ts","../../src/datetime/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;KAmBY,QAAA,GAAW,QAAA,CAAS;KACpB,QAAA,GAAW,aAAA,CAAc;AADzB,KAEA,YAAA,GAFW,MAAA,GAInB,aAAA,CAAc,QAJmB,GAAA,CAAA,MAAA,EAKxB,cALwB,CAAA;AACzB,cAMC,KANU,EAAA,OAML,QANmB;AACzB,cAMC,UAJT,EAAA,CAAA,KAAA,EAAA,OAAc,EAAA,GAAA,KACL,IAGwC,QAH1B;AAEd,cAKA,gBAAA,CALgB;EAChB,OAAA,OAEZ,EAGwB,KAHxB,CAG8B,UALsB,CAEpD,GAAA,CAAA,CAAA;EAEY,UAAA,MAAA,EASK,MATW;EACE,UAAA,GAAA,EASd,QATc,GAAA,IAAA;EAAN,mBAAA,QAAA,EAUM,OAVN,EAAA;EAQP,mBAAA,SAAA,EAGc,QAHd,EAAA;EACD,WAAA,CAAA;EACc,mBAAA,OAAA,EACS,OAAA,CAQZ,aATG,CAAA,OAAA,CAAA;EACC,mBAAA,MAAA,EAQJ,OAAA,CAgBD,aAxBK,CAAA,MAAA,CAAA;EAAQ,SAQZ,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAA,UAgBD,CAAA,KAAA,EAAA,OAAA,CAAA,EAAA,KAAA,IAmBmB,QAnBnB;EAmBmB;;;EASzC,GAAA,CAAA,IAAA,EAAA,MAAA,GAAA,MAAA,GADuB,IACvB,GAD8B,KAC9B,GAAA,IAAA,GAAA,SAAA,CAAA,EAAA,QAAA;EAO+B;;;EAOT,EAAA,CAAA,IAAA,EAAA,MAAA,GAAA,MAAA,GAPS,IAOT,GAPgB,KAOhB,GAAA,IAAA,GAAA,SAAA,CAAA,EAP2C,QAO3C;EAAgB;;;EAoD7B,WAAA,CAAA,IAAA,CAAA,EApDa,IAoDb,GAAA,MAAA,GApD6B,QAoD7B,CAAA,EAAA,MAAA;EACH;;;EAyBY,GAAA,CAAA,CAAA,EAvEP,QAuEO;EAWT;;;;;EAwDA,YAAA,CAAA,CAAA,EAAA,MAAA;EAET;;;;;EA8C4B,SAAA,CAAA,CAAA,EAAA,MAAA;EACnB;;;;;EAqBT,UAAA,cAAA,CAAA,CAAA,EA/KyB,QA+KzB;EA8Ca;;AAalB;EAMiB,QAAA,EAAO,CAAA,QAAA,EApOV,YAoOU,EAAA,IAAA,CAAA,EAnOb,cAmOa,EAAA,GAlOnB,QAkOmB;2CAtN0B;;;ACpKlD;;EAA2D,IAAA,CAAA,CAAA,EDgLpC,OChLoC,CAAA,IAAA,CAAA;;;;AAK3D;AAcA;;EACqC,IAAA,CAAA,QAAA,EDuKvB,YCvKuB,EAAA,QAAA,EAAA;IADE,MAAA,CAAA,ED0KxB,WC1KwB;IAAS,GAAA,CAAA,EAAA,MAAA;MD6K3C;+CA6BS,gCAET;;AEjOL;;gDFqPc,6BAET;wBA8B0B;0BAME;;;;2BAUhB,gBAAgB,QAAQ,cAC3B,eACT,QAAQ;;;;mBAkBC,qBACH,iBACN;;;;WA8Ca;;;;;;UAaD,QAAA;;;;;UAMA,OAAA;;;;;;;;;;;;;;cC1XJ;YAAsB,2BAAwB;;;UAK1C,wBAAA;EDGL;AACZ;AACA;EAKa,OAAA,EAAgB,GAAA,GAAA,OAAX;EACL;AAIb;;EACyB,QAAA,ECPb,YDOa;;AASR,cCXJ,iBAAA,SAA0B,SDWtB,CCXgC,wBDWhC,CAAA,CAAA;EACc,mBAAA,gBAAA,ECXM,gBDWN;EACC,MAAA,EAAA,MAAA;EAAQ,UAQZ,MAAA,CAAA,CAAA,EAAA,IAAA;;;;cE1Cf,gBAAc,OAAA,CAAA,QAIzB,OAAA,CAJyB,MAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/datetime/providers/DateTimeProvider.ts","../../src/datetime/primitives/$interval.ts","../../src/datetime/index.ts"],"mappings":";;;;;;;;;;;;KAmBY,QAAA,GAAW,QAAA,CAAS,KAAA;AAAA,KACpB,QAAA,GAAW,aAAA,CAAc,QAAA;AAAA,KACzB,YAAA,YAER,aAAA,CAAc,QAAA,YACL,cAAA;AAAA,cAEA,KAAA,SAAK,QAAA;AAAA,cACL,UAAA,GAAc,KAAA,cAAiB,KAAA,IAAS,QAAA;AAAA,cAIxC,gBAAA;EAAA,OACG,OAAA,EAAS,KAAA,CAAM,UAAA;EAAA,UAQnB,MAAA,EAAM,MAAA;EAAA,UACN,GAAA,EAAK,QAAA;EAAA,mBACI,QAAA,EAAU,OAAA;EAAA,mBACV,SAAA,EAAW,QAAA;;qBAQX,OAAA,EARmB,OAAA,CAQZ,aAAA;EAAA,mBAgBP,MAAA,EAhBO,OAAA,CAgBD,aAAA;EAelB,SAAA,CAAU,MAAA;EAIV,UAAA,CAAW,KAAA,YAAiB,KAAA,IAAS,QAAA;EA/D1C;;;EAsEK,GAAA,CACL,IAAA,oBAAwB,IAAA,GAAO,KAAA,sBAC9B,QAAA;EAvEsB;AAE3B;;EA4ES,EAAA,CAAG,IAAA,oBAAwB,IAAA,GAAO,KAAA,sBAA2B,QAAA;EA5EpD;;AAClB;EAkFS,WAAA,CAAY,IAAA,GAAM,IAAA,YAAgB,QAAA;;;;EAOlC,GAAA,CAAA,GAAO,QAAA;EAzFqC;;;AAIrD;;EA8FS,YAAA,CAAA;EA7FsB;;;;;EAyGtB,SAAA,CAAA;EA9F+B;;;;;EAAA,UA0G5B,cAAA,CAAA,GAAkB,QAAA;EA/CM;;;EA0D3B,QAAA,GACL,QAAA,EAAU,YAAA,EACV,IAAA,GAAO,cAAA,KACN,QAAA;EAYI,cAAA,CAAe,KAAA,YAAiB,KAAA,IAAS,YAAA;EA3DlC;;;;EAuED,IAAA,CAAA,GAAQ,OAAA;EAZ2B;;;;;;EAsBzC,IAAA,CACL,QAAA,EAAU,YAAA,EACV,OAAA;IACE,MAAA,GAAS,WAAA;IACT,GAAA;EAAA,IAED,OAAA;EA2BI,cAAA,CACL,GAAA,iBACA,QAAA,EAAU,YAAA,EACV,KAAA,aACC,QAAA;EAoEY;;;EAlDR,aAAA,CACL,QAAA,cACA,QAAA,EAAU,YAAA,EACV,GAAA,YACC,OAAA;EA8BI,YAAA,CAAa,OAAA,EAAS,OAAA;EAMtB,aAAA,CAAc,QAAA,EAAU,QAAA;EA8BnB;;;EArBC,QAAA,GAAA,CACX,EAAA,GAAK,MAAA,EAAQ,WAAA,KAAgB,OAAA,CAAQ,CAAA,GACrC,QAAA,EAAU,YAAA,GACT,OAAA,CAAQ,CAAA;EAkEa;;;EAjDX,MAAA,CACX,QAAA,EAAU,YAAA,EACV,IAAA,GAAO,cAAA,GACN,OAAA;EApS0B;;;EAkVtB,KAAA,CAAA,GAAS,QAAA;EAzUD;;;EAiVR,KAAA,CAAA;AAAA;AAAA,UAKQ,QAAA;EACf,KAAA;EACA,QAAA;EACA,GAAA;AAAA;AAAA,UAGe,OAAA;EACf,GAAA;EACA,KAAA;EACA,QAAA;EACA,QAAA;EACA,KAAA;AAAA;;;;;;;;cC/XW,SAAA;EAAA,UAAsB,wBAAA,GAAwB,iBAAA;EAAA;;UAK1C,wBAAA;EDGL;;;ECCV,OAAA;EDDmC;AACrC;;ECKE,QAAA,EAAU,YAAA;AAAA;AAAA,cAKC,iBAAA,SAA0B,SAAA,CAAU,wBAAA;EAAA,mBAC5B,gBAAA,EAAgB,gBAAA;EAE5B,MAAA;EAAA,UAEG,MAAA,CAAA;AAAA;;;cC1BC,cAAA,EAAc,OAAA,CAAA,OAAA,CAIzB,OAAA,CAJyB,MAAA"}
@@ -132,16 +132,16 @@ var DateTimeProvider = class DateTimeProvider {
132
132
  */
133
133
  wait(duration, options = {}) {
134
134
  return new Promise((resolve) => {
135
- let clearTimeout$1;
135
+ let clearTimeout;
136
136
  let callback;
137
137
  const timeout = this.createTimeout(() => {
138
- if (options.signal && clearTimeout$1) options.signal.removeEventListener("abort", callback);
138
+ if (options.signal && clearTimeout) options.signal.removeEventListener("abort", callback);
139
139
  resolve();
140
140
  }, duration, options.now);
141
141
  if (options.signal) {
142
- clearTimeout$1 = () => this.clearTimeout(timeout);
142
+ clearTimeout = () => this.clearTimeout(timeout);
143
143
  callback = () => {
144
- clearTimeout$1();
144
+ clearTimeout();
145
145
  resolve();
146
146
  };
147
147
  options.signal.addEventListener("abort", callback);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["clearTimeout"],"sources":["../../src/datetime/providers/DateTimeProvider.ts","../../src/datetime/primitives/$interval.ts","../../src/datetime/index.ts"],"sourcesContent":["import \"dayjs/plugin/relativeTime.js\";\nimport \"dayjs/plugin/duration.js\";\nimport \"dayjs/plugin/utc.js\";\nimport \"dayjs/plugin/timezone.js\";\nimport \"dayjs/plugin/localizedFormat.js\";\nimport \"dayjs/locale/ar.js\";\nimport \"dayjs/locale/fr.js\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport DayjsApi, {\n type Dayjs,\n type ManipulateType,\n type PluginFunc,\n} from \"dayjs\";\nimport dayjsDuration from \"dayjs/plugin/duration.js\";\nimport dayjsLocalizedFormat from \"dayjs/plugin/localizedFormat.js\";\nimport dayjsRelativeTime from \"dayjs/plugin/relativeTime.js\";\nimport dayjsTimezone from \"dayjs/plugin/timezone.js\";\nimport dayjsUtc from \"dayjs/plugin/utc.js\";\n\nexport type DateTime = DayjsApi.Dayjs;\nexport type Duration = dayjsDuration.Duration;\nexport type DurationLike =\n | number\n | dayjsDuration.Duration\n | [number, ManipulateType];\n\nexport const dayjs = DayjsApi;\nexport const isDateTime = (value: unknown): value is DateTime => {\n return dayjs.isDayjs(value);\n};\n\nexport class DateTimeProvider {\n public static PLUGINS: Array<PluginFunc<any>> = [\n dayjsDuration,\n dayjsRelativeTime,\n dayjsUtc,\n dayjsTimezone,\n dayjsLocalizedFormat,\n ];\n\n protected alepha = $inject(Alepha);\n protected ref: DateTime | null = null;\n protected readonly timeouts: Timeout[] = [];\n protected readonly intervals: Interval[] = [];\n\n constructor() {\n for (const plugin of DateTimeProvider.PLUGINS) {\n dayjs.extend(plugin);\n }\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // we start intervals now but first tick will be rejected as App is not ready yet\n await Promise.all(\n this.intervals.map(async (interval) => {\n if (interval.timer != null) {\n return;\n }\n await interval.run();\n interval.timer = setInterval(interval.run, interval.duration);\n }),\n );\n },\n });\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => {\n for (const timeout of this.timeouts) {\n this.clearTimeout(timeout);\n }\n\n for (const interval of this.intervals) {\n clearInterval(interval.timer);\n interval.duration = 0;\n interval.timer = null;\n }\n },\n });\n\n public setLocale(locale: string): void {\n dayjs.locale(locale);\n }\n\n public isDateTime(value: unknown): value is DateTime {\n return dayjs.isDayjs(value);\n }\n\n /**\n * Create a new UTC DateTime instance.\n */\n public utc(\n date: string | number | Date | Dayjs | null | undefined,\n ): DateTime {\n return dayjs.utc(date);\n }\n\n /**\n * Create a new DateTime instance.\n */\n public of(date: string | number | Date | Dayjs | null | undefined): DateTime {\n return dayjs(date);\n }\n\n /**\n * Get the current date as a string.\n */\n public toISOString(date: Date | string | DateTime = this.now()): string {\n return this.of(date).toISOString();\n }\n\n /**\n * Get the current date.\n */\n public now(): DateTime {\n return this.getCurrentDate();\n }\n\n /**\n * Get the current date as a string.\n *\n * This is much faster than `DateTimeProvider.now().toISOString()` as it avoids creating a DateTime instance.\n */\n public nowISOString(): string {\n if (this.ref) {\n return this.ref.toISOString();\n }\n return new Date().toISOString();\n }\n\n /**\n * Get the current date as milliseconds since epoch.\n *\n * This is much faster than `DateTimeProvider.now().valueOf()` as it avoids creating a DateTime instance.\n */\n public nowMillis(): number {\n if (this.ref) {\n return this.ref.valueOf();\n }\n return Date.now();\n }\n\n /**\n * Get the current date as a string.\n *\n * @protected\n */\n protected getCurrentDate(): DateTime {\n if (this.ref) {\n return this.ref;\n }\n\n return dayjs();\n }\n\n /**\n * Create a new Duration instance.\n */\n public duration = (\n duration: DurationLike,\n unit?: ManipulateType,\n ): Duration => {\n if (Array.isArray(duration)) {\n return dayjs.duration(duration[0], duration[1]);\n }\n\n if (typeof duration === \"number\") {\n return dayjs.duration(duration, unit || \"milliseconds\");\n }\n\n return duration;\n };\n\n public isDurationLike(value: unknown): value is DurationLike {\n return dayjs.isDuration(this.duration(value as DurationLike));\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Timer Management\n\n /**\n * Return a promise that resolves after the next tick.\n * It uses `setTimeout` with 0 ms delay.\n */\n public async tick(): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n\n /**\n * Wait for a certain duration.\n *\n * You can clear the timeout by using the `AbortSignal` API.\n * Aborted signal will resolve the promise immediately, it does not reject it.\n */\n public wait(\n duration: DurationLike,\n options: {\n signal?: AbortSignal;\n now?: number;\n } = {},\n ): Promise<void> {\n return new Promise((resolve) => {\n let clearTimeout: any;\n let callback: any;\n\n const timeout = this.createTimeout(\n () => {\n if (options.signal && clearTimeout) {\n options.signal.removeEventListener(\"abort\", callback);\n }\n resolve();\n },\n duration,\n options.now,\n );\n\n if (options.signal) {\n clearTimeout = () => this.clearTimeout(timeout);\n callback = () => {\n clearTimeout();\n resolve();\n };\n options.signal.addEventListener(\"abort\", callback);\n }\n });\n }\n\n public createInterval(\n run: () => unknown,\n duration: DurationLike,\n start = false,\n ): Interval {\n const interval: Interval = {\n run,\n duration: this.duration(duration).asMilliseconds(),\n };\n\n this.intervals.push(interval);\n\n if (start) {\n interval.timer = setInterval(interval.run, interval.duration);\n }\n\n return interval;\n }\n\n /**\n * Run a callback after a certain duration.\n */\n public createTimeout(\n callback: () => void,\n duration: DurationLike,\n now?: number,\n ): Timeout {\n if (this.ref && now) {\n const next = this.of(now).add(this.duration(duration));\n if (next < this.now()) {\n callback();\n }\n return {\n now,\n duration: 0,\n callback: () => {},\n clear: () => {},\n };\n }\n\n const timeout: Timeout = {\n now: now ?? this.now().valueOf(),\n duration: this.duration(duration).asMilliseconds(),\n callback,\n clear: () => this.clearTimeout(timeout),\n };\n\n timeout.timer = setTimeout(() => {\n timeout.callback();\n }, timeout.duration);\n\n this.timeouts.push(timeout);\n\n return timeout;\n }\n\n public clearTimeout(timeout: Timeout): void {\n clearTimeout(timeout.timer);\n timeout.duration = 0;\n timeout.timer = null;\n }\n\n public clearInterval(interval: Interval): void {\n clearInterval(interval.timer);\n interval.duration = 0;\n interval.timer = null;\n }\n\n /**\n * Run a function with a deadline.\n */\n public async deadline<T>(\n fn: (signal: AbortSignal) => Promise<T>,\n duration: DurationLike,\n ): Promise<T> {\n const abort = new AbortController();\n const timeout = this.createTimeout(() => abort.abort(), duration);\n try {\n return await fn(abort.signal);\n } finally {\n this.clearTimeout(timeout);\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Testing\n\n /**\n * Add time to the current date.\n */\n public async travel(\n duration: DurationLike,\n unit?: ManipulateType,\n ): Promise<void> {\n this.ref = this.ref || this.now();\n this.ref = this.ref.add(this.duration(duration, unit));\n const ms = this.duration(duration, unit).asMilliseconds();\n const now = Date.now();\n\n for (const timeout of this.timeouts) {\n if (!timeout.timer) {\n continue;\n }\n\n clearTimeout(timeout.timer);\n timeout.timer = null;\n\n const spent = now - timeout.now;\n timeout.duration = timeout.duration - spent - ms;\n\n if (timeout.duration <= 0) {\n timeout.callback();\n } else {\n timeout.timer = setTimeout(() => {\n timeout.callback();\n }, timeout.duration);\n }\n }\n\n for (const interval of this.intervals) {\n if (!interval.timer) {\n continue;\n }\n\n clearInterval(interval.timer);\n interval.timer = null;\n\n const repeat = Math.floor(ms / interval.duration);\n for (let i = 0; i < repeat; i++) {\n await interval.run();\n }\n }\n\n await this.tick();\n }\n\n /**\n * Stop the time.\n */\n public pause(): DateTime {\n this.ref = this.ref || this.now();\n return this.ref;\n }\n\n /**\n * Reset the reference date.\n */\n public reset(): void {\n this.ref = null;\n }\n}\n\nexport interface Interval {\n timer?: any;\n duration: number;\n run: () => unknown;\n}\n\nexport interface Timeout {\n now: number;\n timer?: any;\n duration: number;\n callback: () => void;\n clear: () => void;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport {\n DateTimeProvider,\n type DurationLike,\n} from \"../providers/DateTimeProvider.ts\";\n\n/**\n * Run a function periodically.\n * It uses the `setInterval` internally.\n * It starts by default when the context starts and stops when the context stops.\n */\nexport const $interval = (options: IntervalPrimitiveOptions) =>\n createPrimitive(IntervalPrimitive, options);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface IntervalPrimitiveOptions {\n /**\n * The interval handler.\n */\n handler: () => unknown;\n\n /**\n * The interval duration.\n */\n duration: DurationLike;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class IntervalPrimitive extends Primitive<IntervalPrimitiveOptions> {\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public called = 0;\n\n protected onInit() {\n this.dateTimeProvider.createInterval(async () => {\n await this.options.handler();\n this.called += 1;\n }, this.options.duration);\n }\n}\n\n$interval[KIND] = IntervalPrimitive;\n","import { $module } from \"alepha\";\nimport { $interval } from \"./primitives/$interval.ts\";\nimport { DateTimeProvider } from \"./providers/DateTimeProvider.ts\";\n\nexport * from \"./primitives/$interval.ts\";\nexport * from \"./providers/DateTimeProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaDateTime = $module({\n name: \"alepha.datetime\",\n primitives: [$interval],\n services: [DateTimeProvider],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/datetime/providers/DateTimeProvider.ts","../../src/datetime/primitives/$interval.ts","../../src/datetime/index.ts"],"sourcesContent":["import \"dayjs/plugin/relativeTime.js\";\nimport \"dayjs/plugin/duration.js\";\nimport \"dayjs/plugin/utc.js\";\nimport \"dayjs/plugin/timezone.js\";\nimport \"dayjs/plugin/localizedFormat.js\";\nimport \"dayjs/locale/ar.js\";\nimport \"dayjs/locale/fr.js\";\nimport { $hook, $inject, Alepha } from \"alepha\";\nimport DayjsApi, {\n type Dayjs,\n type ManipulateType,\n type PluginFunc,\n} from \"dayjs\";\nimport dayjsDuration from \"dayjs/plugin/duration.js\";\nimport dayjsLocalizedFormat from \"dayjs/plugin/localizedFormat.js\";\nimport dayjsRelativeTime from \"dayjs/plugin/relativeTime.js\";\nimport dayjsTimezone from \"dayjs/plugin/timezone.js\";\nimport dayjsUtc from \"dayjs/plugin/utc.js\";\n\nexport type DateTime = DayjsApi.Dayjs;\nexport type Duration = dayjsDuration.Duration;\nexport type DurationLike =\n | number\n | dayjsDuration.Duration\n | [number, ManipulateType];\n\nexport const dayjs = DayjsApi;\nexport const isDateTime = (value: unknown): value is DateTime => {\n return dayjs.isDayjs(value);\n};\n\nexport class DateTimeProvider {\n public static PLUGINS: Array<PluginFunc<any>> = [\n dayjsDuration,\n dayjsRelativeTime,\n dayjsUtc,\n dayjsTimezone,\n dayjsLocalizedFormat,\n ];\n\n protected alepha = $inject(Alepha);\n protected ref: DateTime | null = null;\n protected readonly timeouts: Timeout[] = [];\n protected readonly intervals: Interval[] = [];\n\n constructor() {\n for (const plugin of DateTimeProvider.PLUGINS) {\n dayjs.extend(plugin);\n }\n }\n\n protected readonly onStart = $hook({\n on: \"start\",\n handler: async () => {\n // we start intervals now but first tick will be rejected as App is not ready yet\n await Promise.all(\n this.intervals.map(async (interval) => {\n if (interval.timer != null) {\n return;\n }\n await interval.run();\n interval.timer = setInterval(interval.run, interval.duration);\n }),\n );\n },\n });\n\n protected readonly onStop = $hook({\n on: \"stop\",\n handler: () => {\n for (const timeout of this.timeouts) {\n this.clearTimeout(timeout);\n }\n\n for (const interval of this.intervals) {\n clearInterval(interval.timer);\n interval.duration = 0;\n interval.timer = null;\n }\n },\n });\n\n public setLocale(locale: string): void {\n dayjs.locale(locale);\n }\n\n public isDateTime(value: unknown): value is DateTime {\n return dayjs.isDayjs(value);\n }\n\n /**\n * Create a new UTC DateTime instance.\n */\n public utc(\n date: string | number | Date | Dayjs | null | undefined,\n ): DateTime {\n return dayjs.utc(date);\n }\n\n /**\n * Create a new DateTime instance.\n */\n public of(date: string | number | Date | Dayjs | null | undefined): DateTime {\n return dayjs(date);\n }\n\n /**\n * Get the current date as a string.\n */\n public toISOString(date: Date | string | DateTime = this.now()): string {\n return this.of(date).toISOString();\n }\n\n /**\n * Get the current date.\n */\n public now(): DateTime {\n return this.getCurrentDate();\n }\n\n /**\n * Get the current date as a string.\n *\n * This is much faster than `DateTimeProvider.now().toISOString()` as it avoids creating a DateTime instance.\n */\n public nowISOString(): string {\n if (this.ref) {\n return this.ref.toISOString();\n }\n return new Date().toISOString();\n }\n\n /**\n * Get the current date as milliseconds since epoch.\n *\n * This is much faster than `DateTimeProvider.now().valueOf()` as it avoids creating a DateTime instance.\n */\n public nowMillis(): number {\n if (this.ref) {\n return this.ref.valueOf();\n }\n return Date.now();\n }\n\n /**\n * Get the current date as a string.\n *\n * @protected\n */\n protected getCurrentDate(): DateTime {\n if (this.ref) {\n return this.ref;\n }\n\n return dayjs();\n }\n\n /**\n * Create a new Duration instance.\n */\n public duration = (\n duration: DurationLike,\n unit?: ManipulateType,\n ): Duration => {\n if (Array.isArray(duration)) {\n return dayjs.duration(duration[0], duration[1]);\n }\n\n if (typeof duration === \"number\") {\n return dayjs.duration(duration, unit || \"milliseconds\");\n }\n\n return duration;\n };\n\n public isDurationLike(value: unknown): value is DurationLike {\n return dayjs.isDuration(this.duration(value as DurationLike));\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Timer Management\n\n /**\n * Return a promise that resolves after the next tick.\n * It uses `setTimeout` with 0 ms delay.\n */\n public async tick(): Promise<void> {\n await new Promise((resolve) => setTimeout(resolve, 0));\n }\n\n /**\n * Wait for a certain duration.\n *\n * You can clear the timeout by using the `AbortSignal` API.\n * Aborted signal will resolve the promise immediately, it does not reject it.\n */\n public wait(\n duration: DurationLike,\n options: {\n signal?: AbortSignal;\n now?: number;\n } = {},\n ): Promise<void> {\n return new Promise((resolve) => {\n let clearTimeout: any;\n let callback: any;\n\n const timeout = this.createTimeout(\n () => {\n if (options.signal && clearTimeout) {\n options.signal.removeEventListener(\"abort\", callback);\n }\n resolve();\n },\n duration,\n options.now,\n );\n\n if (options.signal) {\n clearTimeout = () => this.clearTimeout(timeout);\n callback = () => {\n clearTimeout();\n resolve();\n };\n options.signal.addEventListener(\"abort\", callback);\n }\n });\n }\n\n public createInterval(\n run: () => unknown,\n duration: DurationLike,\n start = false,\n ): Interval {\n const interval: Interval = {\n run,\n duration: this.duration(duration).asMilliseconds(),\n };\n\n this.intervals.push(interval);\n\n if (start) {\n interval.timer = setInterval(interval.run, interval.duration);\n }\n\n return interval;\n }\n\n /**\n * Run a callback after a certain duration.\n */\n public createTimeout(\n callback: () => void,\n duration: DurationLike,\n now?: number,\n ): Timeout {\n if (this.ref && now) {\n const next = this.of(now).add(this.duration(duration));\n if (next < this.now()) {\n callback();\n }\n return {\n now,\n duration: 0,\n callback: () => {},\n clear: () => {},\n };\n }\n\n const timeout: Timeout = {\n now: now ?? this.now().valueOf(),\n duration: this.duration(duration).asMilliseconds(),\n callback,\n clear: () => this.clearTimeout(timeout),\n };\n\n timeout.timer = setTimeout(() => {\n timeout.callback();\n }, timeout.duration);\n\n this.timeouts.push(timeout);\n\n return timeout;\n }\n\n public clearTimeout(timeout: Timeout): void {\n clearTimeout(timeout.timer);\n timeout.duration = 0;\n timeout.timer = null;\n }\n\n public clearInterval(interval: Interval): void {\n clearInterval(interval.timer);\n interval.duration = 0;\n interval.timer = null;\n }\n\n /**\n * Run a function with a deadline.\n */\n public async deadline<T>(\n fn: (signal: AbortSignal) => Promise<T>,\n duration: DurationLike,\n ): Promise<T> {\n const abort = new AbortController();\n const timeout = this.createTimeout(() => abort.abort(), duration);\n try {\n return await fn(abort.signal);\n } finally {\n this.clearTimeout(timeout);\n }\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n // Testing\n\n /**\n * Add time to the current date.\n */\n public async travel(\n duration: DurationLike,\n unit?: ManipulateType,\n ): Promise<void> {\n this.ref = this.ref || this.now();\n this.ref = this.ref.add(this.duration(duration, unit));\n const ms = this.duration(duration, unit).asMilliseconds();\n const now = Date.now();\n\n for (const timeout of this.timeouts) {\n if (!timeout.timer) {\n continue;\n }\n\n clearTimeout(timeout.timer);\n timeout.timer = null;\n\n const spent = now - timeout.now;\n timeout.duration = timeout.duration - spent - ms;\n\n if (timeout.duration <= 0) {\n timeout.callback();\n } else {\n timeout.timer = setTimeout(() => {\n timeout.callback();\n }, timeout.duration);\n }\n }\n\n for (const interval of this.intervals) {\n if (!interval.timer) {\n continue;\n }\n\n clearInterval(interval.timer);\n interval.timer = null;\n\n const repeat = Math.floor(ms / interval.duration);\n for (let i = 0; i < repeat; i++) {\n await interval.run();\n }\n }\n\n await this.tick();\n }\n\n /**\n * Stop the time.\n */\n public pause(): DateTime {\n this.ref = this.ref || this.now();\n return this.ref;\n }\n\n /**\n * Reset the reference date.\n */\n public reset(): void {\n this.ref = null;\n }\n}\n\nexport interface Interval {\n timer?: any;\n duration: number;\n run: () => unknown;\n}\n\nexport interface Timeout {\n now: number;\n timer?: any;\n duration: number;\n callback: () => void;\n clear: () => void;\n}\n","import { $inject, createPrimitive, KIND, Primitive } from \"alepha\";\nimport {\n DateTimeProvider,\n type DurationLike,\n} from \"../providers/DateTimeProvider.ts\";\n\n/**\n * Run a function periodically.\n * It uses the `setInterval` internally.\n * It starts by default when the context starts and stops when the context stops.\n */\nexport const $interval = (options: IntervalPrimitiveOptions) =>\n createPrimitive(IntervalPrimitive, options);\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface IntervalPrimitiveOptions {\n /**\n * The interval handler.\n */\n handler: () => unknown;\n\n /**\n * The interval duration.\n */\n duration: DurationLike;\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport class IntervalPrimitive extends Primitive<IntervalPrimitiveOptions> {\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n public called = 0;\n\n protected onInit() {\n this.dateTimeProvider.createInterval(async () => {\n await this.options.handler();\n this.called += 1;\n }, this.options.duration);\n }\n}\n\n$interval[KIND] = IntervalPrimitive;\n","import { $module } from \"alepha\";\nimport { $interval } from \"./primitives/$interval.ts\";\nimport { DateTimeProvider } from \"./providers/DateTimeProvider.ts\";\n\nexport * from \"./primitives/$interval.ts\";\nexport * from \"./providers/DateTimeProvider.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport const AlephaDateTime = $module({\n name: \"alepha.datetime\",\n primitives: [$interval],\n services: [DateTimeProvider],\n});\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import * as alepha1 from "alepha";
2
- import { InstantiableClass, KIND, Primitive } from "alepha";
1
+ import * as alepha15 from "alepha";
2
+ import { InstantiableClass, KIND, Primitive, Static } from "alepha";
3
3
  import * as alepha_logger0 from "alepha/logger";
4
+ import { FileSystemProvider } from "alepha/file";
4
5
  import { Transporter } from "nodemailer";
5
6
 
6
7
  //#region ../../src/email/providers/EmailProvider.d.ts
@@ -66,16 +67,26 @@ declare class EmailPrimitive extends Primitive<EmailPrimitiveOptions> {
66
67
  }
67
68
  //#endregion
68
69
  //#region ../../src/email/providers/LocalEmailProvider.d.ts
69
- interface LocalEmailProviderOptions {
70
- /**
71
- * Directory to save email files.
72
- */
73
- directory?: string;
70
+ /**
71
+ * Local email provider configuration atom
72
+ */
73
+ declare const localEmailOptions: alepha15.Atom<alepha15.TObject<{
74
+ directory: alepha15.TString;
75
+ }>, "alepha.email.local.options">;
76
+ type LocalEmailProviderOptions = Static<typeof localEmailOptions.schema>;
77
+ declare module "alepha" {
78
+ interface State {
79
+ [localEmailOptions.key]: LocalEmailProviderOptions;
80
+ }
74
81
  }
75
82
  declare class LocalEmailProvider implements EmailProvider {
76
83
  protected readonly log: alepha_logger0.Logger;
77
- protected readonly directory: string;
78
- constructor(options?: LocalEmailProviderOptions);
84
+ protected readonly fs: FileSystemProvider;
85
+ protected readonly options: Readonly<{
86
+ directory: string;
87
+ }>;
88
+ protected get directory(): string;
89
+ protected onStart: alepha15.HookPrimitive<"start">;
79
90
  send(options: EmailSendOptions): Promise<void>;
80
91
  createEmailHtml(options: {
81
92
  to: string;
@@ -103,42 +114,78 @@ declare class MemoryEmailProvider implements EmailProvider {
103
114
  }
104
115
  //#endregion
105
116
  //#region ../../src/email/providers/NodemailerEmailProvider.d.ts
106
- interface NodemailerEmailProviderOptions {
107
- /**
108
- * Custom transporter configuration.
109
- * If provided, will override environment variables.
110
- */
111
- transporter?: Transporter;
112
- /**
113
- * Custom from email address.
114
- * If not provided, will use EMAIL_FROM from environment.
115
- */
116
- from?: string;
117
- /**
118
- * Additional nodemailer options.
119
- */
120
- options?: {
121
- pool?: boolean;
122
- maxConnections?: number;
123
- maxMessages?: number;
124
- rateDelta?: number;
125
- rateLimit?: number;
126
- };
117
+ /**
118
+ * Nodemailer connection pooling and rate limiting options
119
+ */
120
+ declare const nodemailerEmailOptions: alepha15.Atom<alepha15.TObject<{
121
+ pool: alepha15.TOptional<alepha15.TBoolean>;
122
+ maxConnections: alepha15.TOptional<alepha15.TNumber>;
123
+ maxMessages: alepha15.TOptional<alepha15.TNumber>;
124
+ rateDelta: alepha15.TOptional<alepha15.TNumber>;
125
+ rateLimit: alepha15.TOptional<alepha15.TNumber>;
126
+ }>, "alepha.email.nodemailer.options">;
127
+ type NodemailerEmailProviderOptions = Static<typeof nodemailerEmailOptions.schema>;
128
+ declare module "alepha" {
129
+ interface State {
130
+ [nodemailerEmailOptions.key]: NodemailerEmailProviderOptions;
131
+ }
127
132
  }
133
+ /**
134
+ * Email provider using Nodemailer for SMTP transport.
135
+ *
136
+ * Configuration is provided via environment variables:
137
+ * - EMAIL_HOST: SMTP server host
138
+ * - EMAIL_PORT: SMTP server port (default: 587)
139
+ * - EMAIL_USER: SMTP authentication username
140
+ * - EMAIL_PASS: SMTP authentication password
141
+ * - EMAIL_FROM: Default from email address
142
+ * - EMAIL_SECURE: Use secure connection (default: false)
143
+ *
144
+ * Advanced pooling/rate limiting options can be configured via atom:
145
+ * @see {@link nodemailerEmailOptions}
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * // Configure via environment variables
150
+ * // EMAIL_HOST=smtp.example.com
151
+ * // EMAIL_PORT=587
152
+ * // EMAIL_USER=user@example.com
153
+ * // EMAIL_PASS=secret
154
+ * // EMAIL_FROM=noreply@example.com
155
+ *
156
+ * // Optionally configure pooling via atom
157
+ * alepha.state.set(nodemailerEmailOptions.key, {
158
+ * pool: true,
159
+ * maxConnections: 5,
160
+ * rateLimit: 10,
161
+ * });
162
+ * ```
163
+ */
128
164
  declare class NodemailerEmailProvider implements EmailProvider {
129
165
  protected readonly env: {
130
- EMAIL_HOST: string;
166
+ EMAIL_HOST?: string | undefined;
167
+ EMAIL_USER?: string | undefined;
168
+ EMAIL_PASS?: string | undefined;
169
+ EMAIL_FROM?: string | undefined;
131
170
  EMAIL_PORT: number;
132
- EMAIL_USER: string;
133
- EMAIL_PASS: string;
134
- EMAIL_FROM: string;
135
171
  EMAIL_SECURE: boolean;
136
172
  };
137
173
  protected readonly log: alepha_logger0.Logger;
138
- protected transporter: Transporter;
139
- protected fromAddress: string;
140
- readonly options: NodemailerEmailProviderOptions;
141
- constructor();
174
+ protected readonly options: Readonly<{
175
+ pool?: boolean | undefined;
176
+ maxConnections?: number | undefined;
177
+ maxMessages?: number | undefined;
178
+ rateDelta?: number | undefined;
179
+ rateLimit?: number | undefined;
180
+ }>;
181
+ protected transporter: Transporter | null;
182
+ protected get host(): string;
183
+ protected get port(): number;
184
+ protected get secure(): boolean;
185
+ protected get user(): string | undefined;
186
+ protected get pass(): string | undefined;
187
+ protected get fromAddress(): string;
188
+ protected getTransporter(): Transporter;
142
189
  send(options: EmailSendOptions): Promise<void>;
143
190
  protected createTransporter(): Transporter;
144
191
  /**
@@ -149,8 +196,8 @@ declare class NodemailerEmailProvider implements EmailProvider {
149
196
  * Close the transporter connection.
150
197
  */
151
198
  close(): void;
152
- protected readonly onStart: alepha1.HookPrimitive<"start">;
153
- protected readonly onStop: alepha1.HookPrimitive<"stop">;
199
+ protected readonly onStart: alepha15.HookPrimitive<"start">;
200
+ protected readonly onStop: alepha15.HookPrimitive<"stop">;
154
201
  }
155
202
  //#endregion
156
203
  //#region ../../src/email/index.d.ts
@@ -180,7 +227,7 @@ declare module "alepha" {
180
227
  * @see {@link EmailProvider}
181
228
  * @module alepha.email
182
229
  */
183
- declare const AlephaEmail: alepha1.Service<alepha1.Module>;
230
+ declare const AlephaEmail: alepha15.Service<alepha15.Module>;
184
231
  //#endregion
185
- export { $email, AlephaEmail, EmailError, EmailPrimitive, EmailPrimitiveOptions, EmailProvider, EmailRecord, EmailSendOptions, LocalEmailProvider, LocalEmailProviderOptions, MemoryEmailProvider, NodemailerEmailProvider, NodemailerEmailProviderOptions };
232
+ export { $email, AlephaEmail, EmailError, EmailPrimitive, EmailPrimitiveOptions, EmailProvider, EmailRecord, EmailSendOptions, LocalEmailProvider, LocalEmailProviderOptions, MemoryEmailProvider, NodemailerEmailProvider, NodemailerEmailProviderOptions, localEmailOptions, nodemailerEmailOptions };
186
233
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/email/providers/EmailProvider.ts","../../src/email/errors/EmailError.ts","../../src/email/primitives/$email.ts","../../src/email/providers/LocalEmailProvider.ts","../../src/email/providers/MemoryEmailProvider.ts","../../src/email/providers/NodemailerEmailProvider.ts","../../src/email/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;uBAKsB,aAAA;EAAA;AAStB;;;;ECda,SAAA,IAAW,CAAA,OAAA,EDWQ,gBCXK,CAAA,EDWc,OCXd,CAAA,IAAA,CAAA;;KDczB,gBAAA;;EEFC,OAAA,EAC6B,MAAA;EADV,IAAA,EAAA,MAAA;CAAqB;;;cDZxC,UAAA,SAAmB,KAAA;uCACO;;;;cCW1B;aAAmB,wBAAqB;;AFPrD,CAAA;AASY,UEGK,qBAAA,CFHW;;aEKf,kBAAkB;;ADnB/B;;;;ACYA;;;;;;AAKA;AAyBA;;;;;;;AAA6C,cAAhC,cAAA,SAAuB,SAAS,CAAC,qBAAD,CAAA,CAAA;+BAChB;;;ACrC7B;AAOA;EAAgC,IAAA,CAAA,OACR,EDsCK,gBCtCL,CAAA,EDsCwB,OCtCxB,CAAA,IAAA,CAAA;EAGD,UAAA,SAAA,CAAA,CAAA,EDuDE,aCvDF;;;;UAXN,yBAAA;;;;;AHDjB;AASY,cGDC,kBAAA,YAA8B,aHCf,CAAA;0BGDI,cAAA,CACR;;wBAGD;EFjBV,IAAA,CAAA,OAAA,EEqBgB,gBFpBU,CADP,EEqBgB,OFrBX,CAAA,IAAA,CAAA;;;;ICYxB,IAAA,EAC6B,MAAA;EADV,CAAA,CAAA,EAAA,MAAA;EAAqB,UAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;UETpC,WAAA;;;;UAIP;AJFV;AASY,cIJC,mBAAA,YAA+B,aJIhB,CAAA;0BIJK,cAAA,CACT;WACN;gBAEW,mBAAmB;EHdnC;;;cG+BQ;AFnBrB;;;UGkBiB,8BAAA;;;;ALzBjB;EASY,WAAA,CAAA,EKqBI,WLrBY;;;;ACd5B;;;;ACYA;EAAgC,OAAA,CAAA,EAAA;IAAqB,IAAA,CAAA,EAAA,OAAA;;;;IAKpC,SAAA,CAAA,EAAA,MAAA;EAyBJ,CAAA;;AACgB,cGYhB,uBAAA,YAAmC,aHZnB,CAAA;EASA,mBAAA,GAAA,EAAA;IAAmB,UAAA,EAAA,MAAA;IAoBvB,UAAA,EAAA,MAAA;IA9BW,UAAA,EAAA,MAAA;IAAS,UAAA,EAAA,MAAA;;;;ECpC5B,mBAAA,GAAA,EEiDoB,cAAA,CAEb,MFnDkB;EAO7B,UAAA,WAAmB,EE6CP,WF7CO;EAAA,UAAA,WACR,EAAA,MAAA;EAGD,SAAA,OAAA,EE4CI,8BF5CJ;EAIM,WAAA,CAAA;EAAmB,IAAA,CAAA,OAAA,EE+CnB,gBF/CmB,CAAA,EE+CA,OF/CA,CAAA,IAAA,CAAA;EARL,UAAA,iBAAA,CAAA,CAAA,EEgFV,WFhFU;EAAa;;;YE6G/B;EDvHR;AAOjB;;EAEkB,KAAA,CAAA,CAAA,EAAA,IAAA;EAEW,mBAAA,OAAA,EC4GG,OAAA,CAkBJ,aD9HC,CAAA,OAAA,CAAA;EAAmB,mBAAA,MAAA,EC8HpB,OAAA,CAKD,aDnIqB,CAAA,MAAA,CAAA;;;;AJAhD,eAAY,QAAgB,CAAA;;;;MCdf,QAAW,EAAA,MACe;iBKsBtB;gBACD;;IJZH,CAAA;IAAmB,YAAA,EAAA;MAAqB,EAAA,EAAA,MAAA,GAAA,MAAA,EAAA;;gBIkBrC;;EJbC;AAyBjB;;;;;;;;;;;ACpCiB,cGyCJ,WHzC6B,EGyClB,OAAA,CAAA,OHzCkB,CG+ExC,OAAA,CAtCsB,MAAA,CHzCkB"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/email/providers/EmailProvider.ts","../../src/email/errors/EmailError.ts","../../src/email/primitives/$email.ts","../../src/email/providers/LocalEmailProvider.ts","../../src/email/providers/MemoryEmailProvider.ts","../../src/email/providers/NodemailerEmailProvider.ts","../../src/email/index.ts"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
- import { $env, $hook, $module, KIND, Primitive, createPrimitive, t } from "alepha";
1
+ import { $atom, $env, $hook, $inject, $module, $use, KIND, Primitive, createPrimitive, t } from "alepha";
2
2
  import { $logger } from "alepha/logger";
3
- import * as fs from "node:fs/promises";
4
- import * as path from "node:path";
3
+ import { FileSystemProvider } from "alepha/file";
5
4
  import nodemailer from "nodemailer";
6
5
 
7
6
  //#region ../../src/email/providers/EmailProvider.ts
@@ -104,12 +103,34 @@ var EmailError = class extends Error {
104
103
 
105
104
  //#endregion
106
105
  //#region ../../src/email/providers/LocalEmailProvider.ts
106
+ /**
107
+ * Local email provider configuration atom
108
+ */
109
+ const localEmailOptions = $atom({
110
+ name: "alepha.email.local.options",
111
+ schema: t.object({ directory: t.string({ description: "Directory path where email files will be stored" }) }),
112
+ default: { directory: "node_modules/.alepha/emails" }
113
+ });
107
114
  var LocalEmailProvider = class {
108
115
  log = $logger();
109
- directory;
110
- constructor(options = {}) {
111
- this.directory = options.directory ?? "node_modules/.alepha/emails";
116
+ fs = $inject(FileSystemProvider);
117
+ options = $use(localEmailOptions);
118
+ get directory() {
119
+ return this.options.directory;
112
120
  }
121
+ onStart = $hook({
122
+ on: "start",
123
+ handler: async () => {
124
+ try {
125
+ await this.fs.mkdir(this.directory, { recursive: true });
126
+ this.log.info("Email directory OK", { directory: this.directory });
127
+ } catch (error) {
128
+ const message = `Failed to create email directory: ${error instanceof Error ? error.message : String(error)}`;
129
+ this.log.error(message, { directory: this.directory });
130
+ throw new EmailError(message, error instanceof Error ? error : void 0);
131
+ }
132
+ }
133
+ });
113
134
  async send(options) {
114
135
  const { to, subject, body } = options;
115
136
  this.log.debug("Sending email to local file", {
@@ -118,17 +139,16 @@ var LocalEmailProvider = class {
118
139
  directory: this.directory
119
140
  });
120
141
  try {
121
- await fs.mkdir(this.directory, { recursive: true });
122
142
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
123
143
  for (const recipient of Array.isArray(to) ? to : [to]) {
124
144
  const filename = `${recipient.replace(/[^a-zA-Z0-9@.-]/g, "_")}+${timestamp}.html`;
125
- const filepath = path.join(this.directory, filename);
145
+ const filepath = this.fs.join(this.directory, filename);
126
146
  const htmlContent = this.createEmailHtml({
127
147
  to: recipient,
128
148
  subject,
129
149
  body
130
150
  });
131
- await fs.writeFile(filepath, htmlContent, "utf8");
151
+ await this.fs.writeFile(filepath, htmlContent);
132
152
  this.log.info("Email saved to local file", {
133
153
  filepath,
134
154
  to,
@@ -180,29 +200,98 @@ var LocalEmailProvider = class {
180
200
 
181
201
  //#endregion
182
202
  //#region ../../src/email/providers/NodemailerEmailProvider.ts
203
+ /**
204
+ * Environment variables for nodemailer configuration
205
+ */
183
206
  const envSchema = t.object({
184
- EMAIL_HOST: t.text({ description: "SMTP server host" }),
207
+ EMAIL_HOST: t.optional(t.text({ description: "SMTP server host" })),
185
208
  EMAIL_PORT: t.number({
186
209
  default: 587,
187
210
  description: "SMTP server port"
188
211
  }),
189
- EMAIL_USER: t.text({ description: "SMTP authentication username" }),
190
- EMAIL_PASS: t.text({ description: "SMTP authentication password" }),
191
- EMAIL_FROM: t.text({ description: "Default from email address" }),
212
+ EMAIL_USER: t.optional(t.text({ description: "SMTP authentication username" })),
213
+ EMAIL_PASS: t.optional(t.text({ description: "SMTP authentication password" })),
214
+ EMAIL_FROM: t.optional(t.text({ description: "Default from email address" })),
192
215
  EMAIL_SECURE: t.boolean({
193
216
  default: false,
194
217
  description: "Use secure connection (TLS)"
195
218
  })
196
219
  });
220
+ /**
221
+ * Nodemailer connection pooling and rate limiting options
222
+ */
223
+ const nodemailerEmailOptions = $atom({
224
+ name: "alepha.email.nodemailer.options",
225
+ schema: t.object({
226
+ pool: t.optional(t.boolean({ description: "Enable connection pooling" })),
227
+ maxConnections: t.optional(t.number({ description: "Maximum number of connections in pool" })),
228
+ maxMessages: t.optional(t.number({ description: "Maximum messages per connection" })),
229
+ rateDelta: t.optional(t.number({ description: "Time in milliseconds between message sends" })),
230
+ rateLimit: t.optional(t.number({ description: "Maximum number of messages per rateDelta" }))
231
+ }),
232
+ default: {}
233
+ });
234
+ /**
235
+ * Email provider using Nodemailer for SMTP transport.
236
+ *
237
+ * Configuration is provided via environment variables:
238
+ * - EMAIL_HOST: SMTP server host
239
+ * - EMAIL_PORT: SMTP server port (default: 587)
240
+ * - EMAIL_USER: SMTP authentication username
241
+ * - EMAIL_PASS: SMTP authentication password
242
+ * - EMAIL_FROM: Default from email address
243
+ * - EMAIL_SECURE: Use secure connection (default: false)
244
+ *
245
+ * Advanced pooling/rate limiting options can be configured via atom:
246
+ * @see {@link nodemailerEmailOptions}
247
+ *
248
+ * @example
249
+ * ```typescript
250
+ * // Configure via environment variables
251
+ * // EMAIL_HOST=smtp.example.com
252
+ * // EMAIL_PORT=587
253
+ * // EMAIL_USER=user@example.com
254
+ * // EMAIL_PASS=secret
255
+ * // EMAIL_FROM=noreply@example.com
256
+ *
257
+ * // Optionally configure pooling via atom
258
+ * alepha.state.set(nodemailerEmailOptions.key, {
259
+ * pool: true,
260
+ * maxConnections: 5,
261
+ * rateLimit: 10,
262
+ * });
263
+ * ```
264
+ */
197
265
  var NodemailerEmailProvider = class {
198
266
  env = $env(envSchema);
199
267
  log = $logger();
200
- transporter;
201
- fromAddress;
202
- options = {};
203
- constructor() {
204
- this.fromAddress = this.options.from ?? this.env.EMAIL_FROM;
205
- this.transporter = this.createTransporter();
268
+ options = $use(nodemailerEmailOptions);
269
+ transporter = null;
270
+ get host() {
271
+ const host = this.env.EMAIL_HOST;
272
+ if (!host) throw new EmailError("Email host not configured. Set EMAIL_HOST env var.");
273
+ return host;
274
+ }
275
+ get port() {
276
+ return this.env.EMAIL_PORT;
277
+ }
278
+ get secure() {
279
+ return this.env.EMAIL_SECURE;
280
+ }
281
+ get user() {
282
+ return this.env.EMAIL_USER;
283
+ }
284
+ get pass() {
285
+ return this.env.EMAIL_PASS;
286
+ }
287
+ get fromAddress() {
288
+ const from = this.env.EMAIL_FROM;
289
+ if (!from) throw new EmailError("Email from address not configured. Set EMAIL_FROM env var.");
290
+ return from;
291
+ }
292
+ getTransporter() {
293
+ if (!this.transporter) this.transporter = this.createTransporter();
294
+ return this.transporter;
206
295
  }
207
296
  async send(options) {
208
297
  const { to, subject, body } = options;
@@ -211,7 +300,7 @@ var NodemailerEmailProvider = class {
211
300
  subject
212
301
  });
213
302
  try {
214
- const result = await this.transporter.sendMail({
303
+ const result = await this.getTransporter().sendMail({
215
304
  from: this.fromAddress,
216
305
  to,
217
306
  subject,
@@ -233,22 +322,26 @@ var NodemailerEmailProvider = class {
233
322
  }
234
323
  }
235
324
  createTransporter() {
236
- if (this.options.transporter) return this.options.transporter;
237
325
  const transporterConfig = {
238
- host: this.env.EMAIL_HOST,
239
- port: this.env.EMAIL_PORT,
240
- secure: this.env.EMAIL_SECURE,
241
- auth: {
242
- user: this.env.EMAIL_USER,
243
- pass: this.env.EMAIL_PASS
244
- },
245
- ...this.options.options
326
+ host: this.host,
327
+ port: this.port,
328
+ secure: this.secure,
329
+ auth: this.user && this.pass ? {
330
+ user: this.user,
331
+ pass: this.pass
332
+ } : void 0,
333
+ pool: this.options.pool,
334
+ maxConnections: this.options.maxConnections,
335
+ maxMessages: this.options.maxMessages,
336
+ rateDelta: this.options.rateDelta,
337
+ rateLimit: this.options.rateLimit
246
338
  };
247
339
  this.log.debug("Creating Nodemailer transporter", {
248
340
  host: transporterConfig.host,
249
341
  port: transporterConfig.port,
250
342
  secure: transporterConfig.secure,
251
- user: transporterConfig.auth.user
343
+ user: transporterConfig.auth?.user,
344
+ pool: transporterConfig.pool
252
345
  });
253
346
  return nodemailer.createTransport(transporterConfig);
254
347
  }
@@ -257,7 +350,7 @@ var NodemailerEmailProvider = class {
257
350
  */
258
351
  async verify() {
259
352
  try {
260
- await this.transporter.verify();
353
+ await this.getTransporter().verify();
261
354
  this.log.info("Email server connection verified");
262
355
  return true;
263
356
  } catch (error) {
@@ -269,7 +362,10 @@ var NodemailerEmailProvider = class {
269
362
  * Close the transporter connection.
270
363
  */
271
364
  close() {
272
- this.transporter.close();
365
+ if (this.transporter) {
366
+ this.transporter.close();
367
+ this.transporter = null;
368
+ }
273
369
  }
274
370
  onStart = $hook({
275
371
  on: "start",
@@ -327,5 +423,5 @@ const AlephaEmail = $module({
327
423
  });
328
424
 
329
425
  //#endregion
330
- export { $email, AlephaEmail, EmailError, EmailPrimitive, EmailProvider, LocalEmailProvider, MemoryEmailProvider, NodemailerEmailProvider };
426
+ export { $email, AlephaEmail, EmailError, EmailPrimitive, EmailProvider, LocalEmailProvider, MemoryEmailProvider, NodemailerEmailProvider, localEmailOptions, nodemailerEmailOptions };
331
427
  //# sourceMappingURL=index.js.map