@payloadcms/plugin-ecommerce 3.84.0-internal.d5d6e43 → 3.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collections/orders/createOrdersCollection.d.ts +0 -6
- package/dist/collections/orders/createOrdersCollection.d.ts.map +1 -1
- package/dist/collections/orders/createOrdersCollection.js +1 -7
- package/dist/collections/orders/createOrdersCollection.js.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.d.ts +0 -6
- package/dist/collections/transactions/createTransactionsCollection.d.ts.map +1 -1
- package/dist/collections/transactions/createTransactionsCollection.js +1 -7
- package/dist/collections/transactions/createTransactionsCollection.js.map +1 -1
- package/dist/endpoints/confirmOrder.d.ts +1 -11
- package/dist/endpoints/confirmOrder.d.ts.map +1 -1
- package/dist/endpoints/confirmOrder.js +2 -74
- package/dist/endpoints/confirmOrder.js.map +1 -1
- package/dist/endpoints/initiatePayment.d.ts +1 -11
- package/dist/endpoints/initiatePayment.d.ts.map +1 -1
- package/dist/endpoints/initiatePayment.js +3 -74
- package/dist/endpoints/initiatePayment.js.map +1 -1
- package/dist/exports/types.d.ts +1 -1
- package/dist/exports/types.d.ts.map +1 -1
- package/dist/exports/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -11
- package/dist/index.js.map +1 -1
- package/dist/payments/adapters/stripe/index.d.ts +1 -2
- package/dist/payments/adapters/stripe/index.d.ts.map +1 -1
- package/dist/payments/adapters/stripe/index.js.map +1 -1
- package/dist/payments/adapters/stripe/initiatePayment.d.ts.map +1 -1
- package/dist/payments/adapters/stripe/initiatePayment.js +3 -6
- package/dist/payments/adapters/stripe/initiatePayment.js.map +1 -1
- package/dist/react/provider/index.d.ts +1 -0
- package/dist/react/provider/index.d.ts.map +1 -1
- package/dist/react/provider/index.js +9 -7
- package/dist/react/provider/index.js.map +1 -1
- package/dist/types/index.d.ts +6 -201
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/ui/PriceCell/index.d.ts.map +1 -1
- package/dist/ui/PriceCell/index.js +9 -11
- package/dist/ui/PriceCell/index.js.map +1 -1
- package/dist/ui/PriceRowLabel/index.d.ts.map +1 -1
- package/dist/ui/PriceRowLabel/index.js +15 -15
- package/dist/ui/PriceRowLabel/index.js.map +1 -1
- package/dist/ui/utilities.d.ts +11 -0
- package/dist/ui/utilities.d.ts.map +1 -1
- package/dist/ui/utilities.js +14 -0
- package/dist/ui/utilities.js.map +1 -1
- package/dist/utilities/sanitizePluginConfig.spec.js +0 -35
- package/dist/utilities/sanitizePluginConfig.spec.js.map +1 -1
- package/package.json +7 -7
- package/dist/fields/summaryField.d.ts +0 -14
- package/dist/fields/summaryField.d.ts.map +0 -1
- package/dist/fields/summaryField.js +0 -83
- package/dist/fields/summaryField.js.map +0 -1
- package/dist/utilities/runPaymentHooks.d.ts +0 -28
- package/dist/utilities/runPaymentHooks.d.ts.map +0 -1
- package/dist/utilities/runPaymentHooks.js +0 -68
- package/dist/utilities/runPaymentHooks.js.map +0 -1
- package/dist/utilities/runPaymentHooks.spec.js +0 -324
- package/dist/utilities/runPaymentHooks.spec.js.map +0 -1
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { amountField } from './amountField.js';
|
|
2
|
-
import { currencyField } from './currencyField.js';
|
|
3
|
-
/**
|
|
4
|
-
* A read-only group field that records the computed payment summary for a
|
|
5
|
-
* transaction or order — total, currency, and the ordered list of lines
|
|
6
|
-
* (subtotal, tax, shipping, discount, etc.) produced by the payment hook pipeline.
|
|
7
|
-
*/ export const summaryField = ({ currenciesConfig, overrides })=>{
|
|
8
|
-
const lineFields = [
|
|
9
|
-
{
|
|
10
|
-
name: 'type',
|
|
11
|
-
type: 'select',
|
|
12
|
-
options: [
|
|
13
|
-
{
|
|
14
|
-
label: 'Subtotal',
|
|
15
|
-
value: 'subtotal'
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
label: 'Tax',
|
|
19
|
-
value: 'tax'
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
label: 'Shipping',
|
|
23
|
-
value: 'shipping'
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
label: 'Discount',
|
|
27
|
-
value: 'discount'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
label: 'Gift Card',
|
|
31
|
-
value: 'gift_card'
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
label: 'Custom',
|
|
35
|
-
value: 'custom'
|
|
36
|
-
}
|
|
37
|
-
],
|
|
38
|
-
required: true
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'label',
|
|
42
|
-
type: 'text',
|
|
43
|
-
required: true
|
|
44
|
-
},
|
|
45
|
-
amountField({
|
|
46
|
-
currenciesConfig,
|
|
47
|
-
overrides: {
|
|
48
|
-
required: true
|
|
49
|
-
}
|
|
50
|
-
}),
|
|
51
|
-
{
|
|
52
|
-
name: 'metadata',
|
|
53
|
-
type: 'json'
|
|
54
|
-
}
|
|
55
|
-
];
|
|
56
|
-
const field = {
|
|
57
|
-
name: 'summary',
|
|
58
|
-
type: 'group',
|
|
59
|
-
admin: {
|
|
60
|
-
readOnly: true
|
|
61
|
-
},
|
|
62
|
-
fields: [
|
|
63
|
-
amountField({
|
|
64
|
-
currenciesConfig,
|
|
65
|
-
overrides: {
|
|
66
|
-
name: 'total'
|
|
67
|
-
}
|
|
68
|
-
}),
|
|
69
|
-
currencyField({
|
|
70
|
-
currenciesConfig
|
|
71
|
-
}),
|
|
72
|
-
{
|
|
73
|
-
name: 'lines',
|
|
74
|
-
type: 'array',
|
|
75
|
-
fields: lineFields
|
|
76
|
-
}
|
|
77
|
-
],
|
|
78
|
-
...overrides
|
|
79
|
-
};
|
|
80
|
-
return field;
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
//# sourceMappingURL=summaryField.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/fields/summaryField.ts"],"sourcesContent":["import type { Field, GroupField } from 'payload'\n\nimport type { CurrenciesConfig } from '../types/index.js'\n\nimport { amountField } from './amountField.js'\nimport { currencyField } from './currencyField.js'\n\ntype Props = {\n currenciesConfig: CurrenciesConfig\n overrides?: Partial<GroupField>\n}\n\n/**\n * A read-only group field that records the computed payment summary for a\n * transaction or order — total, currency, and the ordered list of lines\n * (subtotal, tax, shipping, discount, etc.) produced by the payment hook pipeline.\n */\nexport const summaryField: (props: Props) => GroupField = ({ currenciesConfig, overrides }) => {\n const lineFields: Field[] = [\n {\n name: 'type',\n type: 'select',\n options: [\n { label: 'Subtotal', value: 'subtotal' },\n { label: 'Tax', value: 'tax' },\n { label: 'Shipping', value: 'shipping' },\n { label: 'Discount', value: 'discount' },\n { label: 'Gift Card', value: 'gift_card' },\n { label: 'Custom', value: 'custom' },\n ],\n required: true,\n },\n {\n name: 'label',\n type: 'text',\n required: true,\n },\n amountField({\n currenciesConfig,\n overrides: { required: true },\n }),\n {\n name: 'metadata',\n type: 'json',\n },\n ]\n\n const field: GroupField = {\n name: 'summary',\n type: 'group',\n admin: {\n readOnly: true,\n },\n fields: [\n amountField({\n currenciesConfig,\n overrides: { name: 'total' },\n }),\n currencyField({ currenciesConfig }),\n {\n name: 'lines',\n type: 'array',\n fields: lineFields,\n },\n ],\n ...overrides,\n }\n\n return field\n}\n"],"names":["amountField","currencyField","summaryField","currenciesConfig","overrides","lineFields","name","type","options","label","value","required","field","admin","readOnly","fields"],"mappings":"AAIA,SAASA,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,aAAa,QAAQ,qBAAoB;AAOlD;;;;CAIC,GACD,OAAO,MAAMC,eAA6C,CAAC,EAAEC,gBAAgB,EAAEC,SAAS,EAAE;IACxF,MAAMC,aAAsB;QAC1B;YACEC,MAAM;YACNC,MAAM;YACNC,SAAS;gBACP;oBAAEC,OAAO;oBAAYC,OAAO;gBAAW;gBACvC;oBAAED,OAAO;oBAAOC,OAAO;gBAAM;gBAC7B;oBAAED,OAAO;oBAAYC,OAAO;gBAAW;gBACvC;oBAAED,OAAO;oBAAYC,OAAO;gBAAW;gBACvC;oBAAED,OAAO;oBAAaC,OAAO;gBAAY;gBACzC;oBAAED,OAAO;oBAAUC,OAAO;gBAAS;aACpC;YACDC,UAAU;QACZ;QACA;YACEL,MAAM;YACNC,MAAM;YACNI,UAAU;QACZ;QACAX,YAAY;YACVG;YACAC,WAAW;gBAAEO,UAAU;YAAK;QAC9B;QACA;YACEL,MAAM;YACNC,MAAM;QACR;KACD;IAED,MAAMK,QAAoB;QACxBN,MAAM;QACNC,MAAM;QACNM,OAAO;YACLC,UAAU;QACZ;QACAC,QAAQ;YACNf,YAAY;gBACVG;gBACAC,WAAW;oBAAEE,MAAM;gBAAQ;YAC7B;YACAL,cAAc;gBAAEE;YAAiB;YACjC;gBACEG,MAAM;gBACNC,MAAM;gBACNQ,QAAQV;YACV;SACD;QACD,GAAGD,SAAS;IACd;IAEA,OAAOQ;AACT,EAAC"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { AfterConfirmOrderHook, BeforeConfirmOrderHook, BeforeInitiatePaymentHook, Summary } from '../types/index.js';
|
|
2
|
-
/**
|
|
3
|
-
* Runs beforeInitiatePayment hooks sequentially, piping the Summary through each.
|
|
4
|
-
*
|
|
5
|
-
* After every hook, the plugin:
|
|
6
|
-
* 1. Recomputes `total` from `sum(lines[].amount)` — any total the hook sets is ignored.
|
|
7
|
-
* 2. Validates `lines[0]` is still the subtotal line with the original cart subtotal.
|
|
8
|
-
* 3. Validates `currency` has not changed.
|
|
9
|
-
*
|
|
10
|
-
* Throws (aborting the payment) if a hook throws or breaks an invariant.
|
|
11
|
-
*/
|
|
12
|
-
export declare function runBeforeInitiatePaymentHooks(hooks: BeforeInitiatePaymentHook[], context: {
|
|
13
|
-
summary: Summary;
|
|
14
|
-
} & Omit<Parameters<BeforeInitiatePaymentHook>[0], 'summary'>): Promise<Summary>;
|
|
15
|
-
/**
|
|
16
|
-
* Runs beforeConfirmOrder hooks sequentially.
|
|
17
|
-
* Throws if any hook throws, aborting the confirmation.
|
|
18
|
-
*/
|
|
19
|
-
export declare function runBeforeConfirmOrderHooks(hooks: BeforeConfirmOrderHook[], context: Parameters<BeforeConfirmOrderHook>[0]): Promise<void>;
|
|
20
|
-
/**
|
|
21
|
-
* Runs afterConfirmOrder hooks sequentially.
|
|
22
|
-
* Errors are caught and logged but do not fail the response.
|
|
23
|
-
* All hooks execute even if some fail.
|
|
24
|
-
*/
|
|
25
|
-
export declare function runAfterConfirmOrderHooks(hooks: AfterConfirmOrderHook[], context: Parameters<AfterConfirmOrderHook>[0], logger: {
|
|
26
|
-
error: (...args: unknown[]) => void;
|
|
27
|
-
}): Promise<void>;
|
|
28
|
-
//# sourceMappingURL=runPaymentHooks.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runPaymentHooks.d.ts","sourceRoot":"","sources":["../../src/utilities/runPaymentHooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,OAAO,EACR,MAAM,mBAAmB,CAAA;AAuC1B;;;;;;;;;GASG;AACH,wBAAsB,6BAA6B,CACjD,KAAK,EAAE,yBAAyB,EAAE,EAClC,OAAO,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,GACxF,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,sBAAsB,EAAE,EAC/B,OAAO,EAAE,UAAU,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,GAC7C,OAAO,CAAC,IAAI,CAAC,CAIf;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,qBAAqB,EAAE,EAC9B,OAAO,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAC7C,MAAM,EAAE;IAAE,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAA;CAAE,GAC9C,OAAO,CAAC,IAAI,CAAC,CAQf"}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
const recomputeTotal = (summary)=>({
|
|
2
|
-
...summary,
|
|
3
|
-
total: summary.lines.reduce((sum, line)=>sum + line.amount, 0)
|
|
4
|
-
});
|
|
5
|
-
const assertSummaryInvariants = (summary, expected, hookIndex)=>{
|
|
6
|
-
if (!summary || !Array.isArray(summary.lines)) {
|
|
7
|
-
throw new Error(`beforeInitiatePayment hook ${hookIndex} returned an invalid summary (missing lines).`);
|
|
8
|
-
}
|
|
9
|
-
const subtotalLine = summary.lines[0];
|
|
10
|
-
if (!subtotalLine || subtotalLine.type !== 'subtotal') {
|
|
11
|
-
throw new Error(`beforeInitiatePayment hook ${hookIndex} removed or reordered the subtotal line. lines[0] must always be the cart subtotal.`);
|
|
12
|
-
}
|
|
13
|
-
if (subtotalLine.amount !== expected.subtotal) {
|
|
14
|
-
throw new Error(`beforeInitiatePayment hook ${hookIndex} changed the subtotal amount from ${expected.subtotal} to ${subtotalLine.amount}. Subtotal is managed by the plugin and must not be mutated.`);
|
|
15
|
-
}
|
|
16
|
-
if (summary.currency !== expected.currency) {
|
|
17
|
-
throw new Error(`beforeInitiatePayment hook ${hookIndex} changed summary.currency — currency must remain "${expected.currency}".`);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Runs beforeInitiatePayment hooks sequentially, piping the Summary through each.
|
|
22
|
-
*
|
|
23
|
-
* After every hook, the plugin:
|
|
24
|
-
* 1. Recomputes `total` from `sum(lines[].amount)` — any total the hook sets is ignored.
|
|
25
|
-
* 2. Validates `lines[0]` is still the subtotal line with the original cart subtotal.
|
|
26
|
-
* 3. Validates `currency` has not changed.
|
|
27
|
-
*
|
|
28
|
-
* Throws (aborting the payment) if a hook throws or breaks an invariant.
|
|
29
|
-
*/ export async function runBeforeInitiatePaymentHooks(hooks, context) {
|
|
30
|
-
let summary = recomputeTotal(context.summary);
|
|
31
|
-
const expected = {
|
|
32
|
-
currency: summary.currency,
|
|
33
|
-
subtotal: summary.lines[0]?.amount ?? 0
|
|
34
|
-
};
|
|
35
|
-
for(let i = 0; i < hooks.length; i++){
|
|
36
|
-
const hook = hooks[i];
|
|
37
|
-
const next = await hook({
|
|
38
|
-
...context,
|
|
39
|
-
summary
|
|
40
|
-
});
|
|
41
|
-
assertSummaryInvariants(next, expected, i);
|
|
42
|
-
summary = recomputeTotal(next);
|
|
43
|
-
}
|
|
44
|
-
return summary;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Runs beforeConfirmOrder hooks sequentially.
|
|
48
|
-
* Throws if any hook throws, aborting the confirmation.
|
|
49
|
-
*/ export async function runBeforeConfirmOrderHooks(hooks, context) {
|
|
50
|
-
for (const hook of hooks){
|
|
51
|
-
await hook(context);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Runs afterConfirmOrder hooks sequentially.
|
|
56
|
-
* Errors are caught and logged but do not fail the response.
|
|
57
|
-
* All hooks execute even if some fail.
|
|
58
|
-
*/ export async function runAfterConfirmOrderHooks(hooks, context, logger) {
|
|
59
|
-
for (const hook of hooks){
|
|
60
|
-
try {
|
|
61
|
-
await hook(context);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
logger.error(error, 'Error in afterConfirmOrder hook.');
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
//# sourceMappingURL=runPaymentHooks.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/runPaymentHooks.ts"],"sourcesContent":["import type {\n AfterConfirmOrderHook,\n BeforeConfirmOrderHook,\n BeforeInitiatePaymentHook,\n Summary,\n} from '../types/index.js'\n\nconst recomputeTotal = (summary: Summary): Summary => ({\n ...summary,\n total: summary.lines.reduce((sum, line) => sum + line.amount, 0),\n})\n\nconst assertSummaryInvariants = (\n summary: Summary,\n expected: { currency: string; subtotal: number },\n hookIndex: number,\n): void => {\n if (!summary || !Array.isArray(summary.lines)) {\n throw new Error(\n `beforeInitiatePayment hook ${hookIndex} returned an invalid summary (missing lines).`,\n )\n }\n\n const subtotalLine = summary.lines[0]\n\n if (!subtotalLine || subtotalLine.type !== 'subtotal') {\n throw new Error(\n `beforeInitiatePayment hook ${hookIndex} removed or reordered the subtotal line. lines[0] must always be the cart subtotal.`,\n )\n }\n\n if (subtotalLine.amount !== expected.subtotal) {\n throw new Error(\n `beforeInitiatePayment hook ${hookIndex} changed the subtotal amount from ${expected.subtotal} to ${subtotalLine.amount}. Subtotal is managed by the plugin and must not be mutated.`,\n )\n }\n\n if (summary.currency !== expected.currency) {\n throw new Error(\n `beforeInitiatePayment hook ${hookIndex} changed summary.currency — currency must remain \"${expected.currency}\".`,\n )\n }\n}\n\n/**\n * Runs beforeInitiatePayment hooks sequentially, piping the Summary through each.\n *\n * After every hook, the plugin:\n * 1. Recomputes `total` from `sum(lines[].amount)` — any total the hook sets is ignored.\n * 2. Validates `lines[0]` is still the subtotal line with the original cart subtotal.\n * 3. Validates `currency` has not changed.\n *\n * Throws (aborting the payment) if a hook throws or breaks an invariant.\n */\nexport async function runBeforeInitiatePaymentHooks(\n hooks: BeforeInitiatePaymentHook[],\n context: { summary: Summary } & Omit<Parameters<BeforeInitiatePaymentHook>[0], 'summary'>,\n): Promise<Summary> {\n let summary: Summary = recomputeTotal(context.summary)\n\n const expected = {\n currency: summary.currency,\n subtotal: summary.lines[0]?.amount ?? 0,\n }\n\n for (let i = 0; i < hooks.length; i++) {\n const hook = hooks[i]!\n const next = await hook({ ...context, summary })\n\n assertSummaryInvariants(next, expected, i)\n summary = recomputeTotal(next)\n }\n\n return summary\n}\n\n/**\n * Runs beforeConfirmOrder hooks sequentially.\n * Throws if any hook throws, aborting the confirmation.\n */\nexport async function runBeforeConfirmOrderHooks(\n hooks: BeforeConfirmOrderHook[],\n context: Parameters<BeforeConfirmOrderHook>[0],\n): Promise<void> {\n for (const hook of hooks) {\n await hook(context)\n }\n}\n\n/**\n * Runs afterConfirmOrder hooks sequentially.\n * Errors are caught and logged but do not fail the response.\n * All hooks execute even if some fail.\n */\nexport async function runAfterConfirmOrderHooks(\n hooks: AfterConfirmOrderHook[],\n context: Parameters<AfterConfirmOrderHook>[0],\n logger: { error: (...args: unknown[]) => void },\n): Promise<void> {\n for (const hook of hooks) {\n try {\n await hook(context)\n } catch (error) {\n logger.error(error, 'Error in afterConfirmOrder hook.')\n }\n }\n}\n"],"names":["recomputeTotal","summary","total","lines","reduce","sum","line","amount","assertSummaryInvariants","expected","hookIndex","Array","isArray","Error","subtotalLine","type","subtotal","currency","runBeforeInitiatePaymentHooks","hooks","context","i","length","hook","next","runBeforeConfirmOrderHooks","runAfterConfirmOrderHooks","logger","error"],"mappings":"AAOA,MAAMA,iBAAiB,CAACC,UAA+B,CAAA;QACrD,GAAGA,OAAO;QACVC,OAAOD,QAAQE,KAAK,CAACC,MAAM,CAAC,CAACC,KAAKC,OAASD,MAAMC,KAAKC,MAAM,EAAE;IAChE,CAAA;AAEA,MAAMC,0BAA0B,CAC9BP,SACAQ,UACAC;IAEA,IAAI,CAACT,WAAW,CAACU,MAAMC,OAAO,CAACX,QAAQE,KAAK,GAAG;QAC7C,MAAM,IAAIU,MACR,CAAC,2BAA2B,EAAEH,UAAU,6CAA6C,CAAC;IAE1F;IAEA,MAAMI,eAAeb,QAAQE,KAAK,CAAC,EAAE;IAErC,IAAI,CAACW,gBAAgBA,aAAaC,IAAI,KAAK,YAAY;QACrD,MAAM,IAAIF,MACR,CAAC,2BAA2B,EAAEH,UAAU,mFAAmF,CAAC;IAEhI;IAEA,IAAII,aAAaP,MAAM,KAAKE,SAASO,QAAQ,EAAE;QAC7C,MAAM,IAAIH,MACR,CAAC,2BAA2B,EAAEH,UAAU,kCAAkC,EAAED,SAASO,QAAQ,CAAC,IAAI,EAAEF,aAAaP,MAAM,CAAC,4DAA4D,CAAC;IAEzL;IAEA,IAAIN,QAAQgB,QAAQ,KAAKR,SAASQ,QAAQ,EAAE;QAC1C,MAAM,IAAIJ,MACR,CAAC,2BAA2B,EAAEH,UAAU,kDAAkD,EAAED,SAASQ,QAAQ,CAAC,EAAE,CAAC;IAErH;AACF;AAEA;;;;;;;;;CASC,GACD,OAAO,eAAeC,8BACpBC,KAAkC,EAClCC,OAAyF;IAEzF,IAAInB,UAAmBD,eAAeoB,QAAQnB,OAAO;IAErD,MAAMQ,WAAW;QACfQ,UAAUhB,QAAQgB,QAAQ;QAC1BD,UAAUf,QAAQE,KAAK,CAAC,EAAE,EAAEI,UAAU;IACxC;IAEA,IAAK,IAAIc,IAAI,GAAGA,IAAIF,MAAMG,MAAM,EAAED,IAAK;QACrC,MAAME,OAAOJ,KAAK,CAACE,EAAE;QACrB,MAAMG,OAAO,MAAMD,KAAK;YAAE,GAAGH,OAAO;YAAEnB;QAAQ;QAE9CO,wBAAwBgB,MAAMf,UAAUY;QACxCpB,UAAUD,eAAewB;IAC3B;IAEA,OAAOvB;AACT;AAEA;;;CAGC,GACD,OAAO,eAAewB,2BACpBN,KAA+B,EAC/BC,OAA8C;IAE9C,KAAK,MAAMG,QAAQJ,MAAO;QACxB,MAAMI,KAAKH;IACb;AACF;AAEA;;;;CAIC,GACD,OAAO,eAAeM,0BACpBP,KAA8B,EAC9BC,OAA6C,EAC7CO,MAA+C;IAE/C,KAAK,MAAMJ,QAAQJ,MAAO;QACxB,IAAI;YACF,MAAMI,KAAKH;QACb,EAAE,OAAOQ,OAAO;YACdD,OAAOC,KAAK,CAACA,OAAO;QACtB;IACF;AACF"}
|
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { runAfterConfirmOrderHooks, runBeforeConfirmOrderHooks, runBeforeInitiatePaymentHooks } from './runPaymentHooks.js';
|
|
3
|
-
const createSummary = (subtotal = 1000)=>({
|
|
4
|
-
currency: 'USD',
|
|
5
|
-
lines: [
|
|
6
|
-
{
|
|
7
|
-
amount: subtotal,
|
|
8
|
-
label: 'Subtotal',
|
|
9
|
-
type: 'subtotal'
|
|
10
|
-
}
|
|
11
|
-
],
|
|
12
|
-
total: subtotal
|
|
13
|
-
});
|
|
14
|
-
const createMockInitiateContext = (overrides = {})=>({
|
|
15
|
-
billingAddress: undefined,
|
|
16
|
-
cart: {
|
|
17
|
-
id: 'cart-1',
|
|
18
|
-
items: [
|
|
19
|
-
{
|
|
20
|
-
id: 'item-1',
|
|
21
|
-
product: 'prod-1',
|
|
22
|
-
quantity: 1
|
|
23
|
-
}
|
|
24
|
-
],
|
|
25
|
-
subtotal: 1000
|
|
26
|
-
},
|
|
27
|
-
currenciesConfig: {
|
|
28
|
-
defaultCurrency: 'USD',
|
|
29
|
-
supportedCurrencies: [
|
|
30
|
-
{
|
|
31
|
-
code: 'USD',
|
|
32
|
-
decimals: 2,
|
|
33
|
-
label: 'US Dollar',
|
|
34
|
-
symbol: '$'
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
|
-
currency: 'USD',
|
|
39
|
-
customerEmail: 'test@example.com',
|
|
40
|
-
req: {},
|
|
41
|
-
shippingAddress: undefined,
|
|
42
|
-
summary: createSummary(),
|
|
43
|
-
...overrides
|
|
44
|
-
});
|
|
45
|
-
describe('runBeforeInitiatePaymentHooks', ()=>{
|
|
46
|
-
it('should return the incoming summary unchanged when no hooks are provided', async ()=>{
|
|
47
|
-
const context = createMockInitiateContext();
|
|
48
|
-
const result = await runBeforeInitiatePaymentHooks([], context);
|
|
49
|
-
expect(result.total).toBe(1000);
|
|
50
|
-
expect(result.lines).toHaveLength(1);
|
|
51
|
-
expect(result.lines[0]?.type).toBe('subtotal');
|
|
52
|
-
});
|
|
53
|
-
it('should append a single line and recompute total', async ()=>{
|
|
54
|
-
const taxHook = ({ summary })=>({
|
|
55
|
-
...summary,
|
|
56
|
-
lines: [
|
|
57
|
-
...summary.lines,
|
|
58
|
-
{
|
|
59
|
-
amount: 100,
|
|
60
|
-
label: 'Sales Tax',
|
|
61
|
-
type: 'tax'
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
});
|
|
65
|
-
const context = createMockInitiateContext();
|
|
66
|
-
const result = await runBeforeInitiatePaymentHooks([
|
|
67
|
-
taxHook
|
|
68
|
-
], context);
|
|
69
|
-
expect(result.lines).toHaveLength(2);
|
|
70
|
-
expect(result.total).toBe(1100);
|
|
71
|
-
});
|
|
72
|
-
it('should pipe summary through multiple hooks and recompute total after each', async ()=>{
|
|
73
|
-
const shippingHook = ({ summary })=>({
|
|
74
|
-
...summary,
|
|
75
|
-
lines: [
|
|
76
|
-
...summary.lines,
|
|
77
|
-
{
|
|
78
|
-
amount: 500,
|
|
79
|
-
label: 'Standard Shipping',
|
|
80
|
-
type: 'shipping'
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
});
|
|
84
|
-
const taxOnAllHook = ({ summary })=>{
|
|
85
|
-
const taxable = summary.lines.reduce((sum, l)=>sum + l.amount, 0);
|
|
86
|
-
return {
|
|
87
|
-
...summary,
|
|
88
|
-
lines: [
|
|
89
|
-
...summary.lines,
|
|
90
|
-
{
|
|
91
|
-
amount: Math.round(taxable * 0.1),
|
|
92
|
-
label: 'Tax (10%)',
|
|
93
|
-
type: 'tax'
|
|
94
|
-
}
|
|
95
|
-
]
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
const context = createMockInitiateContext();
|
|
99
|
-
const result = await runBeforeInitiatePaymentHooks([
|
|
100
|
-
shippingHook,
|
|
101
|
-
taxOnAllHook
|
|
102
|
-
], context);
|
|
103
|
-
expect(result.lines).toHaveLength(3);
|
|
104
|
-
expect(result.total).toBe(1000 + 500 + Math.round(1500 * 0.1));
|
|
105
|
-
});
|
|
106
|
-
it('should ignore any total a hook tries to set and recompute from lines', async ()=>{
|
|
107
|
-
const badHook = ({ summary })=>({
|
|
108
|
-
...summary,
|
|
109
|
-
lines: [
|
|
110
|
-
...summary.lines,
|
|
111
|
-
{
|
|
112
|
-
amount: 200,
|
|
113
|
-
label: 'Tax',
|
|
114
|
-
type: 'tax'
|
|
115
|
-
}
|
|
116
|
-
],
|
|
117
|
-
total: 999999
|
|
118
|
-
});
|
|
119
|
-
const context = createMockInitiateContext();
|
|
120
|
-
const result = await runBeforeInitiatePaymentHooks([
|
|
121
|
-
badHook
|
|
122
|
-
], context);
|
|
123
|
-
expect(result.total).toBe(1200);
|
|
124
|
-
});
|
|
125
|
-
it('should support async hooks', async ()=>{
|
|
126
|
-
const asyncHook = async ({ summary })=>({
|
|
127
|
-
...summary,
|
|
128
|
-
lines: [
|
|
129
|
-
...summary.lines,
|
|
130
|
-
{
|
|
131
|
-
amount: 200,
|
|
132
|
-
label: 'Async Tax',
|
|
133
|
-
type: 'tax'
|
|
134
|
-
}
|
|
135
|
-
]
|
|
136
|
-
});
|
|
137
|
-
const context = createMockInitiateContext();
|
|
138
|
-
const result = await runBeforeInitiatePaymentHooks([
|
|
139
|
-
asyncHook
|
|
140
|
-
], context);
|
|
141
|
-
expect(result.total).toBe(1200);
|
|
142
|
-
});
|
|
143
|
-
it('should throw when a hook throws, aborting the pipeline', async ()=>{
|
|
144
|
-
const failingHook = ()=>{
|
|
145
|
-
throw new Error('Tax service unavailable');
|
|
146
|
-
};
|
|
147
|
-
const neverReachedHook = vi.fn(({ summary })=>summary);
|
|
148
|
-
const context = createMockInitiateContext();
|
|
149
|
-
await expect(runBeforeInitiatePaymentHooks([
|
|
150
|
-
failingHook,
|
|
151
|
-
neverReachedHook
|
|
152
|
-
], context)).rejects.toThrow('Tax service unavailable');
|
|
153
|
-
expect(neverReachedHook).not.toHaveBeenCalled();
|
|
154
|
-
});
|
|
155
|
-
it('should throw when a hook removes the subtotal line', async ()=>{
|
|
156
|
-
const badHook = ({ summary })=>({
|
|
157
|
-
...summary,
|
|
158
|
-
lines: summary.lines.filter((l)=>l.type !== 'subtotal')
|
|
159
|
-
});
|
|
160
|
-
const context = createMockInitiateContext();
|
|
161
|
-
await expect(runBeforeInitiatePaymentHooks([
|
|
162
|
-
badHook
|
|
163
|
-
], context)).rejects.toThrow(/subtotal line/);
|
|
164
|
-
});
|
|
165
|
-
it('should throw when a hook modifies the subtotal amount', async ()=>{
|
|
166
|
-
const badHook = ({ summary })=>({
|
|
167
|
-
...summary,
|
|
168
|
-
lines: [
|
|
169
|
-
{
|
|
170
|
-
...summary.lines[0],
|
|
171
|
-
amount: 1
|
|
172
|
-
},
|
|
173
|
-
...summary.lines.slice(1)
|
|
174
|
-
]
|
|
175
|
-
});
|
|
176
|
-
const context = createMockInitiateContext();
|
|
177
|
-
await expect(runBeforeInitiatePaymentHooks([
|
|
178
|
-
badHook
|
|
179
|
-
], context)).rejects.toThrow(/subtotal amount/i);
|
|
180
|
-
});
|
|
181
|
-
it('should throw when a hook changes currency', async ()=>{
|
|
182
|
-
const badHook = ({ summary })=>({
|
|
183
|
-
...summary,
|
|
184
|
-
currency: 'EUR'
|
|
185
|
-
});
|
|
186
|
-
const context = createMockInitiateContext();
|
|
187
|
-
await expect(runBeforeInitiatePaymentHooks([
|
|
188
|
-
badHook
|
|
189
|
-
], context)).rejects.toThrow(/currency/i);
|
|
190
|
-
});
|
|
191
|
-
it('should allow negative line amounts (discounts) and reflect them in total', async ()=>{
|
|
192
|
-
const discountHook = ({ summary })=>({
|
|
193
|
-
...summary,
|
|
194
|
-
lines: [
|
|
195
|
-
...summary.lines,
|
|
196
|
-
{
|
|
197
|
-
amount: -200,
|
|
198
|
-
label: 'Discount: SAVE20',
|
|
199
|
-
type: 'discount'
|
|
200
|
-
}
|
|
201
|
-
]
|
|
202
|
-
});
|
|
203
|
-
const context = createMockInitiateContext();
|
|
204
|
-
const result = await runBeforeInitiatePaymentHooks([
|
|
205
|
-
discountHook
|
|
206
|
-
], context);
|
|
207
|
-
expect(result.total).toBe(800);
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
describe('runBeforeConfirmOrderHooks', ()=>{
|
|
211
|
-
const createMockConfirmContext = ()=>({
|
|
212
|
-
customerEmail: 'test@example.com',
|
|
213
|
-
data: {
|
|
214
|
-
paymentIntentID: 'pi_123'
|
|
215
|
-
},
|
|
216
|
-
req: {}
|
|
217
|
-
});
|
|
218
|
-
it('should execute hooks sequentially', async ()=>{
|
|
219
|
-
const executionOrder = [];
|
|
220
|
-
const hookOne = async ()=>{
|
|
221
|
-
executionOrder.push(1);
|
|
222
|
-
};
|
|
223
|
-
const hookTwo = async ()=>{
|
|
224
|
-
executionOrder.push(2);
|
|
225
|
-
};
|
|
226
|
-
const context = createMockConfirmContext();
|
|
227
|
-
await runBeforeConfirmOrderHooks([
|
|
228
|
-
hookOne,
|
|
229
|
-
hookTwo
|
|
230
|
-
], context);
|
|
231
|
-
expect(executionOrder).toEqual([
|
|
232
|
-
1,
|
|
233
|
-
2
|
|
234
|
-
]);
|
|
235
|
-
});
|
|
236
|
-
it('should throw when a hook throws', async ()=>{
|
|
237
|
-
const failingHook = ()=>{
|
|
238
|
-
throw new Error('Confirmation check failed');
|
|
239
|
-
};
|
|
240
|
-
const context = createMockConfirmContext();
|
|
241
|
-
await expect(runBeforeConfirmOrderHooks([
|
|
242
|
-
failingHook
|
|
243
|
-
], context)).rejects.toThrow('Confirmation check failed');
|
|
244
|
-
});
|
|
245
|
-
it('should not execute subsequent hooks after a failure', async ()=>{
|
|
246
|
-
const failingHook = ()=>{
|
|
247
|
-
throw new Error('Failed');
|
|
248
|
-
};
|
|
249
|
-
const neverReachedHook = vi.fn();
|
|
250
|
-
const context = createMockConfirmContext();
|
|
251
|
-
await expect(runBeforeConfirmOrderHooks([
|
|
252
|
-
failingHook,
|
|
253
|
-
neverReachedHook
|
|
254
|
-
], context)).rejects.toThrow('Failed');
|
|
255
|
-
expect(neverReachedHook).not.toHaveBeenCalled();
|
|
256
|
-
});
|
|
257
|
-
it('should handle empty hooks array', async ()=>{
|
|
258
|
-
const context = createMockConfirmContext();
|
|
259
|
-
await expect(runBeforeConfirmOrderHooks([], context)).resolves.toBeUndefined();
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
describe('runAfterConfirmOrderHooks', ()=>{
|
|
263
|
-
const createMockAfterContext = ()=>({
|
|
264
|
-
orderID: 'order-1',
|
|
265
|
-
req: {},
|
|
266
|
-
transactionID: 'txn-1'
|
|
267
|
-
});
|
|
268
|
-
const mockLogger = {
|
|
269
|
-
error: vi.fn()
|
|
270
|
-
};
|
|
271
|
-
it('should not throw when a hook throws', async ()=>{
|
|
272
|
-
const failingHook = ()=>{
|
|
273
|
-
throw new Error('Email service down');
|
|
274
|
-
};
|
|
275
|
-
const context = createMockAfterContext();
|
|
276
|
-
mockLogger.error.mockClear();
|
|
277
|
-
await expect(runAfterConfirmOrderHooks([
|
|
278
|
-
failingHook
|
|
279
|
-
], context, mockLogger)).resolves.toBeUndefined();
|
|
280
|
-
expect(mockLogger.error).toHaveBeenCalled();
|
|
281
|
-
});
|
|
282
|
-
it('should execute all hooks even if one fails', async ()=>{
|
|
283
|
-
const executionOrder = [];
|
|
284
|
-
const failingHook = ()=>{
|
|
285
|
-
executionOrder.push(1);
|
|
286
|
-
throw new Error('Hook 1 failed');
|
|
287
|
-
};
|
|
288
|
-
const successHook = async ()=>{
|
|
289
|
-
executionOrder.push(2);
|
|
290
|
-
};
|
|
291
|
-
const context = createMockAfterContext();
|
|
292
|
-
mockLogger.error.mockClear();
|
|
293
|
-
await runAfterConfirmOrderHooks([
|
|
294
|
-
failingHook,
|
|
295
|
-
successHook
|
|
296
|
-
], context, mockLogger);
|
|
297
|
-
expect(executionOrder).toEqual([
|
|
298
|
-
1,
|
|
299
|
-
2
|
|
300
|
-
]);
|
|
301
|
-
expect(mockLogger.error).toHaveBeenCalledTimes(1);
|
|
302
|
-
});
|
|
303
|
-
it('should handle empty hooks array', async ()=>{
|
|
304
|
-
const context = createMockAfterContext();
|
|
305
|
-
await expect(runAfterConfirmOrderHooks([], context, mockLogger)).resolves.toBeUndefined();
|
|
306
|
-
});
|
|
307
|
-
it('should pass correct context to hooks', async ()=>{
|
|
308
|
-
const receivedArgs = [];
|
|
309
|
-
const captureHook = (args)=>{
|
|
310
|
-
receivedArgs.push(args);
|
|
311
|
-
};
|
|
312
|
-
const context = createMockAfterContext();
|
|
313
|
-
await runAfterConfirmOrderHooks([
|
|
314
|
-
captureHook
|
|
315
|
-
], context, mockLogger);
|
|
316
|
-
expect(receivedArgs[0]).toEqual({
|
|
317
|
-
orderID: 'order-1',
|
|
318
|
-
req: {},
|
|
319
|
-
transactionID: 'txn-1'
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
//# sourceMappingURL=runPaymentHooks.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/runPaymentHooks.spec.ts"],"sourcesContent":["import { describe, expect, it, vi } from 'vitest'\n\nimport type {\n AfterConfirmOrderHook,\n BeforeConfirmOrderHook,\n BeforeInitiatePaymentHook,\n Summary,\n} from '../types/index.js'\n\nimport {\n runAfterConfirmOrderHooks,\n runBeforeConfirmOrderHooks,\n runBeforeInitiatePaymentHooks,\n} from './runPaymentHooks.js'\n\nconst createSummary = (subtotal = 1000): Summary => ({\n currency: 'USD',\n lines: [{ amount: subtotal, label: 'Subtotal', type: 'subtotal' }],\n total: subtotal,\n})\n\nconst createMockInitiateContext = (overrides: Record<string, unknown> = {}) => ({\n billingAddress: undefined as any,\n cart: {\n id: 'cart-1',\n items: [{ id: 'item-1', product: 'prod-1', quantity: 1 }],\n subtotal: 1000,\n },\n currenciesConfig: {\n defaultCurrency: 'USD',\n supportedCurrencies: [{ code: 'USD', decimals: 2, label: 'US Dollar', symbol: '$' }],\n },\n currency: 'USD',\n customerEmail: 'test@example.com',\n req: {} as any,\n shippingAddress: undefined as any,\n summary: createSummary(),\n ...overrides,\n})\n\ndescribe('runBeforeInitiatePaymentHooks', () => {\n it('should return the incoming summary unchanged when no hooks are provided', async () => {\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([], context)\n\n expect(result.total).toBe(1000)\n expect(result.lines).toHaveLength(1)\n expect(result.lines[0]?.type).toBe('subtotal')\n })\n\n it('should append a single line and recompute total', async () => {\n const taxHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: [...summary.lines, { amount: 100, label: 'Sales Tax', type: 'tax' }],\n })\n\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([taxHook], context)\n\n expect(result.lines).toHaveLength(2)\n expect(result.total).toBe(1100)\n })\n\n it('should pipe summary through multiple hooks and recompute total after each', async () => {\n const shippingHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: [...summary.lines, { amount: 500, label: 'Standard Shipping', type: 'shipping' }],\n })\n\n const taxOnAllHook: BeforeInitiatePaymentHook = ({ summary }) => {\n const taxable = summary.lines.reduce((sum, l) => sum + l.amount, 0)\n return {\n ...summary,\n lines: [\n ...summary.lines,\n { amount: Math.round(taxable * 0.1), label: 'Tax (10%)', type: 'tax' },\n ],\n }\n }\n\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([shippingHook, taxOnAllHook], context)\n\n expect(result.lines).toHaveLength(3)\n expect(result.total).toBe(1000 + 500 + Math.round(1500 * 0.1))\n })\n\n it('should ignore any total a hook tries to set and recompute from lines', async () => {\n const badHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: [...summary.lines, { amount: 200, label: 'Tax', type: 'tax' }],\n total: 999999,\n })\n\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([badHook], context)\n\n expect(result.total).toBe(1200)\n })\n\n it('should support async hooks', async () => {\n const asyncHook: BeforeInitiatePaymentHook = async ({ summary }) => ({\n ...summary,\n lines: [...summary.lines, { amount: 200, label: 'Async Tax', type: 'tax' }],\n })\n\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([asyncHook], context)\n\n expect(result.total).toBe(1200)\n })\n\n it('should throw when a hook throws, aborting the pipeline', async () => {\n const failingHook: BeforeInitiatePaymentHook = () => {\n throw new Error('Tax service unavailable')\n }\n\n const neverReachedHook: BeforeInitiatePaymentHook = vi.fn(({ summary }) => summary)\n\n const context = createMockInitiateContext()\n\n await expect(\n runBeforeInitiatePaymentHooks([failingHook, neverReachedHook], context),\n ).rejects.toThrow('Tax service unavailable')\n\n expect(neverReachedHook).not.toHaveBeenCalled()\n })\n\n it('should throw when a hook removes the subtotal line', async () => {\n const badHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: summary.lines.filter((l) => l.type !== 'subtotal'),\n })\n\n const context = createMockInitiateContext()\n\n await expect(runBeforeInitiatePaymentHooks([badHook], context)).rejects.toThrow(/subtotal line/)\n })\n\n it('should throw when a hook modifies the subtotal amount', async () => {\n const badHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: [{ ...summary.lines[0]!, amount: 1 }, ...summary.lines.slice(1)],\n })\n\n const context = createMockInitiateContext()\n\n await expect(runBeforeInitiatePaymentHooks([badHook], context)).rejects.toThrow(\n /subtotal amount/i,\n )\n })\n\n it('should throw when a hook changes currency', async () => {\n const badHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n currency: 'EUR',\n })\n\n const context = createMockInitiateContext()\n\n await expect(runBeforeInitiatePaymentHooks([badHook], context)).rejects.toThrow(/currency/i)\n })\n\n it('should allow negative line amounts (discounts) and reflect them in total', async () => {\n const discountHook: BeforeInitiatePaymentHook = ({ summary }) => ({\n ...summary,\n lines: [...summary.lines, { amount: -200, label: 'Discount: SAVE20', type: 'discount' }],\n })\n\n const context = createMockInitiateContext()\n const result = await runBeforeInitiatePaymentHooks([discountHook], context)\n\n expect(result.total).toBe(800)\n })\n})\n\ndescribe('runBeforeConfirmOrderHooks', () => {\n const createMockConfirmContext = () => ({\n customerEmail: 'test@example.com',\n data: { paymentIntentID: 'pi_123' } as Record<string, unknown>,\n req: {} as any,\n })\n\n it('should execute hooks sequentially', async () => {\n const executionOrder: number[] = []\n\n const hookOne: BeforeConfirmOrderHook = async () => {\n executionOrder.push(1)\n }\n\n const hookTwo: BeforeConfirmOrderHook = async () => {\n executionOrder.push(2)\n }\n\n const context = createMockConfirmContext()\n await runBeforeConfirmOrderHooks([hookOne, hookTwo], context)\n\n expect(executionOrder).toEqual([1, 2])\n })\n\n it('should throw when a hook throws', async () => {\n const failingHook: BeforeConfirmOrderHook = () => {\n throw new Error('Confirmation check failed')\n }\n\n const context = createMockConfirmContext()\n\n await expect(runBeforeConfirmOrderHooks([failingHook], context)).rejects.toThrow(\n 'Confirmation check failed',\n )\n })\n\n it('should not execute subsequent hooks after a failure', async () => {\n const failingHook: BeforeConfirmOrderHook = () => {\n throw new Error('Failed')\n }\n\n const neverReachedHook: BeforeConfirmOrderHook = vi.fn()\n\n const context = createMockConfirmContext()\n\n await expect(\n runBeforeConfirmOrderHooks([failingHook, neverReachedHook], context),\n ).rejects.toThrow('Failed')\n\n expect(neverReachedHook).not.toHaveBeenCalled()\n })\n\n it('should handle empty hooks array', async () => {\n const context = createMockConfirmContext()\n await expect(runBeforeConfirmOrderHooks([], context)).resolves.toBeUndefined()\n })\n})\n\ndescribe('runAfterConfirmOrderHooks', () => {\n const createMockAfterContext = () => ({\n orderID: 'order-1' as any,\n req: {} as any,\n transactionID: 'txn-1' as any,\n })\n\n const mockLogger = {\n error: vi.fn(),\n }\n\n it('should not throw when a hook throws', async () => {\n const failingHook: AfterConfirmOrderHook = () => {\n throw new Error('Email service down')\n }\n\n const context = createMockAfterContext()\n mockLogger.error.mockClear()\n\n await expect(\n runAfterConfirmOrderHooks([failingHook], context, mockLogger),\n ).resolves.toBeUndefined()\n\n expect(mockLogger.error).toHaveBeenCalled()\n })\n\n it('should execute all hooks even if one fails', async () => {\n const executionOrder: number[] = []\n\n const failingHook: AfterConfirmOrderHook = () => {\n executionOrder.push(1)\n throw new Error('Hook 1 failed')\n }\n\n const successHook: AfterConfirmOrderHook = async () => {\n executionOrder.push(2)\n }\n\n const context = createMockAfterContext()\n mockLogger.error.mockClear()\n\n await runAfterConfirmOrderHooks([failingHook, successHook], context, mockLogger)\n\n expect(executionOrder).toEqual([1, 2])\n expect(mockLogger.error).toHaveBeenCalledTimes(1)\n })\n\n it('should handle empty hooks array', async () => {\n const context = createMockAfterContext()\n await expect(runAfterConfirmOrderHooks([], context, mockLogger)).resolves.toBeUndefined()\n })\n\n it('should pass correct context to hooks', async () => {\n const receivedArgs: any[] = []\n\n const captureHook: AfterConfirmOrderHook = (args) => {\n receivedArgs.push(args)\n }\n\n const context = createMockAfterContext()\n await runAfterConfirmOrderHooks([captureHook], context, mockLogger)\n\n expect(receivedArgs[0]).toEqual({\n orderID: 'order-1',\n req: {},\n transactionID: 'txn-1',\n })\n })\n})\n"],"names":["describe","expect","it","vi","runAfterConfirmOrderHooks","runBeforeConfirmOrderHooks","runBeforeInitiatePaymentHooks","createSummary","subtotal","currency","lines","amount","label","type","total","createMockInitiateContext","overrides","billingAddress","undefined","cart","id","items","product","quantity","currenciesConfig","defaultCurrency","supportedCurrencies","code","decimals","symbol","customerEmail","req","shippingAddress","summary","context","result","toBe","toHaveLength","taxHook","shippingHook","taxOnAllHook","taxable","reduce","sum","l","Math","round","badHook","asyncHook","failingHook","Error","neverReachedHook","fn","rejects","toThrow","not","toHaveBeenCalled","filter","slice","discountHook","createMockConfirmContext","data","paymentIntentID","executionOrder","hookOne","push","hookTwo","toEqual","resolves","toBeUndefined","createMockAfterContext","orderID","transactionID","mockLogger","error","mockClear","successHook","toHaveBeenCalledTimes","receivedArgs","captureHook","args"],"mappings":"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"}
|