@numueg/theme-sdk 0.10.1 → 0.13.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/CHANGELOG.md CHANGED
@@ -4,6 +4,145 @@ All notable changes to `@numueg/theme-sdk` are documented here. The format is ba
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.13.0] - unreleased
8
+
9
+ Cart-level offer visibility and the platform promotion primitives. Purely
10
+ **additive** — no removals versus 0.12.0.
11
+
12
+ Background: automatic promotions priced the cart correctly at checkout but
13
+ were invisible in the cart itself — the backend cart response carried no
14
+ discount fields, the host's adapter whitelisted them out, and this `Cart` type
15
+ had nowhere to put them. A shopper who qualified for an offer saw the full
16
+ price and only learned about the discount one step later, which is precisely
17
+ when it can no longer motivate the purchase that unlocks it. For an AOV
18
+ mechanic, the cart display *is* the feature.
19
+
20
+ ### Added
21
+
22
+ - **`Cart.applied_promotions`** — `{id, title, title_ar?, amount}[]`, the same
23
+ shape as `Order.applied_promotions`, so one component renders the cart, the
24
+ checkout summary and the order. Plus **`Cart.automatic_discount_cents`**.
25
+ ⚠️ Unlike the identically-named field on `Order`, these amounts reach a theme
26
+ in **MAJOR units** — `normalizeCartFromServer` converts them alongside
27
+ `subtotal` / `total` / `discount_amount`. Do not divide by 100 again.
28
+ - **`useActivePromotions(page?, locale?)`** — typed read of the host proxy
29
+ `GET /api/storefront/promotions`. SSR-safe (resolves on hydrate), returns
30
+ `null` on any miss so an offer surface disappears rather than breaking its
31
+ page. Built on `useCachedResource`, so several sections share one request.
32
+ - **`multibuyOffers(promotions)`** — pulls well-formed "any N for a fixed
33
+ total P" offers out of the feed. Malformed rules and unknown kinds are
34
+ skipped, never thrown on: a theme built before a rule kind existed keeps
35
+ rendering when a merchant starts using it.
36
+ - **`offerProgress(offer, cart, eligibleUnits?)`** → `{unitsInCart,
37
+ unitsNeeded, groupsUnlocked, savingMajor}`. Counts UNITS not lines (three of
38
+ one product is a valid trio, as the engine scores it). `savingMajor` is read
39
+ from the engine's `cart.applied_promotions` — never recomputed, so the theme
40
+ can't drift from the charged amount. Pass `eligibleUnits` for scoped offers;
41
+ only the server knows which products are in the targeted set.
42
+ - **`offerBeatsRegularPrice(offer, unitPriceMajor)`** — guard for PDP offer
43
+ pills: don't advertise a bundle that costs more than buying the items
44
+ outright (the engine refuses to apply it either).
45
+ - Types `ActivePromotion`, `ActivePromotionsPayload`, `DiscountRule`,
46
+ `DiscountTier`, `MultibuyOffer`, `OfferProgress`. (Money conversion reuses
47
+ the existing `centsToMajor` from `utils/money` — one converter, not two.)
48
+
49
+ `DiscountRule.kind` is an open string union on purpose so new platform rule
50
+ kinds don't require an SDK bump to be tolerated.
51
+
52
+ ### Deploy order (federation)
53
+
54
+ Themes are federated: a theme bundle importing an export the host's runtime
55
+ SDK doesn't serve yet fails at ESM link time and the theme does not mount.
56
+ Publish this SDK → rebuild + deploy the storefront runtime → verify
57
+ `/__numu-runtime/` serves it → only then ship theme bundles that import the
58
+ new exports. Never reverse.
59
+
60
+ ## [0.12.0] - unreleased
61
+
62
+ Metafields, blog/article content, and the shared template-resolution engine.
63
+ Purely **additive** at the API surface — 16 new runtime exports, zero removals
64
+ versus 0.10.1 (verified by diffing the published tarball's export list).
65
+
66
+ ### Added
67
+
68
+ - **`useListingHeading(options)`** — resolves the title/subtitle a listing
69
+ (collection / all-products / search) should render, so every theme's product
70
+ grid agrees on the heading source. New types `ListingHeading`,
71
+ `ListingHeadingOptions`.
72
+ - **Template + section-group resolution** — `resolveSections`,
73
+ `selectTemplateSections`, `selectChromeSections`, plus types
74
+ `MaybeOrderedTemplate` and `ResolvedSection`. This is the "no blank page"
75
+ engine that was previously copy-pasted as `_template-utils.ts` into 14
76
+ themes. Headless: it decides WHICH sections render, never how they look.
77
+ - **`useMetafield` / `useMetafields`** — first-class read access to
78
+ merchant-defined typed fields, complementing the dynamic-source binding path
79
+ (`{owner}.metafield:{namespace}.{key}`). Public metafields only. New type
80
+ `MetafieldOwner`.
81
+ - **`useBlogs` / `useBlog` / `useArticles` / `useArticle`** — blog CMS content
82
+ the host resolves into `page.data` for the blogs/blog/article templates. New
83
+ types `BlogSummary`, `ArticleSummary`, `ArticleDetail`. Article bodies are
84
+ UN-sanitized merchant HTML — render through `<RichText>`, never raw
85
+ `dangerouslySetInnerHTML`.
86
+
87
+ ## [0.11.0] - unreleased
88
+
89
+ Superseded by 0.12.0 — never published to npm.
90
+
91
+ ### Added
92
+
93
+ - **`productHref` / `collectionHref`** — storefront route builders. The URL
94
+ shape is platform knowledge, so themes ask for a href instead of hardcoding
95
+ the host's routing. `ProductCard` now uses `productHref` internally, so a
96
+ card and a theme's own links can't disagree about the product route.
97
+ - **Money primitives** — `formatMoney`, `formatMoneyMajor`, `centsToMajor`,
98
+ `majorToCents` and the `FormatMoneyOptions` type. EGP fallback, whole pounds,
99
+ `ar-EG` — matching what the fleet renders today, NOT theme-kit's generic
100
+ USD/2-digit default.
101
+ - **Metafield dynamic sources** — `product.metafield:{ns}.{key}` and
102
+ `collection.metafield:{ns}.{key}` resolve through `resolveSourcePath`; new
103
+ `Metafield` type and `metafields?: Metafield[]` on `Product` / `Collection`.
104
+
105
+ ### Changed
106
+
107
+ - **BREAKING (behaviour, not signature): `applyImageTransform(undefined)` now
108
+ returns `{}` instead of `{ objectFit: fit }`.** An inline style beats a
109
+ className, so the old default silently overrode a placement's own
110
+ `object-contain` / `object-none` class on every UNtransformed image — which
111
+ is most merchant images. The section's className is back in charge; callers
112
+ that need a guaranteed fit supply it themselves, e.g.
113
+ `{ objectFit: fit, ...applyImageTransform(t, fit) }`. `HeroMedia` was updated
114
+ accordingly. The TypeScript signature is unchanged, so this will NOT surface
115
+ as a compile error in a consuming theme.
116
+
117
+ ## [0.10.1] - 2026-07-23
118
+
119
+ Analytics correctness. No API additions or removals (export surface identical
120
+ to 0.10.0).
121
+
122
+ ### Fixed
123
+
124
+ - **`dispatchAnalyticsEvent` mints ONE `event_id` for both channels.** The
125
+ `numu:analytics:event` CustomEvent now carries `detail.event_id` and the
126
+ `/track` POST reuses the same id. The host's Meta/TikTok pixel bridges read
127
+ `detail.event_id`, so theme-fired events dedupe browser-vs-server instead of
128
+ double-counting on both platforms. Previously the CustomEvent had no id at
129
+ all while the POST minted its own.
130
+ - **`CartMutationResult` gains the applied `cart`** (major units, same
131
+ normalization as `useCart().cart`) so callers can read written state without
132
+ racing React state. Absent on failure.
133
+ - **`addItem`'s browser `AddToCart` event includes `value` + `currency`**,
134
+ derived from the written line's snapshot price (variant-aware), making the
135
+ event usable for value-based ad optimization and dynamic ads.
136
+
137
+ ## [0.10.0] - 2026-07-04
138
+
139
+ ### Added
140
+
141
+ - **Soft navigation** — `<Link>` dispatches a cancelable `numu:navigate` event
142
+ so the host can route client-side instead of doing a full document load.
143
+ - **Variant selection registry** — live picker axes act as a `variant_name`
144
+ fallback when a product's variants carry no structured options.
145
+
7
146
  ## [0.9.0] - 2026-07-04
8
147
 
9
148
  Template epic I3 — the SDK side of template overrides + global sections shared
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/validation/index.ts
4
4
  var THEME_CONTRACT_VERSION = 1;
5
- var SDK_VERSION = "0.10.1" ;
5
+ var SDK_VERSION = "0.13.0" ;
6
6
  var REQUIRED_TEMPLATES = [
7
7
  "home",
8
8
  "product",
@@ -404,5 +404,5 @@ exports.validateBuiltManifest = validateBuiltManifest;
404
404
  exports.validateManifest = validateManifest;
405
405
  exports.validateSectionSchema = validateSectionSchema;
406
406
  exports.validateSettingsAgainstSchema = validateSettingsAgainstSchema;
407
- //# sourceMappingURL=chunk-O4GLTNLE.cjs.map
408
- //# sourceMappingURL=chunk-O4GLTNLE.cjs.map
407
+ //# sourceMappingURL=chunk-H7RGDWSU.cjs.map
408
+ //# sourceMappingURL=chunk-H7RGDWSU.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validation/index.ts"],"names":[],"mappings":";;;AAuBO,IAAM,sBAAA,GAAyB;AAI/B,IAAM,WAAA,GAC2B,QAAA;AAsBjC,IAAM,kBAAA,GAAqB;AAAA,EAChC,MAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF;AAEO,IAAM,eAAA,uBAA2C,GAAA,CAAI;AAAA,EAC1D,GAAG,kBAAA;AAAA,EACH,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,mBAAA,uBAA+C,GAAA,CAAI;AAAA,EAC9D,MAAA;AAAA,EAAQ,UAAA;AAAA,EAAY,UAAA;AAAA,EAAY,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,OAAA;AAAA,EAAS,UAAA;AAAA,EAC5D,QAAA;AAAA,EAAU,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,cAAA;AAAA,EAAgB,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,cAAA;AAAA,EAC7D,YAAA;AAAA,EAAc,iBAAA;AAAA,EAAmB,QAAA;AAAA,EAAU,WAAA;AAAA,EAAa,MAAA;AAAA,EAAQ,MAAA;AAAA,EAChE,MAAA;AAAA,EAAQ,cAAA;AAAA,EAAgB,cAAA;AAAA,EAAgB,aAAA;AAAA,EAAe,aAAA;AAAA,EACvD,kBAAA;AAAA,EAAoB,gBAAA;AAAA,EAAkB,aAAA;AAAA,EAAe,aAAA;AAAA,EAAe;AACtE,CAAC;AAGD,IAAM,4BAAA,uBAAwD,GAAA,CAAI;AAAA,EAChE,QAAA;AAAA,EAAU,WAAA;AAAA,EAAa;AACzB,CAAC,CAAA;AAID,IAAM,eAAA,GAAkB,oBAAA;AACxB,IAAM,WAAA,GAAc,+BAAA;AAEpB,IAAM,SAAA,GACJ,0DAAA;AAEF,SAAS,SAAS,CAAA,EAA0C;AAC1D,EAAA,OAAO,OAAO,MAAM,QAAA,IAAY,CAAA,KAAM,QAAQ,CAAC,KAAA,CAAM,QAAQ,CAAC,CAAA;AAChE;AAEA,SAAS,iBAAiB,CAAA,EAAyB;AACjD,EAAA,OAAO,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,CAAE,IAAA,GAAO,MAAA,GAAS,CAAA;AACpD;AAEA,IAAM,WAAN,MAAe;AAAA,EAAf,WAAA,GAAA;AACE,IAAA,IAAA,CAAS,SAA4B,EAAC;AAAA,EAAA;AAAA,EACtC,GAAA,CAAI,IAAA,EAAc,OAAA,EAAiB,IAAA,EAAe;AAChD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EAC1D;AAAA,EACA,IAAA,CAAK,IAAA,EAAc,OAAA,EAAiB,IAAA,EAAe;AACjD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,WAAW,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,EAC5D;AAAA,EACA,MAAA,GAA2B;AACzB,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,CAAC,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,OAAO,CAAA;AAAA,MACnD,QAAQ,IAAA,CAAK;AAAA,KACf;AAAA,EACF;AACF,CAAA;AAGA,SAAS,0BAA0B,QAAA,EAAgD;AACjF,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AACzB,EAAA,IAAI,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG,OAAO,KAAA;AAC/B,EAAA,MAAM,OAAA,GAAU,CAAC,OAAA,CAAQ,SAAA,EAAW,QAAQ,cAAc,CAAA;AAC1D,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG;AACvB,IAAA,KAAA,MAAW,KAAA,IAAS,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA,EAAG;AACzC,MAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG;AACtB,MAAA,MAAM,WAAW,KAAA,CAAM,QAAA;AAEvB,MAAA,MAAM,SAAA,GAAY,KAAA,CAAM,OAAA,CAAQ,QAAQ,CAAA,GACpC,QAAA,GACA,QAAA,CAAS,QAAQ,CAAA,GACf,MAAA,CAAO,MAAA,CAAO,QAAQ,IACtB,EAAC;AACP,MAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,QAAA,IAAI,QAAA,CAAS,IAAI,CAAA,IAAK,gBAAA,CAAiB,IAAA,CAAK,IAAI,CAAA,EAAG,KAAA,CAAM,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA;AAAA,MACxE;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,KAAA;AACT;AAIA,SAAS,mBAAA,CACP,GAAA,EACA,OAAA,EACA,UAAA,EACA,OAAA,EACA;AACA,EAAA,IAAI,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG;AACtB,IAAA,GAAA,CAAI,GAAA,CAAI,wBAAA,EAA0B,4BAAA,EAA8B,UAAU,CAAA;AAC1E,IAAA;AAAA,EACF;AACA,EAAA,MAAM,OAAO,OAAA,CAAQ,IAAA;AACrB,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC3B,IAAA,GAAA,CAAI,GAAA,CAAI,6BAAA,EAA+B,8BAAA,EAAgC,UAAU,CAAA;AAAA,EACnF,CAAA,MAAA,IAAW,CAAC,mBAAA,CAAoB,GAAA,CAAI,IAAI,CAAA,EAAG;AACzC,IAAA,GAAA,CAAI,IAAA;AAAA,MACF,6BAAA;AAAA,MACA,yBAAyB,IAAI,CAAA,uDAAA,CAAA;AAAA,MAC7B;AAAA,KACF;AAAA,EACF;AACA,EAAA,MAAM,iBACJ,gBAAA,CAAiB,IAAI,CAAA,IAAK,4BAAA,CAA6B,IAAI,IAAI,CAAA;AACjE,EAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,IAAA,IAAI,CAAC,gBAAA,CAAiB,OAAA,CAAQ,EAAE,CAAA,EAAG;AACjC,MAAA,GAAA,CAAI,GAAA,CAAI,2BAAA,EAA6B,6BAAA,EAA+B,UAAU,CAAA;AAAA,IAChF,CAAA,MAAO;AACL,MAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AAC3B,QAAA,GAAA,CAAI,GAAA;AAAA,UACF,6BAAA;AAAA,UACA,CAAA,sBAAA,EAAyB,QAAQ,EAAE,CAAA,EAAA,CAAA;AAAA,UACnC;AAAA,SACF;AAAA,MACF;AACA,MAAA,OAAA,CAAQ,GAAA,CAAI,QAAQ,EAAE,CAAA;AAAA,IACxB;AACA,IAAA,IAAI,CAAC,gBAAA,CAAiB,OAAA,CAAQ,KAAK,CAAA,EAAG;AACpC,MAAA,GAAA,CAAI,IAAA,CAAK,8BAAA,EAAgC,yBAAA,EAA2B,UAAU,CAAA;AAAA,IAChF;AAAA,EACF;AAEA,EAAA,IAAI,IAAA,KAAS,QAAA,IAAY,IAAA,KAAS,OAAA,EAAS;AACzC,IAAA,MAAM,UAAU,OAAA,CAAQ,OAAA;AACxB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,WAAW,CAAA,EAAG;AACnD,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,gCAAA;AAAA,QACA,IAAI,IAAI,CAAA,WAAA,EAAc,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAC,CAAA,6CAAA,CAAA;AAAA,QACxC;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,SAAS,OAAA,EAAS;AACpB,IAAA,IAAI,OAAO,OAAA,CAAQ,GAAA,KAAQ,YAAY,OAAO,OAAA,CAAQ,QAAQ,QAAA,EAAU;AACtE,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,6BAAA;AAAA,QACA,CAAA,iBAAA,EAAoB,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAC,CAAA,2CAAA,CAAA;AAAA,QACtC;AAAA,OACF;AAAA,IACF,CAAA,MAAA,IAAW,OAAA,CAAQ,GAAA,IAAO,OAAA,CAAQ,GAAA,EAAK;AACrC,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,4BAAA;AAAA,QACA,CAAA,iBAAA,EAAoB,MAAA,CAAO,OAAA,CAAQ,EAAE,CAAC,CAAA,iBAAA,CAAA;AAAA,QACtC;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACF;AAOO,SAAS,qBAAA,CACd,MAAA,EACA,IAAA,GAAkC,EAAC,EACjB;AAClB,EAAA,MAAM,GAAA,GAAM,IAAI,QAAA,EAAS;AACzB,EAAA,MAAM,QAAQ,IAAA,CAAK,YAAA,GAAe,CAAA,EAAG,IAAA,CAAK,YAAY,CAAA,KAAA,CAAA,GAAU,gBAAA;AAChE,EAAA,IAAI,CAAC,QAAA,CAAS,MAAM,CAAA,EAAG;AACrB,IAAA,GAAA,CAAI,GAAA,CAAI,gBAAA,EAAkB,uCAAA,EAAyC,KAAK,CAAA;AACxE,IAAA,OAAO,IAAI,MAAA,EAAO;AAAA,EACpB;AACA,EAAA,MAAM,OAAO,MAAA,CAAO,IAAA;AACpB,EAAA,IAAI,CAAC,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC3B,IAAA,GAAA,CAAI,GAAA,CAAI,qBAAA,EAAuB,qCAAA,EAAuC,KAAK,CAAA;AAAA,EAC7E,CAAA,MAAO;AACL,IAAA,IAAI,CAAC,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,EAAG;AAC/B,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,oBAAA;AAAA,QACA,CAAA,cAAA,EAAiB,IAAI,CAAA,aAAA,EAAgB,eAAe,CAAA,kCAAA,CAAA;AAAA,QACpD;AAAA,OACF;AAAA,IACF;AACA,IAAA,IAAI,IAAA,CAAK,YAAA,IAAgB,IAAA,KAAS,IAAA,CAAK,YAAA,EAAc;AACnD,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,+BAAA;AAAA,QACA,CAAA,aAAA,EAAgB,IAAI,CAAA,2BAAA,EAA8B,IAAA,CAAK,YAAY,CAAA,gDAAA,CAAA;AAAA,QACnE;AAAA,OACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,IAAI,CAAC,gBAAA,CAAiB,MAAA,CAAO,IAAI,CAAA,EAAG;AAClC,IAAA,GAAA,CAAI,GAAA,CAAI,qBAAA,EAAuB,qCAAA,EAAuC,KAAK,CAAA;AAAA,EAC7E;AACA,EAAA,IAAI,MAAA,CAAO,aAAa,MAAA,EAAW;AACjC,IAAA,GAAA,CAAI,IAAA,CAAK,yBAAA,EAA2B,mCAAA,EAAqC,KAAK,CAAA;AAAA,EAChF,WAAW,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,EAAG;AAC1C,IAAA,GAAA,CAAI,GAAA,CAAI,yBAAA,EAA2B,8BAAA,EAAgC,KAAK,CAAA;AAAA,EAC1E,CAAA,MAAO;AACL,IAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,IAAA,MAAA,CAAO,QAAA,CAAS,OAAA;AAAA,MAAQ,CAAC,CAAA,EAAG,CAAA,KAC1B,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA,UAAA,EAAa,CAAC,CAAA,CAAA,CAAA,EAAK,IAAI;AAAA,KAC7D;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,CAAO,WAAW,MAAA,EAAW;AAC/B,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACjC,MAAA,GAAA,CAAI,GAAA,CAAI,uBAAA,EAAyB,4BAAA,EAA8B,KAAK,CAAA;AAAA,IACtE,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,EAAG,CAAA,KAAM;AAC9B,QAAA,IAAI,CAAC,SAAS,CAAC,CAAA,IAAK,CAAC,gBAAA,CAAiB,CAAA,CAAE,IAAI,CAAA,EAAG;AAC7C,UAAA,GAAA,CAAI,GAAA,CAAI,2BAAA,EAA6B,CAAA,MAAA,EAAS,CAAC,4BAA4B,KAAK,CAAA;AAChF,UAAA;AAAA,QACF;AACA,QAAA,IAAI,CAAC,eAAA,CAAgB,IAAA,CAAK,CAAA,CAAE,IAAI,CAAA,EAAG;AACjC,UAAA,GAAA,CAAI,GAAA;AAAA,YACF,0BAAA;AAAA,YACA,CAAA,YAAA,EAAe,CAAA,CAAE,IAAI,CAAA,aAAA,EAAgB,eAAe,CAAA,CAAA,CAAA;AAAA,YACpD;AAAA,WACF;AAAA,QACF;AACA,QAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,QAAQ,CAAA,EAAG;AAC7B,UAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,UAAA,CAAA,CAAE,QAAA,CAAS,OAAA;AAAA,YAAQ,CAAC,CAAA,EAAG,CAAA,KACrB,mBAAA,CAAoB,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA,QAAA,EAAW,CAAC,CAAA,WAAA,EAAc,CAAC,KAAK,IAAI;AAAA,WAC1E;AAAA,QACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AACA,EAAA,OAAO,IAAI,MAAA,EAAO;AACpB;AAQO,SAAS,6BAAA,CACd,QAAA,EACA,MAAA,EACA,UAAA,GAAa,UAAA,EACK;AAClB,EAAA,MAAM,GAAA,GAAM,IAAI,QAAA,EAAS;AACzB,EAAA,IAAI,CAAC,QAAA,CAAS,QAAQ,CAAA,EAAG;AACvB,IAAA,GAAA,CAAI,GAAA,CAAI,2BAAA,EAA6B,qCAAA,EAAuC,UAAU,CAAA;AACtF,IAAA,OAAO,IAAI,MAAA,EAAO;AAAA,EACpB;AACA,EAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA,GAAI,MAAA,CAAO,WAAW,EAAC;AACjE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA+B;AAChD,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,EAAM,IAAI,gBAAA,CAAiB,CAAA,EAAG,EAAE,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,EAAA,EAAI,CAAC,CAAA;AAEnE,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACnD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AACxB,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,GAAA,CAAI,IAAA;AAAA,QACF,0BAAA;AAAA,QACA,YAAY,GAAG,CAAA,0BAAA,EAA6B,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA,SAAA,CAAA;AAAA,QAC/D,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,GAAG,CAAA;AAAA,OACtB;AACA,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AAC3C,IAAA,MAAM,CAAA,GAAI,CAAA,EAAG,UAAU,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC9B,IAAA,IAAA,CAAK,GAAA,CAAI,IAAA,KAAS,QAAA,IAAY,GAAA,CAAI,IAAA,KAAS,YAAY,KAAA,CAAM,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,EAAG;AACjF,MAAA,MAAM,UAAU,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAC,CAAA,KAAM,EAAE,KAAK,CAAA;AAC9C,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA,EAAG;AACzD,QAAA,GAAA,CAAI,GAAA;AAAA,UACF,iCAAA;AAAA,UACA,CAAA,CAAA,EAAI,GAAG,CAAA,KAAA,EAAQ,KAAK,oBAAoB,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,UAC1D;AAAA,SACF;AAAA,MACF;AAAA,IACF;AACA,IAAA,IAAI,GAAA,CAAI,IAAA,KAAS,OAAA,IAAW,OAAO,UAAU,QAAA,EAAU;AACrD,MAAA,IAAI,OAAO,GAAA,CAAI,GAAA,KAAQ,QAAA,IAAY,KAAA,GAAQ,IAAI,GAAA,EAAK;AAClD,QAAA,GAAA,CAAI,GAAA,CAAI,8BAAA,EAAgC,CAAA,CAAA,EAAI,GAAG,CAAA,IAAA,EAAO,KAAK,CAAA,cAAA,EAAiB,GAAA,CAAI,GAAG,CAAA,CAAA,CAAA,EAAK,CAAC,CAAA;AAAA,MAC3F;AACA,MAAA,IAAI,OAAO,GAAA,CAAI,GAAA,KAAQ,QAAA,IAAY,KAAA,GAAQ,IAAI,GAAA,EAAK;AAClD,QAAA,GAAA,CAAI,GAAA,CAAI,6BAAA,EAA+B,CAAA,CAAA,EAAI,GAAG,CAAA,IAAA,EAAO,KAAK,CAAA,cAAA,EAAiB,GAAA,CAAI,GAAG,CAAA,CAAA,CAAA,EAAK,CAAC,CAAA;AAAA,MAC1F;AAAA,IACF;AACA,IAAA,IAAK,GAAA,CAAI,IAAA,KAAS,UAAA,IAAe,OAAO,UAAU,SAAA,EAAW;AAC3D,MAAA,GAAA,CAAI,IAAA,CAAK,gCAAA,EAAkC,CAAA,CAAA,EAAI,GAAG,0BAA0B,CAAC,CAAA;AAAA,IAC/E;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,SAAS,QAAA,IAAY,GAAA,CAAI,SAAS,OAAA,KAAY,OAAO,UAAU,QAAA,EAAU;AAChF,MAAA,GAAA,CAAI,IAAA,CAAK,gCAAA,EAAkC,CAAA,CAAA,EAAI,GAAG,yBAAyB,CAAC,CAAA;AAAA,IAC9E;AAAA,EACF;AACA,EAAA,OAAO,IAAI,MAAA,EAAO;AACpB;AAKA,SAAS,oBAAA,CAAqB,KAAe,CAAA,EAA4B;AACvE,EAAA,IAAI,CAAC,gBAAA,CAAiB,CAAA,CAAE,EAAE,CAAA,EAAG;AAC3B,IAAA,GAAA,CAAI,GAAA,CAAI,qBAAA,EAAuB,6BAAA,EAA+B,IAAI,CAAA;AAAA,EACpE,WAAW,CAAC,WAAA,CAAY,IAAA,CAAK,CAAA,CAAE,EAAE,CAAA,EAAG;AAClC,IAAA,GAAA,CAAI,GAAA;AAAA,MACF,oBAAA;AAAA,MACA,CAAA,UAAA,EAAa,EAAE,EAAE,CAAA,yFAAA,CAAA;AAAA,MACjB;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,OAAO,CAAA,CAAE,IAAA;AACf,EAAA,MAAM,SACJ,gBAAA,CAAiB,IAAI,CAAA,IACpB,QAAA,CAAS,IAAI,CAAA,IAAK,MAAA,CAAO,MAAA,CAAO,IAAI,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,gBAAA,CAAiB,CAAC,CAAC,CAAA;AACxE,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,GAAA,CAAI,GAAA,CAAI,uBAAA,EAAyB,2CAAA,EAA6C,MAAM,CAAA;AAAA,EACtF;AACA,EAAA,IAAI,CAAC,gBAAA,CAAiB,CAAA,CAAE,OAAO,CAAA,EAAG;AAChC,IAAA,GAAA,CAAI,GAAA,CAAI,0BAAA,EAA4B,kCAAA,EAAoC,SAAS,CAAA;AAAA,EACnF,WAAW,CAAC,SAAA,CAAU,IAAA,CAAK,CAAA,CAAE,OAAO,CAAA,EAAG;AACrC,IAAA,GAAA,CAAI,IAAI,0BAAA,EAA4B,CAAA,SAAA,EAAY,CAAA,CAAE,OAAO,0BAA0B,SAAS,CAAA;AAAA,EAC9F;AACA,EAAA,IAAI,CAAC,gBAAA,CAAiB,CAAA,CAAE,MAAM,CAAA,EAAG;AAC/B,IAAA,GAAA,CAAI,GAAA,CAAI,yBAAA,EAA2B,iCAAA,EAAmC,QAAQ,CAAA;AAAA,EAChF;AACA,EAAA,IAAI,CAAA,CAAE,eAAA,KAAoB,MAAA,IAAa,CAAC,SAAA,CAAU,KAAK,MAAA,CAAO,CAAA,CAAE,eAAe,CAAC,CAAA,EAAG;AACjF,IAAA,GAAA,CAAI,IAAA,CAAK,kCAAA,EAAoC,wCAAA,EAA0C,iBAAiB,CAAA;AAAA,EAC1G;AACF;AAUO,SAAS,gBAAA,CACd,QAAA,EACA,GAAA,GAA8C,EAAC,EAC7B;AAClB,EAAA,MAAM,GAAA,GAAM,IAAI,QAAA,EAAS;AACzB,EAAA,IAAI,CAAC,QAAA,CAAS,QAAQ,CAAA,EAAG;AACvB,IAAA,GAAA,CAAI,GAAA,CAAI,kBAAA,EAAoB,mCAAA,EAAqC,YAAY,CAAA;AAC7E,IAAA,OAAO,IAAI,MAAA,EAAO;AAAA,EACpB;AACA,EAAA,oBAAA,CAAqB,KAAK,QAAQ,CAAA;AAElC,EAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AACzB,EAAA,IAAI,CAAC,SAAS,OAAO,CAAA,IAAK,OAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,KAAW,CAAA,EAAG;AAC3D,IAAA,GAAA,CAAI,IAAA,CAAK,wBAAA,EAA0B,sEAAA,EAAmE,SAAS,CAAA;AAAA,EACjH,CAAA,MAAO;AAEL,IAAA,IAAI,IAAI,YAAA,EAAc;AACpB,MAAA,KAAA,MAAW,IAAA,IAAQ,yBAAA,CAA0B,QAAQ,CAAA,EAAG;AACtD,QAAA,IAAI,CAAC,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG;AAC/B,UAAA,GAAA,CAAI,GAAA;AAAA,YACF,iCAAA;AAAA,YACA,CAAA,gCAAA,EAAmC,IAAI,CAAA,2BAAA,EAA8B,IAAI,CAAA,MAAA,CAAA;AAAA,YACzE;AAAA,WACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,YAAY,QAAA,CAAS,OAAA,CAAQ,SAAS,CAAA,GAAI,OAAA,CAAQ,YAAY,EAAC;AACrE,IAAA,KAAA,MAAW,KAAK,kBAAA,EAAoB;AAClC,MAAA,IAAI,EAAE,KAAK,SAAA,CAAA,EAAY;AACrB,QAAA,GAAA,CAAI,IAAA;AAAA,UACF,2BAAA;AAAA,UACA,oCAAoC,CAAC,CAAA,uDAAA,CAAA;AAAA,UACrC,qBAAqB,CAAC,CAAA;AAAA,SACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAI,MAAA,EAAO;AACpB;AAWO,SAAS,qBAAA,CACd,aAAA,EACA,SAAA,EACA,IAAA,GAAyC,EAAC,EACxB;AAClB,EAAA,MAAM,GAAA,GAAM,IAAI,QAAA,EAAS;AACzB,EAAA,IAAI,CAAC,QAAA,CAAS,aAAa,CAAA,EAAG;AAC5B,IAAA,GAAA,CAAI,GAAA,CAAI,eAAA,EAAiB,sCAAA,EAAwC,eAAe,CAAA;AAChF,IAAA,OAAO,IAAI,MAAA,EAAO;AAAA,EACpB;AACA,EAAA,oBAAA,CAAqB,KAAK,aAAa,CAAA;AAGvC,EAAA,MAAM,UAAU,aAAA,CAAc,eAAA;AAC9B,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAY,QAAA,CAAS,OAAO,CAAA,GAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,GAAI,EAAE,CAAA;AAC7E,EAAA,IAAI,CAAC,QAAA,CAAS,OAAO,CAAA,EAAG;AACtB,IAAA,GAAA,CAAI,IAAA,CAAK,+BAAA,EAAiC,yCAAA,EAA2C,iBAAiB,CAAA;AAAA,EACxG;AACA,EAAA,KAAA,MAAW,IAAA,IAAQ,yBAAA,CAA0B,aAAa,CAAA,EAAG;AAC3D,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACtB,MAAA,GAAA,CAAI,GAAA;AAAA,QACF,8BAAA;AAAA,QACA,mCAAmC,IAAI,CAAA,iCAAA,CAAA;AAAA,QACvC;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,QAAA,CAAS,OAAO,CAAA,EAAG;AACrB,IAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACpD,MAAA,MAAM,IAAI,qBAAA,CAAsB,MAAA,EAAQ,EAAE,YAAA,EAAc,MAAM,CAAA;AAC9D,MAAA,KAAA,MAAW,SAAS,CAAA,CAAE,MAAA,EAAQ,GAAA,CAAI,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACrD;AAAA,EACF;AACA,EAAA,IAAI,CAAC,gBAAA,CAAiB,aAAA,CAAc,cAAc,CAAA,EAAG;AACnD,IAAA,GAAA,CAAI,IAAA,CAAK,8BAAA,EAAgC,wCAAA,EAA0C,gBAAgB,CAAA;AAAA,EACrG;AAGA,EAAA,IAAI,cAAc,MAAA,EAAW;AAC3B,IAAA,IAAI,CAAC,QAAA,CAAS,SAAS,CAAA,EAAG;AACxB,MAAA,GAAA,CAAI,GAAA,CAAI,mBAAA,EAAqB,wCAAA,EAA0C,iBAAiB,CAAA;AAAA,IAC1F,CAAA,MAAO;AACL,MAAA,MAAM,KAAK,SAAA,CAAU,gBAAA;AACrB,MAAA,IAAI,OAAO,OAAO,QAAA,EAAU;AAC1B,QAAA,GAAA,CAAI,IAAA;AAAA,UACF,oCAAA;AAAA,UACA,oFAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF,WACE,OAAO,IAAA,CAAK,wBAAwB,QAAA,IACpC,EAAA,GAAK,KAAK,mBAAA,EACV;AACA,QAAA,GAAA,CAAI,GAAA;AAAA,UACF,yCAAA;AAAA,UACA,CAAA,0BAAA,EAA6B,EAAE,CAAA,gCAAA,EAAmC,IAAA,CAAK,mBAAmB,CAAA,CAAA,CAAA;AAAA,UAC1F;AAAA,SACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,IAAI,MAAA,EAAO;AACpB;AAGO,SAAS,gBAAgB,OAAA,EAA+C;AAC7E,EAAA,MAAM,SAAS,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,EAAE,MAAM,CAAA;AAC9C,EAAA,OAAO,EAAE,KAAA,EAAO,CAAC,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,OAAO,CAAA,EAAG,MAAA,EAAO;AACnE","file":"chunk-O4GLTNLE.cjs","sourcesContent":["/**\n * Shared theme-contract validators — the single source of truth.\n *\n * This module is PURE: it imports only types (erased at compile time) and\n * has no React/DOM/fs dependencies, so the same logic runs in the CLI, the\n * Vite plugin, and (re-implemented) the backend. Callers parse JSON files\n * themselves and pass plain objects in; these functions never touch disk.\n *\n * The goal is that \"builds green\" implies \"matches the contract\": every\n * place a theme can drift from what the storefront expects is checked here\n * once, instead of being re-derived (and drifting) in each tool.\n */\n\nimport type { SectionSchema, SettingDefinition } from \"../types/theme\";\n\n/**\n * The theme CONTRACT version — bumped only on a breaking change to what a\n * built theme must look like (manifest shape, required emitted artifacts,\n * section/setting semantics). The plugin stamps this into the built\n * manifest/import-map; the host refuses bundles whose contract version it\n * doesn't support. Distinct from the npm SDK version (`SDK_VERSION`), which\n * moves on every release including non-breaking ones.\n */\nexport const THEME_CONTRACT_VERSION = 1;\n\n/** npm version of this SDK build (inlined by tsup `define`). Informational. */\ndeclare const __SDK_VERSION__: string | undefined;\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0\";\n\nexport interface ValidationIssue {\n level: \"error\" | \"warning\";\n /** Stable machine code, e.g. \"manifest.version.invalid\". */\n code: string;\n message: string;\n /** Dotted path or file hint, e.g. \"presets.templates.home\" or \"hero.json\". */\n path?: string;\n}\n\nexport interface ValidationResult {\n /** True when there are zero error-level issues. */\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Page templates the storefront routes to. A theme that omits a REQUIRED\n * template still works (the host falls back to its built-in), so a miss is\n * a warning, not an error — but tooling can elevate it with --strict.\n */\nexport const REQUIRED_TEMPLATES = [\n \"home\",\n \"product\",\n \"collection\",\n \"cart\",\n \"page\",\n \"search\",\n \"404\",\n] as const;\n\nexport const KNOWN_TEMPLATES: ReadonlySet<string> = new Set([\n ...REQUIRED_TEMPLATES,\n \"blog\",\n \"article\",\n \"policies\",\n \"password\",\n \"account\",\n \"checkout\",\n]);\n\n/** Setting types the V3 customizer renders. Unknown types warn (forward-compat). */\nexport const KNOWN_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"text\", \"textarea\", \"richtext\", \"number\", \"range\", \"color\", \"checkbox\",\n \"select\", \"radio\", \"font\", \"image_picker\", \"url\", \"product\", \"product_list\",\n \"collection\", \"collection_list\", \"header\", \"paragraph\", \"html\", \"date\",\n \"time\", \"video_picker\", \"color_scheme\", \"page_picker\", \"blog_picker\",\n \"link_list_picker\", \"variant_picker\", \"file_upload\", \"icon_picker\", \"icon\",\n]);\n\n/** Setting types that are presentational (no value) — `id`/`label` optional. */\nconst PRESENTATIONAL_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"header\", \"paragraph\", \"html\",\n]);\n\n// ── Primitives ────────────────────────────────────────────────────\n\nconst SECTION_TYPE_RE = /^[a-z][a-z0-9_-]*$/;\nconst THEME_ID_RE = /^[a-z0-9][a-z0-9_-]*[a-z0-9]$/;\n// Pragmatic semver (major.minor.patch + optional -prerelease / +build).\nconst SEMVER_RE =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-.]+)?(?:\\+[0-9A-Za-z-.]+)?$/;\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.trim().length > 0;\n}\n\nclass IssueBag {\n readonly issues: ValidationIssue[] = [];\n err(code: string, message: string, path?: string) {\n this.issues.push({ level: \"error\", code, message, path });\n }\n warn(code: string, message: string, path?: string) {\n this.issues.push({ level: \"warning\", code, message, path });\n }\n result(): ValidationResult {\n return {\n valid: !this.issues.some((i) => i.level === \"error\"),\n issues: this.issues,\n };\n }\n}\n\n/** Pull the section types referenced by a manifest's presets. */\nfunction collectPresetSectionTypes(manifest: Record<string, unknown>): Set<string> {\n const types = new Set<string>();\n const presets = manifest.presets;\n if (!isObject(presets)) return types;\n const buckets = [presets.templates, presets.section_groups];\n for (const bucket of buckets) {\n if (!isObject(bucket)) continue;\n for (const entry of Object.values(bucket)) {\n if (!isObject(entry)) continue;\n const sections = entry.sections;\n // sections may be an array of instances OR a map id -> instance.\n const instances = Array.isArray(sections)\n ? sections\n : isObject(sections)\n ? Object.values(sections)\n : [];\n for (const inst of instances) {\n if (isObject(inst) && isNonEmptyString(inst.type)) types.add(inst.type);\n }\n }\n }\n return types;\n}\n\n// ── Setting / schema validation ───────────────────────────────────\n\nfunction validateSettingInto(\n bag: IssueBag,\n setting: unknown,\n pathPrefix: string,\n seenIds: Set<string>,\n) {\n if (!isObject(setting)) {\n bag.err(\"schema.setting.invalid\", \"Setting must be an object.\", pathPrefix);\n return;\n }\n const type = setting.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.setting.type.missing\", \"Setting is missing a `type`.\", pathPrefix);\n } else if (!KNOWN_SETTING_TYPES.has(type)) {\n bag.warn(\n \"schema.setting.type.unknown\",\n `Unknown setting type \"${type}\" — the customizer will fall back to a text input.`,\n pathPrefix,\n );\n }\n const presentational =\n isNonEmptyString(type) && PRESENTATIONAL_SETTING_TYPES.has(type);\n if (!presentational) {\n if (!isNonEmptyString(setting.id)) {\n bag.err(\"schema.setting.id.missing\", \"Setting is missing an `id`.\", pathPrefix);\n } else {\n if (seenIds.has(setting.id)) {\n bag.err(\n \"schema.setting.id.duplicate\",\n `Duplicate setting id \"${setting.id}\".`,\n pathPrefix,\n );\n }\n seenIds.add(setting.id);\n }\n if (!isNonEmptyString(setting.label)) {\n bag.warn(\"schema.setting.label.missing\", \"Setting has no `label`.\", pathPrefix);\n }\n }\n // select / radio need options.\n if (type === \"select\" || type === \"radio\") {\n const options = setting.options;\n if (!Array.isArray(options) || options.length === 0) {\n bag.err(\n \"schema.setting.options.missing\",\n `\"${type}\" setting \"${String(setting.id)}\" must declare a non-empty \\`options\\` array.`,\n pathPrefix,\n );\n }\n }\n // range needs bounds.\n if (type === \"range\") {\n if (typeof setting.min !== \"number\" || typeof setting.max !== \"number\") {\n bag.err(\n \"schema.setting.range.bounds\",\n `\"range\" setting \"${String(setting.id)}\" must declare numeric \\`min\\` and \\`max\\`.`,\n pathPrefix,\n );\n } else if (setting.min >= setting.max) {\n bag.err(\n \"schema.setting.range.order\",\n `\"range\" setting \"${String(setting.id)}\" has min >= max.`,\n pathPrefix,\n );\n }\n }\n}\n\n/**\n * Validate one section schema (the parsed schemas/sections/<type>.json).\n * When `filenameType` is given, enforces the component-filename = schema-type\n * convention by requiring `schema.type` to equal it.\n */\nexport function validateSectionSchema(\n schema: unknown,\n opts: { filenameType?: string } = {},\n): ValidationResult {\n const bag = new IssueBag();\n const where = opts.filenameType ? `${opts.filenameType}.json` : \"section schema\";\n if (!isObject(schema)) {\n bag.err(\"schema.invalid\", \"Section schema must be a JSON object.\", where);\n return bag.result();\n }\n const type = schema.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.type.missing\", \"Section schema is missing a `type`.\", where);\n } else {\n if (!SECTION_TYPE_RE.test(type)) {\n bag.err(\n \"schema.type.format\",\n `Section type \"${type}\" must match ${SECTION_TYPE_RE} (lowercase, start with a letter).`,\n where,\n );\n }\n if (opts.filenameType && type !== opts.filenameType) {\n bag.err(\n \"schema.type.filename_mismatch\",\n `Schema type \"${type}\" must equal its filename \"${opts.filenameType}\" (component-filename = schema-type convention).`,\n where,\n );\n }\n }\n if (!isNonEmptyString(schema.name)) {\n bag.err(\"schema.name.missing\", \"Section schema is missing a `name`.\", where);\n }\n if (schema.settings === undefined) {\n bag.warn(\"schema.settings.missing\", \"Section schema has no `settings`.\", where);\n } else if (!Array.isArray(schema.settings)) {\n bag.err(\"schema.settings.invalid\", \"`settings` must be an array.\", where);\n } else {\n const seen = new Set<string>();\n schema.settings.forEach((s, i) =>\n validateSettingInto(bag, s, `${where}.settings[${i}]`, seen),\n );\n }\n // Nested block schemas (shallow — type + settings shape).\n if (schema.blocks !== undefined) {\n if (!Array.isArray(schema.blocks)) {\n bag.err(\"schema.blocks.invalid\", \"`blocks` must be an array.\", where);\n } else {\n schema.blocks.forEach((b, i) => {\n if (!isObject(b) || !isNonEmptyString(b.type)) {\n bag.err(\"schema.block.type.missing\", `Block[${i}] is missing a \\`type\\`.`, where);\n return;\n }\n if (!SECTION_TYPE_RE.test(b.type)) {\n bag.err(\n \"schema.block.type.format\",\n `Block type \"${b.type}\" must match ${SECTION_TYPE_RE}.`,\n where,\n );\n }\n if (Array.isArray(b.settings)) {\n const seen = new Set<string>();\n b.settings.forEach((s, j) =>\n validateSettingInto(bag, s, `${where}.blocks[${i}].settings[${j}]`, seen),\n );\n }\n });\n }\n }\n return bag.result();\n}\n\n/**\n * Instance conformance: check a settings object (from a preset or a merchant\n * customization) against its section schema. Unknown keys warn (harmless at\n * runtime — ignored); invalid values (bad select option, out-of-range,\n * wrong primitive) error.\n */\nexport function validateSettingsAgainstSchema(\n settings: unknown,\n schema: Pick<SectionSchema, \"settings\" | \"type\">,\n pathPrefix = \"settings\",\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(settings)) {\n bag.err(\"instance.settings.invalid\", \"Section settings must be an object.\", pathPrefix);\n return bag.result();\n }\n const defs = Array.isArray(schema.settings) ? schema.settings : [];\n const byId = new Map<string, SettingDefinition>();\n for (const d of defs) if (isNonEmptyString(d?.id)) byId.set(d.id, d);\n\n for (const [key, value] of Object.entries(settings)) {\n const def = byId.get(key);\n if (!def) {\n bag.warn(\n \"instance.setting.unknown\",\n `Setting \"${key}\" is not declared in the \"${String(schema.type)}\" schema.`,\n `${pathPrefix}.${key}`,\n );\n continue;\n }\n if (value === null || value === undefined) continue;\n const p = `${pathPrefix}.${key}`;\n if ((def.type === \"select\" || def.type === \"radio\") && Array.isArray(def.options)) {\n const allowed = def.options.map((o) => o.value);\n if (typeof value === \"string\" && !allowed.includes(value)) {\n bag.err(\n \"instance.setting.option.invalid\",\n `\"${key}\" = \"${value}\" is not one of: ${allowed.join(\", \")}.`,\n p,\n );\n }\n }\n if (def.type === \"range\" && typeof value === \"number\") {\n if (typeof def.min === \"number\" && value < def.min) {\n bag.err(\"instance.setting.range.under\", `\"${key}\" = ${value} is below min ${def.min}.`, p);\n }\n if (typeof def.max === \"number\" && value > def.max) {\n bag.err(\"instance.setting.range.over\", `\"${key}\" = ${value} is above max ${def.max}.`, p);\n }\n }\n if ((def.type === \"checkbox\") && typeof value !== \"boolean\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a boolean.`, p);\n }\n if ((def.type === \"number\" || def.type === \"range\") && typeof value !== \"number\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a number.`, p);\n }\n }\n return bag.result();\n}\n\n// ── Manifest validation ───────────────────────────────────────────\n\n/** Core manifest field checks shared by source (theme.json) and built manifests. */\nfunction validateManifestCore(bag: IssueBag, m: Record<string, unknown>) {\n if (!isNonEmptyString(m.id)) {\n bag.err(\"manifest.id.missing\", \"theme.json is missing `id`.\", \"id\");\n } else if (!THEME_ID_RE.test(m.id)) {\n bag.err(\n \"manifest.id.format\",\n `Theme id \"${m.id}\" must be lowercase alphanumeric with dashes/underscores (no leading/trailing separator).`,\n \"id\",\n );\n }\n // name: string or bilingual object { en|default, ... }.\n const name = m.name;\n const nameOk =\n isNonEmptyString(name) ||\n (isObject(name) && Object.values(name).some((v) => isNonEmptyString(v)));\n if (!nameOk) {\n bag.err(\"manifest.name.missing\", \"theme.json is missing a non-empty `name`.\", \"name\");\n }\n if (!isNonEmptyString(m.version)) {\n bag.err(\"manifest.version.missing\", \"theme.json is missing `version`.\", \"version\");\n } else if (!SEMVER_RE.test(m.version)) {\n bag.err(\"manifest.version.invalid\", `Version \"${m.version}\" is not valid semver.`, \"version\");\n }\n if (!isNonEmptyString(m.author)) {\n bag.err(\"manifest.author.missing\", \"theme.json is missing `author`.\", \"author\");\n }\n if (m.min_sdk_version !== undefined && !SEMVER_RE.test(String(m.min_sdk_version))) {\n bag.warn(\"manifest.min_sdk_version.invalid\", \"`min_sdk_version` is not valid semver.\", \"min_sdk_version\");\n }\n}\n\n/**\n * Validate a source theme manifest (parsed theme.json).\n *\n * `ctx.sectionTypes` — the set of section types the theme actually ships\n * (from schemas/sections/*.json). When provided, every section type\n * referenced by a preset must be present, and missing required templates\n * are surfaced as warnings.\n */\nexport function validateManifest(\n manifest: unknown,\n ctx: { sectionTypes?: ReadonlySet<string> } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(manifest)) {\n bag.err(\"manifest.invalid\", \"theme.json must be a JSON object.\", \"theme.json\");\n return bag.result();\n }\n validateManifestCore(bag, manifest);\n\n const presets = manifest.presets;\n if (!isObject(presets) || Object.keys(presets).length === 0) {\n bag.warn(\"manifest.presets.empty\", \"theme.json has no presets — merchants start with an empty page.\", \"presets\");\n } else {\n // Every referenced section type must resolve to a shipped schema.\n if (ctx.sectionTypes) {\n for (const type of collectPresetSectionTypes(manifest)) {\n if (!ctx.sectionTypes.has(type)) {\n bag.err(\n \"manifest.preset.unknown_section\",\n `Preset references section type \"${type}\" with no schemas/sections/${type}.json.`,\n \"presets\",\n );\n }\n }\n }\n // Required-template coverage (warning).\n const templates = isObject(presets.templates) ? presets.templates : {};\n for (const t of REQUIRED_TEMPLATES) {\n if (!(t in templates)) {\n bag.warn(\n \"manifest.template.missing\",\n `No preset for required template \"${t}\" — the storefront will fall back to its built-in.`,\n `presets.templates.${t}`,\n );\n }\n }\n }\n return bag.result();\n}\n\n/**\n * Server-side gate: validate the artifacts the plugin emits — dist/manifest.json\n * (the embedded built manifest, including section_schemas) and dist/import-map.json\n * (the federation + contract-version descriptor). This is what the backend should\n * run on upload/submit, since it can't run the source build.\n *\n * `opts.hostContractVersion` — when given, refuses bundles whose\n * `contract_version` the host doesn't support.\n */\nexport function validateBuiltManifest(\n builtManifest: unknown,\n importMap?: unknown,\n opts: { hostContractVersion?: number } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(builtManifest)) {\n bag.err(\"built.invalid\", \"manifest.json must be a JSON object.\", \"manifest.json\");\n return bag.result();\n }\n validateManifestCore(bag, builtManifest);\n\n // section_schemas must cover every type the presets reference.\n const schemas = builtManifest.section_schemas;\n const shipped = new Set<string>(isObject(schemas) ? Object.keys(schemas) : []);\n if (!isObject(schemas)) {\n bag.warn(\"built.section_schemas.missing\", \"manifest.json has no `section_schemas`.\", \"section_schemas\");\n }\n for (const type of collectPresetSectionTypes(builtManifest)) {\n if (!shipped.has(type)) {\n bag.err(\n \"built.preset.unknown_section\",\n `Preset references section type \"${type}\" not present in section_schemas.`,\n \"presets\",\n );\n }\n }\n // Each shipped schema must itself be valid.\n if (isObject(schemas)) {\n for (const [type, schema] of Object.entries(schemas)) {\n const r = validateSectionSchema(schema, { filenameType: type });\n for (const issue of r.issues) bag.issues.push(issue);\n }\n }\n if (!isNonEmptyString(builtManifest.plugin_version)) {\n bag.warn(\"built.plugin_version.missing\", \"manifest.json has no `plugin_version`.\", \"plugin_version\");\n }\n\n // Contract-version compatibility from the import map.\n if (importMap !== undefined) {\n if (!isObject(importMap)) {\n bag.err(\"importmap.invalid\", \"import-map.json must be a JSON object.\", \"import-map.json\");\n } else {\n const cv = importMap.contract_version;\n if (typeof cv !== \"number\") {\n bag.warn(\n \"importmap.contract_version.missing\",\n \"import-map.json has no numeric `contract_version` — built by an older plugin.\",\n \"contract_version\",\n );\n } else if (\n typeof opts.hostContractVersion === \"number\" &&\n cv > opts.hostContractVersion\n ) {\n bag.err(\n \"importmap.contract_version.incompatible\",\n `Theme built for contract v${cv}; this platform supports up to v${opts.hostContractVersion}.`,\n \"contract_version\",\n );\n }\n }\n }\n return bag.result();\n}\n\n/** Convenience: merge several results into one. */\nexport function mergeResults(...results: ValidationResult[]): ValidationResult {\n const issues = results.flatMap((r) => r.issues);\n return { valid: !issues.some((i) => i.level === \"error\"), issues };\n}\n"]}
1
+ {"version":3,"sources":["../src/validation/index.ts"],"names":[],"mappings":"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","file":"chunk-H7RGDWSU.cjs","sourcesContent":["/**\n * Shared theme-contract validators — the single source of truth.\n *\n * This module is PURE: it imports only types (erased at compile time) and\n * has no React/DOM/fs dependencies, so the same logic runs in the CLI, the\n * Vite plugin, and (re-implemented) the backend. Callers parse JSON files\n * themselves and pass plain objects in; these functions never touch disk.\n *\n * The goal is that \"builds green\" implies \"matches the contract\": every\n * place a theme can drift from what the storefront expects is checked here\n * once, instead of being re-derived (and drifting) in each tool.\n */\n\nimport type { SectionSchema, SettingDefinition } from \"../types/theme\";\n\n/**\n * The theme CONTRACT version — bumped only on a breaking change to what a\n * built theme must look like (manifest shape, required emitted artifacts,\n * section/setting semantics). The plugin stamps this into the built\n * manifest/import-map; the host refuses bundles whose contract version it\n * doesn't support. Distinct from the npm SDK version (`SDK_VERSION`), which\n * moves on every release including non-breaking ones.\n */\nexport const THEME_CONTRACT_VERSION = 1;\n\n/** npm version of this SDK build (inlined by tsup `define`). Informational. */\ndeclare const __SDK_VERSION__: string | undefined;\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0\";\n\nexport interface ValidationIssue {\n level: \"error\" | \"warning\";\n /** Stable machine code, e.g. \"manifest.version.invalid\". */\n code: string;\n message: string;\n /** Dotted path or file hint, e.g. \"presets.templates.home\" or \"hero.json\". */\n path?: string;\n}\n\nexport interface ValidationResult {\n /** True when there are zero error-level issues. */\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Page templates the storefront routes to. A theme that omits a REQUIRED\n * template still works (the host falls back to its built-in), so a miss is\n * a warning, not an error — but tooling can elevate it with --strict.\n */\nexport const REQUIRED_TEMPLATES = [\n \"home\",\n \"product\",\n \"collection\",\n \"cart\",\n \"page\",\n \"search\",\n \"404\",\n] as const;\n\nexport const KNOWN_TEMPLATES: ReadonlySet<string> = new Set([\n ...REQUIRED_TEMPLATES,\n \"blog\",\n \"article\",\n \"policies\",\n \"password\",\n \"account\",\n \"checkout\",\n]);\n\n/** Setting types the V3 customizer renders. Unknown types warn (forward-compat). */\nexport const KNOWN_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"text\", \"textarea\", \"richtext\", \"number\", \"range\", \"color\", \"checkbox\",\n \"select\", \"radio\", \"font\", \"image_picker\", \"url\", \"product\", \"product_list\",\n \"collection\", \"collection_list\", \"header\", \"paragraph\", \"html\", \"date\",\n \"time\", \"video_picker\", \"color_scheme\", \"page_picker\", \"blog_picker\",\n \"link_list_picker\", \"variant_picker\", \"file_upload\", \"icon_picker\", \"icon\",\n]);\n\n/** Setting types that are presentational (no value) — `id`/`label` optional. */\nconst PRESENTATIONAL_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"header\", \"paragraph\", \"html\",\n]);\n\n// ── Primitives ────────────────────────────────────────────────────\n\nconst SECTION_TYPE_RE = /^[a-z][a-z0-9_-]*$/;\nconst THEME_ID_RE = /^[a-z0-9][a-z0-9_-]*[a-z0-9]$/;\n// Pragmatic semver (major.minor.patch + optional -prerelease / +build).\nconst SEMVER_RE =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-.]+)?(?:\\+[0-9A-Za-z-.]+)?$/;\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.trim().length > 0;\n}\n\nclass IssueBag {\n readonly issues: ValidationIssue[] = [];\n err(code: string, message: string, path?: string) {\n this.issues.push({ level: \"error\", code, message, path });\n }\n warn(code: string, message: string, path?: string) {\n this.issues.push({ level: \"warning\", code, message, path });\n }\n result(): ValidationResult {\n return {\n valid: !this.issues.some((i) => i.level === \"error\"),\n issues: this.issues,\n };\n }\n}\n\n/** Pull the section types referenced by a manifest's presets. */\nfunction collectPresetSectionTypes(manifest: Record<string, unknown>): Set<string> {\n const types = new Set<string>();\n const presets = manifest.presets;\n if (!isObject(presets)) return types;\n const buckets = [presets.templates, presets.section_groups];\n for (const bucket of buckets) {\n if (!isObject(bucket)) continue;\n for (const entry of Object.values(bucket)) {\n if (!isObject(entry)) continue;\n const sections = entry.sections;\n // sections may be an array of instances OR a map id -> instance.\n const instances = Array.isArray(sections)\n ? sections\n : isObject(sections)\n ? Object.values(sections)\n : [];\n for (const inst of instances) {\n if (isObject(inst) && isNonEmptyString(inst.type)) types.add(inst.type);\n }\n }\n }\n return types;\n}\n\n// ── Setting / schema validation ───────────────────────────────────\n\nfunction validateSettingInto(\n bag: IssueBag,\n setting: unknown,\n pathPrefix: string,\n seenIds: Set<string>,\n) {\n if (!isObject(setting)) {\n bag.err(\"schema.setting.invalid\", \"Setting must be an object.\", pathPrefix);\n return;\n }\n const type = setting.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.setting.type.missing\", \"Setting is missing a `type`.\", pathPrefix);\n } else if (!KNOWN_SETTING_TYPES.has(type)) {\n bag.warn(\n \"schema.setting.type.unknown\",\n `Unknown setting type \"${type}\" — the customizer will fall back to a text input.`,\n pathPrefix,\n );\n }\n const presentational =\n isNonEmptyString(type) && PRESENTATIONAL_SETTING_TYPES.has(type);\n if (!presentational) {\n if (!isNonEmptyString(setting.id)) {\n bag.err(\"schema.setting.id.missing\", \"Setting is missing an `id`.\", pathPrefix);\n } else {\n if (seenIds.has(setting.id)) {\n bag.err(\n \"schema.setting.id.duplicate\",\n `Duplicate setting id \"${setting.id}\".`,\n pathPrefix,\n );\n }\n seenIds.add(setting.id);\n }\n if (!isNonEmptyString(setting.label)) {\n bag.warn(\"schema.setting.label.missing\", \"Setting has no `label`.\", pathPrefix);\n }\n }\n // select / radio need options.\n if (type === \"select\" || type === \"radio\") {\n const options = setting.options;\n if (!Array.isArray(options) || options.length === 0) {\n bag.err(\n \"schema.setting.options.missing\",\n `\"${type}\" setting \"${String(setting.id)}\" must declare a non-empty \\`options\\` array.`,\n pathPrefix,\n );\n }\n }\n // range needs bounds.\n if (type === \"range\") {\n if (typeof setting.min !== \"number\" || typeof setting.max !== \"number\") {\n bag.err(\n \"schema.setting.range.bounds\",\n `\"range\" setting \"${String(setting.id)}\" must declare numeric \\`min\\` and \\`max\\`.`,\n pathPrefix,\n );\n } else if (setting.min >= setting.max) {\n bag.err(\n \"schema.setting.range.order\",\n `\"range\" setting \"${String(setting.id)}\" has min >= max.`,\n pathPrefix,\n );\n }\n }\n}\n\n/**\n * Validate one section schema (the parsed schemas/sections/<type>.json).\n * When `filenameType` is given, enforces the component-filename = schema-type\n * convention by requiring `schema.type` to equal it.\n */\nexport function validateSectionSchema(\n schema: unknown,\n opts: { filenameType?: string } = {},\n): ValidationResult {\n const bag = new IssueBag();\n const where = opts.filenameType ? `${opts.filenameType}.json` : \"section schema\";\n if (!isObject(schema)) {\n bag.err(\"schema.invalid\", \"Section schema must be a JSON object.\", where);\n return bag.result();\n }\n const type = schema.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.type.missing\", \"Section schema is missing a `type`.\", where);\n } else {\n if (!SECTION_TYPE_RE.test(type)) {\n bag.err(\n \"schema.type.format\",\n `Section type \"${type}\" must match ${SECTION_TYPE_RE} (lowercase, start with a letter).`,\n where,\n );\n }\n if (opts.filenameType && type !== opts.filenameType) {\n bag.err(\n \"schema.type.filename_mismatch\",\n `Schema type \"${type}\" must equal its filename \"${opts.filenameType}\" (component-filename = schema-type convention).`,\n where,\n );\n }\n }\n if (!isNonEmptyString(schema.name)) {\n bag.err(\"schema.name.missing\", \"Section schema is missing a `name`.\", where);\n }\n if (schema.settings === undefined) {\n bag.warn(\"schema.settings.missing\", \"Section schema has no `settings`.\", where);\n } else if (!Array.isArray(schema.settings)) {\n bag.err(\"schema.settings.invalid\", \"`settings` must be an array.\", where);\n } else {\n const seen = new Set<string>();\n schema.settings.forEach((s, i) =>\n validateSettingInto(bag, s, `${where}.settings[${i}]`, seen),\n );\n }\n // Nested block schemas (shallow — type + settings shape).\n if (schema.blocks !== undefined) {\n if (!Array.isArray(schema.blocks)) {\n bag.err(\"schema.blocks.invalid\", \"`blocks` must be an array.\", where);\n } else {\n schema.blocks.forEach((b, i) => {\n if (!isObject(b) || !isNonEmptyString(b.type)) {\n bag.err(\"schema.block.type.missing\", `Block[${i}] is missing a \\`type\\`.`, where);\n return;\n }\n if (!SECTION_TYPE_RE.test(b.type)) {\n bag.err(\n \"schema.block.type.format\",\n `Block type \"${b.type}\" must match ${SECTION_TYPE_RE}.`,\n where,\n );\n }\n if (Array.isArray(b.settings)) {\n const seen = new Set<string>();\n b.settings.forEach((s, j) =>\n validateSettingInto(bag, s, `${where}.blocks[${i}].settings[${j}]`, seen),\n );\n }\n });\n }\n }\n return bag.result();\n}\n\n/**\n * Instance conformance: check a settings object (from a preset or a merchant\n * customization) against its section schema. Unknown keys warn (harmless at\n * runtime — ignored); invalid values (bad select option, out-of-range,\n * wrong primitive) error.\n */\nexport function validateSettingsAgainstSchema(\n settings: unknown,\n schema: Pick<SectionSchema, \"settings\" | \"type\">,\n pathPrefix = \"settings\",\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(settings)) {\n bag.err(\"instance.settings.invalid\", \"Section settings must be an object.\", pathPrefix);\n return bag.result();\n }\n const defs = Array.isArray(schema.settings) ? schema.settings : [];\n const byId = new Map<string, SettingDefinition>();\n for (const d of defs) if (isNonEmptyString(d?.id)) byId.set(d.id, d);\n\n for (const [key, value] of Object.entries(settings)) {\n const def = byId.get(key);\n if (!def) {\n bag.warn(\n \"instance.setting.unknown\",\n `Setting \"${key}\" is not declared in the \"${String(schema.type)}\" schema.`,\n `${pathPrefix}.${key}`,\n );\n continue;\n }\n if (value === null || value === undefined) continue;\n const p = `${pathPrefix}.${key}`;\n if ((def.type === \"select\" || def.type === \"radio\") && Array.isArray(def.options)) {\n const allowed = def.options.map((o) => o.value);\n if (typeof value === \"string\" && !allowed.includes(value)) {\n bag.err(\n \"instance.setting.option.invalid\",\n `\"${key}\" = \"${value}\" is not one of: ${allowed.join(\", \")}.`,\n p,\n );\n }\n }\n if (def.type === \"range\" && typeof value === \"number\") {\n if (typeof def.min === \"number\" && value < def.min) {\n bag.err(\"instance.setting.range.under\", `\"${key}\" = ${value} is below min ${def.min}.`, p);\n }\n if (typeof def.max === \"number\" && value > def.max) {\n bag.err(\"instance.setting.range.over\", `\"${key}\" = ${value} is above max ${def.max}.`, p);\n }\n }\n if ((def.type === \"checkbox\") && typeof value !== \"boolean\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a boolean.`, p);\n }\n if ((def.type === \"number\" || def.type === \"range\") && typeof value !== \"number\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a number.`, p);\n }\n }\n return bag.result();\n}\n\n// ── Manifest validation ───────────────────────────────────────────\n\n/** Core manifest field checks shared by source (theme.json) and built manifests. */\nfunction validateManifestCore(bag: IssueBag, m: Record<string, unknown>) {\n if (!isNonEmptyString(m.id)) {\n bag.err(\"manifest.id.missing\", \"theme.json is missing `id`.\", \"id\");\n } else if (!THEME_ID_RE.test(m.id)) {\n bag.err(\n \"manifest.id.format\",\n `Theme id \"${m.id}\" must be lowercase alphanumeric with dashes/underscores (no leading/trailing separator).`,\n \"id\",\n );\n }\n // name: string or bilingual object { en|default, ... }.\n const name = m.name;\n const nameOk =\n isNonEmptyString(name) ||\n (isObject(name) && Object.values(name).some((v) => isNonEmptyString(v)));\n if (!nameOk) {\n bag.err(\"manifest.name.missing\", \"theme.json is missing a non-empty `name`.\", \"name\");\n }\n if (!isNonEmptyString(m.version)) {\n bag.err(\"manifest.version.missing\", \"theme.json is missing `version`.\", \"version\");\n } else if (!SEMVER_RE.test(m.version)) {\n bag.err(\"manifest.version.invalid\", `Version \"${m.version}\" is not valid semver.`, \"version\");\n }\n if (!isNonEmptyString(m.author)) {\n bag.err(\"manifest.author.missing\", \"theme.json is missing `author`.\", \"author\");\n }\n if (m.min_sdk_version !== undefined && !SEMVER_RE.test(String(m.min_sdk_version))) {\n bag.warn(\"manifest.min_sdk_version.invalid\", \"`min_sdk_version` is not valid semver.\", \"min_sdk_version\");\n }\n}\n\n/**\n * Validate a source theme manifest (parsed theme.json).\n *\n * `ctx.sectionTypes` — the set of section types the theme actually ships\n * (from schemas/sections/*.json). When provided, every section type\n * referenced by a preset must be present, and missing required templates\n * are surfaced as warnings.\n */\nexport function validateManifest(\n manifest: unknown,\n ctx: { sectionTypes?: ReadonlySet<string> } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(manifest)) {\n bag.err(\"manifest.invalid\", \"theme.json must be a JSON object.\", \"theme.json\");\n return bag.result();\n }\n validateManifestCore(bag, manifest);\n\n const presets = manifest.presets;\n if (!isObject(presets) || Object.keys(presets).length === 0) {\n bag.warn(\"manifest.presets.empty\", \"theme.json has no presets — merchants start with an empty page.\", \"presets\");\n } else {\n // Every referenced section type must resolve to a shipped schema.\n if (ctx.sectionTypes) {\n for (const type of collectPresetSectionTypes(manifest)) {\n if (!ctx.sectionTypes.has(type)) {\n bag.err(\n \"manifest.preset.unknown_section\",\n `Preset references section type \"${type}\" with no schemas/sections/${type}.json.`,\n \"presets\",\n );\n }\n }\n }\n // Required-template coverage (warning).\n const templates = isObject(presets.templates) ? presets.templates : {};\n for (const t of REQUIRED_TEMPLATES) {\n if (!(t in templates)) {\n bag.warn(\n \"manifest.template.missing\",\n `No preset for required template \"${t}\" — the storefront will fall back to its built-in.`,\n `presets.templates.${t}`,\n );\n }\n }\n }\n return bag.result();\n}\n\n/**\n * Server-side gate: validate the artifacts the plugin emits — dist/manifest.json\n * (the embedded built manifest, including section_schemas) and dist/import-map.json\n * (the federation + contract-version descriptor). This is what the backend should\n * run on upload/submit, since it can't run the source build.\n *\n * `opts.hostContractVersion` — when given, refuses bundles whose\n * `contract_version` the host doesn't support.\n */\nexport function validateBuiltManifest(\n builtManifest: unknown,\n importMap?: unknown,\n opts: { hostContractVersion?: number } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(builtManifest)) {\n bag.err(\"built.invalid\", \"manifest.json must be a JSON object.\", \"manifest.json\");\n return bag.result();\n }\n validateManifestCore(bag, builtManifest);\n\n // section_schemas must cover every type the presets reference.\n const schemas = builtManifest.section_schemas;\n const shipped = new Set<string>(isObject(schemas) ? Object.keys(schemas) : []);\n if (!isObject(schemas)) {\n bag.warn(\"built.section_schemas.missing\", \"manifest.json has no `section_schemas`.\", \"section_schemas\");\n }\n for (const type of collectPresetSectionTypes(builtManifest)) {\n if (!shipped.has(type)) {\n bag.err(\n \"built.preset.unknown_section\",\n `Preset references section type \"${type}\" not present in section_schemas.`,\n \"presets\",\n );\n }\n }\n // Each shipped schema must itself be valid.\n if (isObject(schemas)) {\n for (const [type, schema] of Object.entries(schemas)) {\n const r = validateSectionSchema(schema, { filenameType: type });\n for (const issue of r.issues) bag.issues.push(issue);\n }\n }\n if (!isNonEmptyString(builtManifest.plugin_version)) {\n bag.warn(\"built.plugin_version.missing\", \"manifest.json has no `plugin_version`.\", \"plugin_version\");\n }\n\n // Contract-version compatibility from the import map.\n if (importMap !== undefined) {\n if (!isObject(importMap)) {\n bag.err(\"importmap.invalid\", \"import-map.json must be a JSON object.\", \"import-map.json\");\n } else {\n const cv = importMap.contract_version;\n if (typeof cv !== \"number\") {\n bag.warn(\n \"importmap.contract_version.missing\",\n \"import-map.json has no numeric `contract_version` — built by an older plugin.\",\n \"contract_version\",\n );\n } else if (\n typeof opts.hostContractVersion === \"number\" &&\n cv > opts.hostContractVersion\n ) {\n bag.err(\n \"importmap.contract_version.incompatible\",\n `Theme built for contract v${cv}; this platform supports up to v${opts.hostContractVersion}.`,\n \"contract_version\",\n );\n }\n }\n }\n return bag.result();\n}\n\n/** Convenience: merge several results into one. */\nexport function mergeResults(...results: ValidationResult[]): ValidationResult {\n const issues = results.flatMap((r) => r.issues);\n return { valid: !issues.some((i) => i.level === \"error\"), issues };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  // src/validation/index.ts
2
2
  var THEME_CONTRACT_VERSION = 1;
3
- var SDK_VERSION = "0.10.1" ;
3
+ var SDK_VERSION = "0.13.0" ;
4
4
  var REQUIRED_TEMPLATES = [
5
5
  "home",
6
6
  "product",
@@ -393,5 +393,5 @@ function mergeResults(...results) {
393
393
  }
394
394
 
395
395
  export { KNOWN_SETTING_TYPES, KNOWN_TEMPLATES, REQUIRED_TEMPLATES, SDK_VERSION, THEME_CONTRACT_VERSION, mergeResults, validateBuiltManifest, validateManifest, validateSectionSchema, validateSettingsAgainstSchema };
396
- //# sourceMappingURL=chunk-QFFTHIFZ.mjs.map
397
- //# sourceMappingURL=chunk-QFFTHIFZ.mjs.map
396
+ //# sourceMappingURL=chunk-QPXMBK5U.mjs.map
397
+ //# sourceMappingURL=chunk-QPXMBK5U.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/validation/index.ts"],"names":[],"mappings":"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","file":"chunk-QFFTHIFZ.mjs","sourcesContent":["/**\n * Shared theme-contract validators — the single source of truth.\n *\n * This module is PURE: it imports only types (erased at compile time) and\n * has no React/DOM/fs dependencies, so the same logic runs in the CLI, the\n * Vite plugin, and (re-implemented) the backend. Callers parse JSON files\n * themselves and pass plain objects in; these functions never touch disk.\n *\n * The goal is that \"builds green\" implies \"matches the contract\": every\n * place a theme can drift from what the storefront expects is checked here\n * once, instead of being re-derived (and drifting) in each tool.\n */\n\nimport type { SectionSchema, SettingDefinition } from \"../types/theme\";\n\n/**\n * The theme CONTRACT version — bumped only on a breaking change to what a\n * built theme must look like (manifest shape, required emitted artifacts,\n * section/setting semantics). The plugin stamps this into the built\n * manifest/import-map; the host refuses bundles whose contract version it\n * doesn't support. Distinct from the npm SDK version (`SDK_VERSION`), which\n * moves on every release including non-breaking ones.\n */\nexport const THEME_CONTRACT_VERSION = 1;\n\n/** npm version of this SDK build (inlined by tsup `define`). Informational. */\ndeclare const __SDK_VERSION__: string | undefined;\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0\";\n\nexport interface ValidationIssue {\n level: \"error\" | \"warning\";\n /** Stable machine code, e.g. \"manifest.version.invalid\". */\n code: string;\n message: string;\n /** Dotted path or file hint, e.g. \"presets.templates.home\" or \"hero.json\". */\n path?: string;\n}\n\nexport interface ValidationResult {\n /** True when there are zero error-level issues. */\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Page templates the storefront routes to. A theme that omits a REQUIRED\n * template still works (the host falls back to its built-in), so a miss is\n * a warning, not an error — but tooling can elevate it with --strict.\n */\nexport const REQUIRED_TEMPLATES = [\n \"home\",\n \"product\",\n \"collection\",\n \"cart\",\n \"page\",\n \"search\",\n \"404\",\n] as const;\n\nexport const KNOWN_TEMPLATES: ReadonlySet<string> = new Set([\n ...REQUIRED_TEMPLATES,\n \"blog\",\n \"article\",\n \"policies\",\n \"password\",\n \"account\",\n \"checkout\",\n]);\n\n/** Setting types the V3 customizer renders. Unknown types warn (forward-compat). */\nexport const KNOWN_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"text\", \"textarea\", \"richtext\", \"number\", \"range\", \"color\", \"checkbox\",\n \"select\", \"radio\", \"font\", \"image_picker\", \"url\", \"product\", \"product_list\",\n \"collection\", \"collection_list\", \"header\", \"paragraph\", \"html\", \"date\",\n \"time\", \"video_picker\", \"color_scheme\", \"page_picker\", \"blog_picker\",\n \"link_list_picker\", \"variant_picker\", \"file_upload\", \"icon_picker\", \"icon\",\n]);\n\n/** Setting types that are presentational (no value) — `id`/`label` optional. */\nconst PRESENTATIONAL_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"header\", \"paragraph\", \"html\",\n]);\n\n// ── Primitives ────────────────────────────────────────────────────\n\nconst SECTION_TYPE_RE = /^[a-z][a-z0-9_-]*$/;\nconst THEME_ID_RE = /^[a-z0-9][a-z0-9_-]*[a-z0-9]$/;\n// Pragmatic semver (major.minor.patch + optional -prerelease / +build).\nconst SEMVER_RE =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-.]+)?(?:\\+[0-9A-Za-z-.]+)?$/;\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.trim().length > 0;\n}\n\nclass IssueBag {\n readonly issues: ValidationIssue[] = [];\n err(code: string, message: string, path?: string) {\n this.issues.push({ level: \"error\", code, message, path });\n }\n warn(code: string, message: string, path?: string) {\n this.issues.push({ level: \"warning\", code, message, path });\n }\n result(): ValidationResult {\n return {\n valid: !this.issues.some((i) => i.level === \"error\"),\n issues: this.issues,\n };\n }\n}\n\n/** Pull the section types referenced by a manifest's presets. */\nfunction collectPresetSectionTypes(manifest: Record<string, unknown>): Set<string> {\n const types = new Set<string>();\n const presets = manifest.presets;\n if (!isObject(presets)) return types;\n const buckets = [presets.templates, presets.section_groups];\n for (const bucket of buckets) {\n if (!isObject(bucket)) continue;\n for (const entry of Object.values(bucket)) {\n if (!isObject(entry)) continue;\n const sections = entry.sections;\n // sections may be an array of instances OR a map id -> instance.\n const instances = Array.isArray(sections)\n ? sections\n : isObject(sections)\n ? Object.values(sections)\n : [];\n for (const inst of instances) {\n if (isObject(inst) && isNonEmptyString(inst.type)) types.add(inst.type);\n }\n }\n }\n return types;\n}\n\n// ── Setting / schema validation ───────────────────────────────────\n\nfunction validateSettingInto(\n bag: IssueBag,\n setting: unknown,\n pathPrefix: string,\n seenIds: Set<string>,\n) {\n if (!isObject(setting)) {\n bag.err(\"schema.setting.invalid\", \"Setting must be an object.\", pathPrefix);\n return;\n }\n const type = setting.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.setting.type.missing\", \"Setting is missing a `type`.\", pathPrefix);\n } else if (!KNOWN_SETTING_TYPES.has(type)) {\n bag.warn(\n \"schema.setting.type.unknown\",\n `Unknown setting type \"${type}\" — the customizer will fall back to a text input.`,\n pathPrefix,\n );\n }\n const presentational =\n isNonEmptyString(type) && PRESENTATIONAL_SETTING_TYPES.has(type);\n if (!presentational) {\n if (!isNonEmptyString(setting.id)) {\n bag.err(\"schema.setting.id.missing\", \"Setting is missing an `id`.\", pathPrefix);\n } else {\n if (seenIds.has(setting.id)) {\n bag.err(\n \"schema.setting.id.duplicate\",\n `Duplicate setting id \"${setting.id}\".`,\n pathPrefix,\n );\n }\n seenIds.add(setting.id);\n }\n if (!isNonEmptyString(setting.label)) {\n bag.warn(\"schema.setting.label.missing\", \"Setting has no `label`.\", pathPrefix);\n }\n }\n // select / radio need options.\n if (type === \"select\" || type === \"radio\") {\n const options = setting.options;\n if (!Array.isArray(options) || options.length === 0) {\n bag.err(\n \"schema.setting.options.missing\",\n `\"${type}\" setting \"${String(setting.id)}\" must declare a non-empty \\`options\\` array.`,\n pathPrefix,\n );\n }\n }\n // range needs bounds.\n if (type === \"range\") {\n if (typeof setting.min !== \"number\" || typeof setting.max !== \"number\") {\n bag.err(\n \"schema.setting.range.bounds\",\n `\"range\" setting \"${String(setting.id)}\" must declare numeric \\`min\\` and \\`max\\`.`,\n pathPrefix,\n );\n } else if (setting.min >= setting.max) {\n bag.err(\n \"schema.setting.range.order\",\n `\"range\" setting \"${String(setting.id)}\" has min >= max.`,\n pathPrefix,\n );\n }\n }\n}\n\n/**\n * Validate one section schema (the parsed schemas/sections/<type>.json).\n * When `filenameType` is given, enforces the component-filename = schema-type\n * convention by requiring `schema.type` to equal it.\n */\nexport function validateSectionSchema(\n schema: unknown,\n opts: { filenameType?: string } = {},\n): ValidationResult {\n const bag = new IssueBag();\n const where = opts.filenameType ? `${opts.filenameType}.json` : \"section schema\";\n if (!isObject(schema)) {\n bag.err(\"schema.invalid\", \"Section schema must be a JSON object.\", where);\n return bag.result();\n }\n const type = schema.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.type.missing\", \"Section schema is missing a `type`.\", where);\n } else {\n if (!SECTION_TYPE_RE.test(type)) {\n bag.err(\n \"schema.type.format\",\n `Section type \"${type}\" must match ${SECTION_TYPE_RE} (lowercase, start with a letter).`,\n where,\n );\n }\n if (opts.filenameType && type !== opts.filenameType) {\n bag.err(\n \"schema.type.filename_mismatch\",\n `Schema type \"${type}\" must equal its filename \"${opts.filenameType}\" (component-filename = schema-type convention).`,\n where,\n );\n }\n }\n if (!isNonEmptyString(schema.name)) {\n bag.err(\"schema.name.missing\", \"Section schema is missing a `name`.\", where);\n }\n if (schema.settings === undefined) {\n bag.warn(\"schema.settings.missing\", \"Section schema has no `settings`.\", where);\n } else if (!Array.isArray(schema.settings)) {\n bag.err(\"schema.settings.invalid\", \"`settings` must be an array.\", where);\n } else {\n const seen = new Set<string>();\n schema.settings.forEach((s, i) =>\n validateSettingInto(bag, s, `${where}.settings[${i}]`, seen),\n );\n }\n // Nested block schemas (shallow — type + settings shape).\n if (schema.blocks !== undefined) {\n if (!Array.isArray(schema.blocks)) {\n bag.err(\"schema.blocks.invalid\", \"`blocks` must be an array.\", where);\n } else {\n schema.blocks.forEach((b, i) => {\n if (!isObject(b) || !isNonEmptyString(b.type)) {\n bag.err(\"schema.block.type.missing\", `Block[${i}] is missing a \\`type\\`.`, where);\n return;\n }\n if (!SECTION_TYPE_RE.test(b.type)) {\n bag.err(\n \"schema.block.type.format\",\n `Block type \"${b.type}\" must match ${SECTION_TYPE_RE}.`,\n where,\n );\n }\n if (Array.isArray(b.settings)) {\n const seen = new Set<string>();\n b.settings.forEach((s, j) =>\n validateSettingInto(bag, s, `${where}.blocks[${i}].settings[${j}]`, seen),\n );\n }\n });\n }\n }\n return bag.result();\n}\n\n/**\n * Instance conformance: check a settings object (from a preset or a merchant\n * customization) against its section schema. Unknown keys warn (harmless at\n * runtime — ignored); invalid values (bad select option, out-of-range,\n * wrong primitive) error.\n */\nexport function validateSettingsAgainstSchema(\n settings: unknown,\n schema: Pick<SectionSchema, \"settings\" | \"type\">,\n pathPrefix = \"settings\",\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(settings)) {\n bag.err(\"instance.settings.invalid\", \"Section settings must be an object.\", pathPrefix);\n return bag.result();\n }\n const defs = Array.isArray(schema.settings) ? schema.settings : [];\n const byId = new Map<string, SettingDefinition>();\n for (const d of defs) if (isNonEmptyString(d?.id)) byId.set(d.id, d);\n\n for (const [key, value] of Object.entries(settings)) {\n const def = byId.get(key);\n if (!def) {\n bag.warn(\n \"instance.setting.unknown\",\n `Setting \"${key}\" is not declared in the \"${String(schema.type)}\" schema.`,\n `${pathPrefix}.${key}`,\n );\n continue;\n }\n if (value === null || value === undefined) continue;\n const p = `${pathPrefix}.${key}`;\n if ((def.type === \"select\" || def.type === \"radio\") && Array.isArray(def.options)) {\n const allowed = def.options.map((o) => o.value);\n if (typeof value === \"string\" && !allowed.includes(value)) {\n bag.err(\n \"instance.setting.option.invalid\",\n `\"${key}\" = \"${value}\" is not one of: ${allowed.join(\", \")}.`,\n p,\n );\n }\n }\n if (def.type === \"range\" && typeof value === \"number\") {\n if (typeof def.min === \"number\" && value < def.min) {\n bag.err(\"instance.setting.range.under\", `\"${key}\" = ${value} is below min ${def.min}.`, p);\n }\n if (typeof def.max === \"number\" && value > def.max) {\n bag.err(\"instance.setting.range.over\", `\"${key}\" = ${value} is above max ${def.max}.`, p);\n }\n }\n if ((def.type === \"checkbox\") && typeof value !== \"boolean\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a boolean.`, p);\n }\n if ((def.type === \"number\" || def.type === \"range\") && typeof value !== \"number\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a number.`, p);\n }\n }\n return bag.result();\n}\n\n// ── Manifest validation ───────────────────────────────────────────\n\n/** Core manifest field checks shared by source (theme.json) and built manifests. */\nfunction validateManifestCore(bag: IssueBag, m: Record<string, unknown>) {\n if (!isNonEmptyString(m.id)) {\n bag.err(\"manifest.id.missing\", \"theme.json is missing `id`.\", \"id\");\n } else if (!THEME_ID_RE.test(m.id)) {\n bag.err(\n \"manifest.id.format\",\n `Theme id \"${m.id}\" must be lowercase alphanumeric with dashes/underscores (no leading/trailing separator).`,\n \"id\",\n );\n }\n // name: string or bilingual object { en|default, ... }.\n const name = m.name;\n const nameOk =\n isNonEmptyString(name) ||\n (isObject(name) && Object.values(name).some((v) => isNonEmptyString(v)));\n if (!nameOk) {\n bag.err(\"manifest.name.missing\", \"theme.json is missing a non-empty `name`.\", \"name\");\n }\n if (!isNonEmptyString(m.version)) {\n bag.err(\"manifest.version.missing\", \"theme.json is missing `version`.\", \"version\");\n } else if (!SEMVER_RE.test(m.version)) {\n bag.err(\"manifest.version.invalid\", `Version \"${m.version}\" is not valid semver.`, \"version\");\n }\n if (!isNonEmptyString(m.author)) {\n bag.err(\"manifest.author.missing\", \"theme.json is missing `author`.\", \"author\");\n }\n if (m.min_sdk_version !== undefined && !SEMVER_RE.test(String(m.min_sdk_version))) {\n bag.warn(\"manifest.min_sdk_version.invalid\", \"`min_sdk_version` is not valid semver.\", \"min_sdk_version\");\n }\n}\n\n/**\n * Validate a source theme manifest (parsed theme.json).\n *\n * `ctx.sectionTypes` — the set of section types the theme actually ships\n * (from schemas/sections/*.json). When provided, every section type\n * referenced by a preset must be present, and missing required templates\n * are surfaced as warnings.\n */\nexport function validateManifest(\n manifest: unknown,\n ctx: { sectionTypes?: ReadonlySet<string> } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(manifest)) {\n bag.err(\"manifest.invalid\", \"theme.json must be a JSON object.\", \"theme.json\");\n return bag.result();\n }\n validateManifestCore(bag, manifest);\n\n const presets = manifest.presets;\n if (!isObject(presets) || Object.keys(presets).length === 0) {\n bag.warn(\"manifest.presets.empty\", \"theme.json has no presets — merchants start with an empty page.\", \"presets\");\n } else {\n // Every referenced section type must resolve to a shipped schema.\n if (ctx.sectionTypes) {\n for (const type of collectPresetSectionTypes(manifest)) {\n if (!ctx.sectionTypes.has(type)) {\n bag.err(\n \"manifest.preset.unknown_section\",\n `Preset references section type \"${type}\" with no schemas/sections/${type}.json.`,\n \"presets\",\n );\n }\n }\n }\n // Required-template coverage (warning).\n const templates = isObject(presets.templates) ? presets.templates : {};\n for (const t of REQUIRED_TEMPLATES) {\n if (!(t in templates)) {\n bag.warn(\n \"manifest.template.missing\",\n `No preset for required template \"${t}\" — the storefront will fall back to its built-in.`,\n `presets.templates.${t}`,\n );\n }\n }\n }\n return bag.result();\n}\n\n/**\n * Server-side gate: validate the artifacts the plugin emits — dist/manifest.json\n * (the embedded built manifest, including section_schemas) and dist/import-map.json\n * (the federation + contract-version descriptor). This is what the backend should\n * run on upload/submit, since it can't run the source build.\n *\n * `opts.hostContractVersion` — when given, refuses bundles whose\n * `contract_version` the host doesn't support.\n */\nexport function validateBuiltManifest(\n builtManifest: unknown,\n importMap?: unknown,\n opts: { hostContractVersion?: number } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(builtManifest)) {\n bag.err(\"built.invalid\", \"manifest.json must be a JSON object.\", \"manifest.json\");\n return bag.result();\n }\n validateManifestCore(bag, builtManifest);\n\n // section_schemas must cover every type the presets reference.\n const schemas = builtManifest.section_schemas;\n const shipped = new Set<string>(isObject(schemas) ? Object.keys(schemas) : []);\n if (!isObject(schemas)) {\n bag.warn(\"built.section_schemas.missing\", \"manifest.json has no `section_schemas`.\", \"section_schemas\");\n }\n for (const type of collectPresetSectionTypes(builtManifest)) {\n if (!shipped.has(type)) {\n bag.err(\n \"built.preset.unknown_section\",\n `Preset references section type \"${type}\" not present in section_schemas.`,\n \"presets\",\n );\n }\n }\n // Each shipped schema must itself be valid.\n if (isObject(schemas)) {\n for (const [type, schema] of Object.entries(schemas)) {\n const r = validateSectionSchema(schema, { filenameType: type });\n for (const issue of r.issues) bag.issues.push(issue);\n }\n }\n if (!isNonEmptyString(builtManifest.plugin_version)) {\n bag.warn(\"built.plugin_version.missing\", \"manifest.json has no `plugin_version`.\", \"plugin_version\");\n }\n\n // Contract-version compatibility from the import map.\n if (importMap !== undefined) {\n if (!isObject(importMap)) {\n bag.err(\"importmap.invalid\", \"import-map.json must be a JSON object.\", \"import-map.json\");\n } else {\n const cv = importMap.contract_version;\n if (typeof cv !== \"number\") {\n bag.warn(\n \"importmap.contract_version.missing\",\n \"import-map.json has no numeric `contract_version` — built by an older plugin.\",\n \"contract_version\",\n );\n } else if (\n typeof opts.hostContractVersion === \"number\" &&\n cv > opts.hostContractVersion\n ) {\n bag.err(\n \"importmap.contract_version.incompatible\",\n `Theme built for contract v${cv}; this platform supports up to v${opts.hostContractVersion}.`,\n \"contract_version\",\n );\n }\n }\n }\n return bag.result();\n}\n\n/** Convenience: merge several results into one. */\nexport function mergeResults(...results: ValidationResult[]): ValidationResult {\n const issues = results.flatMap((r) => r.issues);\n return { valid: !issues.some((i) => i.level === \"error\"), issues };\n}\n"]}
1
+ {"version":3,"sources":["../src/validation/index.ts"],"names":[],"mappings":"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","file":"chunk-QPXMBK5U.mjs","sourcesContent":["/**\n * Shared theme-contract validators — the single source of truth.\n *\n * This module is PURE: it imports only types (erased at compile time) and\n * has no React/DOM/fs dependencies, so the same logic runs in the CLI, the\n * Vite plugin, and (re-implemented) the backend. Callers parse JSON files\n * themselves and pass plain objects in; these functions never touch disk.\n *\n * The goal is that \"builds green\" implies \"matches the contract\": every\n * place a theme can drift from what the storefront expects is checked here\n * once, instead of being re-derived (and drifting) in each tool.\n */\n\nimport type { SectionSchema, SettingDefinition } from \"../types/theme\";\n\n/**\n * The theme CONTRACT version — bumped only on a breaking change to what a\n * built theme must look like (manifest shape, required emitted artifacts,\n * section/setting semantics). The plugin stamps this into the built\n * manifest/import-map; the host refuses bundles whose contract version it\n * doesn't support. Distinct from the npm SDK version (`SDK_VERSION`), which\n * moves on every release including non-breaking ones.\n */\nexport const THEME_CONTRACT_VERSION = 1;\n\n/** npm version of this SDK build (inlined by tsup `define`). Informational. */\ndeclare const __SDK_VERSION__: string | undefined;\nexport const SDK_VERSION: string =\n typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"0.0.0\";\n\nexport interface ValidationIssue {\n level: \"error\" | \"warning\";\n /** Stable machine code, e.g. \"manifest.version.invalid\". */\n code: string;\n message: string;\n /** Dotted path or file hint, e.g. \"presets.templates.home\" or \"hero.json\". */\n path?: string;\n}\n\nexport interface ValidationResult {\n /** True when there are zero error-level issues. */\n valid: boolean;\n issues: ValidationIssue[];\n}\n\n/**\n * Page templates the storefront routes to. A theme that omits a REQUIRED\n * template still works (the host falls back to its built-in), so a miss is\n * a warning, not an error — but tooling can elevate it with --strict.\n */\nexport const REQUIRED_TEMPLATES = [\n \"home\",\n \"product\",\n \"collection\",\n \"cart\",\n \"page\",\n \"search\",\n \"404\",\n] as const;\n\nexport const KNOWN_TEMPLATES: ReadonlySet<string> = new Set([\n ...REQUIRED_TEMPLATES,\n \"blog\",\n \"article\",\n \"policies\",\n \"password\",\n \"account\",\n \"checkout\",\n]);\n\n/** Setting types the V3 customizer renders. Unknown types warn (forward-compat). */\nexport const KNOWN_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"text\", \"textarea\", \"richtext\", \"number\", \"range\", \"color\", \"checkbox\",\n \"select\", \"radio\", \"font\", \"image_picker\", \"url\", \"product\", \"product_list\",\n \"collection\", \"collection_list\", \"header\", \"paragraph\", \"html\", \"date\",\n \"time\", \"video_picker\", \"color_scheme\", \"page_picker\", \"blog_picker\",\n \"link_list_picker\", \"variant_picker\", \"file_upload\", \"icon_picker\", \"icon\",\n]);\n\n/** Setting types that are presentational (no value) — `id`/`label` optional. */\nconst PRESENTATIONAL_SETTING_TYPES: ReadonlySet<string> = new Set([\n \"header\", \"paragraph\", \"html\",\n]);\n\n// ── Primitives ────────────────────────────────────────────────────\n\nconst SECTION_TYPE_RE = /^[a-z][a-z0-9_-]*$/;\nconst THEME_ID_RE = /^[a-z0-9][a-z0-9_-]*[a-z0-9]$/;\n// Pragmatic semver (major.minor.patch + optional -prerelease / +build).\nconst SEMVER_RE =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-.]+)?(?:\\+[0-9A-Za-z-.]+)?$/;\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\nfunction isNonEmptyString(v: unknown): v is string {\n return typeof v === \"string\" && v.trim().length > 0;\n}\n\nclass IssueBag {\n readonly issues: ValidationIssue[] = [];\n err(code: string, message: string, path?: string) {\n this.issues.push({ level: \"error\", code, message, path });\n }\n warn(code: string, message: string, path?: string) {\n this.issues.push({ level: \"warning\", code, message, path });\n }\n result(): ValidationResult {\n return {\n valid: !this.issues.some((i) => i.level === \"error\"),\n issues: this.issues,\n };\n }\n}\n\n/** Pull the section types referenced by a manifest's presets. */\nfunction collectPresetSectionTypes(manifest: Record<string, unknown>): Set<string> {\n const types = new Set<string>();\n const presets = manifest.presets;\n if (!isObject(presets)) return types;\n const buckets = [presets.templates, presets.section_groups];\n for (const bucket of buckets) {\n if (!isObject(bucket)) continue;\n for (const entry of Object.values(bucket)) {\n if (!isObject(entry)) continue;\n const sections = entry.sections;\n // sections may be an array of instances OR a map id -> instance.\n const instances = Array.isArray(sections)\n ? sections\n : isObject(sections)\n ? Object.values(sections)\n : [];\n for (const inst of instances) {\n if (isObject(inst) && isNonEmptyString(inst.type)) types.add(inst.type);\n }\n }\n }\n return types;\n}\n\n// ── Setting / schema validation ───────────────────────────────────\n\nfunction validateSettingInto(\n bag: IssueBag,\n setting: unknown,\n pathPrefix: string,\n seenIds: Set<string>,\n) {\n if (!isObject(setting)) {\n bag.err(\"schema.setting.invalid\", \"Setting must be an object.\", pathPrefix);\n return;\n }\n const type = setting.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.setting.type.missing\", \"Setting is missing a `type`.\", pathPrefix);\n } else if (!KNOWN_SETTING_TYPES.has(type)) {\n bag.warn(\n \"schema.setting.type.unknown\",\n `Unknown setting type \"${type}\" — the customizer will fall back to a text input.`,\n pathPrefix,\n );\n }\n const presentational =\n isNonEmptyString(type) && PRESENTATIONAL_SETTING_TYPES.has(type);\n if (!presentational) {\n if (!isNonEmptyString(setting.id)) {\n bag.err(\"schema.setting.id.missing\", \"Setting is missing an `id`.\", pathPrefix);\n } else {\n if (seenIds.has(setting.id)) {\n bag.err(\n \"schema.setting.id.duplicate\",\n `Duplicate setting id \"${setting.id}\".`,\n pathPrefix,\n );\n }\n seenIds.add(setting.id);\n }\n if (!isNonEmptyString(setting.label)) {\n bag.warn(\"schema.setting.label.missing\", \"Setting has no `label`.\", pathPrefix);\n }\n }\n // select / radio need options.\n if (type === \"select\" || type === \"radio\") {\n const options = setting.options;\n if (!Array.isArray(options) || options.length === 0) {\n bag.err(\n \"schema.setting.options.missing\",\n `\"${type}\" setting \"${String(setting.id)}\" must declare a non-empty \\`options\\` array.`,\n pathPrefix,\n );\n }\n }\n // range needs bounds.\n if (type === \"range\") {\n if (typeof setting.min !== \"number\" || typeof setting.max !== \"number\") {\n bag.err(\n \"schema.setting.range.bounds\",\n `\"range\" setting \"${String(setting.id)}\" must declare numeric \\`min\\` and \\`max\\`.`,\n pathPrefix,\n );\n } else if (setting.min >= setting.max) {\n bag.err(\n \"schema.setting.range.order\",\n `\"range\" setting \"${String(setting.id)}\" has min >= max.`,\n pathPrefix,\n );\n }\n }\n}\n\n/**\n * Validate one section schema (the parsed schemas/sections/<type>.json).\n * When `filenameType` is given, enforces the component-filename = schema-type\n * convention by requiring `schema.type` to equal it.\n */\nexport function validateSectionSchema(\n schema: unknown,\n opts: { filenameType?: string } = {},\n): ValidationResult {\n const bag = new IssueBag();\n const where = opts.filenameType ? `${opts.filenameType}.json` : \"section schema\";\n if (!isObject(schema)) {\n bag.err(\"schema.invalid\", \"Section schema must be a JSON object.\", where);\n return bag.result();\n }\n const type = schema.type;\n if (!isNonEmptyString(type)) {\n bag.err(\"schema.type.missing\", \"Section schema is missing a `type`.\", where);\n } else {\n if (!SECTION_TYPE_RE.test(type)) {\n bag.err(\n \"schema.type.format\",\n `Section type \"${type}\" must match ${SECTION_TYPE_RE} (lowercase, start with a letter).`,\n where,\n );\n }\n if (opts.filenameType && type !== opts.filenameType) {\n bag.err(\n \"schema.type.filename_mismatch\",\n `Schema type \"${type}\" must equal its filename \"${opts.filenameType}\" (component-filename = schema-type convention).`,\n where,\n );\n }\n }\n if (!isNonEmptyString(schema.name)) {\n bag.err(\"schema.name.missing\", \"Section schema is missing a `name`.\", where);\n }\n if (schema.settings === undefined) {\n bag.warn(\"schema.settings.missing\", \"Section schema has no `settings`.\", where);\n } else if (!Array.isArray(schema.settings)) {\n bag.err(\"schema.settings.invalid\", \"`settings` must be an array.\", where);\n } else {\n const seen = new Set<string>();\n schema.settings.forEach((s, i) =>\n validateSettingInto(bag, s, `${where}.settings[${i}]`, seen),\n );\n }\n // Nested block schemas (shallow — type + settings shape).\n if (schema.blocks !== undefined) {\n if (!Array.isArray(schema.blocks)) {\n bag.err(\"schema.blocks.invalid\", \"`blocks` must be an array.\", where);\n } else {\n schema.blocks.forEach((b, i) => {\n if (!isObject(b) || !isNonEmptyString(b.type)) {\n bag.err(\"schema.block.type.missing\", `Block[${i}] is missing a \\`type\\`.`, where);\n return;\n }\n if (!SECTION_TYPE_RE.test(b.type)) {\n bag.err(\n \"schema.block.type.format\",\n `Block type \"${b.type}\" must match ${SECTION_TYPE_RE}.`,\n where,\n );\n }\n if (Array.isArray(b.settings)) {\n const seen = new Set<string>();\n b.settings.forEach((s, j) =>\n validateSettingInto(bag, s, `${where}.blocks[${i}].settings[${j}]`, seen),\n );\n }\n });\n }\n }\n return bag.result();\n}\n\n/**\n * Instance conformance: check a settings object (from a preset or a merchant\n * customization) against its section schema. Unknown keys warn (harmless at\n * runtime — ignored); invalid values (bad select option, out-of-range,\n * wrong primitive) error.\n */\nexport function validateSettingsAgainstSchema(\n settings: unknown,\n schema: Pick<SectionSchema, \"settings\" | \"type\">,\n pathPrefix = \"settings\",\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(settings)) {\n bag.err(\"instance.settings.invalid\", \"Section settings must be an object.\", pathPrefix);\n return bag.result();\n }\n const defs = Array.isArray(schema.settings) ? schema.settings : [];\n const byId = new Map<string, SettingDefinition>();\n for (const d of defs) if (isNonEmptyString(d?.id)) byId.set(d.id, d);\n\n for (const [key, value] of Object.entries(settings)) {\n const def = byId.get(key);\n if (!def) {\n bag.warn(\n \"instance.setting.unknown\",\n `Setting \"${key}\" is not declared in the \"${String(schema.type)}\" schema.`,\n `${pathPrefix}.${key}`,\n );\n continue;\n }\n if (value === null || value === undefined) continue;\n const p = `${pathPrefix}.${key}`;\n if ((def.type === \"select\" || def.type === \"radio\") && Array.isArray(def.options)) {\n const allowed = def.options.map((o) => o.value);\n if (typeof value === \"string\" && !allowed.includes(value)) {\n bag.err(\n \"instance.setting.option.invalid\",\n `\"${key}\" = \"${value}\" is not one of: ${allowed.join(\", \")}.`,\n p,\n );\n }\n }\n if (def.type === \"range\" && typeof value === \"number\") {\n if (typeof def.min === \"number\" && value < def.min) {\n bag.err(\"instance.setting.range.under\", `\"${key}\" = ${value} is below min ${def.min}.`, p);\n }\n if (typeof def.max === \"number\" && value > def.max) {\n bag.err(\"instance.setting.range.over\", `\"${key}\" = ${value} is above max ${def.max}.`, p);\n }\n }\n if ((def.type === \"checkbox\") && typeof value !== \"boolean\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a boolean.`, p);\n }\n if ((def.type === \"number\" || def.type === \"range\") && typeof value !== \"number\") {\n bag.warn(\"instance.setting.type.mismatch\", `\"${key}\" should be a number.`, p);\n }\n }\n return bag.result();\n}\n\n// ── Manifest validation ───────────────────────────────────────────\n\n/** Core manifest field checks shared by source (theme.json) and built manifests. */\nfunction validateManifestCore(bag: IssueBag, m: Record<string, unknown>) {\n if (!isNonEmptyString(m.id)) {\n bag.err(\"manifest.id.missing\", \"theme.json is missing `id`.\", \"id\");\n } else if (!THEME_ID_RE.test(m.id)) {\n bag.err(\n \"manifest.id.format\",\n `Theme id \"${m.id}\" must be lowercase alphanumeric with dashes/underscores (no leading/trailing separator).`,\n \"id\",\n );\n }\n // name: string or bilingual object { en|default, ... }.\n const name = m.name;\n const nameOk =\n isNonEmptyString(name) ||\n (isObject(name) && Object.values(name).some((v) => isNonEmptyString(v)));\n if (!nameOk) {\n bag.err(\"manifest.name.missing\", \"theme.json is missing a non-empty `name`.\", \"name\");\n }\n if (!isNonEmptyString(m.version)) {\n bag.err(\"manifest.version.missing\", \"theme.json is missing `version`.\", \"version\");\n } else if (!SEMVER_RE.test(m.version)) {\n bag.err(\"manifest.version.invalid\", `Version \"${m.version}\" is not valid semver.`, \"version\");\n }\n if (!isNonEmptyString(m.author)) {\n bag.err(\"manifest.author.missing\", \"theme.json is missing `author`.\", \"author\");\n }\n if (m.min_sdk_version !== undefined && !SEMVER_RE.test(String(m.min_sdk_version))) {\n bag.warn(\"manifest.min_sdk_version.invalid\", \"`min_sdk_version` is not valid semver.\", \"min_sdk_version\");\n }\n}\n\n/**\n * Validate a source theme manifest (parsed theme.json).\n *\n * `ctx.sectionTypes` — the set of section types the theme actually ships\n * (from schemas/sections/*.json). When provided, every section type\n * referenced by a preset must be present, and missing required templates\n * are surfaced as warnings.\n */\nexport function validateManifest(\n manifest: unknown,\n ctx: { sectionTypes?: ReadonlySet<string> } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(manifest)) {\n bag.err(\"manifest.invalid\", \"theme.json must be a JSON object.\", \"theme.json\");\n return bag.result();\n }\n validateManifestCore(bag, manifest);\n\n const presets = manifest.presets;\n if (!isObject(presets) || Object.keys(presets).length === 0) {\n bag.warn(\"manifest.presets.empty\", \"theme.json has no presets — merchants start with an empty page.\", \"presets\");\n } else {\n // Every referenced section type must resolve to a shipped schema.\n if (ctx.sectionTypes) {\n for (const type of collectPresetSectionTypes(manifest)) {\n if (!ctx.sectionTypes.has(type)) {\n bag.err(\n \"manifest.preset.unknown_section\",\n `Preset references section type \"${type}\" with no schemas/sections/${type}.json.`,\n \"presets\",\n );\n }\n }\n }\n // Required-template coverage (warning).\n const templates = isObject(presets.templates) ? presets.templates : {};\n for (const t of REQUIRED_TEMPLATES) {\n if (!(t in templates)) {\n bag.warn(\n \"manifest.template.missing\",\n `No preset for required template \"${t}\" — the storefront will fall back to its built-in.`,\n `presets.templates.${t}`,\n );\n }\n }\n }\n return bag.result();\n}\n\n/**\n * Server-side gate: validate the artifacts the plugin emits — dist/manifest.json\n * (the embedded built manifest, including section_schemas) and dist/import-map.json\n * (the federation + contract-version descriptor). This is what the backend should\n * run on upload/submit, since it can't run the source build.\n *\n * `opts.hostContractVersion` — when given, refuses bundles whose\n * `contract_version` the host doesn't support.\n */\nexport function validateBuiltManifest(\n builtManifest: unknown,\n importMap?: unknown,\n opts: { hostContractVersion?: number } = {},\n): ValidationResult {\n const bag = new IssueBag();\n if (!isObject(builtManifest)) {\n bag.err(\"built.invalid\", \"manifest.json must be a JSON object.\", \"manifest.json\");\n return bag.result();\n }\n validateManifestCore(bag, builtManifest);\n\n // section_schemas must cover every type the presets reference.\n const schemas = builtManifest.section_schemas;\n const shipped = new Set<string>(isObject(schemas) ? Object.keys(schemas) : []);\n if (!isObject(schemas)) {\n bag.warn(\"built.section_schemas.missing\", \"manifest.json has no `section_schemas`.\", \"section_schemas\");\n }\n for (const type of collectPresetSectionTypes(builtManifest)) {\n if (!shipped.has(type)) {\n bag.err(\n \"built.preset.unknown_section\",\n `Preset references section type \"${type}\" not present in section_schemas.`,\n \"presets\",\n );\n }\n }\n // Each shipped schema must itself be valid.\n if (isObject(schemas)) {\n for (const [type, schema] of Object.entries(schemas)) {\n const r = validateSectionSchema(schema, { filenameType: type });\n for (const issue of r.issues) bag.issues.push(issue);\n }\n }\n if (!isNonEmptyString(builtManifest.plugin_version)) {\n bag.warn(\"built.plugin_version.missing\", \"manifest.json has no `plugin_version`.\", \"plugin_version\");\n }\n\n // Contract-version compatibility from the import map.\n if (importMap !== undefined) {\n if (!isObject(importMap)) {\n bag.err(\"importmap.invalid\", \"import-map.json must be a JSON object.\", \"import-map.json\");\n } else {\n const cv = importMap.contract_version;\n if (typeof cv !== \"number\") {\n bag.warn(\n \"importmap.contract_version.missing\",\n \"import-map.json has no numeric `contract_version` — built by an older plugin.\",\n \"contract_version\",\n );\n } else if (\n typeof opts.hostContractVersion === \"number\" &&\n cv > opts.hostContractVersion\n ) {\n bag.err(\n \"importmap.contract_version.incompatible\",\n `Theme built for contract v${cv}; this platform supports up to v${opts.hostContractVersion}.`,\n \"contract_version\",\n );\n }\n }\n }\n return bag.result();\n}\n\n/** Convenience: merge several results into one. */\nexport function mergeResults(...results: ValidationResult[]): ValidationResult {\n const issues = results.flatMap((r) => r.issues);\n return { valid: !issues.some((i) => i.level === \"error\"), issues };\n}\n"]}