@doswiftly/storefront-sdk 4.2.0 → 4.3.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/dist/core/image.d.ts +18 -9
- package/dist/core/image.d.ts.map +1 -1
- package/dist/core/image.js +32 -12
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/package.json +1 -1
- package/src/core/image.ts +40 -12
- package/src/core/index.ts +2 -0
package/dist/core/image.d.ts
CHANGED
|
@@ -35,21 +35,30 @@ export interface ImageLoaderParams {
|
|
|
35
35
|
quality?: number;
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* Width
|
|
45
|
-
* No HMAC, no env vars, no setup — like Shopify Hydrogen's image loader.
|
|
38
|
+
* Image format for imgproxy output.
|
|
39
|
+
*/
|
|
40
|
+
export type ImageFormat = 'webp' | 'avif' | 'jpeg';
|
|
41
|
+
/**
|
|
42
|
+
* Default image loader — WebP format. Used as global loaderFile in next.config.ts.
|
|
43
|
+
* Zero configuration: works out-of-the-box with GraphQL image URLs.
|
|
44
|
+
* Width quantized to preset breakpoints for optimal CDN cache.
|
|
46
45
|
*
|
|
47
46
|
* @example
|
|
48
47
|
* ```tsx
|
|
49
48
|
* import { storefrontImageLoader } from '@doswiftly/storefront-sdk';
|
|
50
|
-
*
|
|
51
49
|
* <Image loader={storefrontImageLoader} src={image.url} width={800} alt="..." />
|
|
52
50
|
* ```
|
|
53
51
|
*/
|
|
54
52
|
export declare function storefrontImageLoader({ src, width, quality }: ImageLoaderParams): string;
|
|
53
|
+
/**
|
|
54
|
+
* Create a custom loader with specific format (avif, jpeg).
|
|
55
|
+
* Use as per-component override when you need a different format than default WebP.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```tsx
|
|
59
|
+
* const avifLoader = createImageLoader('avif');
|
|
60
|
+
* <Image loader={avifLoader} src={image.url} width={800} alt="..." />
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function createImageLoader(format: ImageFormat): (params: ImageLoaderParams) => string;
|
|
55
64
|
//# sourceMappingURL=image.d.ts.map
|
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;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,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;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/core/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,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;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAenD;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,iBAAiB,GAAG,MAAM,CAExF;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,MAAM,CAE5F"}
|
package/dist/core/image.js
CHANGED
|
@@ -24,25 +24,45 @@ function nearestPresetWidth(requested) {
|
|
|
24
24
|
return PRESET_WIDTHS[PRESET_WIDTHS.length - 1];
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* Appends resize query params (?width=&quality=&format=) to the URL
|
|
31
|
-
* that backend already returned via GraphQL.
|
|
32
|
-
*
|
|
33
|
-
* Width is quantized to preset breakpoints for optimal CDN cache.
|
|
34
|
-
* No HMAC, no env vars, no setup — like Shopify Hydrogen's image loader.
|
|
27
|
+
* Default image loader — WebP format. Used as global loaderFile in next.config.ts.
|
|
28
|
+
* Zero configuration: works out-of-the-box with GraphQL image URLs.
|
|
29
|
+
* Width quantized to preset breakpoints for optimal CDN cache.
|
|
35
30
|
*
|
|
36
31
|
* @example
|
|
37
32
|
* ```tsx
|
|
38
33
|
* import { storefrontImageLoader } from '@doswiftly/storefront-sdk';
|
|
39
|
-
*
|
|
40
34
|
* <Image loader={storefrontImageLoader} src={image.url} width={800} alt="..." />
|
|
41
35
|
* ```
|
|
42
36
|
*/
|
|
43
37
|
export function storefrontImageLoader({ src, width, quality }) {
|
|
38
|
+
return buildImgproxyUrl(src, width, quality);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create a custom loader with specific format (avif, jpeg).
|
|
42
|
+
* Use as per-component override when you need a different format than default WebP.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* const avifLoader = createImageLoader('avif');
|
|
47
|
+
* <Image loader={avifLoader} src={image.url} width={800} alt="..." />
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function createImageLoader(format) {
|
|
51
|
+
return ({ src, width, quality }) => buildImgproxyUrl(src, width, quality, format);
|
|
52
|
+
}
|
|
53
|
+
function buildImgproxyUrl(src, width, quality, format = 'webp') {
|
|
44
54
|
const w = nearestPresetWidth(width);
|
|
45
|
-
const q = quality
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
const q = quality ?? 85;
|
|
56
|
+
if (!src.startsWith('http')) {
|
|
57
|
+
return src;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const url = new URL(src);
|
|
61
|
+
const path = url.pathname.slice(1);
|
|
62
|
+
return `${url.origin}/rs:fit:${w}:0:0/q:${q}/f:${format}/plain/${path}`;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Malformed URL — return as-is, let browser handle it
|
|
66
|
+
return src;
|
|
67
|
+
}
|
|
48
68
|
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -61,7 +61,7 @@ export { CART_COOKIE_NAME, CART_COOKIE_MAX_AGE } from './cart/cookie-config';
|
|
|
61
61
|
export { matchesRoute, type RouteProtectionConfig } from './auth/routes';
|
|
62
62
|
export { createSetTokenHandler, createClearTokenHandler } from './auth/handlers';
|
|
63
63
|
export { createAuthTokenClient, type AuthTokenClient } from './auth/token-client';
|
|
64
|
-
export { storefrontImageLoader, type ImageData, type ImageLoaderParams, } from './image';
|
|
64
|
+
export { storefrontImageLoader, createImageLoader, type ImageData, type ImageLoaderParams, type ImageFormat, } from './image';
|
|
65
65
|
export { getOperationName } from './client/operation-name';
|
|
66
66
|
export { hashQuery } from './client/hash';
|
|
67
67
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"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"}
|
package/dist/core/index.js
CHANGED
|
@@ -75,7 +75,7 @@ export { createSetTokenHandler, createClearTokenHandler } from './auth/handlers'
|
|
|
75
75
|
// Auth token client (client-side fetch helpers)
|
|
76
76
|
export { createAuthTokenClient } from './auth/token-client';
|
|
77
77
|
// Image utilities
|
|
78
|
-
export { storefrontImageLoader, } from './image';
|
|
78
|
+
export { storefrontImageLoader, createImageLoader, } from './image';
|
|
79
79
|
// Utilities
|
|
80
80
|
export { getOperationName } from './client/operation-name';
|
|
81
81
|
export { hashQuery } from './client/hash';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@doswiftly/storefront-sdk",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.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
|
"types": "dist/core/index.d.ts",
|
package/src/core/image.ts
CHANGED
|
@@ -37,6 +37,11 @@ export interface ImageLoaderParams {
|
|
|
37
37
|
quality?: number;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Image format for imgproxy output.
|
|
42
|
+
*/
|
|
43
|
+
export type ImageFormat = 'webp' | 'avif' | 'jpeg';
|
|
44
|
+
|
|
40
45
|
/**
|
|
41
46
|
* Preset widths for CDN cache optimization.
|
|
42
47
|
* Loader quantizes requested width to the nearest preset — limits cache variants.
|
|
@@ -51,25 +56,48 @@ function nearestPresetWidth(requested: number): number {
|
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
/**
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
* Appends resize query params (?width=&quality=&format=) to the URL
|
|
58
|
-
* that backend already returned via GraphQL.
|
|
59
|
-
*
|
|
60
|
-
* Width is quantized to preset breakpoints for optimal CDN cache.
|
|
61
|
-
* No HMAC, no env vars, no setup — like Shopify Hydrogen's image loader.
|
|
59
|
+
* Default image loader — WebP format. Used as global loaderFile in next.config.ts.
|
|
60
|
+
* Zero configuration: works out-of-the-box with GraphQL image URLs.
|
|
61
|
+
* Width quantized to preset breakpoints for optimal CDN cache.
|
|
62
62
|
*
|
|
63
63
|
* @example
|
|
64
64
|
* ```tsx
|
|
65
65
|
* import { storefrontImageLoader } from '@doswiftly/storefront-sdk';
|
|
66
|
-
*
|
|
67
66
|
* <Image loader={storefrontImageLoader} src={image.url} width={800} alt="..." />
|
|
68
67
|
* ```
|
|
69
68
|
*/
|
|
70
69
|
export function storefrontImageLoader({ src, width, quality }: ImageLoaderParams): string {
|
|
70
|
+
return buildImgproxyUrl(src, width, quality);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create a custom loader with specific format (avif, jpeg).
|
|
75
|
+
* Use as per-component override when you need a different format than default WebP.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```tsx
|
|
79
|
+
* const avifLoader = createImageLoader('avif');
|
|
80
|
+
* <Image loader={avifLoader} src={image.url} width={800} alt="..." />
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function createImageLoader(format: ImageFormat): (params: ImageLoaderParams) => string {
|
|
84
|
+
return ({ src, width, quality }) => buildImgproxyUrl(src, width, quality, format);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function buildImgproxyUrl(src: string, width: number, quality?: number, format: ImageFormat = 'webp'): string {
|
|
71
88
|
const w = nearestPresetWidth(width);
|
|
72
|
-
const q = quality
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
const q = quality ?? 85;
|
|
90
|
+
|
|
91
|
+
if (!src.startsWith('http')) {
|
|
92
|
+
return src;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
const url = new URL(src);
|
|
97
|
+
const path = url.pathname.slice(1);
|
|
98
|
+
return `${url.origin}/rs:fit:${w}:0:0/q:${q}/f:${format}/plain/${path}`;
|
|
99
|
+
} catch {
|
|
100
|
+
// Malformed URL — return as-is, let browser handle it
|
|
101
|
+
return src;
|
|
102
|
+
}
|
|
75
103
|
}
|
package/src/core/index.ts
CHANGED
|
@@ -169,8 +169,10 @@ export { createAuthTokenClient, type AuthTokenClient } from './auth/token-client
|
|
|
169
169
|
// Image utilities
|
|
170
170
|
export {
|
|
171
171
|
storefrontImageLoader,
|
|
172
|
+
createImageLoader,
|
|
172
173
|
type ImageData,
|
|
173
174
|
type ImageLoaderParams,
|
|
175
|
+
type ImageFormat,
|
|
174
176
|
} from './image';
|
|
175
177
|
|
|
176
178
|
// Utilities
|