@doswiftly/storefront-operations 7.0.0 → 7.1.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/README.md CHANGED
@@ -1,199 +1,735 @@
1
1
  # @doswiftly/storefront-operations
2
2
 
3
- Pre-built GraphQL operations and schema for DoSwiftly e-commerce storefronts. Contains the GraphQL schema file, ready-to-use queries, mutations, and fragments for products, collections, cart, checkout, and customer management.
4
-
5
- **No running backend needed for codegen** — the schema is included as a file.
3
+ The **DoSwiftly Storefront API catalog** a versioned, AI-friendly reference
4
+ bundle of the GraphQL schema, named operations, and reusable fragments for
5
+ building storefronts on the DoSwiftly platform.
6
+
7
+ > **This package is a reference catalog and AI knowledge base, not a runtime
8
+ > dependency.** Install it as a `devDependency`. Nothing from this package is
9
+ > imported into your runtime bundle — your AI assistant reads it for context,
10
+ > and (optionally) your codegen reads `schema.graphql` for type generation.
11
+
12
+ > **AI agents** (Cursor, Codex, Claude Code, GitHub Copilot, Aider, Gemini CLI):
13
+ > open [`AGENTS.md`](./AGENTS.md) — the entry point with the critical
14
+ > conventions you need before generating queries. The full operation reference
15
+ > with descriptions, typed variables, and executable bodies lives in
16
+ > [`llms-full.txt`](./llms-full.txt). For structured / programmatic access (MCP
17
+ > servers, custom tools): [`operations.json`](./operations.json).
6
18
 
7
19
  ## Installation
8
20
 
9
21
  ```bash
10
- npm install @doswiftly/storefront-operations
22
+ pnpm add -D @doswiftly/storefront-operations
11
23
  # or
12
- pnpm add @doswiftly/storefront-operations
24
+ npm install --save-dev @doswiftly/storefront-operations
13
25
  ```
14
26
 
15
- ## Quick Start
27
+ It ships only `.graphql` source files plus Markdown / JSON / text reference
28
+ documents — there is no JavaScript to import, no runtime code, no transitive
29
+ runtime deps. Hence `devDependencies`.
16
30
 
17
- ### 1. Install dependencies
31
+ ## What's in the package
18
32
 
19
- ```bash
20
- npm install @doswiftly/storefront-operations @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typed-document-node
33
+ | File | What it's for |
34
+ | ---- | ------------- |
35
+ | `AGENTS.md` | AI agent entry point — critical conventions, anti-hallucination notes |
36
+ | `llms-full.txt` | Full operation reference: descriptions + variables + bodies |
37
+ | `operations.json` | Same operations as structured JSON (MCP / programmatic tools) |
38
+ | `queries.graphql` | All named queries — read as a catalog, copy what you need |
39
+ | `mutations.graphql` | All named mutations — same |
40
+ | `fragments.graphql` | Reusable fragments referenced by queries + mutations |
41
+ | `schema.graphql` | Full GraphQL schema — point your codegen at this for type generation |
42
+
43
+ ## How to use it
44
+
45
+ The intended use is: **install once, consume forever as inspiration + schema
46
+ source**. You write your own operations into your own `src/graphql/`
47
+ directory — either by hand from the catalog, or with an AI assistant
48
+ reading this package's context. The package's `.graphql` operation files are
49
+ **reference patterns**, not bind-time dependencies that ship into your build.
50
+
51
+ ### Primary: AI-assisted (recommended)
52
+
53
+ This is the intended primary path. Install the package, open your repo in
54
+ an AI coding tool, and ask it to build a storefront feature.
55
+
56
+ AI tools that respect the [AGENTS.md convention](https://agents.md/) — Cursor,
57
+ OpenAI Codex, Claude Code, Aider, Gemini CLI — auto-discover
58
+ `node_modules/@doswiftly/storefront-operations/AGENTS.md` from your repo and
59
+ pull it into context. The assistant then knows:
60
+
61
+ - Every operation name, its typed variables, the canonical GraphQL body
62
+ - Anti-hallucination conventions (cart mutations are `cartAddLines` NOT
63
+ `cartLinesAdd`, `userErrors[].code` is `String` not enum, etc.)
64
+ - When to use which fragment (`ProductCard` vs `ProductBase` vs `ProductFull`)
65
+ - Auth and pagination conventions
66
+
67
+ You then ask it to write operations into your `src/graphql/`. No codegen
68
+ config is required for this use case (though you'll likely want codegen for
69
+ type-safe consumption — see below).
70
+
71
+ For AI tools that do NOT auto-discover AGENTS.md from `node_modules`
72
+ (GitHub Copilot Chat, some Cody configurations), explicitly reference it
73
+ in your prompt:
74
+
75
+ ```
76
+ Read @doswiftly/storefront-operations/AGENTS.md and llms-full.txt, then
77
+ write me a product page query in src/graphql/product.graphql.
78
+ ```
79
+
80
+ Or add a one-line pointer to your own workspace `AGENTS.md`:
81
+
82
+ ```markdown
83
+ ## DoSwiftly storefront API
84
+
85
+ Operations + critical conventions live in
86
+ `node_modules/@doswiftly/storefront-operations/AGENTS.md` and `llms-full.txt`.
87
+ Read those before writing GraphQL.
21
88
  ```
22
89
 
23
- ### 2. Create `codegen.ts`
90
+ ### Manual: open the catalog and copy what you need
91
+
92
+ If you're not using an AI assistant (or want to handle this yourself), open
93
+ the `.graphql` files in `node_modules` and treat them as starter examples.
94
+ Find the operation you need, copy it into your `src/graphql/` directory,
95
+ adapt the field selection to your UI.
96
+
97
+ For type safety on the operations *you* write, point GraphQL codegen at the
98
+ package's **schema** (not at its operation files):
24
99
 
25
100
  ```typescript
26
- import { CodegenConfig } from "@graphql-codegen/cli";
101
+ // codegen.ts schema from the package, documents from YOUR repo only
102
+ import type { CodegenConfig } from '@graphql-codegen/cli';
27
103
 
28
104
  const config: CodegenConfig = {
29
- // Schema from package — no running backend needed!
30
- schema: "node_modules/@doswiftly/storefront-operations/schema.graphql",
31
- documents: [
32
- "node_modules/@doswiftly/storefront-operations/**/*.graphql",
33
- "src/**/*.{ts,tsx}", // Your custom operations (optional)
34
- ],
105
+ schema: 'node_modules/@doswiftly/storefront-operations/schema.graphql',
106
+ documents: ['src/graphql/**/*.graphql'],
35
107
  generates: {
36
- "src/generated/graphql.ts": {
37
- plugins: ["typescript", "typescript-operations", "typed-document-node"],
108
+ 'src/generated/graphql.ts': {
109
+ plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
38
110
  },
39
111
  },
40
112
  };
41
-
42
113
  export default config;
43
114
  ```
44
115
 
45
- ### 3. Add script to `package.json`
116
+ The schema lives offline as a file in the package — no running backend needed
117
+ for codegen.
46
118
 
47
- ```json
48
- {
49
- "scripts": {
50
- "codegen": "graphql-codegen --config codegen.ts"
51
- }
52
- }
53
- ```
119
+ ### Advanced: codegen the entire catalog (not recommended for custom storefronts)
54
120
 
55
- ### 4. Run codegen
121
+ You *can* hook the package's operation files directly into your codegen as
122
+ additional `documents:` to get `TypedDocumentNode`s for all upstream
123
+ operations. This is mainly useful for **scaffolded starter templates** that
124
+ want a complete sample storefront out of the box.
56
125
 
57
- ```bash
58
- npm run codegen
59
- ```
126
+ We don't recommend this for custom storefronts because:
60
127
 
61
- ### 5. Use in your components
128
+ - Every operation upstream ends up in your codegen output, even ones you
129
+ don't use (bundle bloat — tree-shaking helps but doesn't fully eliminate)
130
+ - Your generated types become coupled to every selection change upstream
131
+ (a tweak to a fragment in this package can ripple through your generated
132
+ files even though your code doesn't use it)
133
+ - Loses the catalog framing — you stop treating these as patterns and
134
+ start treating them as a hard dependency
62
135
 
63
- ```typescript
64
- import { useQuery } from '@tanstack/react-query';
65
- import { graphqlClient } from '@/lib/graphql-client';
66
- import { ProductsDocument } from '@/generated/graphql';
136
+ If you do choose this path:
67
137
 
68
- export function ProductList() {
69
- const { data, isLoading } = useQuery({
70
- queryKey: ['products'],
71
- queryFn: () => graphqlClient.request(ProductsDocument, { first: 12 }),
72
- });
73
-
74
- if (isLoading) return <div>Loading...</div>;
75
-
76
- return (
77
- <div className="grid grid-cols-3 gap-4">
78
- {data?.products.edges.map(({ node }) => (
79
- <ProductCard key={node.id} product={node} />
80
- ))}
81
- </div>
82
- );
83
- }
138
+ ```typescript
139
+ // codegen.ts both schema AND documents come from the package (advanced)
140
+ const config: CodegenConfig = {
141
+ schema: 'node_modules/@doswiftly/storefront-operations/schema.graphql',
142
+ documents: [
143
+ 'node_modules/@doswiftly/storefront-operations/{queries,mutations,fragments}.graphql',
144
+ 'src/**/*.graphql',
145
+ ],
146
+ // ...
147
+ };
84
148
  ```
85
149
 
86
- ## Available Operations
150
+ ## Available operations
151
+
152
+ Tables below are **auto-generated** from the `.graphql` files in this package
153
+ and regenerated on every release — they cannot drift from the schema.
154
+
155
+ Use them to scan what's available. Click through to `llms-full.txt` for the
156
+ full executable body of each operation.
87
157
 
88
158
  ### Queries
89
159
 
90
- | Operation | Description |
91
- | ------------------- | ---------------------------------------- |
92
- | `Shop` | Shop configuration, currencies, settings |
93
- | `Product` | Single product by ID or handle |
94
- | `Products` | Product list with pagination and filters |
95
- | `ProductSearch` | Full-text product search |
96
- | `Collection` | Collection with its products |
97
- | `Collections` | All collections |
98
- | `Category` | Category with hierarchy |
99
- | `Categories` | Paginowana lista kategorii (Relay Connection) — drzewo budujesz po stronie klienta z `parent`/`children` |
100
- | `Cart` | Cart contents by ID |
101
- | `Customer` | Logged-in customer data |
102
- | `CustomerOrders` | Customer order history |
103
- | `CustomerAddresses` | Customer saved addresses |
160
+ <!-- AUTOGEN:QUERIES:BEGIN — auto-regenerated, do not edit by hand -->
161
+ #### Shop
104
162
 
105
- ### Mutations
163
+ | Operation | Description |
164
+ | --- | --- |
165
+ | `Shop` | Returns shop configuration: name, base + supported currencies, supported locales, branding (logo, colors, fonts, social links), contact info, active payment methods, brand metadata, money format template, and the list of countries the shop ships to. Public; no auth required. Call once per session and cache — almost everything else is contextualized by the shop returned here. |
106
166
 
107
- **Cart**
167
+ #### Products
108
168
 
109
- - `CartCreate` - Create a new cart
110
- - `CartLinesAdd` - Add items to cart
111
- - `CartLinesUpdate` - Update item quantities
112
- - `CartLinesRemove` - Remove items from cart
113
- - `CartDiscountCodesUpdate` - Apply/remove discount codes
114
- - `CartBuyerIdentityUpdate` - Set customer info on cart
115
- - `CartNoteUpdate` - Add note to cart
169
+ | Operation | Description |
170
+ | --- | --- |
171
+ | `Product` | Fetches a single product by `id` or `handle` (URL slug). Pass either — whichever is provided wins; if both are missing, returns null. Returns null if the product is not storefront-accessible (must be `ACTIVE` status with `PUBLIC` or `BUNDLE_ONLY` visibility). |
172
+ | `ProductConfigurator` | Fetches a product together with its filtered attribute definitions, optimized for the configurator UI (e.g. customer-facing text fields, finishing options, scoped variants). `fillingMode: "CUSTOMER"` returns only customer-facing attributes; pass `"BOTH"` to also include attributes shared with the merchant admin. Single round-trip — saves a separate `attributes` query. |
173
+ | `Products` | Paginated product list (Relay Connection, default page size 20, max 100). The `query` argument supports a structured search syntax — `tag:summer`, `vendor:foo`, `product_type:shirts`, `variants.price:>10`, plus `AND`/`OR`/`NOT` — falling back to free-text title/content search. The `filters[]` array uses multi-filter logic: same field name appears multiple times → OR; different fields → AND. Sort: `RELEVANCE`, `TITLE`, `PRICE`, `NEWEST`, `OLDEST`, `BEST_SELLING`. The response includes a `filters` block for faceted navigation (counts per filterable attribute value). |
174
+ | `ProductSearch` | Full-text product search `$query` is required. Functionally equivalent to `Products` with `$query` set, minus the `sortKey` argument (search defaults to relevance ranking). Use for the search results page; combine with `filters[]` for guided refinement. |
175
+ | `PredictiveSearch` | Type-ahead suggestions for the storefront search input. Returns up to `$limit` matching products (hard cap 50) plus up to 5 styled query suggestions with `<mark>` tags around matched spans. Polish-language aware (handles morphology in suggestions). Run on each keystroke (debounce 200-300ms). The `$query` is capped at 100 characters server-side. |
116
176
 
117
- **Authentication**
177
+ #### Collections
118
178
 
119
- - `CustomerSignup` - Register new customer
120
- - `CustomerLogin` - Login and get token
121
- - `CustomerLogout` - Logout
122
- - `CustomerRefreshToken` - Refresh auth token
123
- - `CustomerActivate` - Activate account via email link
124
- - `CustomerMetaPropertiesSet` - Set custom key-value entries on the logged-in customer
125
- - `CustomerMetaPropertyDelete` - Delete a custom key-value entry from the logged-in customer
179
+ | Operation | Description |
180
+ | --- | --- |
181
+ | `Collection` | Fetches a single collection by `id` or `handle`, with paginated products. Collections come in two types: **MANUAL** (curated — products explicitly added by the merchant) and **AUTO** (rule-based — products matched dynamically). Both surfaces use the same field selection. |
182
+ | `Collections` | Paginated list of all active collections (default 20, max 100). Sort by `TITLE` or `UPDATED_AT` via `sortKey`. Note: the `query` argument is reserved for future text filtering — it is currently accepted but ignored. |
126
183
 
127
- **Customer Profile**
184
+ #### Categories
128
185
 
129
- - `CustomerUpdate` - Update profile info
130
- - `CustomerAddAddress` - Add new address
131
- - `CustomerUpdateAddress` - Update address
132
- - `CustomerRemoveAddress` - Remove address
133
- - `CustomerSetDefaultAddress` - Set default address
186
+ | Operation | Description |
187
+ | --- | --- |
188
+ | `Category` | Fetches a single category by `id` or `slug` with its parent and immediate children. Use for breadcrumbs and sub-navigation. Nested queries on `parent` / `children` are batched server-side safe to use in lists without N+1 concerns. |
189
+ | `Categories` | Returns active categories for the shop. Each category exposes its `parent` and `children` — build the tree client-side by walking those fields (server batches the lookups, no N+1). The hierarchy is not depth-capped server-side. Use for nav mega-menus and category pages. |
134
190
 
135
- **Password**
191
+ #### Cart
136
192
 
137
- - `CustomerRequestPasswordReset` - Request password reset email
138
- - `CustomerResetPassword` - Reset password with token
193
+ | Operation | Description |
194
+ | --- | --- |
195
+ | `Cart` | Fetches a cart by `id` (the value persisted by the SDK in the `cart-id` cookie). The cart query is public — no auth needed to read it — but once a customer logs in and gets associated with the cart, mutations enforce ownership. Returns line items (paginated up to 100), totals, applied discount codes, gift cards, buyer identity, note, attributes, and warnings. Refetch after every cart mutation. |
139
196
 
140
- ## Schema
197
+ #### Customer (requires auth)
141
198
 
142
- The package includes `schema.graphql` — the full GraphQL schema auto-generated from the backend (NestJS code-first). This enables **offline codegen** without a running backend.
199
+ | Operation | Description |
200
+ | --- | --- |
201
+ | `Customer` | Full customer profile — basic info plus the first 10 addresses and first 10 orders. Heaviest customer query; for narrow use cases prefer `CustomerProfile` (no orders / addresses) or `CustomerOrder` (single order). Returns null if unauthenticated. |
202
+ | `CustomerProfile` | Lightweight customer profile (no orders, no addresses list). Use for settings / profile pages that only need basic customer info — much cheaper than `Customer`. Returns null if unauthenticated. |
203
+ | `CustomerOrder` | Single order by `orderId`. Returns only orders that belong to the authenticated customer (cross-customer access returns null, not an error). Much cheaper than fetching the full `Customer` payload to access one order. Use on the order detail page. |
143
204
 
144
- To update the schema after backend changes:
205
+ #### Checkout
145
206
 
146
- ```bash
147
- # From monorepo root (requires backend to have been started at least once)
148
- cd packages/@doswiftly/storefront-operations
149
- pnpm run sync
150
- ```
207
+ | Operation | Description |
208
+ | --- | --- |
209
+ | `Checkout` | Fetches a checkout session by `id`. **Important**: `checkoutId` and `cartId` are 1:1 — there is no separate "checkout" record, the response is built dynamically from the cart. Returns line items, addresses, selected shipping rate, available shipping rates + payment methods, applied discount/gift cards (gift card codes are masked for security), and totals (`cost`, `tax`, `paymentDue`). Public read; ownership enforced on mutations. Refetch after every checkout mutation. |
210
+
211
+ #### Payment Methods
212
+
213
+ | Operation | Description |
214
+ | --- | --- |
215
+ | `AvailablePaymentMethods` | Returns the active payment methods for the shop, sorted by the merchant-configured display position. Shop-level — does NOT vary by cart amount or currency. Each method exposes `type` (`CARD`, `BANK_TRANSFER`, `BLIK`, `PAYPAL`, `APPLE_PAY`, `GOOGLE_PAY`, `CASH_ON_DELIVERY`, `OTHER`), provider, icon, description, and supported currencies. Use to render the payment step of checkout. |
216
+
217
+ #### Shipments / Tracking
218
+
219
+ | Operation | Description |
220
+ | --- | --- |
221
+ | `Shipment` | Fetches a shipment by `id` with status, tracking events, recipient address, and shipped/delivered timestamps. **Auth required** — customer access token plus ownership of the parent order. Wrapped response: `{ shipment, userErrors[] }`. Error codes: `INVALID_TOKEN`, `NOT_FOUND` (also returned on ownership mismatch to prevent enumeration), `FETCH_FAILED`. |
222
+ | `ShipmentByTrackingNumber` | **Public** shipment lookup by carrier tracking number — no auth required. Designed for "Track my order" landing pages reachable without login. Returns the basic shipment fragment including recipient address. Wrapped response: `{ shipment, userErrors[] }`. Error codes: `INVALID_INPUT`, `NOT_FOUND`, `FETCH_FAILED`. |
151
223
 
152
- ## TypeScript Support
224
+ #### Returns / RMA
153
225
 
154
- All operations are fully typed. After running codegen, you get:
226
+ | Operation | Description |
227
+ | --- | --- |
228
+ | `Return` | Fetches a single return (RMA) by `id` with line items, refund/compensation info, and history. **Auth required** — customer access token plus ownership of the return. Wrapped response: `{ return, userErrors[] }`. Error codes: `INVALID_TOKEN`, `NOT_FOUND` (also returned on ownership mismatch), `FETCH_FAILED`. |
229
+ | `ReturnsByOrder` | Lists returns for a given order (paginated, default page size 20, cursor-based). **Auth required** — customer access token plus ownership of the order; the connection is empty (no explicit error) on auth failure. Use on the order detail page to show return history. |
230
+ | `ReturnReasons` | Returns the standard list of return reasons used by the RMA flow: `DEFECTIVE`, `NOT_AS_DESCRIBED`, `WRONG_ITEM`, `CHANGED_MIND`, `BETTER_PRICE`, `DAMAGED_SHIPPING`, `OTHER`. The list is fixed across all shops — not per-shop configurable. Public; no auth required. |
155
231
 
156
- - Document nodes for each operation
157
- - Input types for variables
158
- - Response types for results
232
+ #### Gift Cards
233
+
234
+ | Operation | Description |
235
+ | --- | --- |
236
+ | `GiftCard` | Public gift-card lookup by `code`. Returns balance, currency, expiry, and `maskedCode` (first 4 + last 4 chars only — the full code never leaks back). Returns null if the code is unknown (rather than an explicit error, to limit enumeration). **Rate-limited**: 10 requests per 60 seconds per IP. |
237
+ | `GiftCardValidate` | Validates whether a gift card is usable (and optionally for a given `$amount`). Checks status (`DISABLED`, `USED`, `EXPIRED`), expiry date, and — when `$amount` is provided — sufficient balance. Returns `{ validation: { isValid, availableBalance, error: { code, message } }, userErrors[] }`. Validation error codes: `NOT_FOUND`, `DISABLED`, `ALREADY_USED`, `EXPIRED`, `INSUFFICIENT_BALANCE`. **Rate-limited**: 10 / 60s. |
238
+
239
+ #### Shipping Methods
240
+
241
+ | Operation | Description |
242
+ | --- | --- |
243
+ | `AvailableShippingMethods` | Returns shipping methods for a given destination address and cart shape (subtotal, total weight, currency). The query computes everything from the inputs alone — no existing cart is required, so it can be used for "shipping cost preview" UIs before the customer adds anything to a cart. Each method includes price, free-shipping progress (`{ qualifies, currentAmount, threshold, remaining, progressPercent }`), estimated delivery, and carrier metadata. Sorted by the merchant's `sortOrder`, then by price. |
244
+
245
+ #### Attribute Filters
246
+
247
+ | Operation | Description |
248
+ | --- | --- |
249
+ | `AvailableFilters` | Returns the dynamic facet filters available for a listing context — pass `collectionId`, `categoryId`, or `searchQuery`. For each visible & filterable attribute, returns either discrete value counts (for `SELECT` / `CHECKBOX` types) or numeric range bounds (for `SLIDER` types). Plus `priceRange`, per-category counts, `activeCount` (length of `currentFilters` input), and `matchCount` (total products in the context). Use to render filter sidebars on listing/search pages. |
250
+
251
+ #### Loyalty Program
252
+
253
+ | Operation | Description |
254
+ | --- | --- |
255
+ | `LoyaltyMember` | Returns the logged-in customer's loyalty membership: points (current, pending, redeemed, expired, expiring), current tier, tier progress, annual spend, last activity. Returns null if the customer is not enrolled — there is **no auto-enrollment** here (enrollment happens via signup or a first qualifying order). Auth required. |
256
+ | `LoyaltyTiers` | Lists the loyalty tiers configured for the shop (`BRONZE`, `SILVER`, `GOLD`, `PLATINUM`, `DIAMOND` etc.) with their `minPoints`, `minAnnualSpend`, `pointsMultiplier`, and custom benefits. Sorted by `minPoints` ASC. Public; no auth required. |
257
+ | `LoyaltyRewards` | Lists rewards customers can redeem (free shipping, percent off, free product, gift card). Filtered to **active** rewards only (`is_active = true` AND inside their `starts_at`/`ends_at` window). Public; no auth required. |
258
+ | `LoyaltyTransactions` | Paginated history of loyalty point transactions for the logged-in customer (default 20). Transaction `type` enum: `EARN_PURCHASE`, `EARN_SIGNUP`, `EARN_REFERRAL`, `EARN_REVIEW`, `EARN_BIRTHDAY`, `EARN_BONUS`, `REDEEM`, `EXPIRE`, `ADJUST`, `REFUND_REVERSAL`. Auth required — empty connection if unauthenticated. |
259
+ | `LoyaltySettings` | Returns the loyalty program configuration: `isEnabled`, `pointsName` (e.g. "stars"), `pointsPerCurrency`, `pointsExpiryMonths`, available earn actions, referral settings. Use this at app boot to decide whether to render any loyalty UI at all. Public; no auth required. |
260
+ | `EstimatePoints` | Estimates how many loyalty points the customer would earn for an order of `$orderTotal` (in major currency units). When the customer is authenticated, the result accounts for their current tier's points multiplier. Use on cart/checkout to show "Earn X points with this order". |
261
+ | `ReferralStats` | Returns the customer's referral statistics: `referralCode`, `shareUrl`, `totalReferred`, `completedReferrals`, `pendingReferrals`, `totalPointsEarned`. Auth required. Returns null if unauthenticated or if the referral program is disabled for the shop. |
262
+
263
+ #### Reviews
264
+
265
+ | Operation | Description |
266
+ | --- | --- |
267
+ | `ProductReviews` | Paginated list of customer reviews for a product, **filtered to APPROVED reviews only** (PENDING / REJECTED reviews are not exposed to the storefront). Sort by `CREATED_AT` (default), helpfulness, or rating. Public; no auth required. |
268
+ | `ReviewStats` | Aggregate review statistics for a product: average rating, total count, distribution per star (1-5). Computed from APPROVED reviews only. Use for product card review summaries. Public; no auth required. |
269
+
270
+ #### Wishlists
271
+
272
+ | Operation | Description |
273
+ | --- | --- |
274
+ | `Wishlists` | Paginated list of the logged-in customer's wishlists (default 20). Auth required — empty connection if unauthenticated. Customers typically have a small set (<10). |
275
+ | `WishlistById` | Fetches a single wishlist by `id`. Private wishlists are visible only to the owner; public wishlists are visible to anyone. Note: this query supports lookup by `id` only — there is currently no way to fetch a wishlist by its share token. |
276
+
277
+ #### Blog
278
+
279
+ | Operation | Description |
280
+ | --- | --- |
281
+ | `BlogPosts` | Paginated list of published blog posts. Filter by `categorySlug`, `tagSlug`, or `featured` (boolean flag, not enum). Sort: `PUBLISHED_AT` (default), `TITLE`, `VIEW_COUNT`, or `CREATED_AT`. Public; no auth required. |
282
+ | `BlogPost` | Fetches a single blog post by `id` or `slug`. Visibility-gated: returns null if the post is not yet `PUBLISHED` or if its publish date is in the future (scheduled posts stay hidden until their publish time). Side effect: fetching a post increments its `view_count` asynchronously (does not block the response). |
283
+ | `BlogCategories` | Lists all blog categories with per-category `postCount` and SEO metadata. Use to render category navigation on blog pages. Public; no auth required. |
284
+ | `BlogTags` | Lists blog tags with usage counts (`postCount` per tag). Use to render a tag cloud. Public; no auth required. |
285
+
286
+ #### Recommendations
287
+
288
+ | Operation | Description |
289
+ | --- | --- |
290
+ | `ProductRecommendations` | Returns up to `$limit` recommended products related to `$productId`. Default `$intent: SIMILAR` — products sharing categories or tags. Use on PDP "You may also like" sections. Public; no auth required. |
291
+
292
+ #### Content: Pages
293
+
294
+ | Operation | Description |
295
+ | --- | --- |
296
+ | `Page` | Fetches a single CMS page (About, Privacy, Returns Policy, Terms, etc.) by `handle` or `id`. Visibility-gated: returns null if the page is hidden or if its publish date is in the future. Public; no auth required. |
297
+ | `Pages` | Paginated list of visible, already-published CMS pages. Use for sitemap, footer link list, or page directory. The `query` argument supports text search over the page title/handle. Public; no auth required. |
298
+
299
+ #### Content: Navigation Menus
300
+
301
+ | Operation | Description |
302
+ | --- | --- |
303
+ | `Menu` | Fetches a navigation menu by `handle` (e.g. `"main-menu"`, `"footer"`, `"mobile"`). Returns the nested item tree. Each item is typed as one of: `HTTP`, `FRONTPAGE`, `SEARCH`, `CATALOG`, `BLOG`, `PRODUCT`, `COLLECTION`, `CATEGORY`, or `PAGE` — switch on the type to render the right link target. Linked resources and URLs are resolved on demand by the field selections in the `Menu` fragment. |
304
+
305
+ #### Content: URL Redirects
306
+
307
+ | Operation | Description |
308
+ | --- | --- |
309
+ | `UrlRedirects` | Returns the shop's URL redirects (legacy `path` → new `target` mappings). Use server-side at the edge or in SSR to issue 301 redirects for migrated routes (preserves SEO equity). Default page size 250 — most shops fit in a single page. |
310
+
311
+ #### Store Availability: per-location stock (BOPIS / multi-location)
312
+
313
+ | Operation | Description |
314
+ | --- | --- |
315
+ | `ProductStoreAvailability` | Fetches a product (by `handle` or `id`) along with per-variant availability across the merchant's physical locations — for the BOPIS / multi-location flow. The `storeAvailability` connection lives on each `ProductVariant`; its arguments (`first`, `after`, `near`, `locationType`) are set inside the `VariantStoreAvailability` fragment. The connection returns null for single-location shops (in which case the storefront can skip the store picker entirely). `availableStock` is null for anonymous users and an integer for authenticated customers. Apply `@inContext(preferredLocationId: ...)` on the operation to pin the customer's preferred location to the top of the result. |
316
+
317
+ #### Locations (store picker UI)
318
+
319
+ | Operation | Description |
320
+ | --- | --- |
321
+ | `Locations` | Paginated list of active store locations (default 20, max 100). Filters: `near` (`{ latitude, longitude }`) for proximity search — sorts ascending by distance; `hasPickupEnabled` for pickup-only filtering; `locationType` (`RETAIL`, `WAREHOUSE`, `PICKUP_POINT`). When `near` is omitted, results are sorted by the merchant's `priority`, then name. Use for the BOPIS store picker UI. Public; no auth required. |
322
+ | `Location` | Fetches a single store location by `id` — full address, coordinates, business hours, pickup config (lead time, hours, timezone), and services. Returns null if the location is not found, not active, or owned by another shop. Use on the location detail page. Public; no auth required. |
323
+ <!-- AUTOGEN:QUERIES:END -->
324
+
325
+ ### Mutations
326
+
327
+ <!-- AUTOGEN:MUTATIONS:BEGIN — auto-regenerated, do not edit by hand -->
328
+ #### Cart Mutations
329
+
330
+ | Operation | Description |
331
+ | --- | --- |
332
+ | `CartCreate` | Creates a new cart and optionally pre-populates it with line items. Cart ID is a UUID stored by the SDK in the `cart-id` cookie (30-day TTL); the cart itself expires server-side after 72 hours of inactivity. The `warnings` field is reserved for non-blocking issues — current implementation returns it empty in this path. |
333
+ | `CartAddLines` | Adds line items to a cart. Each line is `{ merchandiseId, quantity, attributes?, attributeSelections? }`. If the same variant + identical attributes are added twice, quantities merge into one row instead of duplicating. Validates stock (`INSUFFICIENT_STOCK`) and configurator attributes (`ATTRIBUTE_REQUIRED`, `ATTRIBUTE_OPTION_INVALID`). Triggers cart re-pricing including discount recalculation. |
334
+ | `CartUpdateLines` | Updates quantity and/or attributes of existing cart lines by `id`. Setting `quantity: 0` auto-deletes the line. Passing `attributes: []` clears them; omitting the field preserves existing values. Re-validates stock and re-prices the cart after each update. |
335
+ | `CartRemoveLines` | Removes specific lines from cart by `lineIds[]`. Internally delegates to `cartUpdateLines` with `quantity: 0` — both endpoints are functionally equivalent; this one exists for API ergonomics when intent is explicit removal. Triggers cart re-pricing. |
336
+ | `CartApplyDiscountCodes` | Replaces (NOT appends) the cart's discount codes with the given list. Pass `[]` to clear all codes. Each code is validated against `discounts` table (existence, active status); invalid codes appear in `userErrors[]` as `DISCOUNT_CODE_INVALID`. Triggers cart re-pricing — discount allocations are recomputed and stored in `cart.discountAmount`. |
337
+ | `CartUpdateBuyerIdentity` | Associates a customer with the cart. Despite the input shape accepting `email`, `phone`, `countryCode`, `languageCode`, only `customerId` is currently persisted — other fields are silently ignored. Does NOT trigger tax / shipping recalculation; pure cart-to-customer linking. Use during login or guest-to-account upgrade. |
338
+ | `CartUpdateNote` | Sets a free-text note on the cart (gift message, special instructions). Pass empty string to clear. Stored on the `Cart` row, propagated to the `Order` at checkout completion, visible to merchant in admin. |
339
+
340
+ #### Customer Auth Mutations
341
+
342
+ | Operation | Description |
343
+ | --- | --- |
344
+ | `CustomerSignup` | Registers a new customer. Returns `customerAccessToken` immediately — the customer record is created with status `ACTIVE` (no pending state). The activation email containing `customerActivate` token is sent for `emailVerified=true` confirmation, but is NOT required for login. Cookie: `customerAccessToken`, 30-day max-age, httpOnly. JWT TTL: 24h. Bot-protection guarded. |
345
+ | `CustomerLogin` | Logs in with email + password. JWT lifetime 24h; cookie max-age 30d (cookie outlives JWT — call `customerRefreshToken` before JWT expiry to extend session). Brute-force protected: 10 failed attempts per email = 15-min Redis-backed lockout. Failed attempts are recorded for non-existent emails too (timing-attack safe). |
346
+ | `CustomerLogout` | Clears the `customerAccessToken` cookie. Note: the JWT itself is NOT server-side invalidated — it remains valid until its 24h expiry. Server-side token revocation is on the roadmap. Idempotent. |
347
+ | `CustomerRefreshToken` | Issues a fresh JWT (24h TTL) for the currently-authenticated customer. Reads identity from the current cookie/Bearer token; takes no input. Use proactively before JWT expiry or reactively on a 401 retry. The new token replaces the cookie value. |
348
+
349
+ #### Customer Profile Mutations
350
+
351
+ | Operation | Description |
352
+ | --- | --- |
353
+ | `CustomerUpdate` | Updates the logged-in customer's profile. Supported fields include `firstName`, `lastName`, `phone`, marketing preferences, and B2B identity (`customerType`, `companyName`, `taxId`, `vatNumber`, `regon`). Concurrent updates from the storefront and the merchant admin are reconciled safely — the loser of a race retries against the latest version. Marketing consent changes are recorded separately for audit purposes. |
354
+
355
+ #### Customer Address Mutations
356
+
357
+ | Operation | Description |
358
+ | --- | --- |
359
+ | `CustomerAddAddress` | Adds a new mailing address. If `isDefaultShipping` or `isDefaultBilling` is `true` in the input, the new address is set as default and any other address for this customer holding that flag is atomically cleared in the same transaction. |
360
+ | `CustomerUpdateAddress` | Updates an existing address owned by the logged-in customer. If `isDefaultShipping` or `isDefaultBilling` toggles to `true`, default flag is atomically cleared on all other addresses for this customer. |
361
+ | `CustomerRemoveAddress` | Hard-deletes an address row from `customer_addresses`. Historical orders that referenced this address are unaffected (address is snapshotted into the order at checkout completion). |
362
+ | `CustomerSetDefaultAddress` | Marks the given address as the customer's default **shipping** address. Atomically clears the shipping-default flag from all other addresses. Note: there is no separate setter for default billing — set `isDefaultBilling: true` via `customerAddAddress` / `customerUpdateAddress` instead. |
363
+
364
+ #### Customer Password Mutations
365
+
366
+ | Operation | Description |
367
+ | --- | --- |
368
+ | `CustomerRequestPasswordReset` | Sends a password reset email. Always returns success regardless of whether the email exists (no account enumeration). The email is dispatched asynchronously, so a small delay between request and inbox arrival is normal. Rate-limited to 3 requests per 10 minutes. |
369
+ | `CustomerActivate` | Activates a newly-created account using the 64-hex activation token from the welcome email + a chosen password. Token TTL is 24h, single-use (atomically marked `used_at`). On success: sets `email_verified=true`, transitions status `INACTIVE`→`ACTIVE`, returns a fresh JWT for auto-login. Rate-limited. |
370
+ | `CustomerResetPassword` | Resets the password using the 64-hex reset token from the password-reset email. Token TTL is 1h, single-use (atomically marked `used_at`). On success: updates the password hash and returns a fresh JWT for auto-login (no second login step needed). Rate-limited. |
371
+
372
+ #### Checkout Mutations
373
+
374
+ | Operation | Description |
375
+ | --- | --- |
376
+ | `CheckoutCreate` | Creates a new checkout session for the given cart (or a fresh cart if `cartId` is omitted). Inherits applied discounts and gift cards from the cart by reference (not snapshot). Errors: `CART_NOT_FOUND`, `EMPTY_CART`, `ALREADY_COMPLETED` (cart already converted to order). NOT idempotent — multiple calls create multiple checkouts. |
377
+ | `CheckoutShippingAddressUpdate` | Sets the shipping address (full replace, not patch). Triggers cart re-pricing. Address format is NOT validated here — full validation runs at `checkoutComplete` (`validateOrderReadiness`). |
378
+ | `CheckoutBillingAddressUpdate` | Sets the billing address (full replace). Independent of shipping address — pass it explicitly even when "billing same as shipping". |
379
+ | `CheckoutEmailUpdate` | Sets or updates the contact email on the checkout (used for guest checkout, order confirmation, and tracking emails). Validated against a regex; returns `INVALID` for malformed format. |
380
+ | `CheckoutShippingLineUpdate` | Selects a shipping method by `shippingRateHandle` (a stable shipping-method UUID, NOT an opaque per-request token). The id comes from `availableShippingMethods` query, computed for the current address + cart subtotal at request time. |
381
+ | `CheckoutDiscountCodeApply` | Appends a discount code to the cart's `discount_codes` array. Note: while multiple codes can be stored, the pricing engine currently uses **only the first applied code** — codes do not stack. Validated for existence, active status, and customer usage limits via `discountService.validateDiscount`. |
382
+ | `CheckoutDiscountCodeRemove` | Removes a code from the cart's `discount_codes` array (filters by exact match). Triggers re-pricing. |
383
+ | `CheckoutDiscountCodeValidate` | READ-ONLY validation of a discount code against the current checkout — does NOT modify state. Returns `{ isValid, discount, error }` for previewing the effect (e.g. inline UI feedback as the user types). |
384
+ | `CheckoutPaymentMethodUpdate` | Selects a payment method by `paymentMethodId` (UUID from `availablePaymentMethods` query). Validates existence and active status; no pre-authorization is performed here. |
385
+ | `CheckoutComplete` | Finalizes the checkout: creates the `Order`, marks the cart `CONVERTED`, deducts gift cards, emits `ORDER_CREATED` (and `ORDER_CONFIRMED` for COD) — all in a single serializable transaction. **Idempotent on `idempotencyKey`** (NOT on `checkoutId`); auto-generated from `cartId + timestamp` if the caller omits it. The `paymentUrl` field is reserved but is NOT populated here — for hosted gateways (PayU, P24) the storefront calls a separate `paymentCreate` mutation after this returns. |
386
+
387
+ #### Gift Card Checkout Mutations
388
+
389
+ | Operation | Description |
390
+ | --- | --- |
391
+ | `CheckoutGiftCardApply` | Applies a gift card to the cart, stackable with discount codes. Consumption is FIFO: each card consumes `min(remainingBalance, paymentDue)` against the current cart total in the order they were applied. The gift card balance is NOT debited yet — actual deduction happens atomically inside the `checkoutComplete` transaction. Errors: `GIFT_CARD_NOT_FOUND`, `GIFT_CARD_DEPLETED`, `GIFT_CARD_UNUSABLE`, `GIFT_CARD_ALREADY_APPLIED`. |
392
+ | `CheckoutGiftCardRemove` | Removes a gift card from the applied list and recalculates FIFO `appliedAmount` for the remaining cards. Since gift card balances are only debited at `checkoutComplete`, removing before completion has no effect on the underlying gift card balance. |
393
+ | `CheckoutGiftCardRecipientUpdate` | Sets per-line-item recipient details (name, email, message, delivery date) for digital gift card products in the cart (variants with `type: GIFT_CARD`). Required before `checkoutComplete` for any line item with a gift-card variant. Recipient details are associated with each gift-card line item and propagated to the resulting order. |
394
+
395
+ #### Return Mutations
396
+
397
+ | Operation | Description |
398
+ | --- | --- |
399
+ | `ReturnCreate` | Creates an RMA in `REQUESTED` status (awaits merchant approval — NOT auto-approved). Input: `orderId`, `reason`, `items[{ variantId, quantity, reason, condition }]`, optional `compensationType` (REFUND or STORE_CREDIT) and `customerNote`. Validates the order's `fulfillmentStatus` permits returns and that requested quantities don't exceed already-shipped/unreturned quantities. Supports optional `idempotencyKey` for retry-safe creation. |
400
+ | `ReturnCancel` | Cancels a return that is currently in `REQUESTED`, `APPROVED`, or `DRAFT` status (cancellation is allowed even AFTER merchant approval, as long as the return shipment hasn't been processed). Sets `cancelled_at` timestamp. Customer can only cancel returns they own. |
401
+
402
+ #### Loyalty Program Mutations
403
+
404
+ | Operation | Description |
405
+ | --- | --- |
406
+ | `RedeemLoyaltyReward` | Redeems a loyalty reward by `rewardId`. Three reward types are supported, distinguished by which output field is populated: `discountCode` (issues a `LOYALTY-XXXX` code with 30-day expiry), `productDiscountCode` (issues a single-use 100%-off code for a specific product), or `giftCardCode` (creates a new gift card for the customer). Points are deducted atomically inside a transaction — if external creation (e.g. gift card service) fails after deduction, points are reversed. |
407
+ | `GenerateReferralCode` | Returns the customer's referral code, generating one on first call. Idempotent UPSERT — subsequent calls return the existing code from `customers.referral_code`. Format: `REF-XXXXXXXX` (8 random alphanumeric chars). Output also includes a `shareUrl` built from the shop's domain. |
408
+
409
+ #### Review Mutations
410
+
411
+ | Operation | Description |
412
+ | --- | --- |
413
+ | `ReviewCreate` | Submits a product review (rating 1-5, content 10-5000 chars, sanitized via `sanitizePlainText`). Default state is `PENDING` — review is hidden from public until merchant approves. If the input includes `orderId`, `isVerifiedPurchase` is auto-set to `true`. Bot-protected and rate-limited (10/min by default). |
414
+ | `ReviewUpvote` | Records an upvote (helpful) on a review. UPSERT semantics — one `ReviewVote` row per `(reviewId, customerId)`. Calling upvote twice is a no-op; calling downvote afterwards replaces the vote. Increments `helpful_count` on the review (and decrements `unhelpful_count` if replacing a downvote). |
415
+ | `ReviewDownvote` | Records a downvote (unhelpful) on a review. Same UPSERT semantics as `reviewUpvote` — one vote row per `(reviewId, customerId)`, replacing any prior vote. Increments `unhelpful_count`. |
416
+
417
+ #### Wishlist Mutations
418
+
419
+ | Operation | Description |
420
+ | --- | --- |
421
+ | `WishlistCreate` | Creates a new wishlist for the logged-in customer. `name` is optional (defaults to "My Wishlist"); name uniqueness is NOT enforced — customers can have multiple lists with the same name. Setting `isPublic: true` generates a 16-byte hex `shareToken` for public sharing. |
422
+ | `WishlistAddItem` | Adds an item by `productId` (and optional `variantId`) to a wishlist. Idempotent on the `(wishlist_id, product_id, variant_id)` unique constraint — adding an already-present item is a silent no-op (`ON CONFLICT DO NOTHING`). Captures `priceAtAdd` for price-drop notifications. |
423
+ | `WishlistRemoveItem` | Hard-deletes a wishlist item by `itemId` (the `WishlistItem` row id, NOT the product id). |
424
+ | `WishlistDelete` | Hard-deletes the wishlist row. All `WishlistItem` rows are removed via FK cascade. No soft-delete; cannot be undone. |
425
+
426
+ #### Cart Attributes
427
+
428
+ | Operation | Description |
429
+ | --- | --- |
430
+ | `CartUpdateAttributes` | Replaces (NOT merges) the cart's custom attributes — free-form `[{ key, value }]` pairs visible to merchant in admin. Use for delivery instructions, gift wrap flags, B2B PO numbers, etc. Limit: 250 pairs per cart (returns `CART_ATTRIBUTES_LIMIT_EXCEEDED`); each `key` max 255 chars. |
431
+ <!-- AUTOGEN:MUTATIONS:END -->
432
+
433
+ ### Fragments
434
+
435
+ <!-- AUTOGEN:FRAGMENTS:BEGIN — auto-regenerated, do not edit by hand -->
436
+ #### Common
437
+
438
+ | Fragment | On Type | Description |
439
+ | --- | --- | --- |
440
+ | `PageInfo` | `PageInfo` | Standard Relay Connection page metadata. Spread on every paginated query's `pageInfo`. |
441
+ | `UserError` | `UserError` | Generic mutation error envelope — included in every mutation's `userErrors[]` field. Always check before consuming the happy-path payload. |
442
+ | `CartWarning` | `CartWarning` | Non-blocking cart warning (e.g. low stock, partial availability). Cart mutations succeed but surface these for UI hints. |
443
+ | `Image` | `Image` | Base image — original size, no transform. Use for logos, favicons, branding assets that are already sized correctly. ~few KB. |
444
+ | `ImageThumbnail` | `Image` | Thumbnail — cart line items, variant swatches, author avatars (rendered ~96px on screen, transform delivers up to 300px for 3x DPI). Includes `thumbhash` for blurred placeholder. Format auto-negotiated from the `Accept` header. |
445
+ | `ImageCard` | `Image` | Card — product cards, collection / category tiles, blog post previews (rendered ~400px, transform delivers up to 800px for 2x DPI). Includes `thumbhash` placeholder. |
446
+ | `ImageFull` | `Image` | Full — product detail gallery, hero banners (rendered ~800px, transform delivers up to 1600px for 2x DPI). Includes `thumbhash` placeholder. |
447
+ | `Money` | `Money` | Plain `{ amount, currencyCode }` price. Use for `compareAtPrice`, totals, and any field where currency conversion transparency is not needed. `amount` is a String. |
448
+ | `Price` | `PriceMoney` | Lightweight price for listing views (cards, grids, search results) — same shape as `Money`. Spread when full conversion metadata is overkill. |
449
+ | `PriceMoney` | `PriceMoney` | Full price with currency-conversion transparency — adds `baseAmount`, `baseCurrencyCode`, `exchangeRate`, `marginApplied`, `rateTimestamp`, `isConverted`. Spread on PDP / cart / checkout where the customer needs to see the original price + applied conversion. |
450
+ | `SelectedOption` | `SelectedOption` | Selected variant option (e.g. `{ name: "Color", value: "Red" }`) on a `ProductVariant`. Use to render variant labels in cart / order summaries. |
451
+
452
+ #### Products
453
+
454
+ | Fragment | On Type | Description |
455
+ | --- | --- | --- |
456
+ | `ProductVariant` | `ProductVariant` | Single variant of a product — price, compare-at, stock flags, sort, image, selected options. Spread on cart line items, PDP variant selectors, search result rows that need price. |
457
+ | `ProductCard` | `Product` | Minimal product shape for listing views (collection grids, search results, "you may also like"). Includes price range, featured image (card size), rating + review count, vendor, tags. Use for any list of products where you don't need variants/description. |
458
+ | `ProductBase` | `Product` | `ProductCard` plus textual content (description, descriptionHtml), stock total, type, visibility flags, and timestamps. Use when you need full product copy but not the heavy variants/images lists. Sweet spot for blog post embeds, related-product cards with description. |
459
+ | `ProductFull` | `Product` | Full product shape for the PDP — `ProductBase` plus the full image gallery (up to 20, full-size) and all variants (up to 100) with their pricing/stock. Spread on the product detail page. |
460
+
461
+ #### Collections
462
+
463
+ | Fragment | On Type | Description |
464
+ | --- | --- | --- |
465
+ | `Collection` | `Collection` | Collection (manual or rule-based product grouping) — title, description, hero image, SEO. Spread on collection landing pages and collection cards. Does NOT include products — query `collection(id, handle).products` separately for those. |
466
+
467
+ #### Categories
468
+
469
+ | Fragment | On Type | Description |
470
+ | --- | --- | --- |
471
+ | `Category` | `Category` | Category node in the shop's taxonomy — name, slug, hero image, depth `level`, materialized `path`, product count, sort order. Spread on category cards and breadcrumb segments. Does NOT include parent / children — query those fields separately and let the server batch them. |
472
+
473
+ #### Customer
474
+
475
+ | Fragment | On Type | Description |
476
+ | --- | --- | --- |
477
+ | `MailingAddress` | `MailingAddress` | Customer mailing address — full street/city/state/country/postal code with names and phone. `isDefault` flips when this address is the default for shipping. Spread on the address book UI and order summaries. |
478
+ | `CustomerAccessToken` | `CustomerAccessToken` | Customer access token returned by `customerLogin` / `customerSignup` / `customerActivate` / `customerResetPassword` / `customerRefreshToken`. The token's JWT TTL is 24h; cookie max-age is 30d. |
479
+ | `Customer` | `Customer` | Customer profile — basic info plus B2B fields (`taxId`, `vatNumber`, `regon`, `companyName`), default address, lifetime stats (`orderCount`, `totalSpent`), marketing preferences. Use on profile / settings pages. |
480
+ | `Order` | `Order` | Order summary — number, totals (cost / tax / shipping), payment + fulfillment status, shipping address, item count, lifecycle timestamps. Spread on the order list and order detail pages. Line items are not included here. |
481
+
482
+ #### Cart
483
+
484
+ | Fragment | On Type | Description |
485
+ | --- | --- | --- |
486
+ | `CartCost` | `CartCost` | Cart-level totals — subtotal, total, tax, duty, checkout charge. Spread inside the `Cart` fragment. |
487
+ | `CartLineCost` | `CartLineCost` | Per-line cost breakdown — unit price, line subtotal/total, compare-at unit price (for showing strikethroughs). Spread inside `CartLine`. |
488
+ | `AttributeSelection` | `AttributeSelection` | Typed snapshot of a customer-filled product attribute (configurator selection) on a cart line. Includes the chosen option / text value, fillingMode, billingMode, surcharge, tax class, and any linked variant. Distinct from `CartLine.attributes` which holds raw key-value line item properties (free-form, untyped). |
489
+ | `CartLine` | `CartLine` | A single line in the cart — variant + quantity + per-line cost, plus dual attribute storage: `attributes[]` for free-form key-value properties (gift wrap, engraving notes), `attributeSelections[]` for typed configurator answers. |
490
+ | `CartBuyerIdentity` | `CartBuyerIdentity` | Buyer identity associated with the cart. Note: only `customerId` is currently persisted server-side; `email`, `phone`, `countryCode` are accepted in the input but ignored. |
491
+ | `CartDiscountCode` | `CartDiscountCode` | Discount code applied to the cart with its `isApplicable` flag — false means the code was kept on the cart but does not currently qualify (e.g. minimum spend not reached). |
492
+ | `CartDiscountAllocation` | `CartDiscountAllocation` | Allocation of a discount code to the cart total — pairs the code with the actual money discounted. Use to show "saved X with code Y" in cart UI. |
493
+ | `Cart` | `Cart` | Full cart shape — totals, line items (paginated up to 100), buyer identity, applied discount codes + allocations, note, custom attributes. Spread on the cart drawer / cart page; refetch after every cart mutation. |
494
+
495
+ #### Shop
496
+
497
+ | Fragment | On Type | Description |
498
+ | --- | --- | --- |
499
+ | `ShopColors` | `ShopColors` | Shop branding colors — primary, secondary, accent, background, text. Use to theme the storefront from server-side config. |
500
+ | `ShopFonts` | `ShopFonts` | Shop branding fonts — body (`primary`) and `heading` font families. |
501
+ | `SocialLinks` | `SocialLinks` | Social media links configured for the shop. Spread on the footer. |
502
+ | `ShopAddress` | `ShopAddress` | Shop's physical / business address. Use on the contact page and footer. |
503
+ | `BusinessHour` | `BusinessHour` | One day's business hours window. Spread inside `Shop.businessHours[]`. |
504
+ | `ShopBranding` | `ShopBranding` | Full shop branding bundle — logo + favicon + colors + fonts + social links. Spread inside the `Shop` fragment. |
505
+ | `BotProtectionProvider` | `BotProtectionProviderInfo` | Bot-protection provider config (provider name, site key, script URL) for storefront-side challenge widgets. |
506
+ | `BotProtection` | `BotProtectionInfo` | Bot-protection setup for the shop — primary + fallback provider, and the list of `protectedOperations` (mutation names that require a challenge token). Spread inside `Shop`. |
507
+ | `Shop` | `Shop` | The shop itself — name, primary domain, currencies + locales, branding, contact info, business hours, bot-protection config. Spread on the root `shop` query; cache for the session. |
508
+
509
+ #### Payment Methods
510
+
511
+ | Fragment | On Type | Description |
512
+ | --- | --- | --- |
513
+ | `PaymentMethod` | `PaymentMethod` | Single payment method enabled for the shop — type (CARD / BANK_TRANSFER / BLIK / PAYPAL / APPLE_PAY / GOOGLE_PAY / CASH_ON_DELIVERY / OTHER), provider, icon, supported currencies, default flag, sort position. Spread on the checkout payment step. |
514
+ | `AvailablePaymentMethods` | `AvailablePaymentMethods` | Active payment methods list with the merchant's `defaultMethod`. Returned by the `availablePaymentMethods` query. |
515
+
516
+ #### Checkout
517
+
518
+ | Fragment | On Type | Description |
519
+ | --- | --- | --- |
520
+ | `ShippingRate` | `ShippingRate` | Single shipping rate option — `handle` is the stable id you pass to `checkoutShippingLineUpdate`, plus title and price. |
521
+ | `TaxLine` | `TaxLine` | One tax line on the checkout — title, rate (decimal, e.g. 0.23 for 23%), computed amount. Spread on the order summary. |
522
+ | `DiscountAffectedItem` | `DiscountAffectedItem` | Item affected by a discount — the discounted product/variant with original + discounted prices and savings. Used on Buy-X-Get-Y promotions to highlight which items the discount applies to. |
523
+ | `DiscountApplication` | `DiscountApplication` | A discount currently applied to the checkout — code, type, value, plus BXGY (Buy X Get Y) metadata when applicable (`buyQuantity`, `getQuantity`, `getDiscountPercent`, `affectedItems`). Use to render a "Discounts applied" panel. |
524
+ | `DiscountCode` | `DiscountCode` | Lightweight discount code entry on the checkout — code + applicability flag. |
525
+ | `CheckoutLineItem` | `CheckoutLineItem` | Single line item in the checkout — variant snapshot, quantity, unit + total prices, image. Use on the order summary panel. |
526
+ | `AppliedGiftCard` | `AppliedGiftCard` | Gift card applied to the checkout — `maskedCode` (first + last 4 chars), `lastCharacters` (for display matching), the amount applied to this checkout, and remaining balance after this order would complete. |
527
+ | `Checkout` | `Checkout` | Full checkout shape — line items, shipping + billing addresses, selected + available shipping rates, available payment methods, applied discounts + gift cards, tax lines, totals (`cost`, `paymentDue`, `totalGiftCardAmount`). Spread on the checkout flow; refetch after every checkout mutation. `isReady` flips to true when the checkout has all required fields to call `checkoutComplete`. |
528
+
529
+ #### Shipments / Tracking
530
+
531
+ | Fragment | On Type | Description |
532
+ | --- | --- | --- |
533
+ | `ShipmentEvent` | `ShipmentEvent` | One tracking event in the shipment timeline — status, description, location, timestamp. Spread on the tracking page timeline. |
534
+ | `ShipmentPackage` | `ShipmentPackage` | Physical package metadata (weight + dimensions). Used in the merchant's label generation; storefronts rarely render this directly. |
535
+ | `ShipmentItem` | `ShipmentItem` | One item in a shipment — title, variant, sku, quantity, image URL. Spread inside `Shipment.items[]` for the tracking page item list. |
536
+ | `Shipment` | `Shipment` | Full shipment shape — provider, tracking number + URL, label URL, status, ETA, recipient address, packages, items, full event timeline. Spread on the tracking page. |
537
+ | `ShipmentBasic` | `Shipment` | Lightweight shipment shape — id, tracking number + URL, status, dates. No items / events / address. Use for order summary cards or on the public `shipmentByTrackingNumber` query. |
538
+
539
+ #### Returns / RMA
540
+
541
+ | Fragment | On Type | Description |
542
+ | --- | --- | --- |
543
+ | `ReturnShippingLabel` | `ReturnShippingLabel` | Return shipping label generated by the carrier — URL to download, carrier name, tracking number, expiry. Spread on the return detail page. |
544
+ | `ReturnItemPhoto` | `ReturnItemPhoto` | Photo evidence attached to a return item (e.g. damage photo). Spread inside `ReturnItem.photos[]`. |
545
+ | `ReturnItem` | `ReturnItem` | Single line in a return request — variant identity, quantity requested, reason, condition, photos, status, approved quantity (set by merchant after review). Spread inside `Return.items[]`. |
546
+ | `Return` | `Return` | Full return shape — number, parent order, status, reason, customer note, compensation type (`REFUND` / `STORE_CREDIT`), items, refund amount, shipping label, lifecycle timestamps. Spread on the return detail page. |
547
+ | `ReturnReasonOption` | `ReturnReasonOption` | Single option in the return reasons dropdown — `value` enum, human-readable `label`, optional `description`. Returned by `returnReasons` query. |
548
+
549
+ #### Gift Cards
550
+
551
+ | Fragment | On Type | Description |
552
+ | --- | --- | --- |
553
+ | `GiftCard` | `GiftCard` | Gift card detail — masked code (first + last 4 chars), status, initial + remaining balance, expiry, recipient/message. Returned by `giftCard($code)` query. |
554
+ | `GiftCardError` | `GiftCardError` | Validation error on a gift card check — code (`NOT_FOUND` / `DISABLED` / `ALREADY_USED` / `EXPIRED` / `INSUFFICIENT_BALANCE`) + human message. |
555
+ | `GiftCardValidation` | `GiftCardValidation` | Result of `giftCardValidate($code, $amount)` — `isValid` flag, available balance, optional `error` (when invalid), and the matched gift card (when found). Use to inline-validate gift card inputs before applying. |
556
+
557
+ #### Shipping Methods
558
+
559
+ | Fragment | On Type | Description |
560
+ | --- | --- | --- |
561
+ | `ShippingCarrier` | `ShippingCarrier` | Carrier offering the shipping method — id, display name, logo URL, internal service code. |
562
+ | `DeliveryEstimate` | `DeliveryEstimate` | Estimated delivery window — `minDays` to `maxDays` plus a human-readable description (e.g. "2-4 business days"). |
563
+ | `FreeShippingProgress` | `FreeShippingProgress` | Free-shipping progress info — `qualifies` flag, current cart amount, threshold, remaining to qualify, percent progress, and a localized message ("Add 20 PLN more for free shipping"). Use to render a free-shipping progress bar in the cart drawer. |
564
+ | `AvailableShippingMethod` | `AvailableShippingMethod` | One shipping method offered for the destination + cart — id, name, carrier, price, free-shipping progress, estimated delivery, sort order. Spread on the checkout shipping step. |
565
+
566
+ #### Attribute Filters
567
+
568
+ | Fragment | On Type | Description |
569
+ | --- | --- | --- |
570
+ | `AttributeSwatch` | `AttributeSwatch` | Visual swatch for an attribute filter value — color hex (for color filters) or image URL (for pattern/material swatches). |
571
+ | `AttributeRangeBounds` | `AttributeRangeBounds` | Numeric range bounds for slider-style filters — min, max, currency code (when relevant). |
572
+ | `AttributeFilterValue` | `AttributeFilterValue` | One discrete value in a filterable attribute (e.g. "Red" for the Color filter). Includes `productCount` in the current listing context (for "(12)" badges next to filter values), optional swatch and price modifier. |
573
+ | `AttributeDefinition` | `AttributeDefinition` | Filterable attribute exposed on the storefront — name, type (SELECT / CHECKBOX / SLIDER / etc.), filterability flags, display order, and either discrete `filterValues[]` or numeric `rangeBounds`. Spread inside `availableFilters.attributes[]`. |
574
+ | `PriceRangeFilter` | `PriceRange` | Min / max price range across products in the current listing context. Use to bound the price slider. |
575
+ | `CategoryFilterOption` | `CategoryFilterOption` | One category option in the categories filter — id, name, slug, count of products in this category within the current listing context, level + parentId for tree rendering. |
576
+ | `AvailableFilters` | `AvailableFilters` | Full result of the `availableFilters($input)` query — attribute filters, price range, category filters, count of currently active filters, total products matching the context. Spread on listing pages to render filter sidebars. |
577
+
578
+ #### Loyalty Program
579
+
580
+ | Fragment | On Type | Description |
581
+ | --- | --- | --- |
582
+ | `LoyaltyPageInfo` | `LoyaltyPageInfo` | Page metadata for the loyalty transactions connection (separate type from generic `PageInfo` for legacy reasons; identical shape). |
583
+ | `LoyaltyTier` | `LoyaltyTier` | Loyalty tier definition — name, type enum (`BRONZE` / `SILVER` / `GOLD` / `PLATINUM` / `DIAMOND`), entry threshold (`minPoints` and/or `minAnnualSpend`), points multiplier, custom benefits list. Returned by `loyaltyTiers` and embedded in member tier data. |
584
+ | `LoyaltyPointsSummary` | `LoyaltyPointsSummary` | Customer's points breakdown — total earned, currently spendable, pending (not yet vested), redeemed lifetime, expired lifetime, expiring soon, and the next expiry date. Spread inside `LoyaltyMember`. |
585
+ | `TierProgress` | `TierProgress` | Customer's progress toward the next tier — current tier, next tier, points + spend remaining, percent progress. Use to render the "X points to GOLD" tracker. |
586
+ | `LoyaltyMember` | `LoyaltyMember` | Customer's loyalty membership — points summary, current tier, tier progress, annual spend, last activity. Returned by `loyaltyMember` (null if not enrolled). |
587
+ | `LoyaltyTransaction` | `LoyaltyTransaction` | One row in the loyalty points history — type (`EARN_PURCHASE` / `EARN_SIGNUP` / `EARN_REFERRAL` / `EARN_REVIEW` / `EARN_BIRTHDAY` / `EARN_BONUS` / `REDEEM` / `EXPIRE` / `ADJUST` / `REFUND_REVERSAL`), points delta, balance after, source order, expiry. Spread on the loyalty dashboard transaction list. |
588
+ | `LoyaltyReward` | `LoyaltyReward` | Reward customers can redeem — name, type, points cost, discount value (% or fixed), tier requirement, availability flag, remaining redemptions. Spread on the rewards page. |
589
+ | `PointsEstimate` | `PointsEstimate` | Estimated points for an order — base points, bonus points (tier multiplier applied), total, multiplier used. Returned by `estimatePoints($orderTotal)` for "Earn X points" UI on cart/checkout. |
590
+ | `LoyaltyAction` | `LoyaltyAction` | One earn action configured in the loyalty program — type (`PURCHASE` / `SIGNUP` / `REFERRAL` / `REVIEW` / `BIRTHDAY`), enabled flag, points granted. |
591
+ | `LoyaltySettings` | `LoyaltySettings` | Loyalty program configuration — `isEnabled` (use to gate UI rendering), points name (e.g. "stars"), earn rate, expiry policy, available actions, referral settings. Returned by `loyaltySettings`. |
592
+ | `ReferralStats` | `ReferralStats` | Customer referral statistics — code, share URL, counts of referred / completed / pending, lifetime points earned. Returned by `referralStats`. |
593
+ | `RedeemRewardPayload` | `RedeemRewardPayload` | Result of `redeemLoyaltyReward` — depending on the reward type, exactly one of `discountCode`, `productDiscountCode`, `giftCardCode` is populated. Apply the returned code on cart/checkout. |
594
+ | `GenerateReferralCodePayload` | `GenerateReferralCodePayload` | Result of `generateReferralCode` — the customer's referral code and shareable URL. |
595
+
596
+ #### Reviews
597
+
598
+ | Fragment | On Type | Description |
599
+ | --- | --- | --- |
600
+ | `ProductReview` | `ProductReview` | Single product review — rating, title, body, optional pros/cons, image attachments, author, verified-purchase flag, helpful/unhelpful counts, optional merchant response. Only `APPROVED` reviews are exposed to the storefront. |
601
+ | `ReviewStats` | `ReviewStats` | Aggregate review stats for a product — average rating, total count, distribution per star (1-5). Returned by `reviewStats($productId)`. |
602
+
603
+ #### Wishlists
604
+
605
+ | Fragment | On Type | Description |
606
+ | --- | --- | --- |
607
+ | `WishlistItem` | `WishlistItem` | One item in a wishlist — references the product and (optionally) a specific variant, snapshots the price at the time it was added, plus notification preferences (`notifyOnSale`, `notifyOnRestock`). |
608
+ | `Wishlist` | `Wishlist` | A customer's wishlist — name, public/private flag, share token (when public), items, item count. Spread on the wishlists page. |
609
+
610
+ #### Blog
611
+
612
+ | Fragment | On Type | Description |
613
+ | --- | --- | --- |
614
+ | `BlogCategory` | `BlogCategory` | Blog category — name, slug, description, post count. Spread on category navigation and post category labels. |
615
+ | `BlogTag` | `BlogTag` | Blog tag — name, slug, post count. Spread on tag clouds and post tag labels. |
616
+ | `BlogPost` | `BlogPost` | Full blog post — title, slug, excerpt, content (with `contentFormat` indicating HTML/Markdown), featured image, author, category, tags, publish date, reading time, view + comment counts, SEO metadata. Spread on the post detail page. |
617
+
618
+ #### Recommendations
619
+
620
+ | Fragment | On Type | Description |
621
+ | --- | --- | --- |
622
+ | `ProductRecommendation` | `ProductRecommendation` | One recommended product — the product itself (card-level), recommendation type (e.g. SIMILAR / FREQUENTLY_BOUGHT_TOGETHER), score (0-100), human reason text. Spread on PDP "You may also like" sections. |
623
+ | `CartRecommendation` | `CartRecommendations` | Recommendations bundle for the cart drawer — `frequentlyBoughtTogether` (cross-sell) and `youMayAlsoLike` (related). Each entry has the same shape as `ProductRecommendation`. |
624
+
625
+ #### Store Availability (BOPIS / multi-location)
626
+
627
+ | Fragment | On Type | Description |
628
+ | --- | --- | --- |
629
+ | `LocationAddress` | `LocationAddress` | Field-access notes: - `isAvailable` — always public. - `pickupTime` — public, localized merchant-configured string. - `availableStock` — token-gated (null for anonymous, integer for authenticated customers). - `location` — public, includes coords + business hours when configured. Physical location address — street, city, country, state, postal code, phone, lat/lng, formatted single-line representation. Spread inside `Location.address`. |
630
+ | `BusinessHoursWindow` | `BusinessHoursWindow` | One day's open/close window inside `BusinessHours` (24h clock). |
631
+ | `BusinessHours` | `BusinessHours` | Weekly business hours — one window per day. Spread inside `Location.businessHours`. |
632
+ | `Location` | `Location` | Physical store / pickup location — name, type (RETAIL / WAREHOUSE / PICKUP_POINT), address, business hours, pickup support flag + instructions, timezone. Spread on the store picker and location detail pages. |
633
+ | `StoreAvailability` | `StoreAvailability` | Per-location stock entry for one variant — availability flag, stock quantity (token-gated), pickup time, full location detail. Spread inside `StoreAvailabilityConnection.edges[].node`. |
634
+ | `StoreAvailabilityConnection` | `StoreAvailabilityConnection` | Relay connection of `StoreAvailability` entries for a variant — used inside the `VariantStoreAvailability` fragment. Pre-paginated to 10 by default. |
635
+ | `VariantStoreAvailability` | `ProductVariant` | Slim variant projection optimized for the store-picker UI — id, title, sku, isAvailable, total `availableStock` plus per-location `storeAvailability` connection. Use in `productStoreAvailability` query. |
636
+
637
+ #### Pages
638
+
639
+ | Fragment | On Type | Description |
640
+ | --- | --- | --- |
641
+ | `ShopPage` | `ShopPage` | CMS page — handle (URL slug), title, body (HTML), excerpt, SEO metadata, publish date. Spread on About / Privacy / Terms / Returns Policy pages. |
642
+
643
+ #### Navigation Menus
644
+
645
+ | Fragment | On Type | Description |
646
+ | --- | --- | --- |
647
+ | `MenuItem` | `MenuItem` | One menu item with up to 3 levels of nested children — title, URL, type (`HTTP` / `FRONTPAGE` / `SEARCH` / `CATALOG` / `BLOG` / `PRODUCT` / `COLLECTION` / `CATEGORY` / `PAGE`), `resourceId` for typed items, optional image. Switch on `type` to render the right link target. |
648
+ | `Menu` | `Menu` | Navigation menu — handle (e.g. "main-menu", "footer", "mobile"), title, nested item tree. Returned by `menu($handle)` query. |
649
+
650
+ #### URL Redirects
651
+
652
+ | Fragment | On Type | Description |
653
+ | --- | --- | --- |
654
+ | `UrlRedirect` | `UrlRedirect` | Single legacy `path` → new `target` redirect entry. Use on the server / edge to issue 301 redirects for migrated routes. |
655
+
656
+ #### Product Configurator (per-product attributes)
657
+
658
+ | Fragment | On Type | Description |
659
+ | --- | --- | --- |
660
+ | `LinkedVariantSummary` | `LinkedVariantSummary` | Slim variant snapshot linked from a configurator option — when an attribute option (e.g. "256 GB" storage) maps to a specific variant, this fragment exposes that variant's id, title, sku, stock flags. Spread inside `ProductAttributeOption.linkedVariant`. |
661
+ | `ProductAttributeOption` | `ProductAttributeOption` | One option (choice) within a configurator attribute — value, label, sort order, optional color hex, surcharge (amount + type), default flag, optional linked variant for variant-mapped options. |
662
+ | `ProductAttributeDefinition` | `ProductAttributeDefinition` | Configurator attribute definition — name, type, fillingMode (CUSTOMER / MERCHANT / BOTH), billingMode, tax class, validation bounds, options (for choice-type attributes), required + visibility flags. Returned by `product.attributes(filter)` for the configurator UI. |
663
+ <!-- AUTOGEN:FRAGMENTS:END -->
664
+
665
+ For full operation signatures with typed variables, GraphQL bodies and
666
+ fragment references, open [`llms-full.txt`](./llms-full.txt) or
667
+ [`operations.json`](./operations.json).
668
+
669
+ ## Runtime transport (separate package)
670
+
671
+ This catalog is transport-agnostic. The recommended runtime is
672
+ [`@doswiftly/storefront-sdk`](https://www.npmjs.com/package/@doswiftly/storefront-sdk),
673
+ which handles auth (cookie + Bearer), retries, currency context, and cart
674
+ state. **That** package belongs in `dependencies` (runtime). It accepts any
675
+ `TypedDocumentNode` you generate from the operations you wrote into your
676
+ `src/graphql/`:
159
677
 
160
678
  ```typescript
161
- import {
162
- ProductDocument,
163
- ProductQuery,
164
- ProductQueryVariables,
165
- } from "@/generated/graphql";
166
-
167
- // Full type safety
168
- const variables: ProductQueryVariables = {
169
- handle: "awesome-product",
170
- };
171
- ```
679
+ import { createStorefrontClient } from '@doswiftly/storefront-sdk';
680
+ import { ProductsDocument } from '@/generated/graphql';
681
+
682
+ const client = createStorefrontClient({
683
+ endpoint: 'https://api.your-shop.doswiftly.pl/storefront',
684
+ });
172
685
 
173
- ## Custom Operations
174
-
175
- You can add your own GraphQL operations alongside the package operations:
176
-
177
- ```graphql
178
- # src/graphql/custom-queries.graphql
179
- query FeaturedProducts {
180
- products(first: 4, filters: { tag: "featured" }) {
181
- edges {
182
- node {
183
- ...ProductCard
184
- }
185
- }
186
- }
187
- }
686
+ const data = await client.execute(ProductsDocument, { first: 12 });
188
687
  ```
189
688
 
190
- Re-run `npm run codegen` to generate types for your custom operations.
689
+ Any GraphQL client that consumes `TypedDocumentNode` works too
690
+ `graphql-request`, Apollo Client, urql, etc.
691
+
692
+ ## Conventions worth knowing before you generate queries
693
+
694
+ A short list of things LLMs (and humans) commonly get wrong against this API.
695
+ The full list with examples lives in [`AGENTS.md`](./AGENTS.md).
696
+
697
+ - **Cart mutations** use `cart<Verb><Object>` naming —
698
+ `cartAddLines` / `cartUpdateLines` / `cartRemoveLines`. The
699
+ `cart<Object><Verb>` aliases (`cartLinesAdd`, `cartDiscountCodesUpdate`,
700
+ etc.) do **not** exist in this API.
701
+ - **Errors live in `userErrors[]`** on every mutation:
702
+ `{ code, field, message }`. Always check this **before** consuming the
703
+ happy-path payload. `code` is a `String`, not an enum.
704
+ - **Auth** — send the `customerAccessToken` cookie (browser) **or**
705
+ `Authorization: Bearer <token>` header (server-to-server). Never both.
706
+ - **Money** — `Money.amount` is a **string** for decimal precision. Don't
707
+ `parseFloat` totals; use string-aware money math or pass through verbatim.
708
+ - **Pagination** — every list query uses Relay-style
709
+ `edges/nodes/pageInfo/totalCount` with `first/after/sortKey/reverse`.
710
+
711
+ ## Schema + versioning
712
+
713
+ `schema.graphql` is shipped inside this package as a static file, so your
714
+ codegen runs offline — no running backend needed and no introspection
715
+ roundtrip. Every published version reflects the live API at the time of
716
+ release; when you upgrade this package, run `pnpm codegen` in your project
717
+ to refresh types.
718
+
719
+ Versioning policy:
720
+
721
+ - **Major** — breaking changes (renamed/removed field, narrowed nullability,
722
+ removed operation). Migration notes in `CHANGELOG.md`.
723
+ - **Minor** — additive (new operation, new optional field).
724
+ - **Patch** — non-schema (documentation, descriptions).
191
725
 
192
726
  ## Links
193
727
 
194
- - [DoSwiftly Website](https://doswiftly.pl)
195
- - [DoSwiftly Documentation](https://doswiftly.pl/docs)
196
- - [GraphQL API Reference](https://doswiftly.pl/docs/api/graphql)
728
+ - [DoSwiftly platform](https://doswiftly.pl)
729
+ - [Storefront developer docs](https://doswiftly.pl/docs/storefront-developer)
730
+ - [GraphQL API reference](https://doswiftly.pl/docs/storefront-developer/api)
731
+ - [`@doswiftly/storefront-sdk`](https://www.npmjs.com/package/@doswiftly/storefront-sdk)
732
+ - [AGENTS.md format](https://agents.md/)
197
733
 
198
734
  ## License
199
735