stratal 0.0.20 → 0.0.21

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 (113) hide show
  1. package/dist/base-email.provider-CfQCA08m.mjs.map +1 -1
  2. package/dist/bin/cloudflare-workers-loader.mjs.map +1 -1
  3. package/dist/bin/quarry.mjs.map +1 -1
  4. package/dist/cache/index.d.mts +1 -1
  5. package/dist/cache/index.mjs +5 -3
  6. package/dist/cache/index.mjs.map +1 -1
  7. package/dist/command-BgSlsS4M.mjs.map +1 -1
  8. package/dist/{command-Bu-PjJrX.d.mts → command-Cmmf0oHX.d.mts} +2 -2
  9. package/dist/{command-Bu-PjJrX.d.mts.map → command-Cmmf0oHX.d.mts.map} +1 -1
  10. package/dist/config/index.d.mts +1 -1
  11. package/dist/config/index.mjs +5 -3
  12. package/dist/config/index.mjs.map +1 -1
  13. package/dist/{controller.decorator-DQzenvSN.mjs → controller.decorator-B9vwn0zK.mjs} +3 -3
  14. package/dist/{controller.decorator-DQzenvSN.mjs.map → controller.decorator-B9vwn0zK.mjs.map} +1 -1
  15. package/dist/cron/index.d.mts +2 -2
  16. package/dist/cron/index.mjs +1 -1
  17. package/dist/{cron-manager-BEsH1mjW.d.mts → cron-manager-CmTimEjf.d.mts} +2 -2
  18. package/dist/cron-manager-CmTimEjf.d.mts.map +1 -0
  19. package/dist/{cron-manager-7Symz_TE.mjs → cron-manager-DQSK8uoV.mjs} +10 -4
  20. package/dist/cron-manager-DQSK8uoV.mjs.map +1 -0
  21. package/dist/di/index.d.mts +1 -1
  22. package/dist/di/index.mjs +2 -2
  23. package/dist/email/index.d.mts +2 -2
  24. package/dist/email/index.mjs +12 -7
  25. package/dist/email/index.mjs.map +1 -1
  26. package/dist/errors/index.d.mts +1 -1
  27. package/dist/errors/index.mjs +1 -1
  28. package/dist/{errors-BdyV5PnY.mjs → errors-COW9-Mar.mjs} +16 -2
  29. package/dist/{errors-BdyV5PnY.mjs.map → errors-COW9-Mar.mjs.map} +1 -1
  30. package/dist/{errors-Da3Pz2X7.mjs → errors-ORxu1-Bb.mjs} +2 -2
  31. package/dist/{errors-Da3Pz2X7.mjs.map → errors-ORxu1-Bb.mjs.map} +1 -1
  32. package/dist/events/index.mjs +1 -1
  33. package/dist/{events-COKixqnG.mjs → events-CzCV8jI8.mjs} +4 -2
  34. package/dist/{events-COKixqnG.mjs.map → events-CzCV8jI8.mjs.map} +1 -1
  35. package/dist/{gateway-context-CdJjpUCW.mjs → gateway-context-CXmXtaUP.mjs} +4 -3
  36. package/dist/{gateway-context-CdJjpUCW.mjs.map → gateway-context-CXmXtaUP.mjs.map} +1 -1
  37. package/dist/guards/index.d.mts +1 -1
  38. package/dist/guards/index.mjs +1 -1
  39. package/dist/{guards-DUk_Kzst.mjs → guards-DU1_J9YA.mjs} +2 -1
  40. package/dist/{guards-DUk_Kzst.mjs.map → guards-DU1_J9YA.mjs.map} +1 -1
  41. package/dist/{http-method.decorator-DXwxAfb_.mjs → http-method.decorator-BrgHMdLQ.mjs} +2 -2
  42. package/dist/{http-method.decorator-DXwxAfb_.mjs.map → http-method.decorator-BrgHMdLQ.mjs.map} +1 -1
  43. package/dist/i18n/index.d.mts +1 -1
  44. package/dist/i18n/index.mjs +2 -2
  45. package/dist/{i18n.module-BBlNNlcG.mjs → i18n.module-CzXLW9Hy.mjs} +59 -19
  46. package/dist/i18n.module-CzXLW9Hy.mjs.map +1 -0
  47. package/dist/{index-D0US0X14.d.mts → index-ByOyTmqf.d.mts} +6 -3
  48. package/dist/{index-D0US0X14.d.mts.map → index-ByOyTmqf.d.mts.map} +1 -1
  49. package/dist/{index-CjaQ6_tZ.d.mts → index-DUzWs0z7.d.mts} +2 -2
  50. package/dist/{index-CjaQ6_tZ.d.mts.map → index-DUzWs0z7.d.mts.map} +1 -1
  51. package/dist/index.d.mts +1 -1
  52. package/dist/index.mjs +1 -1
  53. package/dist/is-command-C6a7WTPw.mjs.map +1 -1
  54. package/dist/is-seeder-CebjZCDn.mjs.map +1 -1
  55. package/dist/logger/index.mjs +1 -1
  56. package/dist/{logger-V6Ms3QnQ.mjs → logger-DlV7NtvD.mjs} +8 -4
  57. package/dist/{logger-V6Ms3QnQ.mjs.map → logger-DlV7NtvD.mjs.map} +1 -1
  58. package/dist/macroable-BmufBshB.mjs.map +1 -1
  59. package/dist/module/index.d.mts +1 -1
  60. package/dist/module/index.mjs +1 -1
  61. package/dist/{module-Dk2qTa77.mjs → module-BzLg57FK.mjs} +10 -4
  62. package/dist/{module-Dk2qTa77.mjs.map → module-BzLg57FK.mjs.map} +1 -1
  63. package/dist/openapi/index.d.mts +2 -2
  64. package/dist/openapi/index.mjs +1 -1
  65. package/dist/openapi-tools.service-Zs-Ewv7F.mjs.map +1 -1
  66. package/dist/{openapi.service-BLgvn3hJ.d.mts → openapi.service-Bt9bCIrd.d.mts} +2 -2
  67. package/dist/{openapi.service-BLgvn3hJ.d.mts.map → openapi.service-Bt9bCIrd.d.mts.map} +1 -1
  68. package/dist/quarry/index.d.mts +4 -4
  69. package/dist/quarry/index.mjs +1 -1
  70. package/dist/{quarry-registry-DNEej-Db.mjs → quarry-registry-BwY2hOxm.mjs} +15 -4
  71. package/dist/{quarry-registry-DNEej-Db.mjs.map → quarry-registry-BwY2hOxm.mjs.map} +1 -1
  72. package/dist/queue/index.d.mts +1 -1
  73. package/dist/queue/index.mjs +3 -2
  74. package/dist/queue/index.mjs.map +1 -1
  75. package/dist/{queue.module-BCdCiySt.mjs → queue.module-BhCjZp6H.mjs} +13 -4
  76. package/dist/{queue.module-BCdCiySt.mjs.map → queue.module-BhCjZp6H.mjs.map} +1 -1
  77. package/dist/{r2-storage.provider-Co6F0ZYV.mjs → r2-storage.provider-DuonKeYm.mjs} +5 -2
  78. package/dist/{r2-storage.provider-Co6F0ZYV.mjs.map → r2-storage.provider-DuonKeYm.mjs.map} +1 -1
  79. package/dist/{rate-limit.decorator--o6Q6p9w.mjs → rate-limit.decorator-6qzNcSOt.mjs} +2 -2
  80. package/dist/{rate-limit.decorator--o6Q6p9w.mjs.map → rate-limit.decorator-6qzNcSOt.mjs.map} +1 -1
  81. package/dist/rate-limiter/index.d.mts +1 -1
  82. package/dist/rate-limiter/index.mjs +13 -4
  83. package/dist/rate-limiter/index.mjs.map +1 -1
  84. package/dist/{resend.provider-M6qRLrcy.mjs → resend.provider-DB4IlFjG.mjs} +2 -1
  85. package/dist/{resend.provider-M6qRLrcy.mjs.map → resend.provider-DB4IlFjG.mjs.map} +1 -1
  86. package/dist/router/index.d.mts +1 -1
  87. package/dist/router/index.mjs +5 -5
  88. package/dist/seeder/index.d.mts +2 -2
  89. package/dist/seeder/index.mjs +1 -1
  90. package/dist/{seeder-CJAOHEIo.mjs → seeder-zoEfEw9i.mjs} +6 -3
  91. package/dist/{seeder-CJAOHEIo.mjs.map → seeder-zoEfEw9i.mjs.map} +1 -1
  92. package/dist/setup-CefZKV_e.mjs.map +1 -1
  93. package/dist/signed-url-BQPbv2In.mjs.map +1 -1
  94. package/dist/{smtp.provider-w0Ve52Xg.mjs → smtp.provider-B6D7zuWX.mjs} +2 -1
  95. package/dist/{smtp.provider-w0Ve52Xg.mjs.map → smtp.provider-B6D7zuWX.mjs.map} +1 -1
  96. package/dist/storage/index.d.mts +1 -1
  97. package/dist/storage/index.mjs +2 -2
  98. package/dist/storage/providers/index.mjs +1 -1
  99. package/dist/{storage-1zw-6Yiz.mjs → storage-D8CBP72Z.mjs} +13 -8
  100. package/dist/{storage-1zw-6Yiz.mjs.map → storage-D8CBP72Z.mjs.map} +1 -1
  101. package/dist/{stratal-DeEcGgdq.mjs → stratal-CNwpbSZl.mjs} +12 -10
  102. package/dist/{stratal-DeEcGgdq.mjs.map → stratal-CNwpbSZl.mjs.map} +1 -1
  103. package/dist/usage-generator-BUdlhnCK.mjs.map +1 -1
  104. package/dist/validation-DtJwAv7O.mjs.map +1 -1
  105. package/dist/websocket/index.d.mts +1 -1
  106. package/dist/websocket/index.mjs +1 -1
  107. package/dist/workers/index.d.mts +1 -1
  108. package/dist/workers/index.mjs +2 -2
  109. package/dist/workers/index.mjs.map +1 -1
  110. package/package.json +13 -13
  111. package/dist/cron-manager-7Symz_TE.mjs.map +0 -1
  112. package/dist/cron-manager-BEsH1mjW.d.mts.map +0 -1
  113. package/dist/i18n.module-BBlNNlcG.mjs.map +0 -1
@@ -1,5 +1,5 @@
1
- import { H as ApplicationError, k as ERROR_CODES } from "./errors-BdyV5PnY.mjs";
2
- import { a as __decorate, p as Transient } from "./logger-V6Ms3QnQ.mjs";
1
+ import { H as ApplicationError, k as ERROR_CODES } from "./errors-COW9-Mar.mjs";
2
+ import { a as __decorate, p as Transient, u as LOGGER_TOKENS } from "./logger-DlV7NtvD.mjs";
3
3
  //#region src/cron/errors/cron-execution.error.ts
4
4
  /**
5
5
  * Error thrown when one or more cron jobs fail execution
@@ -58,7 +58,13 @@ let CronManager = class CronManager {
58
58
  async executeScheduled(controller, container) {
59
59
  const { cron } = controller;
60
60
  const matchingJobs = this.jobs.get(cron) ?? [];
61
- if (matchingJobs.length === 0) return;
61
+ if (matchingJobs.length === 0) {
62
+ container.resolve(LOGGER_TOKENS.LoggerService).warn("No cron jobs matched scheduled trigger", {
63
+ incomingCron: cron,
64
+ registeredSchedules: Array.from(this.jobs.keys())
65
+ });
66
+ return;
67
+ }
62
68
  const errors = [];
63
69
  for (const { jobClass } of matchingJobs) {
64
70
  const jobName = jobClass.name;
@@ -114,4 +120,4 @@ CronManager = __decorate([Transient()], CronManager);
114
120
  //#endregion
115
121
  export { CronExecutionError as n, CronManager as t };
116
122
 
117
- //# sourceMappingURL=cron-manager-7Symz_TE.mjs.map
123
+ //# sourceMappingURL=cron-manager-DQSK8uoV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cron-manager-DQSK8uoV.mjs","names":[],"sources":["../src/cron/errors/cron-execution.error.ts","../src/cron/cron-manager.ts"],"sourcesContent":["import { ApplicationError } from '../../errors'\nimport { ERROR_CODES } from '../../errors'\n\n/**\n * Error thrown when one or more cron jobs fail execution\n *\n * This error aggregates failures from multiple jobs that share the same schedule.\n */\nexport class CronExecutionError extends ApplicationError {\n\tconstructor(\n\t\tschedule: string,\n\t\tfailedJobsCount: number,\n\t\tjobNames: string\n\t) {\n\t\tsuper(\n\t\t\t'errors.cronExecutionFailed',\n\t\t\tERROR_CODES.SYSTEM.CRON_EXECUTION_FAILED,\n\t\t\t{\n\t\t\t\tschedule,\n\t\t\t\tcount: failedJobsCount,\n\t\t\t\tjobs: jobNames\n\t\t\t}\n\t\t)\n\t}\n}\n","import type { Container } from '../di/container'\nimport { Transient } from '../di/decorators'\nimport { LOGGER_TOKENS } from '../logger/logger.tokens'\nimport type { LoggerService } from '../logger/services/logger.service'\nimport type { CronJob, RegisteredJob } from './cron-job'\nimport { CronExecutionError } from './errors/cron-execution.error'\n\n/**\n * Manages cron job registration and execution\n *\n * CronManager is a singleton service that:\n * - Registers cron job class references from modules\n * - Routes scheduled events to matching jobs\n * - Resolves jobs from a request-scoped container at execution time\n *\n * Jobs are grouped by their cron expression, allowing multiple jobs\n * to run on the same schedule.\n */\n@Transient()\nexport class CronManager {\n\t/**\n\t * Map of cron expressions to registered job entries\n\t * Key: Cron expression (e.g., '0 2 * * *')\n\t * Value: Array of registered jobs (class ref + schedule)\n\t */\n\tprivate jobs = new Map<string, RegisteredJob[]>()\n\n\t/**\n\t * Register a cron job class\n\t *\n\t * Jobs with the same schedule are grouped together and executed\n\t * sequentially when the trigger fires.\n\t *\n\t * @param schedule - Cron expression (e.g., '0 2 * * *')\n\t * @param jobClass - CronJob class constructor (resolved at execution time)\n\t */\n\tregisterJob(schedule: string, jobClass: RegisteredJob['jobClass']): void {\n\t\tconst existing = this.jobs.get(schedule) ?? []\n\t\texisting.push({ schedule, jobClass })\n\t\tthis.jobs.set(schedule, existing)\n\t}\n\n\t/**\n\t * Execute all jobs matching the triggered cron expression\n\t *\n\t * Jobs are resolved from the provided request-scoped container,\n\t * ensuring dependencies (e.g. database) are properly scoped.\n\t *\n\t * Jobs are executed sequentially. If a job fails:\n\t * - Its onError() hook is called (if defined)\n\t * - Execution continues with the next job\n\t * - Errors are collected and thrown as CronExecutionError\n\t *\n\t * @param controller - Cloudflare ScheduledController\n\t * @param container - Request-scoped container to resolve jobs from\n\t */\n\tasync executeScheduled(controller: ScheduledController, container: Container): Promise<void> {\n\t\tconst { cron } = controller\n\t\tconst matchingJobs = this.jobs.get(cron) ?? []\n\n\t\tif (matchingJobs.length === 0) {\n\t\t\tconst logger = container.resolve<LoggerService>(LOGGER_TOKENS.LoggerService)\n\t\t\tlogger.warn('No cron jobs matched scheduled trigger', {\n\t\t\t\tincomingCron: cron,\n\t\t\t\tregisteredSchedules: Array.from(this.jobs.keys()),\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tconst errors: { job: string; error: Error }[] = []\n\n\t\tfor (const { jobClass } of matchingJobs) {\n\t\t\tconst jobName = jobClass.name\n\n\t\t\ttry {\n\t\t\t\t// Register the job class in the request-scoped container so its\n\t\t\t\t// dependencies are resolved from request scope (not the parent).\n\t\t\t\t// Without this, tsyringe falls through to the parent container\n\t\t\t\t// and request-scoped services (e.g. database) get stale instances.\n\t\t\t\tcontainer.register(jobClass, jobClass)\n\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\tawait job.execute(controller)\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error\n\t\t\t\terrors.push({ job: jobName, error: err })\n\n\t\t\t\t// Try to resolve and call onError if possible\n\t\t\t\ttry {\n\t\t\t\t\tconst job = container.resolve<CronJob>(jobClass)\n\t\t\t\t\tif (job.onError) {\n\t\t\t\t\t\tawait job.onError(err, controller)\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// If resolution or onError fails, continue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If any jobs failed, throw an aggregate error\n\t\t// This ensures the error is logged by ExceptionHandler\n\t\tif (errors.length > 0) {\n\t\t\tconst jobNames = errors\n\t\t\t\t.map(({ job, error }) => `${job}: ${error.message}`)\n\t\t\t\t.join('; ')\n\n\t\t\tthrow new CronExecutionError(cron, errors.length, jobNames)\n\t\t}\n\t}\n\n\t/**\n\t * Get all registered jobs for a specific cron expression\n\t *\n\t * @param schedule - Cron expression\n\t * @returns Array of registered jobs, or empty array if none\n\t */\n\tgetJobsForSchedule(schedule: string): RegisteredJob[] {\n\t\treturn this.jobs.get(schedule) ?? []\n\t}\n\n\t/**\n\t * Get all registered cron expressions\n\t *\n\t * @returns Array of unique cron expressions\n\t */\n\tgetAllSchedules(): string[] {\n\t\treturn Array.from(this.jobs.keys())\n\t}\n\n\t/**\n\t * Get total number of registered jobs across all schedules\n\t *\n\t * @returns Total job count\n\t */\n\tgetTotalJobCount(): number {\n\t\tlet count = 0\n\t\tfor (const jobs of this.jobs.values()) {\n\t\t\tcount += jobs.length\n\t\t}\n\t\treturn count\n\t}\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,qBAAb,cAAwC,iBAAiB;CACxD,YACC,UACA,iBACA,UACC;EACD,MACC,8BACA,YAAY,OAAO,uBACnB;GACC;GACA,OAAO;GACP,MAAM;GACN,CACD;;;;;ACHI,IAAA,cAAA,MAAM,YAAY;;;;;;CAMxB,uBAAe,IAAI,KAA8B;;;;;;;;;;CAWjD,YAAY,UAAkB,UAA2C;EACxE,MAAM,WAAW,KAAK,KAAK,IAAI,SAAS,IAAI,EAAE;EAC9C,SAAS,KAAK;GAAE;GAAU;GAAU,CAAC;EACrC,KAAK,KAAK,IAAI,UAAU,SAAS;;;;;;;;;;;;;;;;CAiBlC,MAAM,iBAAiB,YAAiC,WAAqC;EAC5F,MAAM,EAAE,SAAS;EACjB,MAAM,eAAe,KAAK,KAAK,IAAI,KAAK,IAAI,EAAE;EAE9C,IAAI,aAAa,WAAW,GAAG;GAE9B,UADyB,QAAuB,cAAc,cACxD,CAAC,KAAK,0CAA0C;IACrD,cAAc;IACd,qBAAqB,MAAM,KAAK,KAAK,KAAK,MAAM,CAAC;IACjD,CAAC;GACF;;EAGD,MAAM,SAA0C,EAAE;EAElD,KAAK,MAAM,EAAE,cAAc,cAAc;GACxC,MAAM,UAAU,SAAS;GAEzB,IAAI;IAKH,UAAU,SAAS,UAAU,SAAS;IAEtC,MADY,UAAU,QAAiB,SAC9B,CAAC,QAAQ,WAAW;YACrB,OAAO;IACf,MAAM,MAAM;IACZ,OAAO,KAAK;KAAE,KAAK;KAAS,OAAO;KAAK,CAAC;IAGzC,IAAI;KACH,MAAM,MAAM,UAAU,QAAiB,SAAS;KAChD,IAAI,IAAI,SACP,MAAM,IAAI,QAAQ,KAAK,WAAW;YAE5B;;;EAQV,IAAI,OAAO,SAAS,GAAG;GACtB,MAAM,WAAW,OACf,KAAK,EAAE,KAAK,YAAY,GAAG,IAAI,IAAI,MAAM,UAAU,CACnD,KAAK,KAAK;GAEZ,MAAM,IAAI,mBAAmB,MAAM,OAAO,QAAQ,SAAS;;;;;;;;;CAU7D,mBAAmB,UAAmC;EACrD,OAAO,KAAK,KAAK,IAAI,SAAS,IAAI,EAAE;;;;;;;CAQrC,kBAA4B;EAC3B,OAAO,MAAM,KAAK,KAAK,KAAK,MAAM,CAAC;;;;;;;CAQpC,mBAA2B;EAC1B,IAAI,QAAQ;EACZ,KAAK,MAAM,QAAQ,KAAK,KAAK,QAAQ,EACpC,SAAS,KAAK;EAEf,OAAO;;;0BAxHR,WAAW,CAAA,EAAA,YAAA"}
@@ -1,2 +1,2 @@
1
- import { Ar as container, Br as PredicateContainer, Dr as Container, Fr as singleton, Hr as ExtensionDecorator, Ir as ConditionalBindingBuilder, Lr as ConditionalBindingBuilderImpl, Mr as inject, Nr as injectable, Or as ContainerOptions, Pr as instancePerContainerCachingFactory, Rr as ConditionalBindingGive, Ur as Scope, Vr as ContainerLike, Wr as WhenOptions, _r as DIToken, cr as runWithContainer, dr as Transient, fr as INJECT_PARAM_METADATA_KEY, gr as CONTAINER_TOKEN, hr as getMethodInjections, jr as delay, kr as DependencyContainer, lr as RequestScopeOperationNotAllowedError, mr as ParamInjection, or as containerStorage, pr as InjectParam, sr as getContainer, ur as ConditionalBindingFallbackError, vr as DI_TOKENS, zr as ConditionalBindingUse } from "../index-D0US0X14.mjs";
1
+ import { Ar as container, Br as PredicateContainer, Dr as Container, Fr as singleton, Hr as ExtensionDecorator, Ir as ConditionalBindingBuilder, Lr as ConditionalBindingBuilderImpl, Mr as inject, Nr as injectable, Or as ContainerOptions, Pr as instancePerContainerCachingFactory, Rr as ConditionalBindingGive, Ur as Scope, Vr as ContainerLike, Wr as WhenOptions, _r as DIToken, cr as runWithContainer, dr as Transient, fr as INJECT_PARAM_METADATA_KEY, gr as CONTAINER_TOKEN, hr as getMethodInjections, jr as delay, kr as DependencyContainer, lr as RequestScopeOperationNotAllowedError, mr as ParamInjection, or as containerStorage, pr as InjectParam, sr as getContainer, ur as ConditionalBindingFallbackError, vr as DI_TOKENS, zr as ConditionalBindingUse } from "../index-ByOyTmqf.mjs";
2
2
  export { CONTAINER_TOKEN, ConditionalBindingBuilder, ConditionalBindingBuilderImpl, ConditionalBindingFallbackError, ConditionalBindingGive, ConditionalBindingUse, Container, ContainerLike, ContainerOptions, DIToken, DI_TOKENS, DependencyContainer, ExtensionDecorator, INJECT_PARAM_METADATA_KEY, InjectParam, ParamInjection, PredicateContainer, RequestScopeOperationNotAllowedError, Scope, Transient, WhenOptions, container, containerStorage, delay, getContainer, getMethodInjections, inject, injectable, instancePerContainerCachingFactory, runWithContainer, singleton };
package/dist/di/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { A as Scope, B as ConditionalBindingFallbackError, D as runWithContainer, E as getContainer, F as injectable, I as instancePerContainerCachingFactory, L as singleton, M as container, N as delay, P as inject, R as ConditionalBindingBuilderImpl, T as containerStorage, j as Container, z as RequestScopeOperationNotAllowedError } from "../errors-BdyV5PnY.mjs";
2
- import { d as CONTAINER_TOKEN, f as DI_TOKENS, g as getMethodInjections, h as InjectParam, m as INJECT_PARAM_METADATA_KEY, p as Transient } from "../logger-V6Ms3QnQ.mjs";
1
+ import { A as Scope, B as ConditionalBindingFallbackError, D as runWithContainer, E as getContainer, F as injectable, I as instancePerContainerCachingFactory, L as singleton, M as container, N as delay, P as inject, R as ConditionalBindingBuilderImpl, T as containerStorage, j as Container, z as RequestScopeOperationNotAllowedError } from "../errors-COW9-Mar.mjs";
2
+ import { d as CONTAINER_TOKEN, f as DI_TOKENS, g as getMethodInjections, h as InjectParam, m as INJECT_PARAM_METADATA_KEY, p as Transient } from "../logger-DlV7NtvD.mjs";
3
3
  export { CONTAINER_TOKEN, ConditionalBindingBuilderImpl, ConditionalBindingFallbackError, Container, DI_TOKENS, INJECT_PARAM_METADATA_KEY, InjectParam, RequestScopeOperationNotAllowedError, Scope, Transient, container, containerStorage, delay, getContainer, getMethodInjections, inject, injectable, instancePerContainerCachingFactory, runWithContainer, singleton };
@@ -1,6 +1,6 @@
1
- import { d as ApplicationError, gn as AsyncModuleOptions, vn as DynamicModule } from "../index-D0US0X14.mjs";
1
+ import { d as ApplicationError, gn as AsyncModuleOptions, vn as DynamicModule } from "../index-ByOyTmqf.mjs";
2
2
  import { o as z } from "../index-Bnpfq6uk.mjs";
3
- import { g as QueueName, h as IQueueSender } from "../index-CjaQ6_tZ.mjs";
3
+ import { g as QueueName, h as IQueueSender } from "../index-DUzWs0z7.mjs";
4
4
  import { ReactElement } from "react";
5
5
 
6
6
  //#region src/email/email.module.d.ts
@@ -1,10 +1,10 @@
1
- import { H as ApplicationError, k as ERROR_CODES } from "../errors-BdyV5PnY.mjs";
2
- import { a as __decorate, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "../logger-V6Ms3QnQ.mjs";
3
- import { k as Module } from "../module-Dk2qTa77.mjs";
1
+ import { H as ApplicationError, k as ERROR_CODES } from "../errors-COW9-Mar.mjs";
2
+ import { a as __decorate, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "../logger-DlV7NtvD.mjs";
3
+ import { k as Module } from "../module-BzLg57FK.mjs";
4
4
  import { i as z, s as withI18n } from "../validation-DtJwAv7O.mjs";
5
- import { c as QUEUE_TOKENS } from "../queue.module-BCdCiySt.mjs";
5
+ import { c as QUEUE_TOKENS } from "../queue.module-BhCjZp6H.mjs";
6
6
  import "../queue/index.mjs";
7
- import { u as STORAGE_TOKENS } from "../storage-1zw-6Yiz.mjs";
7
+ import { u as STORAGE_TOKENS } from "../storage-D8CBP72Z.mjs";
8
8
  import { inject } from "tsyringe";
9
9
  import { render } from "@react-email/render";
10
10
  //#region src/email/email.tokens.ts
@@ -43,6 +43,9 @@ const EMAIL_TOKENS = {
43
43
  //#endregion
44
44
  //#region src/email/consumers/email.consumer.ts
45
45
  let EmailConsumer = class EmailConsumer {
46
+ logger;
47
+ providerFactory;
48
+ storage;
46
49
  messageTypes = ["email.send", "email.batch.send"];
47
50
  constructor(logger, providerFactory, storage) {
48
51
  this.logger = logger;
@@ -126,6 +129,7 @@ EmailConsumer = __decorate([
126
129
  //#endregion
127
130
  //#region src/email/services/email.service.ts
128
131
  let EmailService = class EmailService {
132
+ queue;
129
133
  constructor(queue) {
130
134
  this.queue = queue;
131
135
  }
@@ -259,6 +263,7 @@ var EmailProviderNotSupportedError = class extends ApplicationError {
259
263
  //#endregion
260
264
  //#region src/email/services/email-provider-factory.ts
261
265
  let EmailProviderFactory = class EmailProviderFactory {
266
+ options;
262
267
  constructor(options) {
263
268
  this.options = options;
264
269
  }
@@ -271,11 +276,11 @@ let EmailProviderFactory = class EmailProviderFactory {
271
276
  async create() {
272
277
  switch (this.options.provider) {
273
278
  case "resend": {
274
- const { ResendProvider } = await import("../resend.provider-M6qRLrcy.mjs");
279
+ const { ResendProvider } = await import("../resend.provider-DB4IlFjG.mjs");
275
280
  return new ResendProvider(this.options);
276
281
  }
277
282
  case "smtp": {
278
- const { SmtpProvider } = await import("../smtp.provider-w0Ve52Xg.mjs");
283
+ const { SmtpProvider } = await import("../smtp.provider-B6D7zuWX.mjs");
279
284
  return new SmtpProvider(this.options);
280
285
  }
281
286
  default: throw new EmailProviderNotSupportedError(this.options.provider);
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../src/email/email.tokens.ts","../../src/email/consumers/email.consumer.ts","../../src/email/services/email.service.ts","../../src/email/errors/resend-api-key-missing.error.ts","../../src/email/errors/smtp-configuration-missing.error.ts","../../src/email/errors/smtp-host-missing.error.ts","../../src/email/errors/email-smtp-connection-failed.error.ts","../../src/email/errors/email-resend-api-failed.error.ts","../../src/email/errors/email-provider-not-supported.error.ts","../../src/email/services/email-provider-factory.ts","../../src/email/email.module.ts","../../src/email/contracts/email-attachment.ts","../../src/email/contracts/email-message.contract.ts","../../src/email/contracts/send-email.input.ts"],"sourcesContent":["/**\n * Dependency Injection Tokens for Email Module\n *\n * These Symbol-based tokens ensure type-safe dependency injection\n * throughout the email module and prevent naming collisions.\n */\n\n/**\n * Email Module DI Tokens\n */\nexport const EMAIL_TOKENS = {\n /**\n * Email module configuration options\n */\n Options: Symbol.for('stratal:email:options'),\n\n /**\n * Main email service - facade for sending emails via queues\n */\n EmailService: Symbol.for('stratal:email:service'),\n\n /**\n * Factory for creating email provider instances based on configuration\n */\n EmailProviderFactory: Symbol.for('stratal:email:provider:factory'),\n\n /**\n * Email provider interface - abstracts provider implementation\n */\n EmailProvider: Symbol.for('stratal:email:provider'),\n\n /**\n * Queue sender for email dispatch.\n * Bound via EmailModule.forRoot({ queue: 'queue-name' })\n */\n EmailQueue: Symbol.for('stratal:email:queue'),\n} as const\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { LOGGER_TOKENS, type LoggerService } from '../../logger'\nimport type { IQueueConsumer, QueueMessage } from '../../queue/queue-consumer'\nimport { STORAGE_TOKENS, type StorageService } from '../../storage'\nimport type { EmailAttachment, ResolvedEmailAttachment, SendEmailInput } from '../contracts'\nimport { EMAIL_TOKENS } from '../email.tokens'\nimport type { EmailProviderFactory } from '../services/email-provider-factory'\n\n/**\n * Email Consumer\n *\n * Generic queue consumer that handles email.send and email.batch.send messages\n * from ANY queue. Message routing is based on message type, not queue name.\n *\n * This consumer:\n * - Resolves storage-based attachments to streams\n * - Creates email provider instances via factory\n * - Sends emails with proper logging (no PII)\n * - Handles errors with retry support\n *\n * @example\n * ```typescript\n * // Registered in EmailModule\n * @Module({\n * consumers: [EmailConsumer]\n * })\n * ```\n */\n@Transient()\nexport class EmailConsumer implements IQueueConsumer<SendEmailInput> {\n readonly messageTypes = ['email.send', 'email.batch.send']\n\n constructor(\n @inject(LOGGER_TOKENS.LoggerService)\n private readonly logger: LoggerService,\n @inject(EMAIL_TOKENS.EmailProviderFactory)\n private readonly providerFactory: EmailProviderFactory,\n @inject(STORAGE_TOKENS.StorageService)\n private readonly storage: StorageService\n ) { }\n\n async handle(message: QueueMessage<SendEmailInput>): Promise<void> {\n const { type, payload } = message\n const recipientCount = Array.isArray(payload.to) ? payload.to.length : 1\n\n this.logger.info('Processing email message', {\n type,\n recipientCount,\n hasHtml: !!payload.html,\n hasText: !!payload.text,\n hasAttachments: !!payload.attachments?.length,\n })\n\n try {\n // Resolve storage-based attachments before sending\n const resolvedAttachments = await this.resolveAttachments(payload.attachments)\n\n const provider = await this.providerFactory.create()\n const result = await provider.send({\n ...payload,\n attachments: resolvedAttachments,\n })\n\n this.logger.info('Email sent successfully', {\n type,\n recipientCount,\n messageId: result.messageId,\n })\n }\n catch (error) {\n this.logger.error('Failed to send email', {\n type,\n recipientCount,\n error: (error as Error).message,\n })\n throw error // Retry via queue\n }\n }\n\n onError(error: Error, message: QueueMessage<SendEmailInput>): Promise<void> {\n const recipientCount = Array.isArray(message.payload.to)\n ? message.payload.to.length\n : 1\n\n this.logger.error('Email send failed after retries', {\n recipientCount,\n error: error.message,\n stack: error.stack,\n })\n\n return Promise.resolve()\n }\n\n /**\n * Resolve email attachments\n *\n * Converts attachment schemas to resolved attachments.\n * - Inline attachments: decode base64 to Buffer\n * - Storage attachments: pass stream directly (providers support streams)\n */\n private async resolveAttachments(\n attachments: EmailAttachment[] | undefined\n ): Promise<ResolvedEmailAttachment[] | undefined> {\n if (!attachments?.length) return undefined\n\n return Promise.all(attachments.map(async (attachment) => {\n // Check for inline attachment (has content property)\n if ('content' in attachment) {\n return {\n filename: attachment.filename,\n content: Buffer.from(attachment.content, 'base64'),\n contentType: attachment.contentType,\n }\n }\n\n // Storage attachment - pass stream directly to provider\n const result = await this.storage.download(\n attachment.storageKey,\n attachment.disk\n )\n\n return {\n filename: attachment.filename,\n content: result.toStream() ?? Buffer.alloc(0),\n contentType: result.contentType,\n }\n }))\n }\n}\n","import { render } from '@react-email/render'\nimport type { ReactElement } from 'react'\nimport { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport type { IQueueSender } from '../../queue'\nimport type { SendBatchEmailInput, SendEmailInput } from '../contracts'\nimport { EMAIL_TOKENS } from '../email.tokens'\n\nexport type SendEmailInputWithTemplate = Omit<SendEmailInput, 'html' | 'text'> & {\n template?: ReactElement\n}\n\nexport type SendBatchEmailInputWithTemplate = Omit<SendBatchEmailInput, 'messages'> & {\n messages: SendEmailInputWithTemplate[]\n}\n\n/**\n * Email Service\n *\n * Main facade for sending emails. Routes emails to queues for async processing.\n * The queue is injected via EMAIL_TOKENS.EmailQueue, configured by the application\n * via EmailModule.forRoot({ queue: 'queue-name' }).\n *\n * @example Basic usage\n * ```typescript\n * @inject(EMAIL_TOKENS.EmailService)\n * private readonly emailService: EmailService\n *\n * await this.emailService.send({\n * to: 'user@example.com',\n * subject: 'Welcome',\n * template: <WelcomeEmail name=\"John\" />\n * })\n * ```\n */\n@Transient(EMAIL_TOKENS.EmailService)\nexport class EmailService {\n constructor(\n @inject(EMAIL_TOKENS.EmailQueue)\n protected readonly queue: IQueueSender\n ) { }\n\n /**\n * Send a single email\n *\n * Dispatches the email to the queue for async processing.\n * Supports optional React template rendering.\n *\n * @param input - Email message details\n */\n async send({ template, ...input }: SendEmailInputWithTemplate): Promise<void> {\n await this.queue.dispatch({\n type: 'email.send',\n payload: { ...input, html: template ? await render(template) : undefined },\n })\n }\n\n /**\n * Send multiple emails in a batch\n *\n * Dispatches all emails to the queue for async processing.\n * Supports React template rendering for each message.\n *\n * @param input - Batch email details\n */\n async sendBatch(input: SendBatchEmailInputWithTemplate): Promise<void> {\n for (const message of input.messages) {\n await this.send(message)\n }\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * ResendApiKeyMissingError\n *\n * Thrown when the Resend API key is not configured in environment variables.\n * This prevents the Resend email provider from initializing.\n *\n * Resolution: Set the RESEND_EMAIL_API_KEY environment variable.\n */\nexport class ResendApiKeyMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.resendApiKeyMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * SmtpConfigurationMissingError\n *\n * Thrown when SMTP configuration is not found in environment variables.\n * This prevents the SMTP email provider from initializing.\n *\n * Resolution: Set the SMTP_URL environment variable with format: smtp://user:pass@host:port\n */\nexport class SmtpConfigurationMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.smtpConfigurationMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * SmtpHostMissingError\n *\n * Thrown when SMTP host could not be parsed from SMTP_URL or is empty.\n * This prevents the SMTP email provider from initializing.\n *\n * Resolution: Ensure SMTP_URL is correctly formatted: smtp://user:pass@host:port\n */\nexport class SmtpHostMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.smtpHostMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailSmtpConnectionFailedError\n *\n * Thrown when connection to SMTP server fails during email sending.\n * This is a runtime error that may be temporary.\n *\n * Resolution: Check SMTP server availability, network connectivity, or wait and retry.\n */\nexport class EmailSmtpConnectionFailedError extends ApplicationError {\n constructor(smtpHost: string, smtpPort: number) {\n super(\n 'errors.email.smtpConnectionFailed',\n ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR,\n { smtpHost, smtpPort }\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailResendApiFailedError\n *\n * Thrown when Resend API returns an error during email sending.\n * This is a runtime error from the Resend service.\n *\n * Resolution: Check Resend API status, API key validity, or wait and retry.\n */\nexport class EmailResendApiFailedError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.resendApiFailed',\n ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR,\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailProviderNotSupportedError\n *\n * Thrown when an unsupported email provider is configured.\n * Only 'resend' and 'smtp' providers are currently supported.\n *\n * Resolution: Set EMAIL_PROVIDER to either 'resend' or 'smtp'.\n */\nexport class EmailProviderNotSupportedError extends ApplicationError {\n constructor(provider: string) {\n super(\n 'errors.email.providerNotSupported',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR,\n { provider }\n )\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport type { EmailModuleOptions } from '../email.module'\nimport { EMAIL_TOKENS } from '../email.tokens'\nimport { EmailProviderNotSupportedError } from '../errors'\nimport type { IEmailProvider } from '../providers/email-provider.interface'\n\n/**\n * Email Provider Factory\n *\n * Creates email provider instances based on configuration.\n * Supports automatic provider selection from module options.\n *\n * Providers are loaded lazily via dynamic imports to avoid pulling in\n * heavy Node.js-only dependencies (e.g. nodemailer) at module parse time,\n * which would break Cloudflare Workers and vitest-pool-workers environments.\n */\n@Transient(EMAIL_TOKENS.EmailProviderFactory)\nexport class EmailProviderFactory {\n constructor(\n @inject(EMAIL_TOKENS.Options)\n private readonly options: EmailModuleOptions\n ) { }\n\n /**\n * Create email provider instance based on configuration\n *\n * @returns Email provider implementation\n * @throws EmailProviderNotSupportedError if provider is not supported\n */\n async create(): Promise<IEmailProvider> {\n switch (this.options.provider) {\n case 'resend': {\n const { ResendProvider } = await import('../providers/resend.provider')\n return new ResendProvider(this.options)\n }\n\n case 'smtp': {\n const { SmtpProvider } = await import('../providers/smtp.provider')\n return new SmtpProvider(this.options)\n }\n\n default:\n throw new EmailProviderNotSupportedError(this.options.provider)\n }\n }\n}\n","/**\n * Email Module\n *\n * Provides email sending capabilities with provider abstraction.\n * Supports multiple email providers (Resend, SMTP) with automatic provider selection.\n * Emails are sent asynchronously via Cloudflare Queues.\n *\n * **Usage:**\n * ```typescript\n * // In AppModule imports with static options\n * EmailModule.forRoot({\n * provider: 'resend',\n * apiKey: 'your-api-key',\n * from: { name: 'App', email: 'noreply@example.com' },\n * queue: 'notifications-queue',\n * })\n *\n * // Or with async options from config namespaces\n * EmailModule.forRootAsync({\n * inject: [emailConfig.KEY],\n * useFactory: (email) => ({\n * provider: email.provider,\n * apiKey: email.apiKey,\n * from: email.from,\n * queue: email.queue,\n * }),\n * })\n *\n * // In your service\n * @inject(EMAIL_TOKENS.EmailService)\n * private readonly emailService: EmailService\n *\n * await this.emailService.send({\n * to: 'user@example.com',\n * subject: 'Welcome',\n * template: <WelcomeEmail name=\"John\" />\n * })\n * ```\n */\n\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule } from '../module/types'\nimport type { QueueName } from '../queue'\nimport { QUEUE_TOKENS, type QueueRegistry } from '../queue'\nimport { EmailConsumer } from './consumers/email.consumer'\nimport { EMAIL_TOKENS } from './email.tokens'\nimport { EmailProviderFactory, EmailService } from './services'\n\n/**\n * SMTP configuration options\n */\nexport interface SmtpConfig {\n /** SMTP server host */\n host: string\n /** SMTP server port */\n port: number\n /** Use TLS */\n secure?: boolean\n /** SMTP username */\n username?: string\n /** SMTP password */\n password?: string\n}\n\n/**\n * Email module configuration options\n */\nexport interface EmailModuleOptions {\n /** Email provider type */\n provider: 'resend' | 'smtp'\n\n /** Default from address */\n from: { name: string; email: string }\n\n /** Resend API key (required for resend provider) */\n apiKey?: string\n\n /** SMTP configuration (required for smtp provider) */\n smtp?: SmtpConfig\n\n /** Default reply-to address */\n replyTo?: string\n\n /**\n * Queue name for email dispatch.\n * The queue must be registered via QueueModule.registerQueue(name).\n */\n queue: QueueName\n}\n\n@Module({\n providers: [\n { provide: EMAIL_TOKENS.EmailService, useClass: EmailService },\n { provide: EMAIL_TOKENS.EmailProviderFactory, useClass: EmailProviderFactory },\n ],\n consumers: [EmailConsumer],\n})\nexport class EmailModule {\n /**\n * Configure EmailModule with static options\n *\n * @param options - Email configuration options\n * @returns Dynamic module with email infrastructure\n *\n * @example\n * ```typescript\n * EmailModule.forRoot({\n * provider: 'resend',\n * apiKey: env.RESEND_API_KEY,\n * from: { name: 'App', email: 'noreply@example.com' },\n * queue: 'notifications-queue',\n * })\n * ```\n */\n static forRoot(options: EmailModuleOptions): DynamicModule {\n return {\n module: EmailModule,\n providers: [\n { provide: EMAIL_TOKENS.Options, useValue: options },\n { provide: EMAIL_TOKENS.EmailQueue, useExisting: options.queue },\n ],\n }\n }\n\n /**\n * Configure EmailModule with async factory\n *\n * Use when configuration depends on other services.\n *\n * @param options - Async configuration with factory and inject tokens\n * @returns Dynamic module with email infrastructure\n *\n * @example\n * ```typescript\n * EmailModule.forRootAsync({\n * inject: [emailConfig.KEY],\n * useFactory: (email) => ({\n * provider: email.provider,\n * apiKey: email.apiKey,\n * from: email.from,\n * smtp: email.smtp,\n * queue: email.queue,\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<EmailModuleOptions>): DynamicModule {\n return {\n module: EmailModule,\n providers: [\n {\n provide: EMAIL_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n // Resolve queue from QueueRegistry using the queue name from options\n {\n provide: EMAIL_TOKENS.EmailQueue,\n useFactory: (emailOptions: EmailModuleOptions, registry: QueueRegistry) =>\n registry.getQueue(emailOptions.queue),\n inject: [EMAIL_TOKENS.Options, QUEUE_TOKENS.QueueRegistry],\n },\n ],\n }\n }\n}\n","import { z } from '../../i18n/validation'\n\n/**\n * Inline Email Attachment Schema\n *\n * Attachment with content embedded as base64 string.\n * Use for small files that can fit in queue message.\n */\nexport const inlineEmailAttachmentSchema = z.object({\n /**\n * Filename to display for the attachment\n */\n filename: z.string().min(1).max(255),\n\n /**\n * Base64 encoded content of the attachment\n */\n content: z.string(),\n\n /**\n * MIME type of the attachment (e.g., 'application/pdf', 'image/png')\n */\n contentType: z.string(),\n\n /**\n * Optional size of the attachment in bytes\n */\n size: z.number().positive().optional(),\n})\n\n/**\n * Storage Email Attachment Schema\n *\n * Attachment stored in cloud storage.\n * Content type and size are derived from storage metadata.\n * Use for large files to avoid queue message size limits.\n */\nexport const storageEmailAttachmentSchema = z.object({\n /**\n * Filename to display for the attachment\n */\n filename: z.string().min(1).max(255),\n\n /**\n * Path to the file in storage\n */\n storageKey: z.string(),\n\n /**\n * Optional storage disk name (uses default if not provided)\n */\n disk: z.string().optional(),\n})\n\n/**\n * Email Attachment Schema\n *\n * Union type - type is inferred from presence of `content` vs `storageKey`.\n * - If `content` is present: inline attachment\n * - If `storageKey` is present: storage-based attachment\n */\nexport const emailAttachmentSchema = z.union([\n inlineEmailAttachmentSchema,\n storageEmailAttachmentSchema,\n])\n\n/**\n * Type definitions\n */\nexport type InlineEmailAttachment = z.infer<typeof inlineEmailAttachmentSchema>\nexport type StorageEmailAttachment = z.infer<typeof storageEmailAttachmentSchema>\nexport type EmailAttachment = z.infer<typeof emailAttachmentSchema>\n\n/**\n * Resolved Email Attachment\n *\n * Attachment after resolution, ready for email provider.\n * Content can be Buffer (for inline) or ReadableStream (for storage-based).\n * Both nodemailer and Resend support these formats directly.\n */\nexport interface ResolvedEmailAttachment {\n filename: string\n content: Buffer | ReadableStream\n contentType: string\n}\n","import { withI18n, z } from '../../i18n/validation'\nimport { emailAttachmentSchema, type ResolvedEmailAttachment } from './email-attachment'\n\n/**\n * Email Address Schema\n *\n * Represents an email address with optional name\n */\nexport const emailAddressSchema = z.object({\n name: z.string().optional(),\n email: z.string().email(),\n})\n\n/**\n * Base Email Message Schema\n *\n * Defines the core structure for email messages.\n * Ensures either html or text content is provided.\n */\nexport const emailMessageSchema = z\n .object({\n /**\n * Recipient email address(es)\n * Can be a single email string or array of emails\n */\n to: z.union([z.string().email(), z.array(z.string().email())]),\n\n /**\n * Sender email address with optional name\n * Falls back to default from config if not provided\n */\n from: emailAddressSchema.optional(),\n\n /**\n * Email subject line\n */\n subject: z.string().min(1).max(500),\n\n /**\n * HTML content of the email\n * Either html or text must be provided\n */\n html: z.string().optional(),\n\n /**\n * Plain text content of the email\n * Either html or text must be provided\n */\n text: z.string().optional(),\n\n /**\n * Reply-to email address\n */\n replyTo: z.string().email().optional(),\n\n /**\n * CC recipients\n */\n cc: z.array(z.string().email()).optional(),\n\n /**\n * BCC recipients\n */\n bcc: z.array(z.string().email()).optional(),\n\n /**\n * Email attachments\n */\n attachments: z.array(emailAttachmentSchema).optional(),\n })\n .refine(\n (data) => data.html ?? data.text,\n withI18n('zodI18n.errors.custom.emailOrTextRequired')\n )\n\n/**\n * Type definition for email message\n */\nexport type EmailMessage = z.infer<typeof emailMessageSchema>\n\n/**\n * Type definition for email address\n */\nexport type EmailAddress = z.infer<typeof emailAddressSchema>\n\n/**\n * Resolved Email Message\n *\n * Email message with attachments resolved to Buffer content.\n * Used by providers after the consumer resolves storage-based attachments.\n */\nexport type ResolvedEmailMessage = Omit<EmailMessage, 'attachments'> & {\n attachments?: ResolvedEmailAttachment[]\n}\n","import { z } from '../../i18n/validation'\nimport { emailMessageSchema } from './email-message.contract'\n\n/**\n * Send Email Input Schema\n *\n * Input schema for sending emails through the EmailService.\n * Extends the base email message with optional metadata.\n * Uses safeExtend() because emailMessageSchema contains refinements.\n */\nexport const sendEmailInputSchema = emailMessageSchema.safeExtend({\n /**\n * Optional metadata to include with the email\n * Can be used for tracking, categorization, etc.\n */\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\n/**\n * Type definition for send email input\n */\nexport type SendEmailInput = z.infer<typeof sendEmailInputSchema>\n\n/**\n * Send Batch Email Input Schema\n *\n * Schema for sending multiple emails in a batch\n */\nexport const sendBatchEmailInputSchema = z.object({\n /**\n * Array of email messages to send\n */\n messages: z.array(sendEmailInputSchema).min(1).max(100),\n})\n\n/**\n * Type definition for send batch email input\n */\nexport type SendBatchEmailInput = z.infer<typeof sendBatchEmailInputSchema>\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../src/email/email.tokens.ts","../../src/email/consumers/email.consumer.ts","../../src/email/services/email.service.ts","../../src/email/errors/resend-api-key-missing.error.ts","../../src/email/errors/smtp-configuration-missing.error.ts","../../src/email/errors/smtp-host-missing.error.ts","../../src/email/errors/email-smtp-connection-failed.error.ts","../../src/email/errors/email-resend-api-failed.error.ts","../../src/email/errors/email-provider-not-supported.error.ts","../../src/email/services/email-provider-factory.ts","../../src/email/email.module.ts","../../src/email/contracts/email-attachment.ts","../../src/email/contracts/email-message.contract.ts","../../src/email/contracts/send-email.input.ts"],"sourcesContent":["/**\n * Dependency Injection Tokens for Email Module\n *\n * These Symbol-based tokens ensure type-safe dependency injection\n * throughout the email module and prevent naming collisions.\n */\n\n/**\n * Email Module DI Tokens\n */\nexport const EMAIL_TOKENS = {\n /**\n * Email module configuration options\n */\n Options: Symbol.for('stratal:email:options'),\n\n /**\n * Main email service - facade for sending emails via queues\n */\n EmailService: Symbol.for('stratal:email:service'),\n\n /**\n * Factory for creating email provider instances based on configuration\n */\n EmailProviderFactory: Symbol.for('stratal:email:provider:factory'),\n\n /**\n * Email provider interface - abstracts provider implementation\n */\n EmailProvider: Symbol.for('stratal:email:provider'),\n\n /**\n * Queue sender for email dispatch.\n * Bound via EmailModule.forRoot({ queue: 'queue-name' })\n */\n EmailQueue: Symbol.for('stratal:email:queue'),\n} as const\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport { LOGGER_TOKENS, type LoggerService } from '../../logger'\nimport type { IQueueConsumer, QueueMessage } from '../../queue/queue-consumer'\nimport { STORAGE_TOKENS, type StorageService } from '../../storage'\nimport type { EmailAttachment, ResolvedEmailAttachment, SendEmailInput } from '../contracts'\nimport { EMAIL_TOKENS } from '../email.tokens'\nimport type { EmailProviderFactory } from '../services/email-provider-factory'\n\n/**\n * Email Consumer\n *\n * Generic queue consumer that handles email.send and email.batch.send messages\n * from ANY queue. Message routing is based on message type, not queue name.\n *\n * This consumer:\n * - Resolves storage-based attachments to streams\n * - Creates email provider instances via factory\n * - Sends emails with proper logging (no PII)\n * - Handles errors with retry support\n *\n * @example\n * ```typescript\n * // Registered in EmailModule\n * @Module({\n * consumers: [EmailConsumer]\n * })\n * ```\n */\n@Transient()\nexport class EmailConsumer implements IQueueConsumer<SendEmailInput> {\n readonly messageTypes = ['email.send', 'email.batch.send']\n\n constructor(\n @inject(LOGGER_TOKENS.LoggerService)\n private readonly logger: LoggerService,\n @inject(EMAIL_TOKENS.EmailProviderFactory)\n private readonly providerFactory: EmailProviderFactory,\n @inject(STORAGE_TOKENS.StorageService)\n private readonly storage: StorageService\n ) { }\n\n async handle(message: QueueMessage<SendEmailInput>): Promise<void> {\n const { type, payload } = message\n const recipientCount = Array.isArray(payload.to) ? payload.to.length : 1\n\n this.logger.info('Processing email message', {\n type,\n recipientCount,\n hasHtml: !!payload.html,\n hasText: !!payload.text,\n hasAttachments: !!payload.attachments?.length,\n })\n\n try {\n // Resolve storage-based attachments before sending\n const resolvedAttachments = await this.resolveAttachments(payload.attachments)\n\n const provider = await this.providerFactory.create()\n const result = await provider.send({\n ...payload,\n attachments: resolvedAttachments,\n })\n\n this.logger.info('Email sent successfully', {\n type,\n recipientCount,\n messageId: result.messageId,\n })\n }\n catch (error) {\n this.logger.error('Failed to send email', {\n type,\n recipientCount,\n error: (error as Error).message,\n })\n throw error // Retry via queue\n }\n }\n\n onError(error: Error, message: QueueMessage<SendEmailInput>): Promise<void> {\n const recipientCount = Array.isArray(message.payload.to)\n ? message.payload.to.length\n : 1\n\n this.logger.error('Email send failed after retries', {\n recipientCount,\n error: error.message,\n stack: error.stack,\n })\n\n return Promise.resolve()\n }\n\n /**\n * Resolve email attachments\n *\n * Converts attachment schemas to resolved attachments.\n * - Inline attachments: decode base64 to Buffer\n * - Storage attachments: pass stream directly (providers support streams)\n */\n private async resolveAttachments(\n attachments: EmailAttachment[] | undefined\n ): Promise<ResolvedEmailAttachment[] | undefined> {\n if (!attachments?.length) return undefined\n\n return Promise.all(attachments.map(async (attachment) => {\n // Check for inline attachment (has content property)\n if ('content' in attachment) {\n return {\n filename: attachment.filename,\n content: Buffer.from(attachment.content, 'base64'),\n contentType: attachment.contentType,\n }\n }\n\n // Storage attachment - pass stream directly to provider\n const result = await this.storage.download(\n attachment.storageKey,\n attachment.disk\n )\n\n return {\n filename: attachment.filename,\n content: result.toStream() ?? Buffer.alloc(0),\n contentType: result.contentType,\n }\n }))\n }\n}\n","import { render } from '@react-email/render'\nimport type { ReactElement } from 'react'\nimport { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport type { IQueueSender } from '../../queue'\nimport type { SendBatchEmailInput, SendEmailInput } from '../contracts'\nimport { EMAIL_TOKENS } from '../email.tokens'\n\nexport type SendEmailInputWithTemplate = Omit<SendEmailInput, 'html' | 'text'> & {\n template?: ReactElement\n}\n\nexport type SendBatchEmailInputWithTemplate = Omit<SendBatchEmailInput, 'messages'> & {\n messages: SendEmailInputWithTemplate[]\n}\n\n/**\n * Email Service\n *\n * Main facade for sending emails. Routes emails to queues for async processing.\n * The queue is injected via EMAIL_TOKENS.EmailQueue, configured by the application\n * via EmailModule.forRoot({ queue: 'queue-name' }).\n *\n * @example Basic usage\n * ```typescript\n * @inject(EMAIL_TOKENS.EmailService)\n * private readonly emailService: EmailService\n *\n * await this.emailService.send({\n * to: 'user@example.com',\n * subject: 'Welcome',\n * template: <WelcomeEmail name=\"John\" />\n * })\n * ```\n */\n@Transient(EMAIL_TOKENS.EmailService)\nexport class EmailService {\n constructor(\n @inject(EMAIL_TOKENS.EmailQueue)\n protected readonly queue: IQueueSender\n ) { }\n\n /**\n * Send a single email\n *\n * Dispatches the email to the queue for async processing.\n * Supports optional React template rendering.\n *\n * @param input - Email message details\n */\n async send({ template, ...input }: SendEmailInputWithTemplate): Promise<void> {\n await this.queue.dispatch({\n type: 'email.send',\n payload: { ...input, html: template ? await render(template) : undefined },\n })\n }\n\n /**\n * Send multiple emails in a batch\n *\n * Dispatches all emails to the queue for async processing.\n * Supports React template rendering for each message.\n *\n * @param input - Batch email details\n */\n async sendBatch(input: SendBatchEmailInputWithTemplate): Promise<void> {\n for (const message of input.messages) {\n await this.send(message)\n }\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * ResendApiKeyMissingError\n *\n * Thrown when the Resend API key is not configured in environment variables.\n * This prevents the Resend email provider from initializing.\n *\n * Resolution: Set the RESEND_EMAIL_API_KEY environment variable.\n */\nexport class ResendApiKeyMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.resendApiKeyMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * SmtpConfigurationMissingError\n *\n * Thrown when SMTP configuration is not found in environment variables.\n * This prevents the SMTP email provider from initializing.\n *\n * Resolution: Set the SMTP_URL environment variable with format: smtp://user:pass@host:port\n */\nexport class SmtpConfigurationMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.smtpConfigurationMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * SmtpHostMissingError\n *\n * Thrown when SMTP host could not be parsed from SMTP_URL or is empty.\n * This prevents the SMTP email provider from initializing.\n *\n * Resolution: Ensure SMTP_URL is correctly formatted: smtp://user:pass@host:port\n */\nexport class SmtpHostMissingError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.smtpHostMissing',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailSmtpConnectionFailedError\n *\n * Thrown when connection to SMTP server fails during email sending.\n * This is a runtime error that may be temporary.\n *\n * Resolution: Check SMTP server availability, network connectivity, or wait and retry.\n */\nexport class EmailSmtpConnectionFailedError extends ApplicationError {\n constructor(smtpHost: string, smtpPort: number) {\n super(\n 'errors.email.smtpConnectionFailed',\n ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR,\n { smtpHost, smtpPort }\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailResendApiFailedError\n *\n * Thrown when Resend API returns an error during email sending.\n * This is a runtime error from the Resend service.\n *\n * Resolution: Check Resend API status, API key validity, or wait and retry.\n */\nexport class EmailResendApiFailedError extends ApplicationError {\n constructor() {\n super(\n 'errors.email.resendApiFailed',\n ERROR_CODES.SYSTEM.INFRASTRUCTURE_ERROR,\n )\n }\n}\n","import { ApplicationError, ERROR_CODES } from '../../errors'\n\n/**\n * EmailProviderNotSupportedError\n *\n * Thrown when an unsupported email provider is configured.\n * Only 'resend' and 'smtp' providers are currently supported.\n *\n * Resolution: Set EMAIL_PROVIDER to either 'resend' or 'smtp'.\n */\nexport class EmailProviderNotSupportedError extends ApplicationError {\n constructor(provider: string) {\n super(\n 'errors.email.providerNotSupported',\n ERROR_CODES.SYSTEM.CONFIGURATION_ERROR,\n { provider }\n )\n }\n}\n","import { inject } from 'tsyringe'\nimport { Transient } from '../../di/decorators'\nimport type { EmailModuleOptions } from '../email.module'\nimport { EMAIL_TOKENS } from '../email.tokens'\nimport { EmailProviderNotSupportedError } from '../errors'\nimport type { IEmailProvider } from '../providers/email-provider.interface'\n\n/**\n * Email Provider Factory\n *\n * Creates email provider instances based on configuration.\n * Supports automatic provider selection from module options.\n *\n * Providers are loaded lazily via dynamic imports to avoid pulling in\n * heavy Node.js-only dependencies (e.g. nodemailer) at module parse time,\n * which would break Cloudflare Workers and vitest-pool-workers environments.\n */\n@Transient(EMAIL_TOKENS.EmailProviderFactory)\nexport class EmailProviderFactory {\n constructor(\n @inject(EMAIL_TOKENS.Options)\n private readonly options: EmailModuleOptions\n ) { }\n\n /**\n * Create email provider instance based on configuration\n *\n * @returns Email provider implementation\n * @throws EmailProviderNotSupportedError if provider is not supported\n */\n async create(): Promise<IEmailProvider> {\n switch (this.options.provider) {\n case 'resend': {\n const { ResendProvider } = await import('../providers/resend.provider')\n return new ResendProvider(this.options)\n }\n\n case 'smtp': {\n const { SmtpProvider } = await import('../providers/smtp.provider')\n return new SmtpProvider(this.options)\n }\n\n default:\n throw new EmailProviderNotSupportedError(this.options.provider)\n }\n }\n}\n","/**\n * Email Module\n *\n * Provides email sending capabilities with provider abstraction.\n * Supports multiple email providers (Resend, SMTP) with automatic provider selection.\n * Emails are sent asynchronously via Cloudflare Queues.\n *\n * **Usage:**\n * ```typescript\n * // In AppModule imports with static options\n * EmailModule.forRoot({\n * provider: 'resend',\n * apiKey: 'your-api-key',\n * from: { name: 'App', email: 'noreply@example.com' },\n * queue: 'notifications-queue',\n * })\n *\n * // Or with async options from config namespaces\n * EmailModule.forRootAsync({\n * inject: [emailConfig.KEY],\n * useFactory: (email) => ({\n * provider: email.provider,\n * apiKey: email.apiKey,\n * from: email.from,\n * queue: email.queue,\n * }),\n * })\n *\n * // In your service\n * @inject(EMAIL_TOKENS.EmailService)\n * private readonly emailService: EmailService\n *\n * await this.emailService.send({\n * to: 'user@example.com',\n * subject: 'Welcome',\n * template: <WelcomeEmail name=\"John\" />\n * })\n * ```\n */\n\nimport { Module } from '../module'\nimport type { AsyncModuleOptions, DynamicModule } from '../module/types'\nimport type { QueueName } from '../queue'\nimport { QUEUE_TOKENS, type QueueRegistry } from '../queue'\nimport { EmailConsumer } from './consumers/email.consumer'\nimport { EMAIL_TOKENS } from './email.tokens'\nimport { EmailProviderFactory, EmailService } from './services'\n\n/**\n * SMTP configuration options\n */\nexport interface SmtpConfig {\n /** SMTP server host */\n host: string\n /** SMTP server port */\n port: number\n /** Use TLS */\n secure?: boolean\n /** SMTP username */\n username?: string\n /** SMTP password */\n password?: string\n}\n\n/**\n * Email module configuration options\n */\nexport interface EmailModuleOptions {\n /** Email provider type */\n provider: 'resend' | 'smtp'\n\n /** Default from address */\n from: { name: string; email: string }\n\n /** Resend API key (required for resend provider) */\n apiKey?: string\n\n /** SMTP configuration (required for smtp provider) */\n smtp?: SmtpConfig\n\n /** Default reply-to address */\n replyTo?: string\n\n /**\n * Queue name for email dispatch.\n * The queue must be registered via QueueModule.registerQueue(name).\n */\n queue: QueueName\n}\n\n@Module({\n providers: [\n { provide: EMAIL_TOKENS.EmailService, useClass: EmailService },\n { provide: EMAIL_TOKENS.EmailProviderFactory, useClass: EmailProviderFactory },\n ],\n consumers: [EmailConsumer],\n})\nexport class EmailModule {\n /**\n * Configure EmailModule with static options\n *\n * @param options - Email configuration options\n * @returns Dynamic module with email infrastructure\n *\n * @example\n * ```typescript\n * EmailModule.forRoot({\n * provider: 'resend',\n * apiKey: env.RESEND_API_KEY,\n * from: { name: 'App', email: 'noreply@example.com' },\n * queue: 'notifications-queue',\n * })\n * ```\n */\n static forRoot(options: EmailModuleOptions): DynamicModule {\n return {\n module: EmailModule,\n providers: [\n { provide: EMAIL_TOKENS.Options, useValue: options },\n { provide: EMAIL_TOKENS.EmailQueue, useExisting: options.queue },\n ],\n }\n }\n\n /**\n * Configure EmailModule with async factory\n *\n * Use when configuration depends on other services.\n *\n * @param options - Async configuration with factory and inject tokens\n * @returns Dynamic module with email infrastructure\n *\n * @example\n * ```typescript\n * EmailModule.forRootAsync({\n * inject: [emailConfig.KEY],\n * useFactory: (email) => ({\n * provider: email.provider,\n * apiKey: email.apiKey,\n * from: email.from,\n * smtp: email.smtp,\n * queue: email.queue,\n * })\n * })\n * ```\n */\n static forRootAsync(options: AsyncModuleOptions<EmailModuleOptions>): DynamicModule {\n return {\n module: EmailModule,\n providers: [\n {\n provide: EMAIL_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n // Resolve queue from QueueRegistry using the queue name from options\n {\n provide: EMAIL_TOKENS.EmailQueue,\n useFactory: (emailOptions: EmailModuleOptions, registry: QueueRegistry) =>\n registry.getQueue(emailOptions.queue),\n inject: [EMAIL_TOKENS.Options, QUEUE_TOKENS.QueueRegistry],\n },\n ],\n }\n }\n}\n","import { z } from '../../i18n/validation'\n\n/**\n * Inline Email Attachment Schema\n *\n * Attachment with content embedded as base64 string.\n * Use for small files that can fit in queue message.\n */\nexport const inlineEmailAttachmentSchema = z.object({\n /**\n * Filename to display for the attachment\n */\n filename: z.string().min(1).max(255),\n\n /**\n * Base64 encoded content of the attachment\n */\n content: z.string(),\n\n /**\n * MIME type of the attachment (e.g., 'application/pdf', 'image/png')\n */\n contentType: z.string(),\n\n /**\n * Optional size of the attachment in bytes\n */\n size: z.number().positive().optional(),\n})\n\n/**\n * Storage Email Attachment Schema\n *\n * Attachment stored in cloud storage.\n * Content type and size are derived from storage metadata.\n * Use for large files to avoid queue message size limits.\n */\nexport const storageEmailAttachmentSchema = z.object({\n /**\n * Filename to display for the attachment\n */\n filename: z.string().min(1).max(255),\n\n /**\n * Path to the file in storage\n */\n storageKey: z.string(),\n\n /**\n * Optional storage disk name (uses default if not provided)\n */\n disk: z.string().optional(),\n})\n\n/**\n * Email Attachment Schema\n *\n * Union type - type is inferred from presence of `content` vs `storageKey`.\n * - If `content` is present: inline attachment\n * - If `storageKey` is present: storage-based attachment\n */\nexport const emailAttachmentSchema = z.union([\n inlineEmailAttachmentSchema,\n storageEmailAttachmentSchema,\n])\n\n/**\n * Type definitions\n */\nexport type InlineEmailAttachment = z.infer<typeof inlineEmailAttachmentSchema>\nexport type StorageEmailAttachment = z.infer<typeof storageEmailAttachmentSchema>\nexport type EmailAttachment = z.infer<typeof emailAttachmentSchema>\n\n/**\n * Resolved Email Attachment\n *\n * Attachment after resolution, ready for email provider.\n * Content can be Buffer (for inline) or ReadableStream (for storage-based).\n * Both nodemailer and Resend support these formats directly.\n */\nexport interface ResolvedEmailAttachment {\n filename: string\n content: Buffer | ReadableStream\n contentType: string\n}\n","import { withI18n, z } from '../../i18n/validation'\nimport { emailAttachmentSchema, type ResolvedEmailAttachment } from './email-attachment'\n\n/**\n * Email Address Schema\n *\n * Represents an email address with optional name\n */\nexport const emailAddressSchema = z.object({\n name: z.string().optional(),\n email: z.string().email(),\n})\n\n/**\n * Base Email Message Schema\n *\n * Defines the core structure for email messages.\n * Ensures either html or text content is provided.\n */\nexport const emailMessageSchema = z\n .object({\n /**\n * Recipient email address(es)\n * Can be a single email string or array of emails\n */\n to: z.union([z.string().email(), z.array(z.string().email())]),\n\n /**\n * Sender email address with optional name\n * Falls back to default from config if not provided\n */\n from: emailAddressSchema.optional(),\n\n /**\n * Email subject line\n */\n subject: z.string().min(1).max(500),\n\n /**\n * HTML content of the email\n * Either html or text must be provided\n */\n html: z.string().optional(),\n\n /**\n * Plain text content of the email\n * Either html or text must be provided\n */\n text: z.string().optional(),\n\n /**\n * Reply-to email address\n */\n replyTo: z.string().email().optional(),\n\n /**\n * CC recipients\n */\n cc: z.array(z.string().email()).optional(),\n\n /**\n * BCC recipients\n */\n bcc: z.array(z.string().email()).optional(),\n\n /**\n * Email attachments\n */\n attachments: z.array(emailAttachmentSchema).optional(),\n })\n .refine(\n (data) => data.html ?? data.text,\n withI18n('zodI18n.errors.custom.emailOrTextRequired')\n )\n\n/**\n * Type definition for email message\n */\nexport type EmailMessage = z.infer<typeof emailMessageSchema>\n\n/**\n * Type definition for email address\n */\nexport type EmailAddress = z.infer<typeof emailAddressSchema>\n\n/**\n * Resolved Email Message\n *\n * Email message with attachments resolved to Buffer content.\n * Used by providers after the consumer resolves storage-based attachments.\n */\nexport type ResolvedEmailMessage = Omit<EmailMessage, 'attachments'> & {\n attachments?: ResolvedEmailAttachment[]\n}\n","import { z } from '../../i18n/validation'\nimport { emailMessageSchema } from './email-message.contract'\n\n/**\n * Send Email Input Schema\n *\n * Input schema for sending emails through the EmailService.\n * Extends the base email message with optional metadata.\n * Uses safeExtend() because emailMessageSchema contains refinements.\n */\nexport const sendEmailInputSchema = emailMessageSchema.safeExtend({\n /**\n * Optional metadata to include with the email\n * Can be used for tracking, categorization, etc.\n */\n metadata: z.record(z.string(), z.unknown()).optional(),\n})\n\n/**\n * Type definition for send email input\n */\nexport type SendEmailInput = z.infer<typeof sendEmailInputSchema>\n\n/**\n * Send Batch Email Input Schema\n *\n * Schema for sending multiple emails in a batch\n */\nexport const sendBatchEmailInputSchema = z.object({\n /**\n * Array of email messages to send\n */\n messages: z.array(sendEmailInputSchema).min(1).max(100),\n})\n\n/**\n * Type definition for send batch email input\n */\nexport type SendBatchEmailInput = z.infer<typeof sendBatchEmailInputSchema>\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { F as QueueExceptionContext, Fn as RenderableCallback, Gr as Environment, I as createCliExceptionContext, In as Reportable, Kr as ErrorResponse, L as createCronExceptionContext, Ln as ReportableCallback, M as CronExceptionContext, Mn as ApplicationErrorConstructor, N as ExceptionContext, Nn as ContextCallback, P as HttpExceptionContext, Pn as LogSeverity, R as createHttpExceptionContext, Rn as RespondCallback, a as InternalError, c as getHttpStatus, d as ApplicationError, f as ERROR_CODES, i as isApplicationError, j as CliExceptionContext, jn as ExceptionHandler, l as resolveHttpStatus, n as RequestContainerNotInitializedError, o as HttpException, p as ErrorCode, qr as isErrorResponse, r as ContainerNotInitializedError, s as abort, t as StratalNotInitializedError, u as DefaultExceptionHandler, z as createQueueExceptionContext } from "../index-D0US0X14.mjs";
1
+ import { F as QueueExceptionContext, Fn as RenderableCallback, Gr as Environment, I as createCliExceptionContext, In as Reportable, Kr as ErrorResponse, L as createCronExceptionContext, Ln as ReportableCallback, M as CronExceptionContext, Mn as ApplicationErrorConstructor, N as ExceptionContext, Nn as ContextCallback, P as HttpExceptionContext, Pn as LogSeverity, R as createHttpExceptionContext, Rn as RespondCallback, a as InternalError, c as getHttpStatus, d as ApplicationError, f as ERROR_CODES, i as isApplicationError, j as CliExceptionContext, jn as ExceptionHandler, l as resolveHttpStatus, n as RequestContainerNotInitializedError, o as HttpException, p as ErrorCode, qr as isErrorResponse, r as ContainerNotInitializedError, s as abort, t as StratalNotInitializedError, u as DefaultExceptionHandler, z as createQueueExceptionContext } from "../index-ByOyTmqf.mjs";
2
2
  export { ApplicationError, ApplicationErrorConstructor, CliExceptionContext, ContainerNotInitializedError, ContextCallback, CronExceptionContext, DefaultExceptionHandler, ERROR_CODES, Environment, ErrorCode, ErrorResponse, ExceptionContext, ExceptionHandler, HttpException, HttpExceptionContext, InternalError, LogSeverity, QueueExceptionContext, RenderableCallback, Reportable, ReportableCallback, RequestContainerNotInitializedError, RespondCallback, StratalNotInitializedError, abort, createCliExceptionContext, createCronExceptionContext, createHttpExceptionContext, createQueueExceptionContext, getHttpStatus, isApplicationError, isErrorResponse, resolveHttpStatus };
@@ -1,2 +1,2 @@
1
- import { C as abort, H as ApplicationError, O as ContainerNotInitializedError, S as HttpException, _ as ExceptionHandler, a as createHttpExceptionContext, b as getHttpStatus, g as DefaultExceptionHandler, h as isErrorResponse, i as createCronExceptionContext, k as ERROR_CODES, n as RequestContainerNotInitializedError, o as createQueueExceptionContext, r as createCliExceptionContext, t as StratalNotInitializedError, v as isApplicationError, x as resolveHttpStatus, y as InternalError } from "../errors-BdyV5PnY.mjs";
1
+ import { C as abort, H as ApplicationError, O as ContainerNotInitializedError, S as HttpException, _ as ExceptionHandler, a as createHttpExceptionContext, b as getHttpStatus, g as DefaultExceptionHandler, h as isErrorResponse, i as createCronExceptionContext, k as ERROR_CODES, n as RequestContainerNotInitializedError, o as createQueueExceptionContext, r as createCliExceptionContext, t as StratalNotInitializedError, v as isApplicationError, x as resolveHttpStatus, y as InternalError } from "../errors-COW9-Mar.mjs";
2
2
  export { ApplicationError, ContainerNotInitializedError, DefaultExceptionHandler, ERROR_CODES, ExceptionHandler, HttpException, InternalError, RequestContainerNotInitializedError, StratalNotInitializedError, abort, createCliExceptionContext, createCronExceptionContext, createHttpExceptionContext, createQueueExceptionContext, getHttpStatus, isApplicationError, isErrorResponse, resolveHttpStatus };
@@ -1,4 +1,4 @@
1
- import { a as __decorate, d as CONTAINER_TOKEN, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "./logger-V6Ms3QnQ.mjs";
1
+ import { a as __decorate, d as CONTAINER_TOKEN, f as DI_TOKENS, o as __decorateParam, p as Transient, s as __decorateMetadata, u as LOGGER_TOKENS } from "./logger-DlV7NtvD.mjs";
2
2
  import { t as Macroable } from "./macroable-BmufBshB.mjs";
3
3
  import { Lifecycle, container as container$1, delay, inject, inject as inject$1, injectable as injectable$1, instancePerContainerCachingFactory as instancePerContainerCachingFactory$1, predicateAwareClassFactory, singleton } from "tsyringe";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -206,6 +206,10 @@ var RequestScopeOperationNotAllowedError = class extends ApplicationError {
206
206
  * @internal
207
207
  */
208
208
  var ConditionalBindingBuilderImpl = class {
209
+ tsyringeContainer;
210
+ predicateContainer;
211
+ predicate;
212
+ options;
209
213
  constructor(tsyringeContainer, predicateContainer, predicate, options) {
210
214
  this.tsyringeContainer = tsyringeContainer;
211
215
  this.predicateContainer = predicateContainer;
@@ -222,6 +226,11 @@ var ConditionalBindingBuilderImpl = class {
222
226
  * @internal
223
227
  */
224
228
  var ConditionalBindingUseImpl = class {
229
+ tsyringeContainer;
230
+ predicateContainer;
231
+ predicate;
232
+ options;
233
+ token;
225
234
  constructor(tsyringeContainer, predicateContainer, predicate, options, token) {
226
235
  this.tsyringeContainer = tsyringeContainer;
227
236
  this.predicateContainer = predicateContainer;
@@ -906,6 +915,10 @@ function isApplicationError(error) {
906
915
  //#endregion
907
916
  //#region src/errors/exception-handler.ts
908
917
  let ExceptionHandler = class ExceptionHandler {
918
+ logger;
919
+ env;
920
+ container;
921
+ executionContext;
909
922
  reportables = [];
910
923
  renderables = [];
911
924
  dontReportSet = /* @__PURE__ */ new Set();
@@ -1445,6 +1458,7 @@ const DEFAULT_CONTENT_TYPE = "application/json";
1445
1458
  * ```
1446
1459
  */
1447
1460
  var RouterContext = class extends Macroable {
1461
+ c;
1448
1462
  /**
1449
1463
  * Native Hono context
1450
1464
  * Access for advanced use cases not covered by helper methods
@@ -1722,4 +1736,4 @@ var StratalNotInitializedError = class extends ApplicationError {
1722
1736
  //#endregion
1723
1737
  export { Scope as A, ConditionalBindingFallbackError as B, abort as C, runWithContainer as D, getContainer as E, injectable$1 as F, ApplicationError as H, instancePerContainerCachingFactory$1 as I, singleton as L, container$1 as M, delay as N, ContainerNotInitializedError as O, inject$1 as P, ConditionalBindingBuilderImpl as R, HttpException as S, containerStorage as T, ROUTER_TOKENS as V, ExceptionHandler as _, createHttpExceptionContext as a, getHttpStatus as b, DEFAULT_CONTENT_TYPE as c, ROUTER_CONTEXT_KEYS as d, ROUTE_METADATA_KEYS as f, DefaultExceptionHandler as g, isErrorResponse as h, createCronExceptionContext as i, Container as j, ERROR_CODES as k, HTTP_METHODS as l, VERSION_NEUTRAL as m, RequestContainerNotInitializedError as n, createQueueExceptionContext as o, SECURITY_SCHEMES as p, createCliExceptionContext as r, RouterContext as s, StratalNotInitializedError as t, METHOD_STATUS_CODES as u, isApplicationError as v, I18N_TOKENS as w, resolveHttpStatus as x, InternalError as y, RequestScopeOperationNotAllowedError as z };
1724
1738
 
1725
- //# sourceMappingURL=errors-BdyV5PnY.mjs.map
1739
+ //# sourceMappingURL=errors-COW9-Mar.mjs.map