@payloadcms/plugin-ecommerce 4.0.0-internal.7b031c8 → 4.0.0-internal.8001944
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/README.md +6 -0
- package/dist/collections/addresses/createAddressesCollection.d.ts.map +1 -1
- package/dist/collections/addresses/createAddressesCollection.js +1 -0
- package/dist/collections/addresses/createAddressesCollection.js.map +1 -1
- package/dist/collections/carts/beforeChange.d.ts.map +1 -1
- package/dist/collections/carts/beforeChange.js +2 -0
- package/dist/collections/carts/beforeChange.js.map +1 -1
- package/dist/collections/carts/createCartsCollection.d.ts.map +1 -1
- package/dist/collections/carts/createCartsCollection.js +1 -0
- package/dist/collections/carts/createCartsCollection.js.map +1 -1
- package/dist/collections/orders/createOrdersCollection.d.ts.map +1 -1
- package/dist/collections/orders/createOrdersCollection.js +1 -0
- package/dist/collections/orders/createOrdersCollection.js.map +1 -1
- package/dist/collections/products/createProductsCollection.d.ts.map +1 -1
- package/dist/collections/products/createProductsCollection.js +1 -0
- package/dist/collections/products/createProductsCollection.js.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.d.ts.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.js +1 -0
- package/dist/collections/transactions/createTransactionsCollection.js.map +1 -1
- package/dist/collections/variants/createVariantOptionsCollection.d.ts.map +1 -1
- package/dist/collections/variants/createVariantOptionsCollection.js +1 -0
- package/dist/collections/variants/createVariantOptionsCollection.js.map +1 -1
- package/dist/collections/variants/createVariantTypesCollection.d.ts.map +1 -1
- package/dist/collections/variants/createVariantTypesCollection.js +1 -0
- package/dist/collections/variants/createVariantTypesCollection.js.map +1 -1
- package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.d.ts.map +1 -1
- package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.js +2 -0
- package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.js.map +1 -1
- package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.d.ts.map +1 -1
- package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.js +1 -0
- package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.js.map +1 -1
- package/dist/collections/variants/createVariantsCollection/index.d.ts.map +1 -1
- package/dist/collections/variants/createVariantsCollection/index.js +1 -0
- package/dist/collections/variants/createVariantsCollection/index.js.map +1 -1
- package/dist/endpoints/confirmOrder.d.ts.map +1 -1
- package/dist/endpoints/confirmOrder.js +306 -44
- package/dist/endpoints/confirmOrder.js.map +1 -1
- package/dist/endpoints/initiatePayment.d.ts.map +1 -1
- package/dist/endpoints/initiatePayment.js +2 -0
- package/dist/endpoints/initiatePayment.js.map +1 -1
- package/dist/fields/statusField.d.ts.map +1 -1
- package/dist/fields/statusField.js +5 -0
- package/dist/fields/statusField.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/payments/adapters/stripe/confirmOrder.d.ts.map +1 -1
- package/dist/payments/adapters/stripe/confirmOrder.js +108 -75
- package/dist/payments/adapters/stripe/confirmOrder.js.map +1 -1
- package/dist/payments/adapters/stripe/initiatePayment.d.ts.map +1 -1
- package/dist/payments/adapters/stripe/initiatePayment.js +1 -0
- package/dist/payments/adapters/stripe/initiatePayment.js.map +1 -1
- package/dist/payments/adapters/stripe/validateSettlement.d.ts +37 -0
- package/dist/payments/adapters/stripe/validateSettlement.d.ts.map +1 -0
- package/dist/payments/adapters/stripe/validateSettlement.js +157 -0
- package/dist/payments/adapters/stripe/validateSettlement.js.map +1 -0
- package/dist/react/provider/index.d.ts.map +1 -1
- package/dist/react/provider/index.js +75 -34
- package/dist/react/provider/index.js.map +1 -1
- package/dist/types/index.d.ts +24 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/ui/VariantOptionsSelector/index.d.ts.map +1 -1
- package/dist/ui/VariantOptionsSelector/index.js +3 -1
- package/dist/ui/VariantOptionsSelector/index.js.map +1 -1
- package/package.json +10 -10
- package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js +0 -358
- package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js.map +0 -1
- package/dist/payments/adapters/stripe/confirmOrder.spec.js +0 -166
- package/dist/payments/adapters/stripe/confirmOrder.spec.js.map +0 -1
- package/dist/utilities/accessComposition.spec.js +0 -765
- package/dist/utilities/accessComposition.spec.js.map +0 -1
- package/dist/utilities/defaultProductsValidation.spec.js +0 -384
- package/dist/utilities/defaultProductsValidation.spec.js.map +0 -1
- package/dist/utilities/getCollectionSlugMap.spec.js +0 -254
- package/dist/utilities/getCollectionSlugMap.spec.js.map +0 -1
- package/dist/utilities/sanitizePluginConfig.spec.js +0 -516
- package/dist/utilities/sanitizePluginConfig.spec.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirmOrder.d.ts","sourceRoot":"","sources":["../../src/endpoints/confirmOrder.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"confirmOrder.d.ts","sourceRoot":"","sources":["../../src/endpoints/confirmOrder.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,QAAQ,EAGd,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAEnB,MAAM,mBAAmB,CAAA;AAS1B,KAAK,IAAI,GAAG;IACV;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,gBAAgB,CAAA;IAClC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,cAAc,CAAA;IAC7B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,KAAK,mBAAmB,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAA;AAE9D;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,mBAgQ/B,CAAA"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { addDataAndFileToRequest } from 'payload';
|
|
1
|
+
import { addDataAndFileToRequest, commitTransaction, initTransaction, killTransaction } from 'payload';
|
|
2
|
+
const SETTLEMENT_POLL_INTERVAL_MS = 25;
|
|
3
|
+
const SETTLEMENT_WAIT_TIMEOUT_MS = 500;
|
|
2
4
|
/**
|
|
3
5
|
* Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider.
|
|
4
6
|
* This is the first step in the payment process.
|
|
@@ -26,7 +28,7 @@ import { addDataAndFileToRequest } from 'payload';
|
|
|
26
28
|
}
|
|
27
29
|
} else {
|
|
28
30
|
// Get the email from the data if user is not available
|
|
29
|
-
if (data?.customerEmail &&
|
|
31
|
+
if (typeof data?.customerEmail === 'string' && normalizeEmail(data.customerEmail).length > 0) {
|
|
30
32
|
customerEmail = data.customerEmail;
|
|
31
33
|
} else {
|
|
32
34
|
return Response.json({
|
|
@@ -83,62 +85,105 @@ import { addDataAndFileToRequest } from 'payload';
|
|
|
83
85
|
status: 400
|
|
84
86
|
});
|
|
85
87
|
}
|
|
88
|
+
let shouldCommit = false;
|
|
86
89
|
try {
|
|
90
|
+
const canonicalCartID = cart.id;
|
|
91
|
+
if (canonicalCartID === null || canonicalCartID === undefined || typeof canonicalCartID === 'string' && canonicalCartID.trim() === '') {
|
|
92
|
+
throw new Error('Canonical cart ID is required.');
|
|
93
|
+
}
|
|
94
|
+
const cartCustomerEmail = 'customerEmail' in cart ? cart.customerEmail : undefined;
|
|
95
|
+
const normalizedCartCustomerEmail = normalizeEmail(cartCustomerEmail);
|
|
96
|
+
const normalizedSubmittedCustomerEmail = normalizeEmail(customerEmail);
|
|
97
|
+
const canonicalEmail = user ? normalizeEmail(user.email) : normalizedCartCustomerEmail || normalizedSubmittedCustomerEmail;
|
|
98
|
+
if (!user && normalizedCartCustomerEmail && normalizedSubmittedCustomerEmail !== normalizedCartCustomerEmail) {
|
|
99
|
+
throw new Error('Customer email does not match the cart.');
|
|
100
|
+
}
|
|
101
|
+
shouldCommit = await initTransaction(req);
|
|
102
|
+
const hadActiveTransaction = Boolean(await req.transactionID);
|
|
103
|
+
let didCallFinalizeOrder = false;
|
|
104
|
+
let didFinalizeOrder = false;
|
|
105
|
+
let didRecoverTransientConflict = false;
|
|
106
|
+
let finalizedTransactionID;
|
|
107
|
+
const finalizeOrder = async ({ orderData, transactionID })=>{
|
|
108
|
+
if (didCallFinalizeOrder) {
|
|
109
|
+
throw new Error('Order settlement was already finalized for this request.');
|
|
110
|
+
}
|
|
111
|
+
didCallFinalizeOrder = true;
|
|
112
|
+
finalizedTransactionID = transactionID;
|
|
113
|
+
let order;
|
|
114
|
+
try {
|
|
115
|
+
order = await finalizeTransactionOrder({
|
|
116
|
+
cartID: canonicalCartID,
|
|
117
|
+
cartsSlug,
|
|
118
|
+
orderData,
|
|
119
|
+
ordersSlug,
|
|
120
|
+
productsSlug,
|
|
121
|
+
req,
|
|
122
|
+
transactionID,
|
|
123
|
+
transactionsSlug,
|
|
124
|
+
variantsSlug
|
|
125
|
+
});
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (!shouldCommit || !isTransientTransactionConflict(error)) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
// MongoDB reports a losing transactional claim as a transient write conflict rather
|
|
131
|
+
// than a null compare-and-set result. Leave the aborted snapshot before polling.
|
|
132
|
+
await killTransaction(req);
|
|
133
|
+
shouldCommit = false;
|
|
134
|
+
order = await waitForCanonicalOrder({
|
|
135
|
+
ordersSlug,
|
|
136
|
+
req,
|
|
137
|
+
transactionID,
|
|
138
|
+
transactionsSlug
|
|
139
|
+
});
|
|
140
|
+
didRecoverTransientConflict = true;
|
|
141
|
+
}
|
|
142
|
+
didFinalizeOrder = true;
|
|
143
|
+
return order;
|
|
144
|
+
};
|
|
87
145
|
const paymentResponse = await paymentMethod.confirmOrder({
|
|
88
146
|
cartsSlug,
|
|
89
147
|
customersSlug,
|
|
90
148
|
data: {
|
|
91
149
|
...data,
|
|
92
|
-
|
|
150
|
+
cartID: canonicalCartID,
|
|
151
|
+
customerEmail: canonicalEmail
|
|
93
152
|
},
|
|
153
|
+
finalizeOrder,
|
|
94
154
|
ordersSlug,
|
|
95
155
|
req,
|
|
96
156
|
transactionsSlug
|
|
97
157
|
});
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const id = typeof item.variant === 'object' ? item.variant.id : item.variant;
|
|
112
|
-
await payload.db.updateOne({
|
|
113
|
-
id,
|
|
114
|
-
collection: variantsSlug,
|
|
115
|
-
data: {
|
|
116
|
-
inventory: {
|
|
117
|
-
$inc: item.quantity * -1
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
} else if (item.product) {
|
|
122
|
-
const id = typeof item.product === 'object' ? item.product.id : item.product;
|
|
123
|
-
await payload.db.updateOne({
|
|
124
|
-
id,
|
|
125
|
-
collection: productsSlug,
|
|
126
|
-
data: {
|
|
127
|
-
inventory: {
|
|
128
|
-
$inc: item.quantity * -1
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
158
|
+
const hasActiveTransaction = Boolean(await req.transactionID);
|
|
159
|
+
const transactionID = paymentResponse.transactionID;
|
|
160
|
+
if (!isValidDocumentID(transactionID)) {
|
|
161
|
+
throw new Error('Transaction ID is missing or invalid.');
|
|
162
|
+
}
|
|
163
|
+
if (!didCallFinalizeOrder) {
|
|
164
|
+
throw new Error('Payment adapter did not finalize the order.');
|
|
165
|
+
}
|
|
166
|
+
if (!didFinalizeOrder) {
|
|
167
|
+
throw new Error('Order settlement did not complete successfully.');
|
|
168
|
+
}
|
|
169
|
+
if (didFinalizeOrder && getRelationshipID(transactionID) !== getRelationshipID(finalizedTransactionID)) {
|
|
170
|
+
throw new Error('Confirmation response transaction does not match the settlement.');
|
|
135
171
|
}
|
|
136
|
-
if (
|
|
137
|
-
|
|
172
|
+
if (hadActiveTransaction && !hasActiveTransaction && !didRecoverTransientConflict) {
|
|
173
|
+
throw new Error('Order confirmation lost its active transaction.');
|
|
174
|
+
}
|
|
175
|
+
if (shouldCommit && hasActiveTransaction) {
|
|
176
|
+
await commitTransaction(req);
|
|
138
177
|
}
|
|
139
178
|
return Response.json(paymentResponse);
|
|
140
|
-
} catch (
|
|
141
|
-
|
|
179
|
+
} catch (err) {
|
|
180
|
+
if (shouldCommit) {
|
|
181
|
+
await killTransaction(req);
|
|
182
|
+
}
|
|
183
|
+
payload.logger.error({
|
|
184
|
+
err,
|
|
185
|
+
msg: 'Error confirming order.'
|
|
186
|
+
});
|
|
142
187
|
return Response.json({
|
|
143
188
|
message: 'Error confirming order.'
|
|
144
189
|
}, {
|
|
@@ -146,5 +191,222 @@ import { addDataAndFileToRequest } from 'payload';
|
|
|
146
191
|
});
|
|
147
192
|
}
|
|
148
193
|
};
|
|
194
|
+
const normalizeEmail = (email)=>typeof email === 'string' ? email.trim().toLowerCase() : '';
|
|
195
|
+
const isValidDocumentID = (id)=>typeof id === 'number' && Number.isFinite(id) || typeof id === 'string' && id.trim().length > 0;
|
|
196
|
+
const finalizeTransactionOrder = async ({ cartID, cartsSlug, orderData, ordersSlug, productsSlug, req, transactionID, transactionsSlug, variantsSlug })=>{
|
|
197
|
+
if (!isValidDocumentID(transactionID)) {
|
|
198
|
+
throw new Error('Transaction ID is missing or invalid.');
|
|
199
|
+
}
|
|
200
|
+
if (!isRecord(orderData)) {
|
|
201
|
+
throw new Error('Order data is missing or invalid.');
|
|
202
|
+
}
|
|
203
|
+
const claimedTransaction = await req.payload.db.updateOne({
|
|
204
|
+
collection: transactionsSlug,
|
|
205
|
+
data: {
|
|
206
|
+
status: 'processing'
|
|
207
|
+
},
|
|
208
|
+
options: {
|
|
209
|
+
atomic: true
|
|
210
|
+
},
|
|
211
|
+
req,
|
|
212
|
+
where: {
|
|
213
|
+
and: [
|
|
214
|
+
{
|
|
215
|
+
id: {
|
|
216
|
+
equals: transactionID
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
status: {
|
|
221
|
+
equals: 'pending'
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
order: {
|
|
226
|
+
exists: false
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
if (!claimedTransaction) {
|
|
233
|
+
return waitForCanonicalOrder({
|
|
234
|
+
ordersSlug,
|
|
235
|
+
req,
|
|
236
|
+
transactionID,
|
|
237
|
+
transactionsSlug
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (getRelationshipID(claimedTransaction.id) !== getRelationshipID(transactionID)) {
|
|
241
|
+
throw new Error('Claimed transaction does not match the requested transaction.');
|
|
242
|
+
}
|
|
243
|
+
const transaction = await req.payload.findByID({
|
|
244
|
+
id: transactionID,
|
|
245
|
+
collection: transactionsSlug,
|
|
246
|
+
depth: 0,
|
|
247
|
+
overrideAccess: true,
|
|
248
|
+
req
|
|
249
|
+
});
|
|
250
|
+
if (!transaction || getRelationshipID(transaction.id) !== getRelationshipID(transactionID) || transaction.status !== 'processing') {
|
|
251
|
+
throw new Error('Claimed transaction could not be loaded for settlement.');
|
|
252
|
+
}
|
|
253
|
+
const referencedOrders = await req.payload.find({
|
|
254
|
+
collection: ordersSlug,
|
|
255
|
+
depth: 0,
|
|
256
|
+
limit: 1,
|
|
257
|
+
overrideAccess: true,
|
|
258
|
+
pagination: false,
|
|
259
|
+
req,
|
|
260
|
+
where: {
|
|
261
|
+
transactions: {
|
|
262
|
+
equals: transactionID
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
if (referencedOrders.totalDocs !== 0 || referencedOrders.docs.length !== 0) {
|
|
267
|
+
throw new Error('An order already references the claimed transaction.');
|
|
268
|
+
}
|
|
269
|
+
const order = await req.payload.create({
|
|
270
|
+
collection: ordersSlug,
|
|
271
|
+
data: {
|
|
272
|
+
...orderData,
|
|
273
|
+
transactions: [
|
|
274
|
+
transactionID
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
overrideAccess: true,
|
|
278
|
+
req
|
|
279
|
+
});
|
|
280
|
+
const orderID = requireDocumentID({
|
|
281
|
+
fieldName: 'order ID',
|
|
282
|
+
value: order.id
|
|
283
|
+
});
|
|
284
|
+
await req.payload.update({
|
|
285
|
+
id: cartID,
|
|
286
|
+
collection: cartsSlug,
|
|
287
|
+
data: {
|
|
288
|
+
purchasedAt: new Date().toISOString()
|
|
289
|
+
},
|
|
290
|
+
overrideAccess: true,
|
|
291
|
+
req
|
|
292
|
+
});
|
|
293
|
+
await decrementInventory({
|
|
294
|
+
items: transaction.items,
|
|
295
|
+
productsSlug,
|
|
296
|
+
req,
|
|
297
|
+
variantsSlug
|
|
298
|
+
});
|
|
299
|
+
await req.payload.update({
|
|
300
|
+
id: transactionID,
|
|
301
|
+
collection: transactionsSlug,
|
|
302
|
+
data: {
|
|
303
|
+
order: orderID,
|
|
304
|
+
status: 'succeeded'
|
|
305
|
+
},
|
|
306
|
+
overrideAccess: true,
|
|
307
|
+
req
|
|
308
|
+
});
|
|
309
|
+
return order;
|
|
310
|
+
};
|
|
311
|
+
const decrementInventory = async ({ items, productsSlug, req, variantsSlug })=>{
|
|
312
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
313
|
+
throw new Error('Inventory transaction items are missing or invalid.');
|
|
314
|
+
}
|
|
315
|
+
for (const item of items){
|
|
316
|
+
if (!isRecord(item) || typeof item.quantity !== 'number' || !Number.isFinite(item.quantity) || item.quantity <= 0) {
|
|
317
|
+
throw new Error('Inventory item quantity is missing or invalid.');
|
|
318
|
+
}
|
|
319
|
+
const hasVariant = item.variant !== null && item.variant !== undefined;
|
|
320
|
+
const id = hasVariant ? item.variant : item.product;
|
|
321
|
+
if (!isValidDocumentID(id)) {
|
|
322
|
+
throw new Error('Inventory item target is missing or invalid.');
|
|
323
|
+
}
|
|
324
|
+
const updatedInventory = await req.payload.db.updateOne({
|
|
325
|
+
id,
|
|
326
|
+
collection: hasVariant ? variantsSlug : productsSlug,
|
|
327
|
+
data: {
|
|
328
|
+
inventory: {
|
|
329
|
+
$inc: item.quantity * -1
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
req
|
|
333
|
+
});
|
|
334
|
+
if (!updatedInventory) {
|
|
335
|
+
throw new Error('Inventory item could not be updated.');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
const waitForCanonicalOrder = async ({ ordersSlug, req, transactionID, transactionsSlug })=>{
|
|
340
|
+
const deadline = Date.now() + SETTLEMENT_WAIT_TIMEOUT_MS;
|
|
341
|
+
do {
|
|
342
|
+
const transaction = await req.payload.findByID({
|
|
343
|
+
id: transactionID,
|
|
344
|
+
collection: transactionsSlug,
|
|
345
|
+
depth: 0,
|
|
346
|
+
overrideAccess: true,
|
|
347
|
+
req
|
|
348
|
+
});
|
|
349
|
+
if (!transaction) {
|
|
350
|
+
throw new Error('Canonical transaction was not found.');
|
|
351
|
+
}
|
|
352
|
+
if (transaction.status === 'succeeded') {
|
|
353
|
+
return findExactlyLinkedOrder({
|
|
354
|
+
orderID: transaction.order,
|
|
355
|
+
ordersSlug,
|
|
356
|
+
req,
|
|
357
|
+
transactionID
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
if (transaction.status !== 'pending' && transaction.status !== 'processing') {
|
|
361
|
+
throw new Error('Transaction is not available for settlement.');
|
|
362
|
+
}
|
|
363
|
+
if (Date.now() >= deadline) {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
await new Promise((resolve)=>setTimeout(resolve, Math.min(SETTLEMENT_POLL_INTERVAL_MS, deadline - Date.now())));
|
|
367
|
+
}while (Date.now() <= deadline)
|
|
368
|
+
throw new Error('Transaction settlement did not complete in time.');
|
|
369
|
+
};
|
|
370
|
+
const findExactlyLinkedOrder = async ({ orderID, ordersSlug, req, transactionID })=>{
|
|
371
|
+
const canonicalOrderID = requireDocumentID({
|
|
372
|
+
fieldName: 'order ID',
|
|
373
|
+
value: orderID
|
|
374
|
+
});
|
|
375
|
+
const result = await req.payload.find({
|
|
376
|
+
collection: ordersSlug,
|
|
377
|
+
depth: 0,
|
|
378
|
+
limit: 2,
|
|
379
|
+
overrideAccess: true,
|
|
380
|
+
pagination: false,
|
|
381
|
+
req,
|
|
382
|
+
where: {
|
|
383
|
+
transactions: {
|
|
384
|
+
equals: transactionID
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
if (result.totalDocs !== 1 || result.docs.length !== 1 || getRelationshipID(result.docs[0]?.id) !== getRelationshipID(canonicalOrderID)) {
|
|
389
|
+
throw new Error('Transaction does not have exactly one canonical linked order.');
|
|
390
|
+
}
|
|
391
|
+
return result.docs[0];
|
|
392
|
+
};
|
|
393
|
+
const getRelationshipID = (value)=>{
|
|
394
|
+
const id = isRecord(value) ? value.id : value;
|
|
395
|
+
return isValidDocumentID(id) ? String(id) : undefined;
|
|
396
|
+
};
|
|
397
|
+
const requireDocumentID = ({ fieldName, value })=>{
|
|
398
|
+
const id = isRecord(value) ? value.id : value;
|
|
399
|
+
if (!isValidDocumentID(id)) {
|
|
400
|
+
throw new Error(`${fieldName} is missing or invalid.`);
|
|
401
|
+
}
|
|
402
|
+
return id;
|
|
403
|
+
};
|
|
404
|
+
const isRecord = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
405
|
+
const isTransientTransactionConflict = (error)=>{
|
|
406
|
+
if (!isRecord(error)) {
|
|
407
|
+
return false;
|
|
408
|
+
}
|
|
409
|
+
return error.code === 112 || error.codeName === 'WriteConflict' || Array.isArray(error.errorLabels) && error.errorLabels.includes('TransientTransactionError');
|
|
410
|
+
};
|
|
149
411
|
|
|
150
412
|
//# sourceMappingURL=confirmOrder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/endpoints/confirmOrder.ts"],"sourcesContent":["import { addDataAndFileToRequest, type DefaultDocumentIDType, type Endpoint } from 'payload'\n\nimport type {\n CurrenciesConfig,\n PaymentAdapter,\n ProductsValidation,\n UserWithCart,\n} from '../types/index.js'\n\ntype Args = {\n /**\n * The slug of the carts collection, defaults to 'carts'.\n */\n cartsSlug?: string\n currenciesConfig: CurrenciesConfig\n /**\n * The slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * The slug of the orders collection, defaults to 'orders'.\n */\n ordersSlug?: string\n paymentMethod: PaymentAdapter\n /**\n * The slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Customise the validation used for checking products or variants before a transaction is created.\n */\n productsValidation?: ProductsValidation\n /**\n * The slug of the transactions collection, defaults to 'transactions'.\n */\n transactionsSlug?: string\n /**\n * The slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\ntype ConfirmOrderHandler = (args: Args) => Endpoint['handler']\n\n/**\n * Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider.\n * This is the first step in the payment process.\n */\nexport const confirmOrderHandler: ConfirmOrderHandler =\n ({\n cartsSlug = 'carts',\n currenciesConfig,\n customersSlug = 'users',\n ordersSlug = 'orders',\n paymentMethod,\n productsSlug = 'products',\n productsValidation,\n transactionsSlug = 'transactions',\n variantsSlug = 'variants',\n }) =>\n async (req) => {\n await addDataAndFileToRequest(req)\n\n const data = req.data\n const payload = req.payload\n const user = req.user as null | UserWithCart\n\n let currency: string = currenciesConfig.defaultCurrency\n let cartID: DefaultDocumentIDType = data?.cartID\n let cart = undefined\n let customerEmail: string = user?.email ?? ''\n const cartSecret = data?.secret\n\n if (user) {\n if (user.cart?.docs && Array.isArray(user.cart.docs) && user.cart.docs.length > 0) {\n if (!cartID && user.cart.docs[0]) {\n // Use the user's cart instead\n if (typeof user.cart.docs[0] === 'object') {\n cartID = user.cart.docs[0].id\n cart = user.cart.docs[0]\n } else {\n cartID = user.cart.docs[0]\n }\n }\n }\n } else {\n // Get the email from the data if user is not available\n if (data?.customerEmail && typeof data.customerEmail === 'string') {\n customerEmail = data.customerEmail\n } else {\n return Response.json(\n {\n message: 'A customer email is required to make a purchase.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (!cart) {\n if (cartID) {\n // Add cart secret to query for guest cart access control\n if (cartSecret && typeof cartSecret === 'string') {\n req.query = req.query || {}\n req.query.secret = cartSecret\n }\n\n cart = await payload.findByID({\n id: cartID,\n collection: cartsSlug,\n depth: 2,\n overrideAccess: false,\n req,\n select: {\n id: true,\n currency: true,\n customerEmail: true,\n items: true,\n subtotal: true,\n },\n })\n\n if (!cart) {\n return Response.json(\n {\n message: `Cart with ID ${cartID} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n } else {\n return Response.json(\n {\n message: 'Cart ID is required.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (cart.currency && typeof cart.currency === 'string') {\n currency = cart.currency\n }\n\n // Ensure the currency is provided or inferred in some way\n if (!currency) {\n return Response.json(\n {\n message: 'Currency is required.',\n },\n {\n status: 400,\n },\n )\n }\n\n try {\n const paymentResponse = await paymentMethod.confirmOrder({\n cartsSlug,\n customersSlug,\n data: {\n ...data,\n customerEmail,\n },\n ordersSlug,\n req,\n transactionsSlug,\n })\n\n if (paymentResponse.transactionID) {\n const transaction = await payload.findByID({\n id: paymentResponse.transactionID,\n collection: transactionsSlug,\n depth: 0,\n select: {\n id: true,\n items: true,\n },\n })\n\n if (transaction && Array.isArray(transaction.items) && transaction.items.length > 0) {\n for (const item of transaction.items) {\n if (item.variant) {\n const id = typeof item.variant === 'object' ? item.variant.id : item.variant\n\n await payload.db.updateOne({\n id,\n collection: variantsSlug,\n data: {\n inventory: {\n $inc: item.quantity * -1,\n },\n },\n })\n } else if (item.product) {\n const id = typeof item.product === 'object' ? item.product.id : item.product\n\n await payload.db.updateOne({\n id,\n collection: productsSlug,\n data: {\n inventory: {\n $inc: item.quantity * -1,\n },\n },\n })\n }\n }\n }\n }\n\n if ('paymentResponse.transactionID' in paymentResponse && paymentResponse.transactionID) {\n delete (paymentResponse as Partial<typeof paymentResponse>).transactionID\n }\n\n return Response.json(paymentResponse)\n } catch (error) {\n payload.logger.error(error, 'Error confirming order.')\n\n return Response.json(\n {\n message: 'Error confirming order.',\n },\n {\n status: 500,\n },\n )\n }\n }\n"],"names":["addDataAndFileToRequest","confirmOrderHandler","cartsSlug","currenciesConfig","customersSlug","ordersSlug","paymentMethod","productsSlug","productsValidation","transactionsSlug","variantsSlug","req","data","payload","user","currency","defaultCurrency","cartID","cart","undefined","customerEmail","email","cartSecret","secret","docs","Array","isArray","length","id","Response","json","message","status","query","findByID","collection","depth","overrideAccess","select","items","subtotal","paymentResponse","confirmOrder","transactionID","transaction","item","variant","db","updateOne","inventory","$inc","quantity","product","error","logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/confirmOrder.ts"],"sourcesContent":["import {\n addDataAndFileToRequest,\n commitTransaction,\n type DefaultDocumentIDType,\n type Endpoint,\n initTransaction,\n killTransaction,\n} from 'payload'\n\nimport type {\n CurrenciesConfig,\n PaymentAdapter,\n ProductsValidation,\n UserWithCart,\n} from '../types/index.js'\n\ntype ConfirmOrderArgs = Parameters<PaymentAdapter['confirmOrder']>[0]\ntype FinalizeOrder = ConfirmOrderArgs['finalizeOrder']\ntype RecordValue = Record<string, unknown>\n\nconst SETTLEMENT_POLL_INTERVAL_MS = 25\nconst SETTLEMENT_WAIT_TIMEOUT_MS = 500\n\ntype Args = {\n /**\n * The slug of the carts collection, defaults to 'carts'.\n */\n cartsSlug?: string\n currenciesConfig: CurrenciesConfig\n /**\n * The slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * The slug of the orders collection, defaults to 'orders'.\n */\n ordersSlug?: string\n paymentMethod: PaymentAdapter\n /**\n * The slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Customise the validation used for checking products or variants before a transaction is created.\n */\n productsValidation?: ProductsValidation\n /**\n * The slug of the transactions collection, defaults to 'transactions'.\n */\n transactionsSlug?: string\n /**\n * The slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\ntype ConfirmOrderHandler = (args: Args) => Endpoint['handler']\n\n/**\n * Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider.\n * This is the first step in the payment process.\n */\nexport const confirmOrderHandler: ConfirmOrderHandler =\n ({\n cartsSlug = 'carts',\n currenciesConfig,\n customersSlug = 'users',\n ordersSlug = 'orders',\n paymentMethod,\n productsSlug = 'products',\n productsValidation,\n transactionsSlug = 'transactions',\n variantsSlug = 'variants',\n }) =>\n async (req) => {\n await addDataAndFileToRequest(req)\n\n const data = req.data\n const payload = req.payload\n const user = req.user as null | UserWithCart\n\n let currency: string = currenciesConfig.defaultCurrency\n let cartID: DefaultDocumentIDType = data?.cartID\n let cart = undefined\n let customerEmail: string = user?.email ?? ''\n const cartSecret = data?.secret\n\n if (user) {\n if (user.cart?.docs && Array.isArray(user.cart.docs) && user.cart.docs.length > 0) {\n if (!cartID && user.cart.docs[0]) {\n // Use the user's cart instead\n if (typeof user.cart.docs[0] === 'object') {\n cartID = user.cart.docs[0].id\n cart = user.cart.docs[0]\n } else {\n cartID = user.cart.docs[0]\n }\n }\n }\n } else {\n // Get the email from the data if user is not available\n if (\n typeof data?.customerEmail === 'string' &&\n normalizeEmail(data.customerEmail).length > 0\n ) {\n customerEmail = data.customerEmail\n } else {\n return Response.json(\n {\n message: 'A customer email is required to make a purchase.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (!cart) {\n if (cartID) {\n // Add cart secret to query for guest cart access control\n if (cartSecret && typeof cartSecret === 'string') {\n req.query = req.query || {}\n req.query.secret = cartSecret\n }\n\n cart = await payload.findByID({\n id: cartID,\n collection: cartsSlug,\n depth: 2,\n overrideAccess: false,\n req,\n select: {\n id: true,\n currency: true,\n customerEmail: true,\n items: true,\n subtotal: true,\n },\n })\n\n if (!cart) {\n return Response.json(\n {\n message: `Cart with ID ${cartID} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n } else {\n return Response.json(\n {\n message: 'Cart ID is required.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (cart.currency && typeof cart.currency === 'string') {\n currency = cart.currency\n }\n\n // Ensure the currency is provided or inferred in some way\n if (!currency) {\n return Response.json(\n {\n message: 'Currency is required.',\n },\n {\n status: 400,\n },\n )\n }\n\n let shouldCommit = false\n\n try {\n const canonicalCartID = cart.id\n if (\n canonicalCartID === null ||\n canonicalCartID === undefined ||\n (typeof canonicalCartID === 'string' && canonicalCartID.trim() === '')\n ) {\n throw new Error('Canonical cart ID is required.')\n }\n\n const cartCustomerEmail = 'customerEmail' in cart ? cart.customerEmail : undefined\n const normalizedCartCustomerEmail = normalizeEmail(cartCustomerEmail)\n const normalizedSubmittedCustomerEmail = normalizeEmail(customerEmail)\n const canonicalEmail = user\n ? normalizeEmail(user.email)\n : normalizedCartCustomerEmail || normalizedSubmittedCustomerEmail\n\n if (\n !user &&\n normalizedCartCustomerEmail &&\n normalizedSubmittedCustomerEmail !== normalizedCartCustomerEmail\n ) {\n throw new Error('Customer email does not match the cart.')\n }\n\n shouldCommit = await initTransaction(req)\n const hadActiveTransaction = Boolean(await req.transactionID)\n let didCallFinalizeOrder = false\n let didFinalizeOrder = false\n let didRecoverTransientConflict = false\n let finalizedTransactionID: DefaultDocumentIDType | undefined\n\n const finalizeOrder: FinalizeOrder = async ({ orderData, transactionID }) => {\n if (didCallFinalizeOrder) {\n throw new Error('Order settlement was already finalized for this request.')\n }\n\n didCallFinalizeOrder = true\n finalizedTransactionID = transactionID\n\n let order: RecordValue\n\n try {\n order = await finalizeTransactionOrder({\n cartID: canonicalCartID,\n cartsSlug,\n orderData,\n ordersSlug,\n productsSlug,\n req,\n transactionID,\n transactionsSlug,\n variantsSlug,\n })\n } catch (error) {\n if (!shouldCommit || !isTransientTransactionConflict(error)) {\n throw error\n }\n\n // MongoDB reports a losing transactional claim as a transient write conflict rather\n // than a null compare-and-set result. Leave the aborted snapshot before polling.\n await killTransaction(req)\n shouldCommit = false\n order = await waitForCanonicalOrder({\n ordersSlug,\n req,\n transactionID,\n transactionsSlug,\n })\n didRecoverTransientConflict = true\n }\n\n didFinalizeOrder = true\n\n return order\n }\n\n const paymentResponse = await paymentMethod.confirmOrder({\n cartsSlug,\n customersSlug,\n data: {\n ...data,\n cartID: canonicalCartID,\n customerEmail: canonicalEmail,\n },\n finalizeOrder,\n ordersSlug,\n req,\n transactionsSlug,\n })\n const hasActiveTransaction = Boolean(await req.transactionID)\n const transactionID = paymentResponse.transactionID\n\n if (!isValidDocumentID(transactionID)) {\n throw new Error('Transaction ID is missing or invalid.')\n }\n\n if (!didCallFinalizeOrder) {\n throw new Error('Payment adapter did not finalize the order.')\n }\n\n if (!didFinalizeOrder) {\n throw new Error('Order settlement did not complete successfully.')\n }\n\n if (\n didFinalizeOrder &&\n getRelationshipID(transactionID) !== getRelationshipID(finalizedTransactionID)\n ) {\n throw new Error('Confirmation response transaction does not match the settlement.')\n }\n\n if (hadActiveTransaction && !hasActiveTransaction && !didRecoverTransientConflict) {\n throw new Error('Order confirmation lost its active transaction.')\n }\n\n if (shouldCommit && hasActiveTransaction) {\n await commitTransaction(req)\n }\n\n return Response.json(paymentResponse)\n } catch (err) {\n if (shouldCommit) {\n await killTransaction(req)\n }\n\n payload.logger.error({ err, msg: 'Error confirming order.' })\n\n return Response.json(\n {\n message: 'Error confirming order.',\n },\n {\n status: 500,\n },\n )\n }\n }\n\nconst normalizeEmail = (email: unknown): string =>\n typeof email === 'string' ? email.trim().toLowerCase() : ''\n\nconst isValidDocumentID = (id: unknown): id is DefaultDocumentIDType =>\n (typeof id === 'number' && Number.isFinite(id)) ||\n (typeof id === 'string' && id.trim().length > 0)\n\nconst finalizeTransactionOrder = async ({\n cartID,\n cartsSlug,\n orderData,\n ordersSlug,\n productsSlug,\n req,\n transactionID,\n transactionsSlug,\n variantsSlug,\n}: {\n cartID: DefaultDocumentIDType\n cartsSlug: string\n orderData: Record<string, unknown>\n ordersSlug: string\n productsSlug: string\n req: ConfirmOrderArgs['req']\n transactionID: DefaultDocumentIDType\n transactionsSlug: string\n variantsSlug: string\n}): Promise<RecordValue> => {\n if (!isValidDocumentID(transactionID)) {\n throw new Error('Transaction ID is missing or invalid.')\n }\n\n if (!isRecord(orderData)) {\n throw new Error('Order data is missing or invalid.')\n }\n\n const claimedTransaction = await req.payload.db.updateOne({\n collection: transactionsSlug,\n data: { status: 'processing' },\n options: { atomic: true },\n req,\n where: {\n and: [\n { id: { equals: transactionID } },\n { status: { equals: 'pending' } },\n { order: { exists: false } },\n ],\n },\n })\n\n if (!claimedTransaction) {\n return waitForCanonicalOrder({ ordersSlug, req, transactionID, transactionsSlug })\n }\n\n if (getRelationshipID(claimedTransaction.id) !== getRelationshipID(transactionID)) {\n throw new Error('Claimed transaction does not match the requested transaction.')\n }\n\n const transaction = await req.payload.findByID({\n id: transactionID,\n collection: transactionsSlug,\n depth: 0,\n overrideAccess: true,\n req,\n })\n\n if (\n !transaction ||\n getRelationshipID(transaction.id) !== getRelationshipID(transactionID) ||\n transaction.status !== 'processing'\n ) {\n throw new Error('Claimed transaction could not be loaded for settlement.')\n }\n\n const referencedOrders = await req.payload.find({\n collection: ordersSlug,\n depth: 0,\n limit: 1,\n overrideAccess: true,\n pagination: false,\n req,\n where: { transactions: { equals: transactionID } },\n })\n\n if (referencedOrders.totalDocs !== 0 || referencedOrders.docs.length !== 0) {\n throw new Error('An order already references the claimed transaction.')\n }\n\n const order = (await req.payload.create({\n collection: ordersSlug,\n data: {\n ...orderData,\n transactions: [transactionID],\n },\n overrideAccess: true,\n req,\n })) as RecordValue\n const orderID = requireDocumentID({ fieldName: 'order ID', value: order.id })\n\n await req.payload.update({\n id: cartID,\n collection: cartsSlug,\n data: { purchasedAt: new Date().toISOString() },\n overrideAccess: true,\n req,\n })\n\n await decrementInventory({\n items: transaction.items,\n productsSlug,\n req,\n variantsSlug,\n })\n\n await req.payload.update({\n id: transactionID,\n collection: transactionsSlug,\n data: { order: orderID, status: 'succeeded' },\n overrideAccess: true,\n req,\n })\n\n return order\n}\n\nconst decrementInventory = async ({\n items,\n productsSlug,\n req,\n variantsSlug,\n}: {\n items: unknown\n productsSlug: string\n req: ConfirmOrderArgs['req']\n variantsSlug: string\n}): Promise<void> => {\n if (!Array.isArray(items) || items.length === 0) {\n throw new Error('Inventory transaction items are missing or invalid.')\n }\n\n for (const item of items) {\n if (\n !isRecord(item) ||\n typeof item.quantity !== 'number' ||\n !Number.isFinite(item.quantity) ||\n item.quantity <= 0\n ) {\n throw new Error('Inventory item quantity is missing or invalid.')\n }\n\n const hasVariant = item.variant !== null && item.variant !== undefined\n const id = hasVariant ? item.variant : item.product\n\n if (!isValidDocumentID(id)) {\n throw new Error('Inventory item target is missing or invalid.')\n }\n\n const updatedInventory = await req.payload.db.updateOne({\n id,\n collection: hasVariant ? variantsSlug : productsSlug,\n data: { inventory: { $inc: item.quantity * -1 } },\n req,\n })\n\n if (!updatedInventory) {\n throw new Error('Inventory item could not be updated.')\n }\n }\n}\n\nconst waitForCanonicalOrder = async ({\n ordersSlug,\n req,\n transactionID,\n transactionsSlug,\n}: {\n ordersSlug: string\n req: ConfirmOrderArgs['req']\n transactionID: DefaultDocumentIDType\n transactionsSlug: string\n}): Promise<RecordValue> => {\n const deadline = Date.now() + SETTLEMENT_WAIT_TIMEOUT_MS\n\n do {\n const transaction = await req.payload.findByID({\n id: transactionID,\n collection: transactionsSlug,\n depth: 0,\n overrideAccess: true,\n req,\n })\n\n if (!transaction) {\n throw new Error('Canonical transaction was not found.')\n }\n\n if (transaction.status === 'succeeded') {\n return findExactlyLinkedOrder({\n orderID: transaction.order,\n ordersSlug,\n req,\n transactionID,\n })\n }\n\n if (transaction.status !== 'pending' && transaction.status !== 'processing') {\n throw new Error('Transaction is not available for settlement.')\n }\n\n if (Date.now() >= deadline) {\n break\n }\n\n await new Promise<void>((resolve) =>\n setTimeout(resolve, Math.min(SETTLEMENT_POLL_INTERVAL_MS, deadline - Date.now())),\n )\n } while (Date.now() <= deadline)\n\n throw new Error('Transaction settlement did not complete in time.')\n}\n\nconst findExactlyLinkedOrder = async ({\n orderID,\n ordersSlug,\n req,\n transactionID,\n}: {\n orderID: unknown\n ordersSlug: string\n req: ConfirmOrderArgs['req']\n transactionID: DefaultDocumentIDType\n}): Promise<RecordValue> => {\n const canonicalOrderID = requireDocumentID({ fieldName: 'order ID', value: orderID })\n const result = await req.payload.find({\n collection: ordersSlug,\n depth: 0,\n limit: 2,\n overrideAccess: true,\n pagination: false,\n req,\n where: { transactions: { equals: transactionID } },\n })\n\n if (\n result.totalDocs !== 1 ||\n result.docs.length !== 1 ||\n getRelationshipID(result.docs[0]?.id) !== getRelationshipID(canonicalOrderID)\n ) {\n throw new Error('Transaction does not have exactly one canonical linked order.')\n }\n\n return result.docs[0] as RecordValue\n}\n\nconst getRelationshipID = (value: unknown): string | undefined => {\n const id = isRecord(value) ? value.id : value\n\n return isValidDocumentID(id) ? String(id) : undefined\n}\n\nconst requireDocumentID = ({\n fieldName,\n value,\n}: {\n fieldName: string\n value: unknown\n}): DefaultDocumentIDType => {\n const id = isRecord(value) ? value.id : value\n\n if (!isValidDocumentID(id)) {\n throw new Error(`${fieldName} is missing or invalid.`)\n }\n\n return id\n}\n\nconst isRecord = (value: unknown): value is RecordValue =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst isTransientTransactionConflict = (error: unknown): boolean => {\n if (!isRecord(error)) {\n return false\n }\n\n return (\n error.code === 112 ||\n error.codeName === 'WriteConflict' ||\n (Array.isArray(error.errorLabels) && error.errorLabels.includes('TransientTransactionError'))\n )\n}\n"],"names":["addDataAndFileToRequest","commitTransaction","initTransaction","killTransaction","SETTLEMENT_POLL_INTERVAL_MS","SETTLEMENT_WAIT_TIMEOUT_MS","confirmOrderHandler","cartsSlug","currenciesConfig","customersSlug","ordersSlug","paymentMethod","productsSlug","productsValidation","transactionsSlug","variantsSlug","req","data","payload","user","currency","defaultCurrency","cartID","cart","undefined","customerEmail","email","cartSecret","secret","docs","Array","isArray","length","id","normalizeEmail","Response","json","message","status","query","findByID","collection","depth","overrideAccess","select","items","subtotal","shouldCommit","canonicalCartID","trim","Error","cartCustomerEmail","normalizedCartCustomerEmail","normalizedSubmittedCustomerEmail","canonicalEmail","hadActiveTransaction","Boolean","transactionID","didCallFinalizeOrder","didFinalizeOrder","didRecoverTransientConflict","finalizedTransactionID","finalizeOrder","orderData","order","finalizeTransactionOrder","error","isTransientTransactionConflict","waitForCanonicalOrder","paymentResponse","confirmOrder","hasActiveTransaction","isValidDocumentID","getRelationshipID","err","logger","msg","toLowerCase","Number","isFinite","isRecord","claimedTransaction","db","updateOne","options","atomic","where","and","equals","exists","transaction","referencedOrders","find","limit","pagination","transactions","totalDocs","create","orderID","requireDocumentID","fieldName","value","update","purchasedAt","Date","toISOString","decrementInventory","item","quantity","hasVariant","variant","product","updatedInventory","inventory","$inc","deadline","now","findExactlyLinkedOrder","Promise","resolve","setTimeout","Math","min","canonicalOrderID","result","String","code","codeName","errorLabels","includes"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initiatePayment.d.ts","sourceRoot":"","sources":["../../src/endpoints/initiatePayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuD,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE5F,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,8BAA8B,EAE/B,MAAM,mBAAmB,CAAA;AAI1B,KAAK,IAAI,GAAG;IACV;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,gBAAgB,CAAA;IAClC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,8BAA8B,CAAC,WAAW,CAAC,CAAA;IACvD,aAAa,EAAE,cAAc,CAAA;IAC7B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAA;AAE1D;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"initiatePayment.d.ts","sourceRoot":"","sources":["../../src/endpoints/initiatePayment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuD,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE5F,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,8BAA8B,EAE/B,MAAM,mBAAmB,CAAA;AAI1B,KAAK,IAAI,GAAG;IACV;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,gBAAgB,CAAA;IAClC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,SAAS,CAAC,EAAE,8BAA8B,CAAC,WAAW,CAAC,CAAA;IACvD,aAAa,EAAE,cAAc,CAAA;IAC7B;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;OAEG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,KAAK,eAAe,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,SAAS,CAAC,CAAA;AAE1D;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,eAmSlC,CAAA"}
|
|
@@ -113,6 +113,7 @@ import { defaultProductsValidation } from '../utilities/defaultProductsValidatio
|
|
|
113
113
|
id,
|
|
114
114
|
collection: productsSlug,
|
|
115
115
|
depth: 0,
|
|
116
|
+
overrideAccess: true,
|
|
116
117
|
select: {
|
|
117
118
|
inventory: true,
|
|
118
119
|
[priceField]: true
|
|
@@ -158,6 +159,7 @@ import { defaultProductsValidation } from '../utilities/defaultProductsValidatio
|
|
|
158
159
|
id,
|
|
159
160
|
collection: variantsSlug,
|
|
160
161
|
depth: 0,
|
|
162
|
+
overrideAccess: true,
|
|
161
163
|
select: {
|
|
162
164
|
inventory: true,
|
|
163
165
|
[priceField]: true
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/endpoints/initiatePayment.ts"],"sourcesContent":["import { addDataAndFileToRequest, type DefaultDocumentIDType, type Endpoint } from 'payload'\n\nimport type {\n CurrenciesConfig,\n PaymentAdapter,\n ProductsValidation,\n SanitizedEcommercePluginConfig,\n UserWithCart,\n} from '../types/index.js'\n\nimport { defaultProductsValidation } from '../utilities/defaultProductsValidation.js'\n\ntype Args = {\n /**\n * The slug of the carts collection, defaults to 'carts'.\n */\n cartsSlug?: string\n currenciesConfig: CurrenciesConfig\n /**\n * The slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * Track inventory stock for the products and variants.\n * Accepts an object to override the default field name.\n */\n inventory?: SanitizedEcommercePluginConfig['inventory']\n paymentMethod: PaymentAdapter\n /**\n * The slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Customise the validation used for checking products or variants before a transaction is created.\n */\n productsValidation?: ProductsValidation\n /**\n * The slug of the transactions collection, defaults to 'transactions'.\n */\n transactionsSlug?: string\n /**\n * The slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\ntype InitiatePayment = (args: Args) => Endpoint['handler']\n\n/**\n * Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider.\n * This is the first step in the payment process.\n */\nexport const initiatePaymentHandler: InitiatePayment =\n ({\n cartsSlug = 'carts',\n currenciesConfig,\n customersSlug = 'users',\n paymentMethod,\n productsSlug = 'products',\n productsValidation,\n transactionsSlug = 'transactions',\n variantsSlug = 'variants',\n }) =>\n async (req) => {\n await addDataAndFileToRequest(req)\n const data = req.data\n const payload = req.payload\n const user = req.user as null | UserWithCart\n\n let currency: string = currenciesConfig.defaultCurrency\n let cartID: DefaultDocumentIDType = data?.cartID\n let cart: any = undefined\n const billingAddress = data?.billingAddress\n const shippingAddress = data?.shippingAddress\n const cartSecret = data?.secret\n\n let customerEmail: string = user?.email ?? ''\n\n if (user) {\n if (user.cart?.docs && Array.isArray(user.cart.docs) && user.cart.docs.length > 0) {\n if (!cartID && user.cart.docs[0]) {\n // Use the user's cart instead\n if (typeof user.cart.docs[0] === 'object') {\n cartID = user.cart.docs[0].id\n cart = user.cart.docs[0]\n } else {\n cartID = user.cart.docs[0]\n }\n }\n }\n } else {\n // Get the email from the data if user is not available\n if (data?.customerEmail && typeof data.customerEmail === 'string') {\n customerEmail = data.customerEmail\n } else {\n return Response.json(\n {\n message: 'A customer email is required to make a purchase.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (!cart) {\n if (cartID) {\n // Add cart secret to query for guest cart access control\n if (cartSecret && typeof cartSecret === 'string') {\n req.query = req.query || {}\n req.query.secret = cartSecret\n }\n\n cart = await payload.findByID({\n id: cartID,\n collection: cartsSlug,\n depth: 2,\n overrideAccess: false,\n req,\n select: {\n id: true,\n currency: true,\n customerEmail: true,\n items: true,\n subtotal: true,\n },\n })\n\n if (!cart) {\n return Response.json(\n {\n message: `Cart with ID ${cartID} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n } else {\n return Response.json(\n {\n message: 'Cart ID is required.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (cart.currency && typeof cart.currency === 'string') {\n currency = cart.currency\n }\n\n // Ensure the currency is provided or inferred in some way\n if (!currency) {\n return Response.json(\n {\n message: 'Currency is required.',\n },\n {\n status: 400,\n },\n )\n }\n\n // Ensure the selected currency is supported\n if (\n !currenciesConfig.supportedCurrencies.find(\n (c) => c.code.toLocaleLowerCase() === currency.toLocaleLowerCase(),\n )\n ) {\n return Response.json(\n {\n message: `Currency ${currency} is not supported.`,\n },\n {\n status: 400,\n },\n )\n }\n\n // Verify the cart is available and items are present in an array\n if (!cart || !cart.items || !Array.isArray(cart.items) || cart.items.length === 0) {\n return Response.json(\n {\n message: 'Cart is required and must contain at least one item.',\n },\n {\n status: 400,\n },\n )\n }\n\n for (const item of cart.items) {\n // Target field to check the price based on the currency so we can validate the total\n const priceField = `priceIn${currency.toUpperCase()}`\n const quantity = item.quantity || 1\n\n // If the item has a product but no variant, we assume the product has a price in the specified currency\n if (item.product && !item.variant) {\n const id = typeof item.product === 'object' ? item.product.id : item.product\n\n const product = await payload.findByID({\n id,\n collection: productsSlug,\n depth: 0,\n select: {\n inventory: true,\n [priceField]: true,\n },\n })\n\n if (!product) {\n return Response.json(\n {\n message: `Product with ID ${item.product} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n\n try {\n if (productsValidation) {\n await productsValidation({ currenciesConfig, currency, product, quantity })\n } else {\n await defaultProductsValidation({\n currenciesConfig,\n currency,\n product,\n quantity,\n })\n }\n } catch (error) {\n payload.logger.error(\n error,\n 'Error validating product or variant during payment initiation.',\n )\n\n return Response.json(\n {\n message: error,\n ...(error instanceof Error ? { cause: error.cause } : {}),\n },\n {\n status: 400,\n },\n )\n }\n\n if (item.variant) {\n const id = typeof item.variant === 'object' ? item.variant.id : item.variant\n\n const variant = await payload.findByID({\n id,\n collection: variantsSlug,\n depth: 0,\n select: {\n inventory: true,\n [priceField]: true,\n },\n })\n\n if (!variant) {\n return Response.json(\n {\n message: `Variant with ID ${item.variant} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n\n try {\n if (productsValidation) {\n await productsValidation({\n currenciesConfig,\n currency,\n product: item.product,\n quantity,\n variant,\n })\n } else {\n await defaultProductsValidation({\n currenciesConfig,\n currency,\n product: item.product,\n quantity,\n variant,\n })\n }\n } catch (error) {\n payload.logger.error(\n error,\n 'Error validating product or variant during payment initiation.',\n )\n\n return Response.json(\n {\n message: error,\n },\n {\n status: 400,\n },\n )\n }\n }\n }\n }\n\n try {\n const paymentResponse = await paymentMethod.initiatePayment({\n customersSlug,\n data: {\n billingAddress,\n cart,\n currency,\n customerEmail,\n shippingAddress,\n },\n req,\n transactionsSlug,\n })\n\n return Response.json(paymentResponse)\n } catch (error) {\n payload.logger.error(error, 'Error initiating payment.')\n\n return Response.json(\n {\n message: 'Error initiating payment.',\n },\n {\n status: 500,\n },\n )\n }\n }\n"],"names":["addDataAndFileToRequest","defaultProductsValidation","initiatePaymentHandler","cartsSlug","currenciesConfig","customersSlug","paymentMethod","productsSlug","productsValidation","transactionsSlug","variantsSlug","req","data","payload","user","currency","defaultCurrency","cartID","cart","undefined","billingAddress","shippingAddress","cartSecret","secret","customerEmail","email","docs","Array","isArray","length","id","Response","json","message","status","query","findByID","collection","depth","overrideAccess","select","items","subtotal","supportedCurrencies","find","c","code","toLocaleLowerCase","item","priceField","toUpperCase","quantity","product","variant","inventory","error","logger","Error","cause","paymentResponse","initiatePayment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/endpoints/initiatePayment.ts"],"sourcesContent":["import { addDataAndFileToRequest, type DefaultDocumentIDType, type Endpoint } from 'payload'\n\nimport type {\n CurrenciesConfig,\n PaymentAdapter,\n ProductsValidation,\n SanitizedEcommercePluginConfig,\n UserWithCart,\n} from '../types/index.js'\n\nimport { defaultProductsValidation } from '../utilities/defaultProductsValidation.js'\n\ntype Args = {\n /**\n * The slug of the carts collection, defaults to 'carts'.\n */\n cartsSlug?: string\n currenciesConfig: CurrenciesConfig\n /**\n * The slug of the customers collection, defaults to 'users'.\n */\n customersSlug?: string\n /**\n * Track inventory stock for the products and variants.\n * Accepts an object to override the default field name.\n */\n inventory?: SanitizedEcommercePluginConfig['inventory']\n paymentMethod: PaymentAdapter\n /**\n * The slug of the products collection, defaults to 'products'.\n */\n productsSlug?: string\n /**\n * Customise the validation used for checking products or variants before a transaction is created.\n */\n productsValidation?: ProductsValidation\n /**\n * The slug of the transactions collection, defaults to 'transactions'.\n */\n transactionsSlug?: string\n /**\n * The slug of the variants collection, defaults to 'variants'.\n */\n variantsSlug?: string\n}\n\ntype InitiatePayment = (args: Args) => Endpoint['handler']\n\n/**\n * Handles the endpoint for initiating payments. We will handle checking the amount and product and variant prices here before it is sent to the payment provider.\n * This is the first step in the payment process.\n */\nexport const initiatePaymentHandler: InitiatePayment =\n ({\n cartsSlug = 'carts',\n currenciesConfig,\n customersSlug = 'users',\n paymentMethod,\n productsSlug = 'products',\n productsValidation,\n transactionsSlug = 'transactions',\n variantsSlug = 'variants',\n }) =>\n async (req) => {\n await addDataAndFileToRequest(req)\n const data = req.data\n const payload = req.payload\n const user = req.user as null | UserWithCart\n\n let currency: string = currenciesConfig.defaultCurrency\n let cartID: DefaultDocumentIDType = data?.cartID\n let cart: any = undefined\n const billingAddress = data?.billingAddress\n const shippingAddress = data?.shippingAddress\n const cartSecret = data?.secret\n\n let customerEmail: string = user?.email ?? ''\n\n if (user) {\n if (user.cart?.docs && Array.isArray(user.cart.docs) && user.cart.docs.length > 0) {\n if (!cartID && user.cart.docs[0]) {\n // Use the user's cart instead\n if (typeof user.cart.docs[0] === 'object') {\n cartID = user.cart.docs[0].id\n cart = user.cart.docs[0]\n } else {\n cartID = user.cart.docs[0]\n }\n }\n }\n } else {\n // Get the email from the data if user is not available\n if (data?.customerEmail && typeof data.customerEmail === 'string') {\n customerEmail = data.customerEmail\n } else {\n return Response.json(\n {\n message: 'A customer email is required to make a purchase.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (!cart) {\n if (cartID) {\n // Add cart secret to query for guest cart access control\n if (cartSecret && typeof cartSecret === 'string') {\n req.query = req.query || {}\n req.query.secret = cartSecret\n }\n\n cart = await payload.findByID({\n id: cartID,\n collection: cartsSlug,\n depth: 2,\n overrideAccess: false,\n req,\n select: {\n id: true,\n currency: true,\n customerEmail: true,\n items: true,\n subtotal: true,\n },\n })\n\n if (!cart) {\n return Response.json(\n {\n message: `Cart with ID ${cartID} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n } else {\n return Response.json(\n {\n message: 'Cart ID is required.',\n },\n {\n status: 400,\n },\n )\n }\n }\n\n if (cart.currency && typeof cart.currency === 'string') {\n currency = cart.currency\n }\n\n // Ensure the currency is provided or inferred in some way\n if (!currency) {\n return Response.json(\n {\n message: 'Currency is required.',\n },\n {\n status: 400,\n },\n )\n }\n\n // Ensure the selected currency is supported\n if (\n !currenciesConfig.supportedCurrencies.find(\n (c) => c.code.toLocaleLowerCase() === currency.toLocaleLowerCase(),\n )\n ) {\n return Response.json(\n {\n message: `Currency ${currency} is not supported.`,\n },\n {\n status: 400,\n },\n )\n }\n\n // Verify the cart is available and items are present in an array\n if (!cart || !cart.items || !Array.isArray(cart.items) || cart.items.length === 0) {\n return Response.json(\n {\n message: 'Cart is required and must contain at least one item.',\n },\n {\n status: 400,\n },\n )\n }\n\n for (const item of cart.items) {\n // Target field to check the price based on the currency so we can validate the total\n const priceField = `priceIn${currency.toUpperCase()}`\n const quantity = item.quantity || 1\n\n // If the item has a product but no variant, we assume the product has a price in the specified currency\n if (item.product && !item.variant) {\n const id = typeof item.product === 'object' ? item.product.id : item.product\n\n const product = await payload.findByID({\n id,\n collection: productsSlug,\n depth: 0,\n overrideAccess: true,\n select: {\n inventory: true,\n [priceField]: true,\n },\n })\n\n if (!product) {\n return Response.json(\n {\n message: `Product with ID ${item.product} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n\n try {\n if (productsValidation) {\n await productsValidation({ currenciesConfig, currency, product, quantity })\n } else {\n await defaultProductsValidation({\n currenciesConfig,\n currency,\n product,\n quantity,\n })\n }\n } catch (error) {\n payload.logger.error(\n error,\n 'Error validating product or variant during payment initiation.',\n )\n\n return Response.json(\n {\n message: error,\n ...(error instanceof Error ? { cause: error.cause } : {}),\n },\n {\n status: 400,\n },\n )\n }\n\n if (item.variant) {\n const id = typeof item.variant === 'object' ? item.variant.id : item.variant\n\n const variant = await payload.findByID({\n id,\n collection: variantsSlug,\n depth: 0,\n overrideAccess: true,\n select: {\n inventory: true,\n [priceField]: true,\n },\n })\n\n if (!variant) {\n return Response.json(\n {\n message: `Variant with ID ${item.variant} not found.`,\n },\n {\n status: 404,\n },\n )\n }\n\n try {\n if (productsValidation) {\n await productsValidation({\n currenciesConfig,\n currency,\n product: item.product,\n quantity,\n variant,\n })\n } else {\n await defaultProductsValidation({\n currenciesConfig,\n currency,\n product: item.product,\n quantity,\n variant,\n })\n }\n } catch (error) {\n payload.logger.error(\n error,\n 'Error validating product or variant during payment initiation.',\n )\n\n return Response.json(\n {\n message: error,\n },\n {\n status: 400,\n },\n )\n }\n }\n }\n }\n\n try {\n const paymentResponse = await paymentMethod.initiatePayment({\n customersSlug,\n data: {\n billingAddress,\n cart,\n currency,\n customerEmail,\n shippingAddress,\n },\n req,\n transactionsSlug,\n })\n\n return Response.json(paymentResponse)\n } catch (error) {\n payload.logger.error(error, 'Error initiating payment.')\n\n return Response.json(\n {\n message: 'Error initiating payment.',\n },\n {\n status: 500,\n },\n )\n }\n }\n"],"names":["addDataAndFileToRequest","defaultProductsValidation","initiatePaymentHandler","cartsSlug","currenciesConfig","customersSlug","paymentMethod","productsSlug","productsValidation","transactionsSlug","variantsSlug","req","data","payload","user","currency","defaultCurrency","cartID","cart","undefined","billingAddress","shippingAddress","cartSecret","secret","customerEmail","email","docs","Array","isArray","length","id","Response","json","message","status","query","findByID","collection","depth","overrideAccess","select","items","subtotal","supportedCurrencies","find","c","code","toLocaleLowerCase","item","priceField","toUpperCase","quantity","product","variant","inventory","error","logger","Error","cause","paymentResponse","initiatePayment"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statusField.d.ts","sourceRoot":"","sources":["../../src/fields/statusField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"statusField.d.ts","sourceRoot":"","sources":["../../src/fields/statusField.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,SAAS,CAoChD,CAAA;AAED,KAAK,KAAK,GAAG;IACX,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,WAiB5C,CAAA"}
|
|
@@ -4,6 +4,11 @@ export const statusOptions = [
|
|
|
4
4
|
label: ({ t })=>t('plugin-ecommerce:pending'),
|
|
5
5
|
value: 'pending'
|
|
6
6
|
},
|
|
7
|
+
{
|
|
8
|
+
// @ts-expect-error - translations are not typed in plugins yet
|
|
9
|
+
label: ({ t })=>t('plugin-ecommerce:processing'),
|
|
10
|
+
value: 'processing'
|
|
11
|
+
},
|
|
7
12
|
{
|
|
8
13
|
// @ts-expect-error - translations are not typed in plugins yet
|
|
9
14
|
label: ({ t })=>t('plugin-ecommerce:succeeded'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/statusField.ts"],"sourcesContent":["import type { SelectField } from 'payload'\n\nexport const statusOptions: SelectField['options'] = [\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:pending'),\n value: 'pending',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:succeeded'),\n value: 'succeeded',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:failed'),\n value: 'failed',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:cancelled'),\n value: 'cancelled',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:expired'),\n value: 'expired',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:refunded'),\n value: 'refunded',\n },\n]\n\ntype Props = {\n overrides?: Partial<SelectField>\n}\n\nexport const statusField: (props?: Props) => SelectField = (props) => {\n const { overrides } = props || {}\n\n // @ts-expect-error - issue with payload types\n const field: SelectField = {\n name: 'status',\n type: 'select',\n defaultValue: 'pending',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:status'),\n options: statusOptions,\n required: true,\n ...overrides,\n }\n\n return field\n}\n"],"names":["statusOptions","label","t","value","statusField","props","overrides","field","name","type","defaultValue","options","required"],"mappings":"AAEA,OAAO,MAAMA,gBAAwC;IACnD;QACE,+DAA+D;QAC/DC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;CACD,CAAA;AAMD,OAAO,MAAMC,cAA8C,CAACC;IAC1D,MAAM,EAAEC,SAAS,EAAE,GAAGD,SAAS,CAAC;IAEhC,8CAA8C;IAC9C,MAAME,QAAqB;QACzBC,MAAM;QACNC,MAAM;QACNC,cAAc;QACdT,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;YAC/DA,EAAE;QACJS,SAASX;QACTY,UAAU;QACV,GAAGN,SAAS;IACd;IAEA,OAAOC;AACT,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/fields/statusField.ts"],"sourcesContent":["import type { SelectField } from 'payload'\n\nexport const statusOptions: SelectField['options'] = [\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:pending'),\n value: 'pending',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:processing'),\n value: 'processing',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:succeeded'),\n value: 'succeeded',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:failed'),\n value: 'failed',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:cancelled'),\n value: 'cancelled',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:expired'),\n value: 'expired',\n },\n {\n // @ts-expect-error - translations are not typed in plugins yet\n label: ({ t }) => t('plugin-ecommerce:refunded'),\n value: 'refunded',\n },\n]\n\ntype Props = {\n overrides?: Partial<SelectField>\n}\n\nexport const statusField: (props?: Props) => SelectField = (props) => {\n const { overrides } = props || {}\n\n // @ts-expect-error - issue with payload types\n const field: SelectField = {\n name: 'status',\n type: 'select',\n defaultValue: 'pending',\n label: ({ t }) =>\n // @ts-expect-error - translations are not typed in plugins yet\n t('plugin-ecommerce:status'),\n options: statusOptions,\n required: true,\n ...overrides,\n }\n\n return field\n}\n"],"names":["statusOptions","label","t","value","statusField","props","overrides","field","name","type","defaultValue","options","required"],"mappings":"AAEA,OAAO,MAAMA,gBAAwC;IACnD;QACE,+DAA+D;QAC/DC,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;IACA;QACE,+DAA+D;QAC/DF,OAAO,CAAC,EAAEC,CAAC,EAAE,GAAKA,EAAE;QACpBC,OAAO;IACT;CACD,CAAA;AAMD,OAAO,MAAMC,cAA8C,CAACC;IAC1D,MAAM,EAAEC,SAAS,EAAE,GAAGD,SAAS,CAAC;IAEhC,8CAA8C;IAC9C,MAAME,QAAqB;QACzBC,MAAM;QACNC,MAAM;QACNC,cAAc;QACdT,OAAO,CAAC,EAAEC,CAAC,EAAE,GACX,+DAA+D;YAC/DA,EAAE;QACJS,SAASX;QACTY,UAAU;QACV,GAAGN,SAAS;IACd;IAEA,OAAOC;AACT,EAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAkC,MAAM,kBAAkB,CAAA;AAE7F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sDAAsD,CAAA;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAA;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAA;AAC7F,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,8BAA8B,EAAE,MAAM,0DAA0D,CAAA;AACzG,OAAO,EAAE,wBAAwB,EAAE,MAAM,0DAA0D,CAAA;AACnG,OAAO,EAAE,4BAA4B,EAAE,MAAM,wDAAwD,CAAA;AAQrG,eAAO,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,qBAAqB,EAAkC,MAAM,kBAAkB,CAAA;AAE7F,OAAO,EAAE,yBAAyB,EAAE,MAAM,sDAAsD,CAAA;AAChG,OAAO,EAAE,qBAAqB,EAAE,MAAM,8CAA8C,CAAA;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gDAAgD,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,oDAAoD,CAAA;AAC7F,OAAO,EAAE,4BAA4B,EAAE,MAAM,4DAA4D,CAAA;AACzG,OAAO,EAAE,8BAA8B,EAAE,MAAM,0DAA0D,CAAA;AACzG,OAAO,EAAE,wBAAwB,EAAE,MAAM,0DAA0D,CAAA;AACnG,OAAO,EAAE,4BAA4B,EAAE,MAAM,wDAAwD,CAAA;AAQrG,eAAO,MAAM,eAAe,2EAmV1B,CAAA;AAEF,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,EAC5B,8BAA8B,EAC9B,wBAAwB,EACxB,4BAA4B,GAC7B,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,MAAM,2CAA2C,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,6CAA6C,CAAA;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0DAA0D,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAA;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAA;AAC3E,YAAY,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,cAAc,EACd,cAAc,GACf,MAAM,yCAAyC,CAAA;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,8CAA8C,CAAA;AACzE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA"}
|