@webiny/api-mailer 6.0.0-beta.0 → 6.0.0-rc.0

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 (165) hide show
  1. package/README.md +10 -13
  2. package/constants.d.ts +1 -0
  3. package/constants.js +3 -0
  4. package/constants.js.map +1 -0
  5. package/domain/Encryption/abstractions.d.ts +8 -0
  6. package/domain/Encryption/abstractions.js +4 -0
  7. package/domain/Encryption/abstractions.js.map +1 -0
  8. package/domain/MailTransport/abstractions.d.ts +18 -0
  9. package/domain/MailTransport/abstractions.js +5 -0
  10. package/domain/MailTransport/abstractions.js.map +1 -0
  11. package/domain/MailerService/abstractions.d.ts +19 -0
  12. package/domain/MailerService/abstractions.js +4 -0
  13. package/domain/MailerService/abstractions.js.map +1 -0
  14. package/domain/MailerService/errors.d.ts +16 -0
  15. package/domain/MailerService/errors.js +30 -0
  16. package/domain/MailerService/errors.js.map +1 -0
  17. package/domain/errors.d.ts +24 -0
  18. package/domain/errors.js +44 -0
  19. package/domain/errors.js.map +1 -0
  20. package/features/DummyTransport/DummyMailTransport.d.ts +9 -0
  21. package/features/DummyTransport/DummyMailTransport.js +12 -0
  22. package/features/DummyTransport/DummyMailTransport.js.map +1 -0
  23. package/features/DummyTransport/DummyMailTransportFactory.d.ts +8 -0
  24. package/features/DummyTransport/DummyMailTransportFactory.js +13 -0
  25. package/features/DummyTransport/DummyMailTransportFactory.js.map +1 -0
  26. package/features/DummyTransport/feature.d.ts +1 -0
  27. package/features/DummyTransport/feature.js +10 -0
  28. package/features/DummyTransport/feature.js.map +1 -0
  29. package/features/Encryption/PasswordEncryption.d.ts +9 -0
  30. package/features/Encryption/PasswordEncryption.js +23 -0
  31. package/features/Encryption/PasswordEncryption.js.map +1 -0
  32. package/features/Encryption/feature.d.ts +1 -0
  33. package/features/Encryption/feature.js +10 -0
  34. package/features/Encryption/feature.js.map +1 -0
  35. package/features/Encryption/utils/password.js +56 -0
  36. package/features/Encryption/utils/password.js.map +1 -0
  37. package/features/Encryption/utils/secret.js +11 -0
  38. package/features/Encryption/utils/secret.js.map +1 -0
  39. package/features/GetSettings/GetSettingsRepository.d.ts +15 -0
  40. package/features/GetSettings/GetSettingsRepository.js +39 -0
  41. package/features/GetSettings/GetSettingsRepository.js.map +1 -0
  42. package/features/GetSettings/GetSettingsUseCase.d.ts +12 -0
  43. package/features/GetSettings/GetSettingsUseCase.js +15 -0
  44. package/features/GetSettings/GetSettingsUseCase.js.map +1 -0
  45. package/features/GetSettings/abstractions.d.ts +16 -0
  46. package/features/GetSettings/abstractions.js +5 -0
  47. package/features/GetSettings/abstractions.js.map +1 -0
  48. package/features/GetSettings/feature.d.ts +1 -0
  49. package/features/GetSettings/feature.js +12 -0
  50. package/features/GetSettings/feature.js.map +1 -0
  51. package/features/GetSettings/index.d.ts +1 -0
  52. package/features/GetSettings/index.js +3 -0
  53. package/features/GetSettings/index.js.map +1 -0
  54. package/features/MailerService/MailerService.d.ts +15 -0
  55. package/features/MailerService/MailerService.js +52 -0
  56. package/features/MailerService/MailerService.js.map +1 -0
  57. package/features/MailerService/TransportFactory.d.ts +2 -0
  58. package/features/MailerService/TransportFactory.js +31 -0
  59. package/features/MailerService/TransportFactory.js.map +1 -0
  60. package/features/MailerService/feature.d.ts +1 -0
  61. package/features/MailerService/feature.js +10 -0
  62. package/features/MailerService/feature.js.map +1 -0
  63. package/features/SaveSettings/SaveSettingsRepository.d.ts +13 -0
  64. package/features/SaveSettings/SaveSettingsRepository.js +57 -0
  65. package/features/SaveSettings/SaveSettingsRepository.js.map +1 -0
  66. package/features/SaveSettings/SaveSettingsUseCase.d.ts +14 -0
  67. package/features/SaveSettings/SaveSettingsUseCase.js +51 -0
  68. package/features/SaveSettings/SaveSettingsUseCase.js.map +1 -0
  69. package/features/SaveSettings/abstractions.d.ts +53 -0
  70. package/features/SaveSettings/abstractions.js +11 -0
  71. package/features/SaveSettings/abstractions.js.map +1 -0
  72. package/features/SaveSettings/events.d.ts +10 -0
  73. package/features/SaveSettings/events.js +16 -0
  74. package/features/SaveSettings/events.js.map +1 -0
  75. package/features/SaveSettings/feature.d.ts +1 -0
  76. package/features/SaveSettings/feature.js +12 -0
  77. package/features/SaveSettings/feature.js.map +1 -0
  78. package/features/SaveSettings/index.d.ts +1 -0
  79. package/features/SaveSettings/index.js +3 -0
  80. package/features/SaveSettings/index.js.map +1 -0
  81. package/features/SaveSettings/validation.d.ts +23 -0
  82. package/features/SaveSettings/validation.js +19 -0
  83. package/features/SaveSettings/validation.js.map +1 -0
  84. package/features/SendMail/SendMailUseCase.d.ts +16 -0
  85. package/features/SendMail/SendMailUseCase.js +62 -0
  86. package/features/SendMail/SendMailUseCase.js.map +1 -0
  87. package/features/SendMail/abstractions.d.ts +45 -0
  88. package/features/SendMail/abstractions.js +11 -0
  89. package/features/SendMail/abstractions.js.map +1 -0
  90. package/features/SendMail/events.d.ts +14 -0
  91. package/features/SendMail/events.js +22 -0
  92. package/features/SendMail/events.js.map +1 -0
  93. package/features/SendMail/feature.d.ts +1 -0
  94. package/features/SendMail/feature.js +10 -0
  95. package/features/SendMail/feature.js.map +1 -0
  96. package/features/SmtpTransport/SmtpConfig.d.ts +6 -0
  97. package/features/SmtpTransport/SmtpConfig.js +29 -0
  98. package/features/SmtpTransport/SmtpConfig.js.map +1 -0
  99. package/features/SmtpTransport/SmtpMailTransport.d.ts +18 -0
  100. package/features/SmtpTransport/SmtpMailTransport.js +61 -0
  101. package/features/SmtpTransport/SmtpMailTransport.js.map +1 -0
  102. package/features/SmtpTransport/SmtpMailTransportFactory.d.ts +9 -0
  103. package/features/SmtpTransport/SmtpMailTransportFactory.js +14 -0
  104. package/features/SmtpTransport/SmtpMailTransportFactory.js.map +1 -0
  105. package/features/SmtpTransport/feature.d.ts +1 -0
  106. package/features/SmtpTransport/feature.js +10 -0
  107. package/features/SmtpTransport/feature.js.map +1 -0
  108. package/graphql/settings.d.ts +2 -2
  109. package/graphql/settings.js +46 -34
  110. package/graphql/settings.js.map +1 -1
  111. package/index.d.ts +4 -5
  112. package/index.js +22 -78
  113. package/index.js.map +1 -1
  114. package/package.json +31 -37
  115. package/types.d.ts +1 -108
  116. package/types.js +1 -5
  117. package/types.js.map +1 -1
  118. package/context.d.ts +0 -3
  119. package/context.js +0 -20
  120. package/context.js.map +0 -1
  121. package/crud/settings/hooks.d.ts +0 -5
  122. package/crud/settings/hooks.js +0 -42
  123. package/crud/settings/hooks.js.map +0 -1
  124. package/crud/settings/model.d.ts +0 -2
  125. package/crud/settings/model.js +0 -72
  126. package/crud/settings/model.js.map +0 -1
  127. package/crud/settings/password.js +0 -55
  128. package/crud/settings/password.js.map +0 -1
  129. package/crud/settings/secret.js +0 -19
  130. package/crud/settings/secret.js.map +0 -1
  131. package/crud/settings/transform.d.ts +0 -13
  132. package/crud/settings/transform.js +0 -46
  133. package/crud/settings/transform.js.map +0 -1
  134. package/crud/settings/validation.d.ts +0 -45
  135. package/crud/settings/validation.js +0 -28
  136. package/crud/settings/validation.js.map +0 -1
  137. package/crud/settings.crud.d.ts +0 -5
  138. package/crud/settings.crud.js +0 -269
  139. package/crud/settings.crud.js.map +0 -1
  140. package/crud/transport/onTransportBeforeSend.d.ts +0 -7
  141. package/crud/transport/onTransportBeforeSend.js +0 -62
  142. package/crud/transport/onTransportBeforeSend.js.map +0 -1
  143. package/crud/transporter.crud.d.ts +0 -2
  144. package/crud/transporter.crud.js +0 -158
  145. package/crud/transporter.crud.js.map +0 -1
  146. package/graphql/index.d.ts +0 -1
  147. package/graphql/index.js +0 -13
  148. package/graphql/index.js.map +0 -1
  149. package/plugins/CreateTransportPlugin.d.ts +0 -17
  150. package/plugins/CreateTransportPlugin.js +0 -24
  151. package/plugins/CreateTransportPlugin.js.map +0 -1
  152. package/plugins/index.d.ts +0 -1
  153. package/plugins/index.js +0 -18
  154. package/plugins/index.js.map +0 -1
  155. package/transports/createDummyTransport.d.ts +0 -5
  156. package/transports/createDummyTransport.js +0 -25
  157. package/transports/createDummyTransport.js.map +0 -1
  158. package/transports/createSmtpTransport.d.ts +0 -12
  159. package/transports/createSmtpTransport.js +0 -94
  160. package/transports/createSmtpTransport.js.map +0 -1
  161. package/transports/index.d.ts +0 -2
  162. package/transports/index.js +0 -29
  163. package/transports/index.js.map +0 -1
  164. /package/{crud/settings → features/Encryption/utils}/password.d.ts +0 -0
  165. /package/{crud/settings → features/Encryption/utils}/secret.d.ts +0 -0
@@ -0,0 +1,12 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { GetSettingsRepositoryImplementation } from "./GetSettingsRepository.js";
3
+ import { GetSettingsUseCaseImplementation } from "./GetSettingsUseCase.js";
4
+ export const GetSettingsFeature = createFeature({
5
+ name: "GetSettings",
6
+ register(container) {
7
+ container.register(GetSettingsRepositoryImplementation).inSingletonScope();
8
+ container.register(GetSettingsUseCaseImplementation);
9
+ }
10
+ });
11
+
12
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createFeature","GetSettingsRepositoryImplementation","GetSettingsUseCaseImplementation","GetSettingsFeature","name","register","container","inSingletonScope"],"sources":["feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { GetSettingsRepositoryImplementation } from \"./GetSettingsRepository.js\";\nimport { GetSettingsUseCaseImplementation } from \"./GetSettingsUseCase.js\";\n\nexport const GetSettingsFeature = createFeature({\n name: \"GetSettings\",\n register(container) {\n container.register(GetSettingsRepositoryImplementation).inSingletonScope();\n container.register(GetSettingsUseCaseImplementation);\n }\n});\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,qBAAqB;AACnD,SAASC,mCAAmC;AAC5C,SAASC,gCAAgC;AAEzC,OAAO,MAAMC,kBAAkB,GAAGH,aAAa,CAAC;EAC5CI,IAAI,EAAE,aAAa;EACnBC,QAAQA,CAACC,SAAS,EAAE;IAChBA,SAAS,CAACD,QAAQ,CAACJ,mCAAmC,CAAC,CAACM,gBAAgB,CAAC,CAAC;IAC1ED,SAAS,CAACD,QAAQ,CAACH,gCAAgC,CAAC;EACxD;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export { GetSettingsUseCase } from "./abstractions.js";
@@ -0,0 +1,3 @@
1
+ export { GetSettingsUseCase } from "./abstractions.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["GetSettingsUseCase"],"sources":["index.ts"],"sourcesContent":["export { GetSettingsUseCase } from \"./abstractions.js\";\n"],"mappings":"AAAA,SAASA,kBAAkB","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ import { MailerService as Abstraction } from "../../domain/MailerService/abstractions.js";
2
+ import { MailTransportFactory } from "../../domain/MailTransport/abstractions.js";
3
+ import { GetSettingsRepository } from "../GetSettings/abstractions.js";
4
+ import type { TransportSendData } from "../../types.js";
5
+ declare class MailerServiceImpl implements Abstraction.Interface {
6
+ private getSettingsRepository;
7
+ private transportFactories;
8
+ constructor(getSettingsRepository: GetSettingsRepository.Interface, transportFactories: MailTransportFactory.Interface[]);
9
+ sendMail<T = any>(data: TransportSendData): Abstraction.Return<T>;
10
+ private getTransport;
11
+ }
12
+ export declare const MailerService: typeof MailerServiceImpl & {
13
+ __abstraction: import("@webiny/di").Abstraction<import("~/domain/MailerService/abstractions.js").IMailerService>;
14
+ };
15
+ export {};
@@ -0,0 +1,52 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { MailerService as Abstraction } from "../../domain/MailerService/abstractions.js";
3
+ import { NoTransportAvailableError, NoSettingsConfiguredError, TransportSendError } from "../../domain/MailerService/errors.js";
4
+ import { MailTransportFactory } from "../../domain/MailTransport/abstractions.js";
5
+ import { GetSettingsRepository } from "../GetSettings/abstractions.js";
6
+ import { getDefaultSettingsFromEnv } from "./TransportFactory.js";
7
+ class MailerServiceImpl {
8
+ constructor(getSettingsRepository, transportFactories) {
9
+ this.getSettingsRepository = getSettingsRepository;
10
+ this.transportFactories = transportFactories;
11
+ }
12
+ async sendMail(data) {
13
+ // Get settings from repository or environment variables
14
+ const result = await this.getSettingsRepository.get();
15
+ const settings = result.value ?? getDefaultSettingsFromEnv();
16
+ if (!settings) {
17
+ return Result.fail(new NoSettingsConfiguredError());
18
+ }
19
+
20
+ // Get and configure transport
21
+ const transport = await this.getTransport(settings);
22
+ if (!transport) {
23
+ return Result.fail(new NoTransportAvailableError());
24
+ }
25
+ try {
26
+ const response = await transport.send(data);
27
+
28
+ // If transport.send returned an error in the response
29
+ if (response.error) {
30
+ return Result.fail(new TransportSendError(response.error));
31
+ }
32
+ return Result.ok(response);
33
+ } catch (error) {
34
+ return Result.fail(new TransportSendError(error));
35
+ }
36
+ }
37
+ async getTransport(settings) {
38
+ if (this.transportFactories.length === 0) {
39
+ return null;
40
+ }
41
+ const factory = this.transportFactories[this.transportFactories.length - 1];
42
+ return factory.createTransport(settings);
43
+ }
44
+ }
45
+ export const MailerService = Abstraction.createImplementation({
46
+ implementation: MailerServiceImpl,
47
+ dependencies: [GetSettingsRepository, [MailTransportFactory, {
48
+ multiple: true
49
+ }]]
50
+ });
51
+
52
+ //# sourceMappingURL=MailerService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","MailerService","Abstraction","NoTransportAvailableError","NoSettingsConfiguredError","TransportSendError","MailTransportFactory","GetSettingsRepository","getDefaultSettingsFromEnv","MailerServiceImpl","constructor","getSettingsRepository","transportFactories","sendMail","data","result","get","settings","value","fail","transport","getTransport","response","send","error","ok","length","factory","createTransport","createImplementation","implementation","dependencies","multiple"],"sources":["MailerService.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { MailerService as Abstraction } from \"~/domain/MailerService/abstractions.js\";\nimport {\n NoTransportAvailableError,\n NoSettingsConfiguredError,\n TransportSendError\n} from \"~/domain/MailerService/errors.js\";\nimport { MailTransport, MailTransportFactory } from \"~/domain/MailTransport/abstractions.js\";\nimport { GetSettingsRepository } from \"../GetSettings/abstractions.js\";\nimport type { TransportSettings, TransportSendData } from \"~/types.js\";\nimport { getDefaultSettingsFromEnv } from \"./TransportFactory.js\";\n\nclass MailerServiceImpl implements Abstraction.Interface {\n constructor(\n private getSettingsRepository: GetSettingsRepository.Interface,\n private transportFactories: MailTransportFactory.Interface[]\n ) {}\n\n async sendMail<T = any>(data: TransportSendData): Abstraction.Return<T> {\n // Get settings from repository or environment variables\n const result = await this.getSettingsRepository.get();\n const settings = result.value ?? getDefaultSettingsFromEnv();\n\n if (!settings) {\n return Result.fail(new NoSettingsConfiguredError());\n }\n\n // Get and configure transport\n const transport = await this.getTransport(settings);\n\n if (!transport) {\n return Result.fail(new NoTransportAvailableError());\n }\n\n try {\n const response = await transport.send(data);\n\n // If transport.send returned an error in the response\n if (response.error) {\n return Result.fail(new TransportSendError(response.error));\n }\n\n return Result.ok(response);\n } catch (error) {\n return Result.fail(new TransportSendError(error));\n }\n }\n\n private async getTransport(\n settings: TransportSettings\n ): Promise<MailTransport.Interface | null> {\n if (this.transportFactories.length === 0) {\n return null;\n }\n\n const factory = this.transportFactories[this.transportFactories.length - 1];\n\n return factory.createTransport(settings);\n }\n}\n\nexport const MailerService = Abstraction.createImplementation({\n implementation: MailerServiceImpl,\n dependencies: [GetSettingsRepository, [MailTransportFactory, { multiple: true }]]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,aAAa,IAAIC,WAAW;AACrC,SACIC,yBAAyB,EACzBC,yBAAyB,EACzBC,kBAAkB;AAEtB,SAAwBC,oBAAoB;AAC5C,SAASC,qBAAqB;AAE9B,SAASC,yBAAyB;AAElC,MAAMC,iBAAiB,CAAkC;EACrDC,WAAWA,CACCC,qBAAsD,EACtDC,kBAAoD,EAC9D;IAAA,KAFUD,qBAAsD,GAAtDA,qBAAsD;IAAA,KACtDC,kBAAoD,GAApDA,kBAAoD;EAC7D;EAEH,MAAMC,QAAQA,CAAUC,IAAuB,EAAyB;IACpE;IACA,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACJ,qBAAqB,CAACK,GAAG,CAAC,CAAC;IACrD,MAAMC,QAAQ,GAAGF,MAAM,CAACG,KAAK,IAAIV,yBAAyB,CAAC,CAAC;IAE5D,IAAI,CAACS,QAAQ,EAAE;MACX,OAAOjB,MAAM,CAACmB,IAAI,CAAC,IAAIf,yBAAyB,CAAC,CAAC,CAAC;IACvD;;IAEA;IACA,MAAMgB,SAAS,GAAG,MAAM,IAAI,CAACC,YAAY,CAACJ,QAAQ,CAAC;IAEnD,IAAI,CAACG,SAAS,EAAE;MACZ,OAAOpB,MAAM,CAACmB,IAAI,CAAC,IAAIhB,yBAAyB,CAAC,CAAC,CAAC;IACvD;IAEA,IAAI;MACA,MAAMmB,QAAQ,GAAG,MAAMF,SAAS,CAACG,IAAI,CAACT,IAAI,CAAC;;MAE3C;MACA,IAAIQ,QAAQ,CAACE,KAAK,EAAE;QAChB,OAAOxB,MAAM,CAACmB,IAAI,CAAC,IAAId,kBAAkB,CAACiB,QAAQ,CAACE,KAAK,CAAC,CAAC;MAC9D;MAEA,OAAOxB,MAAM,CAACyB,EAAE,CAACH,QAAQ,CAAC;IAC9B,CAAC,CAAC,OAAOE,KAAK,EAAE;MACZ,OAAOxB,MAAM,CAACmB,IAAI,CAAC,IAAId,kBAAkB,CAACmB,KAAK,CAAC,CAAC;IACrD;EACJ;EAEA,MAAcH,YAAYA,CACtBJ,QAA2B,EACY;IACvC,IAAI,IAAI,CAACL,kBAAkB,CAACc,MAAM,KAAK,CAAC,EAAE;MACtC,OAAO,IAAI;IACf;IAEA,MAAMC,OAAO,GAAG,IAAI,CAACf,kBAAkB,CAAC,IAAI,CAACA,kBAAkB,CAACc,MAAM,GAAG,CAAC,CAAC;IAE3E,OAAOC,OAAO,CAACC,eAAe,CAACX,QAAQ,CAAC;EAC5C;AACJ;AAEA,OAAO,MAAMhB,aAAa,GAAGC,WAAW,CAAC2B,oBAAoB,CAAC;EAC1DC,cAAc,EAAErB,iBAAiB;EACjCsB,YAAY,EAAE,CAACxB,qBAAqB,EAAE,CAACD,oBAAoB,EAAE;IAAE0B,QAAQ,EAAE;EAAK,CAAC,CAAC;AACpF,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ import type { TransportSettings } from "../../types.js";
2
+ export declare const getDefaultSettingsFromEnv: () => TransportSettings | null;
@@ -0,0 +1,31 @@
1
+ const getPort = value => {
2
+ const port = Number(value);
3
+ if (!!value && isNaN(port) === false) {
4
+ return port;
5
+ }
6
+ return 25;
7
+ };
8
+ export const getDefaultSettingsFromEnv = () => {
9
+ const input = {
10
+ host: process.env.WEBINY_API_MAILER_HOST,
11
+ port: getPort(process.env.WEBINY_API_MAILER_PORT),
12
+ user: process.env.WEBINY_API_MAILER_USER,
13
+ password: process.env.WEBINY_API_MAILER_PASSWORD,
14
+ replyTo: process.env.WEBINY_API_MAILER_REPLY_TO,
15
+ from: process.env.WEBINY_API_MAILER_FROM
16
+ };
17
+
18
+ // No need to do the validation if there is not at least one variable defined
19
+ const hasAtLeastOneValue = Object.values(input).some(value => !!String(value).trim());
20
+ if (!hasAtLeastOneValue) {
21
+ return null;
22
+ }
23
+
24
+ // Basic validation - require essential fields
25
+ if (!input.host || !input.user || !input.from) {
26
+ return null;
27
+ }
28
+ return input;
29
+ };
30
+
31
+ //# sourceMappingURL=TransportFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getPort","value","port","Number","isNaN","getDefaultSettingsFromEnv","input","host","process","env","WEBINY_API_MAILER_HOST","WEBINY_API_MAILER_PORT","user","WEBINY_API_MAILER_USER","password","WEBINY_API_MAILER_PASSWORD","replyTo","WEBINY_API_MAILER_REPLY_TO","from","WEBINY_API_MAILER_FROM","hasAtLeastOneValue","Object","values","some","String","trim"],"sources":["TransportFactory.ts"],"sourcesContent":["import type { TransportSettings } from \"~/types.js\";\n\nconst getPort = (value: any): number => {\n const port = Number(value);\n if (!!value && isNaN(port) === false) {\n return port;\n }\n return 25;\n};\n\nexport const getDefaultSettingsFromEnv = (): TransportSettings | null => {\n const input: Partial<TransportSettings> = {\n host: process.env.WEBINY_API_MAILER_HOST,\n port: getPort(process.env.WEBINY_API_MAILER_PORT),\n user: process.env.WEBINY_API_MAILER_USER,\n password: process.env.WEBINY_API_MAILER_PASSWORD,\n replyTo: process.env.WEBINY_API_MAILER_REPLY_TO,\n from: process.env.WEBINY_API_MAILER_FROM\n };\n\n // No need to do the validation if there is not at least one variable defined\n const hasAtLeastOneValue = Object.values(input).some(value => !!String(value).trim());\n if (!hasAtLeastOneValue) {\n return null;\n }\n\n // Basic validation - require essential fields\n if (!input.host || !input.user || !input.from) {\n return null;\n }\n\n return input as TransportSettings;\n};\n"],"mappings":"AAEA,MAAMA,OAAO,GAAIC,KAAU,IAAa;EACpC,MAAMC,IAAI,GAAGC,MAAM,CAACF,KAAK,CAAC;EAC1B,IAAI,CAAC,CAACA,KAAK,IAAIG,KAAK,CAACF,IAAI,CAAC,KAAK,KAAK,EAAE;IAClC,OAAOA,IAAI;EACf;EACA,OAAO,EAAE;AACb,CAAC;AAED,OAAO,MAAMG,yBAAyB,GAAGA,CAAA,KAAgC;EACrE,MAAMC,KAAiC,GAAG;IACtCC,IAAI,EAAEC,OAAO,CAACC,GAAG,CAACC,sBAAsB;IACxCR,IAAI,EAAEF,OAAO,CAACQ,OAAO,CAACC,GAAG,CAACE,sBAAsB,CAAC;IACjDC,IAAI,EAAEJ,OAAO,CAACC,GAAG,CAACI,sBAAsB;IACxCC,QAAQ,EAAEN,OAAO,CAACC,GAAG,CAACM,0BAA0B;IAChDC,OAAO,EAAER,OAAO,CAACC,GAAG,CAACQ,0BAA0B;IAC/CC,IAAI,EAAEV,OAAO,CAACC,GAAG,CAACU;EACtB,CAAC;;EAED;EACA,MAAMC,kBAAkB,GAAGC,MAAM,CAACC,MAAM,CAAChB,KAAK,CAAC,CAACiB,IAAI,CAACtB,KAAK,IAAI,CAAC,CAACuB,MAAM,CAACvB,KAAK,CAAC,CAACwB,IAAI,CAAC,CAAC,CAAC;EACrF,IAAI,CAACL,kBAAkB,EAAE;IACrB,OAAO,IAAI;EACf;;EAEA;EACA,IAAI,CAACd,KAAK,CAACC,IAAI,IAAI,CAACD,KAAK,CAACM,IAAI,IAAI,CAACN,KAAK,CAACY,IAAI,EAAE;IAC3C,OAAO,IAAI;EACf;EAEA,OAAOZ,KAAK;AAChB,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const MailerServiceFeature: import("@webiny/feature/api/createFeature.js").FeatureDefinition<unknown>;
@@ -0,0 +1,10 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { MailerService } from "./MailerService.js";
3
+ export const MailerServiceFeature = createFeature({
4
+ name: "Mailer/MailerService",
5
+ register(container) {
6
+ container.register(MailerService).inSingletonScope();
7
+ }
8
+ });
9
+
10
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createFeature","MailerService","MailerServiceFeature","name","register","container","inSingletonScope"],"sources":["feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { MailerService } from \"./MailerService.js\";\n\nexport const MailerServiceFeature = createFeature({\n name: \"Mailer/MailerService\",\n register(container) {\n container.register(MailerService).inSingletonScope();\n }\n});\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,qBAAqB;AACnD,SAASC,aAAa;AAEtB,OAAO,MAAMC,oBAAoB,GAAGF,aAAa,CAAC;EAC9CG,IAAI,EAAE,sBAAsB;EAC5BC,QAAQA,CAACC,SAAS,EAAE;IAChBA,SAAS,CAACD,QAAQ,CAACH,aAAa,CAAC,CAACK,gBAAgB,CAAC,CAAC;EACxD;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ import { Encryption } from "../../domain/Encryption/abstractions.js";
2
+ import { SaveSettingsRepository, type SaveSettingsInput } from "./abstractions.js";
3
+ import { KeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
4
+ declare class SaveSettingsRepositoryImpl implements SaveSettingsRepository.Interface {
5
+ private keyValueStore;
6
+ private encryption;
7
+ constructor(keyValueStore: KeyValueStore.Interface, encryption: Encryption.Interface);
8
+ execute(input: SaveSettingsInput): SaveSettingsRepository.Return;
9
+ }
10
+ export declare const SaveSettingsRepositoryImplementation: typeof SaveSettingsRepositoryImpl & {
11
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ISaveSettingsRepository>;
12
+ };
13
+ export {};
@@ -0,0 +1,57 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { Encryption } from "../../domain/Encryption/abstractions.js";
3
+ import { SaveSettingsRepository } from "./abstractions.js";
4
+ import { SettingsPersistenceError } from "../../domain/errors.js";
5
+ import { KeyValueStore } from "@webiny/api-core/features/keyValueStore/index.js";
6
+ import { MAILER_TRANSPORT_SETTINGS } from "../../constants.js";
7
+ const DEFAULT_PORT = 25;
8
+ class SaveSettingsRepositoryImpl {
9
+ constructor(keyValueStore, encryption) {
10
+ this.keyValueStore = keyValueStore;
11
+ this.encryption = encryption;
12
+ }
13
+ async execute(input) {
14
+ // Check if settings exist
15
+ const existingResult = await this.keyValueStore.get(MAILER_TRANSPORT_SETTINGS);
16
+ const existingSettings = existingResult.isOk() ? existingResult.value : null;
17
+ const transportSettings = existingSettings ?? {};
18
+
19
+ // If updating and no password provided, keep the existing password
20
+ let passwordToStore = input.password || "";
21
+ if (!input.password && existingSettings) {
22
+ passwordToStore = await this.encryption.decrypt(transportSettings.password || "");
23
+ }
24
+
25
+ // Encrypt password
26
+ const encryptedPassword = await this.encryption.encrypt(passwordToStore);
27
+
28
+ // Prepare data
29
+ const data = {
30
+ host: input.host ?? transportSettings.host,
31
+ port: input.port ?? transportSettings.port ?? DEFAULT_PORT,
32
+ user: input.user ?? transportSettings.user,
33
+ password: encryptedPassword,
34
+ from: input.from ?? transportSettings.from,
35
+ replyTo: input.replyTo ?? transportSettings.replyTo
36
+ };
37
+
38
+ // Save settings
39
+ const result = await this.keyValueStore.set(MAILER_TRANSPORT_SETTINGS, data);
40
+ if (result.isFail()) {
41
+ return Result.fail(new SettingsPersistenceError(result.error));
42
+ }
43
+
44
+ // Return without encrypted password
45
+ const returnSettings = {
46
+ ...data,
47
+ password: "" // Don't return password
48
+ };
49
+ return Result.ok(returnSettings);
50
+ }
51
+ }
52
+ export const SaveSettingsRepositoryImplementation = SaveSettingsRepository.createImplementation({
53
+ implementation: SaveSettingsRepositoryImpl,
54
+ dependencies: [KeyValueStore, Encryption]
55
+ });
56
+
57
+ //# sourceMappingURL=SaveSettingsRepository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","Encryption","SaveSettingsRepository","SettingsPersistenceError","KeyValueStore","MAILER_TRANSPORT_SETTINGS","DEFAULT_PORT","SaveSettingsRepositoryImpl","constructor","keyValueStore","encryption","execute","input","existingResult","get","existingSettings","isOk","value","transportSettings","passwordToStore","password","decrypt","encryptedPassword","encrypt","data","host","port","user","from","replyTo","result","set","isFail","fail","error","returnSettings","ok","SaveSettingsRepositoryImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsRepository.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport { Encryption } from \"~/domain/Encryption/abstractions.js\";\nimport { SaveSettingsRepository, type SaveSettingsInput } from \"./abstractions.js\";\nimport type { TransportSettings } from \"~/types.js\";\nimport { SettingsPersistenceError } from \"~/domain/errors.js\";\nimport { KeyValueStore } from \"@webiny/api-core/features/keyValueStore/index.js\";\nimport { MAILER_TRANSPORT_SETTINGS } from \"~/constants.js\";\n\nconst DEFAULT_PORT = 25;\n\nclass SaveSettingsRepositoryImpl implements SaveSettingsRepository.Interface {\n constructor(\n private keyValueStore: KeyValueStore.Interface,\n private encryption: Encryption.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsRepository.Return {\n // Check if settings exist\n const existingResult =\n await this.keyValueStore.get<TransportSettings>(MAILER_TRANSPORT_SETTINGS);\n const existingSettings = existingResult.isOk() ? existingResult.value : null;\n const transportSettings: Partial<TransportSettings> = existingSettings ?? {};\n\n // If updating and no password provided, keep the existing password\n let passwordToStore = input.password || \"\";\n if (!input.password && existingSettings) {\n passwordToStore = await this.encryption.decrypt(transportSettings.password || \"\");\n }\n\n // Encrypt password\n const encryptedPassword = await this.encryption.encrypt(passwordToStore);\n\n // Prepare data\n const data = {\n host: input.host ?? transportSettings.host,\n port: input.port ?? transportSettings.port ?? DEFAULT_PORT,\n user: input.user ?? transportSettings.user,\n password: encryptedPassword,\n from: input.from ?? transportSettings.from,\n replyTo: input.replyTo ?? transportSettings.replyTo\n };\n\n // Save settings\n const result = await this.keyValueStore.set(MAILER_TRANSPORT_SETTINGS, data);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Return without encrypted password\n const returnSettings: TransportSettings = {\n ...data,\n password: \"\" // Don't return password\n };\n\n return Result.ok(returnSettings);\n }\n}\n\nexport const SaveSettingsRepositoryImplementation = SaveSettingsRepository.createImplementation({\n implementation: SaveSettingsRepositoryImpl,\n dependencies: [KeyValueStore, Encryption]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SAASC,UAAU;AACnB,SAASC,sBAAsB;AAE/B,SAASC,wBAAwB;AACjC,SAASC,aAAa,QAAQ,kDAAkD;AAChF,SAASC,yBAAyB;AAElC,MAAMC,YAAY,GAAG,EAAE;AAEvB,MAAMC,0BAA0B,CAA6C;EACzEC,WAAWA,CACCC,aAAsC,EACtCC,UAAgC,EAC1C;IAAA,KAFUD,aAAsC,GAAtCA,aAAsC;IAAA,KACtCC,UAAgC,GAAhCA,UAAgC;EACzC;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAAiC;IACnE;IACA,MAAMC,cAAc,GAChB,MAAM,IAAI,CAACJ,aAAa,CAACK,GAAG,CAAoBT,yBAAyB,CAAC;IAC9E,MAAMU,gBAAgB,GAAGF,cAAc,CAACG,IAAI,CAAC,CAAC,GAAGH,cAAc,CAACI,KAAK,GAAG,IAAI;IAC5E,MAAMC,iBAA6C,GAAGH,gBAAgB,IAAI,CAAC,CAAC;;IAE5E;IACA,IAAII,eAAe,GAAGP,KAAK,CAACQ,QAAQ,IAAI,EAAE;IAC1C,IAAI,CAACR,KAAK,CAACQ,QAAQ,IAAIL,gBAAgB,EAAE;MACrCI,eAAe,GAAG,MAAM,IAAI,CAACT,UAAU,CAACW,OAAO,CAACH,iBAAiB,CAACE,QAAQ,IAAI,EAAE,CAAC;IACrF;;IAEA;IACA,MAAME,iBAAiB,GAAG,MAAM,IAAI,CAACZ,UAAU,CAACa,OAAO,CAACJ,eAAe,CAAC;;IAExE;IACA,MAAMK,IAAI,GAAG;MACTC,IAAI,EAAEb,KAAK,CAACa,IAAI,IAAIP,iBAAiB,CAACO,IAAI;MAC1CC,IAAI,EAAEd,KAAK,CAACc,IAAI,IAAIR,iBAAiB,CAACQ,IAAI,IAAIpB,YAAY;MAC1DqB,IAAI,EAAEf,KAAK,CAACe,IAAI,IAAIT,iBAAiB,CAACS,IAAI;MAC1CP,QAAQ,EAAEE,iBAAiB;MAC3BM,IAAI,EAAEhB,KAAK,CAACgB,IAAI,IAAIV,iBAAiB,CAACU,IAAI;MAC1CC,OAAO,EAAEjB,KAAK,CAACiB,OAAO,IAAIX,iBAAiB,CAACW;IAChD,CAAC;;IAED;IACA,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACrB,aAAa,CAACsB,GAAG,CAAC1B,yBAAyB,EAAEmB,IAAI,CAAC;IAE5E,IAAIM,MAAM,CAACE,MAAM,CAAC,CAAC,EAAE;MACjB,OAAOhC,MAAM,CAACiC,IAAI,CAAC,IAAI9B,wBAAwB,CAAC2B,MAAM,CAACI,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA,MAAMC,cAAiC,GAAG;MACtC,GAAGX,IAAI;MACPJ,QAAQ,EAAE,EAAE,CAAC;IACjB,CAAC;IAED,OAAOpB,MAAM,CAACoC,EAAE,CAACD,cAAc,CAAC;EACpC;AACJ;AAEA,OAAO,MAAME,oCAAoC,GAAGnC,sBAAsB,CAACoC,oBAAoB,CAAC;EAC5FC,cAAc,EAAEhC,0BAA0B;EAC1CiC,YAAY,EAAE,CAACpC,aAAa,EAAEH,UAAU;AAC5C,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,14 @@
1
+ import { EventPublisher as EventPublisherAbstraction } from "@webiny/api-core/features/EventPublisher";
2
+ import { SaveSettingsUseCase, SaveSettingsRepository, type SaveSettingsInput } from "./abstractions.js";
3
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
4
+ declare class SaveSettingsUseCaseImpl implements SaveSettingsUseCase.Interface {
5
+ private identityContext;
6
+ private eventPublisher;
7
+ private repository;
8
+ constructor(identityContext: IdentityContext.Interface, eventPublisher: EventPublisherAbstraction.Interface, repository: SaveSettingsRepository.Interface);
9
+ execute(input: SaveSettingsInput): SaveSettingsUseCase.Return;
10
+ }
11
+ export declare const SaveSettingsUseCaseImplementation: typeof SaveSettingsUseCaseImpl & {
12
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ISaveSettings>;
13
+ };
14
+ export {};
@@ -0,0 +1,51 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import { EventPublisher } from "@webiny/api-core/features/EventPublisher";
3
+ import { SaveSettingsUseCase, SaveSettingsRepository } from "./abstractions.js";
4
+ import { MailerSettingsBeforeSaveEvent, MailerSettingsAfterSaveEvent } from "./events.js";
5
+ import { saveValidation } from "./validation.js";
6
+ import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized } from "../../domain/errors.js";
7
+ import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
8
+ class SaveSettingsUseCaseImpl {
9
+ constructor(identityContext, eventPublisher, repository) {
10
+ this.identityContext = identityContext;
11
+ this.eventPublisher = eventPublisher;
12
+ this.repository = repository;
13
+ }
14
+ async execute(input) {
15
+ const permission = await this.identityContext.getPermission("mailer.settings");
16
+ if (!permission) {
17
+ return Result.fail(new SettingsNotAuthorized());
18
+ }
19
+
20
+ // Validate input
21
+ const validationResult = saveValidation.safeParse(input);
22
+ if (!validationResult.success) {
23
+ return Result.fail(new SettingsValidationError(validationResult.error.errors));
24
+ }
25
+
26
+ // Publish before save event
27
+ const beforeSaveEvent = new MailerSettingsBeforeSaveEvent({
28
+ input
29
+ });
30
+ await this.eventPublisher.publish(beforeSaveEvent);
31
+
32
+ // Save settings
33
+ const result = await this.repository.execute(input);
34
+ if (result.isFail()) {
35
+ return Result.fail(new SettingsPersistenceError(result.error));
36
+ }
37
+
38
+ // Publish after save event
39
+ const afterSaveEvent = new MailerSettingsAfterSaveEvent({
40
+ settings: result.value
41
+ });
42
+ await this.eventPublisher.publish(afterSaveEvent);
43
+ return result;
44
+ }
45
+ }
46
+ export const SaveSettingsUseCaseImplementation = SaveSettingsUseCase.createImplementation({
47
+ implementation: SaveSettingsUseCaseImpl,
48
+ dependencies: [IdentityContext, EventPublisher, SaveSettingsRepository]
49
+ });
50
+
51
+ //# sourceMappingURL=SaveSettingsUseCase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Result","EventPublisher","SaveSettingsUseCase","SaveSettingsRepository","MailerSettingsBeforeSaveEvent","MailerSettingsAfterSaveEvent","saveValidation","SettingsValidationError","SettingsPersistenceError","SettingsNotAuthorized","IdentityContext","SaveSettingsUseCaseImpl","constructor","identityContext","eventPublisher","repository","execute","input","permission","getPermission","fail","validationResult","safeParse","success","error","errors","beforeSaveEvent","publish","result","isFail","afterSaveEvent","settings","value","SaveSettingsUseCaseImplementation","createImplementation","implementation","dependencies"],"sources":["SaveSettingsUseCase.ts"],"sourcesContent":["import { Result } from \"@webiny/feature/api\";\nimport {\n EventPublisher,\n EventPublisher as EventPublisherAbstraction\n} from \"@webiny/api-core/features/EventPublisher\";\nimport {\n SaveSettingsUseCase,\n SaveSettingsRepository,\n type SaveSettingsInput\n} from \"./abstractions.js\";\nimport { MailerSettingsBeforeSaveEvent, MailerSettingsAfterSaveEvent } from \"./events.js\";\nimport { saveValidation } from \"./validation.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized\n} from \"~/domain/errors.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\n\nclass SaveSettingsUseCaseImpl implements SaveSettingsUseCase.Interface {\n constructor(\n private identityContext: IdentityContext.Interface,\n private eventPublisher: EventPublisherAbstraction.Interface,\n private repository: SaveSettingsRepository.Interface\n ) {}\n\n async execute(input: SaveSettingsInput): SaveSettingsUseCase.Return {\n const permission = await this.identityContext.getPermission(\"mailer.settings\");\n\n if (!permission) {\n return Result.fail(new SettingsNotAuthorized());\n }\n\n // Validate input\n const validationResult = saveValidation.safeParse(input);\n if (!validationResult.success) {\n return Result.fail(new SettingsValidationError(validationResult.error.errors));\n }\n\n // Publish before save event\n const beforeSaveEvent = new MailerSettingsBeforeSaveEvent({ input });\n await this.eventPublisher.publish(beforeSaveEvent);\n\n // Save settings\n const result = await this.repository.execute(input);\n\n if (result.isFail()) {\n return Result.fail(new SettingsPersistenceError(result.error));\n }\n\n // Publish after save event\n const afterSaveEvent = new MailerSettingsAfterSaveEvent({ settings: result.value });\n await this.eventPublisher.publish(afterSaveEvent);\n\n return result;\n }\n}\n\nexport const SaveSettingsUseCaseImplementation = SaveSettingsUseCase.createImplementation({\n implementation: SaveSettingsUseCaseImpl,\n dependencies: [IdentityContext, EventPublisher, SaveSettingsRepository]\n});\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,qBAAqB;AAC5C,SACIC,cAAc,QAEX,0CAA0C;AACjD,SACIC,mBAAmB,EACnBC,sBAAsB;AAG1B,SAASC,6BAA6B,EAAEC,4BAA4B;AACpE,SAASC,cAAc;AACvB,SACIC,uBAAuB,EACvBC,wBAAwB,EACxBC,qBAAqB;AAEzB,SAASC,eAAe,QAAQ,6DAA6D;AAE7F,MAAMC,uBAAuB,CAA0C;EACnEC,WAAWA,CACCC,eAA0C,EAC1CC,cAAmD,EACnDC,UAA4C,EACtD;IAAA,KAHUF,eAA0C,GAA1CA,eAA0C;IAAA,KAC1CC,cAAmD,GAAnDA,cAAmD;IAAA,KACnDC,UAA4C,GAA5CA,UAA4C;EACrD;EAEH,MAAMC,OAAOA,CAACC,KAAwB,EAA8B;IAChE,MAAMC,UAAU,GAAG,MAAM,IAAI,CAACL,eAAe,CAACM,aAAa,CAAC,iBAAiB,CAAC;IAE9E,IAAI,CAACD,UAAU,EAAE;MACb,OAAOlB,MAAM,CAACoB,IAAI,CAAC,IAAIX,qBAAqB,CAAC,CAAC,CAAC;IACnD;;IAEA;IACA,MAAMY,gBAAgB,GAAGf,cAAc,CAACgB,SAAS,CAACL,KAAK,CAAC;IACxD,IAAI,CAACI,gBAAgB,CAACE,OAAO,EAAE;MAC3B,OAAOvB,MAAM,CAACoB,IAAI,CAAC,IAAIb,uBAAuB,CAACc,gBAAgB,CAACG,KAAK,CAACC,MAAM,CAAC,CAAC;IAClF;;IAEA;IACA,MAAMC,eAAe,GAAG,IAAItB,6BAA6B,CAAC;MAAEa;IAAM,CAAC,CAAC;IACpE,MAAM,IAAI,CAACH,cAAc,CAACa,OAAO,CAACD,eAAe,CAAC;;IAElD;IACA,MAAME,MAAM,GAAG,MAAM,IAAI,CAACb,UAAU,CAACC,OAAO,CAACC,KAAK,CAAC;IAEnD,IAAIW,MAAM,CAACC,MAAM,CAAC,CAAC,EAAE;MACjB,OAAO7B,MAAM,CAACoB,IAAI,CAAC,IAAIZ,wBAAwB,CAACoB,MAAM,CAACJ,KAAK,CAAC,CAAC;IAClE;;IAEA;IACA,MAAMM,cAAc,GAAG,IAAIzB,4BAA4B,CAAC;MAAE0B,QAAQ,EAAEH,MAAM,CAACI;IAAM,CAAC,CAAC;IACnF,MAAM,IAAI,CAAClB,cAAc,CAACa,OAAO,CAACG,cAAc,CAAC;IAEjD,OAAOF,MAAM;EACjB;AACJ;AAEA,OAAO,MAAMK,iCAAiC,GAAG/B,mBAAmB,CAACgC,oBAAoB,CAAC;EACtFC,cAAc,EAAExB,uBAAuB;EACvCyB,YAAY,EAAE,CAAC1B,eAAe,EAAET,cAAc,EAAEE,sBAAsB;AAC1E,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,53 @@
1
+ import { Result } from "@webiny/feature/api";
2
+ import type { DomainEvent, IEventHandler } from "@webiny/api-core/features/EventPublisher";
3
+ import type { TransportSettings } from "../../types.js";
4
+ import { SettingsValidationError, SettingsPersistenceError, SettingsNotAuthorized } from "../../domain/errors.js";
5
+ export interface SaveSettingsInput {
6
+ host: string;
7
+ port?: number;
8
+ user: string;
9
+ password?: string;
10
+ from: string;
11
+ replyTo?: string;
12
+ }
13
+ export interface ISaveSettingsErrors {
14
+ validation: SettingsValidationError;
15
+ persistence: SettingsPersistenceError;
16
+ notAuthorized: SettingsNotAuthorized;
17
+ }
18
+ type SaveSettingsError = ISaveSettingsErrors[keyof ISaveSettingsErrors];
19
+ export interface ISaveSettingsRepository {
20
+ execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;
21
+ }
22
+ export declare const SaveSettingsRepository: import("@webiny/di").Abstraction<ISaveSettingsRepository>;
23
+ export declare namespace SaveSettingsRepository {
24
+ type Interface = ISaveSettingsRepository;
25
+ type Return = Promise<Result<TransportSettings, SaveSettingsError>>;
26
+ type Error = SaveSettingsError;
27
+ }
28
+ export interface ISaveSettings {
29
+ execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;
30
+ }
31
+ export declare const SaveSettingsUseCase: import("@webiny/di").Abstraction<ISaveSettings>;
32
+ export declare namespace SaveSettingsUseCase {
33
+ type Interface = ISaveSettings;
34
+ type Return = Promise<Result<TransportSettings, SaveSettingsError>>;
35
+ type Error = SaveSettingsError;
36
+ }
37
+ export interface MailerSettingsBeforeSavePayload {
38
+ input: SaveSettingsInput;
39
+ }
40
+ export interface MailerSettingsAfterSavePayload {
41
+ settings: TransportSettings;
42
+ }
43
+ export declare const MailerSettingsBeforeSaveHandler: import("@webiny/di").Abstraction<IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>>;
44
+ export declare namespace MailerSettingsBeforeSaveHandler {
45
+ type Interface = IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>;
46
+ type Event = DomainEvent<MailerSettingsBeforeSavePayload>;
47
+ }
48
+ export declare const MailerSettingsAfterSaveHandler: import("@webiny/di").Abstraction<IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>>;
49
+ export declare namespace MailerSettingsAfterSaveHandler {
50
+ type Interface = IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>;
51
+ type Event = DomainEvent<MailerSettingsAfterSavePayload>;
52
+ }
53
+ export {};
@@ -0,0 +1,11 @@
1
+ import { createAbstraction } from "@webiny/feature/api";
2
+ export const SaveSettingsRepository = createAbstraction("SaveSettingsRepository");
3
+ export const SaveSettingsUseCase = createAbstraction("SaveSettingsUseCase");
4
+
5
+ // Domain Events
6
+
7
+ // Event Handler Abstractions
8
+ export const MailerSettingsBeforeSaveHandler = createAbstraction("MailerSettingsBeforeSaveHandler");
9
+ export const MailerSettingsAfterSaveHandler = createAbstraction("MailerSettingsAfterSaveHandler");
10
+
11
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createAbstraction","SaveSettingsRepository","SaveSettingsUseCase","MailerSettingsBeforeSaveHandler","MailerSettingsAfterSaveHandler"],"sources":["abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/api\";\nimport { Result } from \"@webiny/feature/api\";\nimport type { DomainEvent, IEventHandler } from \"@webiny/api-core/features/EventPublisher\";\nimport type { TransportSettings } from \"~/types.js\";\nimport {\n SettingsValidationError,\n SettingsPersistenceError,\n SettingsNotAuthorized\n} from \"~/domain/errors.js\";\n\nexport interface SaveSettingsInput {\n host: string;\n port?: number;\n user: string;\n password?: string;\n from: string;\n replyTo?: string;\n}\n\nexport interface ISaveSettingsErrors {\n validation: SettingsValidationError;\n persistence: SettingsPersistenceError;\n notAuthorized: SettingsNotAuthorized;\n}\n\ntype SaveSettingsError = ISaveSettingsErrors[keyof ISaveSettingsErrors];\n\nexport interface ISaveSettingsRepository {\n execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsRepository =\n createAbstraction<ISaveSettingsRepository>(\"SaveSettingsRepository\");\n\nexport namespace SaveSettingsRepository {\n export type Interface = ISaveSettingsRepository;\n export type Return = Promise<Result<TransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\nexport interface ISaveSettings {\n execute(input: SaveSettingsInput): Promise<Result<TransportSettings, SaveSettingsError>>;\n}\n\nexport const SaveSettingsUseCase = createAbstraction<ISaveSettings>(\"SaveSettingsUseCase\");\n\nexport namespace SaveSettingsUseCase {\n export type Interface = ISaveSettings;\n export type Return = Promise<Result<TransportSettings, SaveSettingsError>>;\n export type Error = SaveSettingsError;\n}\n\n// Domain Events\nexport interface MailerSettingsBeforeSavePayload {\n input: SaveSettingsInput;\n}\n\nexport interface MailerSettingsAfterSavePayload {\n settings: TransportSettings;\n}\n\n// Event Handler Abstractions\nexport const MailerSettingsBeforeSaveHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>\n>(\"MailerSettingsBeforeSaveHandler\");\n\nexport namespace MailerSettingsBeforeSaveHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>;\n export type Event = DomainEvent<MailerSettingsBeforeSavePayload>;\n}\n\nexport const MailerSettingsAfterSaveHandler = createAbstraction<\n IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>\n>(\"MailerSettingsAfterSaveHandler\");\n\nexport namespace MailerSettingsAfterSaveHandler {\n export type Interface = IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>;\n export type Event = DomainEvent<MailerSettingsAfterSavePayload>;\n}\n"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,qBAAqB;AA+BvD,OAAO,MAAMC,sBAAsB,GAC/BD,iBAAiB,CAA0B,wBAAwB,CAAC;AAYxE,OAAO,MAAME,mBAAmB,GAAGF,iBAAiB,CAAgB,qBAAqB,CAAC;;AAQ1F;;AASA;AACA,OAAO,MAAMG,+BAA+B,GAAGH,iBAAiB,CAE9D,iCAAiC,CAAC;AAOpC,OAAO,MAAMI,8BAA8B,GAAGJ,iBAAiB,CAE7D,gCAAgC,CAAC","ignoreList":[]}
@@ -0,0 +1,10 @@
1
+ import { DomainEvent } from "@webiny/api-core/features/EventPublisher";
2
+ import type { MailerSettingsBeforeSavePayload, MailerSettingsAfterSavePayload } from "./abstractions.js";
3
+ export declare class MailerSettingsBeforeSaveEvent extends DomainEvent<MailerSettingsBeforeSavePayload> {
4
+ eventType: "mailer.settings.beforeSave";
5
+ getHandlerAbstraction(): import("@webiny/di").Abstraction<import("@webiny/api-core/features/EventPublisher").IEventHandler<DomainEvent<MailerSettingsBeforeSavePayload>>>;
6
+ }
7
+ export declare class MailerSettingsAfterSaveEvent extends DomainEvent<MailerSettingsAfterSavePayload> {
8
+ eventType: "mailer.settings.afterSave";
9
+ getHandlerAbstraction(): import("@webiny/di").Abstraction<import("@webiny/api-core/features/EventPublisher").IEventHandler<DomainEvent<MailerSettingsAfterSavePayload>>>;
10
+ }
@@ -0,0 +1,16 @@
1
+ import { DomainEvent } from "@webiny/api-core/features/EventPublisher";
2
+ import { MailerSettingsBeforeSaveHandler, MailerSettingsAfterSaveHandler } from "./abstractions.js";
3
+ export class MailerSettingsBeforeSaveEvent extends DomainEvent {
4
+ eventType = "mailer.settings.beforeSave";
5
+ getHandlerAbstraction() {
6
+ return MailerSettingsBeforeSaveHandler;
7
+ }
8
+ }
9
+ export class MailerSettingsAfterSaveEvent extends DomainEvent {
10
+ eventType = "mailer.settings.afterSave";
11
+ getHandlerAbstraction() {
12
+ return MailerSettingsAfterSaveHandler;
13
+ }
14
+ }
15
+
16
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["DomainEvent","MailerSettingsBeforeSaveHandler","MailerSettingsAfterSaveHandler","MailerSettingsBeforeSaveEvent","eventType","getHandlerAbstraction","MailerSettingsAfterSaveEvent"],"sources":["events.ts"],"sourcesContent":["import { DomainEvent } from \"@webiny/api-core/features/EventPublisher\";\nimport { MailerSettingsBeforeSaveHandler, MailerSettingsAfterSaveHandler } from \"./abstractions.js\";\nimport type {\n MailerSettingsBeforeSavePayload,\n MailerSettingsAfterSavePayload\n} from \"./abstractions.js\";\n\nexport class MailerSettingsBeforeSaveEvent extends DomainEvent<MailerSettingsBeforeSavePayload> {\n eventType = \"mailer.settings.beforeSave\" as const;\n\n getHandlerAbstraction() {\n return MailerSettingsBeforeSaveHandler;\n }\n}\n\nexport class MailerSettingsAfterSaveEvent extends DomainEvent<MailerSettingsAfterSavePayload> {\n eventType = \"mailer.settings.afterSave\" as const;\n\n getHandlerAbstraction() {\n return MailerSettingsAfterSaveHandler;\n }\n}\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,0CAA0C;AACtE,SAASC,+BAA+B,EAAEC,8BAA8B;AAMxE,OAAO,MAAMC,6BAA6B,SAASH,WAAW,CAAkC;EAC5FI,SAAS,GAAG,4BAA4B;EAExCC,qBAAqBA,CAAA,EAAG;IACpB,OAAOJ,+BAA+B;EAC1C;AACJ;AAEA,OAAO,MAAMK,4BAA4B,SAASN,WAAW,CAAiC;EAC1FI,SAAS,GAAG,2BAA2B;EAEvCC,qBAAqBA,CAAA,EAAG;IACpB,OAAOH,8BAA8B;EACzC;AACJ","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export declare const SaveSettingsFeature: import("@webiny/feature/api/createFeature.js").FeatureDefinition<unknown>;
@@ -0,0 +1,12 @@
1
+ import { createFeature } from "@webiny/feature/api";
2
+ import { SaveSettingsRepositoryImplementation } from "./SaveSettingsRepository.js";
3
+ import { SaveSettingsUseCaseImplementation } from "./SaveSettingsUseCase.js";
4
+ export const SaveSettingsFeature = createFeature({
5
+ name: "SaveSettings",
6
+ register(container) {
7
+ container.register(SaveSettingsRepositoryImplementation).inSingletonScope();
8
+ container.register(SaveSettingsUseCaseImplementation);
9
+ }
10
+ });
11
+
12
+ //# sourceMappingURL=feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createFeature","SaveSettingsRepositoryImplementation","SaveSettingsUseCaseImplementation","SaveSettingsFeature","name","register","container","inSingletonScope"],"sources":["feature.ts"],"sourcesContent":["import { createFeature } from \"@webiny/feature/api\";\nimport { SaveSettingsRepositoryImplementation } from \"./SaveSettingsRepository.js\";\nimport { SaveSettingsUseCaseImplementation } from \"./SaveSettingsUseCase.js\";\n\nexport const SaveSettingsFeature = createFeature({\n name: \"SaveSettings\",\n register(container) {\n container.register(SaveSettingsRepositoryImplementation).inSingletonScope();\n container.register(SaveSettingsUseCaseImplementation);\n }\n});\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,qBAAqB;AACnD,SAASC,oCAAoC;AAC7C,SAASC,iCAAiC;AAE1C,OAAO,MAAMC,mBAAmB,GAAGH,aAAa,CAAC;EAC7CI,IAAI,EAAE,cAAc;EACpBC,QAAQA,CAACC,SAAS,EAAE;IAChBA,SAAS,CAACD,QAAQ,CAACJ,oCAAoC,CAAC,CAACM,gBAAgB,CAAC,CAAC;IAC3ED,SAAS,CAACD,QAAQ,CAACH,iCAAiC,CAAC;EACzD;AACJ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export { SaveSettingsUseCase, MailerSettingsAfterSaveHandler, MailerSettingsBeforeSaveHandler } from "./abstractions.js";
@@ -0,0 +1,3 @@
1
+ export { SaveSettingsUseCase, MailerSettingsAfterSaveHandler, MailerSettingsBeforeSaveHandler } from "./abstractions.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["SaveSettingsUseCase","MailerSettingsAfterSaveHandler","MailerSettingsBeforeSaveHandler"],"sources":["index.ts"],"sourcesContent":["export {\n SaveSettingsUseCase,\n MailerSettingsAfterSaveHandler,\n MailerSettingsBeforeSaveHandler\n} from \"./abstractions.js\";\n"],"mappings":"AAAA,SACIA,mBAAmB,EACnBC,8BAA8B,EAC9BC,+BAA+B","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ import zod from "zod";
2
+ export declare const saveValidation: zod.ZodObject<{
3
+ password: zod.ZodEffects<zod.ZodOptional<zod.ZodOptional<zod.ZodNullable<zod.ZodString>>>, string | null, string | null | undefined>;
4
+ from: zod.ZodString;
5
+ port: zod.ZodOptional<zod.ZodNullable<zod.ZodOptional<zod.ZodNumber>>>;
6
+ replyTo: zod.ZodEffects<zod.ZodOptional<zod.ZodNullable<zod.ZodOptional<zod.ZodString>>>, string | null | undefined, unknown>;
7
+ host: zod.ZodString;
8
+ user: zod.ZodString;
9
+ }, "strip", zod.ZodTypeAny, {
10
+ host: string;
11
+ user: string;
12
+ password: string | null;
13
+ from: string;
14
+ port?: number | null | undefined;
15
+ replyTo?: string | null | undefined;
16
+ }, {
17
+ host: string;
18
+ user: string;
19
+ from: string;
20
+ port?: number | null | undefined;
21
+ password?: string | null | undefined;
22
+ replyTo?: unknown;
23
+ }>;
@@ -0,0 +1,19 @@
1
+ import zod from "zod";
2
+ const password = zod.string().describe("Password");
3
+ const common = {
4
+ from: zod.string().email().describe("Mail from"),
5
+ port: zod.number().optional().nullish().describe("Port"),
6
+ replyTo: zod.preprocess(
7
+ // We need to set empty strings to `null` before email validation kicks in
8
+ value => value === "" ? null : value, zod.string().email().optional().nullish()).describe("Mail reply-to"),
9
+ host: zod.string().describe("Hostname"),
10
+ user: zod.string().describe("User")
11
+ };
12
+ export const saveValidation = zod.object({
13
+ ...common,
14
+ password: password.nullish().optional().transform(value => {
15
+ return value === undefined ? null : value;
16
+ })
17
+ });
18
+
19
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["zod","password","string","describe","common","from","email","port","number","optional","nullish","replyTo","preprocess","value","host","user","saveValidation","object","transform","undefined"],"sources":["validation.ts"],"sourcesContent":["import zod from \"zod\";\n\nconst password = zod.string().describe(\"Password\");\n\nconst common = {\n from: zod.string().email().describe(\"Mail from\"),\n port: zod.number().optional().nullish().describe(\"Port\"),\n replyTo: zod\n .preprocess(\n // We need to set empty strings to `null` before email validation kicks in\n value => (value === \"\" ? null : value),\n zod.string().email().optional().nullish()\n )\n .describe(\"Mail reply-to\"),\n host: zod.string().describe(\"Hostname\"),\n user: zod.string().describe(\"User\")\n};\n\nexport const saveValidation = zod.object({\n ...common,\n password: password\n .nullish()\n .optional()\n .transform(value => {\n return value === undefined ? null : value;\n })\n});\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,KAAK;AAErB,MAAMC,QAAQ,GAAGD,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;AAElD,MAAMC,MAAM,GAAG;EACXC,IAAI,EAAEL,GAAG,CAACE,MAAM,CAAC,CAAC,CAACI,KAAK,CAAC,CAAC,CAACH,QAAQ,CAAC,WAAW,CAAC;EAChDI,IAAI,EAAEP,GAAG,CAACQ,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CAAC,CAACP,QAAQ,CAAC,MAAM,CAAC;EACxDQ,OAAO,EAAEX,GAAG,CACPY,UAAU;EACP;EACAC,KAAK,IAAKA,KAAK,KAAK,EAAE,GAAG,IAAI,GAAGA,KAAM,EACtCb,GAAG,CAACE,MAAM,CAAC,CAAC,CAACI,KAAK,CAAC,CAAC,CAACG,QAAQ,CAAC,CAAC,CAACC,OAAO,CAAC,CAC5C,CAAC,CACAP,QAAQ,CAAC,eAAe,CAAC;EAC9BW,IAAI,EAAEd,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,UAAU,CAAC;EACvCY,IAAI,EAAEf,GAAG,CAACE,MAAM,CAAC,CAAC,CAACC,QAAQ,CAAC,MAAM;AACtC,CAAC;AAED,OAAO,MAAMa,cAAc,GAAGhB,GAAG,CAACiB,MAAM,CAAC;EACrC,GAAGb,MAAM;EACTH,QAAQ,EAAEA,QAAQ,CACbS,OAAO,CAAC,CAAC,CACTD,QAAQ,CAAC,CAAC,CACVS,SAAS,CAACL,KAAK,IAAI;IAChB,OAAOA,KAAK,KAAKM,SAAS,GAAG,IAAI,GAAGN,KAAK;EAC7C,CAAC;AACT,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ import { EventPublisher as EventPublisherAbstraction } from "@webiny/api-core/features/EventPublisher";
2
+ import { SendMailUseCase } from "./abstractions.js";
3
+ import { MailerService } from "../../domain/MailerService/abstractions.js";
4
+ import type { TransportSendData } from "../../types.js";
5
+ import { MailValidationError } from "../../domain/errors.js";
6
+ import { Result } from "@webiny/feature/api";
7
+ declare class SendMailUseCaseImpl implements SendMailUseCase.Interface {
8
+ private mailerService;
9
+ private eventPublisher;
10
+ constructor(mailerService: MailerService.Interface, eventPublisher: EventPublisherAbstraction.Interface);
11
+ execute(data: TransportSendData): Promise<Result<never, MailValidationError> | Result<import("~/types.js").TransportSendResponse<any>, import("../../domain/MailerService/errors.js").NoTransportAvailableError | import("../../domain/MailerService/errors.js").NoSettingsConfiguredError | import("../../domain/MailerService/errors.js").TransportSendError>>;
12
+ }
13
+ export declare const SendMailUseCaseImplementation: typeof SendMailUseCaseImpl & {
14
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").ISendMailUseCase>;
15
+ };
16
+ export {};
@@ -0,0 +1,62 @@
1
+ import zod from "zod";
2
+ import { EventPublisher } from "@webiny/api-core/features/EventPublisher";
3
+ import { SendMailUseCase } from "./abstractions.js";
4
+ import { MailBeforeSendEvent, MailAfterSendEvent, MailSendErrorEvent } from "./events.js";
5
+ import { MailerService } from "../../domain/MailerService/abstractions.js";
6
+ import { MailValidationError } from "../../domain/errors.js";
7
+ import { Result } from "@webiny/feature/api";
8
+ const requiredString = zod.string();
9
+ const requiredEmail = requiredString.email();
10
+ const schema = zod.object({
11
+ to: zod.array(requiredEmail).optional(),
12
+ from: zod.string().email().optional(),
13
+ subject: requiredString.max(1024).min(2),
14
+ cc: zod.array(requiredEmail).optional(),
15
+ bcc: zod.array(requiredEmail).optional(),
16
+ replyTo: zod.string().email().optional(),
17
+ text: zod.string().optional(),
18
+ html: zod.string().optional()
19
+ }).refine(data => {
20
+ return !!data.text || !!data.html;
21
+ }, "Either text or html is required.");
22
+ class SendMailUseCaseImpl {
23
+ constructor(mailerService, eventPublisher) {
24
+ this.mailerService = mailerService;
25
+ this.eventPublisher = eventPublisher;
26
+ }
27
+ async execute(data) {
28
+ const validation = schema.safeParse(data);
29
+ if (!validation.success) {
30
+ return Result.fail(new MailValidationError(validation.error.errors));
31
+ }
32
+
33
+ // Publish before send event
34
+ await this.eventPublisher.publish(new MailBeforeSendEvent({
35
+ data
36
+ }));
37
+
38
+ // Send mail
39
+ const result = await this.mailerService.sendMail(data);
40
+ if (result.isFail()) {
41
+ // Publish error event
42
+ await this.eventPublisher.publish(new MailSendErrorEvent({
43
+ data,
44
+ error: result.error
45
+ }));
46
+ return result;
47
+ }
48
+
49
+ // Publish after send event
50
+ await this.eventPublisher.publish(new MailAfterSendEvent({
51
+ data,
52
+ response: result.value
53
+ }));
54
+ return result;
55
+ }
56
+ }
57
+ export const SendMailUseCaseImplementation = SendMailUseCase.createImplementation({
58
+ implementation: SendMailUseCaseImpl,
59
+ dependencies: [MailerService, EventPublisher]
60
+ });
61
+
62
+ //# sourceMappingURL=SendMailUseCase.js.map