@doswiftly/storefront-sdk 22.8.1 → 22.9.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 +44 -0
- package/README.md +10 -7
- package/dist/core/generated/operation-types.d.ts +5 -3
- package/dist/core/generated/operation-types.d.ts.map +1 -1
- package/dist/core/image.d.ts +9 -0
- package/dist/core/image.d.ts.map +1 -1
- package/dist/core/image.js +24 -14
- package/dist/core/operations/cart.d.ts.map +1 -1
- package/dist/core/operations/cart.js +1 -0
- package/dist/next/image-loader.d.ts +4 -4
- package/dist/next/image-loader.d.ts.map +1 -1
- package/dist/next/image-loader.js +5 -4
- package/package.json +1 -1
package/dist/core/image.d.ts
CHANGED
|
@@ -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
|
package/dist/core/image.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/core/image.js
CHANGED
|
@@ -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
|
|
76
|
-
*
|
|
77
|
-
* (
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
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,
|
|
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 =
|
|
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,
|
|
112
|
+
function buildNextMediaCdnUrl(base, ns, suffix, width) {
|
|
107
113
|
const encoded = suffix.split('/').map(encodeURIComponent).join('/');
|
|
108
|
-
return `${base}
|
|
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,
|
|
142
|
+
const mediaSuffix = absoluteNextMediaSuffix(src, ns);
|
|
133
143
|
if (mediaSuffix !== null && LOADER_IMAGE_EXTENSIONS.test(mediaSuffix)) {
|
|
134
|
-
return buildNextMediaCdnUrl(base,
|
|
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,
|
|
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}
|
|
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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart.d.ts","sourceRoot":"","sources":["../../../src/core/operations/cart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
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"}
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
* export default createImageLoader();
|
|
13
13
|
* ```
|
|
14
14
|
*
|
|
15
|
-
* Zero configuration: the shop identifier, deployment version,
|
|
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,
|
|
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,
|
|
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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doswiftly/storefront-sdk",
|
|
3
|
-
"version": "22.
|
|
3
|
+
"version": "22.9.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,
|