@hartl-services/medusa-base 0.4.0 → 1.1.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 (258) hide show
  1. package/.medusa/server/src/admin/index.js +1657 -111
  2. package/.medusa/server/src/admin/index.mjs +1647 -101
  3. package/.medusa/server/src/api/admin/email/messages/[id]/resends/route.js +24 -0
  4. package/.medusa/server/src/api/admin/email/messages/[id]/route.js +12 -0
  5. package/.medusa/server/src/api/admin/email/messages/route.js +12 -0
  6. package/.medusa/server/src/api/admin/email/terms-versions/[id]/download/route.js +16 -0
  7. package/.medusa/server/src/api/admin/email/terms-versions/route.js +47 -0
  8. package/.medusa/server/src/api/admin/orders/[id]/documents/[document_id]/download/route.js +21 -0
  9. package/.medusa/server/src/api/admin/orders/[id]/documents/[document_id]/regenerate/route.js +38 -0
  10. package/.medusa/server/src/api/admin/orders/[id]/documents/regenerate/route.js +32 -0
  11. package/.medusa/server/src/api/admin/orders/[id]/documents/route.js +36 -0
  12. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/[fulfillment_id]/download/route.js +24 -0
  13. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/[fulfillment_id]/retry/route.js +44 -0
  14. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/route.js +82 -0
  15. package/.medusa/server/src/api/document-download-response.js +16 -0
  16. package/.medusa/server/src/api/document-response.js +23 -0
  17. package/.medusa/server/src/api/files/[asset]/route.js +24 -0
  18. package/.medusa/server/src/api/files/file-response.js +43 -0
  19. package/.medusa/server/src/api/files/gateway-options.js +31 -0
  20. package/.medusa/server/src/api/files/private/[token]/route.js +29 -0
  21. package/.medusa/server/src/api/files/upload/[token]/route.js +66 -0
  22. package/.medusa/server/src/api/middlewares.js +168 -1
  23. package/.medusa/server/src/api/packing-list-response.js +22 -0
  24. package/.medusa/server/src/api/route.js +27 -0
  25. package/.medusa/server/src/api/store/documents/[id]/download/route.js +21 -0
  26. package/.medusa/server/src/api/store/documents/[id]/route.js +15 -0
  27. package/.medusa/server/src/api/store/documents/route.js +11 -0
  28. package/.medusa/server/src/api/terms-download-response.js +12 -0
  29. package/.medusa/server/src/documents/config/index.js +18 -0
  30. package/.medusa/server/src/documents/paths/documents.js +6 -0
  31. package/.medusa/server/src/documents/paths/index.js +18 -0
  32. package/.medusa/server/src/documents/plugin-features.js +38 -0
  33. package/.medusa/server/src/documents/schemas/documents.js +18 -0
  34. package/.medusa/server/src/documents/schemas/index.js +18 -0
  35. package/.medusa/server/src/documents/scripts/verify-documents-file-storage.js +55 -0
  36. package/.medusa/server/src/documents/templates/financial-document.js +160 -0
  37. package/.medusa/server/src/documents/templates/format.js +73 -0
  38. package/.medusa/server/src/documents/templates/html-factory.js +42 -0
  39. package/.medusa/server/src/documents/templates/html-utils.js +23 -0
  40. package/.medusa/server/src/documents/templates/layout.js +142 -0
  41. package/.medusa/server/src/documents/templates/packing-list.js +52 -0
  42. package/.medusa/server/src/documents/types/admin-api.js +3 -0
  43. package/.medusa/server/src/documents/types/document-summary.js +3 -0
  44. package/.medusa/server/src/documents/types/documents.js +3 -0
  45. package/.medusa/server/src/documents/types/html-factory.js +6 -0
  46. package/.medusa/server/src/documents/types/index.js +22 -0
  47. package/.medusa/server/src/documents/types/store-api.js +3 -0
  48. package/.medusa/server/src/documents/utils/document-merchant.js +22 -0
  49. package/.medusa/server/src/documents/utils/document-render-settings.js +59 -0
  50. package/.medusa/server/src/documents/utils/html-to-pdf.js +61 -0
  51. package/.medusa/server/src/documents/utils/private-file-storage.js +64 -0
  52. package/.medusa/server/src/documents/utils/resolve-services.js +7 -0
  53. package/.medusa/server/src/email/application/handle-invite-event.js +318 -0
  54. package/.medusa/server/src/email/application/handle-password-reset-event.js +366 -0
  55. package/.medusa/server/src/email/config/index.js +84 -0
  56. package/.medusa/server/src/email/config/notification-module.js +20 -0
  57. package/.medusa/server/src/email/domain/business-keys.js +50 -0
  58. package/.medusa/server/src/email/domain/documents-fact-fingerprint.js +7 -0
  59. package/.medusa/server/src/email/domain/event-schemas.js +36 -0
  60. package/.medusa/server/src/email/domain/failure-classification.js +53 -0
  61. package/.medusa/server/src/email/domain/order-summary.js +103 -0
  62. package/.medusa/server/src/email/domain/refund-summary.js +43 -0
  63. package/.medusa/server/src/email/domain/return-summary.js +118 -0
  64. package/.medusa/server/src/email/domain/shipment-summary.js +74 -0
  65. package/.medusa/server/src/email/plugin-features.js +39 -0
  66. package/.medusa/server/src/email/rendering/default-templates.js +719 -0
  67. package/.medusa/server/src/email/rendering/load-email-shop-details.js +36 -0
  68. package/.medusa/server/src/email/rendering/render-email.js +50 -0
  69. package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +67 -0
  70. package/.medusa/server/src/email/types/email-kinds.js +18 -0
  71. package/.medusa/server/src/email/types/index.js +21 -0
  72. package/.medusa/server/src/email/types/shop-configuration.js +3 -0
  73. package/.medusa/server/src/email/types/smtp-configuration.js +3 -0
  74. package/.medusa/server/src/email/types/template-data.js +232 -0
  75. package/.medusa/server/src/files/config/index.js +256 -0
  76. package/.medusa/server/src/files/gateway/index.js +115 -0
  77. package/.medusa/server/src/files/types/index.js +6 -0
  78. package/.medusa/server/src/files/types/public.js +6 -0
  79. package/.medusa/server/src/jobs/document-fact-publication-reconciliation.js +18 -0
  80. package/.medusa/server/src/jobs/document-resolution-reconciliation.js +20 -0
  81. package/.medusa/server/src/jobs/packing-list-reconciliation.js +49 -0
  82. package/.medusa/server/src/jobs/reconcile-email-attempts.js +63 -0
  83. package/.medusa/server/src/jobs/reconcile-pending-email-messages.js +41 -0
  84. package/.medusa/server/src/jobs/retry-email-messages.js +27 -0
  85. package/.medusa/server/src/migration-scripts/dismiss-orphaned-cart-promotion-links.js +26 -0
  86. package/.medusa/server/src/modules/documents/domain/cancellation-snapshot.js +97 -0
  87. package/.medusa/server/src/modules/documents/domain/document-number.js +36 -0
  88. package/.medusa/server/src/modules/documents/domain/document-resolution.js +24 -0
  89. package/.medusa/server/src/modules/documents/domain/issuance-rules.js +37 -0
  90. package/.medusa/server/src/modules/documents/domain/merchant.js +86 -0
  91. package/.medusa/server/src/modules/documents/domain/options.js +40 -0
  92. package/.medusa/server/src/modules/documents/domain/packing-list.js +90 -0
  93. package/.medusa/server/src/modules/documents/domain/snapshot-normalization.js +17 -0
  94. package/.medusa/server/src/modules/documents/domain/tax-breakdown.js +66 -0
  95. package/.medusa/server/src/modules/documents/index.js +15 -0
  96. package/.medusa/server/src/modules/documents/loaders/assert-private-file-storage.js +20 -0
  97. package/.medusa/server/src/modules/documents/migrations/Migration20260827061749.js +75 -0
  98. package/.medusa/server/src/modules/documents/migrations/Migration20260830111207.js +28 -0
  99. package/.medusa/server/src/modules/documents/models/document-artifact.js +25 -0
  100. package/.medusa/server/src/modules/documents/models/document-number-sequence.js +29 -0
  101. package/.medusa/server/src/modules/documents/models/document.js +82 -0
  102. package/.medusa/server/src/modules/documents/models/order-cancellation-resolution.js +51 -0
  103. package/.medusa/server/src/modules/documents/models/packing-list-revision.js +36 -0
  104. package/.medusa/server/src/modules/documents/models/packing-list.js +27 -0
  105. package/.medusa/server/src/modules/documents/models/refund-document-resolution.js +66 -0
  106. package/.medusa/server/src/modules/documents/models/shipment-invoice-assignment.js +51 -0
  107. package/.medusa/server/src/modules/documents/models/shipment-invoice-coordinator.js +44 -0
  108. package/.medusa/server/src/modules/documents/service.js +1701 -0
  109. package/.medusa/server/src/modules/email/domain/attachment.js +25 -0
  110. package/.medusa/server/src/modules/email/domain/message-state.js +69 -0
  111. package/.medusa/server/src/modules/email/index.js +13 -0
  112. package/.medusa/server/src/modules/email/migrations/Migration20260826173422.js +32 -0
  113. package/.medusa/server/src/modules/email/migrations/Migration20260827172945.js +16 -0
  114. package/.medusa/server/src/modules/email/migrations/Migration20260827194804.js +22 -0
  115. package/.medusa/server/src/modules/email/migrations/Migration20260906195205.js +16 -0
  116. package/.medusa/server/src/modules/email/models/email-attempt.js +56 -0
  117. package/.medusa/server/src/modules/email/models/email-message.js +71 -0
  118. package/.medusa/server/src/modules/email/models/email-terms-version.js +37 -0
  119. package/.medusa/server/src/modules/email/service.js +1285 -0
  120. package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +4 -3
  121. package/.medusa/server/src/providers/s3-cache/cache/atomic-write.js +25 -0
  122. package/.medusa/server/src/providers/s3-cache/cache/cache-manager.js +115 -0
  123. package/.medusa/server/src/providers/s3-cache/cache/keyed-lock.js +28 -0
  124. package/.medusa/server/src/providers/s3-cache/index.js +8 -0
  125. package/.medusa/server/src/providers/s3-cache/object-key.js +53 -0
  126. package/.medusa/server/src/providers/s3-cache/s3-cache-file.js +229 -0
  127. package/.medusa/server/src/providers/s3-cache/s3-object-store.js +86 -0
  128. package/.medusa/server/src/providers/smtp/index.js +8 -0
  129. package/.medusa/server/src/providers/smtp/service.js +236 -0
  130. package/.medusa/server/src/providers/smtp/types.js +11 -0
  131. package/.medusa/server/src/public/config.js +186 -0
  132. package/.medusa/server/src/public/descriptor.js +3 -1
  133. package/.medusa/server/src/public/gateway.js +19 -0
  134. package/.medusa/server/src/public/instrumentation.js +56 -0
  135. package/.medusa/server/src/public/shop-config.js +12 -0
  136. package/.medusa/server/src/public/shop-master-data.js +2 -2
  137. package/.medusa/server/src/public/shop-types.js +24 -0
  138. package/.medusa/server/src/shop-config/build-food-shop-config.js +252 -0
  139. package/.medusa/server/src/shop-config/options.js +75 -0
  140. package/.medusa/server/src/subscribers/affiliate-consignment-reminder-due.js +26 -0
  141. package/.medusa/server/src/subscribers/documents-order-canceled.js +24 -0
  142. package/.medusa/server/src/subscribers/documents-order-cancellation-ready.js +26 -0
  143. package/.medusa/server/src/subscribers/documents-refund-ready.js +24 -0
  144. package/.medusa/server/src/subscribers/documents-shipment-created.js +36 -0
  145. package/.medusa/server/src/subscribers/documents-shipment-invoice-assignment-decided.js +26 -0
  146. package/.medusa/server/src/subscribers/email-order-canceled.js +28 -0
  147. package/.medusa/server/src/subscribers/email-shipment-created.js +32 -0
  148. package/.medusa/server/src/subscribers/order-placed.js +27 -0
  149. package/.medusa/server/src/subscribers/packing-list-allocation-revised.js +32 -0
  150. package/.medusa/server/src/subscribers/packing-list-fulfillment-canceled.js +54 -0
  151. package/.medusa/server/src/subscribers/packing-list-fulfillment-created.js +31 -0
  152. package/.medusa/server/src/subscribers/password-reset.js +23 -0
  153. package/.medusa/server/src/subscribers/payment-refunded.js +38 -0
  154. package/.medusa/server/src/subscribers/return-received.js +27 -0
  155. package/.medusa/server/src/subscribers/return-requested.js +27 -0
  156. package/.medusa/server/src/subscribers/user-invite.js +23 -0
  157. package/.medusa/server/src/utils/cart-promotion-links.js +101 -0
  158. package/.medusa/server/src/workflows/documents/issue-cancellation-after-refund.js +246 -0
  159. package/.medusa/server/src/workflows/documents/issue-document.js +165 -0
  160. package/.medusa/server/src/workflows/documents/issue-invoice-after-shipment.js +521 -0
  161. package/.medusa/server/src/workflows/documents/issue-packing-list.js +390 -0
  162. package/.medusa/server/src/workflows/documents/publish-document-facts.js +53 -0
  163. package/.medusa/server/src/workflows/documents/reconcile-document-resolutions.js +48 -0
  164. package/.medusa/server/src/workflows/documents/reconcile-order-cancellation.js +92 -0
  165. package/.medusa/server/src/workflows/documents/regenerate-issued-document.js +61 -0
  166. package/.medusa/server/src/workflows/email/dispatch-email-message.js +301 -0
  167. package/.medusa/server/src/workflows/email/documents-required-facts.js +30 -0
  168. package/.medusa/server/src/workflows/email/prepare-affiliate-reminder-email.js +58 -0
  169. package/.medusa/server/src/workflows/email/prepare-order-canceled-email.js +102 -0
  170. package/.medusa/server/src/workflows/email/prepare-order-received-email.js +82 -0
  171. package/.medusa/server/src/workflows/email/prepare-refund-email.js +71 -0
  172. package/.medusa/server/src/workflows/email/prepare-return-email.js +136 -0
  173. package/.medusa/server/src/workflows/email/prepare-shipment-email.js +115 -0
  174. package/.medusa/server/src/workflows/email/retry-email-messages.js +31 -0
  175. package/.medusa/server/src/workflows/hooks/dismiss-deleted-promotion-cart-links.js +23 -0
  176. package/README.md +1777 -8
  177. package/dist/admin-components/features/plugin-features/components/ImageSettingInput.d.ts +15 -0
  178. package/dist/admin-components/features/plugin-features/components/ImageSettingInput.js +42 -0
  179. package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.js +4 -2
  180. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +1 -1
  181. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +4 -4
  182. package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +1 -1
  183. package/dist/admin-components/features/plugin-features/lib/image-upload.d.ts +6 -0
  184. package/dist/admin-components/features/plugin-features/lib/image-upload.js +17 -0
  185. package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +4 -4
  186. package/dist/admin-components/i18n/texts.d.ts +6 -0
  187. package/dist/admin-components/i18n/texts.js +6 -0
  188. package/dist/documents/config/index.d.ts +11 -0
  189. package/dist/documents/config/index.js +17 -0
  190. package/dist/documents/templates/financial-document.d.ts +3 -0
  191. package/dist/documents/templates/financial-document.js +159 -0
  192. package/dist/documents/templates/format.d.ts +30 -0
  193. package/dist/documents/templates/format.js +72 -0
  194. package/dist/documents/templates/html-factory.d.ts +15 -0
  195. package/dist/documents/templates/html-factory.js +41 -0
  196. package/dist/documents/templates/html-utils.d.ts +8 -0
  197. package/dist/documents/templates/html-utils.js +22 -0
  198. package/dist/documents/templates/layout.d.ts +35 -0
  199. package/dist/documents/templates/layout.js +141 -0
  200. package/dist/documents/templates/packing-list.d.ts +3 -0
  201. package/dist/documents/templates/packing-list.js +51 -0
  202. package/dist/documents/types/admin-api.d.ts +1 -0
  203. package/dist/documents/types/admin-api.js +2 -0
  204. package/dist/documents/types/document-summary.d.ts +1 -0
  205. package/dist/documents/types/document-summary.js +2 -0
  206. package/dist/documents/types/documents.d.ts +191 -0
  207. package/dist/documents/types/documents.js +2 -0
  208. package/dist/documents/types/html-factory.d.ts +8 -0
  209. package/dist/documents/types/html-factory.js +5 -0
  210. package/dist/documents/types/index.d.ts +5 -0
  211. package/dist/documents/types/index.js +21 -0
  212. package/dist/documents/types/store-api.d.ts +1 -0
  213. package/dist/documents/types/store-api.js +2 -0
  214. package/dist/email/config/index.d.ts +17 -0
  215. package/dist/email/config/index.js +83 -0
  216. package/dist/email/config/notification-module.d.ts +22 -0
  217. package/dist/email/config/notification-module.js +19 -0
  218. package/dist/email/types/email-kinds.d.ts +15 -0
  219. package/dist/email/types/email-kinds.js +17 -0
  220. package/dist/email/types/index.d.ts +4 -0
  221. package/dist/email/types/index.js +20 -0
  222. package/dist/email/types/shop-configuration.d.ts +68 -0
  223. package/dist/email/types/shop-configuration.js +2 -0
  224. package/dist/email/types/smtp-configuration.d.ts +9 -0
  225. package/dist/email/types/smtp-configuration.js +2 -0
  226. package/dist/email/types/template-data.d.ts +609 -0
  227. package/dist/email/types/template-data.js +231 -0
  228. package/dist/files/config/index.d.ts +32 -0
  229. package/dist/files/config/index.js +255 -0
  230. package/dist/files/gateway/index.d.ts +30 -0
  231. package/dist/files/gateway/index.js +114 -0
  232. package/dist/files/types/index.d.ts +2 -0
  233. package/dist/files/types/index.js +5 -0
  234. package/dist/files/types/public.d.ts +90 -0
  235. package/dist/files/types/public.js +5 -0
  236. package/dist/modules/documents/domain/merchant.d.ts +22 -0
  237. package/dist/modules/documents/domain/merchant.js +85 -0
  238. package/dist/modules/documents/domain/options.d.ts +34 -0
  239. package/dist/modules/documents/domain/options.js +39 -0
  240. package/dist/public/config.d.ts +59 -0
  241. package/dist/public/config.js +185 -0
  242. package/dist/public/descriptor.js +2 -0
  243. package/dist/public/gateway.d.ts +2 -0
  244. package/dist/public/gateway.js +18 -0
  245. package/dist/public/instrumentation.d.ts +12 -0
  246. package/dist/public/instrumentation.js +55 -0
  247. package/dist/public/shop-config.d.ts +8 -0
  248. package/dist/public/shop-config.js +11 -0
  249. package/dist/public/shop-master-data.d.ts +1 -1
  250. package/dist/public/shop-master-data.js +1 -1
  251. package/dist/public/shop-types.d.ts +7 -0
  252. package/dist/public/shop-types.js +23 -0
  253. package/dist/public/types.d.ts +19 -2
  254. package/dist/shop-config/build-food-shop-config.d.ts +44 -0
  255. package/dist/shop-config/build-food-shop-config.js +251 -0
  256. package/dist/shop-config/options.d.ts +48 -0
  257. package/dist/shop-config/options.js +74 -0
  258. package/package.json +48 -5
@@ -0,0 +1,35 @@
1
+ import type { DocumentRenderSettings, DocumentMerchant } from "../types";
2
+ /**
3
+ * Shop-specific look on top of the default markup. A project passes it to
4
+ * `createDefaultDocumentHtmlFactory` from its own `htmlFactory`, so it keeps
5
+ * the plugin's content and changes only the appearance.
6
+ */
7
+ export type DocumentTheme = {
8
+ /**
9
+ * CSS appended after the default stylesheet; later rules win. A
10
+ * full-page image such as a watermark belongs in `@page { background }`:
11
+ * it covers the whole sheet on every page, while Chromium clips fixed
12
+ * elements at the page margin and sizes an inline `<svg>` in them wrongly
13
+ * from the second page on.
14
+ */
15
+ readonly stylesheet?: string;
16
+ };
17
+ export type DocumentLayoutInput = {
18
+ readonly body: string;
19
+ readonly documentTitle: string;
20
+ readonly metadata: readonly {
21
+ readonly label: string;
22
+ readonly value: string;
23
+ }[];
24
+ readonly number: string;
25
+ readonly pageTitle: string;
26
+ /** Escaped recipient address markup; `null` leaves the block empty. */
27
+ readonly recipient: string | null;
28
+ };
29
+ export type DocumentLayout = (input: DocumentLayoutInput) => string;
30
+ export declare const formatCountryName: (countryCode: string) => string;
31
+ /**
32
+ * `includeLegalDetails` adds UID, company register, contact and bank details
33
+ * to the footer (financial documents); packing lists show only the sender.
34
+ */
35
+ export declare const createDocumentLayout: (merchant: DocumentMerchant, settings: DocumentRenderSettings, includeLegalDetails: boolean, theme?: DocumentTheme) => DocumentLayout;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDocumentLayout = exports.formatCountryName = void 0;
4
+ const html_utils_1 = require("./html-utils");
5
+ const formatCountryName = (countryCode) => new Intl.DisplayNames("de", { type: "region" }).of(countryCode.toUpperCase()) ?? countryCode.toUpperCase();
6
+ exports.formatCountryName = formatCountryName;
7
+ const joinLines = (lines) => lines
8
+ .filter((line) => Boolean(line))
9
+ .map(html_utils_1.escapeHtml)
10
+ .join("<br />");
11
+ const renderFooterColumn = (heading, lines) => {
12
+ const content = joinLines(lines);
13
+ if (!content) {
14
+ return "";
15
+ }
16
+ const title = heading
17
+ ? `<div class="footer-heading">${(0, html_utils_1.escapeHtml)(heading)}</div>`
18
+ : "";
19
+ return `<div class="footer-column">${title}${content}</div>`;
20
+ };
21
+ /**
22
+ * Legal footer in three columns: sender with UID and company register,
23
+ * contact, bank. Packing lists (`includeLegalDetails: false`) show only the
24
+ * sender's name and address.
25
+ */
26
+ const renderMerchantFooter = (merchant, includeLegalDetails) => {
27
+ const sender = `<div class="footer-column"><strong>${(0, html_utils_1.escapeHtml)(merchant.legal_name)}</strong><br />${joinLines([
28
+ merchant.address_line1,
29
+ merchant.address_line2,
30
+ `${merchant.postal_code} ${merchant.city}`,
31
+ (0, exports.formatCountryName)(merchant.country_code),
32
+ ...(includeLegalDetails
33
+ ? [
34
+ merchant.vat_number ? `UID: ${merchant.vat_number}` : null,
35
+ merchant.company_register_number
36
+ ? `Firmenbuchnummer: ${merchant.company_register_number}`
37
+ : null,
38
+ merchant.company_register_court
39
+ ? `Firmenbuchgericht: ${merchant.company_register_court}`
40
+ : null,
41
+ ]
42
+ : []),
43
+ ])}</div>`;
44
+ if (!includeLegalDetails) {
45
+ return sender;
46
+ }
47
+ return [
48
+ sender,
49
+ renderFooterColumn("Kontakt", [
50
+ merchant.phone,
51
+ merchant.email,
52
+ merchant.website,
53
+ ]),
54
+ // The heading names the IBAN; only the BIC keeps its label.
55
+ renderFooterColumn("Bankverbindung", [
56
+ merchant.iban,
57
+ merchant.bic ? `BIC: ${merchant.bic}` : null,
58
+ ]),
59
+ ].join("");
60
+ };
61
+ const renderLetterhead = (merchant, settings) => settings.logo_src
62
+ ? `<img class="logo" src="${(0, html_utils_1.escapeHtml)(settings.logo_src)}" alt="${(0, html_utils_1.escapeHtml)(merchant.legal_name)}" />`
63
+ : `<div class="logo-text">${(0, html_utils_1.escapeHtml)(merchant.legal_name)}</div>`;
64
+ const renderMetadata = (metadata) => metadata
65
+ .map(({ label, value }) => `<tr><th scope="row">${(0, html_utils_1.escapeHtml)(label)}</th><td>${(0, html_utils_1.escapeHtml)(value)}</td></tr>`)
66
+ .join("");
67
+ /**
68
+ * A4 with only a bottom page margin, which holds the page number
69
+ * (`@bottom-right`; `counter(pages)` works only in page margin boxes). `.page`
70
+ * carries the other margins and repeats them on every printed page
71
+ * (`box-decoration-break: clone`); the fixed footer is positioned in the page
72
+ * area, `--footer-height` reserves its space at the bottom of each page.
73
+ */
74
+ const DEFAULT_STYLESHEET = `
75
+ @page { size: A4; margin: 0 0 8mm 0; @bottom-right { color: #6b7280; content: "Seite " counter(page) " von " counter(pages); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 7.5pt; padding-right: 20mm; vertical-align: top; } }
76
+ :root { --accent: #111827; --text: #1f2937; --muted: #6b7280; --line: #d1d5db; --table-head: #f3f4f6; --page-x: 20mm; --page-top: 18mm; --footer-height: 30mm; }
77
+ * { box-sizing: border-box; }
78
+ html, body { margin: 0; padding: 0; }
79
+ body { color: var(--text); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 10pt; line-height: 1.4; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
80
+ .page { -webkit-box-decoration-break: clone; box-decoration-break: clone; padding: var(--page-top) var(--page-x) calc(var(--footer-height) + 8mm); }
81
+ .letterhead { margin-bottom: 14mm; min-height: 16mm; }
82
+ .logo { display: block; height: 22mm; max-width: 90mm; object-fit: contain; object-position: left center; width: auto; }
83
+ .logo-text { color: var(--accent); font-size: 20pt; font-weight: 700; letter-spacing: 0.02em; }
84
+ .document-head { break-inside: avoid; display: flex; gap: 12mm; justify-content: space-between; margin-bottom: 14mm; page-break-inside: avoid; }
85
+ .recipient { flex: 1 1 0; font-style: normal; padding-top: 9mm; }
86
+ .document-info { flex: 0 0 78mm; }
87
+ h1 { color: var(--accent); font-size: 16pt; font-weight: 400; letter-spacing: 0.08em; margin: 0 0 3mm; text-transform: uppercase; }
88
+ h2 { break-after: avoid; font-size: 10pt; margin: 8mm 0 2mm; page-break-after: avoid; }
89
+ .document-metadata { border-collapse: collapse; width: 100%; }
90
+ .document-metadata th, .document-metadata td { border: 0; font-weight: 400; padding: 0; text-align: left; vertical-align: top; }
91
+ .document-metadata td { text-align: right; }
92
+ .muted, .sku, .batch { color: var(--muted); }
93
+ .batch, .packing-batch { font-size: 8pt; margin-top: 1mm; }
94
+ .packing-batch { display: flex; gap: 12px; justify-content: space-between; }
95
+ table { border-collapse: collapse; page-break-inside: auto; width: 100%; }
96
+ thead { display: table-header-group; }
97
+ tfoot { display: table-footer-group; }
98
+ tbody { page-break-inside: auto; }
99
+ tr { break-inside: avoid; page-break-inside: avoid; }
100
+ .items th { background: var(--table-head); font-weight: 700; text-align: left; }
101
+ .items th.number { text-align: right; }
102
+ .items th, .items td { padding: 2.5mm 2mm; vertical-align: top; }
103
+ .items tbody.lines td { border-bottom: 1px solid var(--line); }
104
+ .number { text-align: right; white-space: nowrap; }
105
+ .money { white-space: nowrap; }
106
+ .items tbody.totals td { padding-bottom: 1.5mm; padding-top: 1.5mm; }
107
+ .items tbody.totals tr:first-child td { padding-top: 3mm; }
108
+ .items tbody.totals tr.grand-total td.label, .items tbody.totals tr.grand-total td.number { border-bottom: 1px solid var(--line); border-top: 1px solid var(--line); font-weight: 700; padding-bottom: 2mm; padding-top: 2mm; }
109
+ .payment-terms { margin-top: 10mm; white-space: pre-line; }
110
+ .recipient, .tax-compliance, .payment-terms, .items tbody.totals { break-inside: avoid; page-break-inside: avoid; }
111
+ .page-footer { align-items: flex-start; bottom: 4mm; color: var(--text); display: flex; font-size: 8pt; gap: 8mm; left: var(--page-x); line-height: 1.35; position: fixed; right: var(--page-x); }
112
+ .footer-column { flex: 1 1 0; }
113
+ .footer-heading { color: var(--muted); }
114
+ `;
115
+ /**
116
+ * `includeLegalDetails` adds UID, company register, contact and bank details
117
+ * to the footer (financial documents); packing lists show only the sender.
118
+ */
119
+ const createDocumentLayout = (merchant, settings, includeLegalDetails, theme = {}) => ({ body, documentTitle, metadata, number, pageTitle, recipient }) => `<!doctype html>
120
+ <html lang="de">
121
+ <head>
122
+ <meta charset="utf-8" />
123
+ <title>${(0, html_utils_1.escapeHtml)(pageTitle)} ${(0, html_utils_1.escapeHtml)(number)}</title>
124
+ <style>${DEFAULT_STYLESHEET}${theme.stylesheet ?? ""}</style>
125
+ </head>
126
+ <body>
127
+ <footer class="page-footer">${renderMerchantFooter(merchant, includeLegalDetails)}</footer>
128
+ <main class="page">
129
+ <header class="letterhead">${renderLetterhead(merchant, settings)}</header>
130
+ <section class="document-head">
131
+ <address class="recipient">${recipient ?? ""}</address>
132
+ <div class="document-info">
133
+ <h1>${(0, html_utils_1.escapeHtml)(documentTitle)}</h1>
134
+ <table class="document-metadata"><tbody>${renderMetadata(metadata)}</tbody></table>
135
+ </div>
136
+ </section>
137
+ ${body}
138
+ </main>
139
+ </body>
140
+ </html>`;
141
+ exports.createDocumentLayout = createDocumentLayout;
@@ -0,0 +1,3 @@
1
+ import type { PackingListTemplateInput } from "../types";
2
+ import type { DocumentLayout } from "./layout";
3
+ export declare const renderPackingList: (input: PackingListTemplateInput, layout: DocumentLayout, timeZone: string) => string;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderPackingList = void 0;
4
+ const format_1 = require("./format");
5
+ const html_utils_1 = require("./html-utils");
6
+ const renderBatchAllocations = (line, timeZone) => {
7
+ if (line.batch_allocations.length === 0) {
8
+ return '<span class="muted">-</span>';
9
+ }
10
+ return line.batch_allocations
11
+ .map((allocation) => `<div class="packing-batch">
12
+ <strong>${(0, html_utils_1.escapeHtml)(allocation.lot_number)}</strong>
13
+ <span>MHD: ${(0, html_utils_1.escapeHtml)((0, format_1.formatDocumentDate)(allocation.expiry_date, timeZone))}</span>
14
+ <span>Menge: ${(0, html_utils_1.escapeHtml)(allocation.quantity)}</span>
15
+ </div>`)
16
+ .join("");
17
+ };
18
+ const renderLines = (input, timeZone) => input.lines
19
+ .map((line) => `<tr>
20
+ <td class="item">
21
+ <div class="item-title">${(0, html_utils_1.escapeHtml)(line.title)}</div>
22
+ ${line.sku ? `<div class="sku">SKU: ${(0, html_utils_1.escapeHtml)(line.sku)}</div>` : ""}
23
+ </td>
24
+ <td>${renderBatchAllocations(line, timeZone)}</td>
25
+ <td class="number">${(0, html_utils_1.escapeHtml)(line.quantity)}</td>
26
+ </tr>`)
27
+ .join("");
28
+ const renderPackingList = (input, layout, timeZone) => layout({
29
+ body: `<table class="items packing-items">
30
+ <thead><tr><th class="item">Bezeichnung</th><th>Charge</th><th class="number">Benötigte Menge</th></tr></thead>
31
+ <tbody class="lines">${renderLines(input, timeZone)}</tbody>
32
+ </table>`,
33
+ documentTitle: "Packliste",
34
+ metadata: [
35
+ { label: "Packlistennummer", value: input.document.number },
36
+ {
37
+ label: "Bestellung",
38
+ value: (0, html_utils_1.formatOrderReference)(input.order.display_id),
39
+ },
40
+ { label: "Fulfillment", value: input.fulfillment.id },
41
+ {
42
+ label: "Erstellungsdatum",
43
+ value: (0, format_1.formatDocumentDate)(input.document.generated_at, timeZone),
44
+ },
45
+ { label: "Lagerplatz", value: input.fulfillment.location_name },
46
+ ],
47
+ number: input.document.number,
48
+ pageTitle: "Packliste",
49
+ recipient: null,
50
+ });
51
+ exports.renderPackingList = renderPackingList;
@@ -0,0 +1 @@
1
+ export type * from "@hartl-services/medusa-food-supplements-contracts/types/documents-admin";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type { StoreDocument as DocumentSummary } from "@hartl-services/medusa-food-supplements-contracts/types/documents-store";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,191 @@
1
+ export type DocumentKind = "invoice" | "cancellation" | "credit_note";
2
+ export type DocumentStatus = "processing" | "issued" | "failed";
3
+ export type ShipmentInvoiceDecision = "pending" | "carrier" | "non_carrier";
4
+ export type RefundResolutionState = "pending_source" | "processing" | "ready" | "not_applicable" | "failed";
5
+ export type RefundCommunicationOwner = "standalone" | "cancellation";
6
+ export type OrderCancellationResolutionState = "pending" | "processing" | "ready" | "failed";
7
+ export type DocumentMoney = {
8
+ amount: string;
9
+ currency_code: string;
10
+ };
11
+ export type DocumentAddress = {
12
+ first_name: string | null;
13
+ last_name: string | null;
14
+ company: string | null;
15
+ address_1: string | null;
16
+ address_2: string | null;
17
+ postal_code: string | null;
18
+ city: string | null;
19
+ country_code: string | null;
20
+ };
21
+ export type DocumentBatchAllocationDTO = {
22
+ batch_id: string;
23
+ lot_number: string;
24
+ expiry_date: string;
25
+ quantity: number;
26
+ };
27
+ export type DocumentTaxComplianceDTO = {
28
+ customer_company_name: string;
29
+ customer_vat_number: string;
30
+ exemption_wording: "steuerfreie_innergemeinschaftliche_lieferung";
31
+ };
32
+ /**
33
+ * Tax amount of one configured tax rate (name and percentage as calculated on
34
+ * the order's tax lines). Amounts are rounded to the currency's minor unit and
35
+ * sum up exactly to the rounded document tax total.
36
+ */
37
+ export type DocumentTaxBreakdownEntry = {
38
+ name: string;
39
+ code: string | null;
40
+ rate: number;
41
+ tax_total: DocumentMoney;
42
+ };
43
+ export type DocumentTemplateLine = {
44
+ id: string;
45
+ title: string;
46
+ sku: string | null;
47
+ quantity: number;
48
+ unit_price: DocumentMoney;
49
+ subtotal: DocumentMoney;
50
+ tax_total: DocumentMoney;
51
+ total: DocumentMoney;
52
+ batch_allocations: DocumentBatchAllocationDTO[];
53
+ };
54
+ /**
55
+ * Stable input contract for the project-owned HTML factory. It is a value
56
+ * snapshot, never a live Medusa order model, so rendering stays isolated from
57
+ * Medusa internals and the Storefront can import the types safely.
58
+ */
59
+ export type DocumentTemplateInput = {
60
+ document: {
61
+ id: string;
62
+ kind: DocumentKind;
63
+ number: string;
64
+ issued_at: string;
65
+ source_document_number: string | null;
66
+ };
67
+ order: {
68
+ id: string;
69
+ display_id: number | null;
70
+ email: string;
71
+ currency_code: string;
72
+ billing_address: DocumentAddress | null;
73
+ tax_compliance: DocumentTaxComplianceDTO | null;
74
+ };
75
+ lines: DocumentTemplateLine[];
76
+ totals: {
77
+ subtotal: DocumentMoney;
78
+ tax_total: DocumentMoney;
79
+ /** Empty for documents without tax lines and for legacy snapshots. */
80
+ tax_breakdown: DocumentTaxBreakdownEntry[];
81
+ shipping_total: DocumentMoney;
82
+ discount_total: DocumentMoney;
83
+ total: DocumentMoney;
84
+ };
85
+ };
86
+ export type DocumentSnapshot = DocumentTemplateInput;
87
+ export type PackingListLifecycleStatus = "active" | "canceled";
88
+ export type PackingListGenerationStatus = "processing" | "ready" | "failed";
89
+ export type PackingListBatchAllocation = {
90
+ batch_id: string;
91
+ lot_number: string;
92
+ expiry_date: string;
93
+ quantity: number;
94
+ };
95
+ export type PackingListTemplateLine = {
96
+ line_item_id: string;
97
+ inventory_item_id: string | null;
98
+ title: string;
99
+ sku: string | null;
100
+ quantity: number;
101
+ batch_allocations: PackingListBatchAllocation[];
102
+ };
103
+ export type PackingListTemplateInput = {
104
+ document: {
105
+ kind: "packing_list";
106
+ id: string;
107
+ number: string;
108
+ source_revision: number;
109
+ generated_at: string;
110
+ };
111
+ order: {
112
+ id: string;
113
+ display_id: number | null;
114
+ };
115
+ fulfillment: {
116
+ id: string;
117
+ created_at: string;
118
+ location_id: string;
119
+ location_name: string;
120
+ };
121
+ lines: PackingListTemplateLine[];
122
+ };
123
+ export type PackingListSnapshot = PackingListTemplateInput;
124
+ /**
125
+ * The shop's legal sender facts, read from the base plugin's shop master
126
+ * data ("Shop-Stammdaten") when a document is rendered. Not part of the
127
+ * stored snapshot. Optional fields are `null` when not set; the development
128
+ * UID placeholder `ATU00000000` arrives as `vat_number: null`.
129
+ */
130
+ export type DocumentMerchant = {
131
+ legal_name: string;
132
+ address_line1: string;
133
+ address_line2: string | null;
134
+ postal_code: string;
135
+ city: string;
136
+ /** Lower-case ISO 3166-1 alpha-2 code. */
137
+ country_code: string;
138
+ vat_number: string | null;
139
+ email: string | null;
140
+ phone: string | null;
141
+ website: string | null;
142
+ iban: string | null;
143
+ bic: string | null;
144
+ company_register_number: string | null;
145
+ company_register_court: string | null;
146
+ };
147
+ /**
148
+ * Optional `merchant` plugin option: used per field only where the shop
149
+ * master data in the base plugin has no value (same shape as the demo shop's
150
+ * `merchant` constant in medusa-config).
151
+ */
152
+ export type DocumentMerchantOption = {
153
+ countryCode: string;
154
+ legalName: string;
155
+ registeredAddress: {
156
+ address1: string;
157
+ address2?: string;
158
+ city: string;
159
+ countryCode: string;
160
+ postalCode: string;
161
+ };
162
+ vatNumber?: string;
163
+ };
164
+ /**
165
+ * The Documents settings (Admin -> "Hartl Services Plugins" -> Dokumente) a
166
+ * render needs, read when a document is rendered. Not part of the stored
167
+ * snapshot: a regenerated document shows the current values.
168
+ */
169
+ export type DocumentRenderSettings = {
170
+ /**
171
+ * The uploaded logo as a `data:` URL, ready for `<img src>`; `null` when no
172
+ * logo is set or it could not be loaded (the document then shows the
173
+ * merchant's legal name instead).
174
+ */
175
+ logo_src: string | null;
176
+ /** Payment terms printed below the totals of an invoice; `null` = none. */
177
+ payment_terms: string | null;
178
+ };
179
+ export type FinancialDocumentRenderInput = DocumentTemplateInput & {
180
+ merchant: DocumentMerchant;
181
+ settings: DocumentRenderSettings;
182
+ };
183
+ export type PackingListRenderInput = PackingListTemplateInput & {
184
+ merchant: DocumentMerchant;
185
+ settings: DocumentRenderSettings;
186
+ };
187
+ export type DocumentRenderInput = FinancialDocumentRenderInput | PackingListRenderInput;
188
+ export type DocumentPdfOptions = {
189
+ /** Absolute executable path or command name for the bundled Chromium renderer. */
190
+ executablePath?: string;
191
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import type { DocumentRenderInput } from "./documents";
2
+ /**
3
+ * The only project-specific document extension point. PDF rendering and file
4
+ * storage stay inside the plugin; projects control semantic markup and CSS.
5
+ */
6
+ export type DocumentHtmlFactory = (input: DocumentRenderInput) => string | Promise<string>;
7
+ export declare const defineDocumentHtmlFactory: (factory: DocumentHtmlFactory) => DocumentHtmlFactory;
8
+ export type { DocumentTheme } from "../templates/layout";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defineDocumentHtmlFactory = void 0;
4
+ const defineDocumentHtmlFactory = (factory) => factory;
5
+ exports.defineDocumentHtmlFactory = defineDocumentHtmlFactory;
@@ -0,0 +1,5 @@
1
+ export * from "./admin-api";
2
+ export * from "./documents";
3
+ export * from "./document-summary";
4
+ export * from "./html-factory";
5
+ export * from "./store-api";
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./admin-api"), exports);
18
+ __exportStar(require("./documents"), exports);
19
+ __exportStar(require("./document-summary"), exports);
20
+ __exportStar(require("./html-factory"), exports);
21
+ __exportStar(require("./store-api"), exports);
@@ -0,0 +1 @@
1
+ export type * from "@hartl-services/medusa-food-supplements-contracts/types/documents-store";
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import type { ResolvedSmtpConfiguration, ShopEmailConfiguration } from "../types";
2
+ export { createSmtpNotificationModuleConfig } from "./notification-module";
3
+ export declare const defineShopEmailConfiguration: <Configuration extends ShopEmailConfiguration>(configuration: Configuration) => Configuration;
4
+ export type { ResolvedSmtpConfiguration, ShopEmailConfiguration, } from "../types";
5
+ export declare const SMTP_ENVIRONMENT_VARIABLES: readonly ["SMTP_HOST", "SMTP_PORT", "SMTP_SECURE", "SMTP_USER", "SMTP_PASSWORD", "SMTP_FROM", "SMTP_REQUIRE_TLS"];
6
+ /**
7
+ * `medusa build` loads the configuration without deployment secrets. These
8
+ * placeholders only satisfy the required-variable checks of a build; they
9
+ * never reach a running server.
10
+ */
11
+ export declare const SMTP_BUILD_PLACEHOLDERS: Readonly<Record<string, string>>;
12
+ /**
13
+ * Validates the SMTP environment values and returns the transport
14
+ * configuration. `allowInsecure` permits plain SMTP for development, tests
15
+ * and builds; otherwise `SMTP_SECURE` or `SMTP_REQUIRE_TLS` must be `true`.
16
+ */
17
+ export declare const resolveSmtp: (values: Readonly<Record<(typeof SMTP_ENVIRONMENT_VARIABLES)[number], string>>, allowInsecure: boolean) => ResolvedSmtpConfiguration;
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSmtp = exports.SMTP_BUILD_PLACEHOLDERS = exports.SMTP_ENVIRONMENT_VARIABLES = exports.defineShopEmailConfiguration = exports.createSmtpNotificationModuleConfig = void 0;
4
+ var notification_module_1 = require("./notification-module");
5
+ Object.defineProperty(exports, "createSmtpNotificationModuleConfig", { enumerable: true, get: function () { return notification_module_1.createSmtpNotificationModuleConfig; } });
6
+ const defineShopEmailConfiguration = (configuration) => configuration;
7
+ exports.defineShopEmailConfiguration = defineShopEmailConfiguration;
8
+ exports.SMTP_ENVIRONMENT_VARIABLES = [
9
+ "SMTP_HOST",
10
+ "SMTP_PORT",
11
+ "SMTP_SECURE",
12
+ "SMTP_USER",
13
+ "SMTP_PASSWORD",
14
+ "SMTP_FROM",
15
+ "SMTP_REQUIRE_TLS",
16
+ ];
17
+ /**
18
+ * `medusa build` loads the configuration without deployment secrets. These
19
+ * placeholders only satisfy the required-variable checks of a build; they
20
+ * never reach a running server.
21
+ */
22
+ exports.SMTP_BUILD_PLACEHOLDERS = {
23
+ SMTP_FROM: "no-reply@smtp.build.invalid",
24
+ SMTP_HOST: "smtp.build.invalid",
25
+ SMTP_PASSWORD: "build-password",
26
+ SMTP_PORT: "2525",
27
+ SMTP_REQUIRE_TLS: "false",
28
+ SMTP_SECURE: "false",
29
+ SMTP_USER: "build-user",
30
+ };
31
+ const optionalValue = (values, name) => {
32
+ const value = values[name]?.trim();
33
+ return value ? value : undefined;
34
+ };
35
+ const integerValue = (values, name, minimum, maximum) => {
36
+ const value = optionalValue(values, name);
37
+ if (value === undefined) {
38
+ return undefined;
39
+ }
40
+ const parsed = Number(value);
41
+ if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) {
42
+ throw new TypeError(`${name} must be an integer from ${minimum} through ${maximum}.`);
43
+ }
44
+ return parsed;
45
+ };
46
+ const booleanValue = (values, name, defaultValue) => {
47
+ const value = optionalValue(values, name);
48
+ if (value === undefined) {
49
+ return defaultValue;
50
+ }
51
+ if (value !== "true" && value !== "false") {
52
+ throw new TypeError(`${name} must be either "true" or "false".`);
53
+ }
54
+ return value === "true";
55
+ };
56
+ /**
57
+ * Validates the SMTP environment values and returns the transport
58
+ * configuration. `allowInsecure` permits plain SMTP for development, tests
59
+ * and builds; otherwise `SMTP_SECURE` or `SMTP_REQUIRE_TLS` must be `true`.
60
+ */
61
+ const resolveSmtp = (values, allowInsecure) => {
62
+ const port = integerValue(values, "SMTP_PORT", 1, 65535);
63
+ if (port === undefined) {
64
+ throw new TypeError("SMTP_PORT is required.");
65
+ }
66
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.SMTP_FROM)) {
67
+ throw new TypeError("SMTP_FROM must be a valid email address.");
68
+ }
69
+ const smtp = {
70
+ from: values.SMTP_FROM,
71
+ host: values.SMTP_HOST,
72
+ password: values.SMTP_PASSWORD,
73
+ port,
74
+ requireTls: booleanValue(values, "SMTP_REQUIRE_TLS", false),
75
+ secure: booleanValue(values, "SMTP_SECURE", false),
76
+ user: values.SMTP_USER,
77
+ };
78
+ if (!smtp.secure && !smtp.requireTls && !allowInsecure) {
79
+ throw new TypeError("SMTP must use SMTP_SECURE=true or SMTP_REQUIRE_TLS=true outside development and test.");
80
+ }
81
+ return smtp;
82
+ };
83
+ exports.resolveSmtp = resolveSmtp;
@@ -0,0 +1,22 @@
1
+ import type { ResolvedSmtpConfiguration } from "../types";
2
+ export declare const createSmtpNotificationModuleConfig: (smtp: ResolvedSmtpConfiguration) => {
3
+ resolve: string;
4
+ options: {
5
+ providers: {
6
+ id: string;
7
+ options: {
8
+ channels: string[];
9
+ smtp: Readonly<{
10
+ from: string;
11
+ host: string;
12
+ password: string;
13
+ port: number;
14
+ requireTls: boolean;
15
+ secure: boolean;
16
+ user: string;
17
+ }>;
18
+ };
19
+ resolve: string;
20
+ }[];
21
+ };
22
+ };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createSmtpNotificationModuleConfig = void 0;
4
+ const createSmtpNotificationModuleConfig = (smtp) => ({
5
+ resolve: "@medusajs/medusa/notification",
6
+ options: {
7
+ providers: [
8
+ {
9
+ id: "smtp",
10
+ options: {
11
+ channels: ["email"],
12
+ smtp,
13
+ },
14
+ resolve: "@hartl-services/medusa-base/providers/smtp",
15
+ },
16
+ ],
17
+ },
18
+ });
19
+ exports.createSmtpNotificationModuleConfig = createSmtpNotificationModuleConfig;
@@ -0,0 +1,15 @@
1
+ import { z } from "@medusajs/framework/zod";
2
+ export declare const EMAIL_KINDS: readonly ["order.received", "order.received.admin", "order.shipped", "order.canceled", "order.return_requested", "order.return_received", "order.refunded", "auth.password_reset", "affiliate.consignment_report_due", "user.invite"];
3
+ export declare const EmailKindSchema: z.ZodEnum<{
4
+ "order.received": "order.received";
5
+ "order.received.admin": "order.received.admin";
6
+ "order.shipped": "order.shipped";
7
+ "order.canceled": "order.canceled";
8
+ "order.return_requested": "order.return_requested";
9
+ "order.return_received": "order.return_received";
10
+ "order.refunded": "order.refunded";
11
+ "auth.password_reset": "auth.password_reset";
12
+ "affiliate.consignment_report_due": "affiliate.consignment_report_due";
13
+ "user.invite": "user.invite";
14
+ }>;
15
+ export type EmailKind = (typeof EMAIL_KINDS)[number];