@doswiftly/storefront-operations 7.0.0 → 8.0.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/AGENTS.md ADDED
@@ -0,0 +1,183 @@
1
+ # @doswiftly/storefront-operations — AI Agent Guide
2
+
3
+ > Pre-built GraphQL operations and schema for the **DoSwiftly Storefront API**.
4
+ > Use this when building e-commerce storefronts that consume DoSwiftly platform.
5
+
6
+ This file is the entry point for AI coding agents (Cursor, Claude Code, GitHub
7
+ Copilot, Codex, Aider, etc.). It uses **progressive disclosure** — read the
8
+ sections you need, then fetch deeper references on demand.
9
+
10
+ ## Intended use — this is a reference catalog, not a runtime library
11
+
12
+ This package is installed as a `devDependency` and ships only `.graphql` source
13
+ files plus Markdown / JSON / text reference documents. There is no JavaScript
14
+ to import — nothing here ends up in the storefront's runtime bundle.
15
+
16
+ **Your job when generating code**: read the catalog (this file + `llms-full.txt`
17
+ + `queries.graphql` / `mutations.graphql` in the same directory), then write
18
+ operations directly into the consumer's `src/graphql/` directory (or wherever
19
+ their codegen `documents:` glob points). The consumer's storefront codegen will
20
+ produce `TypedDocumentNode`s from your written operations.
21
+
22
+ Do **not** suggest importing operations from `@doswiftly/storefront-operations`
23
+ in runtime code — the package has no such exports. Do **not** assume the
24
+ consumer's `codegen.ts` references this package's `.graphql` files as
25
+ `documents:` (that's an advanced, discouraged pattern — see the package README
26
+ "Advanced" section). The default expectation is: schema lives here, operations
27
+ live in the consumer's repo.
28
+
29
+ <!-- AUTOGEN:STATS:BEGIN — auto-regenerated, do not edit by hand -->
30
+ - **Schema version**: 8.0.0
31
+ - **Queries**: 48
32
+ - **Mutations**: 44
33
+ - **Fragments**: 104
34
+ <!-- AUTOGEN:STATS:END -->
35
+
36
+ ## Loading order
37
+
38
+ When you need to build a storefront feature, load resources in this order:
39
+
40
+ 1. **`schema.graphql`** — full GraphQL schema. Authoritative source for types,
41
+ fields, enums, input types, and directives. Read this first when you need
42
+ to know what's available.
43
+ 2. **`AGENTS.md`** (this file) — critical conventions and anti-hallucination
44
+ notes. Read once per session.
45
+ 3. **`llms-full.txt`** — full operation reference with descriptions, typed
46
+ variables, and ready-to-execute GraphQL bodies. Search this file when you
47
+ need to know which named operation to use for a task.
48
+ 4. **`operations.json`** — same operations as structured JSON, useful when
49
+ you're calling tools programmatically (MCP servers, codegen).
50
+ 5. **`queries.graphql`, `mutations.graphql`, `fragments.graphql`** — raw
51
+ `.graphql` source. Use these directly with `@graphql-codegen/cli` or any
52
+ GraphQL client tooling.
53
+
54
+ ## Critical conventions — DO NOT hallucinate
55
+
56
+ These are conventions where LLMs **frequently hallucinate from training data**.
57
+ Verify against this list before generating queries.
58
+
59
+ ### Cart mutation names
60
+
61
+ The DoSwiftly API uses `cart<Verb><Object>` naming. **Do not** generate
62
+ `cart<Object><Verb>` aliases — they do not exist in this API.
63
+
64
+ | ✅ Use | ❌ Do NOT use (hallucination) |
65
+ | ------------------------------- | ------------------------------------ |
66
+ | `cartCreate` | (same) |
67
+ | `cartAddLines` | `cartLinesAdd` |
68
+ | `cartUpdateLines` | `cartLinesUpdate` |
69
+ | `cartRemoveLines` | `cartLinesRemove` |
70
+ | `cartApplyDiscountCodes` | `cartDiscountCodesUpdate` |
71
+ | `cartUpdateBuyerIdentity` | `cartBuyerIdentityUpdate` |
72
+ | `cartUpdateNote` | `cartNoteUpdate` |
73
+ | `cartUpdateAttributes` | `cartAttributesUpdate` |
74
+
75
+ ### `userErrors[]` is the global error envelope
76
+
77
+ Every mutation returns a `userErrors: [UserError!]!` field. The shape is:
78
+
79
+ ```graphql
80
+ type UserError {
81
+ message: String!
82
+ code: String # NOT a typed enum at the global level
83
+ field: [String!]
84
+ }
85
+ ```
86
+
87
+ **Always check `userErrors` BEFORE consuming the happy-path payload**:
88
+
89
+ ```graphql
90
+ mutation {
91
+ cartAddLines(id: $id, lines: $lines) {
92
+ cart { id }
93
+ userErrors { code field message } # ← check this first
94
+ }
95
+ }
96
+ ```
97
+
98
+ `userErrors[].code` is `String`, not an enum — handle it as a string. The
99
+ codes are listed in `llms-full.txt` and `operations.json` per-mutation.
100
+
101
+ **Domain-specific typed enums** exist for warnings (not for errors):
102
+ `CartWarningCode`, `DiscountErrorCode`, `GiftCardErrorCode`. These are used
103
+ in dedicated `warnings[]` fields on cart/discount/gift-card payloads — they
104
+ are **separate** from the generic `userErrors[]`.
105
+
106
+ ### Authentication — pick ONE, never both
107
+
108
+ Two auth modes are supported:
109
+
110
+ - **Browser storefronts**: rely on the `customerAccessToken` httpOnly cookie
111
+ (set by the SDK after `customerLogin` mutation). The cookie is sent
112
+ automatically — no header needed.
113
+ - **Server-to-server / mobile**: send `Authorization: Bearer <token>` header,
114
+ where `<token>` is the `accessToken` field returned by `customerLogin`.
115
+
116
+ **Never send both.** Do **not** invent `X-Customer-Token`, `X-Auth-Token`, or
117
+ similar — they are ignored.
118
+
119
+ ### `@inContext` directive
120
+
121
+ Pass storefront context (country, language, B2B buyer) via the `@inContext`
122
+ directive on operations:
123
+
124
+ ```graphql
125
+ query Products @inContext(country: PL, language: pl, preferredLocationId: "...") {
126
+ products(first: 12) { ... }
127
+ }
128
+ ```
129
+
130
+ Available args: `country`, `language`, `preferredLocationId`,
131
+ `buyer { customerAccessToken, companyLocationId }`. The `buyer` arg is for
132
+ **B2B server-to-server** flows only — browser storefronts use cookie auth and
133
+ should not send `buyer.customerAccessToken` in the directive.
134
+
135
+ ### `Money.amount` is a string, not a number
136
+
137
+ Money values use `Money { amount: String!, currencyCode: CurrencyCode! }`.
138
+ The `amount` is a **string** to preserve decimal precision. Never `parseFloat`
139
+ totals — use string-aware money math (e.g., `Decimal.js`) or pass the string
140
+ verbatim to display.
141
+
142
+ ### Pagination is Relay-style on every list
143
+
144
+ Every list query (products, collections, orders, etc.) uses Relay Connection
145
+ shape: `edges { cursor, node { ... } }`, `nodes { ... }`, `pageInfo { ... }`,
146
+ `totalCount`. Variables: `first`, `after`, `last`, `before`, `sortKey`,
147
+ `reverse`. The `cursor` is opaque — pass it back as `after` for the next page.
148
+
149
+ The `query` argument (when present) is a **text-search filter**, not a
150
+ GraphQL operation. Don't confuse with operation name.
151
+
152
+ ### `product(id, handle)` — both optional, one required
153
+
154
+ The `product` query accepts EITHER `id: ID` OR `handle: String`. Pass exactly
155
+ one. Do **not** invent `slug`, `productHandle`, `productId`, or `productSlug`
156
+ arg names.
157
+
158
+ ### Customer order — singular, not plural
159
+
160
+ To fetch customer orders:
161
+
162
+ - `query Customer { customer { orders { ... } } }` — list of orders.
163
+ - `query CustomerOrder($orderId: ID!) { ... }` — single order by ID.
164
+
165
+ **Hallucinations to avoid**: `OrderById`, `Order(id)`, `CustomerOrders` (plural),
166
+ `CustomerAddresses` (use `CustomerProfile` for profile data),
167
+ `CustomerMetaPropertiesSet`/`CustomerMetaPropertyDelete` — these do not exist.
168
+
169
+ ### Mutations are NOT auto-retried
170
+
171
+ `@doswiftly/storefront-sdk` retries **queries** on transient network errors
172
+ but does **NOT** retry mutations (that's a deliberate platform contract — at-most-once
173
+ semantics). Idempotency is the caller's responsibility. If you need retries
174
+ on a mutation, wrap with your own backoff logic and check `userErrors` to
175
+ decide whether to retry.
176
+
177
+ ## When in doubt
178
+
179
+ - **Schema question** ("what fields are on `X`?") → grep `schema.graphql`
180
+ - **Operation question** ("which mutation does Y?") → grep `llms-full.txt` for the verb in `**Description**:` lines
181
+ - **Programmatic enumeration** → load `operations.json`
182
+
183
+ For codegen setup and runtime transport, see `README.md` and [`@doswiftly/storefront-sdk`](https://www.npmjs.com/package/@doswiftly/storefront-sdk).
package/CHANGELOG.md CHANGED
@@ -1,5 +1,111 @@
1
1
  # Changelog
2
2
 
3
+ ## 8.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 5f016e2: **BREAKING**: Operations were renamed to match the underlying GraphQL schema field names. If you used codegen against this package, regenerate your hooks and update import paths.
8
+
9
+ ### Renamed checkout mutations
10
+
11
+ | Old operation name | New operation name | New field call |
12
+ | --------------------------------- | --------------------------------- | ---------------------------------------------------- |
13
+ | `CheckoutShippingAddressUpdate` | `CheckoutUpdateShippingAddress` | `checkoutUpdateShippingAddress(id, shippingAddress)` |
14
+ | `CheckoutBillingAddressUpdate` | `CheckoutUpdateBillingAddress` | `checkoutUpdateBillingAddress(id, billingAddress)` |
15
+ | `CheckoutEmailUpdate` | `CheckoutUpdateEmail` | `checkoutUpdateEmail(id, email)` |
16
+ | `CheckoutShippingLineUpdate` | `CheckoutSelectShippingRate` | `checkoutSelectShippingRate(id, rateId)` |
17
+ | `CheckoutDiscountCodeApply` | `CheckoutApplyDiscountCode` | `checkoutApplyDiscountCode(id, discountCode)` |
18
+ | `CheckoutDiscountCodeRemove` | `CheckoutRemoveDiscountCode` | `checkoutRemoveDiscountCode(id, discountCode)` |
19
+ | `CheckoutDiscountCodeValidate` | `CheckoutValidateDiscountCode` | `checkoutValidateDiscountCode(id, discountCode)` |
20
+ | `CheckoutPaymentMethodUpdate` | `CheckoutSelectPaymentMethod` | `checkoutSelectPaymentMethod(id, paymentMethodId)` |
21
+ | `CheckoutGiftCardApply` | `CheckoutApplyGiftCard` | `checkoutApplyGiftCard(id, giftCardCode)` |
22
+ | `CheckoutGiftCardRemove` | `CheckoutRemoveGiftCard` | `checkoutRemoveGiftCard(id, giftCardCode)` |
23
+ | `CheckoutGiftCardRecipientUpdate` | `CheckoutUpdateGiftCardRecipient` | `checkoutUpdateGiftCardRecipient(input)` |
24
+
25
+ ### Argument changes in checkout mutations
26
+ - Variable `$checkoutId: ID!` → `$id: ID!`
27
+ - Argument `checkoutId:` → `id:`
28
+ - In `CheckoutSelectShippingRate`: variable `$shippingRateHandle: String!` → `$rateId: String!`, argument `shippingRateHandle:` → `rateId:`
29
+
30
+ Note: `CheckoutCreate` and `CheckoutComplete` were already aligned and are unchanged.
31
+
32
+ ### Renamed queries
33
+
34
+ | Old query | New query | New field call |
35
+ | --------------------------------------- | ------------------- | --------------------------------- |
36
+ | `PredictiveSearch` (`predictiveSearch`) | `SearchSuggestions` | `searchSuggestions(query, limit)` |
37
+ | `AvailableFilters` (`availableFilters`) | `ProductFilters` | `productFilters(input)` |
38
+
39
+ `Categories` query now uses the `rootsOnly: true` argument and reads `nodes` instead of `roots`. Same data shape, standard Relay-style connection.
40
+
41
+ ### Renamed mutations (loyalty)
42
+
43
+ | Old mutation field | New mutation field |
44
+ | ---------------------- | ----------------------------- |
45
+ | `redeemLoyaltyReward` | `loyaltyRedeemReward` |
46
+ | `generateReferralCode` | `loyaltyGenerateReferralCode` |
47
+
48
+ Operation names (`RedeemLoyaltyReward`, `GenerateReferralCode`) are unchanged.
49
+
50
+ ### Wishlist mutations — argument alignment
51
+ - `wishlistAddItem(wishlistId, input)` → `wishlistAddItem(id, input)`
52
+ - `wishlistRemoveItem(wishlistId, itemId)` → `wishlistRemoveItem(id, itemId)`
53
+ - `wishlistDelete(wishlistId)` → `wishlistDelete(id)`
54
+
55
+ The `userErrors` field on every wishlist mutation result now correctly carries the `UserError` sub-selection.
56
+
57
+ ### Fragment shape changes
58
+ - `ProductCard` fragment now reads `categories { id, slug, name }` instead of the removed scalar `category` field. Cards that displayed a single category should now show the first item or join the list.
59
+ - `AvailableFilters` fragment now reads `activeCount` (was `activeFilterCount`) and `matchCount` (was `totalProducts`).
60
+ - Variant connections (`product.variants`) now require explicit `nodes { … }` selection — Relay-style.
61
+ - Loyalty payload fragments (`RedeemRewardPayload`, `GenerateReferralCodePayload`) now require the `UserError` sub-selection on `userErrors`.
62
+
63
+ ### Removed fragments
64
+ - `Price`, `PriceMoney`, `ProductRecommendation`, `CartRecommendation` — unused by any operation in this package. Inline equivalents are available if needed.
65
+
66
+ ### Migration
67
+ 1. Regenerate codegen output against the new `schema.graphql` and operation files.
68
+ 2. Update import paths to the new operation/hook names (search-and-replace based on the tables above).
69
+ 3. In your form/UI code, rename the mutation variable `checkoutId` → `id` and update the argument key in the request payload.
70
+ 4. In the shipping-rate flow, rename `shippingRateHandle` → `rateId`.
71
+ 5. In `ProductCard` consumers, switch from `product.category` (string) to the first item of `product.categories` (array of `{ id, slug, name }`).
72
+ 6. In `AvailableFilters` consumers, rename `activeFilterCount` → `activeCount` and `totalProducts` → `matchCount`.
73
+ 7. In any `variants` selection on a product, wrap field selections in `nodes { … }`.
74
+ 8. In `userErrors` reads on loyalty and wishlist mutations, expect the `UserError` shape (no longer a bare scalar).
75
+
76
+ ## 7.1.0
77
+
78
+ ### Minor Changes
79
+
80
+ - 0399ef8: Auto-generated, drift-proof docs and AI-agent context shipped inside the package.
81
+
82
+ The package now ships three new files alongside the `.graphql` sources, all
83
+ generated automatically and kept in sync with the schema:
84
+ - **`AGENTS.md`** — entry point for AI coding agents (Cursor, Claude Code,
85
+ GitHub Copilot, Codex, Aider, Gemini CLI, …). Critical conventions and
86
+ anti-hallucination notes — load this once per session.
87
+ - **`llms-full.txt`** — full operation reference: descriptions, typed variables,
88
+ ready-to-execute GraphQL bodies, fragment cross-references.
89
+ - **`operations.json`** — same operations as structured JSON for MCP servers
90
+ and programmatic tools.
91
+
92
+ The `Available Operations` section in `README.md` is now also auto-generated,
93
+ so it can never drift from the actual schema again.
94
+
95
+ **Anti-hallucination conventions** documented in `AGENTS.md`:
96
+ - Cart mutations are `cartAddLines` / `cartUpdateLines` / `cartRemoveLines`
97
+ (NOT the `cart<Object><Verb>` aliases — they do not exist in this API).
98
+ - `userErrors[].code` is a `String`, not an enum. Domain-typed enums exist
99
+ separately for warnings (`CartWarningCode`, `DiscountErrorCode`, etc.).
100
+ - Authentication uses **either** the `customerAccessToken` cookie **or** the
101
+ `Authorization: Bearer` header — never both.
102
+ - `Money.amount` is a string (decimal precision), not a number.
103
+
104
+ No code changes for existing consumers — `schema.graphql`, `queries.graphql`,
105
+ `mutations.graphql`, and `fragments.graphql` are unchanged in surface (only
106
+ non-functional `#` description comments were added in the operation files).
107
+ Codegen continues to produce identical typed documents.
108
+
3
109
  ## 7.0.0
4
110
 
5
111
  ### Major Changes