@asteby/storefront 0.16.1 → 0.18.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 +24 -0
- package/dist/{types-DSHzYSHU.d.ts → account-settings-Cw3PamUA.d.ts} +241 -1
- package/dist/{types-C5nEQicj.d.cts → account-settings-DAzmXHIn.d.cts} +241 -1
- package/dist/{chunk-IPUAZ3LQ.js → chunk-5BJRZIS3.js} +196 -3
- package/dist/chunk-5BJRZIS3.js.map +1 -0
- package/dist/cli.js +62 -2
- package/dist/fiscal-document.d.cts +2 -2
- package/dist/fiscal-document.d.ts +2 -2
- package/dist/index.cjs +296 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -70
- package/dist/index.d.ts +135 -70
- package/dist/index.js +87 -4
- package/dist/index.js.map +1 -1
- package/dist/mock.cjs +403 -3
- package/dist/mock.cjs.map +1 -1
- package/dist/mock.d.cts +33 -2
- package/dist/mock.d.ts +33 -2
- package/dist/mock.js +299 -5
- 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/package.json +1 -1
- package/dist/chunk-IPUAZ3LQ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -124,9 +124,14 @@ function appendParams(search, params) {
|
|
|
124
124
|
return search;
|
|
125
125
|
}
|
|
126
126
|
function productListQuery(params = {}) {
|
|
127
|
-
const { filters, handles, ...rest } = params;
|
|
127
|
+
const { filters, handles, tags_any, ...rest } = params;
|
|
128
128
|
const search = appendParams(new URLSearchParams(), rest);
|
|
129
129
|
if (handles && handles.length > 0) search.set("handles", handles.join(","));
|
|
130
|
+
if (tags_any && tags_any.length > 0) {
|
|
131
|
+
if (tags_any.length > 5) throw new RangeError("tags_any takes at most 5 tags");
|
|
132
|
+
if (tags_any.some((t) => t.includes(",") || t.length > 120)) throw new TypeError("tags_any: a tag has at most 120 characters and no comma");
|
|
133
|
+
search.set("tags_any", tags_any.join(","));
|
|
134
|
+
}
|
|
130
135
|
if (filters) {
|
|
131
136
|
for (const [key, raw] of Object.entries(filters)) {
|
|
132
137
|
const name = key.startsWith("filter.") ? key : `filter.${key}`;
|
|
@@ -486,6 +491,43 @@ function createStorefrontClient(config) {
|
|
|
486
491
|
get: (options) => get("/storefront/customer", void 0, options),
|
|
487
492
|
/** Updates the profile and the saved fiscal data; `fiscal: null` deletes the latter. `422` with `field: 'fiscal.<field>'`. */
|
|
488
493
|
update: (input, options) => write("PATCH", "/storefront/customer", input, options),
|
|
494
|
+
/**
|
|
495
|
+
* Active sessions of the buyer («Devices»; contract 1.9). Private, never cached. The list carries no address
|
|
496
|
+
* and no token: only what the buyer needs to recognize their own devices.
|
|
497
|
+
*/
|
|
498
|
+
sessions: {
|
|
499
|
+
list: async (options) => (await get("/storefront/customer/sessions", void 0, { ...options, cache: "no-store" })).nodes,
|
|
500
|
+
/** Closes one session. Repeating it is fine. `404` for a session that is not the buyer's. Closing the current one is a sign-out. */
|
|
501
|
+
revoke: (id, options) => write("DELETE", `/storefront/customer/sessions/${enc(id)}`, void 0, options),
|
|
502
|
+
/** Closes every session except the one making the call. */
|
|
503
|
+
revokeOthers: (options) => write("DELETE", "/storefront/customer/sessions/others", void 0, options)
|
|
504
|
+
},
|
|
505
|
+
/**
|
|
506
|
+
* Confirms the buyer's identity again with their password or a sign-in code (`requestOtp` first). The
|
|
507
|
+
* confirmation lasts `valid_for_seconds` (a few minutes) and counts only for the session that made the call;
|
|
508
|
+
* exporting data and deleting the account need it (`403 reauth_required` otherwise, see `isReauthRequired`).
|
|
509
|
+
* A wrong credential is always the same `400`; too many tries is `429` (`StorefrontError.retryAfter`).
|
|
510
|
+
*/
|
|
511
|
+
reauth: (input, options) => write("POST", "/storefront/customer/reauth", input, options),
|
|
512
|
+
/**
|
|
513
|
+
* The buyer's data as a JSON file (contract 1.9, `capabilities().data_export`). Needs a recent `reauth`. It is
|
|
514
|
+
* built on request and is neither stored nor emailed: call it from YOUR server, stream the bytes
|
|
515
|
+
* (`dataExportBytes`, `safeExportFilename`) with `Cache-Control: no-store`, and keep nothing. Three a day per account.
|
|
516
|
+
*/
|
|
517
|
+
exportData: async (options) => {
|
|
518
|
+
const file = await write("POST", "/storefront/customer/data-export", void 0, { ...options, cache: "no-store" });
|
|
519
|
+
if (!file || typeof file.content_base64 !== "string" || typeof file.filename !== "string" || typeof file.content_type !== "string") {
|
|
520
|
+
throw new StorefrontError({ status: 502, code: "invalid_response", message: "The data export answer is not a file" });
|
|
521
|
+
}
|
|
522
|
+
return { filename: file.filename, content_type: file.content_type, content_base64: file.content_base64 };
|
|
523
|
+
},
|
|
524
|
+
/**
|
|
525
|
+
* Deletes the buyer's account (contract 1.9, `capabilities().account_delete`). Needs a recent `reauth` and the
|
|
526
|
+
* text the buyer typed in `confirm`. Personal data is erased; orders and invoices are kept by the store.
|
|
527
|
+
* `409` (see `isAccountDeleteBlocked`) while an order is on its way or a payment is pending. Idempotent: a
|
|
528
|
+
* repeat after success is also fine. Afterwards the token is dead: drop it.
|
|
529
|
+
*/
|
|
530
|
+
deleteAccount: (input, options) => write("DELETE", "/storefront/customer", input, options),
|
|
489
531
|
orders: (params, options) => get("/storefront/customer/orders", params, options),
|
|
490
532
|
/** `null` when the order does not exist or belongs to someone else. */
|
|
491
533
|
order: (id, options) => getOrNull(`/storefront/customer/orders/${enc(id)}`, void 0, options),
|
|
@@ -536,6 +578,19 @@ function createStorefrontClient(config) {
|
|
|
536
578
|
/** Physical delete (a profile leaves nothing behind). A saved default passes to another profile. */
|
|
537
579
|
delete: (id, options) => write("DELETE", `/storefront/customer/fiscal-profiles/${enc(id)}`, void 0, options)
|
|
538
580
|
},
|
|
581
|
+
/**
|
|
582
|
+
* Saved items of the buyer («My items», «My garage»; contract 1.9, `capabilities().subjects`). Personal data:
|
|
583
|
+
* private, never cached, never logged. `422` with `field: 'attributes.<field>'` when the kind refuses a value
|
|
584
|
+
* (it never echoes it); `409` for an item already saved or past the limit; `429` for too many saves; `404` for
|
|
585
|
+
* an item that is not the buyer's. The server builds `label` and `fit_key`; private fields come back masked.
|
|
586
|
+
*/
|
|
587
|
+
subjects: {
|
|
588
|
+
list: async (params, options) => (await get("/storefront/customer/subjects", params, { ...options, cache: "no-store" })).nodes,
|
|
589
|
+
create: (input, options) => write("POST", "/storefront/customer/subjects", input, options),
|
|
590
|
+
update: (id, patch, options) => write("PATCH", `/storefront/customer/subjects/${enc(id)}`, patch, options),
|
|
591
|
+
/** Physical delete (the item leaves nothing behind). The default of its kind passes to another item. */
|
|
592
|
+
delete: (id, options) => write("DELETE", `/storefront/customer/subjects/${enc(id)}`, void 0, options)
|
|
593
|
+
},
|
|
539
594
|
addresses: {
|
|
540
595
|
list: (options) => get("/storefront/customer/addresses", void 0, options),
|
|
541
596
|
create: (address, options) => write("POST", "/storefront/customer/addresses", address, options),
|
|
@@ -544,6 +599,11 @@ function createStorefrontClient(config) {
|
|
|
544
599
|
}
|
|
545
600
|
},
|
|
546
601
|
content: {
|
|
602
|
+
/**
|
|
603
|
+
* The kinds of buyer item the organization declares («My garage») and their catalogs (contract 1.9; public,
|
|
604
|
+
* cacheable). `[]` when it declares none or the server predates the route: the store has no such section.
|
|
605
|
+
*/
|
|
606
|
+
subjectKinds: async (options) => (await getOrNull("/storefront/subject-kinds", void 0, options))?.nodes ?? [],
|
|
547
607
|
theme: (options) => get("/storefront/content/theme", void 0, options),
|
|
548
608
|
/** `null` when the page does not exist. */
|
|
549
609
|
page: (handle, options) => getOrNull(`/storefront/content/pages/${enc(handle)}`, previewQuery(options), options),
|
|
@@ -1451,6 +1511,29 @@ function shipmentsStatus(order) {
|
|
|
1451
1511
|
return live.length ? live[0].status : null;
|
|
1452
1512
|
}
|
|
1453
1513
|
|
|
1514
|
+
// src/account-settings.ts
|
|
1515
|
+
function isReauthRequired(error) {
|
|
1516
|
+
const e = error;
|
|
1517
|
+
return !!e && typeof e === "object" && e.status === 403 && e.code === "reauth_required";
|
|
1518
|
+
}
|
|
1519
|
+
function isAccountDeleteBlocked(error) {
|
|
1520
|
+
const e = error;
|
|
1521
|
+
return !!e && typeof e === "object" && e.status === 409 && (e.field === "orders" || e.field === "pending_payments");
|
|
1522
|
+
}
|
|
1523
|
+
function dataExportBytes(file) {
|
|
1524
|
+
const raw = typeof file.content_base64 === "string" ? file.content_base64.replace(/\s+/g, "") : "";
|
|
1525
|
+
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(raw) || raw.length % 4 === 1) throw new TypeError("data export is not valid base64");
|
|
1526
|
+
const bin = atob(raw);
|
|
1527
|
+
const out = new Uint8Array(bin.length);
|
|
1528
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
1529
|
+
return out;
|
|
1530
|
+
}
|
|
1531
|
+
function safeExportFilename(name, fallback = "account-data.json") {
|
|
1532
|
+
const base = typeof name === "string" ? name.split(/[\\/]/).pop() ?? "" : "";
|
|
1533
|
+
const clean = base.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^\.+/, "").slice(0, 80);
|
|
1534
|
+
return clean || fallback;
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1454
1537
|
// src/invoice-docs.ts
|
|
1455
1538
|
function groupInvoiceDocs(docs) {
|
|
1456
1539
|
const list = Array.isArray(docs) ? docs.filter((d) => !!d && typeof d === "object") : [];
|
|
@@ -1478,6 +1561,199 @@ function safeInvoiceFilename(name, fallback = "factura") {
|
|
|
1478
1561
|
return clean || fallback;
|
|
1479
1562
|
}
|
|
1480
1563
|
|
|
1564
|
+
// src/subjects.ts
|
|
1565
|
+
var MIN_SUBJECT_YEAR = 1900;
|
|
1566
|
+
var MAX_SUBJECT_YEAR = 2100;
|
|
1567
|
+
var MAX_VALUE_LENGTH = 80;
|
|
1568
|
+
var MAX_LABEL_LENGTH = 120;
|
|
1569
|
+
var MAX_FIT_KEY_LENGTH = 100;
|
|
1570
|
+
var isPresent = (v) => v !== null && v !== void 0 && v !== "";
|
|
1571
|
+
var asYear = (v) => {
|
|
1572
|
+
const n = typeof v === "number" ? v : typeof v === "string" && /^\s*\d+\s*$/.test(v) ? Number(v) : NaN;
|
|
1573
|
+
return Number.isInteger(n) && n >= MIN_SUBJECT_YEAR && n <= MAX_SUBJECT_YEAR ? n : null;
|
|
1574
|
+
};
|
|
1575
|
+
var cleanText = (v, max) => {
|
|
1576
|
+
if (typeof v !== "string") return null;
|
|
1577
|
+
const s = v.split(/\s+/).filter(Boolean).join(" ");
|
|
1578
|
+
return [...s].length > max || /[\u0000-\u001f\u007f-\u009f]/.test(s) ? null : s;
|
|
1579
|
+
};
|
|
1580
|
+
var slug = (s) => s.toLowerCase().replace(/[^a-z0-9._+-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1581
|
+
function coversYear(node, year) {
|
|
1582
|
+
if (node.ranges && node.ranges.length > 0) return node.ranges.some(([a, b]) => year >= a && year <= b);
|
|
1583
|
+
if (node.from !== void 0 && year < node.from) return false;
|
|
1584
|
+
if (node.to !== void 0 && year > node.to) return false;
|
|
1585
|
+
return true;
|
|
1586
|
+
}
|
|
1587
|
+
var declaresYears = (n) => n.from !== void 0 || n.to !== void 0 || (n.ranges?.length ?? 0) > 0;
|
|
1588
|
+
function subjectLevels(kind) {
|
|
1589
|
+
return kind.fields.filter((f) => f.source === "catalog" && f.type !== "year");
|
|
1590
|
+
}
|
|
1591
|
+
function subjectFields(kind) {
|
|
1592
|
+
return kind.fields;
|
|
1593
|
+
}
|
|
1594
|
+
function walk(kind, values) {
|
|
1595
|
+
const path = [];
|
|
1596
|
+
const ids = {};
|
|
1597
|
+
let tree = kind.catalog?.tree;
|
|
1598
|
+
for (const f of subjectLevels(kind)) {
|
|
1599
|
+
const raw = values[f.key];
|
|
1600
|
+
const s = isPresent(raw) ? cleanText(raw, MAX_VALUE_LENGTH) : null;
|
|
1601
|
+
const node = s && tree ? tree[s] ?? tree[s.toLowerCase()] : void 0;
|
|
1602
|
+
if (!s || !node) return { path, ids, next: tree };
|
|
1603
|
+
ids[f.key] = tree && tree[s] ? s : s.toLowerCase();
|
|
1604
|
+
path.push(node);
|
|
1605
|
+
tree = node.children;
|
|
1606
|
+
if (!tree) return { path, ids, next: void 0 };
|
|
1607
|
+
}
|
|
1608
|
+
return { path, ids, next: tree };
|
|
1609
|
+
}
|
|
1610
|
+
var byLabel = (a, b) => a.label.localeCompare(b.label, void 0, { sensitivity: "base", numeric: true });
|
|
1611
|
+
function subjectOptions(kind, fieldKey, values) {
|
|
1612
|
+
const field = kind.fields.find((f) => f.key === fieldKey);
|
|
1613
|
+
if (!field || field.source !== "catalog" || !kind.catalog) return [];
|
|
1614
|
+
if (field.type === "year") {
|
|
1615
|
+
const upto = kind.fields.slice(0, kind.fields.indexOf(field));
|
|
1616
|
+
const { path: path2 } = walk({ ...kind, fields: upto }, values);
|
|
1617
|
+
const declared = path2.filter(declaresYears);
|
|
1618
|
+
if (declared.length === 0) return [];
|
|
1619
|
+
let lo = Infinity;
|
|
1620
|
+
let hi = -Infinity;
|
|
1621
|
+
for (const n of declared) {
|
|
1622
|
+
for (const [a, b] of n.ranges?.length ? n.ranges : [[n.from ?? MIN_SUBJECT_YEAR, n.to ?? MAX_SUBJECT_YEAR]]) {
|
|
1623
|
+
lo = Math.min(lo, a);
|
|
1624
|
+
hi = Math.max(hi, b);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
const out = [];
|
|
1628
|
+
for (let y = Math.min(hi, MAX_SUBJECT_YEAR); y >= Math.max(lo, MIN_SUBJECT_YEAR); y--) if (declared.every((n) => coversYear(n, y))) out.push({ value: String(y), label: String(y) });
|
|
1629
|
+
return out;
|
|
1630
|
+
}
|
|
1631
|
+
const levels = subjectLevels(kind);
|
|
1632
|
+
const at = levels.findIndex((f) => f.key === fieldKey);
|
|
1633
|
+
if (at < 0) return [];
|
|
1634
|
+
const before = Object.fromEntries(levels.slice(0, at).map((f) => [f.key, values[f.key]]));
|
|
1635
|
+
const { path, next } = walk({ ...kind, fields: kind.fields.filter((f) => levels.slice(0, at).includes(f) || f.type === "year") }, before);
|
|
1636
|
+
if (path.length < at || !next) return [];
|
|
1637
|
+
const year = asYear(values[kind.fields.find((f) => f.type === "year" && f.source === "catalog")?.key ?? ""]);
|
|
1638
|
+
return Object.entries(next).filter(([, n]) => year === null || coversYear(n, year)).map(([value, n]) => ({ value, label: n.label })).sort(byLabel);
|
|
1639
|
+
}
|
|
1640
|
+
function reconcileSubjectValues(kind, values) {
|
|
1641
|
+
const out = { ...values };
|
|
1642
|
+
for (const f of kind.fields) {
|
|
1643
|
+
if (f.source !== "catalog" || !isPresent(out[f.key])) continue;
|
|
1644
|
+
const options = subjectOptions(kind, f.key, out);
|
|
1645
|
+
const v = String(out[f.key]);
|
|
1646
|
+
const ok = f.type === "year" ? options.length === 0 || options.some((o) => o.value === v) : options.some((o) => o.value === v || o.value === v.toLowerCase());
|
|
1647
|
+
if (!ok) out[f.key] = "";
|
|
1648
|
+
}
|
|
1649
|
+
return out;
|
|
1650
|
+
}
|
|
1651
|
+
function resolveSubject(kind, values) {
|
|
1652
|
+
const problems = {};
|
|
1653
|
+
const known = new Set(kind.fields.map((f) => f.key));
|
|
1654
|
+
for (const key2 of Object.keys(values)) if (isPresent(values[key2]) && !known.has(key2)) problems[key2] = "unknown";
|
|
1655
|
+
const attributes = {};
|
|
1656
|
+
const priv = {};
|
|
1657
|
+
const display = {};
|
|
1658
|
+
const ids = {};
|
|
1659
|
+
const path = [];
|
|
1660
|
+
let tree = kind.catalog?.tree;
|
|
1661
|
+
const years = [];
|
|
1662
|
+
const put = (f, v) => {
|
|
1663
|
+
if (f.private) priv[f.key] = String(v);
|
|
1664
|
+
else attributes[f.key] = v;
|
|
1665
|
+
};
|
|
1666
|
+
for (const f of kind.fields) {
|
|
1667
|
+
const raw = values[f.key];
|
|
1668
|
+
if (!isPresent(raw)) {
|
|
1669
|
+
if (f.required) problems[f.key] = "required";
|
|
1670
|
+
if (f.source === "catalog" && f.type !== "year") tree = void 0;
|
|
1671
|
+
continue;
|
|
1672
|
+
}
|
|
1673
|
+
const max = f.max ?? MAX_VALUE_LENGTH;
|
|
1674
|
+
if (f.type === "year") {
|
|
1675
|
+
const y = asYear(raw);
|
|
1676
|
+
if (y === null) {
|
|
1677
|
+
problems[f.key] = "invalid";
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
put(f, y);
|
|
1681
|
+
display[f.key] = ids[f.key] = String(y);
|
|
1682
|
+
if (f.source === "catalog") years.push(f.key);
|
|
1683
|
+
} else if (f.source === "catalog") {
|
|
1684
|
+
if (!kind.catalog) {
|
|
1685
|
+
problems[f.key] = "catalog_unavailable";
|
|
1686
|
+
continue;
|
|
1687
|
+
}
|
|
1688
|
+
const s = cleanText(raw, max);
|
|
1689
|
+
if (s === null) {
|
|
1690
|
+
problems[f.key] = "invalid";
|
|
1691
|
+
continue;
|
|
1692
|
+
}
|
|
1693
|
+
const node = tree?.[s] ?? tree?.[s.toLowerCase()];
|
|
1694
|
+
if (!node) {
|
|
1695
|
+
problems[f.key] = "not_in_catalog";
|
|
1696
|
+
continue;
|
|
1697
|
+
}
|
|
1698
|
+
const id = tree?.[s] ? s : s.toLowerCase();
|
|
1699
|
+
path.push(node);
|
|
1700
|
+
tree = node.children;
|
|
1701
|
+
put(f, id);
|
|
1702
|
+
display[f.key] = node.label;
|
|
1703
|
+
ids[f.key] = id;
|
|
1704
|
+
} else {
|
|
1705
|
+
const s = cleanText(raw, max);
|
|
1706
|
+
if (s === null) {
|
|
1707
|
+
problems[f.key] = "invalid";
|
|
1708
|
+
continue;
|
|
1709
|
+
}
|
|
1710
|
+
put(f, s);
|
|
1711
|
+
display[f.key] = s;
|
|
1712
|
+
ids[f.key] = slug(s);
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
for (const key2 of years) {
|
|
1716
|
+
const y = attributes[key2];
|
|
1717
|
+
if (y !== void 0 && !problems[key2] && !path.every((n) => coversYear(n, y))) problems[key2] = "year_range";
|
|
1718
|
+
}
|
|
1719
|
+
if (Object.keys(problems).length > 0) return { ok: false, problems };
|
|
1720
|
+
const label = [...kind.fields.filter((f) => !f.private).map((f) => display[f.key]).filter(Boolean).join(" ")].slice(0, MAX_LABEL_LENGTH).join("").trim();
|
|
1721
|
+
if (!label) return { ok: false, problems: { _: "required" } };
|
|
1722
|
+
let complete = true;
|
|
1723
|
+
const key = kind.fit_key_template.replace(/\{([a-z][a-z0-9_]*)\}/g, (_m, name) => {
|
|
1724
|
+
const id = ids[name];
|
|
1725
|
+
if (!id) complete = false;
|
|
1726
|
+
return id ?? "";
|
|
1727
|
+
});
|
|
1728
|
+
return { ok: true, subject: { label, fit_key: complete && key.length <= MAX_FIT_KEY_LENGTH ? key.toLowerCase() : "", attributes, private: priv } };
|
|
1729
|
+
}
|
|
1730
|
+
var PRIVATE_MASK = "\u2022\u2022";
|
|
1731
|
+
var isMasked = (v) => typeof v === "string" && v.startsWith(PRIVATE_MASK);
|
|
1732
|
+
var DEFAULT_FIT_TAG_PREFIX = "fit:";
|
|
1733
|
+
var fitTag = (fitKey, prefix = DEFAULT_FIT_TAG_PREFIX) => `${prefix}${fitKey}`;
|
|
1734
|
+
function fitTagsAny(fitKey, opts = {}) {
|
|
1735
|
+
if (!fitKey) return [];
|
|
1736
|
+
const prefix = opts.prefix ?? DEFAULT_FIT_TAG_PREFIX;
|
|
1737
|
+
return opts.universal === false ? [fitTag(fitKey, prefix)] : [fitTag(fitKey, prefix), `${prefix}universal`];
|
|
1738
|
+
}
|
|
1739
|
+
var SUBJECT_CATALOG_PAGE_BYTES = 28 * 1024;
|
|
1740
|
+
var utf8Bytes = (s) => new TextEncoder().encode(s).length;
|
|
1741
|
+
function splitSubjectTree(tree, maxBytes = SUBJECT_CATALOG_PAGE_BYTES) {
|
|
1742
|
+
const size = (part) => utf8Bytes(JSON.stringify(JSON.stringify(part)));
|
|
1743
|
+
const parts = [];
|
|
1744
|
+
let current = {};
|
|
1745
|
+
for (const [id, node] of Object.entries(tree)) {
|
|
1746
|
+
if (size({ [id]: node }) > maxBytes) throw new RangeError(`splitSubjectTree: option ${id} alone exceeds ${maxBytes} bytes`);
|
|
1747
|
+
const next = { ...current, [id]: node };
|
|
1748
|
+
if (Object.keys(current).length > 0 && size(next) > maxBytes) {
|
|
1749
|
+
parts.push(current);
|
|
1750
|
+
current = { [id]: node };
|
|
1751
|
+
} else current = next;
|
|
1752
|
+
}
|
|
1753
|
+
if (Object.keys(current).length > 0) parts.push(current);
|
|
1754
|
+
return parts;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1481
1757
|
// src/delivery.ts
|
|
1482
1758
|
function parseDelivery(value) {
|
|
1483
1759
|
const raw = (value ?? "").trim();
|
|
@@ -1506,11 +1782,16 @@ function deliveryNotices(delivery) {
|
|
|
1506
1782
|
|
|
1507
1783
|
exports.CLIENT_IP_HEADER = CLIENT_IP_HEADER;
|
|
1508
1784
|
exports.COUNTRY_HEADERS = COUNTRY_HEADERS;
|
|
1785
|
+
exports.DEFAULT_FIT_TAG_PREFIX = DEFAULT_FIT_TAG_PREFIX;
|
|
1786
|
+
exports.MAX_SUBJECT_YEAR = MAX_SUBJECT_YEAR;
|
|
1787
|
+
exports.MIN_SUBJECT_YEAR = MIN_SUBJECT_YEAR;
|
|
1509
1788
|
exports.MISSING_WEIGHT = MISSING_WEIGHT;
|
|
1510
1789
|
exports.NOTE_MAX_LENGTH = NOTE_MAX_LENGTH;
|
|
1511
1790
|
exports.PAYMENT_CHOICE_REFUSED_FIELD = PAYMENT_CHOICE_REFUSED_FIELD;
|
|
1512
1791
|
exports.PICKUP_STEPS = PICKUP_STEPS;
|
|
1792
|
+
exports.PRIVATE_MASK = PRIVATE_MASK;
|
|
1513
1793
|
exports.SHIPPING_STEPS = SHIPPING_STEPS;
|
|
1794
|
+
exports.SUBJECT_CATALOG_PAGE_BYTES = SUBJECT_CATALOG_PAGE_BYTES;
|
|
1514
1795
|
exports.StorefrontError = StorefrontError;
|
|
1515
1796
|
exports.appendParams = appendParams;
|
|
1516
1797
|
exports.availabilityLocale = availabilityLocale;
|
|
@@ -1519,12 +1800,16 @@ exports.availabilityView = availabilityView;
|
|
|
1519
1800
|
exports.cartLineProblemView = cartLineProblemView;
|
|
1520
1801
|
exports.clampPercent = clampPercent;
|
|
1521
1802
|
exports.classifyPaymentError = classifyPaymentError;
|
|
1803
|
+
exports.coversYear = coversYear;
|
|
1522
1804
|
exports.createStorefrontClient = createStorefrontClient;
|
|
1805
|
+
exports.dataExportBytes = dataExportBytes;
|
|
1523
1806
|
exports.declineMessage = declineMessage;
|
|
1524
1807
|
exports.declineMessageKey = declineMessageKey;
|
|
1525
1808
|
exports.deliveryInput = deliveryInput;
|
|
1526
1809
|
exports.deliveryNotices = deliveryNotices;
|
|
1527
1810
|
exports.diagnose = diagnose;
|
|
1811
|
+
exports.fitTag = fitTag;
|
|
1812
|
+
exports.fitTagsAny = fitTagsAny;
|
|
1528
1813
|
exports.formatAvailabilityMessage = formatAvailabilityMessage;
|
|
1529
1814
|
exports.formatMoney = formatMoney;
|
|
1530
1815
|
exports.formatVoucherExpiry = formatVoucherExpiry;
|
|
@@ -1532,6 +1817,9 @@ exports.generateIdempotencyKey = generateIdempotencyKey;
|
|
|
1532
1817
|
exports.groupInvoiceDocs = groupInvoiceDocs;
|
|
1533
1818
|
exports.hreflangLinks = hreflangLinks;
|
|
1534
1819
|
exports.invoiceFileBytes = invoiceFileBytes;
|
|
1820
|
+
exports.isAccountDeleteBlocked = isAccountDeleteBlocked;
|
|
1821
|
+
exports.isMasked = isMasked;
|
|
1822
|
+
exports.isReauthRequired = isReauthRequired;
|
|
1535
1823
|
exports.isStorefrontError = isStorefrontError;
|
|
1536
1824
|
exports.isTestInvoice = isTestInvoice;
|
|
1537
1825
|
exports.isTestShipment = isTestShipment;
|
|
@@ -1556,16 +1844,23 @@ exports.productAvailability = productAvailability;
|
|
|
1556
1844
|
exports.productListQuery = productListQuery;
|
|
1557
1845
|
exports.promoProgressView = promoProgressView;
|
|
1558
1846
|
exports.promotionMessages = promotionMessages;
|
|
1847
|
+
exports.reconcileSubjectValues = reconcileSubjectValues;
|
|
1559
1848
|
exports.repairPath = repairPath;
|
|
1560
1849
|
exports.resolveAvailability = resolveAvailability;
|
|
1850
|
+
exports.resolveSubject = resolveSubject;
|
|
1561
1851
|
exports.rewardLabel = rewardLabel;
|
|
1852
|
+
exports.safeExportFilename = safeExportFilename;
|
|
1562
1853
|
exports.safeHttpsUrl = safeHttpsUrl;
|
|
1563
1854
|
exports.safeInvoiceFilename = safeInvoiceFilename;
|
|
1564
1855
|
exports.safeTrackingUrl = safeTrackingUrl;
|
|
1565
1856
|
exports.schemaAvailability = schemaAvailability;
|
|
1566
1857
|
exports.shipmentsStatus = shipmentsStatus;
|
|
1567
1858
|
exports.sortTrackingEvents = sortTrackingEvents;
|
|
1859
|
+
exports.splitSubjectTree = splitSubjectTree;
|
|
1568
1860
|
exports.storefrontDomainHeader = storefrontDomainHeader;
|
|
1861
|
+
exports.subjectFields = subjectFields;
|
|
1862
|
+
exports.subjectLevels = subjectLevels;
|
|
1863
|
+
exports.subjectOptions = subjectOptions;
|
|
1569
1864
|
exports.suggestMarket = suggestMarket;
|
|
1570
1865
|
exports.toMoney = toMoney;
|
|
1571
1866
|
exports.visitorCountry = visitorCountry;
|