@doswiftly/storefront-sdk 22.8.1 → 22.10.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.
@@ -50,6 +50,15 @@ export interface ImageLoaderConfig {
50
50
  * framework already fingerprints). Defaults to {@link FRAMEWORK_BUILD_PREFIXES}.
51
51
  */
52
52
  buildAssetPrefixes?: readonly string[];
53
+ /**
54
+ * Build clean asset URLs without the `/s/{shopId}` storage namespace. Set for a storefront served
55
+ * from a custom domain (`{cdnBase}/_next/static/media/…`), where the platform restores the namespace
56
+ * toward storage at the edge so the stored object key is unchanged. Defaults to `false` — the
57
+ * platform CDN keeps the namespace in the URL (`{cdnBase}/s/{shopId}/…`). The deploy pipeline sets
58
+ * this from the same provisioning signal that picks the asset host, so the URL form and the storage
59
+ * key can never disagree.
60
+ */
61
+ cleanUrl?: boolean;
53
62
  }
54
63
  /**
55
64
  * Framework build-output path prefixes — hashed/immutable assets the framework already
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/core/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,2GAA2G;IAC3G,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAE7D,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,2GAA2G;IAC3G,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,uDAAwD,CAAC;AAmF9F,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC,MAAM,CAiER;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiD5F"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/core/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,sCAAsC;IACtC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,eAAe;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,2GAA2G;IAC3G,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAMD;;;GAGG;AACH,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAE7D,6EAA6E;AAC7E,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,2GAA2G;IAC3G,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,uDAAwD,CAAC;AAyF9F,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC,MAAM,CAqER;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiD5F"}
@@ -72,24 +72,27 @@ function nextStaticMediaSuffix(pathname) {
72
72
  /** Scheme + authority of an absolute http(s) URL — everything up to the first path `/`. */
73
73
  const ABSOLUTE_URL_AUTHORITY = /^https?:\/\/[^/]+/i;
74
74
  /**
75
- * Suffix after this shop's `/s/{shopId}/_next/static/media/` when `src` is an ABSOLUTE URL — a
76
- * code-imported image whose `src` carries the storefront's Next.js `assetPrefix`
77
- * (`{assetPrefixBase}/s/{shopId}/_next/static/media/{suffix}`, which Next prepends before the loader
78
- * runs). `null` for relative srcs, other shops' assets, and foreign hosts. Anchored on `/s/{shopId}/`
79
- * so a foreign host that merely embeds the marker mid-path is rejected; matched on path structure, not
80
- * host the asset-prefix CDN host is not part of the loader config, only the resize base is.
75
+ * Suffix after the media segment when `src` is an ABSOLUTE URL — a code-imported image whose `src`
76
+ * carries the storefront's Next.js `assetPrefix` (which Next prepends before the loader runs). The
77
+ * anchor is the storage namespace `ns` (`/s/{shopId}` by default, empty when `cleanUrl`):
78
+ * - default: `{assetPrefixBase}/s/{shopId}/_next/static/media/{suffix}` (`ns` = `/s/{shopId}`);
79
+ * - clean: `{assetPrefixBase}/_next/static/media/{suffix}` (`ns` = ``).
80
+ * Anchored on the EXACT `${ns}/_next/static/media/`, so a foreign host that merely embeds the marker
81
+ * mid-path is rejected. `null` for relative srcs, other namespaces, and foreign hosts. Matched on
82
+ * path structure, not host — the asset-prefix host is not part of the loader config, only the resize
83
+ * base is.
81
84
  *
82
85
  * The path is taken from the RAW `src` (strip scheme/authority + query/hash), NOT via `URL.pathname`:
83
86
  * that percent-encodes the path, which would double-encode in {@link buildNextMediaCdnUrl}. The
84
87
  * root-relative counterpart {@link nextStaticMediaSuffix} likewise feeds a raw path, so both `src`
85
88
  * forms of one import — relative (no `assetPrefix`) and absolute (with it) — encode identically.
86
89
  */
87
- function absoluteNextMediaSuffix(src, shopId) {
90
+ function absoluteNextMediaSuffix(src, ns) {
88
91
  // Fast reject before any allocation: must be an absolute http(s) URL that mentions the media segment.
89
92
  if (!ABSOLUTE_URL_AUTHORITY.test(src) || !src.includes(NEXT_STATIC_MEDIA_PREFIX))
90
93
  return null;
91
94
  const path = src.replace(ABSOLUTE_URL_AUTHORITY, '').replace(/[?#].*$/, '');
92
- const prefix = `/s/${shopId}${NEXT_STATIC_MEDIA_PREFIX}`;
95
+ const prefix = `${ns}${NEXT_STATIC_MEDIA_PREFIX}`;
93
96
  return path.startsWith(prefix) ? path.slice(prefix.length) : null;
94
97
  }
95
98
  /**
@@ -101,16 +104,23 @@ function absoluteNextMediaSuffix(src, shopId) {
101
104
  * `encodeURIComponent` keeps `..` (unreserved) — harmless while the image CDN is unsigned + public;
102
105
  * if HMAC signing is ever added, strip `..` segments here AND in the public/ branch.
103
106
  *
107
+ * `ns` is the storage namespace (empty for a custom domain, `/s/{shopId}` for the platform CDN); the
108
+ * platform restores it toward storage for a custom domain, so the stored object key is the same.
109
+ *
104
110
  * @sync-with backend deploy mirror (`_next/static/media/` mirrored 1:1 into the image-CDN key)
105
111
  */
106
- function buildNextMediaCdnUrl(base, shopId, suffix, width) {
112
+ function buildNextMediaCdnUrl(base, ns, suffix, width) {
107
113
  const encoded = suffix.split('/').map(encodeURIComponent).join('/');
108
- return `${base}/s/${shopId}/_next/static/media/${encoded}?width=${width}`;
114
+ return `${base}${ns}/_next/static/media/${encoded}?width=${width}`;
109
115
  }
110
116
  export function buildImageLoaderUrl(config, args) {
111
117
  // `||` (not `??`): an empty injected base must still fall back to the platform default.
112
118
  const base = (config.cdnBase || IMAGE_CDN_BASE_URL).replace(/\/+$/, '');
113
119
  const { src, width } = args;
120
+ // Storage namespace prepended to local-asset URLs: empty when clean (a custom domain restores it
121
+ // toward storage), `/s/{shopId}` otherwise. Computed once, threaded through both URL builders and
122
+ // the absolute-media anchor so the form is decided in one place.
123
+ const ns = (config.cleanUrl ?? false) ? '' : `/s/${config.shopId}`;
114
124
  // (1) Product image — already an absolute CDN URL. Set the per-srcset width.
115
125
  if (src.startsWith(base)) {
116
126
  try {
@@ -129,9 +139,9 @@ export function buildImageLoaderUrl(config, args) {
129
139
  // `_next/static/media/` but are not images, so the extension gate leaves them to load raw from
130
140
  // the asset CDN (they are not mirrored to the resize CDN).
131
141
  if (config.shopId) {
132
- const mediaSuffix = absoluteNextMediaSuffix(src, config.shopId);
142
+ const mediaSuffix = absoluteNextMediaSuffix(src, ns);
133
143
  if (mediaSuffix !== null && LOADER_IMAGE_EXTENSIONS.test(mediaSuffix)) {
134
- return buildNextMediaCdnUrl(base, config.shopId, mediaSuffix, width);
144
+ return buildNextMediaCdnUrl(base, ns, mediaSuffix, width);
135
145
  }
136
146
  }
137
147
  // (2) Local root-relative image — NOT protocol-relative (`//host`). Two sub-cases:
@@ -149,7 +159,7 @@ export function buildImageLoaderUrl(config, args) {
149
159
  // (2a) Next build-output media image — same image-CDN key as the absolute (assetPrefix) form (1b).
150
160
  const mediaSuffix = nextStaticMediaSuffix(pathname);
151
161
  if (mediaSuffix !== null) {
152
- return buildNextMediaCdnUrl(base, config.shopId, mediaSuffix, width);
162
+ return buildNextMediaCdnUrl(base, ns, mediaSuffix, width);
153
163
  }
154
164
  // Any other framework build output (hashed/immutable, NOT mirrored) → untouched.
155
165
  const buildPrefixes = config.buildAssetPrefixes ?? FRAMEWORK_BUILD_PREFIXES;
@@ -166,7 +176,7 @@ export function buildImageLoaderUrl(config, args) {
166
176
  .split('/')
167
177
  .map(encodeURIComponent)
168
178
  .join('/');
169
- return `${base}/s/${config.shopId}/public/${path}?width=${width}&v=${config.version}`;
179
+ return `${base}${ns}/public/${path}?width=${width}&v=${config.version}`;
170
180
  }
171
181
  // (3) Build assets, protocol-relative/external URLs, data URIs — untouched.
172
182
  return src;
@@ -39,7 +39,7 @@ export type { StorefrontClient, StorefrontClientConfig, Middleware, ExecuteFn, G
39
39
  export { createRemoteDebugTransport } from './client/remote-debug-transport';
40
40
  export type { RemoteDebugTransport, RemoteDebugTransportConfig } from './client/remote-debug-transport';
41
41
  export { authMiddleware } from './middleware/auth';
42
- export { cartSecretMiddleware, serverCartSecretMiddleware, CART_SECRET_HEADER, } from './middleware/cart-secret';
42
+ export { cartSecretMiddleware, serverCartSecretMiddleware, isCartScopedOperation, CART_SECRET_HEADER, } from './middleware/cart-secret';
43
43
  export { currencyMiddleware } from './middleware/currency';
44
44
  export { languageMiddleware } from './middleware/language';
45
45
  export { forwardedIpMiddleware, forwardedIpSignedMessage, FORWARDED_IP_HEADER, FORWARDED_IP_TS_HEADER, FORWARDED_IP_SIG_HEADER, type ForwardedIpMiddlewareOptions, } from './middleware/forwarded-ip';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAGpC,YAAY,EACV,gBAAgB,EAChB,sBAAsB,EACtB,UAAU,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,YAAY,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAGxG,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,4BAA4B,GAClC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,8BAA8B,EACnC,KAAK,YAAY,GAClB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAG9F,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC;AAGjF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAGpF,OAAO,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,0BAA0B,EAC1B,KAAK,cAAc,GACpB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,YAAY,EACV,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,wBAAwB,EACxB,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,+BAA+B,EAC/B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAEV,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,KAAK,EACL,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,EACL,cAAc,EAGd,aAAa,EACb,uBAAuB,EACvB,uBAAuB,EACvB,+BAA+B,EAC/B,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,WAAW,EAEX,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,2BAA2B,EAC3B,gBAAgB,EAChB,2BAA2B,EAC3B,0BAA0B,EAC1B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAGhB,gBAAgB,EAEhB,wBAAwB,EACxB,YAAY,EACZ,uBAAuB,GACxB,MAAM,cAAc,CAAC;AAQtB,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,4BAA4B,EAC5B,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,8BAA8B,GAC/B,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACnG,YAAY,EACV,QAAQ,EACR,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,2BAA2B,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,mBAAmB,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,GAC1B,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,0BAA0B,EAC1B,8BAA8B,EAC9B,KAAK,yBAAyB,GAC/B,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG/G,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG/G,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,YAAY,EAAE,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAG/E,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAKlF,OAAO,EACL,KAAK,SAAS,EACd,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
@@ -42,7 +42,7 @@ export { isPublicReadEligible, IDENTITY_HEADERS, VARIANCE_AXIS_HEADERS, VARIANCE
42
42
  export { createRemoteDebugTransport } from './client/remote-debug-transport';
43
43
  // Middleware
44
44
  export { authMiddleware } from './middleware/auth';
45
- export { cartSecretMiddleware, serverCartSecretMiddleware, CART_SECRET_HEADER, } from './middleware/cart-secret';
45
+ export { cartSecretMiddleware, serverCartSecretMiddleware, isCartScopedOperation, CART_SECRET_HEADER, } from './middleware/cart-secret';
46
46
  export { currencyMiddleware } from './middleware/currency';
47
47
  export { languageMiddleware } from './middleware/language';
48
48
  export { forwardedIpMiddleware, forwardedIpSignedMessage, FORWARDED_IP_HEADER, FORWARDED_IP_TS_HEADER, FORWARDED_IP_SIG_HEADER, } from './middleware/forwarded-ip';
@@ -3,6 +3,13 @@
3
3
  * cart access secret. Possession of the secret is what authorizes cart
4
4
  * operations; the cart id alone is not enough.
5
5
  *
6
+ * The header is attached **only to cart operations** (classified by
7
+ * {@link isCartScopedOperation} — operation names with a `Cart` prefix). Public
8
+ * reads such as product listings, search and recommendations never carry the
9
+ * secret, so they stay eligible for the shared response cache even when the
10
+ * visitor already has a cart. Pass a custom classifier as the second argument
11
+ * to override which operations are treated as cart-scoped.
12
+ *
6
13
  * Two variants share one header contract:
7
14
  *
8
15
  * - **Client** (`cartSecretMiddleware`) resolves the secret lazily on every
@@ -27,17 +34,38 @@ import type { CartCredentials } from '../cart/cookie-config';
27
34
  /** Request header carrying the cart access secret. */
28
35
  export declare const CART_SECRET_HEADER = "x-cart-secret";
29
36
  /**
30
- * Client cart-secret middleware. `getSecret` is read on every request so a
31
- * rotated secret is picked up without rebuilding the pipeline. No header is
32
- * sent when the secret is absent (legacy plain-id cookie) the backend then
33
- * treats the cart as unreachable and the SDK recreates one.
37
+ * Default classifier deciding whether an operation should carry the cart access
38
+ * secret. Cart operations are named with a `Cart` prefix (`Cart`, `CartAddLines`,
39
+ * `CartComplete`, `CartAvailableShippingMethods`, ). Three operations are
40
+ * deliberately excluded because none of them is bound to a specific cart, so the
41
+ * secret would be meaningless on them:
42
+ * - `AvailablePaymentMethods` — a shop-level read (cacheable);
43
+ * - `OrderByToken` — a guest order lookup authorized by an opaque order token
44
+ * (not cacheable — served `no-store`);
45
+ * - `PaymentCreate` — a mutation operating on an order.
46
+ *
47
+ * Withholding the secret keeps the cacheable shop-level read in the shared cache
48
+ * (carrying the secret would mark it identity-bearing and push it off); for the
49
+ * order operations it simply avoids sending a credential they never read.
50
+ */
51
+ export declare function isCartScopedOperation(operationName: string | undefined): boolean;
52
+ /**
53
+ * Client cart-secret middleware. The header is sent only for cart-scoped
54
+ * operations (`isCartScoped`, default {@link isCartScopedOperation}); public
55
+ * reads stay cacheable and never touch the cookie. For a cart operation,
56
+ * `getSecret` is read fresh on each request so a rotated secret (recovery
57
+ * redeem) is picked up without rebuilding the pipeline. No header is sent when
58
+ * the secret is absent (legacy plain-id cookie) — the backend then treats the
59
+ * cart as unreachable and the SDK recreates one.
34
60
  */
35
- export declare function cartSecretMiddleware(getSecret: () => string | null | undefined): Middleware;
61
+ export declare function cartSecretMiddleware(getSecret: () => string | null | undefined, isCartScoped?: (operationName: string | undefined) => boolean): Middleware;
36
62
  /**
37
63
  * Server cart-secret middleware. Takes the credentials already read from the
38
64
  * request cookies (`readCartCredentials`) — prepend it to a server client so
39
- * SSR / edge cart reads carry the secret. No header is sent when credentials
40
- * are null or carry no secret.
65
+ * SSR / edge cart reads carry the secret. As with the client variant, the
66
+ * header is sent only for cart-scoped operations (`isCartScoped`, default
67
+ * {@link isCartScopedOperation}). No header is sent when credentials are null or
68
+ * carry no secret.
41
69
  */
42
- export declare function serverCartSecretMiddleware(credentials: CartCredentials | null): Middleware;
70
+ export declare function serverCartSecretMiddleware(credentials: CartCredentials | null, isCartScoped?: (operationName: string | undefined) => boolean): Middleware;
43
71
  //# sourceMappingURL=cart-secret.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cart-secret.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/cart-secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,GACzC,UAAU,CAQZ;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,eAAe,GAAG,IAAI,GAClC,UAAU,CAOZ"}
1
+ {"version":3,"file":"cart-secret.d.ts","sourceRoot":"","sources":["../../../src/core/middleware/cart-secret.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,kBAAkB,CAAC;AAElD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAEhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,EAC1C,YAAY,GAAE,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,KAAK,OAA+B,GACnF,UAAU,CAYZ;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,eAAe,GAAG,IAAI,EACnC,YAAY,GAAE,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,KAAK,OAA+B,GACnF,UAAU,CAOZ"}
@@ -3,6 +3,13 @@
3
3
  * cart access secret. Possession of the secret is what authorizes cart
4
4
  * operations; the cart id alone is not enough.
5
5
  *
6
+ * The header is attached **only to cart operations** (classified by
7
+ * {@link isCartScopedOperation} — operation names with a `Cart` prefix). Public
8
+ * reads such as product listings, search and recommendations never carry the
9
+ * secret, so they stay eligible for the shared response cache even when the
10
+ * visitor already has a cart. Pass a custom classifier as the second argument
11
+ * to override which operations are treated as cart-scoped.
12
+ *
6
13
  * Two variants share one header contract:
7
14
  *
8
15
  * - **Client** (`cartSecretMiddleware`) resolves the secret lazily on every
@@ -25,16 +32,41 @@
25
32
  /** Request header carrying the cart access secret. */
26
33
  export const CART_SECRET_HEADER = 'x-cart-secret';
27
34
  /**
28
- * Client cart-secret middleware. `getSecret` is read on every request so a
29
- * rotated secret is picked up without rebuilding the pipeline. No header is
30
- * sent when the secret is absent (legacy plain-id cookie) the backend then
31
- * treats the cart as unreachable and the SDK recreates one.
35
+ * Default classifier deciding whether an operation should carry the cart access
36
+ * secret. Cart operations are named with a `Cart` prefix (`Cart`, `CartAddLines`,
37
+ * `CartComplete`, `CartAvailableShippingMethods`, ). Three operations are
38
+ * deliberately excluded because none of them is bound to a specific cart, so the
39
+ * secret would be meaningless on them:
40
+ * - `AvailablePaymentMethods` — a shop-level read (cacheable);
41
+ * - `OrderByToken` — a guest order lookup authorized by an opaque order token
42
+ * (not cacheable — served `no-store`);
43
+ * - `PaymentCreate` — a mutation operating on an order.
44
+ *
45
+ * Withholding the secret keeps the cacheable shop-level read in the shared cache
46
+ * (carrying the secret would mark it identity-bearing and push it off); for the
47
+ * order operations it simply avoids sending a credential they never read.
48
+ */
49
+ export function isCartScopedOperation(operationName) {
50
+ return typeof operationName === 'string' && operationName.startsWith('Cart');
51
+ }
52
+ /**
53
+ * Client cart-secret middleware. The header is sent only for cart-scoped
54
+ * operations (`isCartScoped`, default {@link isCartScopedOperation}); public
55
+ * reads stay cacheable and never touch the cookie. For a cart operation,
56
+ * `getSecret` is read fresh on each request so a rotated secret (recovery
57
+ * redeem) is picked up without rebuilding the pipeline. No header is sent when
58
+ * the secret is absent (legacy plain-id cookie) — the backend then treats the
59
+ * cart as unreachable and the SDK recreates one.
32
60
  */
33
- export function cartSecretMiddleware(getSecret) {
61
+ export function cartSecretMiddleware(getSecret, isCartScoped = isCartScopedOperation) {
34
62
  return (request, next) => {
35
- const secret = getSecret();
36
- if (secret) {
37
- request.headers[CART_SECRET_HEADER] = secret;
63
+ // Gate on the cheap operation-name check first so public reads (the
64
+ // high-volume path) skip the secret getter (a cookie read) entirely.
65
+ if (isCartScoped(request.operationName)) {
66
+ const secret = getSecret();
67
+ if (secret) {
68
+ request.headers[CART_SECRET_HEADER] = secret;
69
+ }
38
70
  }
39
71
  return next(request);
40
72
  };
@@ -42,12 +74,14 @@ export function cartSecretMiddleware(getSecret) {
42
74
  /**
43
75
  * Server cart-secret middleware. Takes the credentials already read from the
44
76
  * request cookies (`readCartCredentials`) — prepend it to a server client so
45
- * SSR / edge cart reads carry the secret. No header is sent when credentials
46
- * are null or carry no secret.
77
+ * SSR / edge cart reads carry the secret. As with the client variant, the
78
+ * header is sent only for cart-scoped operations (`isCartScoped`, default
79
+ * {@link isCartScopedOperation}). No header is sent when credentials are null or
80
+ * carry no secret.
47
81
  */
48
- export function serverCartSecretMiddleware(credentials) {
82
+ export function serverCartSecretMiddleware(credentials, isCartScoped = isCartScopedOperation) {
49
83
  return (request, next) => {
50
- if (credentials?.cartSecret) {
84
+ if (credentials?.cartSecret && isCartScoped(request.operationName)) {
51
85
  request.headers[CART_SECRET_HEADER] = credentials.cartSecret;
52
86
  }
53
87
  return next(request);
@@ -1 +1 @@
1
- {"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAkcH,eAAO,MAAM,UAAU,QAOrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAehD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAO1C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAO/B,CAAC;AAMH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAW3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAWjC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAMH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAWrB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,QAY/B,CAAC;AAMH,eAAO,MAAM,yBAAyB,QAWpC,CAAC;AAEH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,QAWtC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,oBAAoB,QAW/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAWhC,CAAC;AAEH,eAAO,MAAM,+BAA+B,QAW1C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAWxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAWvC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
1
+ {"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAmcH,eAAO,MAAM,UAAU,QAOrB,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,qCAAqC,QAehD,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B,QAO1C,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,QAO/B,CAAC;AAMH,eAAO,MAAM,WAAW,QAYtB,CAAC;AAEH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,iBAAiB,QAW5B,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,gBAAgB,QAW3B,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,QAWjC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAMH;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAWrB,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,QAY/B,CAAC;AAMH,eAAO,MAAM,yBAAyB,QAWpC,CAAC;AAEH,eAAO,MAAM,wBAAwB,QAWnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,QAWtC,CAAC;AAEH,eAAO,MAAM,0BAA0B,QAWrC,CAAC;AAEH,eAAO,MAAM,oBAAoB,QAW/B,CAAC;AAEH,eAAO,MAAM,qBAAqB,QAWhC,CAAC;AAEH,eAAO,MAAM,+BAA+B,QAW1C,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa,QAWxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAWzB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAWvC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,QAoBtC,CAAC"}
@@ -277,6 +277,7 @@ const ORDER_FRAGMENT = `
277
277
  expiredAt
278
278
  shippingAddress { ...MailingAddress }
279
279
  itemCount
280
+ customerNote
280
281
  discountAllocations {
281
282
  discountCode
282
283
  amount { ...Money }
@@ -12,10 +12,10 @@
12
12
  * export default createImageLoader();
13
13
  * ```
14
14
  *
15
- * Zero configuration: the shop identifier, deployment version, and image-CDN base URL are
16
- * read from the public environment variables the DoSwiftly deploy pipeline injects
17
- * (`NEXT_PUBLIC_SHOP_ID`, `NEXT_PUBLIC_DEPLOYMENT_COMMIT`, `NEXT_PUBLIC_IMGPROXY_BASE`).
18
- * Pass overrides only for tests or non-standard hosting.
15
+ * Zero configuration: the shop identifier, deployment version, image-CDN base URL, and clean-URL
16
+ * flag are read from the public environment variables the DoSwiftly deploy pipeline injects
17
+ * (`NEXT_PUBLIC_SHOP_ID`, `NEXT_PUBLIC_DEPLOYMENT_COMMIT`, `NEXT_PUBLIC_IMGPROXY_BASE`,
18
+ * `NEXT_PUBLIC_ASSET_CLEAN_URL`). Pass overrides only for tests or non-standard hosting.
19
19
  *
20
20
  * This entry is Next-specific (it reads `NEXT_PUBLIC_*`); the framework-agnostic core (`.`)
21
21
  * stays free of it.
@@ -1 +1 @@
1
- {"version":3,"file":"image-loader.d.ts","sourceRoot":"","sources":["../../src/next/image-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5E,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAClC,CAAC,IAAI,EAAE,mBAAmB,KAAK,MAAM,CAevC"}
1
+ {"version":3,"file":"image-loader.d.ts","sourceRoot":"","sources":["../../src/next/image-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAuB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE5E,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAClC,CAAC,IAAI,EAAE,mBAAmB,KAAK,MAAM,CAgBvC"}
@@ -12,10 +12,10 @@
12
12
  * export default createImageLoader();
13
13
  * ```
14
14
  *
15
- * Zero configuration: the shop identifier, deployment version, and image-CDN base URL are
16
- * read from the public environment variables the DoSwiftly deploy pipeline injects
17
- * (`NEXT_PUBLIC_SHOP_ID`, `NEXT_PUBLIC_DEPLOYMENT_COMMIT`, `NEXT_PUBLIC_IMGPROXY_BASE`).
18
- * Pass overrides only for tests or non-standard hosting.
15
+ * Zero configuration: the shop identifier, deployment version, image-CDN base URL, and clean-URL
16
+ * flag are read from the public environment variables the DoSwiftly deploy pipeline injects
17
+ * (`NEXT_PUBLIC_SHOP_ID`, `NEXT_PUBLIC_DEPLOYMENT_COMMIT`, `NEXT_PUBLIC_IMGPROXY_BASE`,
18
+ * `NEXT_PUBLIC_ASSET_CLEAN_URL`). Pass overrides only for tests or non-standard hosting.
19
19
  *
20
20
  * This entry is Next-specific (it reads `NEXT_PUBLIC_*`); the framework-agnostic core (`.`)
21
21
  * stays free of it.
@@ -39,6 +39,7 @@ export function createImageLoader(config) {
39
39
  shopId: config?.shopId ?? process.env.NEXT_PUBLIC_SHOP_ID ?? '',
40
40
  version: config?.version ?? process.env.NEXT_PUBLIC_DEPLOYMENT_COMMIT ?? '',
41
41
  cdnBase: config?.cdnBase ?? process.env.NEXT_PUBLIC_IMGPROXY_BASE,
42
+ cleanUrl: config?.cleanUrl ?? (process.env.NEXT_PUBLIC_ASSET_CLEAN_URL === 'true'),
42
43
  };
43
44
  // Dev-only hint: surface raster images that the loader can't optimize (an external host, or
44
45
  // a build asset outside `/_next/static/media/`). Only when a shopId is resolved — without one
@@ -1 +1 @@
1
- {"version":3,"file":"storefront-client-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-client-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAOzD,OAAO,EAA2B,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAKhH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CACxB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,oEAAoE;IACpE,aAAa,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,+DAA+D;IAC/D,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,4HAA4H;IAC5H,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,UAAU,EAAE,gBAAqB,EACjC,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,EAAE,6BAA6B,2CA8E/B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,4BAA4B,CAMzE"}
1
+ {"version":3,"file":"storefront-client-provider.d.ts","sourceRoot":"","sources":["../../../src/react/providers/storefront-client-provider.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAA6C,MAAM,OAAO,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAOzD,OAAO,EAA2B,KAAK,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAKhH,OAAO,KAAK,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAEpG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,gBAAgB,CAAC;IACzB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CACxB;AAID,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;IAC/B;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,oEAAoE;IACpE,aAAa,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAClD,+DAA+D;IAC/D,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,4HAA4H;IAC5H,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,MAAM,EACN,UAAU,EAAE,gBAAqB,EACjC,aAAa,EACb,uBAAuB,EACvB,qBAAqB,EACrB,YAAY,GACb,EAAE,6BAA6B,2CAiF/B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,4BAA4B,CAMzE"}
@@ -13,7 +13,7 @@ import { createStorefrontClient } from '../../core/client/create-client';
13
13
  import { CartClient } from '../../core/cart/cart-client';
14
14
  import { AuthClient } from '../../core/auth/auth-client';
15
15
  import { authMiddleware } from '../../core/middleware/auth';
16
- import { cartSecretMiddleware } from '../../core/middleware/cart-secret';
16
+ import { cartSecretMiddleware, isCartScopedOperation } from '../../core/middleware/cart-secret';
17
17
  import { CART_COOKIE_NAME, parseCartCookieValue } from '../../core/cart/cookie-config';
18
18
  import { getCookie } from '../cookies';
19
19
  import { currencyMiddleware } from '../../core/middleware/currency';
@@ -67,7 +67,9 @@ export function StorefrontClientProvider({ children, config, middleware: customM
67
67
  authMiddleware(() => authStore.getState().accessToken),
68
68
  // Cart access secret — read lazily from the composite cart-id cookie so
69
69
  // a rotated secret (recovery redeem) is picked up without rebuilding.
70
- cartSecretMiddleware(() => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartSecret ?? null),
70
+ // Attached only to cart operations (passed explicitly for clarity; it is
71
+ // the default) so public reads stay cacheable when a cart exists.
72
+ cartSecretMiddleware(() => parseCartCookieValue(getCookie(CART_COOKIE_NAME))?.cartSecret ?? null, isCartScopedOperation),
71
73
  currencyMiddleware(() => currencyStore.getState().currency),
72
74
  languageMiddleware(() => languageStore.getState().language),
73
75
  // Bot protection (if configured)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-sdk",
3
- "version": "22.8.1",
3
+ "version": "22.10.0",
4
4
  "description": "Storefront runtime SDK for DoSwiftly Commerce — layered transport, middleware pipeline, React providers, Zustand stores, cache strategies. 0 runtime dependencies in core.",
5
5
  "type": "module",
6
6
  "sideEffects": false,