@doswiftly/storefront-operations 11.1.0 → 11.3.1

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/AGENTS.md CHANGED
@@ -27,7 +27,7 @@ consumer's `codegen.ts` references this package's `.graphql` files as
27
27
  live in the consumer's repo.
28
28
 
29
29
  <!-- AUTOGEN:STATS:BEGIN — auto-regenerated, do not edit by hand -->
30
- - **Schema version**: 11.1.0
30
+ - **Schema version**: 11.3.1
31
31
  - **Queries**: 48
32
32
  - **Mutations**: 40
33
33
  - **Fragments**: 100
package/CHANGELOG.md CHANGED
@@ -1,5 +1,136 @@
1
1
  # Changelog
2
2
 
3
+ ## 11.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9ca724e: Removes the `./schema` subpath export from `@doswiftly/storefront-sdk` — it was a duplicate of what `@doswiftly/storefront-operations` already publishes.
8
+
9
+ **Why:**
10
+
11
+ `@doswiftly/storefront-operations` is a linked package — it is always installed alongside `@doswiftly/storefront-sdk`. It exposes the GraphQL SDL as a raw `schema.graphql` file via the `./schema.graphql` subpath export, which is the format every codegen tool and IDE GraphQL plugin natively consumes. Bundling the same SDL again as an ESM string literal in `@doswiftly/storefront-sdk/schema` added ~128 KB to the npm tarball without giving consumers a meaningful capability that wasn't already there.
12
+
13
+ **Migration:**
14
+
15
+ Switch from:
16
+
17
+ ```ts
18
+ import { schema } from "@doswiftly/storefront-sdk/schema";
19
+ ```
20
+
21
+ to a direct path reference in your codegen config (or `graphql-config` for your IDE):
22
+
23
+ ```ts
24
+ // codegen.ts
25
+ const config = {
26
+ schema: "node_modules/@doswiftly/storefront-operations/schema.graphql",
27
+ // …
28
+ };
29
+ ```
30
+
31
+ The schema content is byte-for-byte identical — your codegen output does not change.
32
+
33
+ **Internal:**
34
+ - Removed `scripts/build-schema-export.cjs` and the matching `pnpm build` chain step.
35
+ - `pnpm build` is now plain `tsc` again.
36
+ - Removed the `dist/schema.js` + `dist/schema.d.ts` build artifacts and the `schema-export.test.ts` unit test.
37
+ - `pnpm run doctor` no longer checks for the schema bundle.
38
+
39
+ `@doswiftly/storefront-operations` is bumped in lockstep (no code change — required because the packages are linked and ship together).
40
+
41
+ ## 11.3.0
42
+
43
+ ### Minor Changes
44
+
45
+ - 0a2dfd8: Phase 1 of the senior-level audit ships security hardening, dead-code cleanup, and a coverage gate.
46
+
47
+ **Security:**
48
+ - `createSetTokenHandler`, `createClearTokenHandler`, `createWhoamiHandler` now validate the `Origin` header against the `Host` header by parsed URL host (`new URL(origin).host === host`) instead of a substring `includes()` check. The previous implementation was bypassable by empty Host (`includes('')` is always true) and by Origin URLs that embedded the trusted host in their query string. Requests without both `Origin` and `Host` headers now respond with `403`.
49
+
50
+ **Removed:**
51
+ - `ServerClientOptions.getHeaders` (accepted by `getStorefrontClient()` but never wired through). Inject request-scoped headers via the `middleware` option — see updated JSDoc.
52
+
53
+ **Internal:**
54
+ - Inconsistent `setIsRenewingToken` setter in `useAuth` is renamed to `setIsRefreshingToken` to match the exposed `isRefreshingToken` flag.
55
+ - Removed an unused `callbackName` field in `TurnstileManager` and a pre-cookie-era `localStorage.removeItem('cart-storage')` call in `createCartStore`.
56
+
57
+ **Infrastructure:**
58
+ - `package.json` now declares `sideEffects: false` so consumer bundlers can tree-shake unused exports aggressively.
59
+ - Adds `test:coverage` script (`vitest run --coverage`) with a baseline threshold (60% statements / 50% branches / 55% functions / 60% lines). The floor will rise as later phases cover the React providers, auth/currency/language stores, and remaining hooks.
60
+ - Adds 102 new unit tests across `format`, `image`, `cookies`, `auth/handlers`, and additional `errorMiddleware`/`timeoutMiddleware`/`languageMiddleware` cases — including two regression tests for the origin-validation bypass vectors.
61
+
62
+ `@doswiftly/storefront-operations` is bumped in lockstep (no code change — required because the packages are linked and ship together).
63
+
64
+ - 09c3744: Phase 2 of the SDK audit ships the developer-experience features external storefront builders have been writing by hand: pre-built React components, tagged-union mutation state, a bundled GraphQL schema export, and a focused-hook auth API.
65
+
66
+ **Pre-built React components** (from `@doswiftly/storefront-sdk/react`):
67
+
68
+ Six headless, accessibility-aware components — zero styling, framework-agnostic, no `next/image` dependency so they work in any React 18/19 environment.
69
+ - `<Money amount currency>` — locale-formatted price from minor units (wraps `formatPrice`).
70
+ - `<Image data sizes priority>` — `<img>` with thumbhash blur placeholder, lazy by default, `fetchpriority` hint.
71
+ - `<CartCount count label hideWhenEmpty>` — aria-live cart item count.
72
+ - `<AddToCartButton variantId quantity onSuccess onError>` — orchestrates `useCartManager.addItem` with loading state + sr-only error alert.
73
+ - `<PriceDisplay price compareAtPrice currency>` — current price + optional strikethrough sale price.
74
+ - `<CartTotals subtotal discount shipping tax total currency labels>` — `<dl>` breakdown that elides empty rows.
75
+
76
+ **Tagged-union status in `useCartManager`**:
77
+ - New `status` field on the hook return — `{ type: 'idle' | 'loading' | 'error' | 'success', operation? }` — enables exhaustive switching without juggling booleans.
78
+ - `isLoading` and `error` remain available as derived selectors (backward-compatible).
79
+ - `clearCart()` resets status to `idle`.
80
+
81
+ **Bundled GraphQL schema** (`@doswiftly/storefront-sdk/schema`):
82
+ - New export path ships the full GraphQL SDL (123 KB) as a string constant, regenerated from `@doswiftly/storefront-operations/schema.graphql` on each build.
83
+ - Wire GraphQL codegen / IDE plugins without a live backend — no extra `npm install`.
84
+
85
+ **`useAuth` split into focused hooks**:
86
+ - `useLogin({ onSetToken })` — login flow only, `{ login, isLoggingIn, error }`.
87
+ - `useLogout({ onClearToken })` — logout, always clears local store even on backend failure.
88
+ - `useRefreshToken({ onSetToken })` — token rotation, keeps existing customer.
89
+ - `useAuth(options)` is preserved as a thin facade composing the three (backward-compatible, no breaking change).
90
+
91
+ Prefer the focused hooks in new code — smaller bundles, isolated state, smaller dependency arrays.
92
+
93
+ **Docs**:
94
+ - README adds a 7-step Next.js 16 App Router setup, BFF route handler examples, components catalog, bundled schema usage.
95
+ - New `docs/storefront-developer/sdk/nextjs-setup.md` and `auth.md` with end-to-end recipes.
96
+
97
+ **Tests**: 476 → 494 unit tests (+18). New files: `components.test.tsx` (37 cases), `schema-export.test.ts` (5 cases), `use-auth.test.tsx` (13 cases). Build clean, 0-deps invariant preserved.
98
+
99
+ `@doswiftly/storefront-operations` is bumped in lockstep (no code change — required because the packages are linked and ship together).
100
+
101
+ ## 11.2.0
102
+
103
+ ### Minor Changes
104
+
105
+ - 760f965: Added automatic stale-cart recovery to the core SDK so every consumer (React, Vue, mobile, CLI, SSR) gets the same protection against `CART_NOT_FOUND` / `ALREADY_COMPLETED` errors without re-implementing detection, cookie cleanup, and retry orchestration.
106
+
107
+ **What's new** (importable from `@doswiftly/storefront-sdk`):
108
+ - `isCartRecoverableError(err)` — type-safe predicate that inspects `err.userErrors[].code` (works across PL/EN/any backend locale, unlike message string matching).
109
+ - `CART_RECOVERABLE_ERROR_CODES` — readonly tuple of codes that warrant cart recreation; mirrored against the backend `CartErrorCode` enum by a drift test.
110
+ - `executeWithCartRecovery(opts)` — pure async orchestrator for any consumer.
111
+ - `createCartRecoveryRunner({ cartClient, cookieStore })` — DX-friendly factory that curries the dependencies, shares a Phase-0 concurrency mutex across operations, and exposes an `onExpired(listener)` subscription for global UI feedback.
112
+ - `CartCookieStore` — port interface (`get` / `set` / `clear`) the caller implements once per runtime. From `@doswiftly/storefront-sdk/react` we now also export `createBrowserCartCookieStore()` (SSR-safe).
113
+ - `CartRecoveryNotPossibleError` — thrown when an operation cannot be safely replayed (line-id / shipping-method references the dead cart). Carries `reason: 'state-dependent' | 'recreate-failed' | 'retry-also-failed'` for diagnostic UX.
114
+ - `recreateWithInput(input)` / `recreateWithLines(lines)` — sugar helpers for the most common atomic `cartCreate(payload)` recovery strategies.
115
+
116
+ **Per-operation taxonomy (decision is in the SDK, not in caller code):**
117
+
118
+ | Operation | Strategy |
119
+ | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
120
+ | `addItems`, `updateBuyerIdentity`, `setShippingAddress`, `updateDiscountCodes`, `updateNote` | Auto-replay via a single atomic `cartCreate(input)` — recovery is invisible to the caller |
121
+ | `updateItems`, `removeItems` | Bail with `CartRecoveryNotPossibleError` and emit a `cart-expired` event — replaying on a fresh empty cart would silently lose the user's intent |
122
+
123
+ **React updates:**
124
+ - `useCartManager` now uses the recovery runner internally. Detection is code-based (no more PL/EN regression — previous implementation matched `'cart not found'` in the error message, which never matched a Polish backend response). Recovery now covers all mutations exposed by the hook, not just `addItem`. New methods: `updateBuyerIdentity`, `setShippingAddress`. New API: `onExpired(listener)` returning an unsubscribe function.
125
+ - `createCartStore` now recovers `addToCart` automatically. New optional `CartActions.createCartWithLines(lines)` lets templates wire the atomic single-round-trip path; without it the store falls back to `createCart()` + `addLines()`. `updateQuantity` and `removeFromCart` bail with the `cart-expired` event when the cart is gone (previously the store kept its local id pointing at a dead cart). `CartStoreConfig.onExpired?(event)` lets the consumer subscribe.
126
+
127
+ **Migration:**
128
+ - No required code changes for existing React consumers — `useCartManager` and `createCartStore` keep their public surface.
129
+ - If you previously caught `StorefrontError` to detect stale carts via message string matching, switch to `isCartRecoverableError(err)` (code-based, locale-proof) or — preferably — subscribe to `runner.onExpired(...)` / `useCartManager().onExpired(...)` / `createCartStore({ onExpired })`.
130
+ - Non-React consumers should wrap their cart mutations in `createCartRecoveryRunner` and implement a `CartCookieStore` adapter for their environment (browser via `createBrowserCartCookieStore()`, server-side via `next/headers`, CLI via in-memory `Map`, mobile via AsyncStorage).
131
+
132
+ `@doswiftly/storefront-operations` is bumped in lockstep (no code change — required because the packages are linked and ship together).
133
+
3
134
  ## 11.1.0
4
135
 
5
136
  ### Minor Changes
package/llms-full.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  # DoSwiftly Storefront Operations — Full Reference
2
2
 
3
- > Schema version: **11.1.0**
3
+ > Schema version: **11.3.1**
4
4
  > 48 queries · 40 mutations · 100 fragments
5
5
 
6
6
  Auto-generated from `.graphql` source files. Do not edit by hand — this file is
package/operations.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "schemaVersion": "11.1.0",
2
+ "schemaVersion": "11.3.1",
3
3
  "queries": [
4
4
  {
5
5
  "name": "Shop",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-operations",
3
- "version": "11.1.0",
3
+ "version": "11.3.1",
4
4
  "description": "GraphQL operations for DoSwiftly Storefront - SSOT from backend",
5
5
  "homepage": "https://doswiftly.pl",
6
6
  "publishConfig": {