platform-types 1.10.688 → 1.10.690

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -103,6 +103,8 @@ __exportStar(require("./storefrontTheme.js"), exports);
103
103
  __exportStar(require("./storeNetwork.js"), exports);
104
104
  __exportStar(require("./storefrontAssets.js"), exports);
105
105
  __exportStar(require("./storefrontEvent.js"), exports);
106
+ __exportStar(require("./storefrontSeo.js"), exports);
107
+ __exportStar(require("./storefrontWebLiteralKeys.js"), exports);
106
108
  __exportStar(require("./subscription.js"), exports);
107
109
  __exportStar(require("./support.js"), exports);
108
110
  __exportStar(require("./terminal.js"), exports);
package/dist/cjs/order.js CHANGED
@@ -344,10 +344,28 @@ exports.orderFulfilmentProgress = orderFulfilmentProgress;
344
344
  * `data.shiftId`. Logged; reconcile the queued sale by hand.
345
345
  * - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
346
346
  * subscription in the store's `currencies`. Logged.
347
- * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent while the store
348
- * has no payment methods at all.
349
- * - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method` names none of
350
- * the store's payment methods.
347
+ * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront/
348
+ * WhatsApp checkout attempted, while the store has no payment methods at
349
+ * all. Storefront checkout carries `data: {}` and refuses before the cart read.
350
+ * - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
351
+ * checkout's `paymentMethod`, names none of the store's payment methods.
352
+ * Storefront checkout carries `data: {}` and refuses before the cart read.
353
+ *
354
+ * Storefront and WhatsApp checkout business refusals. None allocates an order
355
+ * id, redeems a coupon or writes an order; none is logged as an error:
356
+ * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
357
+ * delivery catalogue, including an absent/empty catalogue. `data: {}`;
358
+ * refused before reading the cart.
359
+ * - `ORDER_INVALID_CART` · 400 — the normalized cart has no finite numeric
360
+ * `totals.grandTotal`. `data: {}`; refused before repricing/allocation.
361
+ * - `ORDER_BELOW_MINIMUM_PURCHASE` · 400 — after repricing has confirmed the
362
+ * cart, its grand total is below a finite positive `Number(customer.minBuy)`.
363
+ * Equality passes. `data: OrderBelowMinimumPurchaseData` carries minBuy,
364
+ * grandTotal and the cart display currency, with no currency conversion.
365
+ * - `EMAIL_VERIFICATION_REQUIRED` · 403 — the store requires email verification
366
+ * and the live customer has not verified. No data payload; before cart read.
367
+ * - `ACCOUNT_DISABLED` · 403 — the live customer is disabled. No data payload;
368
+ * before cart read. This is distinct from the staff `CUSTOMER_DISABLED` code.
351
369
  *
352
370
  * Commit-time drawer refusals, on a create whose cash tender books into a
353
371
  * drawer shift. No order committed, but a coupon redeemed before the commit
@@ -552,6 +570,11 @@ exports.ORDER_ERROR_CODES = [
552
570
  'ORDER_CURRENCY_NOT_SUBSCRIBED',
553
571
  'PAYMENT_METHODS_NOT_CONFIGURED',
554
572
  'PAYMENT_METHOD_NOT_FOUND',
573
+ 'DELIVERY_METHOD_NOT_FOUND',
574
+ 'ORDER_BELOW_MINIMUM_PURCHASE',
575
+ 'ORDER_INVALID_CART',
576
+ 'EMAIL_VERIFICATION_REQUIRED',
577
+ 'ACCOUNT_DISABLED',
555
578
  // Commit-time drawer refusals; `CURRENCY_MISMATCH` carries its fields at the body's top level.
556
579
  'CURRENCY_MISMATCH',
557
580
  'SHIFT_NOT_OPEN',
@@ -1,10 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.STOREFRONT_PREVIEW_PROTOCOL_ERRORS = exports.STOREFRONT_PREVIEW_READ_OPERATIONS = exports.STOREFRONT_SOCIAL_HOSTS = exports.STOREFRONT_BENEFIT_ICONS = exports.STOREFRONT_RESERVED_SLUGS = exports.STOREFRONT_CONTACT_FIELDS = exports.STOREFRONT_PROTECTED_BUILTIN_DESTINATIONS = exports.STOREFRONT_BUILTIN_DESTINATIONS = exports.STOREFRONT_SECTION_TYPES = exports.STOREFRONT_DESIGN_LIMITS = void 0;
3
+ exports.STOREFRONT_PREVIEW_PROTOCOL_ERRORS = exports.STOREFRONT_PREVIEW_READ_OPERATIONS = exports.STOREFRONT_BENEFIT_ICONS = exports.STOREFRONT_RESERVED_SLUGS = exports.STOREFRONT_CONTACT_FIELDS = exports.STOREFRONT_PROTECTED_BUILTIN_DESTINATIONS = exports.STOREFRONT_BUILTIN_DESTINATIONS = exports.STOREFRONT_SECTION_TYPES = exports.isStorefrontPageSlug = exports.STOREFRONT_PAGE_SLUG_RE = exports.STOREFRONT_DESIGN_LIMITS = exports.STOREFRONT_SOCIAL_HOSTS = void 0;
4
4
  exports.createStorefrontDesignV1 = createStorefrontDesignV1;
5
5
  exports.parseStorefrontPreviewDocument = parseStorefrontPreviewDocument;
6
6
  exports.parseStorefrontPreviewMessage = parseStorefrontPreviewMessage;
7
7
  exports.acceptStorefrontPreviewMessage = acceptStorefrontPreviewMessage;
8
+ /** The social kinds a contact may link, each to its own hosts; a contact links at most one per kind. */
9
+ exports.STOREFRONT_SOCIAL_HOSTS = {
10
+ instagram: ['instagram.com', 'www.instagram.com'],
11
+ facebook: ['facebook.com', 'www.facebook.com'],
12
+ youtube: ['youtube.com', 'www.youtube.com', 'youtu.be', 'www.youtu.be'],
13
+ tiktok: ['tiktok.com', 'www.tiktok.com'],
14
+ linkedin: ['linkedin.com', 'www.linkedin.com'],
15
+ x: ['x.com', 'www.x.com'],
16
+ };
8
17
  exports.STOREFRONT_DESIGN_LIMITS = {
9
18
  customPages: 20,
10
19
  pageAliases: 20,
@@ -43,9 +52,18 @@ exports.STOREFRONT_DESIGN_LIMITS = {
43
52
  contactAddress: 500,
44
53
  contactNote: 200,
45
54
  contactHours: 14,
46
- contactSocials: 8,
55
+ /** One link per social kind, so the cap is the number of kinds. */
56
+ contactSocials: Object.keys(exports.STOREFRONT_SOCIAL_HOSTS).length,
47
57
  contactEmail: 254,
48
58
  };
59
+ /**
60
+ * A custom page's slug: lowercase ASCII letters, digits and inner hyphens, 1 to
61
+ * `STOREFRONT_DESIGN_LIMITS.slug` characters, starting and ending alphanumeric. The one
62
+ * definition: the api's validators, its page renderer and the edge viewer request read it.
63
+ */
64
+ exports.STOREFRONT_PAGE_SLUG_RE = /^[a-z0-9](?:[a-z0-9-]{0,78}[a-z0-9])?$/;
65
+ const isStorefrontPageSlug = (value) => typeof value === 'string' && exports.STOREFRONT_PAGE_SLUG_RE.test(value);
66
+ exports.isStorefrontPageSlug = isStorefrontPageSlug;
49
67
  exports.STOREFRONT_SECTION_TYPES = [
50
68
  'banner',
51
69
  'imageText',
@@ -124,14 +142,6 @@ exports.STOREFRONT_RESERVED_SLUGS = [
124
142
  'mantenimiento',
125
143
  ];
126
144
  exports.STOREFRONT_BENEFIT_ICONS = ['truck', 'shield', 'credit-card', 'store', 'heart', 'check'];
127
- exports.STOREFRONT_SOCIAL_HOSTS = {
128
- instagram: ['instagram.com', 'www.instagram.com'],
129
- facebook: ['facebook.com', 'www.facebook.com'],
130
- youtube: ['youtube.com', 'www.youtube.com', 'youtu.be', 'www.youtu.be'],
131
- tiktok: ['tiktok.com', 'www.tiktok.com'],
132
- linkedin: ['linkedin.com', 'www.linkedin.com'],
133
- x: ['x.com', 'www.x.com'],
134
- };
135
145
  function createStorefrontDesignV1() {
136
146
  return {
137
147
  schemaVersion: 1,
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * Information-page paths and the storefront's SEO inheritance chain — one
4
+ * definition for the server that renders a shared link's head and the editor
5
+ * that previews it.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.storefrontDefaultSeoDescription = exports.storefrontPagePath = exports.STOREFRONT_PAGE_PATH_PREFIX = void 0;
9
+ exports.resolveStorefrontSeo = resolveStorefrontSeo;
10
+ /** Path prefix of a published information page: `/pagina/<slug>`. */
11
+ exports.STOREFRONT_PAGE_PATH_PREFIX = '/pagina/';
12
+ /** The path an information page with `slug` is served at. The slug is neither validated nor encoded here. */
13
+ const storefrontPagePath = (slug) => `${exports.STOREFRONT_PAGE_PATH_PREFIX}${slug}`;
14
+ exports.storefrontPagePath = storefrontPagePath;
15
+ /** The description a shop is shared with when neither the page nor the shop sets one. */
16
+ const storefrontDefaultSeoDescription = (storeName) => `Comprá online en ${storeName}: catálogo, precios y stock actualizados.`;
17
+ exports.storefrontDefaultSeoDescription = storefrontDefaultSeoDescription;
18
+ const shopImage = (document) => {
19
+ if (document.seo.image)
20
+ return { image: document.seo.image, source: 'shop' };
21
+ if (document.branding.logo)
22
+ return { image: document.branding.logo, source: 'logo' };
23
+ return { image: null, source: 'default' };
24
+ };
25
+ /** Home's SEO — and the default every information page inherits field by field. */
26
+ const shopSeo = (document, storeName) => {
27
+ const { seo } = document;
28
+ const image = shopImage(document);
29
+ return {
30
+ title: seo.title || storeName,
31
+ description: seo.description || (0, exports.storefrontDefaultSeoDescription)(storeName),
32
+ image: image.image,
33
+ noindex: seo.noindex === true,
34
+ source: {
35
+ title: seo.title ? 'shop' : 'default',
36
+ description: seo.description ? 'shop' : 'default',
37
+ image: image.source,
38
+ noindex: typeof seo.noindex === 'boolean' ? 'shop' : 'default',
39
+ },
40
+ };
41
+ };
42
+ function resolveStorefrontSeo(document, target, storeName) {
43
+ const shop = shopSeo(document, storeName);
44
+ if (target === 'home')
45
+ return shop;
46
+ const page = document.pages.find(({ id }) => id === target);
47
+ if (!page)
48
+ return undefined;
49
+ const own = page.seo;
50
+ const pageTitle = own?.title || page.title;
51
+ const pageNoindex = own?.noindex;
52
+ return {
53
+ title: pageTitle || shop.title,
54
+ description: own?.description || shop.description,
55
+ image: own?.image || shop.image,
56
+ noindex: typeof pageNoindex === 'boolean' ? pageNoindex : shop.noindex,
57
+ source: {
58
+ title: pageTitle ? 'page' : shop.source.title,
59
+ description: own?.description ? 'page' : shop.source.description,
60
+ image: own?.image ? 'page' : shop.source.image,
61
+ noindex: typeof pageNoindex === 'boolean' ? 'page' : shop.source.noindex,
62
+ },
63
+ };
64
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveStorefrontTheme = exports.storefrontContrastRatio = void 0;
3
+ exports.resolveStorefrontTheme = exports.resolveStorefrontEffectiveSettings = exports.storefrontGlobalSettingsLayer = exports.storefrontContrastRatio = void 0;
4
4
  const storefrontDesignRegistry_ts_1 = require("./storefrontDesignRegistry.js");
5
5
  const channels = (color) => [
6
6
  Number.parseInt(color.slice(1, 3), 16),
@@ -66,14 +66,38 @@ const surfaceTokens = (background, settings, mode, surface, warnings) => {
66
66
  };
67
67
  };
68
68
  /**
69
- * The storefront theme for a design's settings overrides.
70
- *
71
- * Settings resolve from the registry defaults plus the store's own design
72
- * overrides ONLY — no GLOBAL or WEB layer takes part — so a consumer uses this
73
- * as shipped rather than merging layers of its own first.
69
+ * The GLOBAL design-settings layer of the platform globals row as `getPlatformGlobalsRow`
70
+ * returns it (`{ [key]: { value, ... } }`): each entry's `value`, kept only when it is a
71
+ * valid design setting, so a non-design global or a malformed value never reaches a theme.
74
72
  */
75
- const resolveStorefrontTheme = (overrides = {}) => {
76
- const settings = (0, storefrontDesignRegistry_ts_1.resolveStorefrontDesignSettings)(overrides);
73
+ const storefrontGlobalSettingsLayer = (globalsRow) => ({
74
+ layer: 'GLOBAL',
75
+ values: Object.fromEntries(Object.entries(globalsRow ?? {}).flatMap(([key, entry]) => {
76
+ const value = entry !== null && typeof entry === 'object' ? entry.value : undefined;
77
+ return (0, storefrontDesignRegistry_ts_1.validateStorefrontDesignSetting)(key, value) ? [[key, value]] : [];
78
+ })),
79
+ });
80
+ exports.storefrontGlobalSettingsLayer = storefrontGlobalSettingsLayer;
81
+ /**
82
+ * The settings a storefront is served with: registry defaults, then the platform GLOBAL
83
+ * layer, then the design's own overrides. The one resolver behind the public envelope's
84
+ * `effectiveSettings`, the draft's `effectiveSettings` and the publish contrast report —
85
+ * a caller passes the globals row it read, never a layer stack of its own. The edge
86
+ * renderer's `theme-color` is design-only: its role reads no GLOBALS row.
87
+ */
88
+ const resolveStorefrontEffectiveSettings = (overrides = {}, globalsRow) => (0, storefrontDesignRegistry_ts_1.resolveStorefrontDesignSettings)(overrides, [(0, exports.storefrontGlobalSettingsLayer)(globalsRow)]);
89
+ exports.resolveStorefrontEffectiveSettings = resolveStorefrontEffectiveSettings;
90
+ /**
91
+ * The storefront theme for a design's settings overrides, resolved through
92
+ * `resolveStorefrontEffectiveSettings`: the GLOBAL layer of `globalsRow` sits under the
93
+ * design, exactly as in the public envelope's `effectiveSettings`. Omitting `globalsRow`
94
+ * resolves defaults plus the design only — correct solely while no GLOBAL design setting
95
+ * is set, so a caller serving or reporting on a storefront passes the row (the edge
96
+ * renderer's `theme-color` is the one exception, design-only by its read grant). Passing
97
+ * already-effective settings as `overrides` rebuilds the same theme.
98
+ */
99
+ const resolveStorefrontTheme = (overrides = {}, globalsRow) => {
100
+ const settings = (0, exports.resolveStorefrontEffectiveSettings)(overrides, globalsRow);
77
101
  const warnings = [];
78
102
  const makeMode = (mode) => {
79
103
  const background = (requested) => mode === 'light' ? requested.toUpperCase() : mix(requested, '#000000', 0.9);