@doswiftly/storefront-sdk 22.5.0 → 22.6.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.
@@ -1,11 +1,19 @@
1
1
  /**
2
2
  * Image types and utilities for DoSwiftly storefronts.
3
3
  *
4
- * GraphQL API returns ready-to-use CDN URLs with transform query params.
5
- * No client-side loader needed use `url(transform: { maxWidth: 800 })` in queries.
4
+ * Two ways images reach the browser:
5
+ * - **Product images**: the GraphQL API returns ready-to-use CDN URLs (you may
6
+ * request a size with `url(transform: { maxWidth: 800 })`, but with the image
7
+ * loader below the size is no longer needed — the loader sets it per srcset entry).
8
+ * - **Local images** (your `public/` folder, e.g. a hero or logo used with the
9
+ * Next.js `<Image>` component): routed through the image CDN by the loader so they
10
+ * are resized + format-negotiated instead of shipped at full size.
6
11
  *
7
- * imgproxy auto-negotiates AVIF/WEBP from browser Accept header (IMGPROXY_AUTO_AVIF=true).
8
- * Do NOT hardcode preferredContentType let CDN serve the best format.
12
+ * The image CDN auto-negotiates AVIF/WebP from the browser `Accept` header, so do NOT
13
+ * hardcode a formatthe best one is served automatically.
14
+ *
15
+ * The URL-building below is pure + framework-agnostic. The zero-config Next.js loader
16
+ * (`createImageLoader()`) lives in `@doswiftly/storefront-sdk/next`.
9
17
  */
10
18
  /**
11
19
  * Image data from GraphQL API (matches Image type in storefront schema).
@@ -24,6 +32,37 @@ export interface ImageData {
24
32
  /** ThumbHash placeholder (base64-encoded ~40 chars). Decode with thumbHashToDataURL() for blur preview. */
25
33
  thumbhash?: string | null;
26
34
  }
35
+ /**
36
+ * Base URL of the DoSwiftly image CDN. Platform-owned constant — storefronts never
37
+ * configure it (the override exists only for tests / non-standard hosting).
38
+ */
39
+ export declare const IMAGE_CDN_BASE_URL = "https://img.doswiftly.pl";
40
+ /** Per-storefront configuration the image loader needs to build CDN URLs. */
41
+ export interface ImageLoaderConfig {
42
+ /** Shop identifier — namespaces this storefront's local images in CDN storage. */
43
+ shopId: string;
44
+ /** Current deployment version — busts the cache when a `public/` image is replaced under the same name. */
45
+ version: string;
46
+ /** Override the image CDN base URL. Defaults to {@link IMAGE_CDN_BASE_URL}. */
47
+ cdnBase?: string;
48
+ /**
49
+ * Framework build-output path prefixes to leave untouched (hashed/immutable assets the
50
+ * framework already fingerprints). Defaults to {@link FRAMEWORK_BUILD_PREFIXES}.
51
+ */
52
+ buildAssetPrefixes?: readonly string[];
53
+ }
54
+ /**
55
+ * Framework build-output path prefixes — hashed/immutable assets the framework already
56
+ * fingerprints; never route them through the image CDN. Covers Next/Nuxt/Astro/SvelteKit
57
+ * (underscore-prefixed → collision-free with merchant `public/` folders). Override via
58
+ * {@link ImageLoaderConfig.buildAssetPrefixes} for other conventions (e.g. a Vite-based
59
+ * framework serving build output under `/assets/`, which can collide with `public/assets/`).
60
+ */
61
+ export declare const FRAMEWORK_BUILD_PREFIXES: readonly ["/_next/", "/_nuxt/", "/_astro/", "/_app/"];
62
+ export declare function buildImageLoaderUrl(config: ImageLoaderConfig, args: {
63
+ src: string;
64
+ width: number;
65
+ }): string;
27
66
  /**
28
67
  * Decode a base64-encoded ThumbHash to a data URL for use as a blur placeholder.
29
68
  *
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/core/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;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;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;CACxC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,uDAAwD,CAAC;AA2B9F,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,iBAAiB,EACzB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACnC,MAAM,CAuCR;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAiD5F"}
@@ -1,12 +1,100 @@
1
1
  /**
2
2
  * Image types and utilities for DoSwiftly storefronts.
3
3
  *
4
- * GraphQL API returns ready-to-use CDN URLs with transform query params.
5
- * No client-side loader needed use `url(transform: { maxWidth: 800 })` in queries.
4
+ * Two ways images reach the browser:
5
+ * - **Product images**: the GraphQL API returns ready-to-use CDN URLs (you may
6
+ * request a size with `url(transform: { maxWidth: 800 })`, but with the image
7
+ * loader below the size is no longer needed — the loader sets it per srcset entry).
8
+ * - **Local images** (your `public/` folder, e.g. a hero or logo used with the
9
+ * Next.js `<Image>` component): routed through the image CDN by the loader so they
10
+ * are resized + format-negotiated instead of shipped at full size.
6
11
  *
7
- * imgproxy auto-negotiates AVIF/WEBP from browser Accept header (IMGPROXY_AUTO_AVIF=true).
8
- * Do NOT hardcode preferredContentType let CDN serve the best format.
12
+ * The image CDN auto-negotiates AVIF/WebP from the browser `Accept` header, so do NOT
13
+ * hardcode a formatthe best one is served automatically.
14
+ *
15
+ * The URL-building below is pure + framework-agnostic. The zero-config Next.js loader
16
+ * (`createImageLoader()`) lives in `@doswiftly/storefront-sdk/next`.
17
+ */
18
+ // ---------------------------------------------------------------------------
19
+ // Image loader URL builder (client-side, pure) — feeds the Next.js `<Image>` loader
20
+ // ---------------------------------------------------------------------------
21
+ /**
22
+ * Base URL of the DoSwiftly image CDN. Platform-owned constant — storefronts never
23
+ * configure it (the override exists only for tests / non-standard hosting).
9
24
  */
25
+ export const IMAGE_CDN_BASE_URL = 'https://img.doswiftly.pl';
26
+ /**
27
+ * Framework build-output path prefixes — hashed/immutable assets the framework already
28
+ * fingerprints; never route them through the image CDN. Covers Next/Nuxt/Astro/SvelteKit
29
+ * (underscore-prefixed → collision-free with merchant `public/` folders). Override via
30
+ * {@link ImageLoaderConfig.buildAssetPrefixes} for other conventions (e.g. a Vite-based
31
+ * framework serving build output under `/assets/`, which can collide with `public/assets/`).
32
+ */
33
+ export const FRAMEWORK_BUILD_PREFIXES = ['/_next/', '/_nuxt/', '/_astro/', '/_app/'];
34
+ /**
35
+ * Pure URL builder behind the Next.js image loader. Maps one `<Image>` request
36
+ * (`src` + the width Next.js asks for) to an image-CDN URL, in three cases:
37
+ *
38
+ * 1. **Product image** — `src` is already a CDN URL from the GraphQL API. The
39
+ * requested `width` is set per srcset entry, so the same image renders at the
40
+ * right size for each viewport (truly responsive).
41
+ * 2. **Local `public/` image** — `src` is a root-relative path (e.g. `/hero.webp`),
42
+ * routed through the CDN (resize + format negotiation) from the storefront's
43
+ * uploaded local images.
44
+ * 3. **Anything else** — Next.js build assets (`/_next/*`), absolute external URLs,
45
+ * and `data:` URIs are returned unchanged.
46
+ *
47
+ * Framework-agnostic + side-effect free.
48
+ */
49
+ /**
50
+ * Image formats the loader routes through the resize CDN. MUST stay in sync with the
51
+ * backend deploy mirror — the loader may only point `<Image>` at a `public/` path the
52
+ * deploy actually mirrored. SVG is intentionally excluded: vectors are passed through,
53
+ * not rasterized.
54
+ *
55
+ * @sync-with backend cli.controller.ts `isPublicImageKey`
56
+ */
57
+ const LOADER_IMAGE_EXTENSIONS = /\.(png|jpe?g|webp|avif|gif)$/i;
58
+ export function buildImageLoaderUrl(config, args) {
59
+ // `||` (not `??`): an empty injected base must still fall back to the platform default.
60
+ const base = (config.cdnBase || IMAGE_CDN_BASE_URL).replace(/\/+$/, '');
61
+ const { src, width } = args;
62
+ // (1) Product image — already an absolute CDN URL. Set the per-srcset width.
63
+ if (src.startsWith(base)) {
64
+ try {
65
+ const url = new URL(src);
66
+ url.searchParams.set('width', String(width));
67
+ return url.toString();
68
+ }
69
+ catch {
70
+ return src;
71
+ }
72
+ }
73
+ // (2) Local public/ image — root-relative, NOT protocol-relative (`//host`).
74
+ if (src.startsWith('/') && !src.startsWith('//')) {
75
+ // Not in a deployed storefront (no shop/version) → leave untouched, no resize.
76
+ if (!config.shopId || !config.version)
77
+ return src;
78
+ // Drop any author query/hash — the loader owns `width` and the `?v=` cache-bust.
79
+ const pathname = src.replace(/[?#].*$/, '');
80
+ // Only mirrored image formats; never a framework build asset (any supported framework).
81
+ const buildPrefixes = config.buildAssetPrefixes ?? FRAMEWORK_BUILD_PREFIXES;
82
+ if (buildPrefixes.some((p) => pathname.startsWith(p)) || !LOADER_IMAGE_EXTENSIONS.test(pathname))
83
+ return src;
84
+ // Encode per segment so spaces / non-ASCII filenames match the raw R2 key after the
85
+ // CDN percent-decodes the path (keeps `/` as the separator).
86
+ const path = pathname
87
+ .replace(/^\/+/, '')
88
+ .split('/')
89
+ .map(encodeURIComponent)
90
+ .join('/');
91
+ // Name-stable CDN key; the deploy version rides in `?v=` to bust the CDN cache when a
92
+ // public/ image is replaced under the same name (the source key is overwritten in place).
93
+ return `${base}/s/${config.shopId}/public/${path}?width=${width}&v=${config.version}`;
94
+ }
95
+ // (3) Build assets, protocol-relative/external URLs, data URIs — untouched.
96
+ return src;
97
+ }
10
98
  // ---------------------------------------------------------------------------
11
99
  // ThumbHash decoder (client-side) — algorithm by Evan Wallace
12
100
  // Pure math, zero dependencies, framework-agnostic.
@@ -74,7 +74,7 @@ export { matchesRoute, type RouteProtectionConfig } from './auth/routes';
74
74
  export { createSetTokenHandler, createClearTokenHandler, createWhoamiHandler, originAllowlistValidator, trustedForwardedHostValidator, } from './auth/handlers';
75
75
  export type { OriginValidator, OriginValidatorContext } from './auth/handlers';
76
76
  export { createAuthTokenClient, type AuthTokenClient } from './auth/token-client';
77
- export { type ImageData, thumbHashToDataURL } from './image';
77
+ export { type ImageData, thumbHashToDataURL, IMAGE_CDN_BASE_URL, FRAMEWORK_BUILD_PREFIXES, buildImageLoaderUrl, type ImageLoaderConfig, } from './image';
78
78
  export { getOperationName } from './client/operation-name';
79
79
  export { hashQuery } from './client/hash';
80
80
  //# sourceMappingURL=index.d.ts.map
@@ -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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"}
@@ -95,8 +95,10 @@ export { matchesRoute } from './auth/routes';
95
95
  export { createSetTokenHandler, createClearTokenHandler, createWhoamiHandler, originAllowlistValidator, trustedForwardedHostValidator, } from './auth/handlers';
96
96
  // Auth token client (client-side fetch helpers)
97
97
  export { createAuthTokenClient } from './auth/token-client';
98
- // Image types (loaders removed GraphQL returns ready-to-use CDN URLs with transform params)
99
- export { thumbHashToDataURL } from './image';
98
+ // Image types + loader URL builder. Product images come pre-transformed from the
99
+ // GraphQL API; the pure `buildImageLoaderUrl` powers the Next.js `<Image>` loader
100
+ // (zero-config wrapper `createImageLoader()` lives in `@doswiftly/storefront-sdk/next`).
101
+ export { thumbHashToDataURL, IMAGE_CDN_BASE_URL, FRAMEWORK_BUILD_PREFIXES, buildImageLoaderUrl, } from './image';
100
102
  // Utilities
101
103
  export { getOperationName } from './client/operation-name';
102
104
  export { hashQuery } from './client/hash';
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Next.js `<Image>` loader for DoSwiftly storefronts.
3
+ *
4
+ * Wire it once:
5
+ * ```ts
6
+ * // next.config.ts
7
+ * const nextConfig = { images: { loader: 'custom', loaderFile: './lib/image-loader.ts' } };
8
+ * ```
9
+ * ```ts
10
+ * // lib/image-loader.ts
11
+ * import { createImageLoader } from '@doswiftly/storefront-sdk/next';
12
+ * export default createImageLoader();
13
+ * ```
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.
19
+ *
20
+ * This entry is Next-specific (it reads `NEXT_PUBLIC_*`); the framework-agnostic core (`.`)
21
+ * stays free of it.
22
+ */
23
+ import { type ImageLoaderConfig } from '../core/image';
24
+ /** Arguments Next.js passes to a custom image loader. */
25
+ export interface NextImageLoaderArgs {
26
+ src: string;
27
+ width: number;
28
+ /**
29
+ * Next's per-image quality hint. Not applied — the image CDN negotiates the format
30
+ * (AVIF/WebP) from the browser `Accept` header and applies a fixed server-side quality,
31
+ * so `<Image quality>` / `images.qualities` are intentional no-ops on this loader.
32
+ */
33
+ quality?: number;
34
+ }
35
+ /**
36
+ * Create a Next.js custom image loader — the function `images.loaderFile` /
37
+ * `<Image loader>` expects.
38
+ *
39
+ * Each field defaults from the DoSwiftly deploy environment, so the common usage is
40
+ * argument-free: `export default createImageLoader();`. Any field passed explicitly
41
+ * overrides the env default (useful in tests / non-standard hosting).
42
+ *
43
+ * The env vars are read as LITERAL `process.env.NEXT_PUBLIC_*` member accesses on purpose:
44
+ * Next/Turbopack only inlines those into the client bundle. A dynamic `process.env[name]`
45
+ * read is left as-is and resolves to `undefined` in the browser — which would silently
46
+ * disable the loader and cause a server/client hydration mismatch.
47
+ */
48
+ export declare function createImageLoader(config?: Partial<ImageLoaderConfig>): (args: NextImageLoaderArgs) => string;
49
+ //# sourceMappingURL=image-loader.d.ts.map
@@ -0,0 +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,CAOvC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Next.js `<Image>` loader for DoSwiftly storefronts.
3
+ *
4
+ * Wire it once:
5
+ * ```ts
6
+ * // next.config.ts
7
+ * const nextConfig = { images: { loader: 'custom', loaderFile: './lib/image-loader.ts' } };
8
+ * ```
9
+ * ```ts
10
+ * // lib/image-loader.ts
11
+ * import { createImageLoader } from '@doswiftly/storefront-sdk/next';
12
+ * export default createImageLoader();
13
+ * ```
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.
19
+ *
20
+ * This entry is Next-specific (it reads `NEXT_PUBLIC_*`); the framework-agnostic core (`.`)
21
+ * stays free of it.
22
+ */
23
+ import { buildImageLoaderUrl } from '../core/image';
24
+ /**
25
+ * Create a Next.js custom image loader — the function `images.loaderFile` /
26
+ * `<Image loader>` expects.
27
+ *
28
+ * Each field defaults from the DoSwiftly deploy environment, so the common usage is
29
+ * argument-free: `export default createImageLoader();`. Any field passed explicitly
30
+ * overrides the env default (useful in tests / non-standard hosting).
31
+ *
32
+ * The env vars are read as LITERAL `process.env.NEXT_PUBLIC_*` member accesses on purpose:
33
+ * Next/Turbopack only inlines those into the client bundle. A dynamic `process.env[name]`
34
+ * read is left as-is and resolves to `undefined` in the browser — which would silently
35
+ * disable the loader and cause a server/client hydration mismatch.
36
+ */
37
+ export function createImageLoader(config) {
38
+ const resolved = {
39
+ shopId: config?.shopId ?? process.env.NEXT_PUBLIC_SHOP_ID ?? '',
40
+ version: config?.version ?? process.env.NEXT_PUBLIC_DEPLOYMENT_COMMIT ?? '',
41
+ cdnBase: config?.cdnBase ?? process.env.NEXT_PUBLIC_IMGPROXY_BASE,
42
+ };
43
+ return (args) => buildImageLoaderUrl(resolved, args);
44
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @doswiftly/storefront-sdk/next — Next.js-specific helpers.
3
+ *
4
+ * Utilities that depend on Next.js conventions (the `<Image>` custom loader and
5
+ * build-time public env vars). Kept out of the framework-agnostic core (`.`) so the
6
+ * core stays portable to Node, Edge, Deno, and Bun.
7
+ */
8
+ export { createImageLoader, type NextImageLoaderArgs } from './image-loader';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @doswiftly/storefront-sdk/next — Next.js-specific helpers.
3
+ *
4
+ * Utilities that depend on Next.js conventions (the `<Image>` custom loader and
5
+ * build-time public env vars). Kept out of the framework-agnostic core (`.`) so the
6
+ * core stays portable to Node, Edge, Deno, and Bun.
7
+ */
8
+ export { createImageLoader } from './image-loader';
9
+ // The pure builder + its config/base (`buildImageLoaderUrl`, `IMAGE_CDN_BASE_URL`,
10
+ // `ImageLoaderConfig`) are framework-agnostic and live on the core entry
11
+ // (`@doswiftly/storefront-sdk`) — import them from there, not from `/next`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-sdk",
3
- "version": "22.5.0",
3
+ "version": "22.6.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,
@@ -23,6 +23,10 @@
23
23
  "types": "./dist/react/server/index.d.ts",
24
24
  "default": "./dist/react/server/index.js"
25
25
  },
26
+ "./next": {
27
+ "types": "./dist/next/index.d.ts",
28
+ "default": "./dist/next/index.js"
29
+ },
26
30
  "./cache": {
27
31
  "types": "./dist/core/cache.d.ts",
28
32
  "default": "./dist/core/cache.js"