@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,316 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withAffiliateCartOperationLock = exports.withAffiliateOperationLocks = exports.acquireAffiliateOperationLocks = exports.affiliateProgramSagaLockKey = exports.affiliateSagaLockKey = exports.runAsIndependentAffiliateOperation = exports.isAffiliateCartOperationLockKeyHeld = exports.affiliateCartLockKey = exports.AffiliateOperationLockTimeoutError = void 0;
4
+ const node_async_hooks_1 = require("node:async_hooks");
5
+ const utils_1 = require("@medusajs/framework/utils");
6
+ class KeyedConnectionPermits {
7
+ constructor(capacity) {
8
+ this.capacity = capacity;
9
+ this.active = 0;
10
+ this.activeKeys = new Set();
11
+ this.waiters = [];
12
+ }
13
+ async acquire(keys) {
14
+ return await new Promise((resolve) => {
15
+ this.waiters.push({ keys, resolve });
16
+ this.dispatch();
17
+ });
18
+ }
19
+ release(keys) {
20
+ this.active -= 1;
21
+ for (const key of keys) {
22
+ this.activeKeys.delete(key);
23
+ }
24
+ this.dispatch();
25
+ }
26
+ dispatch() {
27
+ for (let index = 0; index < this.waiters.length;) {
28
+ if (this.active >= this.capacity) {
29
+ return;
30
+ }
31
+ const waiter = this.waiters[index];
32
+ if (waiter.keys.some((key) => this.activeKeys.has(key))) {
33
+ index += 1;
34
+ continue;
35
+ }
36
+ this.waiters.splice(index, 1);
37
+ this.active += 1;
38
+ for (const key of waiter.keys) {
39
+ this.activeKeys.add(key);
40
+ }
41
+ let released = false;
42
+ waiter.resolve(() => {
43
+ if (released)
44
+ return;
45
+ released = true;
46
+ this.release(waiter.keys);
47
+ });
48
+ }
49
+ }
50
+ }
51
+ class AffiliateOperationLockTimeoutError extends Error {
52
+ constructor(lockKey) {
53
+ super(`Timed out acquiring Affiliate operation lock "${lockKey}".`);
54
+ this.name = "AffiliateOperationLockTimeoutError";
55
+ }
56
+ }
57
+ exports.AffiliateOperationLockTimeoutError = AffiliateOperationLockTimeoutError;
58
+ const heldOperationLocks = new node_async_hooks_1.AsyncLocalStorage();
59
+ const schedulerByClient = new WeakMap();
60
+ const defaultPoolMax = 2;
61
+ const reservedWorkflowConnections = 1;
62
+ const advisoryLockTimeoutMs = 5_000;
63
+ const advisoryLockPollIntervalMs = 25;
64
+ const normalizeLockKeys = (lockKeys) => [...new Set(lockKeys)].sort((left, right) => {
65
+ const leftIsCart = left.startsWith("affiliate-cart:");
66
+ const rightIsCart = right.startsWith("affiliate-cart:");
67
+ if (leftIsCart !== rightIsCart)
68
+ return leftIsCart ? -1 : 1;
69
+ return left.localeCompare(right);
70
+ });
71
+ const combinedFailure = (failures, message) => {
72
+ if (failures.length === 1)
73
+ return failures[0];
74
+ return new AggregateError(failures, message);
75
+ };
76
+ const lockCapacity = (knex) => {
77
+ const configuredMaxValue = knex.client.pool?.max ?? knex.client.config?.pool?.max ?? defaultPoolMax;
78
+ const configuredMax = Number.isFinite(configuredMaxValue)
79
+ ? Math.floor(configuredMaxValue)
80
+ : defaultPoolMax;
81
+ if (configuredMax <= reservedWorkflowConnections) {
82
+ throw new Error("Affiliate operation locking requires a PostgreSQL pool with at least two connections.");
83
+ }
84
+ return configuredMax - reservedWorkflowConnections;
85
+ };
86
+ const connectionPermits = (knex) => {
87
+ const client = knex.client;
88
+ let permits = schedulerByClient.get(client);
89
+ if (!permits) {
90
+ permits = new KeyedConnectionPermits(lockCapacity(knex));
91
+ schedulerByClient.set(client, permits);
92
+ }
93
+ return permits;
94
+ };
95
+ const queryBoolean = (result, field) => {
96
+ const rows = result
97
+ ?.rows;
98
+ return rows?.[0]?.[field] === true;
99
+ };
100
+ const wait = async (milliseconds) => await new Promise((resolve) => setTimeout(resolve, milliseconds));
101
+ const acquireAdvisoryLock = async (connection, lockKey) => {
102
+ const deadline = Date.now() + advisoryLockTimeoutMs;
103
+ while (true) {
104
+ const result = await connection.query("select pg_try_advisory_lock(hashtext($1)) as acquired", [lockKey]);
105
+ if (queryBoolean(result, "acquired"))
106
+ return;
107
+ const remaining = deadline - Date.now();
108
+ if (remaining <= 0) {
109
+ throw new AffiliateOperationLockTimeoutError(lockKey);
110
+ }
111
+ await wait(Math.min(advisoryLockPollIntervalMs, remaining));
112
+ }
113
+ };
114
+ const discardConnection = async (knex, connection, reason, failures) => {
115
+ // Close immediately so an ambiguous query cannot leave a server lock alive.
116
+ // Knex rejects the marker during later pool validation; pg's callback-based
117
+ // end() completes immediately when the client is already ended.
118
+ connection.__knex__disposed =
119
+ reason instanceof Error
120
+ ? reason
121
+ : new Error("Affiliate operation lock connection was discarded.");
122
+ try {
123
+ await knex.client.destroyRawConnection(connection);
124
+ }
125
+ catch (destroyError) {
126
+ failures.push(destroyError);
127
+ }
128
+ try {
129
+ const pool = knex.client.pool;
130
+ if (!pool?.release) {
131
+ throw new Error("Tarn cannot release the discarded Affiliate operation lock connection.");
132
+ }
133
+ // Tarn returns false only when this exact resource is already absent from
134
+ // `used`, so either result leaves no occupied pool slot.
135
+ pool.release(connection);
136
+ }
137
+ catch (poolReleaseError) {
138
+ failures.push(poolReleaseError);
139
+ }
140
+ };
141
+ const releaseAdvisoryLocks = async (connection, lockKeys) => {
142
+ for (const lockKey of [...lockKeys].reverse()) {
143
+ const unlockResult = await connection.query("select pg_advisory_unlock(hashtext($1)) as unlocked", [lockKey]);
144
+ if (!queryBoolean(unlockResult, "unlocked")) {
145
+ throw new Error(`PostgreSQL did not release Affiliate lock "${lockKey}".`);
146
+ }
147
+ }
148
+ };
149
+ const releaseAfterFailedAcquisition = async (knex, connection, acquisitionError, acquiredLockKeys) => {
150
+ const failures = [acquisitionError];
151
+ if (acquisitionError instanceof AffiliateOperationLockTimeoutError) {
152
+ try {
153
+ await releaseAdvisoryLocks(connection, acquiredLockKeys);
154
+ await knex.client.releaseConnection(connection);
155
+ }
156
+ catch (unlockError) {
157
+ failures.push(unlockError);
158
+ await discardConnection(knex, connection, unlockError, failures);
159
+ }
160
+ }
161
+ else {
162
+ // A failed query has an unknown server-side outcome.
163
+ await discardConnection(knex, connection, acquisitionError, failures);
164
+ }
165
+ throw combinedFailure(failures, "Affiliate operation lock acquisition failed");
166
+ };
167
+ const affiliateCartLockKey = (cartId) => `affiliate-cart:${cartId}`;
168
+ exports.affiliateCartLockKey = affiliateCartLockKey;
169
+ const isAffiliateCartOperationLockKeyHeld = (lockKey) => heldOperationLocks.getStore()?.has(lockKey) ?? false;
170
+ exports.isAffiliateCartOperationLockKeyHeld = isAffiliateCartOperationLockKeyHeld;
171
+ const runAsIndependentAffiliateOperation = async (operation) => await heldOperationLocks.run(new Set(), operation);
172
+ exports.runAsIndependentAffiliateOperation = runAsIndependentAffiliateOperation;
173
+ const affiliateSagaLockKey = (affiliateId) => `affiliate-saga:${affiliateId}`;
174
+ exports.affiliateSagaLockKey = affiliateSagaLockKey;
175
+ const affiliateProgramSagaLockKey = () => "affiliate-program-saga";
176
+ exports.affiliateProgramSagaLockKey = affiliateProgramSagaLockKey;
177
+ const acquireAffiliateOperationLocks = async (container, lockKeys) => {
178
+ const normalizedLockKeys = normalizeLockKeys(lockKeys);
179
+ const inheritedLocks = heldOperationLocks.getStore();
180
+ const acquiredLockKeys = normalizedLockKeys.filter((lockKey) => !inheritedLocks?.has(lockKey));
181
+ if (!acquiredLockKeys.length) {
182
+ return {
183
+ run: (operation) => operation(),
184
+ release: async () => undefined,
185
+ };
186
+ }
187
+ const knex = container.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
188
+ const releasePermit = await connectionPermits(knex).acquire(acquiredLockKeys);
189
+ let connection;
190
+ try {
191
+ connection = await knex.client.acquireConnection();
192
+ }
193
+ catch (error) {
194
+ releasePermit();
195
+ throw error;
196
+ }
197
+ const lockedKeys = [];
198
+ try {
199
+ for (const lockKey of acquiredLockKeys) {
200
+ await acquireAdvisoryLock(connection, lockKey);
201
+ lockedKeys.push(lockKey);
202
+ }
203
+ }
204
+ catch (acquisitionError) {
205
+ try {
206
+ return await releaseAfterFailedAcquisition(knex, connection, acquisitionError, lockedKeys);
207
+ }
208
+ finally {
209
+ releasePermit();
210
+ }
211
+ }
212
+ const operationLocks = new Set(inheritedLocks ?? []);
213
+ for (const lockKey of acquiredLockKeys) {
214
+ operationLocks.add(lockKey);
215
+ }
216
+ let releasePromise;
217
+ return {
218
+ run: (operation) => heldOperationLocks.run(operationLocks, operation),
219
+ release: () => {
220
+ releasePromise ??= (async () => {
221
+ const failures = [];
222
+ for (const lockKey of acquiredLockKeys) {
223
+ operationLocks.delete(lockKey);
224
+ }
225
+ let unlocked = false;
226
+ try {
227
+ await releaseAdvisoryLocks(connection, acquiredLockKeys);
228
+ unlocked = true;
229
+ }
230
+ catch (unlockError) {
231
+ failures.push(unlockError);
232
+ await discardConnection(knex, connection, unlockError, failures);
233
+ }
234
+ if (unlocked) {
235
+ try {
236
+ await knex.client.releaseConnection(connection);
237
+ }
238
+ catch (releaseError) {
239
+ failures.push(releaseError);
240
+ await discardConnection(knex, connection, releaseError, failures);
241
+ }
242
+ }
243
+ releasePermit();
244
+ if (failures.length) {
245
+ throw combinedFailure(failures, "Affiliate operation lease cleanup failed");
246
+ }
247
+ })();
248
+ return releasePromise;
249
+ },
250
+ };
251
+ };
252
+ exports.acquireAffiliateOperationLocks = acquireAffiliateOperationLocks;
253
+ const withAffiliateOperationLocks = async (container, lockKeys, operation) => {
254
+ const normalizedLockKeys = normalizeLockKeys(lockKeys);
255
+ const inheritedLocks = heldOperationLocks.getStore();
256
+ const acquiredLockKeys = normalizedLockKeys.filter((lockKey) => !inheritedLocks?.has(lockKey));
257
+ if (!acquiredLockKeys.length)
258
+ return await operation();
259
+ const knex = container.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
260
+ const releasePermit = await connectionPermits(knex).acquire(acquiredLockKeys);
261
+ let operationLocks;
262
+ try {
263
+ const connection = await knex.client.acquireConnection();
264
+ const lockedKeys = [];
265
+ try {
266
+ for (const lockKey of acquiredLockKeys) {
267
+ await acquireAdvisoryLock(connection, lockKey);
268
+ lockedKeys.push(lockKey);
269
+ }
270
+ }
271
+ catch (acquisitionError) {
272
+ return await releaseAfterFailedAcquisition(knex, connection, acquisitionError, lockedKeys);
273
+ }
274
+ operationLocks = new Set(inheritedLocks ?? []);
275
+ for (const lockKey of acquiredLockKeys) {
276
+ operationLocks.add(lockKey);
277
+ }
278
+ const failures = [];
279
+ let result;
280
+ try {
281
+ result = await heldOperationLocks.run(operationLocks, operation);
282
+ }
283
+ catch (operationError) {
284
+ failures.push(operationError);
285
+ }
286
+ for (const lockKey of acquiredLockKeys) {
287
+ operationLocks.delete(lockKey);
288
+ }
289
+ let unlocked = false;
290
+ try {
291
+ await releaseAdvisoryLocks(connection, acquiredLockKeys);
292
+ unlocked = true;
293
+ }
294
+ catch (unlockError) {
295
+ failures.push(unlockError);
296
+ await discardConnection(knex, connection, unlockError, failures);
297
+ }
298
+ if (unlocked) {
299
+ await knex.client.releaseConnection(connection);
300
+ }
301
+ if (failures.length) {
302
+ throw combinedFailure(failures, "Affiliate operation cleanup failed");
303
+ }
304
+ return result;
305
+ }
306
+ finally {
307
+ for (const lockKey of acquiredLockKeys) {
308
+ operationLocks?.delete(lockKey);
309
+ }
310
+ releasePermit();
311
+ }
312
+ };
313
+ exports.withAffiliateOperationLocks = withAffiliateOperationLocks;
314
+ const withAffiliateCartOperationLock = async (container, cartId, operation) => await (0, exports.withAffiliateOperationLocks)(container, [(0, exports.affiliateCartLockKey)(cartId)], operation);
315
+ exports.withAffiliateCartOperationLock = withAffiliateCartOperationLock;
316
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWZmaWxpYXRlLWNhcnQtb3BlcmF0aW9uLWxvY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvYWZmaWxpYXRlLWNhcnQtb3BlcmF0aW9uLWxvY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdURBQXFEO0FBR3JELHFEQUFzRTtBQXlCdEUsTUFBTSxzQkFBc0I7SUFLMUIsWUFBNkIsUUFBZ0I7UUFBaEIsYUFBUSxHQUFSLFFBQVEsQ0FBUTtRQUpyQyxXQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ0YsZUFBVSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDL0IsWUFBTyxHQUFtQixFQUFFLENBQUM7SUFFRSxDQUFDO0lBRWpELEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBYztRQUMxQixPQUFPLE1BQU0sSUFBSSxPQUFPLENBQWEsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUMvQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxPQUFPLENBQUMsSUFBYztRQUM1QixJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztRQUNqQixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlCLENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDbEIsQ0FBQztJQUVPLFFBQVE7UUFDZCxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUksQ0FBQztZQUNsRCxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNqQyxPQUFPO1lBQ1QsQ0FBQztZQUNELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbkMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN4RCxLQUFLLElBQUksQ0FBQyxDQUFDO2dCQUNYLFNBQVM7WUFDWCxDQUFDO1lBRUQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO1lBQ2pCLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUM5QixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMzQixDQUFDO1lBQ0QsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO1lBQ3JCLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFO2dCQUNsQixJQUFJLFFBQVE7b0JBQUUsT0FBTztnQkFDckIsUUFBUSxHQUFHLElBQUksQ0FBQztnQkFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDNUIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBRUQsTUFBYSxrQ0FBbUMsU0FBUSxLQUFLO0lBQzNELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsaURBQWlELE9BQU8sSUFBSSxDQUFDLENBQUM7UUFDcEUsSUFBSSxDQUFDLElBQUksR0FBRyxvQ0FBb0MsQ0FBQztJQUNuRCxDQUFDO0NBQ0Y7QUFMRCxnRkFLQztBQUVELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxvQ0FBaUIsRUFBdUIsQ0FBQztBQUN4RSxNQUFNLGlCQUFpQixHQUFHLElBQUksT0FBTyxFQUFrQyxDQUFDO0FBRXhFLE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUN6QixNQUFNLDJCQUEyQixHQUFHLENBQUMsQ0FBQztBQUN0QyxNQUFNLHFCQUFxQixHQUFHLEtBQUssQ0FBQztBQUNwQyxNQUFNLDBCQUEwQixHQUFHLEVBQUUsQ0FBQztBQUV0QyxNQUFNLGlCQUFpQixHQUFHLENBQUMsUUFBMkIsRUFBWSxFQUFFLENBQ2xFLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRTtJQUMxQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDdEQsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBQ3hELElBQUksVUFBVSxLQUFLLFdBQVc7UUFBRSxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbkMsQ0FBQyxDQUFDLENBQUM7QUFFTCxNQUFNLGVBQWUsR0FBRyxDQUFDLFFBQW1CLEVBQUUsT0FBZSxFQUFXLEVBQUU7SUFDeEUsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM5QyxPQUFPLElBQUksY0FBYyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUMvQyxDQUFDLENBQUM7QUFFRixNQUFNLFlBQVksR0FBRyxDQUFDLElBQXNCLEVBQVUsRUFBRTtJQUN0RCxNQUFNLGtCQUFrQixHQUN0QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBSSxjQUFjLENBQUM7SUFDM0UsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQztRQUN2RCxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQztRQUNoQyxDQUFDLENBQUMsY0FBYyxDQUFDO0lBQ25CLElBQUksYUFBYSxJQUFJLDJCQUEyQixFQUFFLENBQUM7UUFDakQsTUFBTSxJQUFJLEtBQUssQ0FDYix1RkFBdUYsQ0FDeEYsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLGFBQWEsR0FBRywyQkFBMkIsQ0FBQztBQUNyRCxDQUFDLENBQUM7QUFFRixNQUFNLGlCQUFpQixHQUFHLENBQUMsSUFBc0IsRUFBMEIsRUFBRTtJQUMzRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBZ0IsQ0FBQztJQUNyQyxJQUFJLE9BQU8sR0FBRyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2IsT0FBTyxHQUFHLElBQUksc0JBQXNCLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDekQsaUJBQWlCLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBQ0QsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQyxDQUFDO0FBRUYsTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFlLEVBQUUsS0FBYSxFQUFXLEVBQUU7SUFDL0QsTUFBTSxJQUFJLEdBQUksTUFBMkQ7UUFDdkUsRUFBRSxJQUFJLENBQUM7SUFDVCxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDO0FBQ3JDLENBQUMsQ0FBQztBQUVGLE1BQU0sSUFBSSxHQUFHLEtBQUssRUFBRSxZQUFvQixFQUFpQixFQUFFLENBQ3pELE1BQU0sSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztBQUUxRSxNQUFNLG1CQUFtQixHQUFHLEtBQUssRUFDL0IsVUFBa0MsRUFDbEMsT0FBZSxFQUNBLEVBQUU7SUFDakIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLHFCQUFxQixDQUFDO0lBQ3BELE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDWixNQUFNLE1BQU0sR0FBRyxNQUFNLFVBQVUsQ0FBQyxLQUFLLENBQ25DLHVEQUF1RCxFQUN2RCxDQUFDLE9BQU8sQ0FBQyxDQUNWLENBQUM7UUFDRixJQUFJLFlBQVksQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDO1lBQUUsT0FBTztRQUU3QyxNQUFNLFNBQVMsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hDLElBQUksU0FBUyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ25CLE1BQU0sSUFBSSxrQ0FBa0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQ0QsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLGlCQUFpQixHQUFHLEtBQUssRUFDN0IsSUFBc0IsRUFDdEIsVUFBa0MsRUFDbEMsTUFBZSxFQUNmLFFBQW1CLEVBQ0osRUFBRTtJQUNqQiw0RUFBNEU7SUFDNUUsNEVBQTRFO0lBQzVFLGdFQUFnRTtJQUNoRSxVQUFVLENBQUMsZ0JBQWdCO1FBQ3pCLE1BQU0sWUFBWSxLQUFLO1lBQ3JCLENBQUMsQ0FBQyxNQUFNO1lBQ1IsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLG9EQUFvRCxDQUFDLENBQUM7SUFFdEUsSUFBSSxDQUFDO1FBQ0gsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFBQyxPQUFPLFlBQVksRUFBRSxDQUFDO1FBQ3RCLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDOUIsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQzlCLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7WUFDbkIsTUFBTSxJQUFJLEtBQUssQ0FDYix3RUFBd0UsQ0FDekUsQ0FBQztRQUNKLENBQUM7UUFDRCwwRUFBMEU7UUFDMUUseURBQXlEO1FBQ3pELElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUFDLE9BQU8sZ0JBQWdCLEVBQUUsQ0FBQztRQUMxQixRQUFRLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDbEMsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLE1BQU0sb0JBQW9CLEdBQUcsS0FBSyxFQUNoQyxVQUFrQyxFQUNsQyxRQUEyQixFQUNaLEVBQUU7SUFDakIsS0FBSyxNQUFNLE9BQU8sSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUM5QyxNQUFNLFlBQVksR0FBRyxNQUFNLFVBQVUsQ0FBQyxLQUFLLENBQ3pDLHFEQUFxRCxFQUNyRCxDQUFDLE9BQU8sQ0FBQyxDQUNWLENBQUM7UUFDRixJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQzVDLE1BQU0sSUFBSSxLQUFLLENBQ2IsOENBQThDLE9BQU8sSUFBSSxDQUMxRCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixNQUFNLDZCQUE2QixHQUFHLEtBQUssRUFDekMsSUFBc0IsRUFDdEIsVUFBa0MsRUFDbEMsZ0JBQXlCLEVBQ3pCLGdCQUFtQyxFQUNuQixFQUFFO0lBQ2xCLE1BQU0sUUFBUSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNwQyxJQUFJLGdCQUFnQixZQUFZLGtDQUFrQyxFQUFFLENBQUM7UUFDbkUsSUFBSSxDQUFDO1lBQ0gsTUFBTSxvQkFBb0IsQ0FBQyxVQUFVLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUN6RCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDbEQsQ0FBQztRQUFDLE9BQU8sV0FBVyxFQUFFLENBQUM7WUFDckIsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMzQixNQUFNLGlCQUFpQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLHFEQUFxRDtRQUNyRCxNQUFNLGlCQUFpQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUNELE1BQU0sZUFBZSxDQUNuQixRQUFRLEVBQ1IsNkNBQTZDLENBQzlDLENBQUM7QUFDSixDQUFDLENBQUM7QUFFSyxNQUFNLG9CQUFvQixHQUFHLENBQUMsTUFBYyxFQUFVLEVBQUUsQ0FDN0Qsa0JBQWtCLE1BQU0sRUFBRSxDQUFDO0FBRGhCLFFBQUEsb0JBQW9CLHdCQUNKO0FBRXRCLE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxPQUFlLEVBQVcsRUFBRSxDQUM5RSxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDO0FBRDFDLFFBQUEsbUNBQW1DLHVDQUNPO0FBRWhELE1BQU0sa0NBQWtDLEdBQUcsS0FBSyxFQUNyRCxTQUEyQixFQUNmLEVBQUUsQ0FBQyxNQUFNLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0FBRnZELFFBQUEsa0NBQWtDLHNDQUVxQjtBQUU3RCxNQUFNLG9CQUFvQixHQUFHLENBQUMsV0FBbUIsRUFBVSxFQUFFLENBQ2xFLGtCQUFrQixXQUFXLEVBQUUsQ0FBQztBQURyQixRQUFBLG9CQUFvQix3QkFDQztBQUUzQixNQUFNLDJCQUEyQixHQUFHLEdBQVcsRUFBRSxDQUN0RCx3QkFBd0IsQ0FBQztBQURkLFFBQUEsMkJBQTJCLCtCQUNiO0FBT3BCLE1BQU0sOEJBQThCLEdBQUcsS0FBSyxFQUNqRCxTQUEwQixFQUMxQixRQUEyQixFQUNXLEVBQUU7SUFDeEMsTUFBTSxrQkFBa0IsR0FBRyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUN2RCxNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNyRCxNQUFNLGdCQUFnQixHQUFHLGtCQUFrQixDQUFDLE1BQU0sQ0FDaEQsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsY0FBYyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FDM0MsQ0FBQztJQUNGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM3QixPQUFPO1lBQ0wsR0FBRyxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxTQUFTLEVBQUU7WUFDL0IsT0FBTyxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsU0FBUztTQUMvQixDQUFDO0lBQ0osQ0FBQztJQUVELE1BQU0sSUFBSSxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQzVCLGlDQUF5QixDQUFDLGFBQWEsQ0FDcEIsQ0FBQztJQUN0QixNQUFNLGFBQWEsR0FBRyxNQUFNLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQzlFLElBQUksVUFBa0MsQ0FBQztJQUN2QyxJQUFJLENBQUM7UUFDSCxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDckQsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixhQUFhLEVBQUUsQ0FBQztRQUNoQixNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7SUFFRCxNQUFNLFVBQVUsR0FBYSxFQUFFLENBQUM7SUFDaEMsSUFBSSxDQUFDO1FBQ0gsS0FBSyxNQUFNLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sbUJBQW1CLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQy9DLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLGdCQUFnQixFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLDZCQUE2QixDQUN4QyxJQUFJLEVBQ0osVUFBVSxFQUNWLGdCQUFnQixFQUNoQixVQUFVLENBQ1gsQ0FBQztRQUNKLENBQUM7Z0JBQVMsQ0FBQztZQUNULGFBQWEsRUFBRSxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDO0lBQ0QsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELEtBQUssTUFBTSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUN2QyxjQUFjLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFDRCxJQUFJLGNBQXlDLENBQUM7SUFFOUMsT0FBTztRQUNMLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLGNBQWMsRUFBRSxTQUFTLENBQUM7UUFDckUsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUNaLGNBQWMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUM3QixNQUFNLFFBQVEsR0FBYyxFQUFFLENBQUM7Z0JBQy9CLEtBQUssTUFBTSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztvQkFDdkMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDakMsQ0FBQztnQkFDRCxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7Z0JBQ3JCLElBQUksQ0FBQztvQkFDSCxNQUFNLG9CQUFvQixDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO29CQUN6RCxRQUFRLEdBQUcsSUFBSSxDQUFDO2dCQUNsQixDQUFDO2dCQUFDLE9BQU8sV0FBVyxFQUFFLENBQUM7b0JBQ3JCLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7b0JBQzNCLE1BQU0saUJBQWlCLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ25FLENBQUM7Z0JBRUQsSUFBSSxRQUFRLEVBQUUsQ0FBQztvQkFDYixJQUFJLENBQUM7d0JBQ0gsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUNsRCxDQUFDO29CQUFDLE9BQU8sWUFBWSxFQUFFLENBQUM7d0JBQ3RCLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7d0JBQzVCLE1BQU0saUJBQWlCLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsUUFBUSxDQUFDLENBQUM7b0JBQ3BFLENBQUM7Z0JBQ0gsQ0FBQztnQkFFRCxhQUFhLEVBQUUsQ0FBQztnQkFDaEIsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ3BCLE1BQU0sZUFBZSxDQUNuQixRQUFRLEVBQ1IsMENBQTBDLENBQzNDLENBQUM7Z0JBQ0osQ0FBQztZQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDTCxPQUFPLGNBQWMsQ0FBQztRQUN4QixDQUFDO0tBQ0YsQ0FBQztBQUNKLENBQUMsQ0FBQztBQXpGVyxRQUFBLDhCQUE4QixrQ0F5RnpDO0FBRUssTUFBTSwyQkFBMkIsR0FBRyxLQUFLLEVBQzlDLFNBQTBCLEVBQzFCLFFBQTJCLEVBQzNCLFNBQTJCLEVBQ2YsRUFBRTtJQUNkLE1BQU0sa0JBQWtCLEdBQUcsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdkQsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDckQsTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQ2hELENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQzNDLENBQUM7SUFDRixJQUFJLENBQUMsZ0JBQWdCLENBQUMsTUFBTTtRQUFFLE9BQU8sTUFBTSxTQUFTLEVBQUUsQ0FBQztJQUV2RCxNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsT0FBTyxDQUM1QixpQ0FBeUIsQ0FBQyxhQUFhLENBQ3BCLENBQUM7SUFDdEIsTUFBTSxhQUFhLEdBQUcsTUFBTSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUM5RSxJQUFJLGNBQXVDLENBQUM7SUFFNUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxVQUFVLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekQsTUFBTSxVQUFVLEdBQWEsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQztZQUNILEtBQUssTUFBTSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDdkMsTUFBTSxtQkFBbUIsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7Z0JBQy9DLFVBQVUsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDM0IsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLGdCQUFnQixFQUFFLENBQUM7WUFDMUIsT0FBTyxNQUFNLDZCQUE2QixDQUN4QyxJQUFJLEVBQ0osVUFBVSxFQUNWLGdCQUFnQixFQUNoQixVQUFVLENBQ1gsQ0FBQztRQUNKLENBQUM7UUFDRCxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsY0FBYyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLEtBQUssTUFBTSxPQUFPLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUN2QyxjQUFjLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlCLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBYyxFQUFFLENBQUM7UUFDL0IsSUFBSSxNQUFxQixDQUFDO1FBQzFCLElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxNQUFNLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDbkUsQ0FBQztRQUFDLE9BQU8sY0FBYyxFQUFFLENBQUM7WUFDeEIsUUFBUSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsS0FBSyxNQUFNLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3ZDLGNBQWMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUNELElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLENBQUM7WUFDSCxNQUFNLG9CQUFvQixDQUFDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3pELFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDbEIsQ0FBQztRQUFDLE9BQU8sV0FBVyxFQUFFLENBQUM7WUFDckIsUUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUMzQixNQUFNLGlCQUFpQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLENBQUM7UUFFRCxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xELENBQUM7UUFFRCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNwQixNQUFNLGVBQWUsQ0FBQyxRQUFRLEVBQUUsb0NBQW9DLENBQUMsQ0FBQztRQUN4RSxDQUFDO1FBQ0QsT0FBTyxNQUFXLENBQUM7SUFDckIsQ0FBQztZQUFTLENBQUM7UUFDVCxLQUFLLE1BQU0sT0FBTyxJQUFJLGdCQUFnQixFQUFFLENBQUM7WUFDdkMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsQyxDQUFDO1FBQ0QsYUFBYSxFQUFFLENBQUM7SUFDbEIsQ0FBQztBQUNILENBQUMsQ0FBQztBQXZFVyxRQUFBLDJCQUEyQiwrQkF1RXRDO0FBRUssTUFBTSw4QkFBOEIsR0FBRyxLQUFLLEVBQ2pELFNBQTBCLEVBQzFCLE1BQWMsRUFDZCxTQUEyQixFQUNmLEVBQUUsQ0FDZCxNQUFNLElBQUEsbUNBQTJCLEVBQy9CLFNBQVMsRUFDVCxDQUFDLElBQUEsNEJBQW9CLEVBQUMsTUFBTSxDQUFDLENBQUMsRUFDOUIsU0FBUyxDQUNWLENBQUM7QUFUUyxRQUFBLDhCQUE4QixrQ0FTdkMifQ==
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.consumeAffiliatePromotionMutationAuthorization = exports.issueAffiliatePromotionMutationAuthorization = exports.affiliatePromotionAuthorizationInputKey = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ exports.affiliatePromotionAuthorizationInputKey = "__affiliate_promotion_mutation_authorization";
6
+ const pendingAuthorizations = new Map();
7
+ const authorizationTtlMs = 30_000;
8
+ const normalizedCodes = (codes) => codes.map((code) => code.trim().toUpperCase());
9
+ const scopesMatch = (authorization, scope) => {
10
+ const authorizedCodes = normalizedCodes(authorization.promo_codes);
11
+ const requestedCodes = normalizedCodes(scope.promo_codes);
12
+ return (authorization.cart_id === scope.cart_id &&
13
+ authorization.coupon_id === scope.coupon_id &&
14
+ authorization.promotion_id === scope.promotion_id &&
15
+ authorization.action === scope.action &&
16
+ authorizedCodes.length === requestedCodes.length &&
17
+ authorizedCodes.every((code, index) => code === requestedCodes[index]));
18
+ };
19
+ const issueAffiliatePromotionMutationAuthorization = (scope) => {
20
+ const now = Date.now();
21
+ for (const [token, authorization] of pendingAuthorizations) {
22
+ if (authorization.expires_at <= now)
23
+ pendingAuthorizations.delete(token);
24
+ }
25
+ const token = (0, node_crypto_1.randomBytes)(32).toString("base64url");
26
+ pendingAuthorizations.set(token, {
27
+ ...scope,
28
+ promo_codes: [...scope.promo_codes],
29
+ expires_at: now + authorizationTtlMs,
30
+ });
31
+ return {
32
+ token,
33
+ revoke: () => {
34
+ pendingAuthorizations.delete(token);
35
+ },
36
+ };
37
+ };
38
+ exports.issueAffiliatePromotionMutationAuthorization = issueAffiliatePromotionMutationAuthorization;
39
+ const consumeAffiliatePromotionMutationAuthorization = (token, scope) => {
40
+ if (typeof token !== "string")
41
+ return false;
42
+ const authorization = pendingAuthorizations.get(token);
43
+ pendingAuthorizations.delete(token);
44
+ return Boolean(authorization &&
45
+ authorization.expires_at > Date.now() &&
46
+ scopesMatch(authorization, scope));
47
+ };
48
+ exports.consumeAffiliatePromotionMutationAuthorization = consumeAffiliatePromotionMutationAuthorization;
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWZmaWxpYXRlLXByb21vdGlvbi1tdXRhdGlvbi1hdXRob3JpemF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL2FmZmlsaWF0ZS1wcm9tb3Rpb24tbXV0YXRpb24tYXV0aG9yaXphdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBMEM7QUFJN0IsUUFBQSx1Q0FBdUMsR0FDbEQsOENBQXVELENBQUM7QUFjMUQsTUFBTSxxQkFBcUIsR0FBRyxJQUFJLEdBQUcsRUFBZ0MsQ0FBQztBQUN0RSxNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQztBQUVsQyxNQUFNLGVBQWUsR0FBRyxDQUFDLEtBQWUsRUFBWSxFQUFFLENBQ3BELEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBRWpELE1BQU0sV0FBVyxHQUFHLENBQ2xCLGFBQW1DLEVBQ25DLEtBQW1ELEVBQzFDLEVBQUU7SUFDWCxNQUFNLGVBQWUsR0FBRyxlQUFlLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ25FLE1BQU0sY0FBYyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDMUQsT0FBTyxDQUNMLGFBQWEsQ0FBQyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU87UUFDdkMsYUFBYSxDQUFDLFNBQVMsS0FBSyxLQUFLLENBQUMsU0FBUztRQUMzQyxhQUFhLENBQUMsWUFBWSxLQUFLLEtBQUssQ0FBQyxZQUFZO1FBQ2pELGFBQWEsQ0FBQyxNQUFNLEtBQUssS0FBSyxDQUFDLE1BQU07UUFDckMsZUFBZSxDQUFDLE1BQU0sS0FBSyxjQUFjLENBQUMsTUFBTTtRQUNoRCxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxLQUFLLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUN2RSxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUssTUFBTSw0Q0FBNEMsR0FBRyxDQUMxRCxLQUFtRCxFQUNoQixFQUFFO0lBQ3JDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN2QixLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLElBQUkscUJBQXFCLEVBQUUsQ0FBQztRQUMzRCxJQUFJLGFBQWEsQ0FBQyxVQUFVLElBQUksR0FBRztZQUFFLHFCQUFxQixDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsSUFBQSx5QkFBVyxFQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFO1FBQy9CLEdBQUcsS0FBSztRQUNSLFdBQVcsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQztRQUNuQyxVQUFVLEVBQUUsR0FBRyxHQUFHLGtCQUFrQjtLQUNyQyxDQUFDLENBQUM7SUFDSCxPQUFPO1FBQ0wsS0FBSztRQUNMLE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDWCxxQkFBcUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEMsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDLENBQUM7QUFwQlcsUUFBQSw0Q0FBNEMsZ0RBb0J2RDtBQUVLLE1BQU0sOENBQThDLEdBQUcsQ0FDNUQsS0FBYyxFQUNkLEtBQW1ELEVBQzFDLEVBQUU7SUFDWCxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUU1QyxNQUFNLGFBQWEsR0FBRyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkQscUJBQXFCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3BDLE9BQU8sT0FBTyxDQUNaLGFBQWE7UUFDYixhQUFhLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDckMsV0FBVyxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FDbEMsQ0FBQztBQUNKLENBQUMsQ0FBQztBQWJXLFFBQUEsOENBQThDLGtEQWF6RCJ9
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readCartPromotions = void 0;
4
+ const readCartPromotions = (promotions) => (promotions ?? []).filter((promotion) => typeof promotion === "object" &&
5
+ promotion !== null &&
6
+ typeof promotion.id === "string" &&
7
+ promotion.id.length > 0);
8
+ exports.readCartPromotions = readCartPromotions;
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FydC1wcm9tb3Rpb25zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL2NhcnQtcHJvbW90aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFjTyxNQUFNLGtCQUFrQixHQUFHLENBQ2hDLFVBQW1DLEVBQzlCLEVBQUUsQ0FDUCxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQ3ZCLENBQUMsU0FBUyxFQUFrQixFQUFFLENBQzVCLE9BQU8sU0FBUyxLQUFLLFFBQVE7SUFDN0IsU0FBUyxLQUFLLElBQUk7SUFDbEIsT0FBTyxTQUFTLENBQUMsRUFBRSxLQUFLLFFBQVE7SUFDaEMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUMxQixDQUFBO0FBVFUsUUFBQSxrQkFBa0Isc0JBUzVCIn0=
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Money = exports.getCurrencyDecimals = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ /**
6
+ * Fallback used when a currency is unknown to Medusa's static currency table.
7
+ * Most ISO currencies use 2 minor-unit digits; the exceptions (0 for JPY, 3 for
8
+ * KWD/BHD, etc.) are resolved from `defaultCurrencies` by `getCurrencyDecimals`.
9
+ */
10
+ const DEFAULT_CURRENCY_DECIMAL_PLACES = 2;
11
+ /**
12
+ * Minor-unit digit count for a currency, e.g. EUR/USD = 2, JPY = 0, KWD = 3.
13
+ * Sourced from Medusa's installed static currency data so commission rounding
14
+ * respects each currency's precision instead of assuming two decimals.
15
+ */
16
+ const getCurrencyDecimals = (currencyCode) => utils_1.defaultCurrencies[currencyCode.toUpperCase()]?.decimal_digits ??
17
+ DEFAULT_CURRENCY_DECIMAL_PLACES;
18
+ exports.getCurrencyDecimals = getCurrencyDecimals;
19
+ /**
20
+ * Immutable value object for authoritative money arithmetic. Wraps MathBN
21
+ * (bignumber.js) so commission calculations never rely on native JS float
22
+ * operators - only the final `toRoundedNumber()` call touches a plain number.
23
+ */
24
+ class Money {
25
+ constructor(value) {
26
+ this.value = value;
27
+ }
28
+ static of(value) {
29
+ return value instanceof Money ? value : new Money(utils_1.MathBN.convert(value));
30
+ }
31
+ static zero() {
32
+ return Money.of(0);
33
+ }
34
+ static sum(values) {
35
+ return values.reduce((total, value) => total.add(value), Money.zero());
36
+ }
37
+ add(value) {
38
+ return new Money(utils_1.MathBN.add(this.value, Money.of(value).value));
39
+ }
40
+ subtract(value) {
41
+ return new Money(utils_1.MathBN.sub(this.value, Money.of(value).value));
42
+ }
43
+ multiply(value) {
44
+ return new Money(utils_1.MathBN.mult(this.value, Money.of(value).value));
45
+ }
46
+ divide(value) {
47
+ return new Money(utils_1.MathBN.div(this.value, Money.of(value).value));
48
+ }
49
+ /** `this * ratePercent / 100`, e.g. a base amount times a commission rate. */
50
+ applyPercentageRate(ratePercent) {
51
+ return this.multiply(ratePercent).divide(100);
52
+ }
53
+ negate() {
54
+ return new Money(utils_1.MathBN.mult(this.value, -1));
55
+ }
56
+ abs() {
57
+ return new Money(utils_1.MathBN.abs(this.value));
58
+ }
59
+ min(value) {
60
+ return new Money(utils_1.MathBN.min(this.value, Money.of(value).value));
61
+ }
62
+ max(value) {
63
+ return new Money(utils_1.MathBN.max(this.value, Money.of(value).value));
64
+ }
65
+ isNegative() {
66
+ return utils_1.MathBN.lt(this.value, 0);
67
+ }
68
+ isPositive() {
69
+ return utils_1.MathBN.gt(this.value, 0);
70
+ }
71
+ toRoundedNumber(decimalPlaces = DEFAULT_CURRENCY_DECIMAL_PLACES) {
72
+ // MathBN.convert's second argument is ignored when it is falsy, so a
73
+ // 0-decimal currency (e.g. JPY) would not be rounded. Round on the
74
+ // BigNumber directly instead, which honors 0.
75
+ return this.value.decimalPlaces(decimalPlaces).toNumber();
76
+ }
77
+ }
78
+ exports.Money = Money;
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uZXkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdXRpbHMvbW9uZXkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEscURBQXFFO0FBR3JFOzs7O0dBSUc7QUFDSCxNQUFNLCtCQUErQixHQUFHLENBQUMsQ0FBQTtBQUV6Qzs7OztHQUlHO0FBQ0ksTUFBTSxtQkFBbUIsR0FBRyxDQUFDLFlBQW9CLEVBQVUsRUFBRSxDQUNsRSx5QkFBaUIsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUMsRUFBRSxjQUFjO0lBQzdELCtCQUErQixDQUFBO0FBRnBCLFFBQUEsbUJBQW1CLHVCQUVDO0FBSWpDOzs7O0dBSUc7QUFDSCxNQUFhLEtBQUs7SUFDaEIsWUFBcUMsS0FBa0I7UUFBbEIsVUFBSyxHQUFMLEtBQUssQ0FBYTtJQUFHLENBQUM7SUFFM0QsTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUE2QjtRQUNyQyxPQUFPLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsY0FBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO0lBQzFFLENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSTtRQUNULE9BQU8sS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNwQixDQUFDO0lBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFrQztRQUMzQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQVEsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO0lBQy9FLENBQUM7SUFFRCxHQUFHLENBQUMsS0FBNkI7UUFDL0IsT0FBTyxJQUFJLEtBQUssQ0FBQyxjQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFL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
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertPromotionCodeAvailable = exports.promotionCodeTakenMessage = exports.findPromotionsWithCodeIgnoringCase = void 0;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ /**
6
+ * Medusa's unique index on `promotion.code` is case-sensitive, while every
7
+ * code a customer types is looked up after normalization (the storefront
8
+ * upper-cases input, the affiliate plugin canonicalizes to upper case). Two
9
+ * promotions whose codes differ only in case are therefore one code from the
10
+ * customer's point of view and must never coexist - regardless of whether
11
+ * the Admin dashboard or an affiliate coupon created them.
12
+ */
13
+ const escapeLikePattern = (value) => value.replace(/[\\%_]/g, (character) => `\\${character}`);
14
+ const findPromotionsWithCodeIgnoringCase = async (promotionService, code, options = {}) => {
15
+ const trimmed = code.trim();
16
+ if (!trimmed)
17
+ return [];
18
+ const excluded = new Set(options.except_promotion_ids ?? []);
19
+ const promotions = (await promotionService.listPromotions({ code: { $ilike: escapeLikePattern(trimmed) } }, { select: ["id", "code"], take: 10 }));
20
+ return promotions.filter((promotion) => !excluded.has(promotion.id) &&
21
+ (promotion.code ?? "").trim().toLowerCase() === trimmed.toLowerCase());
22
+ };
23
+ exports.findPromotionsWithCodeIgnoringCase = findPromotionsWithCodeIgnoringCase;
24
+ const promotionCodeTakenMessage = (code, owner) => `Der Code „${code}“ wird bereits von einer Werbeaktion verwendet („${owner.code ?? owner.id}“). Gutschein- und Promotion-Codes müssen sich auch ohne Beachtung der Groß-/Kleinschreibung unterscheiden.`;
25
+ exports.promotionCodeTakenMessage = promotionCodeTakenMessage;
26
+ const assertPromotionCodeAvailable = async (container, code, options = {}) => {
27
+ const promotionService = container.resolve(utils_1.Modules.PROMOTION);
28
+ const [owner] = await (0, exports.findPromotionsWithCodeIgnoringCase)(promotionService, code, options);
29
+ if (owner) {
30
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.DUPLICATE_ERROR, (0, exports.promotionCodeTakenMessage)(code, owner));
31
+ }
32
+ };
33
+ exports.assertPromotionCodeAvailable = assertPromotionCodeAvailable;
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvbW90aW9uLWNvZGUtYXZhaWxhYmlsaXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3V0aWxzL3Byb21vdGlvbi1jb2RlLWF2YWlsYWJpbGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFJQSxxREFBZ0U7QUFTaEU7Ozs7Ozs7R0FPRztBQUNILE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRSxDQUNsRCxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsS0FBSyxTQUFTLEVBQUUsQ0FBQyxDQUFBO0FBRXBELE1BQU0sa0NBQWtDLEdBQUcsS0FBSyxFQUNyRCxnQkFBcUMsRUFDckMsSUFBWSxFQUNaLFVBQXdELEVBQUUsRUFDM0IsRUFBRTtJQUNqQyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDM0IsSUFBSSxDQUFDLE9BQU87UUFBRSxPQUFPLEVBQUUsQ0FBQTtJQUN2QixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsb0JBQW9CLElBQUksRUFBRSxDQUFDLENBQUE7SUFDNUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxNQUFNLGdCQUFnQixDQUFDLGNBQWMsQ0FDdkQsRUFBRSxJQUFJLEVBQUUsRUFBRSxNQUFNLEVBQUUsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxFQUNoRCxFQUFFLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQ3JDLENBQXlCLENBQUE7SUFDMUIsT0FBTyxVQUFVLENBQUMsTUFBTSxDQUN0QixDQUFDLFNBQVMsRUFBRSxFQUFFLENBQ1osQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDM0IsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxLQUFLLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FDeEUsQ0FBQTtBQUNILENBQUMsQ0FBQTtBQWpCWSxRQUFBLGtDQUFrQyxzQ0FpQjlDO0FBRU0sTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxJQUFZLEVBQ1osS0FBeUIsRUFDakIsRUFBRSxDQUNWLGFBQWEsSUFBSSxvREFDZixLQUFLLENBQUMsSUFBSSxJQUFJLEtBQUssQ0FBQyxFQUN0Qiw2R0FBNkcsQ0FBQTtBQU5sRyxRQUFBLHlCQUF5Qiw2QkFNeUU7QUFFeEcsTUFBTSw0QkFBNEIsR0FBRyxLQUFLLEVBQy9DLFNBQTBCLEVBQzFCLElBQVksRUFDWixVQUF3RCxFQUFFLEVBQzNDLEVBQUU7SUFDakIsTUFBTSxnQkFBZ0IsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUN4QyxlQUFPLENBQUMsU0FBUyxDQUNTLENBQUE7SUFDNUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLE1BQU0sSUFBQSwwQ0FBa0MsRUFDdEQsZ0JBQWdCLEVBQ2hCLElBQUksRUFDSixPQUFPLENBQ1IsQ0FBQTtJQUNELElBQUksS0FBSyxFQUFFLENBQUM7UUFDVixNQUFNLElBQUksbUJBQVcsQ0FDbkIsbUJBQVcsQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUNqQyxJQUFBLGlDQUF5QixFQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FDdkMsQ0FBQTtJQUNILENBQUM7QUFDSCxDQUFDLENBQUE7QUFuQlksUUFBQSw0QkFBNEIsZ0NBbUJ4QyJ9
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireLoginForRegisteredCheckoutEmail = exports.requireLoginForRegisteredPaymentEmail = exports.requireLoginForRegisteredCartEmail = exports.CUSTOMER_LOGIN_REQUIRED_MESSAGE = void 0;
4
+ exports.isCheckoutBlockedForRegisteredEmail = isCheckoutBlockedForRegisteredEmail;
5
+ exports.escapeLikePattern = escapeLikePattern;
6
+ exports.assertEmailAllowedForActor = assertEmailAllowedForActor;
7
+ const utils_1 = require("@medusajs/framework/utils");
8
+ exports.CUSTOMER_LOGIN_REQUIRED_MESSAGE = "Für diese E-Mail-Adresse besteht bereits ein Kundenkonto. Bitte melde dich an, um die Bestellung abzuschließen.";
9
+ function isCheckoutBlockedForRegisteredEmail(input) {
10
+ return (input.registeredCustomerIds.length > 0 &&
11
+ !input.registeredCustomerIds.includes(input.actorId ?? ""));
12
+ }
13
+ // ILIKE gives case-insensitive matching (Medusa does not normalize stored
14
+ // emails), but treats `%` and `_` as wildcards - and `_` is common in real
15
+ // addresses. Unescaped, "a_b@x.de" would match "aXb@x.de".
16
+ function escapeLikePattern(value) {
17
+ return value.replace(/[\\%_]/g, "\\$&");
18
+ }
19
+ /**
20
+ * An email that belongs to a registered account may only be used for a
21
+ * checkout by a request authenticated as that account. Medusa core would
22
+ * otherwise link an anonymous cart to whichever customer record shares the
23
+ * email - the account itself included - and file the order, plus any affiliate
24
+ * own-order discount or commission tied to it, under that identity with
25
+ * nothing but the typed-in address as proof.
26
+ *
27
+ * The request's auth context is the only usable signal: cart.customer_id is
28
+ * set by that same core linking and so never proves a login. The storefront
29
+ * establishes a Medusa browser session at login precisely so that its
30
+ * browser-side cart and payment calls carry this identity.
31
+ */
32
+ async function assertEmailAllowedForActor(container, email, actorId) {
33
+ // Same deliberately provider-agnostic normalization as normalizeAffiliateEmail.
34
+ const normalizedEmail = email?.trim().toLowerCase();
35
+ if (!normalizedEmail) {
36
+ return;
37
+ }
38
+ const customerService = container.resolve(utils_1.Modules.CUSTOMER);
39
+ const registeredCustomers = await customerService.listCustomers({ email: { $ilike: escapeLikePattern(normalizedEmail) }, has_account: true }, { select: ["id"] });
40
+ if (isCheckoutBlockedForRegisteredEmail({
41
+ registeredCustomerIds: registeredCustomers.map(({ id }) => id),
42
+ actorId,
43
+ })) {
44
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_ALLOWED, exports.CUSTOMER_LOGIN_REQUIRED_MESSAGE);
45
+ }
46
+ }
47
+ async function loadCartEmail(container, cartId) {
48
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
49
+ const { data } = await query.graph({
50
+ entity: "cart",
51
+ fields: ["id", "email"],
52
+ filters: { id: cartId },
53
+ });
54
+ return data[0]?.email;
55
+ }
56
+ /**
57
+ * First gate, on setting the email itself (cart create and update): refusing
58
+ * here keeps a cart with someone else's account email from ever existing, and
59
+ * puts the login prompt at the address step - before any payment details.
60
+ * Runs ahead of the core body validation, so the raw body is read defensively.
61
+ */
62
+ const requireLoginForRegisteredCartEmail = async (req, _res, next) => {
63
+ const email = req.body?.email;
64
+ if (typeof email === "string") {
65
+ await assertEmailAllowedForActor(req.scope, email, req.auth_context?.actor_id);
66
+ }
67
+ next();
68
+ };
69
+ exports.requireLoginForRegisteredCartEmail = requireLoginForRegisteredCartEmail;
70
+ /**
71
+ * Second gate. Creating a payment session is what hands the browser a Stripe
72
+ * client secret, and Stripe charges on confirmPayment - before completeCart
73
+ * runs at all. Covers carts that got their email past the first gate (set
74
+ * before it existed, or by a server-side backfill).
75
+ */
76
+ const requireLoginForRegisteredPaymentEmail = async (req, _res, next) => {
77
+ const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
78
+ const { data } = await query.graph({
79
+ entity: "payment_collection",
80
+ fields: ["id", "cart.email"],
81
+ filters: { id: req.params.id },
82
+ });
83
+ const cart = data[0]?.cart;
84
+ if (cart) {
85
+ await assertEmailAllowedForActor(req.scope, cart.email, req.auth_context?.actor_id);
86
+ }
87
+ next();
88
+ };
89
+ exports.requireLoginForRegisteredPaymentEmail = requireLoginForRegisteredPaymentEmail;
90
+ /**
91
+ * Backstop on completion, for a cart whose payment session was created before
92
+ * the gates existed. By this point a payment may already be authorized; the
93
+ * two gates above exist so that this one is never the first to refuse.
94
+ */
95
+ const requireLoginForRegisteredCheckoutEmail = async (req, _res, next) => {
96
+ const email = await loadCartEmail(req.scope, req.params.id);
97
+ await assertEmailAllowedForActor(req.scope, email, req.auth_context?.actor_id);
98
+ next();
99
+ };
100
+ exports.requireLoginForRegisteredCheckoutEmail = requireLoginForRegisteredCheckoutEmail;
101
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0ZXJlZC1lbWFpbC1jaGVja291dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy91dGlscy9yZWdpc3RlcmVkLWVtYWlsLWNoZWNrb3V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQXNCQSxrRkFRQztBQUtELDhDQUVDO0FBZUQsZ0VBK0JDO0FBMUVELHFEQUlrQztBQUVyQixRQUFBLCtCQUErQixHQUMxQyxpSEFBaUgsQ0FBQTtBQU1uSCxTQUFnQixtQ0FBbUMsQ0FBQyxLQUduRDtJQUNDLE9BQU8sQ0FDTCxLQUFLLENBQUMscUJBQXFCLENBQUMsTUFBTSxHQUFHLENBQUM7UUFDdEMsQ0FBQyxLQUFLLENBQUMscUJBQXFCLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQzNELENBQUE7QUFDSCxDQUFDO0FBRUQsMEVBQTBFO0FBQzFFLDJFQUEyRTtBQUMzRSwyREFBMkQ7QUFDM0QsU0FBZ0IsaUJBQWlCLENBQUMsS0FBYTtJQUM3QyxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQ3pDLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSSxLQUFLLFVBQVUsMEJBQTBCLENBQzlDLFNBQTBCLEVBQzFCLEtBQWdDLEVBQ2hDLE9BQWtDO0lBRWxDLGdGQUFnRjtJQUNoRixNQUFNLGVBQWUsR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUE7SUFFbkQsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3JCLE9BQU07SUFDUixDQUFDO0lBRUQsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FDdkMsZUFBTyxDQUFDLFFBQVEsQ0FDUyxDQUFBO0lBQzNCLE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxlQUFlLENBQUMsYUFBYSxDQUM3RCxFQUFFLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFB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
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveAffiliateService = void 0;
4
+ const affiliate_1 = require("../modules/affiliate");
5
+ const resolveAffiliateService = (container) => container.resolve(affiliate_1.AFFILIATE_MODULE);
6
+ exports.resolveAffiliateService = resolveAffiliateService;
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS1zZXJ2aWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy91dGlscy9yZXNvbHZlLXNlcnZpY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLG9EQUF1RDtBQUdoRCxNQUFNLHVCQUF1QixHQUFHLENBQ3JDLFNBQTBCLEVBQ0YsRUFBRSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsNEJBQWdCLENBQUMsQ0FBQTtBQUZuRCxRQUFBLHVCQUF1QiwyQkFFNEIifQ==