@asteby/storefront-react 0.26.1 → 0.28.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/README.md +7 -2
- package/dist/account-server.cjs +533 -83
- package/dist/account-server.cjs.map +1 -1
- package/dist/account-server.d.cts +13 -2
- package/dist/account-server.d.ts +13 -2
- package/dist/account-server.js +23 -6
- package/dist/account-server.js.map +1 -1
- package/dist/account.cjs +572 -96
- package/dist/account.cjs.map +1 -1
- package/dist/account.d.cts +82 -45
- package/dist/account.d.ts +82 -45
- package/dist/account.js +53 -14
- package/dist/account.js.map +1 -1
- package/dist/checkout.cjs +114 -38
- package/dist/checkout.cjs.map +1 -1
- package/dist/checkout.d.cts +24 -1
- package/dist/checkout.d.ts +24 -1
- package/dist/checkout.js +114 -38
- package/dist/checkout.js.map +1 -1
- package/dist/{chunk-MNLROALF.js → chunk-4DZW3R33.js} +19 -2
- package/dist/chunk-4DZW3R33.js.map +1 -0
- package/dist/chunk-BXKV2KWZ.js +291 -0
- package/dist/chunk-BXKV2KWZ.js.map +1 -0
- package/dist/chunk-LIUEQENV.js +156 -0
- package/dist/chunk-LIUEQENV.js.map +1 -0
- package/dist/payments-server.cjs +17 -0
- package/dist/payments-server.cjs.map +1 -1
- package/dist/payments-server.js +2 -2
- package/dist/payments.cjs +17 -0
- package/dist/payments.cjs.map +1 -1
- package/dist/payments.js +2 -2
- package/dist/voucher-document-FWH4DQ5N.js +72 -0
- package/dist/voucher-document-FWH4DQ5N.js.map +1 -0
- package/dist/voucher-pdf-LQC333AB.js +213 -0
- package/dist/voucher-pdf-LQC333AB.js.map +1 -0
- package/package.json +2 -2
- package/dist/chunk-MNLROALF.js.map +0 -1
- package/dist/chunk-TXEYBDFG.js +0 -182
- package/dist/chunk-TXEYBDFG.js.map +0 -1
- package/dist/voucher-document-SFWJCLTN.js +0 -124
- package/dist/voucher-document-SFWJCLTN.js.map +0 -1
package/dist/payments.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isSafeCssValue } from './chunk-672OTUM2.js';
|
|
2
2
|
import { useModalDialog } from './chunk-ZBH7JYU4.js';
|
|
3
3
|
import { findBrand, BrandMark } from './chunk-JNUJGPJC.js';
|
|
4
|
-
import { paymentRecoveryMessages } from './chunk-
|
|
5
|
-
export { buildPayChoices, cashProviderData, checkoutToAttempt, choiceValue, parseChoice, payErrorResponse, paymentCsp, paymentCspHeaderName, paymentCspHeaders, paymentCspMode, paymentNonce, paymentNonceFromHeaders, paymentRecoveryMessages, safeHttpStatus, voucherRows } from './chunk-
|
|
4
|
+
import { paymentRecoveryMessages } from './chunk-4DZW3R33.js';
|
|
5
|
+
export { buildPayChoices, cashProviderData, checkoutToAttempt, choiceValue, parseChoice, payErrorResponse, paymentCsp, paymentCspHeaderName, paymentCspHeaders, paymentCspMode, paymentNonce, paymentNonceFromHeaders, paymentRecoveryMessages, safeHttpStatus, voucherRows } from './chunk-4DZW3R33.js';
|
|
6
6
|
import { useResolvedLocale } from './chunk-T52H5HL3.js';
|
|
7
7
|
import './chunk-DQBL2DFJ.js';
|
|
8
8
|
import { forwardRef, useImperativeHandle, useRef, useEffect, useMemo, useId, useState, useCallback, useSyncExternalStore } from 'react';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { docText, methodName, formatDate, voucherFields, voucherSteps, formatMoney } from './chunk-LIUEQENV.js';
|
|
2
|
+
import { barcodeGeometry } from './chunk-BXKV2KWZ.js';
|
|
3
|
+
|
|
4
|
+
// src/account/voucher-document.ts
|
|
5
|
+
function esc(s) {
|
|
6
|
+
return s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
7
|
+
}
|
|
8
|
+
var CSS = `
|
|
9
|
+
@page { size: A4; margin: 18mm; }
|
|
10
|
+
* { box-sizing: border-box; }
|
|
11
|
+
body { margin: 0; font: 14px/1.5 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; color: #111; background: #fff; }
|
|
12
|
+
main { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }
|
|
13
|
+
h1 { font-size: 22px; margin: 0; }
|
|
14
|
+
.muted { color: #555; }
|
|
15
|
+
.head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }
|
|
16
|
+
.amount { margin: 0; font-size: 28px; font-weight: 700; text-align: right; }
|
|
17
|
+
.box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }
|
|
18
|
+
.label { margin: 0; font-weight: 400; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }
|
|
19
|
+
.value { margin: 0; font: 700 22px/1.3 ui-monospace, "SF Mono", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }
|
|
20
|
+
.bar { text-align: center; }
|
|
21
|
+
.bar svg { max-width: 100%; height: auto; }
|
|
22
|
+
.note { margin-top: 18px; font-size: 12px; }
|
|
23
|
+
.pre { white-space: pre-line; }
|
|
24
|
+
.steps-title { font-size: 16px; margin: 18px 0 0; }
|
|
25
|
+
.steps { margin: 6px 0 0; padding-left: 20px; }
|
|
26
|
+
.bar { margin: 18px 0 0; }
|
|
27
|
+
.actions { margin-top: 24px; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
|
|
28
|
+
.btn { display: inline-block; font: inherit; padding: 10px 18px; border: 2px solid #111; background: #111; color: #fff; cursor: pointer; text-decoration: none; }
|
|
29
|
+
.btn.alt { background: #fff; color: #111; }
|
|
30
|
+
.btn:focus-visible { outline: 3px solid #1a56db; outline-offset: 2px; }
|
|
31
|
+
@media print { .actions { display: none; } main { padding: 0; } }
|
|
32
|
+
`;
|
|
33
|
+
function barcodeSvg(value, format, label) {
|
|
34
|
+
const g = barcodeGeometry(value, { ...format ? { format } : {} });
|
|
35
|
+
if (!g) return null;
|
|
36
|
+
const rects = g.rects.map((r) => `<rect x="${r.x}" y="0" width="${r.w}" height="${g.height}"/>`).join("");
|
|
37
|
+
return `<svg viewBox="0 0 ${g.width} ${g.height}" width="${g.width}" height="${g.height}" role="img" aria-label="${esc(label)} ${esc(value)}" shape-rendering="crispEdges" fill="#000">${rects}</svg>`;
|
|
38
|
+
}
|
|
39
|
+
function renderVoucherDocument(v, opts = {}) {
|
|
40
|
+
const locale = opts.locale ?? "es-MX";
|
|
41
|
+
const t = docText(locale);
|
|
42
|
+
const shop = opts.shopName || "";
|
|
43
|
+
const method = methodName(v, t);
|
|
44
|
+
const code = v.barcode;
|
|
45
|
+
const svg = code ? barcodeSvg(code, v.barcode_format, t.barcode) : null;
|
|
46
|
+
const expires = formatDate(v.expires_at, locale, opts.timeZone);
|
|
47
|
+
const fields = voucherFields(v, t);
|
|
48
|
+
const steps = voucherSteps(v, t);
|
|
49
|
+
const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ""].filter(Boolean).map(esc).join(" \xB7 ");
|
|
50
|
+
const actions = opts.printButton || opts.pdfHref;
|
|
51
|
+
return `<!doctype html>
|
|
52
|
+
<html lang="${esc(locale)}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
53
|
+
<meta name="robots" content="noindex"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ""}</title><style>${CSS}</style></head>
|
|
54
|
+
<body><main aria-labelledby="t">
|
|
55
|
+
<header class="head"><div><h1 id="t">${esc(t.title)}</h1><p class="muted" data-voucher-method="${esc(v.method ?? "")}">${subtitle}</p></div>
|
|
56
|
+
${v.amount ? `<div><p class="label" style="text-align:right">${esc(t.total)}</p><p class="amount">${esc(formatMoney(v.amount, locale))}</p></div>` : ""}</header>
|
|
57
|
+
${fields.map((f) => `<section class="box" data-field="${f.key}"><h2 class="label">${esc(f.label)}</h2><p class="value">${esc(f.value)}</p></section>`).join("")}
|
|
58
|
+
${svg ? `<figure class="bar">${svg}<figcaption class="muted" style="font-family:ui-monospace,monospace">${esc(code)}</figcaption></figure>` : ""}
|
|
59
|
+
${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires.replace(/\.$/, ""))}. ${esc(t.expiresNote)}</p>` : ""}
|
|
60
|
+
<h2 class="steps-title">${esc(t.stepsTitle)}</h2>
|
|
61
|
+
<ol class="steps">${steps.map((s) => `<li>${esc(s)}</li>`).join("")}</ol>
|
|
62
|
+
${v.instructions ? `<p class="note pre muted">${esc(v.instructions)}</p>` : ""}
|
|
63
|
+
<p class="note muted">${esc(t.footer)}</p>
|
|
64
|
+
${actions ? `<div class="actions" role="group" aria-label="${esc(t.title)}">${opts.pdfHref ? `<a class="btn" href="${esc(opts.pdfHref)}" download="ficha-de-pago.pdf" data-voucher-pdf>${esc(t.downloadPdf)}</a>` : ""}${opts.printButton ? `<button type="button" class="btn alt" id="print" hidden>${esc(t.print)}</button><noscript><p class="note muted">${esc(t.noScript)}</p></noscript>` : ""}</div>` : ""}
|
|
65
|
+
</main>
|
|
66
|
+
${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce="${esc(opts.nonce)}"` : ""}>(function(){var b=document.getElementById("print");if(b){b.hidden=false;b.addEventListener("click",function(){window.print()})}${opts.autoPrint ? 'window.addEventListener("load",function(){setTimeout(function(){window.print()},300)});' : ""}})();</script>` : ""}
|
|
67
|
+
</body></html>`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { esc, renderVoucherDocument };
|
|
71
|
+
//# sourceMappingURL=voucher-document-FWH4DQ5N.js.map
|
|
72
|
+
//# sourceMappingURL=voucher-document-FWH4DQ5N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/account/voucher-document.ts"],"names":[],"mappings":";;;;AAQO,SAAS,IAAI,CAAA,EAAmB;AACrC,EAAA,OAAO,EAAE,OAAA,CAAQ,UAAA,EAAY,CAAC,CAAA,KAAA,CAAO,EAAE,KAAK,OAAA,EAAS,GAAA,EAAK,MAAA,EAAQ,GAAA,EAAK,QAAQ,GAAA,EAAK,QAAA,EAAU,KAAK,OAAA,EAAQ,EAAG,CAAC,CAAW,CAAA;AAC5H;AAmBA,IAAM,GAAA,GAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AA0BZ,SAAS,UAAA,CAAW,KAAA,EAAe,MAAA,EAAuC,KAAA,EAA8B;AACtG,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,KAAA,EAAO,EAAE,GAAI,MAAA,GAAS,EAAE,MAAA,EAAO,GAAI,EAAC,EAAI,CAAA;AAClE,EAAA,IAAI,CAAC,GAAG,OAAO,IAAA;AACf,EAAA,MAAM,QAAQ,CAAA,CAAE,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,YAAY,CAAA,CAAE,CAAC,CAAA,eAAA,EAAkB,CAAA,CAAE,CAAC,CAAA,UAAA,EAAa,CAAA,CAAE,MAAM,CAAA,GAAA,CAAK,CAAA,CAAE,KAAK,EAAE,CAAA;AACxG,EAAA,OAAO,CAAA,kBAAA,EAAqB,EAAE,KAAK,CAAA,CAAA,EAAI,EAAE,MAAM,CAAA,SAAA,EAAY,EAAE,KAAK,CAAA,UAAA,EAAa,EAAE,MAAM,CAAA,yBAAA,EAA4B,IAAI,KAAK,CAAC,IAAI,GAAA,CAAI,KAAK,CAAC,CAAA,2CAAA,EAA8C,KAAK,CAAA,MAAA,CAAA;AAChM;AAGO,SAAS,qBAAA,CAAsB,CAAA,EAAgB,IAAA,GAA+B,EAAC,EAAW;AAC/F,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,OAAA;AAC9B,EAAA,MAAM,CAAA,GAAI,QAAQ,MAAM,CAAA;AACxB,EAAA,MAAM,IAAA,GAAO,KAAK,QAAA,IAAY,EAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,CAAA,EAAG,CAAC,CAAA;AAC9B,EAAA,MAAM,OAAO,CAAA,CAAE,OAAA;AACf,EAAA,MAAM,GAAA,GAAM,OAAO,UAAA,CAAW,IAAA,EAAM,EAAE,cAAA,EAAgB,CAAA,CAAE,OAAO,CAAA,GAAI,IAAA;AACnE,EAAA,MAAM,UAAU,UAAA,CAAW,CAAA,CAAE,UAAA,EAAY,MAAA,EAAQ,KAAK,QAAQ,CAAA;AAC9D,EAAA,MAAM,MAAA,GAAS,aAAA,CAAc,CAAA,EAAG,CAAC,CAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,YAAA,CAAa,CAAA,EAAG,CAAC,CAAA;AAC/B,EAAA,MAAM,QAAA,GAAW,CAAC,IAAA,EAAM,MAAA,EAAQ,KAAK,MAAA,GAAS,CAAA,EAAG,CAAA,CAAE,KAAK,CAAA,CAAA,EAAI,IAAA,CAAK,MAAM,CAAA,CAAA,GAAK,EAAE,EAAE,MAAA,CAAO,OAAO,EAAE,GAAA,CAAI,GAAG,CAAA,CAAE,IAAA,CAAK,QAAK,CAAA;AACnH,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,WAAA,IAAe,IAAA,CAAK,OAAA;AACzC,EAAA,OAAO,CAAA;AAAA,YAAA,EACK,GAAA,CAAI,MAAM,CAAC,CAAA;AAAA,6CAAA,EACsB,GAAA,CAAI,CAAA,CAAE,KAAK,CAAC,CAAA,EAAG,IAAA,GAAO,CAAA,GAAA,EAAM,GAAA,CAAI,IAAI,CAAC,CAAA,CAAA,GAAK,EAAE,kBAAkB,GAAG,CAAA;AAAA;AAAA,qCAAA,EAEzE,GAAA,CAAI,CAAA,CAAE,KAAK,CAAC,CAAA,2CAAA,EAA8C,GAAA,CAAI,CAAA,CAAE,MAAA,IAAU,EAAE,CAAC,CAAA,EAAA,EAAK,QAAQ,CAAA;AAAA,EAC/H,EAAE,MAAA,GAAS,CAAA,+CAAA,EAAkD,GAAA,CAAI,CAAA,CAAE,KAAK,CAAC,CAAA,sBAAA,EAAyB,GAAA,CAAI,WAAA,CAAY,EAAE,MAAA,EAAQ,MAAM,CAAC,CAAC,eAAe,EAAE,CAAA;AAAA,EACrJ,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,oCAAoC,CAAA,CAAE,GAAG,uBAAuB,GAAA,CAAI,CAAA,CAAE,KAAK,CAAC,CAAA,sBAAA,EAAyB,IAAI,CAAA,CAAE,KAAK,CAAC,CAAA,cAAA,CAAgB,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC;AAAA,EAC7J,GAAA,GAAM,uBAAuB,GAAG,CAAA,qEAAA,EAAwE,IAAI,IAAc,CAAC,2BAA2B,EAAE;AAAA,EACxJ,OAAA,GAAU,cAAc,GAAA,CAAI,CAAA,CAAE,OAAO,CAAC,CAAA,WAAA,EAAc,IAAI,OAAA,CAAQ,OAAA,CAAQ,OAAO,EAAE,CAAC,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,EAAE,WAAW,CAAC,SAAS,EAAE;AAAA,wBAAA,EAC7F,GAAA,CAAI,CAAA,CAAE,UAAU,CAAC,CAAA;AAAA,kBAAA,EACvB,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,IAAA,EAAO,GAAA,CAAI,CAAC,CAAC,CAAA,KAAA,CAAO,CAAA,CAAE,IAAA,CAAK,EAAE,CAAC,CAAA;AAAA,EACjE,CAAA,CAAE,eAAe,CAAA,0BAAA,EAA6B,GAAA,CAAI,EAAE,YAAY,CAAC,SAAS,EAAE;AAAA,sBAAA,EACtD,GAAA,CAAI,CAAA,CAAE,MAAM,CAAC,CAAA;AAAA,EAEnC,UACI,CAAA,8CAAA,EAAiD,GAAA,CAAI,CAAA,CAAE,KAAK,CAAC,CAAA,EAAA,EAAK,IAAA,CAAK,OAAA,GAAU,CAAA,qBAAA,EAAwB,IAAI,IAAA,CAAK,OAAO,CAAC,CAAA,gDAAA,EAAmD,IAAI,CAAA,CAAE,WAAW,CAAC,CAAA,IAAA,CAAA,GAAS,EAAE,CAAA,EAAG,IAAA,CAAK,WAAA,GAAc,CAAA,wDAAA,EAA2D,IAAI,CAAA,CAAE,KAAK,CAAC,CAAA,yCAAA,EAA4C,IAAI,CAAA,CAAE,QAAQ,CAAC,CAAA,eAAA,CAAA,GAAoB,EAAE,WACxX,EACN;AAAA;AAAA,EAEE,IAAA,CAAK,eAAe,IAAA,CAAK,SAAA,GAAY,UAAU,IAAA,CAAK,KAAA,GAAQ,WAAW,GAAA,CAAI,IAAA,CAAK,KAAK,CAAC,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA,gIAAA,EAAmI,IAAA,CAAK,YAAY,yFAAA,GAA4F,EAAE,mBAAmB,EAAE;AAAA,cAAA,CAAA;AAEvW","file":"voucher-document-FWH4DQ5N.js","sourcesContent":["/**\n * Printable voucher (A4 HTML) that does not depend on any payment gateway: built only from the voucher data OPS keeps.\n * Loaded on demand (the buyer taps print/download) or by `pendingVoucherResponse` on the server; plain text, no React.\n * Everything external passes through `esc` before it enters the HTML.\n */\nimport { barcodeGeometry, type VoucherView } from './voucher.js'\nimport { docText, formatDate, formatMoney, methodName, voucherFields, voucherSteps } from './voucher-text.js'\n\nexport function esc(s: string): string {\n return s.replace(/[&<>\"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[c] as string)\n}\n\nexport type VoucherDocumentOptions = {\n shopName?: string\n /** Order number, if there is one yet. */\n number?: string | null\n locale?: string\n /** IANA zone the expiry is printed in (default: the runtime's). */\n timeZone?: string\n /** Print button on screen (hidden when printing). Needs JS; without it the page says to use the browser's print. */\n printButton?: boolean\n /** Link of the real PDF of this voucher (a plain `<a download>`, so it works without JS). */\n pdfHref?: string\n /** Opens the print dialog on load. */\n autoPrint?: boolean\n /** `<script>` nonce when the one serving the voucher sends a CSP with `script-src 'nonce-…'`. */\n nonce?: string\n}\n\nconst CSS = `\n@page { size: A4; margin: 18mm; }\n* { box-sizing: border-box; }\nbody { margin: 0; font: 14px/1.5 system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif; color: #111; background: #fff; }\nmain { max-width: 174mm; margin: 0 auto; padding: 24px 16px; }\nh1 { font-size: 22px; margin: 0; }\n.muted { color: #555; }\n.head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; border-bottom: 3px solid #111; padding-bottom: 12px; }\n.amount { margin: 0; font-size: 28px; font-weight: 700; text-align: right; }\n.box { border: 1px solid #111; padding: 14px 16px; margin-top: 18px; }\n.label { margin: 0; font-weight: 400; font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: #555; }\n.value { margin: 0; font: 700 22px/1.3 ui-monospace, \"SF Mono\", Menlo, Consolas, monospace; word-break: break-all; letter-spacing: .04em; }\n.bar { text-align: center; }\n.bar svg { max-width: 100%; height: auto; }\n.note { margin-top: 18px; font-size: 12px; }\n.pre { white-space: pre-line; }\n.steps-title { font-size: 16px; margin: 18px 0 0; }\n.steps { margin: 6px 0 0; padding-left: 20px; }\n.bar { margin: 18px 0 0; }\n.actions { margin-top: 24px; display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }\n.btn { display: inline-block; font: inherit; padding: 10px 18px; border: 2px solid #111; background: #111; color: #fff; cursor: pointer; text-decoration: none; }\n.btn.alt { background: #fff; color: #111; }\n.btn:focus-visible { outline: 3px solid #1a56db; outline-offset: 2px; }\n@media print { .actions { display: none; } main { padding: 0; } }\n`\n\nfunction barcodeSvg(value: string, format: VoucherView['barcode_format'], label: string): string | null {\n const g = barcodeGeometry(value, { ...(format ? { format } : {}) })\n if (!g) return null\n const rects = g.rects.map((r) => `<rect x=\"${r.x}\" y=\"0\" width=\"${r.w}\" height=\"${g.height}\"/>`).join('')\n return `<svg viewBox=\"0 0 ${g.width} ${g.height}\" width=\"${g.width}\" height=\"${g.height}\" role=\"img\" aria-label=\"${esc(label)} ${esc(value)}\" shape-rendering=\"crispEdges\" fill=\"#000\">${rects}</svg>`\n}\n\n/** Complete HTML document of the voucher. Missing data is simply not drawn. */\nexport function renderVoucherDocument(v: VoucherView, opts: VoucherDocumentOptions = {}): string {\n const locale = opts.locale ?? 'es-MX'\n const t = docText(locale)\n const shop = opts.shopName || ''\n const method = methodName(v, t)\n const code = v.barcode\n const svg = code ? barcodeSvg(code, v.barcode_format, t.barcode) : null\n const expires = formatDate(v.expires_at, locale, opts.timeZone)\n const fields = voucherFields(v, t)\n const steps = voucherSteps(v, t)\n const subtitle = [shop, method, opts.number ? `${t.order} ${opts.number}` : ''].filter(Boolean).map(esc).join(' · ')\n const actions = opts.printButton || opts.pdfHref\n return `<!doctype html>\n<html lang=\"${esc(locale)}\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<meta name=\"robots\" content=\"noindex\"><title>${esc(t.title)}${shop ? ` - ${esc(shop)}` : ''}</title><style>${CSS}</style></head>\n<body><main aria-labelledby=\"t\">\n<header class=\"head\"><div><h1 id=\"t\">${esc(t.title)}</h1><p class=\"muted\" data-voucher-method=\"${esc(v.method ?? '')}\">${subtitle}</p></div>\n${v.amount ? `<div><p class=\"label\" style=\"text-align:right\">${esc(t.total)}</p><p class=\"amount\">${esc(formatMoney(v.amount, locale))}</p></div>` : ''}</header>\n${fields.map((f) => `<section class=\"box\" data-field=\"${f.key}\"><h2 class=\"label\">${esc(f.label)}</h2><p class=\"value\">${esc(f.value)}</p></section>`).join('')}\n${svg ? `<figure class=\"bar\">${svg}<figcaption class=\"muted\" style=\"font-family:ui-monospace,monospace\">${esc(code as string)}</figcaption></figure>` : ''}\n${expires ? `<p><strong>${esc(t.expires)}:</strong> ${esc(expires.replace(/\\.$/, ''))}. ${esc(t.expiresNote)}</p>` : ''}\n<h2 class=\"steps-title\">${esc(t.stepsTitle)}</h2>\n<ol class=\"steps\">${steps.map((s) => `<li>${esc(s)}</li>`).join('')}</ol>\n${v.instructions ? `<p class=\"note pre muted\">${esc(v.instructions)}</p>` : ''}\n<p class=\"note muted\">${esc(t.footer)}</p>\n${\n actions\n ? `<div class=\"actions\" role=\"group\" aria-label=\"${esc(t.title)}\">${opts.pdfHref ? `<a class=\"btn\" href=\"${esc(opts.pdfHref)}\" download=\"ficha-de-pago.pdf\" data-voucher-pdf>${esc(t.downloadPdf)}</a>` : ''}${opts.printButton ? `<button type=\"button\" class=\"btn alt\" id=\"print\" hidden>${esc(t.print)}</button><noscript><p class=\"note muted\">${esc(t.noScript)}</p></noscript>` : ''}</div>`\n : ''\n}\n</main>\n${opts.printButton || opts.autoPrint ? `<script${opts.nonce ? ` nonce=\"${esc(opts.nonce)}\"` : ''}>(function(){var b=document.getElementById(\"print\");if(b){b.hidden=false;b.addEventListener(\"click\",function(){window.print()})}${opts.autoPrint ? 'window.addEventListener(\"load\",function(){setTimeout(function(){window.print()},300)});' : ''}})();</script>` : ''}\n</body></html>`\n}\n"]}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { docText, formatMoney, methodName, voucherFields, formatDate, voucherSteps } from './chunk-LIUEQENV.js';
|
|
2
|
+
import { barcodeGeometry } from './chunk-BXKV2KWZ.js';
|
|
3
|
+
|
|
4
|
+
// src/account/voucher-pdf.ts
|
|
5
|
+
var MAX_VOUCHER_PDF_BYTES = 256 * 1024;
|
|
6
|
+
var MAX_PAGES = 3;
|
|
7
|
+
var HELV = [278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584];
|
|
8
|
+
var HELV_B = [278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584];
|
|
9
|
+
var FONT_NAMES = { F1: "Helvetica", F2: "Helvetica-Bold", F3: "Courier-Bold", F4: "Courier" };
|
|
10
|
+
var CP1252 = { 8364: 128, 8216: 145, 8217: 146, 8220: 147, 8221: 148, 8226: 149, 8211: 150, 8212: 151 };
|
|
11
|
+
function toBytes(s) {
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const ch of s) {
|
|
14
|
+
const c = ch.codePointAt(0);
|
|
15
|
+
if (c < 32 || c === 127) out.push(32);
|
|
16
|
+
else if (c < 127 || c >= 160 && c <= 255) out.push(c);
|
|
17
|
+
else out.push(CP1252[c] ?? 63);
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
function pdfString(s) {
|
|
22
|
+
let o = "(";
|
|
23
|
+
for (const b of toBytes(s)) o += b >= 32 && b < 127 && b !== 40 && b !== 41 && b !== 92 ? String.fromCharCode(b) : `\\${b.toString(8).padStart(3, "0")}`;
|
|
24
|
+
return o + ")";
|
|
25
|
+
}
|
|
26
|
+
function charWidth(font, ch) {
|
|
27
|
+
if (font === "F3" || font === "F4") return 600;
|
|
28
|
+
const c = ch.codePointAt(0);
|
|
29
|
+
const table = font === "F2" ? HELV_B : HELV;
|
|
30
|
+
if (c >= 32 && c < 127) return table[c - 32];
|
|
31
|
+
const base = ch.normalize("NFD")[0].codePointAt(0);
|
|
32
|
+
return base >= 32 && base < 127 ? table[base - 32] : 556;
|
|
33
|
+
}
|
|
34
|
+
var textWidth = (font, size, s) => [...s].reduce((w, ch) => w + charWidth(font, ch), 0) * size / 1e3;
|
|
35
|
+
function wrap(font, size, text, max) {
|
|
36
|
+
const lines = [];
|
|
37
|
+
for (const para of text.split(/\r?\n/)) {
|
|
38
|
+
let line = "";
|
|
39
|
+
for (const word of para.split(/\s+/).filter(Boolean)) {
|
|
40
|
+
let w = word;
|
|
41
|
+
while (textWidth(font, size, w) > max) {
|
|
42
|
+
let n2 = 1;
|
|
43
|
+
while (n2 < w.length && textWidth(font, size, w.slice(0, n2 + 1)) <= max) n2++;
|
|
44
|
+
if (line) lines.push(line), line = "";
|
|
45
|
+
lines.push(w.slice(0, n2));
|
|
46
|
+
w = w.slice(n2);
|
|
47
|
+
}
|
|
48
|
+
const next = line ? `${line} ${w}` : w;
|
|
49
|
+
if (line && textWidth(font, size, next) > max) lines.push(line), line = w;
|
|
50
|
+
else line = next;
|
|
51
|
+
}
|
|
52
|
+
lines.push(line);
|
|
53
|
+
}
|
|
54
|
+
return lines;
|
|
55
|
+
}
|
|
56
|
+
var n = (x) => String(Math.round(x * 100) / 100);
|
|
57
|
+
function renderVoucherPdf(v, opts = {}) {
|
|
58
|
+
const locale = opts.locale ?? "es-MX";
|
|
59
|
+
const t = docText(locale);
|
|
60
|
+
const [W, H] = opts.paper === "letter" ? [612, 792] : [595.28, 841.89];
|
|
61
|
+
const M = 54;
|
|
62
|
+
const right = W - M;
|
|
63
|
+
const inner = right - M;
|
|
64
|
+
const pages = [];
|
|
65
|
+
let ops = "";
|
|
66
|
+
let y = H - M;
|
|
67
|
+
const newPage = () => {
|
|
68
|
+
if (pages.length >= MAX_PAGES) return false;
|
|
69
|
+
if (ops) pages.push(ops);
|
|
70
|
+
ops = "";
|
|
71
|
+
y = H - M;
|
|
72
|
+
return true;
|
|
73
|
+
};
|
|
74
|
+
const text = (font, size, x, s, gray = 0) => {
|
|
75
|
+
ops += `BT ${n(gray)} g /${font} ${size} Tf ${n(x)} ${n(y)} Td ${pdfString(s)} Tj ET
|
|
76
|
+
`;
|
|
77
|
+
};
|
|
78
|
+
const ensure = (h) => {
|
|
79
|
+
if (y - h < M) newPage();
|
|
80
|
+
};
|
|
81
|
+
const paragraph = (font, size, s, opt = {}) => {
|
|
82
|
+
const lead = opt.lead ?? size * 1.4;
|
|
83
|
+
for (const line of wrap(font, size, s, opt.width ?? inner)) {
|
|
84
|
+
ensure(lead);
|
|
85
|
+
y -= lead;
|
|
86
|
+
if (line) text(font, size, opt.x ?? M, line, opt.gray ?? 0);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const amount = formatMoney(v.amount, locale);
|
|
90
|
+
const top = y;
|
|
91
|
+
y -= 20;
|
|
92
|
+
text("F2", 20, M, t.title);
|
|
93
|
+
const subtitle = [opts.shopName, methodName(v, t), opts.number ? `${t.order} ${opts.number}` : ""].filter(Boolean).join(" \xB7 ");
|
|
94
|
+
if (subtitle) {
|
|
95
|
+
y -= 15;
|
|
96
|
+
paragraph("F1", 10, subtitle, { width: amount ? inner * 0.6 : inner, gray: 0.33, lead: 12 });
|
|
97
|
+
}
|
|
98
|
+
const afterTitle = y;
|
|
99
|
+
if (amount) {
|
|
100
|
+
y = top - 10;
|
|
101
|
+
const label = t.total.toUpperCase();
|
|
102
|
+
text("F1", 8, right - textWidth("F1", 8, label), label, 0.33);
|
|
103
|
+
y -= 22;
|
|
104
|
+
text("F2", 22, right - textWidth("F2", 22, amount), amount);
|
|
105
|
+
}
|
|
106
|
+
y = Math.min(afterTitle, y) - 10;
|
|
107
|
+
ops += `0 g 2 w ${n(M)} ${n(y)} m ${n(right)} ${n(y)} l S
|
|
108
|
+
`;
|
|
109
|
+
y -= 8;
|
|
110
|
+
for (const f of voucherFields(v, t)) {
|
|
111
|
+
const size = f.value.length > 36 ? 12 : 16;
|
|
112
|
+
const lines = wrap("F3", size, f.value, inner - 24);
|
|
113
|
+
const h = 14 + 12 + lines.length * size * 1.3 + 8;
|
|
114
|
+
ensure(h + 12);
|
|
115
|
+
y -= 12;
|
|
116
|
+
ops += `0 G 0.8 w ${n(M)} ${n(y - h)} ${n(inner)} ${n(h)} re S
|
|
117
|
+
`;
|
|
118
|
+
const boxTop = y;
|
|
119
|
+
y -= 16;
|
|
120
|
+
text("F1", 8, M + 12, f.label.toUpperCase(), 0.33);
|
|
121
|
+
y -= 4;
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
y -= size * 1.3;
|
|
124
|
+
text("F3", size, M + 12, line);
|
|
125
|
+
}
|
|
126
|
+
y = boxTop - h;
|
|
127
|
+
}
|
|
128
|
+
const g = v.barcode ? barcodeGeometry(v.barcode, { ...v.barcode_format ? { format: v.barcode_format } : {}, height: 60 }) : null;
|
|
129
|
+
if (g && v.barcode) {
|
|
130
|
+
const scale = Math.min(1, inner / g.width) * 0.75;
|
|
131
|
+
const bw = g.width * scale;
|
|
132
|
+
const bh = 60;
|
|
133
|
+
ensure(bh + 40);
|
|
134
|
+
y -= 18;
|
|
135
|
+
ops += `0 g
|
|
136
|
+
`;
|
|
137
|
+
const x0 = M + (inner - bw) / 2;
|
|
138
|
+
for (const r of g.rects) ops += `${n(x0 + r.x * scale)} ${n(y - bh)} ${n(r.w * scale)} ${n(bh)} re f
|
|
139
|
+
`;
|
|
140
|
+
y -= bh + 12;
|
|
141
|
+
const cw = textWidth("F4", 10, v.barcode);
|
|
142
|
+
text("F4", 10, M + (inner - Math.min(cw, inner)) / 2, v.barcode.slice(0, Math.floor(inner / 6)));
|
|
143
|
+
y -= 4;
|
|
144
|
+
}
|
|
145
|
+
const expires = formatDate(v.expires_at, locale, opts.timeZone);
|
|
146
|
+
if (expires) {
|
|
147
|
+
y -= 8;
|
|
148
|
+
paragraph("F2", 10, `${t.expires}: ${expires.replace(/\.$/, "")}.`);
|
|
149
|
+
paragraph("F1", 10, t.expiresNote);
|
|
150
|
+
}
|
|
151
|
+
y -= 10;
|
|
152
|
+
ensure(40);
|
|
153
|
+
paragraph("F2", 12, t.stepsTitle, { lead: 16 });
|
|
154
|
+
voucherSteps(v, t).forEach((s, i) => {
|
|
155
|
+
const lines = wrap("F1", 10, s, inner - 18);
|
|
156
|
+
ensure(lines.length * 14 + 2);
|
|
157
|
+
y -= 2;
|
|
158
|
+
lines.forEach((line, j) => {
|
|
159
|
+
y -= 14;
|
|
160
|
+
if (j === 0) text("F1", 10, M, `${i + 1}.`);
|
|
161
|
+
text("F1", 10, M + 18, line);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
if (v.instructions) {
|
|
165
|
+
y -= 6;
|
|
166
|
+
paragraph("F1", 9, v.instructions, { gray: 0.33, lead: 12 });
|
|
167
|
+
}
|
|
168
|
+
y -= 8;
|
|
169
|
+
paragraph("F1", 8, t.footer, { gray: 0.33, lead: 11 });
|
|
170
|
+
pages.push(ops);
|
|
171
|
+
const objs = [];
|
|
172
|
+
const kids = pages.map((_, i) => `${8 + i * 2} 0 R`).join(" ");
|
|
173
|
+
objs[1] = "<< /Type /Catalog /Pages 2 0 R >>";
|
|
174
|
+
objs[2] = `<< /Type /Pages /Kids [${kids}] /Count ${pages.length} >>`;
|
|
175
|
+
["F1", "F2", "F3", "F4"].forEach((f, i) => objs[3 + i] = `<< /Type /Font /Subtype /Type1 /BaseFont /${FONT_NAMES[f]} /Encoding /WinAnsiEncoding >>`);
|
|
176
|
+
objs[7] = `<< /Title ${pdfString(`${t.title}${opts.shopName ? ` - ${opts.shopName}` : ""}`)} /Producer ${pdfString("@asteby/storefront-react")} >>`;
|
|
177
|
+
pages.forEach((content, i) => {
|
|
178
|
+
objs[8 + i * 2] = `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${n(W)} ${n(H)}] /Resources << /Font << /F1 3 0 R /F2 4 0 R /F3 5 0 R /F4 6 0 R >> >> /Contents ${9 + i * 2} 0 R >>`;
|
|
179
|
+
objs[9 + i * 2] = `<< /Length ${content.length} >>
|
|
180
|
+
stream
|
|
181
|
+
${content}endstream`;
|
|
182
|
+
});
|
|
183
|
+
let out = "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n";
|
|
184
|
+
const offsets = [];
|
|
185
|
+
for (let i = 1; i < objs.length; i++) {
|
|
186
|
+
offsets[i] = out.length;
|
|
187
|
+
out += `${i} 0 obj
|
|
188
|
+
${objs[i]}
|
|
189
|
+
endobj
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
const xref = out.length;
|
|
193
|
+
out += `xref
|
|
194
|
+
0 ${objs.length}
|
|
195
|
+
0000000000 65535 f
|
|
196
|
+
`;
|
|
197
|
+
for (let i = 1; i < objs.length; i++) out += `${String(offsets[i]).padStart(10, "0")} 00000 n
|
|
198
|
+
`;
|
|
199
|
+
out += `trailer
|
|
200
|
+
<< /Size ${objs.length} /Root 1 0 R /Info 7 0 R >>
|
|
201
|
+
startxref
|
|
202
|
+
${xref}
|
|
203
|
+
%%EOF
|
|
204
|
+
`;
|
|
205
|
+
if (out.length > MAX_VOUCHER_PDF_BYTES) throw new RangeError("voucher PDF too large");
|
|
206
|
+
const bytes = new Uint8Array(out.length);
|
|
207
|
+
for (let i = 0; i < out.length; i++) bytes[i] = out.charCodeAt(i) & 255;
|
|
208
|
+
return bytes;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export { MAX_VOUCHER_PDF_BYTES, pdfString, renderVoucherPdf };
|
|
212
|
+
//# sourceMappingURL=voucher-pdf-LQC333AB.js.map
|
|
213
|
+
//# sourceMappingURL=voucher-pdf-LQC333AB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/account/voucher-pdf.ts"],"names":["n"],"mappings":"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","file":"voucher-pdf-LQC333AB.js","sourcesContent":["/**\n * The voucher as a real PDF 1.4, written by hand: no browser, no native module, no dependency, so the same code runs in\n * the store's Node/SSR route and in the buyer's browser. Standard Helvetica / Courier fonts (not embedded: every reader\n * has them), text in WinAnsi, the barcode as filled rectangles. Every external string reaches the file only through\n * `pdfString`, which writes it as ASCII octal escapes, so nothing a gateway sends can close a string or add an object.\n * Loaded on demand (the server route or the buyer's tap), never in the first load of the order screens.\n */\nimport { barcodeGeometry, type VoucherView } from './voucher.js'\nimport { docText, formatDate, formatMoney, methodName, voucherFields, voucherSteps } from './voucher-text.js'\n\nexport type VoucherPdfOptions = {\n shopName?: string\n number?: string | null\n locale?: string\n timeZone?: string\n /** `a4` (default) or `letter` (Mexico prints on both). */\n paper?: 'a4' | 'letter'\n}\n\n/** Hard ceiling of the file: a voucher is a few KB; anything near this is a bug, not a voucher. */\nexport const MAX_VOUCHER_PDF_BYTES = 256 * 1024\nconst MAX_PAGES = 3\n\n// Advance widths (1/1000 em) of ASCII 32..126 for the standard Helvetica and Helvetica-Bold (Adobe AFM).\nconst HELV = [278, 278, 355, 556, 556, 889, 667, 191, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 278, 278, 584, 584, 584, 556, 1015, 667, 667, 722, 722, 667, 611, 778, 722, 278, 500, 667, 556, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 278, 278, 278, 469, 556, 333, 556, 556, 500, 556, 556, 278, 556, 556, 222, 222, 500, 222, 833, 556, 556, 556, 556, 333, 500, 278, 556, 500, 722, 500, 500, 500, 334, 260, 334, 584]\nconst HELV_B = [278, 333, 474, 556, 556, 889, 722, 238, 333, 333, 389, 584, 278, 333, 278, 278, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 333, 333, 584, 584, 584, 611, 975, 722, 722, 722, 722, 667, 611, 778, 722, 278, 556, 722, 611, 833, 722, 778, 667, 778, 722, 667, 611, 722, 667, 944, 667, 667, 611, 333, 278, 333, 584, 556, 333, 556, 611, 556, 611, 556, 333, 611, 611, 278, 278, 556, 278, 889, 611, 611, 611, 611, 389, 556, 333, 611, 556, 778, 556, 556, 500, 389, 280, 389, 584]\n\ntype Font = 'F1' | 'F2' | 'F3' | 'F4'\nconst FONT_NAMES: Record<Font, string> = { F1: 'Helvetica', F2: 'Helvetica-Bold', F3: 'Courier-Bold', F4: 'Courier' }\n\n// The few characters outside Latin-1 that WinAnsi (cp1252) has at 0x80..0x9F.\nconst CP1252: Record<number, number> = { 0x20ac: 0x80, 0x2018: 0x91, 0x2019: 0x92, 0x201c: 0x93, 0x201d: 0x94, 0x2022: 0x95, 0x2013: 0x96, 0x2014: 0x97 }\n\n/** One WinAnsi byte per character; anything it cannot show becomes `?` (and control characters a space). */\nfunction toBytes(s: string): number[] {\n const out: number[] = []\n for (const ch of s) {\n const c = ch.codePointAt(0)!\n if (c < 32 || c === 127) out.push(32)\n else if (c < 127 || (c >= 160 && c <= 255)) out.push(c)\n else out.push(CP1252[c] ?? 63)\n }\n return out\n}\n\n/** PDF literal string: printable ASCII as is (minus the three that delimit), the rest as `\\ddd`. */\nexport function pdfString(s: string): string {\n let o = '('\n for (const b of toBytes(s)) o += b >= 32 && b < 127 && b !== 40 && b !== 41 && b !== 92 ? String.fromCharCode(b) : `\\\\${b.toString(8).padStart(3, '0')}`\n return o + ')'\n}\n\nfunction charWidth(font: Font, ch: string): number {\n if (font === 'F3' || font === 'F4') return 600\n const c = ch.codePointAt(0)!\n const table = font === 'F2' ? HELV_B : HELV\n if (c >= 32 && c < 127) return table[c - 32]!\n const base = ch.normalize('NFD')[0]!.codePointAt(0)!\n return base >= 32 && base < 127 ? table[base - 32]! : 556\n}\nconst textWidth = (font: Font, size: number, s: string) => ([...s].reduce((w, ch) => w + charWidth(font, ch), 0) * size) / 1000\n\n/** Greedy word wrap to `max` points; a word wider than the line is cut. Explicit newlines are honored. */\nfunction wrap(font: Font, size: number, text: string, max: number): string[] {\n const lines: string[] = []\n for (const para of text.split(/\\r?\\n/)) {\n let line = ''\n for (const word of para.split(/\\s+/).filter(Boolean)) {\n let w = word\n while (textWidth(font, size, w) > max) {\n let n = 1\n while (n < w.length && textWidth(font, size, w.slice(0, n + 1)) <= max) n++\n if (line) (lines.push(line), (line = ''))\n lines.push(w.slice(0, n))\n w = w.slice(n)\n }\n const next = line ? `${line} ${w}` : w\n if (line && textWidth(font, size, next) > max) (lines.push(line), (line = w))\n else line = next\n }\n lines.push(line)\n }\n return lines\n}\n\nconst n = (x: number) => String(Math.round(x * 100) / 100)\n\n/** The voucher as the bytes of a PDF. Throws only if the result would exceed `MAX_VOUCHER_PDF_BYTES`. */\nexport function renderVoucherPdf(v: VoucherView, opts: VoucherPdfOptions = {}): Uint8Array {\n const locale = opts.locale ?? 'es-MX'\n const t = docText(locale)\n const [W, H] = opts.paper === 'letter' ? [612, 792] : [595.28, 841.89]\n const M = 54\n const right = W - M\n const inner = right - M\n\n const pages: string[] = []\n let ops = ''\n let y = H - M\n const newPage = () => {\n if (pages.length >= MAX_PAGES) return false\n if (ops) pages.push(ops)\n ops = ''\n y = H - M\n return true\n }\n const text = (font: Font, size: number, x: number, s: string, gray = 0) => {\n ops += `BT ${n(gray)} g /${font} ${size} Tf ${n(x)} ${n(y)} Td ${pdfString(s)} Tj ET\\n`\n }\n const ensure = (h: number) => {\n if (y - h < M) newPage()\n }\n const paragraph = (font: Font, size: number, s: string, opt: { x?: number; width?: number; gray?: number; lead?: number } = {}) => {\n const lead = opt.lead ?? size * 1.4\n for (const line of wrap(font, size, s, opt.width ?? inner)) {\n ensure(lead)\n y -= lead\n if (line) text(font, size, opt.x ?? M, line, opt.gray ?? 0)\n }\n }\n\n // Header: title and subtitle on the left, amount on the right.\n const amount = formatMoney(v.amount, locale)\n const top = y\n y -= 20\n text('F2', 20, M, t.title)\n const subtitle = [opts.shopName, methodName(v, t), opts.number ? `${t.order} ${opts.number}` : ''].filter(Boolean).join(' · ')\n if (subtitle) {\n y -= 15\n paragraph('F1', 10, subtitle, { width: amount ? inner * 0.6 : inner, gray: 0.33, lead: 12 })\n }\n const afterTitle = y\n if (amount) {\n y = top - 10\n const label = t.total.toUpperCase()\n text('F1', 8, right - textWidth('F1', 8, label), label, 0.33)\n y -= 22\n text('F2', 22, right - textWidth('F2', 22, amount), amount)\n }\n y = Math.min(afterTitle, y) - 10\n ops += `0 g 2 w ${n(M)} ${n(y)} m ${n(right)} ${n(y)} l S\\n`\n y -= 8\n\n // Fields of the method, each in a box.\n for (const f of voucherFields(v, t)) {\n const size = f.value.length > 36 ? 12 : 16\n const lines = wrap('F3', size, f.value, inner - 24)\n const h = 14 + 12 + lines.length * size * 1.3 + 8\n ensure(h + 12)\n y -= 12\n ops += `0 G 0.8 w ${n(M)} ${n(y - h)} ${n(inner)} ${n(h)} re S\\n`\n const boxTop = y\n y -= 16\n text('F1', 8, M + 12, f.label.toUpperCase(), 0.33)\n y -= 4\n for (const line of lines) {\n y -= size * 1.3\n text('F3', size, M + 12, line)\n }\n y = boxTop - h\n }\n\n // Barcode: filled rectangles, the quiet zone included in the width.\n const g = v.barcode ? barcodeGeometry(v.barcode, { ...(v.barcode_format ? { format: v.barcode_format } : {}), height: 60 }) : null\n if (g && v.barcode) {\n const scale = Math.min(1, inner / g.width) * 0.75 // module = 1.5pt at most\n const bw = g.width * scale\n const bh = 60\n ensure(bh + 40)\n y -= 18\n ops += `0 g\\n`\n const x0 = M + (inner - bw) / 2\n for (const r of g.rects) ops += `${n(x0 + r.x * scale)} ${n(y - bh)} ${n(r.w * scale)} ${n(bh)} re f\\n`\n y -= bh + 12\n const cw = textWidth('F4', 10, v.barcode)\n text('F4', 10, M + (inner - Math.min(cw, inner)) / 2, v.barcode.slice(0, Math.floor(inner / 6)))\n y -= 4\n }\n\n const expires = formatDate(v.expires_at, locale, opts.timeZone)\n if (expires) {\n y -= 8\n paragraph('F2', 10, `${t.expires}: ${expires.replace(/\\.$/, '')}.`)\n paragraph('F1', 10, t.expiresNote)\n }\n\n y -= 10\n ensure(40)\n paragraph('F2', 12, t.stepsTitle, { lead: 16 })\n voucherSteps(v, t).forEach((s, i) => {\n const lines = wrap('F1', 10, s, inner - 18)\n ensure(lines.length * 14 + 2)\n y -= 2\n lines.forEach((line, j) => {\n y -= 14\n if (j === 0) text('F1', 10, M, `${i + 1}.`)\n text('F1', 10, M + 18, line)\n })\n })\n if (v.instructions) {\n y -= 6\n paragraph('F1', 9, v.instructions, { gray: 0.33, lead: 12 })\n }\n y -= 8\n paragraph('F1', 8, t.footer, { gray: 0.33, lead: 11 })\n pages.push(ops)\n\n // Objects: 1 catalog, 2 pages, 3..6 fonts, 7 info, then (page, content) pairs.\n const objs: string[] = []\n const kids = pages.map((_, i) => `${8 + i * 2} 0 R`).join(' ')\n objs[1] = '<< /Type /Catalog /Pages 2 0 R >>'\n objs[2] = `<< /Type /Pages /Kids [${kids}] /Count ${pages.length} >>`\n ;(['F1', 'F2', 'F3', 'F4'] as Font[]).forEach((f, i) => (objs[3 + i] = `<< /Type /Font /Subtype /Type1 /BaseFont /${FONT_NAMES[f]} /Encoding /WinAnsiEncoding >>`))\n objs[7] = `<< /Title ${pdfString(`${t.title}${opts.shopName ? ` - ${opts.shopName}` : ''}`)} /Producer ${pdfString('@asteby/storefront-react')} >>`\n pages.forEach((content, i) => {\n objs[8 + i * 2] = `<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${n(W)} ${n(H)}] /Resources << /Font << /F1 3 0 R /F2 4 0 R /F3 5 0 R /F4 6 0 R >> >> /Contents ${9 + i * 2} 0 R >>`\n objs[9 + i * 2] = `<< /Length ${content.length} >>\\nstream\\n${content}endstream`\n })\n\n let out = '%PDF-1.4\\n%\\xE2\\xE3\\xCF\\xD3\\n'\n const offsets: number[] = []\n for (let i = 1; i < objs.length; i++) {\n offsets[i] = out.length\n out += `${i} 0 obj\\n${objs[i]}\\nendobj\\n`\n }\n const xref = out.length\n out += `xref\\n0 ${objs.length}\\n0000000000 65535 f \\n`\n for (let i = 1; i < objs.length; i++) out += `${String(offsets[i]).padStart(10, '0')} 00000 n \\n`\n out += `trailer\\n<< /Size ${objs.length} /Root 1 0 R /Info 7 0 R >>\\nstartxref\\n${xref}\\n%%EOF\\n`\n\n if (out.length > MAX_VOUCHER_PDF_BYTES) throw new RangeError('voucher PDF too large')\n const bytes = new Uint8Array(out.length)\n for (let i = 0; i < out.length; i++) bytes[i] = out.charCodeAt(i) & 0xff\n return bytes\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/storefront-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"description": "React bindings for @asteby/storefront — SSR-safe provider, optimistic cart, Money, responsive Image, prices, variant selection, SEO meta and JSON-LD, section registry and server-rendered theme CSS.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
"react": "^19.0.0"
|
|
185
185
|
},
|
|
186
186
|
"dependencies": {
|
|
187
|
-
"@asteby/storefront": "0.18.
|
|
187
|
+
"@asteby/storefront": "0.18.1"
|
|
188
188
|
},
|
|
189
189
|
"devDependencies": {
|
|
190
190
|
"@testing-library/react": "^16.3.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/payments/recovery-messages.ts","../src/payments/csp.ts","../src/payments/choices.ts"],"names":[],"mappings":"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","file":"chunk-MNLROALF.js","sourcesContent":["import type { PaymentErrorClassKind } from '@asteby/storefront'\n\n/** The notices `<PaymentRecovery>` can show. */\nexport type PaymentNoticeKind =\n /** Confirming the payment (automatic retry or status check). */\n | 'confirming'\n /** The secure card form did not load after the automatic retries. */\n | 'form_failed'\n /** The bank or provider rejected the charge (definitive): another card can be tried. */\n | 'rejected'\n /** The provider refused the charge at API level (definitive, nothing charged). */\n | 'provider_declined'\n /** Credentials or configuration of the merchant with the provider. */\n | 'merchant_config'\n /** The cart already became an order and the payment could not be reopened. */\n | 'stale_checkout'\n /** Another definitive error. */\n | 'other'\n\nexport type PaymentRecoveryMessageKey =\n | `error.${PaymentErrorClassKind}`\n | `notice.${PaymentNoticeKind}.title`\n | `notice.${PaymentNoticeKind}.body`\n | 'action.retry'\n | 'action.retry_form'\n | 'action.refresh'\n /** `{label}` is the name of the alternative payment choice. */\n | 'action.alternative'\n\nexport type PaymentRecoveryMessages = Record<PaymentRecoveryMessageKey, string>\n\nconst ES: PaymentRecoveryMessages = {\n 'error.transient': 'Estamos verificando tu pago. Si el cargo se hizo, lo veremos aquí; no te cobraremos dos veces.',\n 'error.in_progress': 'Ya hay un pago en proceso para este pedido. Estamos verificándolo; no vuelvas a pagar.',\n 'error.rate_limited': 'Hiciste varios intentos seguidos. Espera unos minutos e inténtalo de nuevo.',\n 'error.merchant_config': 'Por ahora no podemos procesar pagos con tarjeta. No es un problema con tu tarjeta: puedes pagar de otra forma.',\n 'error.provider_declined': 'No pudimos procesar tu pago con esa tarjeta. Revisa los datos o prueba con otro método; no se hizo ningún cobro.',\n 'error.stale_checkout': 'Este pedido ya quedó registrado y no se pudo reabrir el pago. Actualiza para ver cómo va tu pedido.',\n 'error.expired': 'Tu carrito venció. Vuelve a armarlo para pagar.',\n 'error.price_mismatch': 'El total cambió. Revisa el nuevo total y vuelve a pagar.',\n 'error.store_closed': 'Esta tienda aún no está abierta para compras. Vuelve pronto.',\n 'error.validation': 'Completa los campos marcados.',\n 'error.other': 'No pudimos procesar tu pago. Intenta de nuevo.',\n 'notice.confirming.title': 'Estamos confirmando tu pago…',\n 'notice.confirming.body': 'No cierres esta página ni vuelvas a pagar. Si el cargo ya se hizo, lo verás reflejado aquí.',\n 'notice.form_failed.title': 'No pudimos cargar el formulario de tarjeta',\n 'notice.form_failed.body': 'Suele resolverse al intentar de nuevo. También puedes pagar de otra forma.',\n 'notice.rejected.title': 'El cargo no se completó',\n 'notice.rejected.body': 'No se hizo ningún cobro. Puedes intentar con otra tarjeta o elegir otra forma de pago.',\n 'notice.provider_declined.title': 'No pudimos procesar tu pago con esa tarjeta',\n 'notice.provider_declined.body': 'No se hizo ningún cobro. Revisa los datos o prueba con otra tarjeta u otro método de pago.',\n 'notice.merchant_config.title': 'Por ahora no podemos cobrar con tarjeta',\n 'notice.merchant_config.body': 'No es un problema con tu tarjeta: es un tema de nuestro lado. Puedes pagar de otra forma.',\n 'notice.stale_checkout.title': 'Tu pedido ya quedó registrado',\n 'notice.stale_checkout.body': 'No pudimos reabrir el pago de este pedido. Actualiza para ver cómo va tu pedido; no se cobró de nuevo.',\n 'notice.other.title': 'No pudimos procesar tu pago',\n 'notice.other.body': 'Intenta de nuevo; si sigue igual, puedes pagar de otra forma.',\n 'action.retry': 'Reintentar pago',\n 'action.retry_form': 'Reintentar',\n 'action.refresh': 'Actualizar mi pedido',\n 'action.alternative': 'Pagar con {label}',\n}\n\nconst EN: PaymentRecoveryMessages = {\n 'error.transient': \"We're verifying your payment. If the charge went through we'll show it here; you won't be charged twice.\",\n 'error.in_progress': \"A payment is already in progress for this order. We're verifying it; don't pay again.\",\n 'error.rate_limited': 'Too many attempts in a row. Wait a few minutes and try again.',\n 'error.merchant_config': \"We can't take card payments right now. It isn't a problem with your card: you can pay another way.\",\n 'error.provider_declined': \"We couldn't process your payment with that card. Check the details or try another method; you were not charged.\",\n 'error.stale_checkout': \"This order is already registered and the payment couldn't be reopened. Refresh to see how it's going.\",\n 'error.expired': 'Your cart expired. Rebuild it to pay.',\n 'error.price_mismatch': 'The total changed. Check the new total and pay again.',\n 'error.store_closed': \"This store isn't open for purchases yet. Come back soon.\",\n 'error.validation': 'Complete the marked fields.',\n 'error.other': \"We couldn't process your payment. Try again.\",\n 'notice.confirming.title': \"We're confirming your payment…\",\n 'notice.confirming.body': \"Don't close this page or pay again. If the charge already went through you'll see it here.\",\n 'notice.form_failed.title': \"We couldn't load the card form\",\n 'notice.form_failed.body': 'Trying again usually fixes it. You can also pay another way.',\n 'notice.rejected.title': \"The charge didn't go through\",\n 'notice.rejected.body': 'You were not charged. Try another card or choose another way to pay.',\n 'notice.provider_declined.title': \"We couldn't process your payment with that card\",\n 'notice.provider_declined.body': 'You were not charged. Check the details or try another card or method.',\n 'notice.merchant_config.title': \"We can't charge cards right now\",\n 'notice.merchant_config.body': \"It isn't a problem with your card: it's on our side. You can pay another way.\",\n 'notice.stale_checkout.title': 'Your order is already registered',\n 'notice.stale_checkout.body': \"We couldn't reopen the payment for this order. Refresh to see how it's going; you were not charged again.\",\n 'notice.other.title': \"We couldn't process your payment\",\n 'notice.other.body': 'Try again; if it keeps failing you can pay another way.',\n 'action.retry': 'Retry payment',\n 'action.retry_form': 'Retry',\n 'action.refresh': 'Refresh my order',\n 'action.alternative': 'Pay with {label}',\n}\n\n/** Texts for a locale (`es*` default, `en*`), with optional overrides. Nothing here names a provider or a brand. */\nexport function paymentRecoveryMessages(locale?: string | null, overrides?: Partial<PaymentRecoveryMessages> | null): PaymentRecoveryMessages {\n const base = (locale ?? 'es-MX').toLowerCase().startsWith('en') ? EN : ES\n return overrides ? { ...base, ...overrides } : base\n}\n","import type { PaymentClient } from '@asteby/storefront'\n\nexport type PaymentCspOptions = {\n /** Per-request nonce; also set it on the inserted `<script>` and on `<Scripts nonce>`. */\n nonce?: string\n /** Extra origins by directive (e.g. your image CDN). */\n extra?: { script?: string[]; frame?: string[]; connect?: string[]; img?: string[]; form?: string[] }\n /** `report-uri` / `report-to` target for the report-only rollout. */\n reportUri?: string\n /** Inline scripts allowed by hash (`'sha256-…'`), e.g. a theme bootstrap that runs before paint. */\n scriptHashes?: string[]\n /** Allow any https image source (product photos from a CDN). */\n imgHttps?: boolean\n}\n\n/** One origin source: `https://host`, `https://*.host`, optional port. Anything else (`;`, spaces, `'unsafe-eval'`) is dropped. */\nconst ORIGIN = /^https:\\/\\/(\\*\\.)?[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*(:\\d{1,5})?$/i\n\nfunction origins(...lists: (readonly string[] | undefined)[]): string[] {\n const out = new Set<string>()\n for (const list of lists) for (const o of list ?? []) if (ORIGIN.test(o)) out.add(o)\n return [...out]\n}\n\n/**\n * Builds the Content-Security-Policy for the payment routes from what each provider declares\n * (`PaymentClient.csp`), so the shop never hard-codes provider hosts. Meant for `/pagar` only,\n * never for the whole site. Roll out as `Content-Security-Policy-Report-Only` first.\n *\n * No SRI on purpose: provider SDK URLs are unversioned and a hash would break payments on any update.\n */\nexport function paymentCsp(clients: readonly (PaymentClient | null | undefined)[], options: PaymentCspOptions = {}): string {\n const list = clients.filter((c): c is PaymentClient => !!c)\n const pick = (k: keyof NonNullable<PaymentClient['csp']>) => list.map((c) => c.csp?.[k])\n const nonce = options.nonce && /^[A-Za-z0-9+/=_-]+$/.test(options.nonce) ? options.nonce : undefined\n const sdkOrigins = list.flatMap((c) => {\n try {\n const u = new URL(c.sdk_url)\n return u.protocol === 'https:' ? [u.origin] : []\n } catch {\n return []\n }\n })\n const dir = (name: string, values: string[]) => `${name} ${values.join(' ')}`\n const parts = [\n \"default-src 'self'\",\n dir('script-src', [\"'self'\", ...(options.scriptHashes ?? []).filter((h) => /^'sha(256|384|512)-[A-Za-z0-9+/=]+'$/.test(h)), ...(nonce ? [`'nonce-${nonce}'`] : []), ...origins(sdkOrigins, ...pick('script'), options.extra?.script)]),\n dir('frame-src', origins(...pick('frame'), options.extra?.frame).length ? origins(...pick('frame'), options.extra?.frame) : [\"'none'\"]),\n dir('connect-src', [\"'self'\", ...origins(...pick('connect'), options.extra?.connect)]),\n dir('img-src', [\"'self'\", 'data:', ...(options.imgHttps ? ['https:'] : []), ...origins(...pick('img'), options.extra?.img)]),\n \"style-src 'self' 'unsafe-inline'\",\n dir('form-action', [\"'self'\", ...origins(...pick('form'), options.extra?.form)]),\n \"frame-ancestors 'none'\",\n \"base-uri 'self'\",\n \"object-src 'none'\",\n ]\n if (options.reportUri && /^(https:\\/\\/|\\/)[^\\s;,]+$/.test(options.reportUri)) parts.push(`report-uri ${options.reportUri}`)\n return parts.join('; ')\n}\n\n/** `Content-Security-Policy` or, during the rollout week, `Content-Security-Policy-Report-Only`. */\nexport function paymentCspHeaderName(reportOnly: boolean): string {\n return reportOnly ? 'Content-Security-Policy-Report-Only' : 'Content-Security-Policy'\n}\n\nexport type PaymentCspMode = 'off' | 'report-only' | 'enforce'\n\n/** `PAYMENT_CSP`-style value: `off`, `report-only` or `enforce`. Unset: report-only in production, off elsewhere (dev servers inject scripts). */\nexport function paymentCspMode(value: string | null | undefined, production: boolean): PaymentCspMode {\n const raw = (value ?? '').trim().toLowerCase()\n if (raw === 'off' || raw === 'report-only' || raw === 'enforce') return raw\n return production ? 'report-only' : 'off'\n}\n\n/** Fresh per-request nonce (128 bits, base64). Works in Node, edge and browsers. */\nexport function paymentNonce(): string {\n const bytes = new Uint8Array(16)\n crypto.getRandomValues(bytes)\n let bin = ''\n for (const b of bytes) bin += String.fromCharCode(b)\n return btoa(bin)\n}\n\n/** Header ready for the response (`{}` when `off`): policy from the providers' `client.csp`, never the whole site. */\nexport function paymentCspHeaders(\n clients: readonly (PaymentClient | null | undefined)[],\n options: PaymentCspOptions & { mode: PaymentCspMode },\n): Record<string, string> {\n if (options.mode === 'off') return {}\n return { [paymentCspHeaderName(options.mode === 'report-only')]: paymentCsp(clients, options) }\n}\n\n/** The nonce the route left in the CSP header, to hand to `ServerRouter` / `<Scripts>`. */\nexport function paymentNonceFromHeaders(headers: Headers): string | undefined {\n const csp = headers.get('Content-Security-Policy') ?? headers.get('Content-Security-Policy-Report-Only') ?? ''\n return /'nonce-([A-Za-z0-9+/=_-]+)'/.exec(csp)?.[1]\n}\n","/**\n * \"Payment method\" rows for a hybrid checkout: pure functions, no DOM and no server, so the loader, the action and the\n * browser share them.\n *\n * Rules (embedded-payment contract 1.2):\n * - Rows come ONLY from what the server publishes (`payment-methods[].options` and `.client`). No provider names and no\n * amounts live here.\n * - Card and cash are paid in the page; `wallet` and `credits` redirect to the provider.\n * - Without `client`, or with the card flagged `redirect: true`, the server does not offer `embedded`: the shop falls\n * back to the usual redirect flow.\n */\nimport { classifyPaymentError } from '@asteby/storefront'\nimport type {\n CheckoutResult,\n PaymentAttemptResult,\n PaymentClient,\n PaymentErrorClassKind,\n PaymentMethod,\n PaymentOption,\n PaymentOptionKey,\n PaymentPoint,\n} from '@asteby/storefront'\nimport { paymentRecoveryMessages, type PaymentRecoveryMessages } from './recovery-messages.js'\n\n/** One row of \"Payment method\". `value` is what travels in the form (`payment_choice`). */\nexport type PayChoice = {\n value: string\n /** Server method key (`payment_method` of the checkout). */\n methodKey: string\n /** Provider option; `null` for a method without options (the plain flow). */\n option: PaymentOptionKey | null\n /** `card` (form in the page), `cash` (voucher), `redirect` (leaves to the gateway) or `plain`. */\n mode: 'card' | 'cash' | 'redirect' | 'plain'\n /** The provider's own text (`option.label`); the shop supplies its own when missing. */\n label: string | null\n points: PaymentPoint[]\n maxInstallments: number | null\n}\n\nexport type PayChoices = {\n choices: PayChoice[]\n /** Public data to mount the card form; `null` when the server does not offer `embedded`. */\n cardClient: PaymentClient | null\n defaultValue: string | null\n}\n\nexport type BuildPayChoicesOptions = {\n /** Method keys this shop never offers even when the server publishes them (e.g. a manual transfer). */\n hide?: Iterable<string>\n}\n\nconst SEP = '|'\n\nexport function choiceValue(methodKey: string, option: PaymentOptionKey | null): string {\n return option ? `${methodKey}${SEP}${option}` : methodKey\n}\n\n/** `\"mercadopago|card\"` becomes method and option. A value without `|` is a method without options. */\nexport function parseChoice(value: string | null | undefined): { methodKey: string; option: PaymentOptionKey | null } | null {\n const raw = (value ?? '').trim()\n if (!raw) return null\n const i = raw.lastIndexOf(SEP)\n if (i === -1) return { methodKey: raw, option: null }\n const option = raw.slice(i + 1)\n if (option !== 'card' && option !== 'cash' && option !== 'wallet' && option !== 'credits') return null\n return { methodKey: raw.slice(0, i), option }\n}\n\nfunction modeOf(option: PaymentOption): PayChoice['mode'] {\n if (option.redirect || option.key === 'wallet' || option.key === 'credits') return 'redirect'\n return option.key === 'cash' ? 'cash' : 'card'\n}\n\n/**\n * Rows from `GET payment-methods`. A method with `options` unfolds into one row per option (server order); one without\n * is a single plain row. `cardClient` only exists when the card is paid in the page.\n */\nexport function buildPayChoices(methods: readonly PaymentMethod[], options: BuildPayChoicesOptions = {}): PayChoices {\n const hidden = new Set(options.hide ?? [])\n const choices: PayChoice[] = []\n let cardClient: PaymentClient | null = null\n let defaultValue: string | null = null\n for (const method of methods) {\n if (hidden.has(method.key)) continue\n const opts = method.options ?? []\n if (opts.length === 0) {\n const value = choiceValue(method.key, null)\n choices.push({ value, methodKey: method.key, option: null, mode: 'plain', label: null, points: [], maxInstallments: null })\n if (method.default && !defaultValue) defaultValue = value\n continue\n }\n opts.forEach((option, i) => {\n const mode = modeOf(option)\n const value = choiceValue(method.key, option.key)\n choices.push({\n value,\n methodKey: method.key,\n option: option.key,\n mode,\n label: option.label?.trim() || null,\n points: option.key === 'cash' ? (option.points ?? []) : [],\n maxInstallments: option.max_installments ?? null,\n })\n if (mode === 'card' && method.client && !cardClient) cardClient = method.client\n if (method.default && i === 0 && !defaultValue) defaultValue = value\n })\n }\n // A card meant for the page but without `client` cannot be mounted: it is paid by redirect.\n const usable = choices.map((c) => (c.mode === 'card' && !cardClient ? { ...c, mode: 'redirect' as const } : c))\n return { choices: usable, cardClient, defaultValue: defaultValue ?? usable[0]?.value ?? null }\n}\n\n/** Chosen cash point becomes the cash `provider_data`, built on the server from the provider's list. */\nexport function cashProviderData(points: readonly PaymentPoint[], pointId: string | null | undefined): Record<string, string> | null {\n const point = points.find((p) => p.id === pointId) ?? (pointId ? null : points[0])\n if (!point) return null\n return {\n payment_method_id: point.payment_method_id,\n ...(point.payment_point ? { payment_point: point.payment_point } : {}),\n }\n}\n\n/**\n * A checkout (`GET checkouts/:id`) as an attempt result, for polling a 3DS challenge or a payment under review.\n * It only translates server states: it never decides a payment.\n */\nexport function checkoutToAttempt(result: CheckoutResult): PaymentAttemptResult {\n const { checkout, payment, order } = result\n const action = payment.action ?? null\n const base = { checkout, ...(order ? { order } : {}) }\n const status = (checkout.status ?? '').toLowerCase()\n if (status === 'paid' || status === 'converted') return { ...base, payment: { provider: payment.provider, status: 'paid', outcome: 'approved' } }\n if (status === 'cancelled' || status === 'canceled') return { ...base, payment: { provider: payment.provider, status: 'cancelled' } }\n if (status === 'expired') return { ...base, payment: { provider: payment.provider, status: 'expired' } }\n if (status === 'failed') {\n const decline = (payment as { decline_code?: PaymentAttemptResult['payment']['decline_code'] }).decline_code ?? 'declined'\n return { ...base, payment: { provider: payment.provider, status: 'failed', outcome: 'rejected', decline_code: decline, retryable: true } }\n }\n // Still pending: same as the last attempt left it (challenge or review), so the screen does not change.\n if (action?.type === 'challenge') return { ...base, payment: { provider: payment.provider, status: 'requires_action', outcome: 'challenge', action } }\n return { ...base, payment: { provider: payment.provider, status: 'pending', outcome: 'pending', action: action ?? { type: 'none' } } }\n}\n\n/**\n * Body `{ error: { code, message, retryable, kind, ... } }` that `createFetchTransport` and `createResilientTransport`\n * understand. `retryable` and `kind` come from `classifyPaymentError`: the browser never guesses them from the status.\n */\nexport type PayErrorBody = {\n error: { code: string; message: string; retryable: boolean; kind: PaymentErrorClassKind; field?: string; retry_after?: number; details?: unknown }\n}\n\ntype ErrorLike = {\n status?: number\n code?: string\n field?: string\n message?: string\n details?: unknown\n /** `StorefrontError.retryable`: what OPS declared. */\n retryable?: boolean | undefined\n checkoutId?: string | undefined\n retryAfter?: number | undefined\n}\n\nexport type PayErrorOptions = {\n locale?: string\n /** Replaces the default texts (`error.<kind>`). */\n messages?: Partial<PaymentRecoveryMessages>\n /** Forces the classification (for refusals the shop itself makes). */\n kind?: PaymentErrorClassKind\n /** `err.message` was written by the shop itself (a refusal it makes, such as `tooManyRequests`): always kept. */\n ownMessage?: boolean\n}\n\n/**\n * 502-504 never leave the shop's pay routes: the proxy (Traefik's `errors` middleware, a CDN) replaces them with an HTML\n * page, and the browser loses the JSON and the `Set-Cookie` of the payment session. They are answered as 500; the\n * body (`retryable`, `kind`) is what decides.\n */\nexport function safeHttpStatus(status: number): number {\n return status === 502 || status === 503 || status === 504 ? 500 : status\n}\n\n/**\n * Server error becomes a JSON response for the browser. Keeps the codes the SDK knows how to read (`price_mismatch`,\n * `payment_in_progress`, `expired`, `too_many_attempts`); the mock sends \"in progress\" in `field`, so that is checked too.\n * Always JSON, never 502-504 (see `safeHttpStatus`), always with `retryable` and `kind`.\n */\nexport function payErrorResponse(err: ErrorLike, options: PayErrorOptions = {}): { status: number; body: PayErrorBody } {\n const status = typeof err.status === 'number' && err.status >= 400 ? err.status : 503\n const { kind: classified, retryable } = classifyPaymentError({ ...err, status, checkoutId: err.checkoutId ?? null })\n const kind = options.kind ?? classified\n let code = err.code ?? (kind === 'transient' ? 'unavailable' : 'server_error')\n if (status === 409 && err.field === 'payment_in_progress') code = 'payment_in_progress'\n if (status === 429) code = 'too_many_attempts'\n if (status === 422 && err.field === 'expected_total') code = 'price_mismatch'\n // Texts the shop wrote itself (missing fields, expired cart, a row it does not offer) are kept; OPS' own message,\n // often technical or in English, is replaced by the catalog text for the kind.\n const own = (options.ownMessage || kind === 'validation' || kind === 'expired' || kind === 'price_mismatch' || (kind === 'other' && status < 500)) && err.message\n const message = own || paymentRecoveryMessages(options.locale, options.messages)[`error.${kind}`]\n return {\n status: safeHttpStatus(status),\n body: {\n error: {\n code,\n message,\n retryable: options.kind ? options.kind === 'transient' || options.kind === 'in_progress' || options.kind === 'rate_limited' : retryable,\n kind,\n ...(err.field ? { field: err.field } : {}),\n ...(err.retryAfter ? { retry_after: err.retryAfter } : {}),\n ...(err.details !== undefined ? { details: err.details } : {}),\n },\n },\n }\n}\n\nexport type VoucherRowLabels = { point: string; reference: string; clabe: string; barcode: string; expires: string }\n\n/** Cookie receipt rows for a payment under review or with a voucher (shown on the thank-you page). */\nexport function voucherRows(\n voucher: NonNullable<NonNullable<PaymentAttemptResult['payment']['action']>['voucher']> | null | undefined,\n labels: VoucherRowLabels,\n locale: string,\n): [label: string, value: string][] {\n if (!voucher) return []\n const rows: [string, string][] = []\n if (voucher.payment_point) rows.push([labels.point, String(voucher.payment_point).slice(0, 60)])\n if (voucher.reference) rows.push([labels.reference, String(voucher.reference).slice(0, 80)])\n if (voucher.clabe) rows.push([labels.clabe, String(voucher.clabe).slice(0, 40)])\n if (voucher.barcode) rows.push([labels.barcode, String(voucher.barcode).slice(0, 80)])\n if (voucher.expires_at) {\n const d = new Date(voucher.expires_at)\n if (!Number.isNaN(d.getTime())) {\n rows.push([labels.expires, new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeStyle: 'short', timeZone: 'UTC' }).format(d) + ' UTC'])\n }\n }\n return rows\n}\n"]}
|