@agent-cards/sdk 0.24.1 → 0.25.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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * How an approved tokenization is named in the confirmation that pays with it,
3
+ * by the Stripe endpoint whose answer produced it. The same four endpoints mint
4
+ * an approved object (lifecycle.ts), and this table holds the three a
5
+ * confirmation names by id on its own. It mirrors APPROVED_OBJECT in the
6
+ * backend's checkout-continuation.ts, which judges exactly this shape: exactly
7
+ * one such field, and no payment_method_data field left beside it.
8
+ *
9
+ * `/v1/tokens` is deliberately absent. Its field lives inside the method data
10
+ * (payment_method_data[card][token]), so paying with a card token means writing
11
+ * into the method data this rewrite strips rather than replacing it, and no page
12
+ * has been seen doing that. A confirm carrying a card token keeps the ordinary
13
+ * hold until one is.
14
+ */
15
+ export declare const STRIPE_APPROVED_WAY: Readonly<Record<string, Readonly<{
16
+ field: string;
17
+ prefix: string;
18
+ }>>>;
19
+ /** An approved object a confirmation can pay with: the field that names it, and its id. */
20
+ export type StripeApprovedWay = {
21
+ field: string;
22
+ id: string;
23
+ };
24
+ /**
25
+ * The approved object a Stripe tokenization answer returned, for the endpoint
26
+ * that answered: its field and its id. Null for an endpoint no confirmation
27
+ * names by id, for a body that will not parse, and for an id that is not the
28
+ * one that endpoint mints, so a confirmation can never be sent paying with
29
+ * something another endpoint produced.
30
+ */
31
+ export declare function stripeApprovedWay(pathname: string, body: unknown): StripeApprovedWay | null;
32
+ /**
33
+ * The page's confirmation, paying with `way` instead of the card it carries:
34
+ * every `payment_method_data[...]` field goes (the card, and the billing details
35
+ * and telemetry Stripe.js sends beside it; the approved object already carries
36
+ * the billing details of the approved request), and `<field>=<id>` takes the
37
+ * place of the first one. Every other field stays byte for byte as the page
38
+ * wrote it (client_secret, key, expected_payment_method_type, use_stripe_sdk,
39
+ * return_url, mandate and option fields). Null, and nothing is rewritten, when
40
+ * the field is not one a confirmation pays with, when the id is not one Stripe
41
+ * mints, when a key cannot be decoded, when the body already names a way to pay
42
+ * (payment_method, source, confirmation_token), or when it carries no
43
+ * payment_method_data at all.
44
+ */
45
+ export declare function confirmPayingWith(body: string, way: StripeApprovedWay): string | null;
@@ -0,0 +1,106 @@
1
+ // What a Stripe confirmation the cardholder already approved may pay with,
2
+ // shared by the card save and the payment (cdp.ts claimStripeContinuation).
3
+ // Kept in its own module, outside the package's published entries, so its
4
+ // tests can reach it and lifecycle.ts can read the same table.
5
+ //
6
+ // A page tokenizes the card through an approval and then confirms. Some pages
7
+ // confirm with the object they got back, which carries no card. Others send
8
+ // the card again inline, as payment_method_data[card][number] in the confirm:
9
+ // confirmCardSetup with the Card Element after createPaymentMethod does on a
10
+ // SetupIntent, and a store that creates a confirmation token for a fraud check
11
+ // and then calls confirmPayment({ elements }) does on a PaymentIntent. The card
12
+ // in that second request is whatever the agent typed; the approved object holds
13
+ // the cardholder's card. So that confirm is sent paying with the approved
14
+ // object instead, with no card in it, and the API decides whether it is the
15
+ // payment the cardholder approved.
16
+ /**
17
+ * How an approved tokenization is named in the confirmation that pays with it,
18
+ * by the Stripe endpoint whose answer produced it. The same four endpoints mint
19
+ * an approved object (lifecycle.ts), and this table holds the three a
20
+ * confirmation names by id on its own. It mirrors APPROVED_OBJECT in the
21
+ * backend's checkout-continuation.ts, which judges exactly this shape: exactly
22
+ * one such field, and no payment_method_data field left beside it.
23
+ *
24
+ * `/v1/tokens` is deliberately absent. Its field lives inside the method data
25
+ * (payment_method_data[card][token]), so paying with a card token means writing
26
+ * into the method data this rewrite strips rather than replacing it, and no page
27
+ * has been seen doing that. A confirm carrying a card token keeps the ordinary
28
+ * hold until one is.
29
+ */
30
+ export const STRIPE_APPROVED_WAY = Object.freeze({
31
+ '/v1/payment_methods': Object.freeze({ field: 'payment_method', prefix: 'pm_' }),
32
+ '/v1/confirmation_tokens': Object.freeze({ field: 'confirmation_token', prefix: 'ctoken_' }),
33
+ '/v1/sources': Object.freeze({ field: 'source', prefix: 'src_' }),
34
+ });
35
+ // The other ways a confirmation can say what it pays with. A body that already
36
+ // names one is not the shape rewritten here, the field about to be written
37
+ // included: there is then nothing to replace, and the body already names a way
38
+ // to pay, so the ordinary hold decides it.
39
+ const OTHER_WAYS_TO_PAY = new Set(['payment_method', 'source', 'confirmation_token']);
40
+ // An id as Stripe mints it, and as a form field can carry it unescaped.
41
+ const APPROVED_ID = /^[a-z]+_[A-Za-z0-9]{1,250}$/;
42
+ /**
43
+ * The approved object a Stripe tokenization answer returned, for the endpoint
44
+ * that answered: its field and its id. Null for an endpoint no confirmation
45
+ * names by id, for a body that will not parse, and for an id that is not the
46
+ * one that endpoint mints, so a confirmation can never be sent paying with
47
+ * something another endpoint produced.
48
+ */
49
+ export function stripeApprovedWay(pathname, body) {
50
+ const way = Object.prototype.hasOwnProperty.call(STRIPE_APPROVED_WAY, pathname) ? STRIPE_APPROVED_WAY[pathname] : undefined;
51
+ if (!way || typeof body !== 'string')
52
+ return null;
53
+ let id;
54
+ try {
55
+ id = JSON.parse(body)?.id;
56
+ }
57
+ catch {
58
+ return null;
59
+ }
60
+ if (typeof id !== 'string' || !id.startsWith(way.prefix) || !APPROVED_ID.test(id))
61
+ return null;
62
+ return { field: way.field, id };
63
+ }
64
+ /**
65
+ * The page's confirmation, paying with `way` instead of the card it carries:
66
+ * every `payment_method_data[...]` field goes (the card, and the billing details
67
+ * and telemetry Stripe.js sends beside it; the approved object already carries
68
+ * the billing details of the approved request), and `<field>=<id>` takes the
69
+ * place of the first one. Every other field stays byte for byte as the page
70
+ * wrote it (client_secret, key, expected_payment_method_type, use_stripe_sdk,
71
+ * return_url, mandate and option fields). Null, and nothing is rewritten, when
72
+ * the field is not one a confirmation pays with, when the id is not one Stripe
73
+ * mints, when a key cannot be decoded, when the body already names a way to pay
74
+ * (payment_method, source, confirmation_token), or when it carries no
75
+ * payment_method_data at all.
76
+ */
77
+ export function confirmPayingWith(body, way) {
78
+ if (typeof body !== 'string' || body === '')
79
+ return null;
80
+ if (!way || !OTHER_WAYS_TO_PAY.has(way.field) || !APPROVED_ID.test(way.id))
81
+ return null;
82
+ const kept = [];
83
+ let replaced = false;
84
+ for (const chunk of body.split('&')) {
85
+ if (chunk === '')
86
+ continue;
87
+ const eq = chunk.indexOf('=');
88
+ let key;
89
+ try {
90
+ key = decodeURIComponent((eq < 0 ? chunk : chunk.slice(0, eq)).replace(/\+/g, ' '));
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ if (OTHER_WAYS_TO_PAY.has(key))
96
+ return null;
97
+ if (key.startsWith('payment_method_data[')) {
98
+ if (!replaced)
99
+ kept.push(`${way.field}=${way.id}`);
100
+ replaced = true;
101
+ continue;
102
+ }
103
+ kept.push(chunk);
104
+ }
105
+ return replaced ? kept.join('&') : null;
106
+ }
@@ -2,15 +2,10 @@
2
2
  export declare const STRIPE_SETUP_INTENT_CONFIRM: RegExp;
3
3
  /**
4
4
  * The page's SetupIntent confirm, paying with `paymentMethod` instead of the
5
- * card it carries: every `payment_method_data[...]` field goes (the card, and
6
- * the billing details and telemetry Stripe.js sends beside it; the payment
7
- * method already carries the billing details of the approved request), and
8
- * `payment_method=<id>` takes the place of the first one. Every other field
9
- * stays byte for byte as the page wrote it (client_secret, key,
10
- * expected_payment_method_type, use_stripe_sdk, return_url, mandate and option
11
- * fields). Null, and nothing is rewritten, when the id is not a payment
12
- * method's, when a key cannot be decoded, when the body already names another
13
- * way to pay (payment_method, source, confirmation_token), or when it carries
14
- * no payment_method_data at all.
5
+ * card it carries (confirmPayingWith, with the payment method as the way to
6
+ * pay). Null, and nothing is rewritten, when the id is not a payment method's,
7
+ * when a key cannot be decoded, when the body already names another way to pay
8
+ * (payment_method, source, confirmation_token), or when it carries no
9
+ * payment_method_data at all.
15
10
  */
16
11
  export declare function setupConfirmPayingWith(body: string, paymentMethod: string): string | null;
@@ -1,6 +1,8 @@
1
1
  // The SetupIntent confirm a Stripe card save continues with, shared by both
2
2
  // adapters (cdp.ts claimStripeContinuation). Kept in its own module, outside the
3
- // package's published entries, so its tests can reach it.
3
+ // package's published entries, so its tests can reach it. The rewrite itself,
4
+ // and the table of approved objects a confirmation can pay with, live in
5
+ // stripe-continuation.ts, which the payment side reads too.
4
6
  //
5
7
  // A page that creates the payment method first (createPaymentMethod, which the
6
8
  // cardholder approves) and then confirms a SetupIntent usually pays with the
@@ -12,50 +14,20 @@
12
14
  // agent typed; the approved payment method holds the cardholder's card. So that
13
15
  // confirm continues paying with the approved payment method instead, once the
14
16
  // API allows it.
17
+ import { confirmPayingWith } from './stripe-continuation.js';
15
18
  /** A SetupIntent confirm's path, as Stripe.js sends it. */
16
19
  export const STRIPE_SETUP_INTENT_CONFIRM = /^\/v1\/setup_intents\/seti_[A-Za-z0-9]+\/confirm$/;
17
20
  const PAYMENT_METHOD_ID = /^pm_[A-Za-z0-9]{1,250}$/;
18
- // The other ways a confirm can say what it pays with. A body that already names
19
- // one is not the shape rewritten here.
20
- const OTHER_WAYS_TO_PAY = new Set(['payment_method', 'source', 'confirmation_token']);
21
21
  /**
22
22
  * The page's SetupIntent confirm, paying with `paymentMethod` instead of the
23
- * card it carries: every `payment_method_data[...]` field goes (the card, and
24
- * the billing details and telemetry Stripe.js sends beside it; the payment
25
- * method already carries the billing details of the approved request), and
26
- * `payment_method=<id>` takes the place of the first one. Every other field
27
- * stays byte for byte as the page wrote it (client_secret, key,
28
- * expected_payment_method_type, use_stripe_sdk, return_url, mandate and option
29
- * fields). Null, and nothing is rewritten, when the id is not a payment
30
- * method's, when a key cannot be decoded, when the body already names another
31
- * way to pay (payment_method, source, confirmation_token), or when it carries
32
- * no payment_method_data at all.
23
+ * card it carries (confirmPayingWith, with the payment method as the way to
24
+ * pay). Null, and nothing is rewritten, when the id is not a payment method's,
25
+ * when a key cannot be decoded, when the body already names another way to pay
26
+ * (payment_method, source, confirmation_token), or when it carries no
27
+ * payment_method_data at all.
33
28
  */
34
29
  export function setupConfirmPayingWith(body, paymentMethod) {
35
- if (!PAYMENT_METHOD_ID.test(paymentMethod) || typeof body !== 'string' || body === '')
30
+ if (!PAYMENT_METHOD_ID.test(paymentMethod))
36
31
  return null;
37
- const kept = [];
38
- let replaced = false;
39
- for (const chunk of body.split('&')) {
40
- if (chunk === '')
41
- continue;
42
- const eq = chunk.indexOf('=');
43
- let key;
44
- try {
45
- key = decodeURIComponent((eq < 0 ? chunk : chunk.slice(0, eq)).replace(/\+/g, ' '));
46
- }
47
- catch {
48
- return null;
49
- }
50
- if (OTHER_WAYS_TO_PAY.has(key))
51
- return null;
52
- if (key.startsWith('payment_method_data[')) {
53
- if (!replaced)
54
- kept.push(`payment_method=${paymentMethod}`);
55
- replaced = true;
56
- continue;
57
- }
58
- kept.push(chunk);
59
- }
60
- return replaced ? kept.join('&') : null;
32
+ return confirmPayingWith(body, { field: 'payment_method', id: paymentMethod });
61
33
  }
@@ -0,0 +1,32 @@
1
+ import type { ReplayResponse } from './client.js';
2
+ /** How long an approved answer may answer a re-send: the approval's own lifetime (cdp.ts HOSTED_FORM_REPEAT_QUIET_MS). */
3
+ export declare const TOKEN_REPEAT_WINDOW_MS: number;
4
+ /** How many re-sends one approved answer answers. Shopify's frame sent 11 in a row; past this the re-send is held. */
5
+ export declare const MAX_TOKEN_REPEATS = 3;
6
+ export interface TokenRepeatAnswer {
7
+ authorizationId: string;
8
+ response: {
9
+ status: number;
10
+ headers: Record<string, string>;
11
+ body: string;
12
+ };
13
+ }
14
+ export declare class TokenRepeats {
15
+ private readonly now;
16
+ private last;
17
+ constructor(now?: () => number);
18
+ /**
19
+ * Keep the answer a token replay handed to a card request, once it reached the page. Only a plain token answer the
20
+ * processor accepted (a 2xx): a hosted form, a card endpoint, a client-side encryption or a device's own send is
21
+ * never answered again from here. A new answer replaces the last, so an earlier approval answers nothing.
22
+ */
23
+ remember(frame: unknown, url: string, body: string | null, replay: ReplayResponse): void;
24
+ /**
25
+ * The stored answer for a byte-identical re-send from the same frame under `authorizationId`, inside the window and
26
+ * the count, or null. Handing one out reserves a place in the count; the caller gives it back (released) when the
27
+ * answer never reached the page.
28
+ */
29
+ answerFor(frame: unknown, url: string, body: string | null, authorizationId: string | null): TokenRepeatAnswer | null;
30
+ /** Give back a place answerFor reserved for an answer that never reached the page. */
31
+ released(authorizationId: string): void;
32
+ }
@@ -0,0 +1,64 @@
1
+ // The page's own re-send of a card request this attachment already answered with an approved token.
2
+ //
3
+ // Once the cardholder's device replayed the card and the processor's token reached the page, a checkout can send the
4
+ // very same card request again before the merchant confirms the order: Shopify's card frame did, after a checkout that
5
+ // sat a few minutes between its total and Pay (lexmod.com, expedusa.com and four more stores, 2026-10-27 to 2026-11-05).
6
+ // The SDK held every such re-send while the merchant resolver read the order as pending (lifecycle.ts resolve), so the
7
+ // page never got a token it would submit and the order stayed unconfirmed with the card already out of the device.
8
+ //
9
+ // TokenRepeats keeps the one answer this attachment last handed a plain token request, and hands it out again only for
10
+ // a byte-identical request from the same frame to the same URL under the same approval: the same card fields, the same
11
+ // amount the approval was given for, and no new question for the cardholder. The pre-claim gate (pre-claim.ts tokenRepeatPreClaim) also
12
+ // asks the merchant resolver first and answers only while the order reads pending, so the stored token never reaches a
13
+ // later purchase. A token the processor takes once is refused by the processor the second time, and nothing charges
14
+ // twice: the page holds the same token it already had, never a second payment.
15
+ /** How long an approved answer may answer a re-send: the approval's own lifetime (cdp.ts HOSTED_FORM_REPEAT_QUIET_MS). */
16
+ export const TOKEN_REPEAT_WINDOW_MS = 15 * 60_000;
17
+ /** How many re-sends one approved answer answers. Shopify's frame sent 11 in a row; past this the re-send is held. */
18
+ export const MAX_TOKEN_REPEATS = 3;
19
+ export class TokenRepeats {
20
+ now;
21
+ last = null;
22
+ constructor(now = Date.now) {
23
+ this.now = now;
24
+ }
25
+ /**
26
+ * Keep the answer a token replay handed to a card request, once it reached the page. Only a plain token answer the
27
+ * processor accepted (a 2xx): a hosted form, a card endpoint, a client-side encryption or a device's own send is
28
+ * never answered again from here. A new answer replaces the last, so an earlier approval answers nothing.
29
+ */
30
+ remember(frame, url, body, replay) {
31
+ try {
32
+ if (frame === undefined || frame === null || frame === '' || body === null || (replay.mode !== undefined && replay.mode !== 'token'))
33
+ return;
34
+ const { status, headers } = replay;
35
+ if (!(status >= 200 && status < 300) || typeof replay.body !== 'string')
36
+ return;
37
+ this.last = { frame, url, body, authorizationId: replay.authorizationId, response: { status, headers: { ...headers }, body: replay.body }, at: this.now(), answered: 0 };
38
+ }
39
+ catch {
40
+ this.last = null;
41
+ }
42
+ }
43
+ /**
44
+ * The stored answer for a byte-identical re-send from the same frame under `authorizationId`, inside the window and
45
+ * the count, or null. Handing one out reserves a place in the count; the caller gives it back (released) when the
46
+ * answer never reached the page.
47
+ */
48
+ answerFor(frame, url, body, authorizationId) {
49
+ const last = this.last;
50
+ if (!last || !authorizationId || body === null || frame === undefined || frame === null || frame === '')
51
+ return null;
52
+ if (last.authorizationId !== authorizationId || last.frame !== frame || last.url !== url || last.body !== body)
53
+ return null;
54
+ if (this.now() - last.at >= TOKEN_REPEAT_WINDOW_MS || last.answered >= MAX_TOKEN_REPEATS)
55
+ return null;
56
+ last.answered += 1;
57
+ return { authorizationId, response: { ...last.response, headers: { ...last.response.headers } } };
58
+ }
59
+ /** Give back a place answerFor reserved for an answer that never reached the page. */
60
+ released(authorizationId) {
61
+ if (this.last?.authorizationId === authorizationId && this.last.answered > 0)
62
+ this.last.answered -= 1;
63
+ }
64
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": 1,
3
3
  "catalog_version": "2026-09-15.1",
4
- "catalog_sha256": "86bf0b382e6d847b49d00310f262cf697a0189d4badf89c36ebfb595e07a005b",
4
+ "catalog_sha256": "87d4e75b981d7186a2cd39b6f382717acf5b757d053ed389cb8e181f261f0a49",
5
5
  "baseline_version": "kernel-native-docs-2026-09-11.1",
6
6
  "baseline_sha256": "d86722f49633d8223fccae54cd3d485df4375aee06aa156a273cc689b7c8507c",
7
7
  "native_build": null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-cards/sdk",
3
- "version": "0.24.1",
3
+ "version": "0.25.0",
4
4
  "description": "Agentcard's SDK: one client, Agentcard, with two modules. checkout pauses a browser purchase and pays it with the person's own card; buy asks the Purchase API for a cart and places it. Card data never enters your process.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "_comment_test": "check:built runs first and names the command when a file the build generates (the copies in src/, the preflight contracts in dist/, the Kernel inventory) is missing or stale; verify:pack runs last, on the same dist.",
31
31
  "check:built": "node scripts/generate-payment-core.mjs --check && node scripts/generate-url-masks.mjs --check && node scripts/generate-capabilities.mjs --check && node scripts/generate-agent-amount.mjs --check && node scripts/generate-preflight-contract.mjs --check && node scripts/generate-kernel-native-inventory.mjs --check",
32
32
  "verify:pack": "node scripts/verify-pack.mjs",
33
- "test": "npm run check:built && node test.mjs && node --test lifecycle.test.mjs merchant-abort.test.mjs preparation.test.mjs braintree.test.mjs pre-claim.test.mjs ekashu.test.mjs redsys.test.mjs quickpay.test.mjs paytrail.test.mjs paypal-hosted-fields.test.mjs paypal-card-forms.test.mjs cybersource-secure-acceptance.test.mjs ebanx.test.mjs payrexx.test.mjs payrexx-follow-ups.test.mjs payrexx-adapters.test.mjs nike-order.test.mjs nike-order-adapters.test.mjs autopilot.test.mjs stripe-checkout.test.mjs stripe-setup.test.mjs stripe-legacy-checkout.test.mjs payment-core.test.mjs prepared-processor.test.mjs merchant-hosted.test.mjs merchant-total.test.mjs sandbox-declaration.test.mjs minimum-delay.test.mjs paysafe.test.mjs wix-payments.test.mjs hipay.test.mjs openpay.test.mjs processout.test.mjs payu.test.mjs attachment.test.mjs worker-targets.test.mjs mercado-checkout.test.mjs mercado-polling.test.mjs amadeus.test.mjs pelecard.test.mjs aci.test.mjs primer.test.mjs payrails.test.mjs elavon-converge.test.mjs agentcard.test.mjs buy.test.mjs clean-dist.test.mjs approvals.test.mjs gmo.test.mjs cybersource-flex.test.mjs juspay-gate.test.mjs card-endpoint.test.mjs card-endpoint-fastspring.test.mjs card-endpoint-navigation.test.mjs merchant-session-probe.test.mjs datatrans.test.mjs authorize-net-dpm.test.mjs creditguard.test.mjs eprotect.test.mjs wspay.test.mjs shiji-sts.test.mjs worldline-mycheckout.test.mjs verifone.test.mjs gravy.test.mjs paddle-vgs.test.mjs sbps.test.mjs hold.test.mjs paddle-tokenex.test.mjs lyra.test.mjs gopay.test.mjs paygent.test.mjs twoc2p.test.mjs tap-payments.test.mjs pay-nl.test.mjs toast.test.mjs redact-url.test.mjs hosted-entry.test.mjs comgate.test.mjs przelewy24.test.mjs tokenex-iframe.test.mjs transbank.test.mjs sumup.test.mjs clover.test.mjs eximbay.test.mjs xendit.test.mjs omise.test.mjs fastspring.test.mjs amazon-payment-services.test.mjs barion.test.mjs paymob.test.mjs payu-latam.test.mjs nexi-checkout.test.mjs oceanpayment.test.mjs pin-payments.test.mjs payplug.test.mjs cardlink-vpos.test.mjs eghl.test.mjs paymentwall.test.mjs vtex-payments.test.mjs vtex-payments-window.test.mjs iyzico.test.mjs usaepay.test.mjs viva-wallet.test.mjs aurus.test.mjs monei.test.mjs paystack.test.mjs frisbii.test.mjs && node --test preflight-package.test.mjs preflight-collector.test.mjs browser-tests.test.mjs && node --test kernel-native-qualification.test.mjs && node --test ../vault/scripts/recurly-validation/watch-duty-sdk-result.test.mjs && node scripts/verify-pack.mjs",
33
+ "test": "npm run check:built && node test.mjs && node --test lifecycle.test.mjs merchant-abort.test.mjs preparation.test.mjs braintree.test.mjs pre-claim.test.mjs ekashu.test.mjs redsys.test.mjs quickpay.test.mjs paytrail.test.mjs paypal-hosted-fields.test.mjs paypal-card-forms.test.mjs cybersource-secure-acceptance.test.mjs ebanx.test.mjs payrexx.test.mjs payrexx-follow-ups.test.mjs payrexx-adapters.test.mjs nike-order.test.mjs nike-order-adapters.test.mjs autopilot.test.mjs stripe-checkout.test.mjs stripe-setup.test.mjs stripe-payment-continuation.test.mjs stripe-legacy-checkout.test.mjs payment-core.test.mjs prepared-processor.test.mjs merchant-hosted.test.mjs merchant-total.test.mjs sandbox-declaration.test.mjs minimum-delay.test.mjs paysafe.test.mjs wix-payments.test.mjs hipay.test.mjs openpay.test.mjs processout.test.mjs payu.test.mjs attachment.test.mjs worker-targets.test.mjs mercado-checkout.test.mjs mercado-polling.test.mjs amadeus.test.mjs pelecard.test.mjs aci.test.mjs primer.test.mjs payrails.test.mjs elavon-converge.test.mjs agentcard.test.mjs buy.test.mjs clean-dist.test.mjs approvals.test.mjs gmo.test.mjs cybersource-flex.test.mjs juspay-gate.test.mjs card-endpoint.test.mjs card-endpoint-fastspring.test.mjs card-endpoint-navigation.test.mjs merchant-session-probe.test.mjs datatrans.test.mjs authorize-net-dpm.test.mjs creditguard.test.mjs eprotect.test.mjs wspay.test.mjs shiji-sts.test.mjs worldline-mycheckout.test.mjs verifone.test.mjs gravy.test.mjs paddle-vgs.test.mjs sbps.test.mjs hold.test.mjs paddle-tokenex.test.mjs lyra.test.mjs gopay.test.mjs paygent.test.mjs twoc2p.test.mjs tap-payments.test.mjs pay-nl.test.mjs toast.test.mjs redact-url.test.mjs hosted-entry.test.mjs comgate.test.mjs przelewy24.test.mjs tokenex-iframe.test.mjs transbank.test.mjs sumup.test.mjs clover.test.mjs eximbay.test.mjs xendit.test.mjs omise.test.mjs fastspring.test.mjs amazon-payment-services.test.mjs barion.test.mjs paymob.test.mjs payu-latam.test.mjs nexi-checkout.test.mjs oceanpayment.test.mjs pin-payments.test.mjs payplug.test.mjs cardlink-vpos.test.mjs eghl.test.mjs paymentwall.test.mjs vtex-payments.test.mjs vtex-payments-window.test.mjs iyzico.test.mjs usaepay.test.mjs viva-wallet.test.mjs aurus.test.mjs monei.test.mjs paystack.test.mjs frisbii.test.mjs token-repeat.test.mjs && node --test preflight-package.test.mjs preflight-collector.test.mjs browser-tests.test.mjs && node --test kernel-native-qualification.test.mjs && node --test ../vault/scripts/recurly-validation/watch-duty-sdk-result.test.mjs && node scripts/verify-pack.mjs",
34
34
  "test:browser": "node browser-tests.mjs",
35
35
  "check:payment-core": "node scripts/generate-payment-core.mjs --check",
36
36
  "test:preflight": "node --test preflight-package.test.mjs preflight-collector.test.mjs kernel-native-qualification.test.mjs",