@payment-kit-js/vanilla 0.3.0 → 0.4.1
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/airwallex-google-pay-adapter-BCmTZip5.mjs +167 -0
- package/dist/airwallex-google-pay-adapter-BCmTZip5.mjs.map +1 -0
- package/dist/airwallex-google-pay-adapter-Be2Af4N9.d.mts +140 -0
- package/dist/airwallex-google-pay-adapter-Be2Af4N9.d.mts.map +1 -0
- package/dist/cdn/paymentkit.js +5768 -83
- package/dist/cdn/paymentkit.js.map +4 -4
- package/dist/cdn/paymentkit.min.js +58 -3
- package/dist/cdn/paymentkit.min.js.map +4 -4
- package/dist/{connect-card-DO2EJxu6.mjs → connect-card-BrtCmsjz.mjs} +1 -1
- package/dist/{connect-card-DO2EJxu6.mjs.map → connect-card-BrtCmsjz.mjs.map} +1 -1
- package/dist/{connect-card-C582hcWw.d.mts → connect-card-DTfXuTsW.d.mts} +1 -1
- package/dist/{connect-card-C582hcWw.d.mts.map → connect-card-DTfXuTsW.d.mts.map} +1 -1
- package/dist/connect-tunnel-x-BhVAej5Q.mjs.map +1 -1
- package/dist/{connect-tunnel-x-B7iMQ7DX.d.mts → connect-tunnel-x-Dxcg5Y7Y.d.mts} +6 -5
- package/dist/connect-tunnel-x-Dxcg5Y7Y.d.mts.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +337 -5
- package/dist/index.mjs.map +1 -1
- package/dist/next-action-handlers-BZs04hYb.mjs +271 -0
- package/dist/next-action-handlers-BZs04hYb.mjs.map +1 -0
- package/dist/payment-methods/airwallex-google-pay-adapter.d.mts +2 -0
- package/dist/payment-methods/airwallex-google-pay-adapter.mjs +3 -0
- package/dist/payment-methods/apple-pay.d.mts +78 -0
- package/dist/payment-methods/apple-pay.d.mts.map +1 -0
- package/dist/payment-methods/apple-pay.mjs +188 -0
- package/dist/payment-methods/apple-pay.mjs.map +1 -0
- package/dist/payment-methods/card.d.mts +3 -3
- package/dist/payment-methods/card.d.mts.map +1 -1
- package/dist/payment-methods/card.mjs +40 -12
- package/dist/payment-methods/card.mjs.map +1 -1
- package/dist/payment-methods/google-pay.d.mts +25 -7
- package/dist/payment-methods/google-pay.d.mts.map +1 -1
- package/dist/payment-methods/google-pay.mjs +165 -30
- package/dist/payment-methods/google-pay.mjs.map +1 -1
- package/dist/payment-methods/next-action-handlers.d.mts.map +1 -1
- package/dist/payment-methods/next-action-handlers.mjs +1 -1
- package/dist/payment-methods/paypal.d.mts +3 -3
- package/dist/payment-methods/paypal.d.mts.map +1 -1
- package/dist/payment-methods/paypal.mjs +8 -3
- package/dist/payment-methods/paypal.mjs.map +1 -1
- package/dist/payment-methods/stripe-apple-pay-adapter.d.mts +2 -0
- package/dist/payment-methods/stripe-apple-pay-adapter.mjs +3 -0
- package/dist/payment-methods/stripe-google-pay-adapter.d.mts +1 -1
- package/dist/payment-methods/stripe-google-pay-adapter.mjs +1 -1
- package/dist/penpal/connect-card.d.mts +1 -1
- package/dist/penpal/connect-card.mjs +1 -1
- package/dist/penpal/connect-tunnel-x.d.mts +1 -1
- package/dist/stripe-apple-pay-adapter-Bg7nCy3P.mjs +313 -0
- package/dist/stripe-apple-pay-adapter-Bg7nCy3P.mjs.map +1 -0
- package/dist/stripe-apple-pay-adapter-Bq3f1mqv.d.mts +141 -0
- package/dist/stripe-apple-pay-adapter-Bq3f1mqv.d.mts.map +1 -0
- package/dist/{stripe-google-pay-adapter-DMDArVp2.mjs → stripe-google-pay-adapter-DjrgDYWe.mjs} +1 -1
- package/dist/{stripe-google-pay-adapter-DMDArVp2.mjs.map → stripe-google-pay-adapter-DjrgDYWe.mjs.map} +1 -1
- package/dist/{stripe-google-pay-adapter-DUUB46SG.d.mts → stripe-google-pay-adapter-xktEycOD.d.mts} +1 -1
- package/dist/{stripe-google-pay-adapter-DUUB46SG.d.mts.map → stripe-google-pay-adapter-xktEycOD.d.mts.map} +1 -1
- package/dist/types-CPuloCtF.d.mts +129 -0
- package/dist/types-CPuloCtF.d.mts.map +1 -0
- package/dist/{utils-h0dxplHy.mjs → utils-Dgyk7RkM.mjs} +40 -2
- package/dist/utils-Dgyk7RkM.mjs.map +1 -0
- package/package.json +9 -3
- package/dist/connect-tunnel-x-B7iMQ7DX.d.mts.map +0 -1
- package/dist/next-action-handlers-DTsWjUIA.mjs +0 -53
- package/dist/next-action-handlers-DTsWjUIA.mjs.map +0 -1
- package/dist/types-DsVMq4jZ.d.mts +0 -64
- package/dist/types-DsVMq4jZ.d.mts.map +0 -1
- package/dist/utils-h0dxplHy.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stripe-google-pay-adapter-
|
|
1
|
+
{"version":3,"file":"stripe-google-pay-adapter-DjrgDYWe.mjs","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":["import type { PaymentRequest, PaymentRequestPaymentMethodEvent, Stripe, StripeConstructor } from \"@stripe/stripe-js\";\n\n// Stripe.js must be loaded via script tag for PCI compliance\ndeclare global {\n interface Window {\n Stripe?: StripeConstructor;\n }\n}\n\nexport interface PaymentRequestConfig {\n country: string;\n currency: string;\n total: { label: string; amount: number };\n requestPayerName: boolean;\n requestPayerEmail: boolean;\n}\n\nexport type ShowPaymentSheetResult =\n | { success: true; paymentMethodId: string; complete: (status: \"success\" | \"fail\") => void }\n | { success: false; cancelled: true }\n | { success: false; error: string };\n\nexport type ConfirmResult = { success: true } | { success: false; error: string };\n\nexport enum GooglePayMockScenario {\n None = \"none\",\n Success = \"success\",\n Cancelled = \"cancelled\",\n}\n\nexport class StripeGooglePayAdapter {\n private stripe: Stripe | null = null;\n private paymentRequest: PaymentRequest | null = null;\n private mockScenario: GooglePayMockScenario;\n\n constructor(mockScenario?: GooglePayMockScenario) {\n this.mockScenario = mockScenario ?? GooglePayMockScenario.None;\n }\n\n initialize(publishableKey: string): boolean {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] initialize called\");\n if (!window.Stripe) {\n console.log(\"[GooglePay] Stripe.js not loaded\");\n return false;\n }\n this.stripe = window.Stripe(publishableKey);\n const success = this.stripe !== null;\n console.log(\"[GooglePay] initialize result:\", success);\n return success;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] initialize called\");\n console.log(\"[MockGooglePay] initialize result:\", true);\n return true;\n }\n }\n }\n\n createPaymentRequest(config: PaymentRequestConfig): void {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] createPaymentRequest called\", config);\n if (!this.stripe) {\n throw new Error(\"Stripe not initialized\");\n }\n this.paymentRequest = this.stripe.paymentRequest(config);\n console.log(\"[GooglePay] paymentRequest created\");\n return;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] createPaymentRequest called\", config);\n return;\n }\n }\n }\n\n async canMakePayment(): Promise<boolean> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] canMakePayment called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] canMakePayment: no paymentRequest\");\n return false;\n }\n const result = await this.paymentRequest.canMakePayment();\n const isAvailable = result?.googlePay ?? false;\n console.log(\"[GooglePay] canMakePayment result:\", { result, isAvailable });\n return isAvailable;\n }\n case GooglePayMockScenario.Success:\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] canMakePayment called\");\n console.log(\"[MockGooglePay] canMakePayment result:\", { result: { googlePay: true }, isAvailable: true });\n return true;\n }\n }\n }\n\n async showPaymentSheet(): Promise<ShowPaymentSheetResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] showPaymentSheet called\");\n if (!this.paymentRequest) {\n console.log(\"[GooglePay] showPaymentSheet: no paymentRequest\");\n return { success: false, error: \"Payment request not created\" };\n }\n\n return new Promise((resolve) => {\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"paymentmethod\", (event: PaymentRequestPaymentMethodEvent) => {\n console.log(\"[GooglePay] showPaymentSheet: paymentmethod event\", {\n paymentMethodId: event.paymentMethod.id,\n });\n resolve({\n success: true,\n paymentMethodId: event.paymentMethod.id,\n complete: (status) => {\n console.log(\"[GooglePay] complete called:\", status);\n event.complete(status);\n },\n });\n });\n\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.on(\"cancel\", () => {\n console.log(\"[GooglePay] showPaymentSheet: cancelled by user\");\n resolve({ success: false, cancelled: true });\n });\n\n console.log(\"[GooglePay] showing payment sheet...\");\n // biome-ignore lint/style/noNonNullAssertion: checked above\n this.paymentRequest!.show();\n });\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] showPaymentSheet: success\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return {\n success: true,\n paymentMethodId: \"pm_mock_123456789\",\n complete: (status) => console.log(`[MockGooglePay] complete: ${status}`),\n };\n }\n case GooglePayMockScenario.Cancelled: {\n console.log(\"[MockGooglePay] showPaymentSheet: cancelled\");\n await new Promise((resolve) => setTimeout(resolve, 500));\n return { success: false, cancelled: true };\n }\n }\n }\n\n async confirmCardSetup(clientSecret: string, paymentMethodId: string): Promise<ConfirmResult> {\n switch (this.mockScenario) {\n case GooglePayMockScenario.None: {\n console.log(\"[GooglePay] confirmCardSetup called\", {\n clientSecret: `${clientSecret.slice(0, 20)}...`,\n paymentMethodId,\n });\n if (!this.stripe) {\n console.log(\"[GooglePay] confirmCardSetup: Stripe not initialized\");\n return { success: false, error: \"Stripe not initialized\" };\n }\n\n const { error } = await this.stripe.confirmCardSetup(clientSecret, {\n payment_method: paymentMethodId,\n });\n\n if (error) {\n console.log(\"[GooglePay] confirmCardSetup error:\", error);\n return { success: false, error: error.message ?? \"Card setup failed\" };\n }\n\n console.log(\"[GooglePay] confirmCardSetup success\");\n return { success: true };\n }\n case GooglePayMockScenario.Success: {\n console.log(\"[MockGooglePay] confirmCardSetup called\", { clientSecret, paymentMethodId });\n return { success: true };\n }\n case GooglePayMockScenario.Cancelled: {\n throw new Error(\"confirmCardSetup should not be called when scenario is Cancelled\");\n }\n }\n }\n}\n"],"mappings":";AAwBA,IAAY,0EAAL;AACL;AACA;AACA;;;AAGF,IAAa,yBAAb,MAAoC;CAClC,AAAQ,SAAwB;CAChC,AAAQ,iBAAwC;CAChD,AAAQ;CAER,YAAY,cAAsC;AAChD,OAAK,eAAe,gBAAgB,sBAAsB;;CAG5D,WAAW,gBAAiC;AAC1C,UAAQ,KAAK,cAAb;GACE,KAAK,sBAAsB,MAAM;AAC/B,YAAQ,IAAI,gCAAgC;AAC5C,QAAI,CAAC,OAAO,QAAQ;AAClB,aAAQ,IAAI,mCAAmC;AAC/C,YAAO;;AAET,SAAK,SAAS,OAAO,OAAO,eAAe;IAC3C,MAAM,UAAU,KAAK,WAAW;AAChC,YAAQ,IAAI,kCAAkC,QAAQ;AACtD,WAAO;;GAET,KAAK,sBAAsB;GAC3B,KAAK,sBAAsB;AACzB,YAAQ,IAAI,oCAAoC;AAChD,YAAQ,IAAI,sCAAsC,KAAK;AACvD,WAAO;;;CAKb,qBAAqB,QAAoC;AACvD,UAAQ,KAAK,cAAb;GACE,KAAK,sBAAsB;AACzB,YAAQ,IAAI,2CAA2C,OAAO;AAC9D,QAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,yBAAyB;AAE3C,SAAK,iBAAiB,KAAK,OAAO,eAAe,OAAO;AACxD,YAAQ,IAAI,qCAAqC;AACjD;GAEF,KAAK,sBAAsB;GAC3B,KAAK,sBAAsB;AACzB,YAAQ,IAAI,+CAA+C,OAAO;AAClE;;;CAKN,MAAM,iBAAmC;AACvC,UAAQ,KAAK,cAAb;GACE,KAAK,sBAAsB,MAAM;AAC/B,YAAQ,IAAI,oCAAoC;AAChD,QAAI,CAAC,KAAK,gBAAgB;AACxB,aAAQ,IAAI,gDAAgD;AAC5D,YAAO;;IAET,MAAM,SAAS,MAAM,KAAK,eAAe,gBAAgB;IACzD,MAAM,cAAc,QAAQ,aAAa;AACzC,YAAQ,IAAI,sCAAsC;KAAE;KAAQ;KAAa,CAAC;AAC1E,WAAO;;GAET,KAAK,sBAAsB;GAC3B,KAAK,sBAAsB;AACzB,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,IAAI,0CAA0C;KAAE,QAAQ,EAAE,WAAW,MAAM;KAAE,aAAa;KAAM,CAAC;AACzG,WAAO;;;CAKb,MAAM,mBAAoD;AACxD,UAAQ,KAAK,cAAb;GACE,KAAK,sBAAsB;AACzB,YAAQ,IAAI,sCAAsC;AAClD,QAAI,CAAC,KAAK,gBAAgB;AACxB,aAAQ,IAAI,kDAAkD;AAC9D,YAAO;MAAE,SAAS;MAAO,OAAO;MAA+B;;AAGjE,WAAO,IAAI,SAAS,YAAY;AAE9B,UAAK,eAAgB,GAAG,kBAAkB,UAA4C;AACpF,cAAQ,IAAI,qDAAqD,EAC/D,iBAAiB,MAAM,cAAc,IACtC,CAAC;AACF,cAAQ;OACN,SAAS;OACT,iBAAiB,MAAM,cAAc;OACrC,WAAW,WAAW;AACpB,gBAAQ,IAAI,gCAAgC,OAAO;AACnD,cAAM,SAAS,OAAO;;OAEzB,CAAC;OACF;AAGF,UAAK,eAAgB,GAAG,gBAAgB;AACtC,cAAQ,IAAI,kDAAkD;AAC9D,cAAQ;OAAE,SAAS;OAAO,WAAW;OAAM,CAAC;OAC5C;AAEF,aAAQ,IAAI,uCAAuC;AAEnD,UAAK,eAAgB,MAAM;MAC3B;GAEJ,KAAK,sBAAsB;AACzB,YAAQ,IAAI,4CAA4C;AACxD,UAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;AACxD,WAAO;KACL,SAAS;KACT,iBAAiB;KACjB,WAAW,WAAW,QAAQ,IAAI,6BAA6B,SAAS;KACzE;GAEH,KAAK,sBAAsB;AACzB,YAAQ,IAAI,8CAA8C;AAC1D,UAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;AACxD,WAAO;KAAE,SAAS;KAAO,WAAW;KAAM;;;CAKhD,MAAM,iBAAiB,cAAsB,iBAAiD;AAC5F,UAAQ,KAAK,cAAb;GACE,KAAK,sBAAsB,MAAM;AAC/B,YAAQ,IAAI,uCAAuC;KACjD,cAAc,GAAG,aAAa,MAAM,GAAG,GAAG,CAAC;KAC3C;KACD,CAAC;AACF,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAQ,IAAI,uDAAuD;AACnE,YAAO;MAAE,SAAS;MAAO,OAAO;MAA0B;;IAG5D,MAAM,EAAE,UAAU,MAAM,KAAK,OAAO,iBAAiB,cAAc,EACjE,gBAAgB,iBACjB,CAAC;AAEF,QAAI,OAAO;AACT,aAAQ,IAAI,uCAAuC,MAAM;AACzD,YAAO;MAAE,SAAS;MAAO,OAAO,MAAM,WAAW;MAAqB;;AAGxE,YAAQ,IAAI,uCAAuC;AACnD,WAAO,EAAE,SAAS,MAAM;;GAE1B,KAAK,sBAAsB;AACzB,YAAQ,IAAI,2CAA2C;KAAE;KAAc;KAAiB,CAAC;AACzF,WAAO,EAAE,SAAS,MAAM;GAE1B,KAAK,sBAAsB,UACzB,OAAM,IAAI,MAAM,mEAAmE"}
|
package/dist/{stripe-google-pay-adapter-DUUB46SG.d.mts → stripe-google-pay-adapter-xktEycOD.d.mts}
RENAMED
|
@@ -51,4 +51,4 @@ declare class StripeGooglePayAdapter {
|
|
|
51
51
|
}
|
|
52
52
|
//#endregion
|
|
53
53
|
export { StripeGooglePayAdapter as a, ShowPaymentSheetResult as i, GooglePayMockScenario as n, PaymentRequestConfig as r, ConfirmResult as t };
|
|
54
|
-
//# sourceMappingURL=stripe-google-pay-adapter-
|
|
54
|
+
//# sourceMappingURL=stripe-google-pay-adapter-xktEycOD.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stripe-google-pay-adapter-
|
|
1
|
+
{"version":3,"file":"stripe-google-pay-adapter-xktEycOD.d.mts","names":[],"sources":["../src/payment-methods/stripe-google-pay-adapter.ts"],"sourcesContent":[],"mappings":";;;;;IAAqH,MAAA,CAAA,EAKxG,iBALwG;EAAA;;AAKvF,UAIb,oBAAA,CAJa;EAAA,OAAA,EAAA,MAAA;EAIb,QAAA,EAAA,MAAA;EAQL,KAAA,EAAA;IAKA,KAAA,EAAA,MAAa;IAEb,MAAA,EAAA,MAAA;EAMC,CAAA;EAKgB,gBAAA,EAAA,OAAA;EA0BE,iBAAA,EAAA,OAAA;;AAyCK,KArFxB,sBAAA,GAqFwB;EAAR,OAAA,EAAA,IAAA;EAqDqD,eAAA,EAAA,MAAA;EAAR,QAAA,EAAA,CAAA,MAAA,EAAA,SAAA,GAAA,MAAA,EAAA,GAAA,IAAA;CAAO,GAAA;;;;;;;KArIpE,aAAA;;;;;;aAEA,qBAAA;;;;;cAMC,sBAAA;;;;6BAKgB;;+BA0BE;oBAmBL;sBAsBE,QAAQ;mEAqDqC,QAAQ"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { t as CardErrorCode } from "./connect-card-DTfXuTsW.mjs";
|
|
2
|
+
import { t as TunnelXIFrameConnection } from "./connect-tunnel-x-Dxcg5Y7Y.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/analytics/checkout-timing.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tracks timing metrics throughout the checkout flow.
|
|
8
|
+
*
|
|
9
|
+
* Create one instance per checkout session and call the track methods
|
|
10
|
+
* at appropriate points in the checkout flow.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* const tracker = new CheckoutTimingTracker(secureToken);
|
|
14
|
+
* tracker.trackPageReady();
|
|
15
|
+
* // ... iframe loads ...
|
|
16
|
+
* tracker.trackInputReady();
|
|
17
|
+
* // ... user submits ...
|
|
18
|
+
* tracker.trackSubmit();
|
|
19
|
+
* // ... API response ...
|
|
20
|
+
* tracker.trackSuccess(attemptId);
|
|
21
|
+
*/
|
|
22
|
+
declare class CheckoutTimingTracker {
|
|
23
|
+
private static pageReadyTracked;
|
|
24
|
+
private startTime;
|
|
25
|
+
private checkoutSessionId;
|
|
26
|
+
private inputReadyTracked;
|
|
27
|
+
constructor(checkoutSessionId: string);
|
|
28
|
+
/**
|
|
29
|
+
* Track when SDK is initialized and ready.
|
|
30
|
+
* Call immediately after PaymentKit() initialization.
|
|
31
|
+
* Only tracks once per page load (subsequent calls are no-ops).
|
|
32
|
+
*/
|
|
33
|
+
trackPageReady(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Track when card input iframe is loaded and ready for input.
|
|
36
|
+
* Should only be called once (for first iframe, typically card_pan).
|
|
37
|
+
* Subsequent calls are no-ops.
|
|
38
|
+
*/
|
|
39
|
+
trackInputReady(): void;
|
|
40
|
+
/**
|
|
41
|
+
* Track when user clicks submit button.
|
|
42
|
+
*/
|
|
43
|
+
trackSubmit(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Track successful checkout.
|
|
46
|
+
*
|
|
47
|
+
* @param checkoutAttemptId - The checkout attempt ID
|
|
48
|
+
*/
|
|
49
|
+
trackSuccess(checkoutAttemptId: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Track failed checkout.
|
|
52
|
+
*
|
|
53
|
+
* @param checkoutAttemptId - The checkout attempt ID (may be null if failed early)
|
|
54
|
+
* @param errorCode - The error code from the checkout response
|
|
55
|
+
* @param errorMessage - The customer-facing error message
|
|
56
|
+
*/
|
|
57
|
+
trackFail(checkoutAttemptId: string | null, errorCode: string | null, errorMessage: string | null): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get elapsed time in milliseconds since tracker creation.
|
|
60
|
+
*/
|
|
61
|
+
private getElapsedMs;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/types.d.ts
|
|
65
|
+
|
|
66
|
+
type FormFieldNames = "customer_name" | "customer_email" | "customer_country" | "customer_zip_code";
|
|
67
|
+
type FormErrorCodes = "required" | "invalid";
|
|
68
|
+
type TInternalFuncs = {
|
|
69
|
+
submitPayment: (fields: PaymentKitFields, options?: unknown) => Promise<{
|
|
70
|
+
data: {
|
|
71
|
+
[key: string]: unknown;
|
|
72
|
+
};
|
|
73
|
+
errors?: never;
|
|
74
|
+
} | {
|
|
75
|
+
data?: never;
|
|
76
|
+
errors: PaymentKitErrors;
|
|
77
|
+
}>;
|
|
78
|
+
cleanup?: () => void;
|
|
79
|
+
};
|
|
80
|
+
type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {
|
|
81
|
+
environment: string;
|
|
82
|
+
secureToken: string;
|
|
83
|
+
paymentMethods: T;
|
|
84
|
+
/** @internal Enable analytics test mode for e2e testing */
|
|
85
|
+
__enableAnalyticsTestMode?: boolean;
|
|
86
|
+
}) => ExternalFuncsMapByPm<T> & {
|
|
87
|
+
submit: PaymentKitSubmitHandler<T>;
|
|
88
|
+
cleanup: () => void;
|
|
89
|
+
};
|
|
90
|
+
type PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <N extends keyof ExternalFuncsMapByPm<T>>(options: {
|
|
91
|
+
fields: PaymentKitFields;
|
|
92
|
+
paymentMethod: N;
|
|
93
|
+
options?: unknown;
|
|
94
|
+
onError: (error: PaymentKitErrors) => void;
|
|
95
|
+
onSuccess: (data: {
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
}) => void;
|
|
98
|
+
}) => void;
|
|
99
|
+
type PaymentKitStates = {
|
|
100
|
+
baseUrl: string;
|
|
101
|
+
apiBaseUrl: string;
|
|
102
|
+
secureToken: string;
|
|
103
|
+
environment: string;
|
|
104
|
+
tunnelXConnection: TunnelXIFrameConnection;
|
|
105
|
+
timingTracker: CheckoutTimingTracker;
|
|
106
|
+
};
|
|
107
|
+
type PaymentKitErrors = {
|
|
108
|
+
root?: string;
|
|
109
|
+
card_pan?: CardErrorCode;
|
|
110
|
+
card_exp?: CardErrorCode;
|
|
111
|
+
card_cvc?: CardErrorCode;
|
|
112
|
+
paypal?: string;
|
|
113
|
+
google_pay?: string;
|
|
114
|
+
apple_pay?: string;
|
|
115
|
+
processor_id?: string;
|
|
116
|
+
amount?: string;
|
|
117
|
+
currency?: string;
|
|
118
|
+
country?: string;
|
|
119
|
+
} & { [key in FormFieldNames]?: FormErrorCodes | string };
|
|
120
|
+
type PaymentKitFields = { [key in FormFieldNames]: string };
|
|
121
|
+
type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {
|
|
122
|
+
name: TName;
|
|
123
|
+
externalFuncs: TExternalFuncs;
|
|
124
|
+
internalFuncs: TInternalFuncs;
|
|
125
|
+
};
|
|
126
|
+
type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = { [K in T[number] as ReturnType<K>["name"]]: ReturnType<K>["externalFuncs"] };
|
|
127
|
+
//#endregion
|
|
128
|
+
export { PaymentKitFields as n, PaymentMethod as r, PaymentKit as t };
|
|
129
|
+
//# sourceMappingURL=types-CPuloCtF.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CPuloCtF.d.mts","names":[],"sources":["../src/analytics/checkout-timing.ts","../src/types.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAkBA;;;;ACoBC;AAID;AAEA;;;;;AAQA;AAA6C,cDlChC,qBAAA,CCkCgC;EAG3B,eAAA,gBAAA;EAGS,QAAA,SAAA;EAArB,QAAA,iBAAA;EAC4B,QAAA,iBAAA;EAAxB,WAAA,CAAA,iBAAA,EAAA,MAAA;EAAuB;AAE/B;;;;EAKQ,cAAA,CAAA,CAAA,EAAA,IAAA;EACO;;;AAMjB;AASA;EAEa,eAAA,CAAA,CAAA,EAAA,IAAA;EACA;;;EASmB,WAAA,CAAA,CAAA,EAAA,IAAA;EAAc;AAE9C;AAEA;;;EAEiB,YAAA,CAAA,iBAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EACA;;AAGjB;;;;;EACwD,SAAA,CAAA,iBAAA,EAAA,MAAA,GAAA,IAAA,EAAA,SAAA,EAAA,MAAA,GAAA,IAAA,EAAA,YAAA,EAAA,MAAA,GAAA,IAAA,CAAA,EAAA,IAAA;EAAX;;;;;;;;AA/D7C,KAFK,cAAA,GAEqB,eAAA,GAAA,gBAAA,GAAA,kBAAA,GAAA,mBAAA;AAEd,KAFA,cAAA,GAEc,UAAA,GAAA,SAAA;AAEd,KAFA,cAAA,GAEA;EAEkF,aAAA,EAAA,CAAA,MAAA,EAFlF,gBAEkF,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,GAAvF,OAAuF,CAAA;IAAvF,IAAA,EAAA;MAAO,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IAIF,CAAA;IAAiC,MAAA,CAAA,EAAA,KAAA;EAG3B,CAAA,GAAA;IAGS,IAAA,CAAA,EAAA,KAAA;IAArB,MAAA,EAVwF,gBAUxF;EAC4B,CAAA,CAAA;EAAxB,OAAA,CAAA,EAAA,GAAA,GAAA,IAAA;CAAuB;AAI5B,KAXO,UAAA,GAWP,CAAA,UAAuB,SAXiB,aAWjB,CAAA,OAAA,CAAA,EAAA,CAAA,CAAA,OAAA,EAAA;EAAoB,WAAA,EAAA,MAAA;EACT,WAAA,EAAA,MAAA;EAArB,cAAA,EATA,CASA;EAER;EACO,yBAAA,CAAA,EAAA,OAAA;CAEE,EAAA,GAXb,oBAWa,CAXQ,CAWR,CAAA,GAAA;EAAgB,MAAA,EAVzB,uBAUyB,CAVD,CAUC,CAAA;EAIvB,OAAA,EAAA,GAAA,GAAA,IAAgB;AAS5B,CAAA;KAnBK,uBAqBQ,CAAA,UAAA,SArBmC,aAqBnC,CAAA,OAAA,CAAA,EAAA,CAAA,GAAA,CAAA,UAAA,MApBK,oBAoBL,CApB0B,CAoB1B,CAAA,CAAA,CAAA,OAAA,EAAA;EACA,MAAA,EAnBH,gBAmBG;EACA,aAAA,EAnBI,CAmBJ;EAQC,OAAA,CAAA,EAAA,OAAA;EAAkB,OAAA,EAAA,CAAA,KAAA,EAzBb,gBAyBa,EAAA,GAAA,IAAA;EAAc,SAAA,EAAA,CAAA,IAAA,EAAA;IAElC,CAAA,GAAA,EAAA,MAAA,CAAA,EAAgB,OAAA;EAEhB,CAAA,EAAA,GAAA,IAAA;CAA6E,EAAA,GAAA,IAAA;AACjF,KA1BI,gBAAA,GA0BJ;EACS,OAAA,EAAA,MAAA;EACA,UAAA,EAAA,MAAA;EAAc,WAAA,EAAA,MAAA;EAGnB,WAAA,EAAA,MAAA;EAAwC,iBAAA,EA1B/B,uBA0B+B;EAC5C,aAAA,EA1BS,qBA0BT;CAAwB;AAAX,KAvBT,gBAAA,GAuBS;EAAmC,IAAA,CAAA,EAAA,MAAA;EAAX,QAAA,CAAA,EArBhC,aAqBgC;EAAU,QAAA,CAAA,EApB1C,aAoB0C;aAnB1C;;;;;;;;cAQC,kBAAkB;KAEpB,gBAAA,aAA6B;KAE7B,6EAA6E;QACjF;iBACS;iBACA;;KAGL,wCAAwC,oCAC5C,aAAa,WAAW,aAAa,WAAW"}
|
|
@@ -1,5 +1,43 @@
|
|
|
1
|
+
import { nanoid } from "nanoid";
|
|
1
2
|
import * as v from "valibot";
|
|
2
3
|
|
|
4
|
+
//#region src/utils/checkout-request-id.ts
|
|
5
|
+
/**
|
|
6
|
+
* Maps PaymentKit environment to request ID env slug.
|
|
7
|
+
* This must match the backend's env slug format.
|
|
8
|
+
*/
|
|
9
|
+
const ENV_TO_SLUG = {
|
|
10
|
+
local: "dev",
|
|
11
|
+
loclx: "dev",
|
|
12
|
+
sandbox: "stg",
|
|
13
|
+
production: "prod"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Generates a checkout request ID for correlating all API calls within a single checkout submission.
|
|
17
|
+
*
|
|
18
|
+
* Format: pk_{env}_{nanoid(12)}
|
|
19
|
+
* - pk = PaymentKit.js (client-generated)
|
|
20
|
+
* - env = dev, stg, or prod
|
|
21
|
+
* - nanoid(12) = 12 character random string
|
|
22
|
+
*
|
|
23
|
+
* Example: pk_stg_a1b2c3d4e5f6
|
|
24
|
+
*
|
|
25
|
+
* This ID should be:
|
|
26
|
+
* 1. Generated once when user clicks submit
|
|
27
|
+
* 2. Passed via x-request-id header on ALL checkout API calls
|
|
28
|
+
* 3. Used to correlate logs across the checkout flow
|
|
29
|
+
*/
|
|
30
|
+
function generateCheckoutRequestId(environment) {
|
|
31
|
+
return `pk_${ENV_TO_SLUG[environment] || "dev"}_${nanoid(12)}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates RequestOptions with the x-request-id header set.
|
|
35
|
+
*/
|
|
36
|
+
function withRequestId(checkoutRequestId) {
|
|
37
|
+
return { headers: { "x-request-id": checkoutRequestId } };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
3
41
|
//#region src/utils/validate-form-fields.ts
|
|
4
42
|
const validateFormFields = async (fields, options = {}) => {
|
|
5
43
|
const schema = v.object({
|
|
@@ -58,5 +96,5 @@ function collectFraudMetadata() {
|
|
|
58
96
|
}
|
|
59
97
|
|
|
60
98
|
//#endregion
|
|
61
|
-
export { validateFormFields as a, definePaymentMethod as i, collectFraudMetadata as n, createCheckoutIFrame as r, $ as t };
|
|
62
|
-
//# sourceMappingURL=utils-
|
|
99
|
+
export { validateFormFields as a, definePaymentMethod as i, collectFraudMetadata as n, generateCheckoutRequestId as o, createCheckoutIFrame as r, withRequestId as s, $ as t };
|
|
100
|
+
//# sourceMappingURL=utils-Dgyk7RkM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-Dgyk7RkM.mjs","names":["ENV_TO_SLUG: Record<string, string>"],"sources":["../src/utils/checkout-request-id.ts","../src/utils/validate-form-fields.ts","../src/utils/index.ts"],"sourcesContent":["import { nanoid } from \"nanoid\";\n\n/**\n * Maps PaymentKit environment to request ID env slug.\n * This must match the backend's env slug format.\n */\nconst ENV_TO_SLUG: Record<string, string> = {\n local: \"dev\",\n loclx: \"dev\",\n sandbox: \"stg\",\n production: \"prod\",\n};\n\n/**\n * Generates a checkout request ID for correlating all API calls within a single checkout submission.\n *\n * Format: pk_{env}_{nanoid(12)}\n * - pk = PaymentKit.js (client-generated)\n * - env = dev, stg, or prod\n * - nanoid(12) = 12 character random string\n *\n * Example: pk_stg_a1b2c3d4e5f6\n *\n * This ID should be:\n * 1. Generated once when user clicks submit\n * 2. Passed via x-request-id header on ALL checkout API calls\n * 3. Used to correlate logs across the checkout flow\n */\nexport function generateCheckoutRequestId(environment: string): string {\n const envSlug = ENV_TO_SLUG[environment] || \"dev\";\n const randomPart = nanoid(12);\n return `pk_${envSlug}_${randomPart}`;\n}\n\n/**\n * Creates RequestOptions with the x-request-id header set.\n */\nexport function withRequestId(checkoutRequestId: string) {\n return {\n headers: {\n \"x-request-id\": checkoutRequestId,\n },\n };\n}\n","import * as v from \"valibot\";\nimport type { FormErrorCodes, PaymentKitErrors, PaymentKitFields } from \"../types\";\n\ntype Options = {\n optionalZipCode?: boolean;\n};\n\nexport const validateFormFields = async (fields: PaymentKitFields, options: Options = {}) => {\n const schema = v.object({\n customer_name: v.pipe(\n v.string(\"required\"),\n v.nonEmpty(\"required\"),\n v.minLength(4, \"invalid\"),\n v.maxLength(40, \"invalid\"),\n ),\n customer_email: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\"), v.email(\"invalid\")),\n customer_country: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n customer_zip_code: options.optionalZipCode\n ? v.pipe(v.string(\"required\"))\n : v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n });\n\n const result = v.safeParse(schema, fields);\n\n if (result.issues) {\n const errors = result.issues.reduce((errors, issue) => {\n const field = v.getDotPath(issue) as keyof PaymentKitErrors;\n\n errors[field] = issue.kind === \"schema\" ? \"required\" : (issue.message as FormErrorCodes);\n return errors;\n }, {} as PaymentKitErrors);\n return { isSuccess: false, errors };\n }\n\n return { isSuccess: true };\n};\n","import type { PaymentMethod } from \"../types\";\n\nexport { generateCheckoutRequestId, withRequestId } from \"./checkout-request-id\";\nexport { validateFormFields } from \"./validate-form-fields\";\n\nexport const $ = (selector: string) => {\n const ele = document.querySelector(selector);\n if (!ele) {\n throw new Error(`Cannot find element with selector: ${selector}`);\n }\n return ele;\n};\n\nexport const definePaymentMethod = <TExternalFuncs, TName extends string>(\n paymentMethod: PaymentMethod<TExternalFuncs, TName>,\n) => paymentMethod;\n\nexport const createCheckoutIFrame = (type: string, baseUrl: string, params?: Record<string, string>) => {\n const iframe = document.createElement(\"iframe\");\n\n const searchParams = new URLSearchParams(params);\n const searchParamsStr = searchParams.toString();\n\n iframe.src = `${baseUrl}/embeds/v1/${type}${searchParamsStr ? `?${searchParamsStr}` : \"\"}`;\n\n Object.assign(iframe.style, { width: \"100%\", height: \"100%\", border: \"none\" });\n\n return iframe;\n};\n\n/**\n * Collects browser and client information for fraud detection.\n */\nexport function collectFraudMetadata() {\n return {\n ipAddress: undefined, // IP address should be collected server-side\n browserInfo: {\n userAgent: navigator.userAgent,\n language: navigator.language,\n screenHeight: window.screen.height,\n screenWidth: window.screen.width,\n colorDepth: window.screen.colorDepth,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n },\n processorFraudInfo: undefined,\n };\n}\n\ntype AddressInput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zip_code?: string;\n country?: string;\n};\n\ntype AddressOutput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zipCode?: string;\n country?: string;\n};\n\n/**\n * Maps address fields from snake_case to camelCase format.\n */\nexport function mapAddress(address?: AddressInput): AddressOutput | undefined {\n if (!address) return undefined;\n\n return {\n line1: address.line1,\n line2: address.line2,\n city: address.city,\n state: address.state,\n zipCode: address.zip_code,\n country: address.country,\n };\n}\n"],"mappings":";;;;;;;;AAMA,MAAMA,cAAsC;CAC1C,OAAO;CACP,OAAO;CACP,SAAS;CACT,YAAY;CACb;;;;;;;;;;;;;;;;AAiBD,SAAgB,0BAA0B,aAA6B;AAGrE,QAAO,MAFS,YAAY,gBAAgB,MAEvB,GADF,OAAO,GAAG;;;;;AAO/B,SAAgB,cAAc,mBAA2B;AACvD,QAAO,EACL,SAAS,EACP,gBAAgB,mBACjB,EACF;;;;;ACnCH,MAAa,qBAAqB,OAAO,QAA0B,UAAmB,EAAE,KAAK;CAC3F,MAAM,SAAS,EAAE,OAAO;EACtB,eAAe,EAAE,KACf,EAAE,OAAO,WAAW,EACpB,EAAE,SAAS,WAAW,EACtB,EAAE,UAAU,GAAG,UAAU,EACzB,EAAE,UAAU,IAAI,UAAU,CAC3B;EACD,gBAAgB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,UAAU,CAAC;EACxF,kBAAkB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACtE,mBAAmB,QAAQ,kBACvB,EAAE,KAAK,EAAE,OAAO,WAAW,CAAC,GAC5B,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACzD,CAAC;CAEF,MAAM,SAAS,EAAE,UAAU,QAAQ,OAAO;AAE1C,KAAI,OAAO,OAOT,QAAO;EAAE,WAAW;EAAO,QANZ,OAAO,OAAO,QAAQ,QAAQ,UAAU;GACrD,MAAM,QAAQ,EAAE,WAAW,MAAM;AAEjC,UAAO,SAAS,MAAM,SAAS,WAAW,aAAc,MAAM;AAC9D,UAAO;KACN,EAAE,CAAqB;EACS;AAGrC,QAAO,EAAE,WAAW,MAAM;;;;;AC7B5B,MAAa,KAAK,aAAqB;CACrC,MAAM,MAAM,SAAS,cAAc,SAAS;AAC5C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,sCAAsC,WAAW;AAEnE,QAAO;;AAGT,MAAa,uBACX,kBACG;AAEL,MAAa,wBAAwB,MAAc,SAAiB,WAAoC;CACtG,MAAM,SAAS,SAAS,cAAc,SAAS;CAG/C,MAAM,kBADe,IAAI,gBAAgB,OAAO,CACX,UAAU;AAE/C,QAAO,MAAM,GAAG,QAAQ,aAAa,OAAO,kBAAkB,IAAI,oBAAoB;AAEtF,QAAO,OAAO,OAAO,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAQ,QAAQ;EAAQ,CAAC;AAE9E,QAAO;;;;;AAMT,SAAgB,uBAAuB;AACrC,QAAO;EACL,WAAW;EACX,aAAa;GACX,WAAW,UAAU;GACrB,UAAU,UAAU;GACpB,cAAc,OAAO,OAAO;GAC5B,aAAa,OAAO,OAAO;GAC3B,YAAY,OAAO,OAAO;GAC1B,UAAU,KAAK,gBAAgB,CAAC,iBAAiB,CAAC;GACnD;EACD,oBAAoB;EACrB"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payment-kit-js/vanilla",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"main": "./dist/index.mjs",
|
|
5
5
|
"types": "./dist/index.d.mts",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": "./dist/index.mjs",
|
|
9
|
+
"./payment-methods/airwallex-google-pay-adapter": "./dist/payment-methods/airwallex-google-pay-adapter.mjs",
|
|
10
|
+
"./payment-methods/apple-pay": "./dist/payment-methods/apple-pay.mjs",
|
|
9
11
|
"./payment-methods/card": "./dist/payment-methods/card.mjs",
|
|
10
12
|
"./payment-methods/google-pay": "./dist/payment-methods/google-pay.mjs",
|
|
11
13
|
"./payment-methods/next-action-handlers": "./dist/payment-methods/next-action-handlers.mjs",
|
|
12
14
|
"./payment-methods/paypal": "./dist/payment-methods/paypal.mjs",
|
|
15
|
+
"./payment-methods/stripe-apple-pay-adapter": "./dist/payment-methods/stripe-apple-pay-adapter.mjs",
|
|
13
16
|
"./payment-methods/stripe-google-pay-adapter": "./dist/payment-methods/stripe-google-pay-adapter.mjs",
|
|
14
17
|
"./penpal/connect-card": "./dist/penpal/connect-card.mjs",
|
|
15
18
|
"./penpal/connect-tunnel-x": "./dist/penpal/connect-tunnel-x.mjs",
|
|
@@ -29,16 +32,19 @@
|
|
|
29
32
|
},
|
|
30
33
|
"packageManager": "yarn@4.10.3",
|
|
31
34
|
"dependencies": {
|
|
35
|
+
"nanoid": "^5.0.7",
|
|
32
36
|
"penpal": "^7.0.4",
|
|
37
|
+
"posthog-js": "^1.196.0",
|
|
33
38
|
"valibot": "^1.1.0"
|
|
34
39
|
},
|
|
35
40
|
"devDependencies": {
|
|
36
41
|
"@pkg/sdk": "0.10.21",
|
|
37
42
|
"@pkg/tsconfig": "0.0.0",
|
|
38
|
-
"@stripe/stripe-js": "^
|
|
43
|
+
"@stripe/stripe-js": "^8.6.1",
|
|
44
|
+
"@types/applepayjs": "^14.0.9",
|
|
39
45
|
"esbuild": "^0.24.2",
|
|
40
46
|
"tsdown": "^0.15.10",
|
|
41
47
|
"typescript": "^5.9.3"
|
|
42
48
|
},
|
|
43
|
-
"stableVersion": "0.
|
|
49
|
+
"stableVersion": "0.4.1"
|
|
44
50
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"connect-tunnel-x-B7iMQ7DX.d.mts","names":[],"sources":["../src/penpal/connect-tunnel-x.ts"],"sourcesContent":[],"mappings":";;;AAOyC,KAMpC,oBAAA,GAAoB;EAGE,YAAA,EAAA,GAAA,GAAA,IAAA;EAA2B,cAAA,EAAA,GAAA,GAAA,IAAA;EAEO,cAAA,EAAA,CAAA,MAAA,EAFlC,MAEkC,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,GAFP,OAEO,CAAA,OAAA,CAAA;EAAR,kBAAA,EAAA,GAAA,GAAA,IAAA;EACK,kBAAA,EAAA,CAAA,iBAAA,EAAA,MAAA,EAAA,GADL,OACK,CADG,eACH,CAAA;EAAR,qBAAA,EAAA,CAAA,WAAA,EAAA,MAAA,EAAA,GAAA,OAAA,CAAQ,wBAAR,CAAA;EACqB,mBAAA,EAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,OAAA,CAAA,EAAA,cAAA,EAAA,GAAmB,OAAnB,CAAA,OAAA,CAAA;CAAmB;KAGrF,oBAAA,GAAuB,MAHqE,CAAA,MAAA,EAAA,KAAA,CAAA;AAG5F,KAEO,uBAAA,GAA0B,UAFJ,CAEe,oBAFf,CAAA;AAEtB,KAEA,uBAAA,GAA0B,UAFW,CAEA,oBAFX,CAAA;AAE1B,cAEC,sBAFoC,EAAA,CAAA,MAAA,EAEF,iBAFT,EAAA,OAAU,EAE2B,oBAF3B,EAAA,GAE+C,UAF/C,CAE+C,oBAF/C,CAAA;AAEnC,cAIA,sBAFZ,EAAA,CAAA,OAAA,EAE+C,oBAF/C,EAAA,GAEmE,UAFnE,CAEmE,oBAFnE,CAAA;;;;;;AAED,KASK,oBAAA,GATQ;EAAmC,qBAAA,EAAA,CAAA,MAAA,EAAA;IAAoB,aAAA,EAAA,MAAA;EAAA,CAAA,EAAA,GAUJ,OAVI,CAUI,wBAVJ,CAAA;EAAA,kBAAA,EAAA,CAAA,MAAA,EAAA;IAS/D,aAAA,EAAA,MAAoB;IAC+C,iBAAA,EAAA,MAAA;EAAR,CAAA,EAAA,GACwB,OADxB,CACgC,eADhC,CAAA;EACgC,YAAA,EAAA,CAAA,MAAA,EAAA;IAAR,aAAA,EAAA,MAAA;IAGzD,yBAAA,EAAA,yBAAA;EACf,CAAA,EAAA,GAAR,OAAQ,CAAA,0BAAA,CAAA;EAAR,kBAAA,EAAA,CAAA,MAAA,EAAA;IAC6D,aAAA,EAAA,MAAA;EAAR,CAAA,EAAA,GAAA,OAAA,CAAQ,0BAAR,CAAA;CAAO;AAGvD,cAAA,cAAA,CAAc;EAER,QAAA,UAAA;EAEsC,QAAA,EAFtC,oBAEsC;EAAuB,OAAA,0BAAA,EAAA,CAAA,UAAA,EAAvB,uBAAuB,EAAA,GAAA,OAAA,CAAA,cAAA,CAAA;EAAA,QAAA,WAAA,CAAA;EAevD;;;;yBAAA"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
//#region src/payment-methods/next-action-handlers.ts
|
|
2
|
-
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
3
|
-
const isStripeJsPresent = () => "Stripe" in window;
|
|
4
|
-
/**
|
|
5
|
-
* Get the Stripe instance from the global window object.
|
|
6
|
-
* Expects Stripe.js to be loaded via HTML script tag.
|
|
7
|
-
* Polls for up to 5 seconds waiting for Stripe to be available.
|
|
8
|
-
*/
|
|
9
|
-
const getLoadedStripe = async (publishableKey) => {
|
|
10
|
-
for (let i = 0; i < 10; i++) {
|
|
11
|
-
if (isStripeJsPresent()) break;
|
|
12
|
-
await sleep(500);
|
|
13
|
-
}
|
|
14
|
-
if (!isStripeJsPresent()) throw new Error("Stripe.js not loaded. Add this script tag to your HTML <head>:\n<script src=\"https://js.stripe.com/v3/\"><\/script>");
|
|
15
|
-
return new window.Stripe(publishableKey);
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Handle Stripe 3DS authentication.
|
|
19
|
-
*/
|
|
20
|
-
const handleStripe3ds = async (nextAction) => {
|
|
21
|
-
console.log("3DS authentication required, loading Stripe...");
|
|
22
|
-
const { clientSecret, stripePk } = nextAction;
|
|
23
|
-
const { error: stripeError } = await (await getLoadedStripe(stripePk)).confirmCardPayment(clientSecret);
|
|
24
|
-
if (stripeError) {
|
|
25
|
-
console.error("3DS authentication failed:", stripeError);
|
|
26
|
-
return {
|
|
27
|
-
success: false,
|
|
28
|
-
error: stripeError.message || "3DS authentication failed"
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
console.log("3DS authentication completed");
|
|
32
|
-
return { success: true };
|
|
33
|
-
};
|
|
34
|
-
/**
|
|
35
|
-
* Handle a next action based on its type.
|
|
36
|
-
* Routes to the appropriate processor-specific handler.
|
|
37
|
-
*
|
|
38
|
-
* @param nextAction - The next action from the checkout response
|
|
39
|
-
* @returns Result indicating success or failure with error message
|
|
40
|
-
*/
|
|
41
|
-
const handleNextAction = async (nextAction) => {
|
|
42
|
-
switch (nextAction.type) {
|
|
43
|
-
case "stripe_3ds": return handleStripe3ds(nextAction);
|
|
44
|
-
default: return {
|
|
45
|
-
success: false,
|
|
46
|
-
error: `Unknown next action type: ${nextAction.type}`
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
//#endregion
|
|
52
|
-
export { handleNextAction as t };
|
|
53
|
-
//# sourceMappingURL=next-action-handlers-DTsWjUIA.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"next-action-handlers-DTsWjUIA.mjs","names":[],"sources":["../src/payment-methods/next-action-handlers.ts"],"sourcesContent":["/**\n * Next action handlers for processor-specific user actions (e.g., 3DS authentication).\n *\n * This module abstracts processor-specific logic away from the generic card payment flow.\n * Each handler implements the logic needed for a specific next action type.\n */\n\nimport type { PublicCardCheckoutResponse } from \"@pkg/sdk/models\";\nimport type { Stripe } from \"@stripe/stripe-js\";\n\n// Helper to wait for a condition\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n// Check if Stripe.js is loaded via script tag\nconst isStripeJsPresent = (): boolean => \"Stripe\" in window;\n\n/**\n * Get the Stripe instance from the global window object.\n * Expects Stripe.js to be loaded via HTML script tag.\n * Polls for up to 5 seconds waiting for Stripe to be available.\n */\nconst getLoadedStripe = async (publishableKey: string): Promise<Stripe> => {\n // Poll for Stripe.js to be loaded (up to 5 seconds)\n for (let i = 0; i < 10; i++) {\n if (isStripeJsPresent()) {\n break;\n }\n await sleep(500);\n }\n\n if (!isStripeJsPresent()) {\n throw new Error(\n \"Stripe.js not loaded. Add this script tag to your HTML <head>:\\n\" +\n '<script src=\"https://js.stripe.com/v3/\"></script>',\n );\n }\n\n // @ts-expect-error Stripe is loaded globally via script tag\n const stripe: Stripe = new window.Stripe(publishableKey);\n return stripe;\n};\n\n/**\n * Result of handling a next action.\n */\nexport type NextActionResult = { success: true } | { success: false; error: string };\n\n/**\n * Handle Stripe 3DS authentication.\n */\nconst handleStripe3ds = async (\n nextAction: Extract<PublicCardCheckoutResponse[\"nextAction\"], { type: \"stripe_3ds\" }>,\n): Promise<NextActionResult> => {\n console.log(\"3DS authentication required, loading Stripe...\");\n const { clientSecret, stripePk } = nextAction;\n\n const stripe = await getLoadedStripe(stripePk);\n\n // Show 3DS modal\n const { error: stripeError } = await stripe.confirmCardPayment(clientSecret);\n\n if (stripeError) {\n console.error(\"3DS authentication failed:\", stripeError);\n return { success: false, error: stripeError.message || \"3DS authentication failed\" };\n }\n\n console.log(\"3DS authentication completed\");\n return { success: true };\n};\n\n/**\n * Handle a next action based on its type.\n * Routes to the appropriate processor-specific handler.\n *\n * @param nextAction - The next action from the checkout response\n * @returns Result indicating success or failure with error message\n */\nexport const handleNextAction = async (\n nextAction: NonNullable<PublicCardCheckoutResponse[\"nextAction\"]>,\n): Promise<NextActionResult> => {\n switch (nextAction.type) {\n case \"stripe_3ds\":\n return handleStripe3ds(nextAction);\n default:\n // TypeScript will catch if we miss a case when new action types are added\n return { success: false, error: `Unknown next action type: ${(nextAction as { type: string }).type}` };\n }\n};\n"],"mappings":";AAWA,MAAM,SAAS,OAA8B,IAAI,SAAS,YAAY,WAAW,SAAS,GAAG,CAAC;AAG9F,MAAM,0BAAmC,YAAY;;;;;;AAOrD,MAAM,kBAAkB,OAAO,mBAA4C;AAEzE,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,KAAK;AAC3B,MAAI,mBAAmB,CACrB;AAEF,QAAM,MAAM,IAAI;;AAGlB,KAAI,CAAC,mBAAmB,CACtB,OAAM,IAAI,MACR,uHAED;AAKH,QADuB,IAAI,OAAO,OAAO,eAAe;;;;;AAY1D,MAAM,kBAAkB,OACtB,eAC8B;AAC9B,SAAQ,IAAI,iDAAiD;CAC7D,MAAM,EAAE,cAAc,aAAa;CAKnC,MAAM,EAAE,OAAO,gBAAgB,OAHhB,MAAM,gBAAgB,SAAS,EAGF,mBAAmB,aAAa;AAE5E,KAAI,aAAa;AACf,UAAQ,MAAM,8BAA8B,YAAY;AACxD,SAAO;GAAE,SAAS;GAAO,OAAO,YAAY,WAAW;GAA6B;;AAGtF,SAAQ,IAAI,+BAA+B;AAC3C,QAAO,EAAE,SAAS,MAAM;;;;;;;;;AAU1B,MAAa,mBAAmB,OAC9B,eAC8B;AAC9B,SAAQ,WAAW,MAAnB;EACE,KAAK,aACH,QAAO,gBAAgB,WAAW;EACpC,QAEE,QAAO;GAAE,SAAS;GAAO,OAAO,6BAA8B,WAAgC;GAAQ"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { t as CardErrorCode } from "./connect-card-C582hcWw.mjs";
|
|
2
|
-
import { t as TunnelXIFrameConnection } from "./connect-tunnel-x-B7iMQ7DX.mjs";
|
|
3
|
-
|
|
4
|
-
//#region src/types.d.ts
|
|
5
|
-
|
|
6
|
-
type FormFieldNames = "customer_name" | "customer_email" | "customer_country" | "customer_zip_code";
|
|
7
|
-
type FormErrorCodes = "required" | "invalid";
|
|
8
|
-
type TInternalFuncs = {
|
|
9
|
-
submitPayment: (fields: PaymentKitFields, options?: unknown) => Promise<{
|
|
10
|
-
data: {
|
|
11
|
-
[key: string]: unknown;
|
|
12
|
-
};
|
|
13
|
-
errors?: never;
|
|
14
|
-
} | {
|
|
15
|
-
data?: never;
|
|
16
|
-
errors: PaymentKitErrors;
|
|
17
|
-
}>;
|
|
18
|
-
cleanup?: () => void;
|
|
19
|
-
};
|
|
20
|
-
type PaymentKit = <T extends readonly PaymentMethod<unknown>[]>(options: {
|
|
21
|
-
environment: string;
|
|
22
|
-
secureToken: string;
|
|
23
|
-
paymentMethods: T;
|
|
24
|
-
}) => ExternalFuncsMapByPm<T> & {
|
|
25
|
-
submit: PaymentKitSubmitHandler<T>;
|
|
26
|
-
cleanup: () => void;
|
|
27
|
-
};
|
|
28
|
-
type PaymentKitSubmitHandler<T extends readonly PaymentMethod<unknown>[]> = <N extends keyof ExternalFuncsMapByPm<T>>(options: {
|
|
29
|
-
fields: PaymentKitFields;
|
|
30
|
-
paymentMethod: N;
|
|
31
|
-
options?: unknown;
|
|
32
|
-
onError: (error: PaymentKitErrors) => void;
|
|
33
|
-
onSuccess: (data: {
|
|
34
|
-
[key: string]: unknown;
|
|
35
|
-
}) => void;
|
|
36
|
-
}) => void;
|
|
37
|
-
type PaymentKitStates = {
|
|
38
|
-
baseUrl: string;
|
|
39
|
-
apiBaseUrl: string;
|
|
40
|
-
secureToken: string;
|
|
41
|
-
tunnelXConnection: TunnelXIFrameConnection;
|
|
42
|
-
};
|
|
43
|
-
type PaymentKitErrors = {
|
|
44
|
-
root?: string;
|
|
45
|
-
card_pan?: CardErrorCode;
|
|
46
|
-
card_exp?: CardErrorCode;
|
|
47
|
-
card_cvc?: CardErrorCode;
|
|
48
|
-
paypal?: string;
|
|
49
|
-
google_pay?: string;
|
|
50
|
-
processor_id?: string;
|
|
51
|
-
amount?: string;
|
|
52
|
-
currency?: string;
|
|
53
|
-
country?: string;
|
|
54
|
-
} & { [key in FormFieldNames]?: FormErrorCodes | string };
|
|
55
|
-
type PaymentKitFields = { [key in FormFieldNames]: string };
|
|
56
|
-
type PaymentMethod<TExternalFuncs = unknown, TName = string> = (paymentKitStates: PaymentKitStates) => {
|
|
57
|
-
name: TName;
|
|
58
|
-
externalFuncs: TExternalFuncs;
|
|
59
|
-
internalFuncs: TInternalFuncs;
|
|
60
|
-
};
|
|
61
|
-
type ExternalFuncsMapByPm<T extends readonly PaymentMethod<unknown>[]> = { [K in T[number] as ReturnType<K>["name"]]: ReturnType<K>["externalFuncs"] };
|
|
62
|
-
//#endregion
|
|
63
|
-
export { PaymentKitFields as n, PaymentMethod as r, PaymentKit as t };
|
|
64
|
-
//# sourceMappingURL=types-DsVMq4jZ.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types-DsVMq4jZ.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;;;;KAmCK,cAAA,GAQyF,eAAA,GAAA,gBAAA,GAAA,kBAAA,GAAA,mBAAA;AAAvF,KANK,cAAA,GAML,UAAA,GAAA,SAAA;AAAO,KAJF,cAAA,GAIE;EAIF,aAAU,EAAA,CAAA,MAAA,EANV,gBAMU,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,GAJf,OAIe,CAAA;IAAuB,IAAA,EAAA;MAG3B,CAAA,GAAA,EAAA,MAAA,CAAA,EAAA,OAAA;IACS,CAAA;IAArB,MAAA,CAAA,EAAA,KAAA;EAC4B,CAAA,GAAA;IAAxB,IAAA,CAAA,EAAA,KAAA;IAAuB,MAAA,EAT6D,gBAS7D;EAI5B,CAAA,CAAA;EAA2C,OAAA,CAAA,EAAA,GAAA,GAAA,IAAA;CACT;AAArB,KAVN,UAAA,GAUM,CAAA,UAAA,SAV2B,aAU3B,CAAA,OAAA,CAAA,EAAA,CAAA,CAAA,OAAA,EAAA;EAER,WAAA,EAAA,MAAA;EACO,WAAA,EAAA,MAAA;EAEE,cAAA,EAZD,CAYC;CAAgB,EAAA,GAX7B,oBAW6B,CAXR,CAWQ,CAAA,GAAA;EAIvB,MAAA,EAdF,uBAkBW,CAlBa,CAkBb,CAAA;EAGT,OAAA,EAAA,GAAA,GAAA,IAAgB;CAEf;KAnBR,uBAoBQ,CAAA,UAAA,SApBmC,aAoBnC,CAAA,OAAA,CAAA,EAAA,CAAA,GAAA,CAAA,UAAA,MAnBK,oBAmBL,CAnB0B,CAmB1B,CAAA,CAAA,CAAA,OAAA,EAAA;EACA,MAAA,EAlBH,gBAkBG;EAOC,aAAA,EAxBG,CAwBH;EAAkB,OAAA,CAAA,EAAA,OAAA;EAAc,OAAA,EAAA,CAAA,KAAA,EAtB3B,gBAsB2B,EAAA,GAAA,IAAA;EAElC,SAAA,EAAA,CAAA,IAAA,EAAA;IAEA,CAAA,GAAA,EAAA,MAAa,CAAA,EAAA,OAAA;EAAgE,CAAA,EAAA,GAAA,IAAA;CACjF,EAAA,GAAA,IAAA;AACS,KAxBL,gBAAA,GAwBK;EACA,OAAA,EAAA,MAAA;EAAc,UAAA,EAAA,MAAA;EAGnB,WAAA,EAAA,MAAA;EAAwC,iBAAA,EAxB/B,uBAwB+B;CAC5C;AAAwB,KAtBpB,gBAAA,GAsBoB;EAAX,IAAA,CAAA,EAAA,MAAA;EAAmC,QAAA,CAAA,EApB3C,aAoB2C;EAAX,QAAA,CAAA,EAnBhC,aAmBgC;EAAU,QAAA,CAAA,EAlB1C,aAkB0C;;;;;;;cAXzC,kBAAkB;KAEpB,gBAAA,aAA6B;KAE7B,6EAA6E;QACjF;iBACS;iBACA;;KAGL,wCAAwC,oCAC5C,aAAa,WAAW,aAAa,WAAW"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-h0dxplHy.mjs","names":[],"sources":["../src/utils/validate-form-fields.ts","../src/utils/index.ts"],"sourcesContent":["import * as v from \"valibot\";\nimport type { FormErrorCodes, PaymentKitErrors, PaymentKitFields } from \"../types\";\n\ntype Options = {\n optionalZipCode?: boolean;\n};\n\nexport const validateFormFields = async (fields: PaymentKitFields, options: Options = {}) => {\n const schema = v.object({\n customer_name: v.pipe(\n v.string(\"required\"),\n v.nonEmpty(\"required\"),\n v.minLength(4, \"invalid\"),\n v.maxLength(40, \"invalid\"),\n ),\n customer_email: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\"), v.email(\"invalid\")),\n customer_country: v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n customer_zip_code: options.optionalZipCode\n ? v.pipe(v.string(\"required\"))\n : v.pipe(v.string(\"required\"), v.nonEmpty(\"required\")),\n });\n\n const result = v.safeParse(schema, fields);\n\n if (result.issues) {\n const errors = result.issues.reduce((errors, issue) => {\n const field = v.getDotPath(issue) as keyof PaymentKitErrors;\n\n errors[field] = issue.kind === \"schema\" ? \"required\" : (issue.message as FormErrorCodes);\n return errors;\n }, {} as PaymentKitErrors);\n return { isSuccess: false, errors };\n }\n\n return { isSuccess: true };\n};\n","import type { PaymentMethod } from \"../types\";\n\nexport { validateFormFields } from \"./validate-form-fields\";\n\nexport const $ = (selector: string) => {\n const ele = document.querySelector(selector);\n if (!ele) {\n throw new Error(`Cannot find element with selector: ${selector}`);\n }\n return ele;\n};\n\nexport const definePaymentMethod = <TExternalFuncs, TName extends string>(\n paymentMethod: PaymentMethod<TExternalFuncs, TName>,\n) => paymentMethod;\n\nexport const createCheckoutIFrame = (type: string, baseUrl: string, params?: Record<string, string>) => {\n const iframe = document.createElement(\"iframe\");\n\n const searchParams = new URLSearchParams(params);\n const searchParamsStr = searchParams.toString();\n\n iframe.src = `${baseUrl}/embeds/v1/${type}${searchParamsStr ? `?${searchParamsStr}` : \"\"}`;\n\n Object.assign(iframe.style, { width: \"100%\", height: \"100%\", border: \"none\" });\n\n return iframe;\n};\n\n/**\n * Collects browser and client information for fraud detection.\n */\nexport function collectFraudMetadata() {\n return {\n ipAddress: undefined, // IP address should be collected server-side\n browserInfo: {\n userAgent: navigator.userAgent,\n language: navigator.language,\n screenHeight: window.screen.height,\n screenWidth: window.screen.width,\n colorDepth: window.screen.colorDepth,\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n },\n processorFraudInfo: undefined,\n };\n}\n\ntype AddressInput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zip_code?: string;\n country?: string;\n};\n\ntype AddressOutput = {\n line1?: string;\n line2?: string;\n city?: string;\n state?: string;\n zipCode?: string;\n country?: string;\n};\n\n/**\n * Maps address fields from snake_case to camelCase format.\n */\nexport function mapAddress(address?: AddressInput): AddressOutput | undefined {\n if (!address) return undefined;\n\n return {\n line1: address.line1,\n line2: address.line2,\n city: address.city,\n state: address.state,\n zipCode: address.zip_code,\n country: address.country,\n };\n}\n"],"mappings":";;;AAOA,MAAa,qBAAqB,OAAO,QAA0B,UAAmB,EAAE,KAAK;CAC3F,MAAM,SAAS,EAAE,OAAO;EACtB,eAAe,EAAE,KACf,EAAE,OAAO,WAAW,EACpB,EAAE,SAAS,WAAW,EACtB,EAAE,UAAU,GAAG,UAAU,EACzB,EAAE,UAAU,IAAI,UAAU,CAC3B;EACD,gBAAgB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,EAAE,EAAE,MAAM,UAAU,CAAC;EACxF,kBAAkB,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACtE,mBAAmB,QAAQ,kBACvB,EAAE,KAAK,EAAE,OAAO,WAAW,CAAC,GAC5B,EAAE,KAAK,EAAE,OAAO,WAAW,EAAE,EAAE,SAAS,WAAW,CAAC;EACzD,CAAC;CAEF,MAAM,SAAS,EAAE,UAAU,QAAQ,OAAO;AAE1C,KAAI,OAAO,OAOT,QAAO;EAAE,WAAW;EAAO,QANZ,OAAO,OAAO,QAAQ,QAAQ,UAAU;GACrD,MAAM,QAAQ,EAAE,WAAW,MAAM;AAEjC,UAAO,SAAS,MAAM,SAAS,WAAW,aAAc,MAAM;AAC9D,UAAO;KACN,EAAE,CAAqB;EACS;AAGrC,QAAO,EAAE,WAAW,MAAM;;;;;AC9B5B,MAAa,KAAK,aAAqB;CACrC,MAAM,MAAM,SAAS,cAAc,SAAS;AAC5C,KAAI,CAAC,IACH,OAAM,IAAI,MAAM,sCAAsC,WAAW;AAEnE,QAAO;;AAGT,MAAa,uBACX,kBACG;AAEL,MAAa,wBAAwB,MAAc,SAAiB,WAAoC;CACtG,MAAM,SAAS,SAAS,cAAc,SAAS;CAG/C,MAAM,kBADe,IAAI,gBAAgB,OAAO,CACX,UAAU;AAE/C,QAAO,MAAM,GAAG,QAAQ,aAAa,OAAO,kBAAkB,IAAI,oBAAoB;AAEtF,QAAO,OAAO,OAAO,OAAO;EAAE,OAAO;EAAQ,QAAQ;EAAQ,QAAQ;EAAQ,CAAC;AAE9E,QAAO;;;;;AAMT,SAAgB,uBAAuB;AACrC,QAAO;EACL,WAAW;EACX,aAAa;GACX,WAAW,UAAU;GACrB,UAAU,UAAU;GACpB,cAAc,OAAO,OAAO;GAC5B,aAAa,OAAO,OAAO;GAC3B,YAAY,OAAO,OAAO;GAC1B,UAAU,KAAK,gBAAgB,CAAC,iBAAiB,CAAC;GACnD;EACD,oBAAoB;EACrB"}
|