order-management 0.0.27 → 0.0.28
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.
- package/.medusa/server/src/admin/index.js +402 -427
- package/.medusa/server/src/admin/index.mjs +402 -427
- package/.medusa/server/src/api/admin/swaps/route.js +9 -1
- package/.medusa/server/src/subscribers/exchange-created.js +196 -183
- package/.medusa/server/src/workflows/steps/swap/create-medusa-exchange-step.js +41 -1
- package/package.json +1 -1
- package/.medusa/server/src/api/admin/swaps/[id]/prepare-exchange/route.js +0 -84
|
@@ -26,6 +26,14 @@ const GET = async (req, res) => {
|
|
|
26
26
|
skip: offset,
|
|
27
27
|
});
|
|
28
28
|
const swapArray = Array.isArray(swaps) ? swaps : swaps ? [swaps] : [];
|
|
29
|
+
// Sort by created_at descending (latest first)
|
|
30
|
+
swapArray.sort((a, b) => {
|
|
31
|
+
const aData = a;
|
|
32
|
+
const bData = b;
|
|
33
|
+
const aDate = aData.created_at ? new Date(aData.created_at).getTime() : 0;
|
|
34
|
+
const bDate = bData.created_at ? new Date(bData.created_at).getTime() : 0;
|
|
35
|
+
return bDate - aDate; // Descending order (newest first)
|
|
36
|
+
});
|
|
29
37
|
res.json({
|
|
30
38
|
swaps: swapArray,
|
|
31
39
|
count: swapArray.length,
|
|
@@ -42,4 +50,4 @@ const GET = async (req, res) => {
|
|
|
42
50
|
}
|
|
43
51
|
};
|
|
44
52
|
exports.GET = GET;
|
|
45
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3N3YXBzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLGdEQUFtRDtBQUc1QyxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQWtCLEVBQ2xCLEdBQW1CLEVBQ0osRUFBRTtJQUNqQixJQUFJLENBQUM7UUFDSCxNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBYyxrQkFBVyxDQUFDLENBQUE7UUFFL0QsdUJBQXVCO1FBQ3ZCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBNEIsQ0FBQTtRQUNyRCxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQThCLENBQUE7UUFDeEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFpQyxDQUFBO1FBQzlELE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtRQUM1RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBRTlFLE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUE7UUFDM0MsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1FBQ3pCLENBQUM7UUFDRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osT0FBTyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUE7UUFDNUIsQ0FBQztRQUNELElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQTtRQUNsQyxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxXQUFXLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRTtZQUNqRCxJQUFJLEVBQUUsS0FBSztZQUNYLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQyxDQUFBO1FBRUYsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtRQUVyRSwrQ0FBK0M7UUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQVUsRUFBRSxDQUFVLEVBQUUsRUFBRTtZQUN4QyxNQUFNLEtBQUssR0FBRyxDQUFtQyxDQUFBO1lBQ2pELE1BQU0sS0FBSyxHQUFHLENBQW1DLENBQUE7WUFDakQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDekUsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDekUsT0FBTyxLQUFLLEdBQUcsS0FBSyxDQUFBLENBQUMsa0NBQWtDO1FBQ3pELENBQUMsQ0FBQyxDQUFBO1FBRUYsR0FBRyxDQUFDLElBQUksQ0FBQztZQUNQLEtBQUssRUFBRSxTQUFTO1lBQ2hCLEtBQUssRUFBRSxTQUFTLENBQUMsTUFBTTtZQUN2QixLQUFLO1lBQ0wsTUFBTTtTQUNQLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxZQUFZLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFBO1FBQzdFLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25CLE9BQU8sRUFBRSwwQkFBMEI7WUFDbkMsS0FBSyxFQUFFLFlBQVk7U0FDcEIsQ0FBQyxDQUFBO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQTtBQXREWSxRQUFBLEdBQUcsT0FzRGYifQ==
|
|
@@ -7,201 +7,214 @@ const swap_1 = require("../modules/swap");
|
|
|
7
7
|
/**
|
|
8
8
|
* Subscriber handler for exchange created events
|
|
9
9
|
* Automatically links exchanges created by admin to approved swaps
|
|
10
|
-
*
|
|
11
|
-
* When an exchange is created, this subscriber:
|
|
12
|
-
* 1. Finds the swap with matching order_id and status "approved" without exchange_id
|
|
13
|
-
* 2. Links the exchange to the swap by updating exchange_id field
|
|
14
|
-
* 3. Stores linking timestamp in metadata
|
|
15
10
|
*/
|
|
16
|
-
async function exchangeCreatedHandler({ event
|
|
11
|
+
async function exchangeCreatedHandler({ event, container, }) {
|
|
12
|
+
const logger = container.resolve("logger");
|
|
17
13
|
const startTime = Date.now();
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
14
|
+
const eventName = event.name || "exchange.created";
|
|
15
|
+
const data = event.data || {};
|
|
16
|
+
logger.info(`[Exchange Created Subscriber] ⚡ Event received: ${eventName}`);
|
|
17
|
+
logger.info(`[Exchange Created Subscriber] Event data: ${JSON.stringify(data, null, 2)}`);
|
|
18
|
+
// Handle both event data formats:
|
|
19
|
+
// - Our custom event: { id, order_id, return_id, swap_id }
|
|
20
|
+
// - Medusa's event: { exchange_id, order_id }
|
|
21
|
+
const exchangeId = data.id || data.exchange_id;
|
|
22
|
+
const orderId = data.order_id;
|
|
23
|
+
if (!exchangeId) {
|
|
24
|
+
logger.error("[Exchange Created Subscriber] No exchange ID found in event data");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!orderId) {
|
|
28
|
+
logger.debug("[Exchange Created Subscriber] No order_id in exchange, skipping link");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
// Execute with retry logic
|
|
32
|
+
await executeWithRetry(async () => await processExchangeLinking(exchangeId, orderId, container, logger), logger, exchangeId);
|
|
33
|
+
const duration = Date.now() - startTime;
|
|
34
|
+
logger.info(`[Exchange Created Subscriber] Completed in ${duration}ms`);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Main processing logic with proper error handling
|
|
38
|
+
*/
|
|
39
|
+
async function processExchangeLinking(exchangeId, orderId, container, logger) {
|
|
40
|
+
const swapService = container.resolve(swap_1.SWAP_MODULE);
|
|
41
|
+
const remoteQuery = container.resolve(utils_1.ContainerRegistrationKeys.REMOTE_QUERY);
|
|
42
|
+
// 1. Validate exchange exists in Medusa
|
|
43
|
+
const exchange = await validateExchangeExists(exchangeId, remoteQuery, logger);
|
|
44
|
+
if (!exchange) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// 2. Find eligible swap for this order
|
|
48
|
+
const swap = await findEligibleSwap(orderId, swapService, logger);
|
|
49
|
+
if (!swap) {
|
|
50
|
+
logger.debug(`[Exchange Created Subscriber] No unlinked swap found for order ${orderId}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// 3. Update swap with exchange linkage
|
|
54
|
+
await linkExchangeToSwap(swap, exchangeId, swapService, logger);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate exchange exists using remote query
|
|
58
|
+
*/
|
|
59
|
+
async function validateExchangeExists(exchangeId, remoteQuery, logger) {
|
|
60
|
+
try {
|
|
61
|
+
const exchangeQuery = (0, utils_1.remoteQueryObjectFromString)({
|
|
62
|
+
entryPoint: "exchange",
|
|
63
|
+
fields: ["id", "order_id", "status"],
|
|
64
|
+
filters: { id: exchangeId },
|
|
65
|
+
});
|
|
66
|
+
const [exchange] = await remoteQuery(exchangeQuery);
|
|
67
|
+
if (!exchange) {
|
|
68
|
+
logger.warn(`[Exchange Created Subscriber] Exchange ${exchangeId} not found`);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return exchange;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
logger.warn(`[Exchange Created Subscriber] Exchange validation failed: ${error.message}`);
|
|
75
|
+
// Continue anyway - exchange might be valid but query failed
|
|
76
|
+
return { id: exchangeId }; // Return minimal object to continue
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Find eligible swap for linking
|
|
81
|
+
*/
|
|
82
|
+
async function findEligibleSwap(orderId, swapService, logger) {
|
|
83
|
+
try {
|
|
84
|
+
// Get all swaps for this order and filter in memory
|
|
85
|
+
// This is more reliable than filtering by exchange_id: null in the query
|
|
86
|
+
const allSwaps = await swapService.listSwaps({ order_id: orderId }, { take: 100 } // Get up to 100 swaps to find unlinked ones
|
|
87
|
+
);
|
|
88
|
+
const swapsArray = Array.isArray(allSwaps) ? allSwaps : allSwaps ? [allSwaps] : [];
|
|
89
|
+
logger.info(`[Exchange Created Subscriber] Found ${swapsArray.length} swap(s) for order ${orderId}`);
|
|
90
|
+
// Filter for unlinked swaps (exchange_id is null or undefined)
|
|
91
|
+
const unlinkedSwaps = swapsArray.filter((swap) => {
|
|
92
|
+
const exchangeId = swap.exchange_id;
|
|
93
|
+
return !exchangeId || exchangeId === null || exchangeId === "";
|
|
94
|
+
});
|
|
95
|
+
logger.info(`[Exchange Created Subscriber] Found ${unlinkedSwaps.length} unlinked swap(s) for order ${orderId}`);
|
|
96
|
+
if (unlinkedSwaps.length === 0) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
// Priority 1: Approved swaps without exchange_id
|
|
100
|
+
const approvedSwaps = unlinkedSwaps.filter((swap) => swap.status === "approved");
|
|
101
|
+
if (approvedSwaps.length > 0) {
|
|
102
|
+
logger.info(`[Exchange Created Subscriber] Found ${approvedSwaps.length} approved unlinked swap(s), using first one`);
|
|
103
|
+
return approvedSwaps[0];
|
|
104
|
+
}
|
|
105
|
+
// Priority 2: Requested swaps with pending_exchange_creation flag
|
|
106
|
+
const requestedSwaps = unlinkedSwaps.filter((swap) => {
|
|
107
|
+
if (swap.status !== "requested")
|
|
108
|
+
return false;
|
|
109
|
+
const metadata = swap.metadata || {};
|
|
110
|
+
return metadata.pending_exchange_creation === true;
|
|
111
|
+
});
|
|
112
|
+
if (requestedSwaps.length > 0) {
|
|
113
|
+
logger.info(`[Exchange Created Subscriber] Found ${requestedSwaps.length} requested swap(s) with pending_exchange_creation flag, using first one`);
|
|
114
|
+
return requestedSwaps[0];
|
|
115
|
+
}
|
|
116
|
+
// Priority 3: Any requested swap (fallback)
|
|
117
|
+
const anyRequestedSwaps = unlinkedSwaps.filter((swap) => swap.status === "requested");
|
|
118
|
+
if (anyRequestedSwaps.length > 0) {
|
|
119
|
+
logger.info(`[Exchange Created Subscriber] Found ${anyRequestedSwaps.length} requested unlinked swap(s), using first one`);
|
|
120
|
+
return anyRequestedSwaps[0];
|
|
121
|
+
}
|
|
122
|
+
logger.debug(`[Exchange Created Subscriber] No eligible unlinked swap found for order ${orderId}`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
logger.error(`[Exchange Created Subscriber] Error finding swap: ${error instanceof Error ? error.message : String(error)}`);
|
|
127
|
+
throw error; // Re-throw to trigger retry
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Link exchange to swap with metadata updates
|
|
132
|
+
*/
|
|
133
|
+
async function linkExchangeToSwap(swap, exchangeId, swapService, logger) {
|
|
134
|
+
const swapId = swap.id;
|
|
135
|
+
const swapStatus = swap.status;
|
|
136
|
+
const metadata = swap.metadata || {};
|
|
137
|
+
logger.info(`[Exchange Created Subscriber] Linking exchange ${exchangeId} to swap ${swapId} (current status: ${swapStatus})`);
|
|
138
|
+
const pendingExchangeCreation = metadata.pending_exchange_creation === true;
|
|
139
|
+
const shouldApprove = swapStatus === "requested" && pendingExchangeCreation;
|
|
140
|
+
logger.info(`[Exchange Created Subscriber] Swap ${swapId} - pending_exchange_creation: ${pendingExchangeCreation}, shouldApprove: ${shouldApprove}`);
|
|
141
|
+
const linkingHistory = metadata.exchange_linking_history || [];
|
|
142
|
+
const statusHistory = metadata.status_history || [];
|
|
143
|
+
const updateData = {
|
|
144
|
+
exchange_id: exchangeId,
|
|
145
|
+
metadata: {
|
|
146
|
+
...metadata,
|
|
147
|
+
exchange_linking_history: [
|
|
148
|
+
...linkingHistory,
|
|
149
|
+
{
|
|
129
150
|
exchange_id: exchangeId,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
exchange_linking_history: [
|
|
134
|
-
...linkingHistory,
|
|
135
|
-
{
|
|
136
|
-
exchange_id: exchangeId,
|
|
137
|
-
linked_at: new Date().toISOString(),
|
|
138
|
-
linked_by: "exchange_created_subscriber",
|
|
139
|
-
auto_approved: shouldApprove,
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
exchange_linked_at: new Date().toISOString(),
|
|
143
|
-
pending_exchange_creation: false,
|
|
144
|
-
...(shouldApprove ? {
|
|
145
|
-
status_history: [
|
|
146
|
-
...statusHistory,
|
|
147
|
-
{
|
|
148
|
-
status: "approved",
|
|
149
|
-
timestamp: new Date().toISOString(),
|
|
150
|
-
auto_approved: true,
|
|
151
|
-
approved_via: "exchange_created_subscriber",
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
} : {}),
|
|
155
|
-
},
|
|
151
|
+
linked_at: new Date().toISOString(),
|
|
152
|
+
linked_by: "exchange_created_subscriber",
|
|
153
|
+
auto_approved: shouldApprove,
|
|
156
154
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
],
|
|
156
|
+
exchange_linked_at: new Date().toISOString(),
|
|
157
|
+
pending_exchange_creation: false,
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
// Update status if needed
|
|
161
|
+
if (shouldApprove) {
|
|
162
|
+
updateData.status = "approved";
|
|
163
|
+
updateData.metadata.status_history = [
|
|
164
|
+
...statusHistory,
|
|
165
|
+
{
|
|
166
|
+
status: "approved",
|
|
167
|
+
timestamp: new Date().toISOString(),
|
|
168
|
+
auto_approved: true,
|
|
169
|
+
approved_via: "exchange_created_subscriber",
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
logger.info(`[Exchange Created Subscriber] Will update swap ${swapId} status from "${swapStatus}" to "approved"`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
logger.info(`[Exchange Created Subscriber] Swap ${swapId} status will remain "${swapStatus}" (not auto-approving)`);
|
|
176
|
+
}
|
|
177
|
+
logger.info(`[Exchange Created Subscriber] Updating swap ${swapId} with exchange_id: ${exchangeId}`);
|
|
178
|
+
const updatedSwap = await swapService.updateSwaps({
|
|
179
|
+
selector: { id: swapId },
|
|
180
|
+
data: updateData,
|
|
181
|
+
});
|
|
182
|
+
const finalSwap = Array.isArray(updatedSwap) ? updatedSwap[0] : updatedSwap;
|
|
183
|
+
const finalStatus = finalSwap?.status || "unknown";
|
|
184
|
+
logger.info(`[Exchange Created Subscriber] ✅ Successfully linked exchange ${exchangeId} to swap ${swapId}. Final status: ${finalStatus}`);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Retry execution with exponential backoff
|
|
188
|
+
*/
|
|
189
|
+
async function executeWithRetry(operation, logger, exchangeId, maxRetries = 3, baseDelay = 1000) {
|
|
190
|
+
let lastError;
|
|
191
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
192
|
+
try {
|
|
193
|
+
return await operation();
|
|
164
194
|
}
|
|
165
195
|
catch (error) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const delay = retryDelay * Math.pow(2, retryCount - 1);
|
|
172
|
-
console.warn(`[Exchange Created Subscriber] Retry ${retryCount}/${maxRetries} after ${delay}ms:`, errorMessage);
|
|
173
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
174
|
-
return executeWithRetry();
|
|
196
|
+
lastError = error;
|
|
197
|
+
if (attempt < maxRetries - 1) {
|
|
198
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
199
|
+
logger.warn(`[Exchange Created Subscriber] Attempt ${attempt + 1}/${maxRetries} failed for exchange ${exchangeId}, retrying in ${delay}ms:`, error.message);
|
|
200
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
175
201
|
}
|
|
176
|
-
console.error("[Exchange Created Subscriber] Error linking exchange to swap (max retries exceeded):", {
|
|
177
|
-
error: errorMessage,
|
|
178
|
-
stack: errorStack,
|
|
179
|
-
retry_count: retryCount,
|
|
180
|
-
exchange_id: data.id,
|
|
181
|
-
order_id: data.order_id,
|
|
182
|
-
});
|
|
183
|
-
// Don't throw - subscriber errors shouldn't break the exchange flow
|
|
184
202
|
}
|
|
185
|
-
}
|
|
186
|
-
|
|
203
|
+
}
|
|
204
|
+
logger.error(`[Exchange Created Subscriber] All ${maxRetries} attempts failed for exchange ${exchangeId}:`, lastError?.message || "Unknown error");
|
|
205
|
+
throw lastError;
|
|
206
|
+
// Don't throw - we don't want to break the exchange flow
|
|
187
207
|
}
|
|
188
208
|
/**
|
|
189
209
|
* Subscriber configuration
|
|
190
210
|
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* This subscriber listens for exchange creation events in Medusa.
|
|
194
|
-
* When an exchange is created, it automatically links it to an approved swap
|
|
195
|
-
* if one exists for the same order.
|
|
196
|
-
*
|
|
197
|
-
* Event Data Structure Expected:
|
|
198
|
-
* {
|
|
199
|
-
* id: string (exchange ID)
|
|
200
|
-
* order_id?: string (order ID)
|
|
201
|
-
* [key: string]: unknown (other exchange fields)
|
|
202
|
-
* }
|
|
211
|
+
* Listen to exchange.created event emitted by create-medusa-exchange-step
|
|
212
|
+
* Also listen to order.exchange_created as fallback in case Medusa emits that instead
|
|
203
213
|
*/
|
|
204
214
|
exports.config = {
|
|
205
|
-
event:
|
|
215
|
+
event: [
|
|
216
|
+
"exchange.created",
|
|
217
|
+
"order.exchange_created",
|
|
218
|
+
],
|
|
206
219
|
};
|
|
207
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
220
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhjaGFuZ2UtY3JlYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9leGNoYW5nZS1jcmVhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSx5Q0FzQ0M7QUF0REQscURBQWtHO0FBRWxHLDBDQUE2QztBQVU3Qzs7O0dBR0c7QUFDWSxLQUFLLFVBQVUsc0JBQXNCLENBQUMsRUFDbkQsS0FBSyxFQUNMLFNBQVMsR0FDZ0M7SUFDekMsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUMxQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUE7SUFFNUIsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLElBQUksSUFBSSxrQkFBa0IsQ0FBQTtJQUNsRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQTtJQUU3QixNQUFNLENBQUMsSUFBSSxDQUFDLG1EQUFtRCxTQUFTLEVBQUUsQ0FBQyxDQUFBO0lBQzNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsNkNBQTZDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7SUFFekYsa0NBQWtDO0lBQ2xDLDJEQUEyRDtJQUMzRCw4Q0FBOEM7SUFDOUMsTUFBTSxVQUFVLEdBQUksSUFBd0IsQ0FBQyxFQUFFLElBQUssSUFBaUMsQ0FBQyxXQUFXLENBQUE7SUFDakcsTUFBTSxPQUFPLEdBQUksSUFBOEIsQ0FBQyxRQUFRLENBQUE7SUFFeEQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sQ0FBQyxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQTtRQUNoRixPQUFNO0lBQ1IsQ0FBQztJQUVELElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsc0VBQXNFLENBQUMsQ0FBQTtRQUNwRixPQUFNO0lBQ1IsQ0FBQztJQUVELDJCQUEyQjtJQUMzQixNQUFNLGdCQUFnQixDQUNwQixLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sc0JBQXNCLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQ2hGLE1BQU0sRUFDTixVQUFVLENBQ1gsQ0FBQTtJQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUE7SUFDdkMsTUFBTSxDQUFDLElBQUksQ0FBQyw4Q0FBOEMsUUFBUSxJQUFJLENBQUMsQ0FBQTtBQUN6RSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsc0JBQXNCLENBQ25DLFVBQWtCLEVBQ2xCLE9BQWUsRUFDZixTQUF3QixFQUN4QixNQUFXO0lBRVgsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBYyxrQkFBVyxDQUFDLENBQUE7SUFDL0QsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBc0IsaUNBQXlCLENBQUMsWUFBWSxDQUFDLENBQUE7SUFFbEcsd0NBQXdDO0lBQ3hDLE1BQU0sUUFBUSxHQUFHLE1BQU0sc0JBQXNCLENBQUMsVUFBVSxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUM5RSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDZCxPQUFNO0lBQ1IsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxNQUFNLElBQUksR0FBRyxNQUFNLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDakUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1YsTUFBTSxDQUFDLEtBQUssQ0FBQyxrRUFBa0UsT0FBTyxFQUFFLENBQUMsQ0FBQTtRQUN6RixPQUFNO0lBQ1IsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxNQUFNLGtCQUFrQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBQ2pFLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxzQkFBc0IsQ0FDbkMsVUFBa0IsRUFDbEIsV0FBZ0MsRUFDaEMsTUFBVztJQUVYLElBQUksQ0FBQztRQUNILE1BQU0sYUFBYSxHQUFHLElBQUEsbUNBQTJCLEVBQUM7WUFDaEQsVUFBVSxFQUFFLFVBQVU7WUFDdEIsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUM7WUFDcEMsT0FBTyxFQUFFLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRTtTQUM1QixDQUFDLENBQUE7UUFFRixNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBTSxXQUFXLENBQUMsYUFBYSxDQUFDLENBQUE7UUFFbkQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsTUFBTSxDQUFDLElBQUksQ0FBQywwQ0FBMEMsVUFBVSxZQUFZLENBQUMsQ0FBQTtZQUM3RSxPQUFPLElBQUksQ0FBQTtRQUNiLENBQUM7UUFFRCxPQUFPLFFBQVEsQ0FBQTtJQUNqQixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sQ0FBQyxJQUFJLENBQUMsNkRBQTZELEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBQ3pGLDZEQUE2RDtRQUM3RCxPQUFPLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxDQUFBLENBQUMsb0NBQW9DO0lBQ2hFLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsZ0JBQWdCLENBQzdCLE9BQWUsRUFDZixXQUF3QixFQUN4QixNQUFXO0lBRVgsSUFBSSxDQUFDO1FBQ0gsb0RBQW9EO1FBQ3BELHlFQUF5RTtRQUN6RSxNQUFNLFFBQVEsR0FBRyxNQUFNLFdBQVcsQ0FBQyxTQUFTLENBQzFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxFQUNyQixFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsQ0FBQyw0Q0FBNEM7U0FDM0QsQ0FBQTtRQUVELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7UUFFbEYsTUFBTSxDQUFDLElBQUksQ0FBQyx1Q0FBdUMsVUFBVSxDQUFDLE1BQU0sc0JBQXNCLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFFcEcsK0RBQStEO1FBQy9ELE1BQU0sYUFBYSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRTtZQUNwRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFBO1lBQ25DLE9BQU8sQ0FBQyxVQUFVLElBQUksVUFBVSxLQUFLLElBQUksSUFBSSxVQUFVLEtBQUssRUFBRSxDQUFBO1FBQ2hFLENBQUMsQ0FBQyxDQUFBO1FBRUYsTUFBTSxDQUFDLElBQUksQ0FBQyx1Q0FBdUMsYUFBYSxDQUFDLE1BQU0sK0JBQStCLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFFaEgsSUFBSSxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQy9CLE9BQU8sSUFBSSxDQUFBO1FBQ2IsQ0FBQztRQUVELGlEQUFpRDtRQUNqRCxNQUFNLGFBQWEsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFVBQVUsQ0FBQyxDQUFBO1FBQ3JGLElBQUksYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3QixNQUFNLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxhQUFhLENBQUMsTUFBTSw2Q0FBNkMsQ0FBQyxDQUFBO1lBQ3JILE9BQU8sYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3pCLENBQUM7UUFFRCxrRUFBa0U7UUFDbEUsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQVMsRUFBRSxFQUFFO1lBQ3hELElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxXQUFXO2dCQUFFLE9BQU8sS0FBSyxDQUFBO1lBQzdDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFBO1lBQ3BDLE9BQU8sUUFBUSxDQUFDLHlCQUF5QixLQUFLLElBQUksQ0FBQTtRQUNwRCxDQUFDLENBQUMsQ0FBQTtRQUVGLElBQUksY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxjQUFjLENBQUMsTUFBTSx5RUFBeUUsQ0FBQyxDQUFBO1lBQ2xKLE9BQU8sY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzFCLENBQUM7UUFFRCw0Q0FBNEM7UUFDNUMsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFdBQVcsQ0FBQyxDQUFBO1FBQzFGLElBQUksaUJBQWlCLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUNBQXVDLGlCQUFpQixDQUFDLE1BQU0sOENBQThDLENBQUMsQ0FBQTtZQUMxSCxPQUFPLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzdCLENBQUM7UUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDLDJFQUEyRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBQ2xHLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLHFEQUFxRCxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQzNILE1BQU0sS0FBSyxDQUFBLENBQUMsNEJBQTRCO0lBQzFDLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsa0JBQWtCLENBQy9CLElBQVMsRUFDVCxVQUFrQixFQUNsQixXQUF3QixFQUN4QixNQUFXO0lBRVgsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQTtJQUN0QixNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFBO0lBQzlCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFBO0lBRXBDLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0RBQWtELFVBQVUsWUFBWSxNQUFNLHFCQUFxQixVQUFVLEdBQUcsQ0FBQyxDQUFBO0lBRTdILE1BQU0sdUJBQXVCLEdBQUcsUUFBUSxDQUFDLHlCQUF5QixLQUFLLElBQUksQ0FBQTtJQUMzRSxNQUFNLGFBQWEsR0FBRyxVQUFVLEtBQUssV0FBVyxJQUFJLHVCQUF1QixDQUFBO0lBRTNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0NBQXNDLE1BQU0saUNBQWlDLHVCQUF1QixvQkFBb0IsYUFBYSxFQUFFLENBQUMsQ0FBQTtJQUVwSixNQUFNLGNBQWMsR0FBRyxRQUFRLENBQUMsd0JBQXdCLElBQUksRUFBRSxDQUFBO0lBQzlELE1BQU0sYUFBYSxHQUFHLFFBQVEsQ0FBQyxjQUFjLElBQUksRUFBRSxDQUFBO0lBRW5ELE1BQU0sVUFBVSxHQUFRO1FBQ3RCLFdBQVcsRUFBRSxVQUFVO1FBQ3ZCLFFBQVEsRUFBRTtZQUNSLEdBQUcsUUFBUTtZQUNYLHdCQUF3QixFQUFFO2dCQUN4QixHQUFHLGNBQWM7Z0JBQ2pCO29CQUNFLFdBQVcsRUFBRSxVQUFVO29CQUN2QixTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7b0JBQ25DLFNBQVMsRUFBRSw2QkFBNkI7b0JBQ3hDLGFBQWEsRUFBRSxhQUFhO2lCQUM3QjthQUNGO1lBQ0Qsa0JBQWtCLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7WUFDNUMseUJBQXlCLEVBQUUsS0FBSztTQUNqQztLQUNGLENBQUE7SUFFRCwwQkFBMEI7SUFDMUIsSUFBSSxhQUFhLEVBQUUsQ0FBQztRQUNsQixVQUFVLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQTtRQUM5QixVQUFVLENBQUMsUUFBUSxDQUFDLGNBQWMsR0FBRztZQUNuQyxHQUFHLGFBQWE7WUFDaEI7Z0JBQ0UsTUFBTSxFQUFFLFVBQVU7Z0JBQ2xCLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRTtnQkFDbkMsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLFlBQVksRUFBRSw2QkFBNkI7YUFDNUM7U0FDRixDQUFBO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxrREFBa0QsTUFBTSxpQkFBaUIsVUFBVSxpQkFBaUIsQ0FBQyxDQUFBO0lBQ25ILENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsTUFBTSx3QkFBd0IsVUFBVSx3QkFBd0IsQ0FBQyxDQUFBO0lBQ3JILENBQUM7SUFFRCxNQUFNLENBQUMsSUFBSSxDQUFDLCtDQUErQyxNQUFNLHNCQUFzQixVQUFVLEVBQUUsQ0FBQyxDQUFBO0lBRXBHLE1BQU0sV0FBVyxHQUFHLE1BQU0sV0FBVyxDQUFDLFdBQVcsQ0FBQztRQUNoRCxRQUFRLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxFQUFFO1FBQ3hCLElBQUksRUFBRSxVQUFVO0tBQ2pCLENBQUMsQ0FBQTtJQUVGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFBO0lBQzNFLE1BQU0sV0FBVyxHQUFJLFNBQWlDLEVBQUUsTUFBTSxJQUFJLFNBQVMsQ0FBQTtJQUUzRSxNQUFNLENBQUMsSUFBSSxDQUFDLGdFQUFnRSxVQUFVLFlBQVksTUFBTSxtQkFBbUIsV0FBVyxFQUFFLENBQUMsQ0FBQTtBQUMzSSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsZ0JBQWdCLENBQzdCLFNBQTJCLEVBQzNCLE1BQVcsRUFDWCxVQUFrQixFQUNsQixhQUFxQixDQUFDLEVBQ3RCLFlBQW9CLElBQUk7SUFFeEIsSUFBSSxTQUE0QixDQUFBO0lBRWhDLEtBQUssSUFBSSxPQUFPLEdBQUcsQ0FBQyxFQUFFLE9BQU8sR0FBRyxVQUFVLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQztRQUN0RCxJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sU0FBUyxFQUFFLENBQUE7UUFDMUIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixTQUFTLEdBQUcsS0FBYyxDQUFBO1lBRTFCLElBQUksT0FBTyxHQUFHLFVBQVUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxLQUFLLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFBO2dCQUM5QyxNQUFNLENBQUMsSUFBSSxDQUNULHlDQUF5QyxPQUFPLEdBQUcsQ0FBQyxJQUFJLFVBQVUsd0JBQXdCLFVBQVUsaUJBQWlCLEtBQUssS0FBSyxFQUMvSCxLQUFLLENBQUMsT0FBTyxDQUNkLENBQUE7Z0JBQ0QsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQTtZQUMxRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsS0FBSyxDQUNWLHFDQUFxQyxVQUFVLGlDQUFpQyxVQUFVLEdBQUcsRUFDN0YsU0FBUyxFQUFFLE9BQU8sSUFBSSxlQUFlLENBQ3RDLENBQUE7SUFDRCxNQUFNLFNBQVMsQ0FBQTtJQUNmLHlEQUF5RDtBQUMzRCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDVSxRQUFBLE1BQU0sR0FBcUI7SUFDdEMsS0FBSyxFQUFFO1FBQ0wsa0JBQWtCO1FBQ2xCLHdCQUF3QjtLQUN6QjtDQUNGLENBQUEifQ==
|