@tokenoftrust/storefront-runner 4.6.1 → 4.6.3

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.
@@ -1,7 +1,7 @@
1
1
  export const SKU_MAX_LENGTH: number;
2
2
  export const CHECKOUT_CODE_MAX_LENGTH: number;
3
3
  export const SKU_TOKEN_MAX_LENGTH: number;
4
- export type SkuRefusal = "not-string" | "empty" | "control-character" | "too-long";
4
+ export type SkuRefusal = "not-string" | "empty" | "control-character" | "ill-formed" | "too-long";
5
5
  export function parseSku(value: unknown): { ok: true; sku: string } | { ok: false; reason: SkuRefusal };
6
6
  export function isStoredSku(value: unknown): value is string;
7
7
  export function skuKey(sku: string): string;
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * A SKU is merchant data, kept exactly as the merchant wrote it. The only rewrite is trimming
5
5
  * leading and trailing whitespace on the way in. A SKU is refused only when it is empty, carries a
6
- * control character, or is longer than {@link SKU_MAX_LENGTH} characters. Anything else, a space
6
+ * control character, is not well-formed Unicode (a lone UTF-16 surrogate, which has no UTF-8 form
7
+ * and so no token), or is longer than {@link SKU_MAX_LENGTH} characters. Anything else, a space
7
8
  * included, is a valid SKU; a space is a lint warning, never an error.
8
9
  *
9
10
  * Two SKUs are the same SKU when their {@link skuKey} is equal: trimmed, NBSP read as a space, and
@@ -25,6 +26,8 @@ export const CHECKOUT_CODE_MAX_LENGTH = 200;
25
26
  export const SKU_TOKEN_MAX_LENGTH = SKU_MAX_LENGTH * 12;
26
27
 
27
28
  const CONTROL = /\p{Cc}/u;
29
+ /** A lone surrogate: in `u` mode a paired surrogate is one code point and never matches. */
30
+ const LONE_SURROGATE = /\p{Cs}/u;
28
31
  const WHITESPACE = /\s/u;
29
32
  const TOKEN_SAFE = /^[A-Za-z0-9._-]$/;
30
33
  const TOKEN = /^(?:[A-Za-z0-9._-]|%[0-9A-F]{2})+$/;
@@ -33,13 +36,14 @@ const TOKEN = /^(?:[A-Za-z0-9._-]|%[0-9A-F]{2})+$/;
33
36
  * Read a SKU as it arrives from a merchant, a file or an import.
34
37
  *
35
38
  * @param {unknown} value
36
- * @returns {{ ok: true, sku: string } | { ok: false, reason: "not-string" | "empty" | "control-character" | "too-long" }}
39
+ * @returns {{ ok: true, sku: string } | { ok: false, reason: "not-string" | "empty" | "control-character" | "ill-formed" | "too-long" }}
37
40
  */
38
41
  export function parseSku(value) {
39
42
  if (typeof value !== "string") return { ok: false, reason: "not-string" };
40
43
  const sku = value.trim();
41
44
  if (sku === "") return { ok: false, reason: "empty" };
42
45
  if (CONTROL.test(sku)) return { ok: false, reason: "control-character" };
46
+ if (LONE_SURROGATE.test(sku)) return { ok: false, reason: "ill-formed" };
43
47
  if ([...sku].length > SKU_MAX_LENGTH) return { ok: false, reason: "too-long" };
44
48
  return { ok: true, sku };
45
49
  }
@@ -92,6 +96,7 @@ const REASONS = {
92
96
  "not-string": "a SKU must be text",
93
97
  empty: "a SKU cannot be empty",
94
98
  "control-character": "a SKU cannot contain a control character (tab, newline, ...)",
99
+ "ill-formed": "a SKU must be well-formed Unicode text (it contains a broken character)",
95
100
  "too-long": `a SKU is at most ${SKU_MAX_LENGTH} characters`,
96
101
  };
97
102
 
@@ -137,10 +137,15 @@ export interface OrderSyncHealth {
137
137
  detail: string;
138
138
  }
139
139
 
140
- /** The sidebar's order-sync row, from the same source the Orders tab reads. */
140
+ /**
141
+ * The sidebar's order-sync row, from the same source the Orders tab reads. `status` is the ledger
142
+ * read; `null` means that read was unavailable, never that the ledger is healthy. A partner-api
143
+ * source has no ledger status and ignores it.
144
+ */
141
145
  export function orderSyncHealth(source: OrderSource, status: LedgerSyncStatus | null): OrderSyncHealth {
142
146
  if (source.kind === "not-connected") return { value: "Not connected", detail: orderSourceGapMessage(source.gap) };
143
- if (source.kind === "partner-api" || !status) return { value: "Connected", detail: "Reads this store's checkout orders." };
147
+ if (source.kind === "partner-api") return { value: "Connected", detail: "Reads this store's checkout orders." };
148
+ if (!status) return { value: "Check", detail: "Order sync status could not be read. Reload to try again." };
144
149
  if (status.unconfirmed.count > 0) {
145
150
  const n = status.unconfirmed.count;
146
151
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "4.6.1",
3
+ "version": "4.6.3",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
6
6
  "packageManager": "pnpm@11.9.0",