@hartl-services/medusa-affiliate 0.3.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 (169) hide show
  1. package/.medusa/server/src/admin/index.js +3739 -0
  2. package/.medusa/server/src/admin/index.mjs +3738 -0
  3. package/.medusa/server/src/api/admin/affiliate-applications/[id]/approve/route.js +28 -0
  4. package/.medusa/server/src/api/admin/affiliate-applications/[id]/reject/route.js +19 -0
  5. package/.medusa/server/src/api/admin/affiliate-applications/route.js +23 -0
  6. package/.medusa/server/src/api/admin/affiliate-distribution-reports/query.js +171 -0
  7. package/.medusa/server/src/api/admin/affiliate-distribution-reports/route.js +13 -0
  8. package/.medusa/server/src/api/admin/affiliate-program-settings/route.js +27 -0
  9. package/.medusa/server/src/api/admin/affiliate-reports/[id]/route.js +45 -0
  10. package/.medusa/server/src/api/admin/affiliate-reports/route.js +27 -0
  11. package/.medusa/server/src/api/admin/affiliates/[id]/consignment-reminders/route.js +31 -0
  12. package/.medusa/server/src/api/admin/affiliates/[id]/consignment-transfers/route.js +41 -0
  13. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/reconcile/route.js +34 -0
  14. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/revoke/route.js +36 -0
  15. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/[coupon_id]/rotate/route.js +40 -0
  16. package/.medusa/server/src/api/admin/affiliates/[id]/coupon-codes/route.js +56 -0
  17. package/.medusa/server/src/api/admin/affiliates/[id]/distribution/route.js +45 -0
  18. package/.medusa/server/src/api/admin/affiliates/[id]/inactive/route.js +20 -0
  19. package/.medusa/server/src/api/admin/affiliates/[id]/route.js +50 -0
  20. package/.medusa/server/src/api/admin/affiliates/[id]/slugs/[slug_id]/route.js +19 -0
  21. package/.medusa/server/src/api/admin/affiliates/[id]/slugs/route.js +26 -0
  22. package/.medusa/server/src/api/admin/affiliates/route.js +43 -0
  23. package/.medusa/server/src/api/admin/consignment-report-response.js +36 -0
  24. package/.medusa/server/src/api/admin/consignment-reports/[id]/approve/route.js +25 -0
  25. package/.medusa/server/src/api/admin/consignment-reports/[id]/correct/route.js +18 -0
  26. package/.medusa/server/src/api/admin/consignment-reports/[id]/reject/route.js +15 -0
  27. package/.medusa/server/src/api/admin/consignment-reports/[id]/route.js +11 -0
  28. package/.medusa/server/src/api/admin/consignment-reports/route.js +27 -0
  29. package/.medusa/server/src/api/admin/customers/[id]/affiliate/route.js +50 -0
  30. package/.medusa/server/src/api/admin/orders/[id]/affiliate-attribution/route.js +30 -0
  31. package/.medusa/server/src/api/affiliate-coupon-http.js +152 -0
  32. package/.medusa/server/src/api/affiliate-referral-cookie.js +34 -0
  33. package/.medusa/server/src/api/affiliate-self-service-http.js +37 -0
  34. package/.medusa/server/src/api/middlewares.js +786 -0
  35. package/.medusa/server/src/api/store/affiliate-referrals/apply-coupon/route.js +47 -0
  36. package/.medusa/server/src/api/store/affiliate-referrals/capture/route.js +76 -0
  37. package/.medusa/server/src/api/store/affiliate-referrals/carts/[cart_id]/route.js +20 -0
  38. package/.medusa/server/src/api/store/affiliates/consignment-inventory/route.js +53 -0
  39. package/.medusa/server/src/api/store/affiliates/consignment-report-response.js +31 -0
  40. package/.medusa/server/src/api/store/affiliates/consignment-reports/[id]/submit/route.js +40 -0
  41. package/.medusa/server/src/api/store/affiliates/consignment-reports/route.js +43 -0
  42. package/.medusa/server/src/api/store/affiliates/coupon-labels/route.js +14 -0
  43. package/.medusa/server/src/api/store/affiliates/me/commissions/route.js +35 -0
  44. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/revoke/route.js +36 -0
  45. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/[coupon_id]/rotate/route.js +40 -0
  46. package/.medusa/server/src/api/store/affiliates/me/coupon-codes/route.js +55 -0
  47. package/.medusa/server/src/api/store/affiliates/me/dashboard/route.js +15 -0
  48. package/.medusa/server/src/api/store/affiliates/me/route.js +85 -0
  49. package/.medusa/server/src/api/store/affiliates/me/slugs/[slug_id]/route.js +29 -0
  50. package/.medusa/server/src/api/store/affiliates/me/slugs/route.js +34 -0
  51. package/.medusa/server/src/api/store/affiliates/own-order-discount/route.js +22 -0
  52. package/.medusa/server/src/api/store/affiliates/own-order-promotion/route.js +30 -0
  53. package/.medusa/server/src/api/store/affiliates/register/route.js +27 -0
  54. package/.medusa/server/src/api/store/affiliates/resolve-referral/route.js +34 -0
  55. package/.medusa/server/src/api/validators.js +52 -0
  56. package/.medusa/server/src/api/wire-response.js +10 -0
  57. package/.medusa/server/src/integration/email-events.js +51 -0
  58. package/.medusa/server/src/integrations/inventory-transfer/batch-management-transfer-adapter.js +36 -0
  59. package/.medusa/server/src/integrations/inventory-transfer/native-inventory-transfer-adapter.js +30 -0
  60. package/.medusa/server/src/integrations/inventory-transfer/resolve-inventory-transfer-adapter.js +46 -0
  61. package/.medusa/server/src/integrations/inventory-transfer/types.js +3 -0
  62. package/.medusa/server/src/jobs/affiliate-attribution-expiry.js +20 -0
  63. package/.medusa/server/src/jobs/affiliate-consignment-report-reminders.js +15 -0
  64. package/.medusa/server/src/jobs/affiliate-promotion-freshness.js +24 -0
  65. package/.medusa/server/src/lib/query-string.js +15 -0
  66. package/.medusa/server/src/modules/affiliate/domain/affiliate-attribution-policy.js +81 -0
  67. package/.medusa/server/src/modules/affiliate/domain/affiliate-coupon-policy.js +61 -0
  68. package/.medusa/server/src/modules/affiliate/domain/commission-policy.js +33 -0
  69. package/.medusa/server/src/modules/affiliate/domain/consignment-reminder-rules.js +74 -0
  70. package/.medusa/server/src/modules/affiliate/domain/email-normalization.js +20 -0
  71. package/.medusa/server/src/modules/affiliate/domain/own-order-coupon-code.js +37 -0
  72. package/.medusa/server/src/modules/affiliate/domain/plugin-options.js +40 -0
  73. package/.medusa/server/src/modules/affiliate/index.js +13 -0
  74. package/.medusa/server/src/modules/affiliate/migrations/Migration20260827085154.js +423 -0
  75. package/.medusa/server/src/modules/affiliate/models/affiliate-application.js +38 -0
  76. package/.medusa/server/src/modules/affiliate/models/affiliate-cart-referral.js +65 -0
  77. package/.medusa/server/src/modules/affiliate/models/affiliate-code-redemption.js +41 -0
  78. package/.medusa/server/src/modules/affiliate/models/affiliate-coupon.js +55 -0
  79. package/.medusa/server/src/modules/affiliate/models/affiliate-distribution-settings.js +22 -0
  80. package/.medusa/server/src/modules/affiliate/models/affiliate-order-attribution.js +49 -0
  81. package/.medusa/server/src/modules/affiliate/models/affiliate-program-settings.js +28 -0
  82. package/.medusa/server/src/modules/affiliate/models/affiliate-referral-session.js +34 -0
  83. package/.medusa/server/src/modules/affiliate/models/affiliate-slug.js +27 -0
  84. package/.medusa/server/src/modules/affiliate/models/affiliate.js +49 -0
  85. package/.medusa/server/src/modules/affiliate/models/commission-entry.js +62 -0
  86. package/.medusa/server/src/modules/affiliate/models/consignment-report-line.js +21 -0
  87. package/.medusa/server/src/modules/affiliate/models/consignment-report.js +31 -0
  88. package/.medusa/server/src/modules/affiliate/models/consignment-transfer-line.js +16 -0
  89. package/.medusa/server/src/modules/affiliate/models/consignment-transfer.js +20 -0
  90. package/.medusa/server/src/modules/affiliate/models/customer-affiliate-assignment.js +58 -0
  91. package/.medusa/server/src/modules/affiliate/service.js +2321 -0
  92. package/.medusa/server/src/modules/affiliate/services/affiliate-application-manager.js +171 -0
  93. package/.medusa/server/src/modules/affiliate/services/affiliate-coupon-manager.js +441 -0
  94. package/.medusa/server/src/modules/affiliate/services/affiliate-discount.service.js +55 -0
  95. package/.medusa/server/src/modules/affiliate/services/affiliate-manager.js +242 -0
  96. package/.medusa/server/src/modules/affiliate/services/affiliate-partner-portal.service.js +138 -0
  97. package/.medusa/server/src/modules/affiliate/services/affiliate-report.service.js +436 -0
  98. package/.medusa/server/src/modules/affiliate/services/affiliate-slug-manager.js +163 -0
  99. package/.medusa/server/src/modules/affiliate/services/commission-ledger.service.js +729 -0
  100. package/.medusa/server/src/modules/affiliate/services/customer-affiliate-assignment-manager.js +350 -0
  101. package/.medusa/server/src/modules/affiliate/services/order-attribution-manager.js +1051 -0
  102. package/.medusa/server/src/modules/affiliate/services/referral-lifecycle-manager.js +1420 -0
  103. package/.medusa/server/src/modules/affiliate/services/utils.js +49 -0
  104. package/.medusa/server/src/modules/affiliate/types/internal.js +3 -0
  105. package/.medusa/server/src/paths/affiliate.js +7 -0
  106. package/.medusa/server/src/paths/index.js +18 -0
  107. package/.medusa/server/src/schemas/index.js +18 -0
  108. package/.medusa/server/src/schemas/store.js +24 -0
  109. package/.medusa/server/src/subscribers/affiliate-cart-updated.js +92 -0
  110. package/.medusa/server/src/subscribers/affiliate-order-canceled.js +70 -0
  111. package/.medusa/server/src/subscribers/affiliate-order-placed.js +63 -0
  112. package/.medusa/server/src/subscribers/affiliate-order-return-received.js +67 -0
  113. package/.medusa/server/src/subscribers/affiliate-product-eligibility-updated.js +87 -0
  114. package/.medusa/server/src/types/admin-api.js +3 -0
  115. package/.medusa/server/src/types/enums.js +53 -0
  116. package/.medusa/server/src/types/index.js +32 -0
  117. package/.medusa/server/src/types/public.js +3 -0
  118. package/.medusa/server/src/types/store-api.js +3 -0
  119. package/.medusa/server/src/utils/affiliate-cart-operation-lock.js +316 -0
  120. package/.medusa/server/src/utils/affiliate-promotion-mutation-authorization.js +49 -0
  121. package/.medusa/server/src/utils/cart-promotions.js +9 -0
  122. package/.medusa/server/src/utils/money.js +79 -0
  123. package/.medusa/server/src/utils/promotion-code-availability.js +34 -0
  124. package/.medusa/server/src/utils/registered-email-checkout.js +101 -0
  125. package/.medusa/server/src/utils/resolve-services.js +7 -0
  126. package/.medusa/server/src/utils/settle-cart-promotions.js +44 -0
  127. package/.medusa/server/src/workflows/affiliate/affiliate-coupon-cart.js +215 -0
  128. package/.medusa/server/src/workflows/affiliate/affiliate-coupon-command-authorization.js +20 -0
  129. package/.medusa/server/src/workflows/affiliate/apply-affiliate-coupon.js +174 -0
  130. package/.medusa/server/src/workflows/affiliate/apply-own-order-promotion.js +89 -0
  131. package/.medusa/server/src/workflows/affiliate/approve-consignment-report.js +186 -0
  132. package/.medusa/server/src/workflows/affiliate/correct-approved-consignment-report.js +263 -0
  133. package/.medusa/server/src/workflows/affiliate/create-affiliate-coupon.js +35 -0
  134. package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-cancellation.js +21 -0
  135. package/.medusa/server/src/workflows/affiliate/create-commission-correction-for-refund.js +24 -0
  136. package/.medusa/server/src/workflows/affiliate/create-commission-for-order.js +17 -0
  137. package/.medusa/server/src/workflows/affiliate/deactivate-affiliate.js +89 -0
  138. package/.medusa/server/src/workflows/affiliate/enable-distribution.js +120 -0
  139. package/.medusa/server/src/workflows/affiliate/enrich-affiliate-report.js +75 -0
  140. package/.medusa/server/src/workflows/affiliate/ensure-affiliate-coupon-promotion.js +410 -0
  141. package/.medusa/server/src/workflows/affiliate/ensure-affiliate-own-order-promotion.js +240 -0
  142. package/.medusa/server/src/workflows/affiliate/ensure-default-affiliate-coupon.js +32 -0
  143. package/.medusa/server/src/workflows/affiliate/expire-affiliate-attribution-state.js +131 -0
  144. package/.medusa/server/src/workflows/affiliate/finalize-affiliate-order-attribution.js +82 -0
  145. package/.medusa/server/src/workflows/affiliate/payment-authorization.js +33 -0
  146. package/.medusa/server/src/workflows/affiliate/promotion-eligibility.js +179 -0
  147. package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-cart-referral.js +219 -0
  148. package/.medusa/server/src/workflows/affiliate/reconcile-affiliate-coupon.js +388 -0
  149. package/.medusa/server/src/workflows/affiliate/refresh-affiliate-promotions.js +114 -0
  150. package/.medusa/server/src/workflows/affiliate/resolve-coupon-labels.js +40 -0
  151. package/.medusa/server/src/workflows/affiliate/revoke-affiliate-coupon.js +29 -0
  152. package/.medusa/server/src/workflows/affiliate/rotate-affiliate-coupon.js +36 -0
  153. package/.medusa/server/src/workflows/affiliate/run-consignment-report-reminders.js +58 -0
  154. package/.medusa/server/src/workflows/affiliate/submit-consignment-report.js +279 -0
  155. package/.medusa/server/src/workflows/affiliate/transfer-batch-aware-inventory.js +172 -0
  156. package/.medusa/server/src/workflows/affiliate/transfer-consignment-stock.js +106 -0
  157. package/.medusa/server/src/workflows/affiliate/update-affiliate-coupon-discounts.js +129 -0
  158. package/.medusa/server/src/workflows/affiliate/utils.js +118 -0
  159. package/.medusa/server/src/workflows/hooks/complete-cart-affiliate-attribution.js +57 -0
  160. package/.medusa/server/src/workflows/hooks/complete-cart-order-created-composition.js +111 -0
  161. package/.medusa/server/src/workflows/hooks/complete-cart-own-order-discount.js +75 -0
  162. package/.medusa/server/src/workflows/hooks/enforce-unique-promotion-codes.js +33 -0
  163. package/.medusa/server/src/workflows/hooks/validate-affiliate-customer-code.js +239 -0
  164. package/.medusa/server/src/workflows/hooks/validate-complete-cart-affiliate-referral.js +137 -0
  165. package/LICENSE +21 -0
  166. package/README.md +799 -0
  167. package/dist/integration/email-events.d.ts +20 -0
  168. package/dist/integration/email-events.js +50 -0
  169. package/package.json +84 -0
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
6
+ const promotion_code_availability_1 = require("../../utils/promotion-code-availability");
7
+ /**
8
+ * Rejects a promotion whose code equals another promotion's code ignoring
9
+ * case (see `utils/promotion-code-availability.ts`). Runs after Medusa has
10
+ * written the promotion, so throwing here makes the workflow compensate and
11
+ * remove it again - the Admin user sees the error, nothing is left behind.
12
+ * Affiliate coupons are covered through the promotion each one provisions.
13
+ */
14
+ const assertNoCaseInsensitiveDuplicates = async (promotions, promotionService) => {
15
+ const ownIds = promotions.map(({ id }) => id);
16
+ for (const promotion of promotions) {
17
+ if (!promotion.code)
18
+ continue;
19
+ const [owner] = await (0, promotion_code_availability_1.findPromotionsWithCodeIgnoringCase)(promotionService, promotion.code, { except_promotion_ids: ownIds });
20
+ if (owner) {
21
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.DUPLICATE_ERROR, (0, promotion_code_availability_1.promotionCodeTakenMessage)(promotion.code, owner));
22
+ }
23
+ }
24
+ };
25
+ core_flows_1.createPromotionsWorkflow.hooks.promotionsCreated(async ({ promotions }, { container }) => {
26
+ await assertNoCaseInsensitiveDuplicates(promotions, container.resolve(utils_1.Modules.PROMOTION));
27
+ return new workflows_sdk_1.StepResponse(undefined);
28
+ });
29
+ core_flows_1.updatePromotionsWorkflow.hooks.promotionsUpdated(async ({ promotions }, { container }) => {
30
+ await assertNoCaseInsensitiveDuplicates(promotions, container.resolve(utils_1.Modules.PROMOTION));
31
+ return new workflows_sdk_1.StepResponse(undefined);
32
+ });
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5mb3JjZS11bmlxdWUtcHJvbW90aW9uLWNvZGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3dvcmtmbG93cy9ob29rcy9lbmZvcmNlLXVuaXF1ZS1wcm9tb3Rpb24tY29kZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFDQSxxRUFBZ0U7QUFDaEUscURBQWdFO0FBQ2hFLDREQUdvQztBQUVwQyx5RkFJZ0Q7QUFFaEQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxpQ0FBaUMsR0FBRyxLQUFLLEVBQzdDLFVBQWdDLEVBQ2hDLGdCQUF5QyxFQUMxQixFQUFFO0lBQ2pCLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUM3QyxLQUFLLE1BQU0sU0FBUyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBQ25DLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSTtZQUFFLFNBQVE7UUFDN0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sSUFBQSxnRUFBa0MsRUFDdEQsZ0JBQWdCLEVBQ2hCLFNBQVMsQ0FBQyxJQUFJLEVBQ2QsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLEVBQUUsQ0FDakMsQ0FBQTtRQUNELElBQUksS0FBSyxFQUFFLENBQUM7WUFDVixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUNqQyxJQUFBLHVEQUF5QixFQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQ2pELENBQUE7UUFDSCxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMsQ0FBQTtBQUVELHFDQUF3QixDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FDOUMsS0FBSyxFQUFFLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQ3RDLE1BQU0saUNBQWlDLENBQ3JDLFVBQWtDLEVBQ2xDLFNBQVMsQ0FBQyxPQUFPLENBQUMsZUFBTyxDQUFDLFNBQVMsQ0FBNEIsQ0FDaEUsQ0FBQTtJQUNELE9BQU8sSUFBSSw0QkFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFBO0FBQ3BDLENBQUMsQ0FDRixDQUFBO0FBRUQscUNBQXdCLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUM5QyxLQUFLLEVBQUUsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDdEMsTUFBTSxpQ0FBaUMsQ0FDckMsVUFBa0MsRUFDbEMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFPLENBQUMsU0FBUyxDQUE0QixDQUNoRSxDQUFBO0lBQ0QsT0FBTyxJQUFJLDRCQUFZLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDcEMsQ0FBQyxDQUNGLENBQUEifQ==
@@ -0,0 +1,239 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.validateAffiliateCustomerCode = exports.isCodeReapplication = void 0;
37
+ const Sentry = __importStar(require("@sentry/node"));
38
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
39
+ const utils_1 = require("@medusajs/framework/utils");
40
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
41
+ const email_normalization_1 = require("../../modules/affiliate/domain/email-normalization");
42
+ const resolve_services_1 = require("../../utils/resolve-services");
43
+ const cart_promotions_1 = require("../../utils/cart-promotions");
44
+ const affiliate_promotion_mutation_authorization_1 = require("../../utils/affiliate-promotion-mutation-authorization");
45
+ const apply_affiliate_coupon_1 = require("../affiliate/apply-affiliate-coupon");
46
+ const affiliate_coupon_cart_1 = require("../affiliate/affiliate-coupon-cart");
47
+ const promotion_eligibility_1 = require("../affiliate/promotion-eligibility");
48
+ const canonicalCode = (code) => code.trim().toUpperCase();
49
+ /**
50
+ * True when the requested mutation neither introduces nor drops a code
51
+ * compared to what the cart already carries: an ADD of codes that are all
52
+ * applied already, or a REPLACE with exactly the applied set (which is what
53
+ * Medusa's own cart refresh sends).
54
+ */
55
+ const isCodeReapplication = (action, requestedCodes, cartPromotions) => {
56
+ const applied = new Set(cartPromotions.flatMap(({ code }) => (code ? [canonicalCode(code)] : [])));
57
+ const requested = new Set(requestedCodes.map(canonicalCode));
58
+ const requestedAllApplied = [...requested].every((code) => applied.has(code));
59
+ if (action === utils_1.PromotionActions.ADD)
60
+ return requestedAllApplied;
61
+ if (action === utils_1.PromotionActions.REPLACE) {
62
+ return requestedAllApplied && requested.size === applied.size;
63
+ }
64
+ return false;
65
+ };
66
+ exports.isCodeReapplication = isCodeReapplication;
67
+ const reportAffiliateCartStateReadFailure = (container, cartId, error) => {
68
+ Sentry.captureException(error, {
69
+ tags: { area: "affiliate-cart-hook" },
70
+ extra: { cartId },
71
+ });
72
+ try {
73
+ container
74
+ .resolve(utils_1.ContainerRegistrationKeys.LOGGER)
75
+ .warn(`Affiliate cart state could not be read for cart ${cartId}; letting the unchanged promotion set through: ${error instanceof Error ? error.message : "Unknown error"}`);
76
+ }
77
+ catch {
78
+ // A missing logger must not turn the fail-safe itself into a failure.
79
+ }
80
+ };
81
+ const validateAffiliateCustomerCode = async ({ input, cart }, { container }) => {
82
+ if (input.action !== utils_1.PromotionActions.ADD &&
83
+ input.action !== utils_1.PromotionActions.REPLACE) {
84
+ return new workflows_sdk_1.StepResponse(undefined);
85
+ }
86
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
87
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
88
+ const typedCart = cart;
89
+ const requestedCodes = [...new Set(input.promo_codes ?? [])];
90
+ let existingPromotions;
91
+ let existingBindings;
92
+ try {
93
+ existingPromotions = await (0, affiliate_coupon_cart_1.retrieveAffiliateCouponCartPromotions)(container, typedCart.id);
94
+ existingBindings = await (0, affiliate_coupon_cart_1.loadAffiliateCouponCartBindings)(affiliateService, existingPromotions);
95
+ }
96
+ catch (error) {
97
+ // This hook runs inside every line-item add/update/remove (Medusa's
98
+ // refreshCartItemsWorkflow re-applies the cart's current codes with
99
+ // REPLACE). A failure while merely *reading* the cart's affiliate state
100
+ // must not turn a plain cart edit into a 500 for a customer who never
101
+ // touched a coupon - but it must never let a coupon slip in or out
102
+ // unvalidated either. So the request is only allowed through when it
103
+ // changes nothing about the applied codes; the complete-cart hook stays
104
+ // the authoritative gate for the coupon itself.
105
+ if (!(0, exports.isCodeReapplication)(input.action, requestedCodes, (0, cart_promotions_1.readCartPromotions)(typedCart.promotions))) {
106
+ throw error;
107
+ }
108
+ reportAffiliateCartStateReadFailure(container, typedCart.id, error);
109
+ return new workflows_sdk_1.StepResponse(undefined);
110
+ }
111
+ const requestedCoupons = (await Promise.all(requestedCodes.map(async (code) => {
112
+ try {
113
+ return await affiliateService.findAffiliateCouponByCode(code);
114
+ }
115
+ catch (error) {
116
+ if (error instanceof utils_1.MedusaError &&
117
+ error.type === utils_1.MedusaError.Types.INVALID_DATA) {
118
+ return null;
119
+ }
120
+ throw error;
121
+ }
122
+ }))).filter((coupon) => coupon !== null);
123
+ const authorizationToken = input[affiliate_promotion_mutation_authorization_1.affiliatePromotionAuthorizationInputKey];
124
+ const effectiveCoupons = new Map();
125
+ if (input.action === utils_1.PromotionActions.ADD) {
126
+ for (const { coupon } of existingBindings) {
127
+ effectiveCoupons.set(coupon.id, coupon);
128
+ }
129
+ }
130
+ for (const coupon of requestedCoupons) {
131
+ effectiveCoupons.set(coupon.id, coupon);
132
+ }
133
+ if (!effectiveCoupons.size &&
134
+ input.action === utils_1.PromotionActions.REPLACE &&
135
+ existingBindings.length) {
136
+ const existingCoupon = existingBindings[0].coupon;
137
+ const authorized = authorizationToken !== undefined &&
138
+ existingCoupon.promotion_id !== null &&
139
+ (0, affiliate_promotion_mutation_authorization_1.consumeAffiliatePromotionMutationAuthorization)(authorizationToken, {
140
+ cart_id: typedCart.id,
141
+ coupon_id: existingCoupon.id,
142
+ promotion_id: existingCoupon.promotion_id,
143
+ action: input.action,
144
+ promo_codes: requestedCodes,
145
+ });
146
+ if (!authorized) {
147
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Affiliate coupon promotion mutation is not authorized.");
148
+ }
149
+ return new workflows_sdk_1.StepResponse(undefined);
150
+ }
151
+ if (!effectiveCoupons.size) {
152
+ return new workflows_sdk_1.StepResponse(undefined);
153
+ }
154
+ if (input.action === utils_1.PromotionActions.ADD &&
155
+ existingBindings.some(({ exact }) => !exact)) {
156
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "The cart contains an invalid Affiliate coupon promotion binding.");
157
+ }
158
+ if (effectiveCoupons.size !== 1) {
159
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "Exactly one public Affiliate coupon promotion may be applied to a cart.");
160
+ }
161
+ const coupon = [...effectiveCoupons.values()][0];
162
+ const affiliate = await affiliateService.retrieveAffiliateRecord(coupon.affiliate_id);
163
+ if (coupon.lifecycle_status !== "enabled" ||
164
+ coupon.provisioning_status !== "ready" ||
165
+ !coupon.promotion_id ||
166
+ affiliate.status !== "active") {
167
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "The Affiliate coupon is inactive or not prepared.");
168
+ }
169
+ const settings = await affiliateService.retrieveProgramSettings();
170
+ await (0, promotion_eligibility_1.assertAuthenticAffiliateCouponPromotion)(container.resolve(utils_1.Modules.PROMOTION), { coupon, affiliate });
171
+ const existingPromotionIds = new Set(existingPromotions.map(({ id }) => id));
172
+ const introducesCoupon = requestedCoupons.some(({ id }) => id === coupon.id) &&
173
+ !existingPromotionIds.has(coupon.promotion_id);
174
+ const normalizedEmail = typedCart.email
175
+ ? (0, email_normalization_1.normalizeAffiliateEmail)(typedCart.email)
176
+ : null;
177
+ const state = await affiliateService.inspectAffiliateCartReferralForCheckout({
178
+ cart_id: typedCart.id,
179
+ customer_id: typedCart.customer_id ?? null,
180
+ normalized_email: normalizedEmail,
181
+ }, query);
182
+ if (introducesCoupon && state.has_code_redemption) {
183
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.CONFLICT, apply_affiliate_coupon_1.AFFILIATE_COUPON_ALREADY_USED_MESSAGE);
184
+ }
185
+ if (introducesCoupon && !typedCart.email) {
186
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "A cart email is required to use an Affiliate coupon.");
187
+ }
188
+ if (introducesCoupon &&
189
+ typedCart.customer_id &&
190
+ (await affiliateService.isCustomerAffiliate(typedCart.customer_id))) {
191
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Affiliate customers cannot use public Affiliate coupons.");
192
+ }
193
+ if (introducesCoupon &&
194
+ (state.assignment_conflict ||
195
+ (state.assignment &&
196
+ state.assignment.affiliate_id !== coupon.affiliate_id))) {
197
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "This customer is assigned to another Affiliate.");
198
+ }
199
+ if (!(0, affiliate_coupon_cart_1.hasExactPreparedAffiliateCouponBinding)(state.referrals, coupon)) {
200
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "The Affiliate coupon has no exact active prepared cart binding.");
201
+ }
202
+ const exactExistingCouponRefresh = input.action === utils_1.PromotionActions.REPLACE &&
203
+ existingBindings.length === 1 &&
204
+ existingBindings[0].exact &&
205
+ existingBindings[0].coupon.id === coupon.id &&
206
+ requestedCoupons.length === 1 &&
207
+ requestedCoupons[0].id === coupon.id &&
208
+ requestedCodes.filter((code) => canonicalCode(code) === coupon.code)
209
+ .length === 1;
210
+ const authorized = authorizationToken !== undefined &&
211
+ (0, affiliate_promotion_mutation_authorization_1.consumeAffiliatePromotionMutationAuthorization)(authorizationToken, {
212
+ cart_id: typedCart.id,
213
+ coupon_id: coupon.id,
214
+ promotion_id: coupon.promotion_id,
215
+ action: input.action,
216
+ promo_codes: requestedCodes,
217
+ });
218
+ if ((authorizationToken !== undefined && !authorized) ||
219
+ (!authorized &&
220
+ requestedCoupons.length > 0 &&
221
+ !exactExistingCouponRefresh)) {
222
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "Affiliate coupon promotion mutation is not authorized.");
223
+ }
224
+ if (settings.promotion_stacking === "exclusive") {
225
+ // Automatic promotions (e.g. a threshold-based free-shipping promotion)
226
+ // aren't something the customer chose to combine, so they don't count
227
+ // as "another promotion" under exclusive stacking.
228
+ const existingOtherPromotion = input.action === utils_1.PromotionActions.ADD &&
229
+ existingPromotions.some(({ id, is_automatic }) => id !== coupon.promotion_id && !is_automatic);
230
+ const requestedOtherCode = requestedCodes.some((code) => canonicalCode(code) !== coupon.code);
231
+ if (existingOtherPromotion || requestedOtherCode) {
232
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, "The Affiliate coupon cannot be combined with another promotion.");
233
+ }
234
+ }
235
+ return new workflows_sdk_1.StepResponse(undefined);
236
+ };
237
+ exports.validateAffiliateCustomerCode = validateAffiliateCustomerCode;
238
+ core_flows_1.updateCartPromotionsWorkflow.hooks.validate(exports.validateAffiliateCustomerCode);
239
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtYWZmaWxpYXRlLWN1c3RvbWVyLWNvZGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2hvb2tzL3ZhbGlkYXRlLWFmZmlsaWF0ZS1jdXN0b21lci1jb2RlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHFEQUF1QztBQUN2QyxxRUFBaUU7QUFFakUscURBS21DO0FBQ25DLDREQUEyRTtBQUUzRSw0RkFBNkY7QUFDN0YsbUVBQXVFO0FBQ3ZFLGlFQUFpRTtBQUNqRSx1SEFHZ0U7QUFFaEUsZ0ZBQTRGO0FBQzVGLDhFQU00QztBQUM1Qyw4RUFBNkY7QUFjN0YsTUFBTSxhQUFhLEdBQUcsQ0FBQyxJQUFZLEVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQztBQUUxRTs7Ozs7R0FLRztBQUNJLE1BQU0sbUJBQW1CLEdBQUcsQ0FDakMsTUFBd0IsRUFDeEIsY0FBaUMsRUFDakMsY0FBNEMsRUFDbkMsRUFBRTtJQUNYLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxDQUNyQixjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQzFFLENBQUM7SUFDRixNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDN0QsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDeEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJ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
@@ -0,0 +1,137 @@
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.validateCompleteCartAffiliateReferral = void 0;
37
+ const Sentry = __importStar(require("@sentry/node"));
38
+ const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
39
+ const utils_1 = require("@medusajs/framework/utils");
40
+ const core_flows_1 = require("@medusajs/medusa/core-flows");
41
+ const email_normalization_1 = require("../../modules/affiliate/domain/email-normalization");
42
+ const resolve_services_1 = require("../../utils/resolve-services");
43
+ const affiliate_coupon_cart_1 = require("../affiliate/affiliate-coupon-cart");
44
+ const promotion_eligibility_1 = require("../affiliate/promotion-eligibility");
45
+ const complete_cart_own_order_discount_1 = require("./complete-cart-own-order-discount");
46
+ const INVALID_AFFILIATE_REFERRAL_MESSAGE = "Der Affiliate-Referral des Warenkorbs ist nicht vollständig validiert. Bitte aktualisiere den Warenkorb und versuche es erneut.";
47
+ const validateCompleteCartAffiliateReferral = async ({ cart }, { container }) => {
48
+ const invalid = () => {
49
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, INVALID_AFFILIATE_REFERRAL_MESSAGE);
50
+ };
51
+ const typedCart = cart;
52
+ const affiliateService = (0, resolve_services_1.resolveAffiliateService)(container);
53
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
54
+ const normalizedEmail = typedCart.email
55
+ ? (0, email_normalization_1.normalizeAffiliateEmail)(typedCart.email)
56
+ : null;
57
+ const state = await affiliateService.inspectAffiliateCartReferralForCheckout({
58
+ cart_id: typedCart.id,
59
+ customer_id: typedCart.customer_id ?? null,
60
+ normalized_email: normalizedEmail,
61
+ }, query);
62
+ if (state.referrals.some((referral) => referral.status === "pending_email_validation")) {
63
+ invalid();
64
+ }
65
+ const activeReferral = state.referrals.find((referral) => referral.status === "active");
66
+ const latestReferral = state.latest_referral;
67
+ const referralAffiliate = activeReferral
68
+ ? await affiliateService.retrieveAffiliateRecord(activeReferral.affiliate_id)
69
+ : null;
70
+ if ((!activeReferral &&
71
+ latestReferral?.status === "invalidated" &&
72
+ latestReferral.invalidated_reason === "affiliate_inactive") ||
73
+ (activeReferral &&
74
+ (new Date(activeReferral.expires_at).getTime() <= Date.now() ||
75
+ referralAffiliate?.status !== "active"))) {
76
+ invalid();
77
+ }
78
+ // Medusa 2.19's complete-cart snapshot selects promotion IDs but not codes.
79
+ const promotions = await (0, affiliate_coupon_cart_1.retrieveAffiliateCouponCartPromotions)(container, typedCart.id);
80
+ const couponBindings = await (0, affiliate_coupon_cart_1.loadAffiliateCouponCartBindings)(affiliateService, promotions);
81
+ if (!couponBindings.length) {
82
+ if (activeReferral?.source === "coupon" ||
83
+ activeReferral?.applied_affiliate_coupon_id ||
84
+ activeReferral?.applied_promotion_id) {
85
+ invalid();
86
+ }
87
+ return new workflows_sdk_1.StepResponse(undefined);
88
+ }
89
+ if (couponBindings.length !== 1 ||
90
+ !couponBindings[0].exact ||
91
+ !activeReferral) {
92
+ invalid();
93
+ }
94
+ const coupon = couponBindings[0].coupon;
95
+ const affiliate = await affiliateService.retrieveAffiliateRecord(coupon.affiliate_id);
96
+ if (coupon.lifecycle_status !== "enabled" ||
97
+ coupon.provisioning_status !== "ready" ||
98
+ !coupon.promotion_id ||
99
+ affiliate.status !== "active" ||
100
+ !typedCart.email ||
101
+ state.assignment_conflict ||
102
+ state.has_code_redemption ||
103
+ (state.assignment && state.assignment.affiliate_id !== affiliate.id) ||
104
+ !(0, affiliate_coupon_cart_1.hasExactPreparedAffiliateCouponBinding)(state.referrals, coupon)) {
105
+ invalid();
106
+ }
107
+ if (typedCart.customer_id &&
108
+ (await affiliateService.isCustomerAffiliate(typedCart.customer_id))) {
109
+ invalid();
110
+ }
111
+ const settings = await affiliateService.retrieveProgramSettings();
112
+ await (0, promotion_eligibility_1.assertAuthenticAffiliateCouponPromotion)(container.resolve(utils_1.Modules.PROMOTION), { coupon, affiliate });
113
+ if (settings.promotion_stacking === "exclusive" &&
114
+ promotions.some(({ id }) => id !== coupon.promotion_id)) {
115
+ invalid();
116
+ }
117
+ return new workflows_sdk_1.StepResponse(undefined);
118
+ };
119
+ exports.validateCompleteCartAffiliateReferral = validateCompleteCartAffiliateReferral;
120
+ core_flows_1.completeCartWorkflow.hooks.validate(async (input, context) => {
121
+ try {
122
+ await (0, complete_cart_own_order_discount_1.validateCompleteCartOwnOrderDiscount)(input, context);
123
+ return await (0, exports.validateCompleteCartAffiliateReferral)(input, context);
124
+ }
125
+ catch (error) {
126
+ // Both hooks already fail the checkout API call via a thrown
127
+ // MedusaError - captured here too for aggregate visibility (e.g.
128
+ // noticing every checkout failing for one affiliate), not because the
129
+ // customer-facing behavior needs to change.
130
+ Sentry.captureException(error, {
131
+ tags: { area: "affiliate-complete-cart-validate" },
132
+ extra: { cartId: input.cart.id },
133
+ });
134
+ throw error;
135
+ }
136
+ });
137
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtY29tcGxldGUtY2FydC1hZmZpbGlhdGUtcmVmZXJyYWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL2hvb2tzL3ZhbGlkYXRlLWNvbXBsZXRlLWNhcnQtYWZmaWxpYXRlLXJlZmVycmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHFEQUFzQztBQUV0QyxxRUFBZ0U7QUFDaEUscURBSWtDO0FBQ2xDLDREQUFrRTtBQUVsRSw0RkFBNEY7QUFDNUYsbUVBQXNFO0FBRXRFLDhFQUkyQztBQUMzQyw4RUFBNEY7QUFDNUYseUZBSTJDO0FBRTNDLE1BQU0sa0NBQWtDLEdBQ3RDLGlJQUFpSSxDQUFBO0FBUzVILE1BQU0scUNBQXFDLEdBQUcsS0FBSyxFQUN4RCxFQUFFLElBQUksRUFBNkIsRUFDbkMsRUFBRSxTQUFTLEVBQStCLEVBQzFDLEVBQUU7SUFDRixNQUFNLE9BQU8sR0FBRyxHQUFVLEVBQUU7UUFDMUIsTUFBTSxJQUFJLG1CQUFXLENBQ25CLG1CQUFXLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFDN0Isa0NBQWtDLENBQ25DLENBQUE7SUFDSCxDQUFDLENBQUE7SUFDRCxNQUFNLFNBQVMsR0FBRyxJQUFxQyxDQUFBO0lBQ3ZELE1BQU0sZ0JBQWdCLEdBQUcsSUFBQSwwQ0FBdUIsRUFBQyxTQUFTLENBQUMsQ0FBQTtJQUMzRCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFBO0lBQ2hFLE1BQU0sZUFBZSxHQUFHLFNBQVMsQ0FBQyxLQUFLO1FBQ3JDLENBQUMsQ0FBQyxJQUFBLDZDQUF1QixFQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUM7UUFDMUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtJQUNSLE1BQU0sS0FBSyxHQUFHLE1BQU0sZ0JBQWdCLENBQUMs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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hartl Services GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.