@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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## 22.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - b1e622d: Add a zero-config Next.js image loader. Re-export `createImageLoader()` from the new
8
+ `@doswiftly/storefront-sdk/next` entry in your `images.loaderFile` and every `<Image>`
9
+ is routed through the image CDN: product images get a real responsive `srcset` (a width
10
+ per entry, so you can drop `transform: { maxWidth }`) and local `public/` images are
11
+ resized and format-negotiated (AVIF/WebP) instead of shipped at full size. Build assets,
12
+ external / protocol-relative URLs and `data:` URIs pass through untouched, and
13
+ `<Image quality>` is a no-op (quality is applied server-side; the format is auto-negotiated). The pure
14
+ `buildImageLoaderUrl` helper is also exported from the package root for non-`<Image>` use.
15
+
16
+ Usage:
17
+
18
+ ```ts
19
+ // lib/image-loader.ts
20
+ import { createImageLoader } from "@doswiftly/storefront-sdk/next";
21
+ export default createImageLoader();
22
+ ```
23
+
24
+ ```ts
25
+ // next.config.ts — bound the generated widths for fewer transforms / better cache hits
26
+ export default {
27
+ images: {
28
+ loader: "custom",
29
+ loaderFile: "./lib/image-loader.ts",
30
+ deviceSizes: [640, 750, 828, 1080, 1200, 1920],
31
+ imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
32
+ },
33
+ };
34
+ ```
35
+
36
+ Migration:
37
+ - New install — nothing to do; existing `<Image>` usage keeps working.
38
+ - Optional — drop `transform: { maxWidth }` from product-image queries; the loader now sets the width per `srcset` entry.
39
+
40
+ ### Patch Changes
41
+
42
+ - 91c3b25: Ship TypeScript types for the codegen recipe (`@doswiftly/storefront-operations/codegen`). A `codegen.ts` that imports `createCodegenConfig` now type-checks under `strict` mode, so `next build` no longer fails with a missing-declaration (implicit `any`) error on the recipe import.
43
+
44
+ ## 22.5.1
45
+
46
+ ### Patch Changes
47
+
48
+ - 6ca2a5f: Corrected the GraphQL schema descriptions for the `CartStatus` enum and the `Cart.status` field so they match the cart's actual behaviour: an `ABANDONED` cart is revived in place by any deliberate buyer edit (it is not locked), editing an `EXPIRED` cart returns `CART_NOT_FOUND`, and only `CONVERTED` / completed carts return `ALREADY_COMPLETED`. Documentation only — no type or API changes.
49
+
3
50
  ## 22.5.0
4
51
 
5
52
  ### Minor Changes
package/README.md CHANGED
@@ -229,6 +229,7 @@ retried.
229
229
  | `@doswiftly/storefront-sdk` | Core: transport, middleware, clients, recovery, errors, format, enums, cookie contracts | **0** |
230
230
  | `@doswiftly/storefront-sdk/react` | Providers, hooks, stores, pre-built UI components | react, zustand |
231
231
  | `@doswiftly/storefront-sdk/react/server` | Server client factory, SDK-BFF auth route, cookie readers | react (peer; `getInitialAuth` additionally requires Next.js) |
232
+ | `@doswiftly/storefront-sdk/next` | Zero-config Next.js adapters — `createImageLoader()` for `images.loaderFile` | **0** |
232
233
  | `@doswiftly/storefront-sdk/cache` | Cache strategy functions | **0** |
233
234
 
234
235
  ## Authentication
@@ -735,6 +736,57 @@ import { Money, PriceDisplay, CartCount } from '@doswiftly/storefront-sdk/react'
735
736
  <CartCount count={3} label="items" />
736
737
  ```
737
738
 
739
+ ## Images — zero-config `next/image` loader
740
+
741
+ `createImageLoader()` is a drop-in loader for Next.js `images.loaderFile`. It
742
+ routes every `<Image>` through the image CDN so each one is resized to the
743
+ viewport (real responsive `srcset`) and format-negotiated (AVIF/WebP from the
744
+ browser `Accept` header) — no per-image configuration.
745
+
746
+ Create the loader file (zero arguments):
747
+
748
+ ```ts
749
+ // lib/image-loader.ts
750
+ import { createImageLoader } from '@doswiftly/storefront-sdk/next';
751
+
752
+ export default createImageLoader();
753
+ ```
754
+
755
+ Point Next.js at it, and bound the generated sizes so a fixed set of widths is
756
+ produced (fewer transforms, better cache hit rate):
757
+
758
+ ```ts
759
+ // next.config.ts
760
+ const nextConfig = {
761
+ images: {
762
+ loader: 'custom',
763
+ loaderFile: './lib/image-loader.ts',
764
+ deviceSizes: [640, 750, 828, 1080, 1200, 1920],
765
+ imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
766
+ },
767
+ };
768
+ export default nextConfig;
769
+ ```
770
+
771
+ The loader is global and handles each `<Image src>` by category:
772
+
773
+ | `src` | Handling |
774
+ |-------|----------|
775
+ | Product image (CDN URL from the GraphQL API) | Width set per `srcset` entry — drop `transform: { maxWidth }`, the loader owns the width |
776
+ | Local `public/` image (e.g. `/hero.webp`) | Routed through the CDN, resized + format-negotiated |
777
+ | Build asset (`/_next/*`), absolute external URL, `data:` URI | Returned unchanged |
778
+
779
+ The loader reads `NEXT_PUBLIC_SHOP_ID`, `NEXT_PUBLIC_DEPLOYMENT_COMMIT`, and
780
+ `NEXT_PUBLIC_IMGPROXY_BASE` — all injected by the platform at build/deploy time. When
781
+ they are absent (e.g. local `doswiftly dev`, where `public/` images are served by the
782
+ dev server) the loader leaves local `public/` images untouched; product images, being
783
+ absolute CDN URLs, are unaffected. `<Image quality>` is a no-op — quality is applied
784
+ server-side (the format is still auto-negotiated AVIF/WebP). Pass explicit overrides only for non-standard setups:
785
+ `createImageLoader({ shopId, version, cdnBase })`.
786
+
787
+ For non-`<Image>` usage (CSS backgrounds, raw `<img>`), build CDN URLs yourself
788
+ with the pure helper `buildImageLoaderUrl` from `@doswiftly/storefront-sdk`.
789
+
738
790
  ## Middleware pipeline
739
791
 
740
792
  Default order (wired automatically by `StorefrontProvider`):
@@ -551,7 +551,7 @@ export type Cart = Node & {
551
551
  selectedShippingMethod?: Maybe<CartShippingMethod>;
552
552
  /** Shipping address attached to the cart via `cartSetShippingAddress`. Null until set. */
553
553
  shippingAddress?: Maybe<MailingAddress>;
554
- /** Lifecycle status — `ACTIVE` for the editable working cart, terminal otherwise. Check this on SSR before rendering the checkout form: a non-`ACTIVE` cart should redirect (typically to the order confirmation when `completedOrder` is populated) instead of presenting a form whose first mutation fails with `CartErrorCode.ALREADY_COMPLETED`. */
554
+ /** Lifecycle status — `ACTIVE` / `RECOVERED` are editable; `ABANDONED` is a recovery flag a deliberate buyer action revives in place; `CONVERTED` / `EXPIRED` are terminal. Check this on SSR before rendering the checkout form: a `CONVERTED` cart should redirect (typically to the order confirmation when `completedOrder` is populated) instead of presenting a form whose first mutation fails with `CartErrorCode.ALREADY_COMPLETED`. */
555
555
  status: CartStatus;
556
556
  /** Sum of `quantity` across all lines — the badge number for the cart icon. */
557
557
  totalQuantity: Scalars['Int']['output'];