@asteby/storefront 0.13.0 → 0.14.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/README.md +27 -1
- package/dist/chunk-IPUAZ3LQ.js +646 -0
- package/dist/chunk-IPUAZ3LQ.js.map +1 -0
- package/dist/cli.js +40 -1
- package/dist/fiscal-document.d.cts +2 -2
- package/dist/fiscal-document.d.ts +2 -2
- package/dist/index.cjs +196 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +67 -3
- package/dist/index.d.ts +67 -3
- package/dist/index.js +73 -316
- package/dist/index.js.map +1 -1
- package/dist/mock.cjs +417 -39
- package/dist/mock.cjs.map +1 -1
- package/dist/mock.d.cts +3 -1
- package/dist/mock.d.ts +3 -1
- package/dist/mock.js +272 -23
- package/dist/mock.js.map +1 -1
- package/dist/mockup.d.cts +1 -1
- package/dist/mockup.d.ts +1 -1
- package/dist/node.cjs +1 -1
- package/dist/node.js +1 -1
- package/dist/{types-C_rsJRCl.d.ts → types-BeTemDg6.d.ts} +209 -1
- package/dist/{types-BQ3S6VjF.d.cts → types-BuKb-zbi.d.cts} +209 -1
- package/package.json +1 -1
- package/dist/chunk-HBSB7XS2.js +0 -220
- package/dist/chunk-HBSB7XS2.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,81 +1,7 @@
|
|
|
1
|
-
import { availabilityLocale, formatAvailabilityMessage } from './chunk-
|
|
2
|
-
export { availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, formatAvailabilityMessage, productAvailability, resolveAvailability, schemaAvailability } from './chunk-
|
|
1
|
+
import { isStorefrontError, availabilityLocale, StorefrontError, formatAvailabilityMessage, defaultCodeForStatus } from './chunk-IPUAZ3LQ.js';
|
|
2
|
+
export { PICKUP_STEPS, SHIPPING_STEPS, StorefrontError, availabilityLocale, availabilityMessages, availabilityView, cartLineProblemView, declineMessage, declineMessageKey, formatAvailabilityMessage, formatVoucherExpiry, isStorefrontError, isTestInvoice, isTestShipment, nextAction, orderProgress, orderShipments, paymentErrorView, paymentIdempotencyKey, paymentMessages, paymentOutcome, productAvailability, resolveAvailability, safeHttpsUrl, safeTrackingUrl, schemaAvailability, shipmentsStatus, sortTrackingEvents } from './chunk-IPUAZ3LQ.js';
|
|
3
3
|
import { isValidPoint } from './chunk-45R47HYO.js';
|
|
4
4
|
|
|
5
|
-
// src/errors.ts
|
|
6
|
-
var StorefrontError = class extends Error {
|
|
7
|
-
name = "StorefrontError";
|
|
8
|
-
status;
|
|
9
|
-
code;
|
|
10
|
-
field;
|
|
11
|
-
details;
|
|
12
|
-
url;
|
|
13
|
-
/** Scopes a `403 insufficient_scope` says the route needs (empty for any other error). */
|
|
14
|
-
requiredScopes;
|
|
15
|
-
/** `true`: repeating the request (same idempotency key) can succeed. `false`: not until someone fixes something. `undefined`: OPS did not say. */
|
|
16
|
-
retryable;
|
|
17
|
-
/** Seconds OPS asks to wait before retrying. */
|
|
18
|
-
retryAfter;
|
|
19
|
-
/** Checkout that a refused cart write can resume. */
|
|
20
|
-
checkoutId;
|
|
21
|
-
/** Current cart cost sent with a `price_mismatch` (untrusted shape). */
|
|
22
|
-
cost;
|
|
23
|
-
/** English version of `message`, when OPS sent one. */
|
|
24
|
-
messageEn;
|
|
25
|
-
constructor(init) {
|
|
26
|
-
super(init.message, init.cause === void 0 ? void 0 : { cause: init.cause });
|
|
27
|
-
this.status = init.status;
|
|
28
|
-
this.code = init.code;
|
|
29
|
-
this.field = init.field;
|
|
30
|
-
this.details = init.details;
|
|
31
|
-
this.url = init.url;
|
|
32
|
-
this.requiredScopes = init.requiredScopes ?? [];
|
|
33
|
-
this.retryable = init.retryable;
|
|
34
|
-
this.retryAfter = init.retryAfter;
|
|
35
|
-
this.checkoutId = init.checkoutId;
|
|
36
|
-
this.cost = init.cost;
|
|
37
|
-
this.messageEn = init.messageEn;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Affected lines of a `409 insufficient_stock` (empty for any other error or a
|
|
41
|
-
* server older than contract 1.1). The cart is untouched: show the lines and
|
|
42
|
-
* let the buyer adjust or remove them.
|
|
43
|
-
*/
|
|
44
|
-
get stockLines() {
|
|
45
|
-
const lines = this.details?.lines;
|
|
46
|
-
if (this.code !== "insufficient_stock" || !Array.isArray(lines)) return [];
|
|
47
|
-
return lines.filter((l) => typeof l === "object" && l !== null && typeof l.sku === "string");
|
|
48
|
-
}
|
|
49
|
-
toJSON() {
|
|
50
|
-
return {
|
|
51
|
-
name: this.name,
|
|
52
|
-
status: this.status,
|
|
53
|
-
code: this.code,
|
|
54
|
-
message: this.message,
|
|
55
|
-
field: this.field,
|
|
56
|
-
...this.requiredScopes.length ? { requiredScopes: this.requiredScopes } : {},
|
|
57
|
-
...this.retryable !== void 0 ? { retryable: this.retryable } : {},
|
|
58
|
-
...this.retryAfter !== void 0 ? { retryAfter: this.retryAfter } : {},
|
|
59
|
-
...this.checkoutId ? { checkoutId: this.checkoutId } : {}
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
function isStorefrontError(err) {
|
|
64
|
-
return err instanceof StorefrontError || typeof err === "object" && err !== null && err.name === "StorefrontError";
|
|
65
|
-
}
|
|
66
|
-
var STATUS_CODES = {
|
|
67
|
-
400: "validation",
|
|
68
|
-
401: "unauthorized",
|
|
69
|
-
403: "forbidden",
|
|
70
|
-
404: "not_found",
|
|
71
|
-
409: "conflict",
|
|
72
|
-
422: "invalid_state",
|
|
73
|
-
429: "rate_limited"
|
|
74
|
-
};
|
|
75
|
-
function defaultCodeForStatus(status) {
|
|
76
|
-
return STATUS_CODES[status] ?? (status >= 500 ? "server_error" : "invalid_response");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
5
|
// src/money.ts
|
|
80
6
|
function parseMoney(money) {
|
|
81
7
|
if (money == null) return 0;
|
|
@@ -171,6 +97,7 @@ function joinUrl(baseUrl, path) {
|
|
|
171
97
|
return baseUrl.replace(/\/+$/, "") + path;
|
|
172
98
|
}
|
|
173
99
|
function enc(segment) {
|
|
100
|
+
if (typeof segment !== "string" || /^(?:\.|%2e){1,2}$/i.test(segment)) throw new TypeError(`Invalid path segment: ${String(segment)}`);
|
|
174
101
|
return encodeURIComponent(segment);
|
|
175
102
|
}
|
|
176
103
|
function linkSignals(signals) {
|
|
@@ -267,6 +194,7 @@ function createStorefrontClient(config) {
|
|
|
267
194
|
const linked = linkSignals([options.signal, timeoutController?.signal]);
|
|
268
195
|
const init = {
|
|
269
196
|
...passthrough,
|
|
197
|
+
...spec.noRedirect ? { redirect: "error" } : {},
|
|
270
198
|
method: spec.method,
|
|
271
199
|
headers,
|
|
272
200
|
...spec.body !== void 0 ? { body: JSON.stringify(spec.body) } : {},
|
|
@@ -292,6 +220,10 @@ function createStorefrontClient(config) {
|
|
|
292
220
|
linked.cleanup();
|
|
293
221
|
}
|
|
294
222
|
if (config.onResponse) await config.onResponse({ ...ctx, response: res, durationMs: Date.now() - started });
|
|
223
|
+
if (spec.noRedirect && res.redirected) {
|
|
224
|
+
await res.text().catch(() => void 0);
|
|
225
|
+
throw new StorefrontError({ status: 502, code: "invalid_response", message: "The answer was redirected; it is refused", url });
|
|
226
|
+
}
|
|
295
227
|
if (res.status === 404 && spec.nullOn404) {
|
|
296
228
|
await res.text().catch(() => void 0);
|
|
297
229
|
return null;
|
|
@@ -477,6 +409,39 @@ function createStorefrontClient(config) {
|
|
|
477
409
|
order: (id, options) => getOrNull(`/storefront/customer/orders/${enc(id)}`, void 0, options),
|
|
478
410
|
requestReturn: (orderId, input, options) => write("POST", `/storefront/customer/orders/${enc(orderId)}/returns`, input, options),
|
|
479
411
|
requestInvoice: (orderId, input, options) => write("POST", `/storefront/customer/orders/${enc(orderId)}/invoice`, input, options),
|
|
412
|
+
/**
|
|
413
|
+
* Checkouts waiting for their payment (cash voucher: OXXO, SPEI). They are not orders yet; once the payment
|
|
414
|
+
* confirms they leave this list and show up in `orders`.
|
|
415
|
+
*/
|
|
416
|
+
pendingPayments: async (params, options) => (
|
|
417
|
+
// An OPS older than the route answers 404: it has no pending payments to list (a 401 still throws).
|
|
418
|
+
await getOrNull("/storefront/customer/pending-payments", params, options) ?? {
|
|
419
|
+
nodes: [],
|
|
420
|
+
page_info: { has_next_page: false, end_cursor: null },
|
|
421
|
+
total_count: 0
|
|
422
|
+
}
|
|
423
|
+
),
|
|
424
|
+
/**
|
|
425
|
+
* Reads one file (`pdf` | `xml`) of an invoice or credit note of the buyer's order, through the authenticated
|
|
426
|
+
* route (`order_invoice_file`): the answer is the file itself (base64), never a URL, so neither the buyer token
|
|
427
|
+
* nor a link of the PAC reaches the browser. Call it from YOUR server and stream the bytes
|
|
428
|
+
* (`invoiceFileBytes`). `null` when the order, the document or the file does not exist or is not the buyer's.
|
|
429
|
+
*/
|
|
430
|
+
invoiceFile: async (orderId, invoiceId, kind, options) => {
|
|
431
|
+
if (kind !== "pdf" && kind !== "xml") throw new TypeError("invoiceFile: kind must be 'pdf' or 'xml'");
|
|
432
|
+
const file = await request({
|
|
433
|
+
method: "GET",
|
|
434
|
+
path: `/storefront/customer/orders/${enc(orderId)}/invoices/${enc(invoiceId)}/${kind}`,
|
|
435
|
+
options: { ...options, cache: "no-store" },
|
|
436
|
+
nullOn404: true,
|
|
437
|
+
noRedirect: true
|
|
438
|
+
});
|
|
439
|
+
if (file === null) return null;
|
|
440
|
+
if (!file || typeof file.content_base64 !== "string" || typeof file.filename !== "string" || typeof file.content_type !== "string") {
|
|
441
|
+
throw new StorefrontError({ status: 502, code: "invalid_response", message: "The invoice file answer is not a file" });
|
|
442
|
+
}
|
|
443
|
+
return { filename: file.filename, content_type: file.content_type, content_base64: file.content_base64 };
|
|
444
|
+
},
|
|
480
445
|
addresses: {
|
|
481
446
|
list: (options) => get("/storefront/customer/addresses", void 0, options),
|
|
482
447
|
create: (address, options) => write("POST", "/storefront/customer/addresses", address, options),
|
|
@@ -571,243 +536,8 @@ async function diagnose(client, options = {}) {
|
|
|
571
536
|
}
|
|
572
537
|
}
|
|
573
538
|
|
|
574
|
-
// src/payments.ts
|
|
575
|
-
var ES = {
|
|
576
|
-
"decline.insufficient_funds": "Tu tarjeta no tiene saldo suficiente. Prueba con otra tarjeta o paga en efectivo.",
|
|
577
|
-
"decline.invalid_cvc": "El c\xF3digo de seguridad no es correcto. Rev\xEDsalo e intenta de nuevo.",
|
|
578
|
-
"decline.invalid_expiry": "La fecha de vencimiento no es correcta.",
|
|
579
|
-
"decline.invalid_card_data": "Revisa los datos de tu tarjeta.",
|
|
580
|
-
"decline.call_issuer": "Tu banco necesita que autorices este pago. Llama al n\xFAmero al reverso de tu tarjeta y vuelve a intentarlo.",
|
|
581
|
-
"decline.card_disabled": "Tu tarjeta no est\xE1 activa. Act\xEDvala con tu banco o usa otra.",
|
|
582
|
-
"decline.duplicate": "Ya hiciste un pago igual hace un momento. Revisa tu correo antes de volver a pagar.",
|
|
583
|
-
"decline.max_attempts": "Llegaste al l\xEDmite de intentos con esta tarjeta. Usa otra o paga en efectivo.",
|
|
584
|
-
"decline.authentication_failed": "Tu banco no pudo verificar el pago. Intenta de nuevo o usa otra tarjeta.",
|
|
585
|
-
"decline.declined": "Tu banco rechaz\xF3 el pago. Usa otra tarjeta o paga en efectivo.",
|
|
586
|
-
"state.loading": "Cargando pago seguro\u2026",
|
|
587
|
-
"state.processing": "Procesando pago\u2026",
|
|
588
|
-
"state.approved": "\xA1Pago aprobado!",
|
|
589
|
-
"state.in_review": "Tu pago est\xE1 en revisi\xF3n. Te avisamos por correo en m\xE1ximo 2 d\xEDas h\xE1biles. No vuelvas a pagar.",
|
|
590
|
-
"state.voucher": "Tu ficha de pago est\xE1 lista. El pedido se confirma cuando pagues.",
|
|
591
|
-
"state.challenge": "Tu banco necesita verificar el pago. Termina la verificaci\xF3n para continuar.",
|
|
592
|
-
"state.expired": "La ficha venci\xF3. Vuelve a armar tu carrito para pagar.",
|
|
593
|
-
"state.cancelled": "El pago se cancel\xF3. Puedes intentarlo de nuevo.",
|
|
594
|
-
"state.redirect": "Te llevamos a la p\xE1gina de pago\u2026",
|
|
595
|
-
"state.fallback": "No pudimos cargar el formulario seguro de tarjeta. Puedes pagar con tarjeta en el sitio del proveedor y regresar aqu\xED.",
|
|
596
|
-
"error.network": "No pudimos conectar. Revisa tu conexi\xF3n e intenta de nuevo; no se te cobrar\xE1 dos veces.",
|
|
597
|
-
"error.card_data": "Revisa los datos de tu tarjeta.",
|
|
598
|
-
"error.price_mismatch": "El total cambi\xF3. Revisa el nuevo total y vuelve a pagar.",
|
|
599
|
-
"error.payment_in_progress": "Ya hay un pago en proceso para este pedido. No vuelvas a pagar; revisa tu correo.",
|
|
600
|
-
"error.expired": "Tu apartado venci\xF3. Vuelve a armar tu carrito.",
|
|
601
|
-
"error.too_many_attempts": "Por seguridad no podemos intentar con m\xE1s tarjetas. Paga en efectivo o escr\xEDbenos.",
|
|
602
|
-
"error.generic": "No pudimos procesar tu pago. Intenta de nuevo.",
|
|
603
|
-
"action.retry": "Reintentar",
|
|
604
|
-
"action.try_again": "Intentar de nuevo",
|
|
605
|
-
"action.pay": "Pagar",
|
|
606
|
-
"action.cancel": "Cancelar",
|
|
607
|
-
"voucher.title": "Ficha de pago",
|
|
608
|
-
"voucher.point": "Punto de pago",
|
|
609
|
-
"voucher.reference": "Referencia",
|
|
610
|
-
"voucher.amount": "Monto exacto",
|
|
611
|
-
"voucher.expires": "Vence el {date}",
|
|
612
|
-
"voucher.clabe": "CLABE",
|
|
613
|
-
"voucher.barcode": "C\xF3digo de barras",
|
|
614
|
-
"voucher.open": "Ver o imprimir ficha",
|
|
615
|
-
"voucher.email": "Tambi\xE9n te la enviamos a tu correo.",
|
|
616
|
-
"form.label": "Datos de tu tarjeta",
|
|
617
|
-
"challenge.title": "Verificaci\xF3n de tu banco",
|
|
618
|
-
"challenge.escape": "Cancelar y volver al pago",
|
|
619
|
-
"challenge.escape_hint": "\xBFTarda demasiado? Puedes cerrar la verificaci\xF3n. Si ya la aprobaste en tu banco, el pago a\xFAn puede completarse: te confirmamos aqu\xED antes de dejarte pagar de nuevo.",
|
|
620
|
-
"challenge.left": "Cerraste la verificaci\xF3n. Estamos confirmando con tu banco si el pago se complet\xF3; no vuelvas a pagar todav\xEDa."
|
|
621
|
-
};
|
|
622
|
-
var EN = {
|
|
623
|
-
"decline.insufficient_funds": "Your card has insufficient funds. Try another card or pay in cash.",
|
|
624
|
-
"decline.invalid_cvc": "The security code is not correct. Check it and try again.",
|
|
625
|
-
"decline.invalid_expiry": "The expiry date is not correct.",
|
|
626
|
-
"decline.invalid_card_data": "Check your card details.",
|
|
627
|
-
"decline.call_issuer": "Your bank needs you to authorize this payment. Call the number on the back of your card and try again.",
|
|
628
|
-
"decline.card_disabled": "Your card is not active. Activate it with your bank or use another one.",
|
|
629
|
-
"decline.duplicate": "You already made the same payment a moment ago. Check your email before paying again.",
|
|
630
|
-
"decline.max_attempts": "You reached the attempt limit for this card. Use another card or pay in cash.",
|
|
631
|
-
"decline.authentication_failed": "Your bank could not verify the payment. Try again or use another card.",
|
|
632
|
-
"decline.declined": "Your bank declined the payment. Use another card or pay in cash.",
|
|
633
|
-
"state.loading": "Loading secure payment\u2026",
|
|
634
|
-
"state.processing": "Processing payment\u2026",
|
|
635
|
-
"state.approved": "Payment approved!",
|
|
636
|
-
"state.in_review": "Your payment is under review. We will email you within 2 business days. Do not pay again.",
|
|
637
|
-
"state.voucher": "Your payment voucher is ready. The order is confirmed once you pay.",
|
|
638
|
-
"state.challenge": "Your bank needs to verify the payment. Finish the verification to continue.",
|
|
639
|
-
"state.expired": "The voucher expired. Rebuild your cart to pay.",
|
|
640
|
-
"state.cancelled": "The payment was cancelled. You can try again.",
|
|
641
|
-
"state.redirect": "Taking you to the payment page\u2026",
|
|
642
|
-
"state.fallback": "We could not load the secure card form. You can pay by card on the provider site and come back here.",
|
|
643
|
-
"error.network": "We could not connect. Check your connection and try again; you will not be charged twice.",
|
|
644
|
-
"error.card_data": "Check your card details.",
|
|
645
|
-
"error.price_mismatch": "The total changed. Review the new total and pay again.",
|
|
646
|
-
"error.payment_in_progress": "A payment is already in progress for this order. Do not pay again; check your email.",
|
|
647
|
-
"error.expired": "Your reservation expired. Rebuild your cart.",
|
|
648
|
-
"error.too_many_attempts": "For security we cannot try more cards. Pay in cash or contact us.",
|
|
649
|
-
"error.generic": "We could not process your payment. Please try again.",
|
|
650
|
-
"action.retry": "Retry",
|
|
651
|
-
"action.try_again": "Try again",
|
|
652
|
-
"action.pay": "Pay",
|
|
653
|
-
"action.cancel": "Cancel",
|
|
654
|
-
"voucher.title": "Payment voucher",
|
|
655
|
-
"voucher.point": "Payment point",
|
|
656
|
-
"voucher.reference": "Reference",
|
|
657
|
-
"voucher.amount": "Exact amount",
|
|
658
|
-
"voucher.expires": "Expires on {date}",
|
|
659
|
-
"voucher.clabe": "CLABE",
|
|
660
|
-
"voucher.barcode": "Barcode",
|
|
661
|
-
"voucher.open": "View or print voucher",
|
|
662
|
-
"voucher.email": "We also emailed it to you.",
|
|
663
|
-
"form.label": "Your card details",
|
|
664
|
-
"challenge.title": "Your bank verification",
|
|
665
|
-
"challenge.escape": "Cancel and go back to payment",
|
|
666
|
-
"challenge.escape_hint": "Taking too long? You can close the verification. If you already approved it with your bank the payment may still go through: we confirm here before letting you pay again.",
|
|
667
|
-
"challenge.left": "You closed the verification. We are checking with your bank whether the payment went through; do not pay again yet."
|
|
668
|
-
};
|
|
669
|
-
var CATALOG = { es: ES, en: EN };
|
|
670
|
-
function paymentMessages(locale, overrides) {
|
|
671
|
-
const base = CATALOG[availabilityLocale(locale)];
|
|
672
|
-
if (!overrides) return base;
|
|
673
|
-
const out = { ...base };
|
|
674
|
-
for (const [k, v] of Object.entries(overrides)) if (typeof v === "string" && k in base) out[k] = v;
|
|
675
|
-
return out;
|
|
676
|
-
}
|
|
677
|
-
var DECLINE_CODES = /* @__PURE__ */ new Set([
|
|
678
|
-
"insufficient_funds",
|
|
679
|
-
"invalid_cvc",
|
|
680
|
-
"invalid_expiry",
|
|
681
|
-
"invalid_card_data",
|
|
682
|
-
"call_issuer",
|
|
683
|
-
"card_disabled",
|
|
684
|
-
"duplicate",
|
|
685
|
-
"max_attempts",
|
|
686
|
-
"authentication_failed",
|
|
687
|
-
"declined"
|
|
688
|
-
]);
|
|
689
|
-
function declineMessageKey(code) {
|
|
690
|
-
return `decline.${code && DECLINE_CODES.has(code) ? code : "declined"}`;
|
|
691
|
-
}
|
|
692
|
-
function declineMessage(code, locale, overrides) {
|
|
693
|
-
return paymentMessages(locale, overrides)[declineMessageKey(code)];
|
|
694
|
-
}
|
|
695
|
-
function safeHttpsUrl(value) {
|
|
696
|
-
if (typeof value !== "string" || value.length > 2048) return null;
|
|
697
|
-
try {
|
|
698
|
-
const u = new URL(value);
|
|
699
|
-
if (u.protocol !== "https:" || u.username || u.password) return null;
|
|
700
|
-
return u.toString();
|
|
701
|
-
} catch {
|
|
702
|
-
return null;
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
var NEXT_STEP = {
|
|
706
|
-
insufficient_funds: "use_other_card",
|
|
707
|
-
invalid_cvc: "fix_card_data",
|
|
708
|
-
invalid_expiry: "fix_card_data",
|
|
709
|
-
invalid_card_data: "fix_card_data",
|
|
710
|
-
call_issuer: "contact_issuer",
|
|
711
|
-
card_disabled: "use_other_card",
|
|
712
|
-
duplicate: "check_email",
|
|
713
|
-
max_attempts: "use_other_card",
|
|
714
|
-
authentication_failed: "retry",
|
|
715
|
-
declined: "use_other_card"
|
|
716
|
-
};
|
|
717
|
-
function voucherMoney(v) {
|
|
718
|
-
const a = v.amount;
|
|
719
|
-
if (a && typeof a === "object" && typeof a.amount === "string") return a;
|
|
720
|
-
const text = typeof a === "number" ? String(a) : typeof a === "string" ? a : "";
|
|
721
|
-
if (!text || !/^\d+(\.\d+)?$/.test(text) || !v.currency) return null;
|
|
722
|
-
return { amount: text.includes(".") ? text : `${text}.00`, currency_code: v.currency };
|
|
723
|
-
}
|
|
724
|
-
function paymentOutcome(result, locale, overrides) {
|
|
725
|
-
const m = paymentMessages(locale, overrides);
|
|
726
|
-
const p = result.payment;
|
|
727
|
-
const action = p.action ?? null;
|
|
728
|
-
const base = {
|
|
729
|
-
decline_code: null,
|
|
730
|
-
retryable: false,
|
|
731
|
-
redirect_url: null,
|
|
732
|
-
challenge: null,
|
|
733
|
-
voucher: null,
|
|
734
|
-
attempts_left: typeof result.attempts_left === "number" ? result.attempts_left : null,
|
|
735
|
-
next_step: p.next_step ?? null
|
|
736
|
-
};
|
|
737
|
-
const out = (kind, message, extra = {}) => ({ ...base, kind, message, ...extra });
|
|
738
|
-
if (p.status === "paid") return out("approved", m["state.approved"]);
|
|
739
|
-
if (p.status === "failed") {
|
|
740
|
-
const code = p.decline_code ?? "declined";
|
|
741
|
-
const known = DECLINE_CODES.has(code) ? code : "declined";
|
|
742
|
-
return out("rejected", m[declineMessageKey(code)], {
|
|
743
|
-
decline_code: known,
|
|
744
|
-
next_step: p.next_step ?? NEXT_STEP[known],
|
|
745
|
-
retryable: p.retryable !== false && base.attempts_left !== 0
|
|
746
|
-
});
|
|
747
|
-
}
|
|
748
|
-
if (p.status === "expired") return out("expired", m["state.expired"], { next_step: "rebuild_cart" });
|
|
749
|
-
if (p.status === "cancelled") return out("cancelled", m["state.cancelled"], { retryable: true, next_step: "rebuild_cart" });
|
|
750
|
-
if (action?.type === "redirect") {
|
|
751
|
-
const url = safeHttpsUrl(action.redirect_url);
|
|
752
|
-
if (url) return out("redirect", m["state.redirect"], { redirect_url: url });
|
|
753
|
-
}
|
|
754
|
-
if (p.status === "requires_action" || p.status === "pending") {
|
|
755
|
-
if (action?.type === "voucher" && action.voucher) {
|
|
756
|
-
const { amount: _a, currency: _c, voucher_url, ...rest } = action.voucher;
|
|
757
|
-
return out("voucher", m["state.voucher"], {
|
|
758
|
-
next_step: "pay_cash",
|
|
759
|
-
voucher: { ...rest, voucher_url: safeHttpsUrl(voucher_url), amount: voucherMoney(action.voucher) }
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
if (action?.type === "challenge" && action.challenge) {
|
|
763
|
-
return out("challenge", m["state.challenge"], {
|
|
764
|
-
challenge: { url: safeHttpsUrl(action.challenge.url), creq: typeof action.challenge.creq === "string" ? action.challenge.creq : null }
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
return out("in_review", m["state.in_review"]);
|
|
769
|
-
}
|
|
770
|
-
function paymentErrorView(err, locale, overrides) {
|
|
771
|
-
const m = paymentMessages(locale, overrides);
|
|
772
|
-
const e = err ?? {};
|
|
773
|
-
const status = typeof e.status === "number" ? e.status : 0;
|
|
774
|
-
const code = typeof e.code === "string" ? e.code : "";
|
|
775
|
-
if (code === "price_mismatch") {
|
|
776
|
-
return { kind: "price_mismatch", message: m["error.price_mismatch"], retrySameAttempt: false, canRetry: true };
|
|
777
|
-
}
|
|
778
|
-
if (status === 409 && code === "expired") return { kind: "expired", message: m["error.expired"], retrySameAttempt: false, canRetry: false };
|
|
779
|
-
if (status === 409 && code === "payment_in_progress") {
|
|
780
|
-
return { kind: "payment_in_progress", message: m["error.payment_in_progress"], retrySameAttempt: false, canRetry: false };
|
|
781
|
-
}
|
|
782
|
-
if (status === 409) return { kind: "generic", message: m["error.generic"], retrySameAttempt: false, canRetry: true };
|
|
783
|
-
if (status === 429 || code === "too_many_attempts") {
|
|
784
|
-
return { kind: "too_many_attempts", message: m["error.too_many_attempts"], retrySameAttempt: false, canRetry: false };
|
|
785
|
-
}
|
|
786
|
-
const declared = e.retryable;
|
|
787
|
-
if (status >= 500 && declared === false) return { kind: "generic", message: m["error.generic"], retrySameAttempt: false, canRetry: true };
|
|
788
|
-
if (status === 0 || status === 502 || status === 503 || status === 504 || code === "network" || code === "timeout" || status >= 500) {
|
|
789
|
-
return { kind: "network", message: m["error.network"], retrySameAttempt: true, canRetry: true };
|
|
790
|
-
}
|
|
791
|
-
return { kind: "generic", message: m["error.generic"], retrySameAttempt: false, canRetry: true };
|
|
792
|
-
}
|
|
793
|
-
function formatVoucherExpiry(expiresAt, locale, overrides) {
|
|
794
|
-
if (!expiresAt) return null;
|
|
795
|
-
const d = new Date(expiresAt);
|
|
796
|
-
if (Number.isNaN(d.getTime())) return null;
|
|
797
|
-
let date;
|
|
798
|
-
try {
|
|
799
|
-
date = new Intl.DateTimeFormat(locale ?? void 0, { dateStyle: "long", timeStyle: "short" }).format(d);
|
|
800
|
-
} catch {
|
|
801
|
-
date = d.toISOString();
|
|
802
|
-
}
|
|
803
|
-
return formatAvailabilityMessage(paymentMessages(locale, overrides)["voucher.expires"], { date });
|
|
804
|
-
}
|
|
805
|
-
function paymentIdempotencyKey(checkoutId, attempt) {
|
|
806
|
-
return `pay-${checkoutId}-${attempt}`;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
539
|
// src/promotions.ts
|
|
810
|
-
var
|
|
540
|
+
var ES = {
|
|
811
541
|
"discount.next": "A\xF1ade {remaining} para activar tu descuento autom\xE1tico",
|
|
812
542
|
"discount.next_upgrade": "A\xF1ade {remaining} para subir a {reward}",
|
|
813
543
|
"discount.applied": "\xA1Tienes {reward} de descuento!",
|
|
@@ -858,7 +588,7 @@ var ES2 = {
|
|
|
858
588
|
"note.error": "No se pudo guardar la nota. Intenta de nuevo.",
|
|
859
589
|
"note.counter": "{n} de {max} caracteres"
|
|
860
590
|
};
|
|
861
|
-
var
|
|
591
|
+
var EN = {
|
|
862
592
|
"discount.next": "Add {remaining} to unlock your automatic discount",
|
|
863
593
|
"discount.next_upgrade": "Add {remaining} to move up to {reward}",
|
|
864
594
|
"discount.applied": "You have {reward} off!",
|
|
@@ -909,9 +639,9 @@ var EN2 = {
|
|
|
909
639
|
"note.error": "The note could not be saved. Please try again.",
|
|
910
640
|
"note.counter": "{n} of {max} characters"
|
|
911
641
|
};
|
|
912
|
-
var
|
|
642
|
+
var CATALOG = { es: ES, en: EN };
|
|
913
643
|
function promotionMessages(locale, overrides) {
|
|
914
|
-
const base =
|
|
644
|
+
const base = CATALOG[availabilityLocale(locale)];
|
|
915
645
|
if (!overrides) return base;
|
|
916
646
|
const out = { ...base };
|
|
917
647
|
for (const [k, v] of Object.entries(overrides)) if (typeof v === "string" && k in base) out[k] = v;
|
|
@@ -1058,6 +788,33 @@ function hreflangLinks(markets, path, defaultMarket, protocol = "https") {
|
|
|
1058
788
|
return links;
|
|
1059
789
|
}
|
|
1060
790
|
|
|
791
|
+
// src/invoice-docs.ts
|
|
792
|
+
function groupInvoiceDocs(docs) {
|
|
793
|
+
const list = Array.isArray(docs) ? docs.filter((d) => !!d && typeof d === "object") : [];
|
|
794
|
+
const groups = list.filter((d) => d.kind !== "credit_note").map((invoice) => ({ invoice, creditNotes: [] }));
|
|
795
|
+
const orphans = [];
|
|
796
|
+
for (const d of list) {
|
|
797
|
+
if (d.kind !== "credit_note") continue;
|
|
798
|
+
const group = d.related_to ? groups.find((g) => g.invoice.id === d.related_to) : void 0;
|
|
799
|
+
if (group) group.creditNotes.push(d);
|
|
800
|
+
else orphans.push(d);
|
|
801
|
+
}
|
|
802
|
+
return { groups, orphans };
|
|
803
|
+
}
|
|
804
|
+
function invoiceFileBytes(file) {
|
|
805
|
+
const raw = typeof file.content_base64 === "string" ? file.content_base64.replace(/\s+/g, "") : "";
|
|
806
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(raw) || raw.length % 4 === 1) throw new TypeError("invoice file is not valid base64");
|
|
807
|
+
const bin = atob(raw);
|
|
808
|
+
const out = new Uint8Array(bin.length);
|
|
809
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
810
|
+
return out;
|
|
811
|
+
}
|
|
812
|
+
function safeInvoiceFilename(name, fallback = "factura") {
|
|
813
|
+
const base = typeof name === "string" ? name.split(/[\\/]/).pop() ?? "" : "";
|
|
814
|
+
const clean = base.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^\.+/, "").slice(0, 80);
|
|
815
|
+
return clean || fallback;
|
|
816
|
+
}
|
|
817
|
+
|
|
1061
818
|
// src/delivery.ts
|
|
1062
819
|
function parseDelivery(value) {
|
|
1063
820
|
const raw = (value ?? "").trim();
|
|
@@ -1084,6 +841,6 @@ function deliveryNotices(delivery) {
|
|
|
1084
841
|
};
|
|
1085
842
|
}
|
|
1086
843
|
|
|
1087
|
-
export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, PAYMENT_CHOICE_REFUSED_FIELD,
|
|
844
|
+
export { CLIENT_IP_HEADER, COUNTRY_HEADERS, MISSING_WEIGHT, NOTE_MAX_LENGTH, PAYMENT_CHOICE_REFUSED_FIELD, appendParams, clampPercent, classifyPaymentError, createStorefrontClient, deliveryInput, deliveryNotices, diagnose, formatMoney, generateIdempotencyKey, groupInvoiceDocs, hreflangLinks, invoiceFileBytes, isTokenPublishable, maskToken, negotiateLocale, normalizeClientIp, normalizeNote, opsSaysNotRetryable, parseDelivery, parseMoney, parseProductFilters, preferredLanguages, productListQuery, promoProgressView, promotionMessages, repairPath, rewardLabel, safeInvoiceFilename, storefrontDomainHeader, suggestMarket, toMoney, visitorCountry };
|
|
1088
845
|
//# sourceMappingURL=index.js.map
|
|
1089
846
|
//# sourceMappingURL=index.js.map
|