@doswiftly/storefront-operations 20.2.0 → 21.0.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 +2 -2
- package/CHANGELOG.md +38 -0
- package/README.md +11 -5
- package/fragments.graphql +30 -15
- package/llms-full.txt +48 -29
- package/operations.json +30 -19
- package/package.json +1 -1
- package/queries.graphql +4 -4
- package/schema.graphql +117 -107
package/AGENTS.md
CHANGED
|
@@ -27,10 +27,10 @@ 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**:
|
|
30
|
+
- **Schema version**: 21.0.1
|
|
31
31
|
- **Queries**: 52
|
|
32
32
|
- **Mutations**: 44
|
|
33
|
-
- **Fragments**:
|
|
33
|
+
- **Fragments**: 105
|
|
34
34
|
<!-- AUTOGEN:STATS:END -->
|
|
35
35
|
|
|
36
36
|
## Loading order
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 21.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 65c7f72: Fixed: cart, order, and customer address reads now include `buildingNumber` and `flatNumber`. The previous release added both fields to the schema and inputs (you could send them), but the SDK's `MailingAddress` selection did not request them back — they always came back missing on `cart.shippingAddress` / `cart.billingAddress`, order addresses, the saved address book (`getAddresses()`), and `customer.defaultAddress`. The generated types now carry both fields as well.
|
|
8
|
+
|
|
9
|
+
Documentation: rewrote the SDK README to match the current API.
|
|
10
|
+
|
|
11
|
+
The README (shown on npm and GitHub) previously described setup patterns from older releases. It now documents the current surface:
|
|
12
|
+
- **Quick start** based on `createStorefrontAuthRoute` (one route file mounting `login` / `refresh` / `logout` / `whoami`), `getInitialAuth()` server seeding, and `<StorefrontProvider>` with automatic session refresh.
|
|
13
|
+
- **Cart** chapter covering the capability model (composite `cart-id` cookie carrying the cart access secret, `cartSecretMiddleware`), the full `useCartManager` checkout lifecycle (per-operation recovery table, tagged-union `status`, lifecycle callbacks, `initialCartId`), `<CartManagerProvider>` / `useCartManagerContext()`, completion + payment session creation, discovery queries, `merge` / `downgradeOnLogout` / `recoveryRedeem`, and the framework-agnostic recovery runner.
|
|
14
|
+
- **Authentication** chapter documenting the session cookie set, proactive + reactive refresh, the BFF sign-in flow, `AuthClient` methods (including `refreshSession()` and `getAddresses()`), and reverse-proxy origin validators.
|
|
15
|
+
- Reference sections for the middleware pipeline order, debug logging (including the remote debug transport), runtime schema enums, cookie contract constants, format hooks, pre-built components (including payment instrument tiles), and server-side helpers (`readCartCredentials`, `serverCartSecretMiddleware`).
|
|
16
|
+
- A **Deprecated** section listing the legacy cart store (`createCartStore` / `CartProvider` / `useCartStore`), `AuthClient.refreshToken()` / `useRefreshToken`, and `ShopCurrencyData` with their replacements.
|
|
17
|
+
|
|
18
|
+
Also cleaned up developer-facing JSDoc across the package (clients, middleware, stores, hooks, pre-built components): comments and IDE hover text are now plain technical English, and the `getBrowserDataForPayment` example no longer suggests passing browser data to `createPayment` (its input is `{ orderId, returnUrl?, cancelUrl? }`). No runtime changes.
|
|
19
|
+
|
|
20
|
+
`@doswiftly/storefront-operations` is version-synced; no code changes.
|
|
21
|
+
|
|
22
|
+
## 21.0.0
|
|
23
|
+
|
|
24
|
+
### Major Changes
|
|
25
|
+
|
|
26
|
+
- a539021: Product attribute fields renamed and split by purpose (breaking)
|
|
27
|
+
|
|
28
|
+
`Product.attributes` now returns the product's **stored custom-field values** — merchant-managed metadata such as manufacturer, licence or material — as `[EntityAttributeField!]!`. Only values marked visible are returned; pass the optional `namespace` argument to fetch a single group.
|
|
29
|
+
|
|
30
|
+
The configurator field **definitions** that previously lived under `Product.attributes` have moved to **`Product.configuratorFields(filter: { filledBy: ... })`**, returning `[ConfiguratorField!]!`.
|
|
31
|
+
|
|
32
|
+
Renames:
|
|
33
|
+
- Type `ProductAttributeDefinition` → `ConfiguratorField`, with field renames `fillingMode` → `filledBy`, `billingMode` → `pricingMode`, `isRequired` → `required`, `displayOrder` → `sortOrder`.
|
|
34
|
+
- Type `ProductAttributeOption` → `ConfiguratorOption`.
|
|
35
|
+
- Input `ProductAttributeFilterInput` → `ConfiguratorFieldFilterInput` (its `fillingMode` argument → `filledBy`).
|
|
36
|
+
|
|
37
|
+
Removed from the public contract: `Product.attributeSetId`; the internal `scopeProductId` and `taxClassId` on configurator fields; and the raw `linkedVariantId` on a configurator option (read `linkedVariant.id` instead).
|
|
38
|
+
|
|
39
|
+
Migration: rename `attributes(filter: { fillingMode })` selections to `configuratorFields(filter: { filledBy })` and spread `...ConfiguratorField`; use the new `attributes` field (optional `namespace`) to read product metadata values.
|
|
40
|
+
|
|
3
41
|
## 20.2.0
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -170,7 +170,7 @@ full executable body of each operation.
|
|
|
170
170
|
| Operation | Description |
|
|
171
171
|
| --- | --- |
|
|
172
172
|
| `Product` | Fetches a single product by `id` or `handle` (URL-friendly identifier). 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). |
|
|
173
|
-
| `ProductConfigurator` | Fetches a product together with its
|
|
173
|
+
| `ProductConfigurator` | Fetches a product together with its configurator fields, optimized for the product-page configurator UI. filledBy CUSTOMER returns only the fields a shopper edits; pass BOTH to also include seller-prefilled fields. Single round-trip. |
|
|
174
174
|
| `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). |
|
|
175
175
|
| `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. |
|
|
176
176
|
| `SearchSuggestions` | 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. |
|
|
@@ -638,13 +638,19 @@ full executable body of each operation.
|
|
|
638
638
|
| --- | --- | --- |
|
|
639
639
|
| `UrlRedirect` | `UrlRedirect` | Single legacy `path` → new `target` redirect entry. Use on the server / edge to issue 301 redirects for migrated routes. |
|
|
640
640
|
|
|
641
|
-
#### Product
|
|
641
|
+
#### Product Attributes (stored metadata values)
|
|
642
642
|
|
|
643
643
|
| Fragment | On Type | Description |
|
|
644
644
|
| --- | --- | --- |
|
|
645
|
-
| `
|
|
646
|
-
|
|
647
|
-
|
|
645
|
+
| `AttributeValue` | `EntityAttributeField` | A stored custom-field value on a product (or variant / customer / order) - merchant-managed metadata exposed via the `attributes` field. Parse `value` (a JSON string) according to `type`. |
|
|
646
|
+
|
|
647
|
+
#### Product Configurator (per-product fields)
|
|
648
|
+
|
|
649
|
+
| Fragment | On Type | Description |
|
|
650
|
+
| --- | --- | --- |
|
|
651
|
+
| `LinkedVariantSummary` | `LinkedVariantSummary` | Slim variant snapshot linked from a configurator choice — when an option (e.g. "256 GB" storage) maps to a specific variant, this fragment exposes that variant's id, title, sku, stock flags. Spread inside `ConfiguratorOption.linkedVariant`. |
|
|
652
|
+
| `ConfiguratorOption` | `ConfiguratorOption` | One selectable choice within a configurator field - value, label, sort order, optional colour, surcharge (amount + type), default flag, and the linked stocked variant for component-style choices. |
|
|
653
|
+
| `ConfiguratorField` | `ConfiguratorField` | A configurator field on the product page - label, input type, who fills it (filledBy), pricing behaviour (pricingMode), validation bounds, required + visibility flags, and selectable options for choice-type fields. |
|
|
648
654
|
<!-- AUTOGEN:FRAGMENTS:END -->
|
|
649
655
|
|
|
650
656
|
For full operation signatures with typed variables, GraphQL bodies and
|
package/fragments.graphql
CHANGED
|
@@ -155,7 +155,9 @@ fragment ProductBase on Product {
|
|
|
155
155
|
stockTotal
|
|
156
156
|
type
|
|
157
157
|
visibility
|
|
158
|
-
|
|
158
|
+
attributes {
|
|
159
|
+
...AttributeValue
|
|
160
|
+
}
|
|
159
161
|
createdAt
|
|
160
162
|
updatedAt
|
|
161
163
|
}
|
|
@@ -1632,10 +1634,26 @@ fragment UrlRedirect on UrlRedirect {
|
|
|
1632
1634
|
}
|
|
1633
1635
|
|
|
1634
1636
|
# ============================================
|
|
1635
|
-
# Product
|
|
1637
|
+
# Product Attributes (stored metadata values)
|
|
1638
|
+
# ============================================
|
|
1639
|
+
|
|
1640
|
+
# A stored custom-field value on a product (or variant / customer / order) - merchant-managed metadata exposed via the `attributes` field. Parse `value` (a JSON string) according to `type`.
|
|
1641
|
+
fragment AttributeValue on EntityAttributeField {
|
|
1642
|
+
id
|
|
1643
|
+
definitionId
|
|
1644
|
+
handle
|
|
1645
|
+
name
|
|
1646
|
+
namespace
|
|
1647
|
+
type
|
|
1648
|
+
value
|
|
1649
|
+
isVisibleOverride
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
# ============================================
|
|
1653
|
+
# Product Configurator (per-product fields)
|
|
1636
1654
|
# ============================================
|
|
1637
1655
|
|
|
1638
|
-
# Slim variant snapshot linked from a configurator
|
|
1656
|
+
# Slim variant snapshot linked from a configurator choice — when an option (e.g. "256 GB" storage) maps to a specific variant, this fragment exposes that variant's id, title, sku, stock flags. Spread inside `ConfiguratorOption.linkedVariant`.
|
|
1639
1657
|
fragment LinkedVariantSummary on LinkedVariantSummary {
|
|
1640
1658
|
id
|
|
1641
1659
|
productId
|
|
@@ -1646,8 +1664,8 @@ fragment LinkedVariantSummary on LinkedVariantSummary {
|
|
|
1646
1664
|
trackQuantity
|
|
1647
1665
|
}
|
|
1648
1666
|
|
|
1649
|
-
# One
|
|
1650
|
-
fragment
|
|
1667
|
+
# One selectable choice within a configurator field - value, label, sort order, optional colour, surcharge (amount + type), default flag, and the linked stocked variant for component-style choices.
|
|
1668
|
+
fragment ConfiguratorOption on ConfiguratorOption {
|
|
1651
1669
|
id
|
|
1652
1670
|
value
|
|
1653
1671
|
label
|
|
@@ -1656,29 +1674,26 @@ fragment ProductAttributeOption on ProductAttributeOption {
|
|
|
1656
1674
|
surchargeAmount
|
|
1657
1675
|
surchargeType
|
|
1658
1676
|
isDefault
|
|
1659
|
-
linkedVariantId
|
|
1660
1677
|
linkedVariant {
|
|
1661
1678
|
...LinkedVariantSummary
|
|
1662
1679
|
}
|
|
1663
1680
|
}
|
|
1664
1681
|
|
|
1665
|
-
#
|
|
1666
|
-
fragment
|
|
1682
|
+
# A configurator field on the product page - label, input type, who fills it (filledBy), pricing behaviour (pricingMode), validation bounds, required + visibility flags, and selectable options for choice-type fields.
|
|
1683
|
+
fragment ConfiguratorField on ConfiguratorField {
|
|
1667
1684
|
id
|
|
1668
1685
|
name
|
|
1669
1686
|
handle
|
|
1670
1687
|
description
|
|
1671
1688
|
type
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
scopeProductId
|
|
1676
|
-
isRequired
|
|
1689
|
+
filledBy
|
|
1690
|
+
pricingMode
|
|
1691
|
+
required
|
|
1677
1692
|
isVisible
|
|
1678
|
-
|
|
1693
|
+
sortOrder
|
|
1679
1694
|
minValue
|
|
1680
1695
|
maxValue
|
|
1681
1696
|
options {
|
|
1682
|
-
...
|
|
1697
|
+
...ConfiguratorOption
|
|
1683
1698
|
}
|
|
1684
1699
|
}
|
package/llms-full.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DoSwiftly Storefront Operations — Full Reference
|
|
2
2
|
|
|
3
|
-
> Schema version: **
|
|
4
|
-
> 52 queries · 44 mutations ·
|
|
3
|
+
> Schema version: **21.0.1**
|
|
4
|
+
> 52 queries · 44 mutations · 105 fragments
|
|
5
5
|
|
|
6
6
|
Auto-generated from `.graphql` source files. Do not edit by hand — this file is
|
|
7
7
|
regenerated on every release to match the published schema.
|
|
@@ -81,21 +81,21 @@ query Product($id: ID, $handle: String) {
|
|
|
81
81
|
|
|
82
82
|
**Section**: Products
|
|
83
83
|
|
|
84
|
-
**Description**: Fetches a product together with its
|
|
84
|
+
**Description**: Fetches a product together with its configurator fields, optimized for the product-page configurator UI. filledBy CUSTOMER returns only the fields a shopper edits; pass BOTH to also include seller-prefilled fields. Single round-trip.
|
|
85
85
|
|
|
86
86
|
**Variables**:
|
|
87
87
|
- `$handle`: `String!`
|
|
88
|
-
- `$
|
|
88
|
+
- `$filledBy`: `AttributeFillingMode` *(default: `CUSTOMER`)*
|
|
89
89
|
|
|
90
|
-
**Fragments used**: `
|
|
90
|
+
**Fragments used**: `ConfiguratorField`, `ProductFull`
|
|
91
91
|
|
|
92
92
|
**GraphQL**:
|
|
93
93
|
```graphql
|
|
94
|
-
query ProductConfigurator($handle: String!, $
|
|
94
|
+
query ProductConfigurator($handle: String!, $filledBy: AttributeFillingMode = CUSTOMER) {
|
|
95
95
|
product(handle: $handle) {
|
|
96
96
|
...ProductFull
|
|
97
|
-
|
|
98
|
-
...
|
|
97
|
+
configuratorFields(filter: {filledBy: $filledBy}) {
|
|
98
|
+
...ConfiguratorField
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -2788,7 +2788,7 @@ fragment ProductCard on Product {
|
|
|
2788
2788
|
|
|
2789
2789
|
**Description**: `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.
|
|
2790
2790
|
|
|
2791
|
-
**Uses fragments**: `ProductCard`
|
|
2791
|
+
**Uses fragments**: `AttributeValue`, `ProductCard`
|
|
2792
2792
|
|
|
2793
2793
|
**GraphQL**:
|
|
2794
2794
|
```graphql
|
|
@@ -2799,7 +2799,9 @@ fragment ProductBase on Product {
|
|
|
2799
2799
|
stockTotal
|
|
2800
2800
|
type
|
|
2801
2801
|
visibility
|
|
2802
|
-
|
|
2802
|
+
attributes {
|
|
2803
|
+
...AttributeValue
|
|
2804
|
+
}
|
|
2803
2805
|
createdAt
|
|
2804
2806
|
updatedAt
|
|
2805
2807
|
}
|
|
@@ -5080,11 +5082,31 @@ fragment UrlRedirect on UrlRedirect {
|
|
|
5080
5082
|
}
|
|
5081
5083
|
```
|
|
5082
5084
|
|
|
5085
|
+
### Fragment: `AttributeValue` on `EntityAttributeField`
|
|
5086
|
+
|
|
5087
|
+
**Section**: Product Attributes (stored metadata values)
|
|
5088
|
+
|
|
5089
|
+
**Description**: A stored custom-field value on a product (or variant / customer / order) - merchant-managed metadata exposed via the `attributes` field. Parse `value` (a JSON string) according to `type`.
|
|
5090
|
+
|
|
5091
|
+
**GraphQL**:
|
|
5092
|
+
```graphql
|
|
5093
|
+
fragment AttributeValue on EntityAttributeField {
|
|
5094
|
+
id
|
|
5095
|
+
definitionId
|
|
5096
|
+
handle
|
|
5097
|
+
name
|
|
5098
|
+
namespace
|
|
5099
|
+
type
|
|
5100
|
+
value
|
|
5101
|
+
isVisibleOverride
|
|
5102
|
+
}
|
|
5103
|
+
```
|
|
5104
|
+
|
|
5083
5105
|
### Fragment: `LinkedVariantSummary` on `LinkedVariantSummary`
|
|
5084
5106
|
|
|
5085
|
-
**Section**: Product Configurator (per-product
|
|
5107
|
+
**Section**: Product Configurator (per-product fields)
|
|
5086
5108
|
|
|
5087
|
-
**Description**: Slim variant snapshot linked from a configurator
|
|
5109
|
+
**Description**: Slim variant snapshot linked from a configurator choice — when an option (e.g. "256 GB" storage) maps to a specific variant, this fragment exposes that variant's id, title, sku, stock flags. Spread inside `ConfiguratorOption.linkedVariant`.
|
|
5088
5110
|
|
|
5089
5111
|
**GraphQL**:
|
|
5090
5112
|
```graphql
|
|
@@ -5099,17 +5121,17 @@ fragment LinkedVariantSummary on LinkedVariantSummary {
|
|
|
5099
5121
|
}
|
|
5100
5122
|
```
|
|
5101
5123
|
|
|
5102
|
-
### Fragment: `
|
|
5124
|
+
### Fragment: `ConfiguratorOption` on `ConfiguratorOption`
|
|
5103
5125
|
|
|
5104
|
-
**Section**: Product Configurator (per-product
|
|
5126
|
+
**Section**: Product Configurator (per-product fields)
|
|
5105
5127
|
|
|
5106
|
-
**Description**: One
|
|
5128
|
+
**Description**: One selectable choice within a configurator field - value, label, sort order, optional colour, surcharge (amount + type), default flag, and the linked stocked variant for component-style choices.
|
|
5107
5129
|
|
|
5108
5130
|
**Uses fragments**: `LinkedVariantSummary`
|
|
5109
5131
|
|
|
5110
5132
|
**GraphQL**:
|
|
5111
5133
|
```graphql
|
|
5112
|
-
fragment
|
|
5134
|
+
fragment ConfiguratorOption on ConfiguratorOption {
|
|
5113
5135
|
id
|
|
5114
5136
|
value
|
|
5115
5137
|
label
|
|
@@ -5118,40 +5140,37 @@ fragment ProductAttributeOption on ProductAttributeOption {
|
|
|
5118
5140
|
surchargeAmount
|
|
5119
5141
|
surchargeType
|
|
5120
5142
|
isDefault
|
|
5121
|
-
linkedVariantId
|
|
5122
5143
|
linkedVariant {
|
|
5123
5144
|
...LinkedVariantSummary
|
|
5124
5145
|
}
|
|
5125
5146
|
}
|
|
5126
5147
|
```
|
|
5127
5148
|
|
|
5128
|
-
### Fragment: `
|
|
5149
|
+
### Fragment: `ConfiguratorField` on `ConfiguratorField`
|
|
5129
5150
|
|
|
5130
|
-
**Section**: Product Configurator (per-product
|
|
5151
|
+
**Section**: Product Configurator (per-product fields)
|
|
5131
5152
|
|
|
5132
|
-
**Description**:
|
|
5153
|
+
**Description**: A configurator field on the product page - label, input type, who fills it (filledBy), pricing behaviour (pricingMode), validation bounds, required + visibility flags, and selectable options for choice-type fields.
|
|
5133
5154
|
|
|
5134
|
-
**Uses fragments**: `
|
|
5155
|
+
**Uses fragments**: `ConfiguratorOption`
|
|
5135
5156
|
|
|
5136
5157
|
**GraphQL**:
|
|
5137
5158
|
```graphql
|
|
5138
|
-
fragment
|
|
5159
|
+
fragment ConfiguratorField on ConfiguratorField {
|
|
5139
5160
|
id
|
|
5140
5161
|
name
|
|
5141
5162
|
handle
|
|
5142
5163
|
description
|
|
5143
5164
|
type
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
scopeProductId
|
|
5148
|
-
isRequired
|
|
5165
|
+
filledBy
|
|
5166
|
+
pricingMode
|
|
5167
|
+
required
|
|
5149
5168
|
isVisible
|
|
5150
|
-
|
|
5169
|
+
sortOrder
|
|
5151
5170
|
minValue
|
|
5152
5171
|
maxValue
|
|
5153
5172
|
options {
|
|
5154
|
-
...
|
|
5173
|
+
...ConfiguratorOption
|
|
5155
5174
|
}
|
|
5156
5175
|
}
|
|
5157
5176
|
```
|
package/operations.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"schemaVersion": "
|
|
2
|
+
"schemaVersion": "21.0.1",
|
|
3
3
|
"queries": [
|
|
4
4
|
{
|
|
5
5
|
"name": "Shop",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"name": "ProductConfigurator",
|
|
50
50
|
"kind": "query",
|
|
51
51
|
"section": "Products",
|
|
52
|
-
"description": "Fetches a product together with its
|
|
52
|
+
"description": "Fetches a product together with its configurator fields, optimized for the product-page configurator UI. filledBy CUSTOMER returns only the fields a shopper edits; pass BOTH to also include seller-prefilled fields. Single round-trip.",
|
|
53
53
|
"variables": [
|
|
54
54
|
{
|
|
55
55
|
"name": "handle",
|
|
@@ -57,16 +57,16 @@
|
|
|
57
57
|
"defaultValue": null
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"name": "
|
|
60
|
+
"name": "filledBy",
|
|
61
61
|
"type": "AttributeFillingMode",
|
|
62
62
|
"defaultValue": "CUSTOMER"
|
|
63
63
|
}
|
|
64
64
|
],
|
|
65
65
|
"fragmentRefs": [
|
|
66
|
-
"
|
|
66
|
+
"ConfiguratorField",
|
|
67
67
|
"ProductFull"
|
|
68
68
|
],
|
|
69
|
-
"body": "query ProductConfigurator($handle: String!, $
|
|
69
|
+
"body": "query ProductConfigurator($handle: String!, $filledBy: AttributeFillingMode = CUSTOMER) {\n product(handle: $handle) {\n ...ProductFull\n configuratorFields(filter: {filledBy: $filledBy}) {\n ...ConfiguratorField\n }\n }\n}"
|
|
70
70
|
},
|
|
71
71
|
{
|
|
72
72
|
"name": "Products",
|
|
@@ -2054,9 +2054,10 @@
|
|
|
2054
2054
|
"description": "`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.",
|
|
2055
2055
|
"variables": [],
|
|
2056
2056
|
"fragmentRefs": [
|
|
2057
|
+
"AttributeValue",
|
|
2057
2058
|
"ProductCard"
|
|
2058
2059
|
],
|
|
2059
|
-
"body": "fragment ProductBase on Product {\n ...ProductCard\n description\n descriptionHtml\n stockTotal\n type\n visibility\n
|
|
2060
|
+
"body": "fragment ProductBase on Product {\n ...ProductCard\n description\n descriptionHtml\n stockTotal\n type\n visibility\n attributes {\n ...AttributeValue\n }\n createdAt\n updatedAt\n}",
|
|
2060
2061
|
"onType": "Product"
|
|
2061
2062
|
},
|
|
2062
2063
|
{
|
|
@@ -3109,39 +3110,49 @@
|
|
|
3109
3110
|
"body": "fragment UrlRedirect on UrlRedirect {\n path\n target\n}",
|
|
3110
3111
|
"onType": "UrlRedirect"
|
|
3111
3112
|
},
|
|
3113
|
+
{
|
|
3114
|
+
"name": "AttributeValue",
|
|
3115
|
+
"kind": "fragment",
|
|
3116
|
+
"section": "Product Attributes (stored metadata values)",
|
|
3117
|
+
"description": "A stored custom-field value on a product (or variant / customer / order) - merchant-managed metadata exposed via the `attributes` field. Parse `value` (a JSON string) according to `type`.",
|
|
3118
|
+
"variables": [],
|
|
3119
|
+
"fragmentRefs": [],
|
|
3120
|
+
"body": "fragment AttributeValue on EntityAttributeField {\n id\n definitionId\n handle\n name\n namespace\n type\n value\n isVisibleOverride\n}",
|
|
3121
|
+
"onType": "EntityAttributeField"
|
|
3122
|
+
},
|
|
3112
3123
|
{
|
|
3113
3124
|
"name": "LinkedVariantSummary",
|
|
3114
3125
|
"kind": "fragment",
|
|
3115
|
-
"section": "Product Configurator (per-product
|
|
3116
|
-
"description": "Slim variant snapshot linked from a configurator
|
|
3126
|
+
"section": "Product Configurator (per-product fields)",
|
|
3127
|
+
"description": "Slim variant snapshot linked from a configurator choice — when an option (e.g. \"256 GB\" storage) maps to a specific variant, this fragment exposes that variant's id, title, sku, stock flags. Spread inside `ConfiguratorOption.linkedVariant`.",
|
|
3117
3128
|
"variables": [],
|
|
3118
3129
|
"fragmentRefs": [],
|
|
3119
3130
|
"body": "fragment LinkedVariantSummary on LinkedVariantSummary {\n id\n productId\n title\n sku\n availableStock\n isAvailable\n trackQuantity\n}",
|
|
3120
3131
|
"onType": "LinkedVariantSummary"
|
|
3121
3132
|
},
|
|
3122
3133
|
{
|
|
3123
|
-
"name": "
|
|
3134
|
+
"name": "ConfiguratorOption",
|
|
3124
3135
|
"kind": "fragment",
|
|
3125
|
-
"section": "Product Configurator (per-product
|
|
3126
|
-
"description": "One
|
|
3136
|
+
"section": "Product Configurator (per-product fields)",
|
|
3137
|
+
"description": "One selectable choice within a configurator field - value, label, sort order, optional colour, surcharge (amount + type), default flag, and the linked stocked variant for component-style choices.",
|
|
3127
3138
|
"variables": [],
|
|
3128
3139
|
"fragmentRefs": [
|
|
3129
3140
|
"LinkedVariantSummary"
|
|
3130
3141
|
],
|
|
3131
|
-
"body": "fragment
|
|
3132
|
-
"onType": "
|
|
3142
|
+
"body": "fragment ConfiguratorOption on ConfiguratorOption {\n id\n value\n label\n sortOrder\n colorHex\n surchargeAmount\n surchargeType\n isDefault\n linkedVariant {\n ...LinkedVariantSummary\n }\n}",
|
|
3143
|
+
"onType": "ConfiguratorOption"
|
|
3133
3144
|
},
|
|
3134
3145
|
{
|
|
3135
|
-
"name": "
|
|
3146
|
+
"name": "ConfiguratorField",
|
|
3136
3147
|
"kind": "fragment",
|
|
3137
|
-
"section": "Product Configurator (per-product
|
|
3138
|
-
"description": "
|
|
3148
|
+
"section": "Product Configurator (per-product fields)",
|
|
3149
|
+
"description": "A configurator field on the product page - label, input type, who fills it (filledBy), pricing behaviour (pricingMode), validation bounds, required + visibility flags, and selectable options for choice-type fields.",
|
|
3139
3150
|
"variables": [],
|
|
3140
3151
|
"fragmentRefs": [
|
|
3141
|
-
"
|
|
3152
|
+
"ConfiguratorOption"
|
|
3142
3153
|
],
|
|
3143
|
-
"body": "fragment
|
|
3144
|
-
"onType": "
|
|
3154
|
+
"body": "fragment ConfiguratorField on ConfiguratorField {\n id\n name\n handle\n description\n type\n filledBy\n pricingMode\n required\n isVisible\n sortOrder\n minValue\n maxValue\n options {\n ...ConfiguratorOption\n }\n}",
|
|
3155
|
+
"onType": "ConfiguratorField"
|
|
3145
3156
|
}
|
|
3146
3157
|
]
|
|
3147
3158
|
}
|
package/package.json
CHANGED
package/queries.graphql
CHANGED
|
@@ -32,12 +32,12 @@ query Product($id: ID, $handle: String) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
# Fetches a product together with its
|
|
36
|
-
query ProductConfigurator($handle: String!, $
|
|
35
|
+
# Fetches a product together with its configurator fields, optimized for the product-page configurator UI. filledBy CUSTOMER returns only the fields a shopper edits; pass BOTH to also include seller-prefilled fields. Single round-trip.
|
|
36
|
+
query ProductConfigurator($handle: String!, $filledBy: AttributeFillingMode = CUSTOMER) {
|
|
37
37
|
product(handle: $handle) {
|
|
38
38
|
...ProductFull
|
|
39
|
-
|
|
40
|
-
...
|
|
39
|
+
configuratorFields(filter: { filledBy: $filledBy }) {
|
|
40
|
+
...ConfiguratorField
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
package/schema.graphql
CHANGED
|
@@ -44,7 +44,7 @@ type Attribute {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
"""
|
|
47
|
-
How
|
|
47
|
+
How an option surcharge is billed: BUNDLED (added into the product price — a single line) or SEPARATE_LINE (shown as its own order line, which may carry its own tax rate).
|
|
48
48
|
"""
|
|
49
49
|
enum AttributeBillingMode {
|
|
50
50
|
BUNDLED
|
|
@@ -89,7 +89,7 @@ type AttributeDefinition {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
"""
|
|
92
|
-
Who
|
|
92
|
+
Who provides the value: MERCHANT (set by the seller — product metadata, not shown as an editable field), CUSTOMER (entered or chosen by the shopper in the configurator), or BOTH (seller sets a default the shopper can change).
|
|
93
93
|
"""
|
|
94
94
|
enum AttributeFillingMode {
|
|
95
95
|
BOTH
|
|
@@ -2167,6 +2167,106 @@ enum CompensationType {
|
|
|
2167
2167
|
STORE_CREDIT
|
|
2168
2168
|
}
|
|
2169
2169
|
|
|
2170
|
+
"""
|
|
2171
|
+
A single field of a product configurator — an input the shopper sees on the product page.
|
|
2172
|
+
"""
|
|
2173
|
+
type ConfiguratorField {
|
|
2174
|
+
"""Optional help text shown beneath the field."""
|
|
2175
|
+
description: String
|
|
2176
|
+
|
|
2177
|
+
"""
|
|
2178
|
+
Who provides the value — CUSTOMER (the shopper fills it in) or BOTH (seller sets a default the shopper can change). Seller-only metadata fields are not returned here.
|
|
2179
|
+
"""
|
|
2180
|
+
filledBy: AttributeFillingMode!
|
|
2181
|
+
|
|
2182
|
+
"""URL-friendly key for the field."""
|
|
2183
|
+
handle: String!
|
|
2184
|
+
|
|
2185
|
+
"""Stable identifier of this field."""
|
|
2186
|
+
id: ID!
|
|
2187
|
+
|
|
2188
|
+
"""Whether this field should be shown on the storefront."""
|
|
2189
|
+
isVisible: Boolean!
|
|
2190
|
+
|
|
2191
|
+
"""Upper bound — maximum value (NUMBER) or maximum length (TEXT)."""
|
|
2192
|
+
maxValue: Float
|
|
2193
|
+
|
|
2194
|
+
"""Lower bound — minimum value (NUMBER) or minimum length (TEXT)."""
|
|
2195
|
+
minValue: Float
|
|
2196
|
+
|
|
2197
|
+
"""Field label shown to the shopper (e.g. "Finish")."""
|
|
2198
|
+
name: String!
|
|
2199
|
+
|
|
2200
|
+
"""
|
|
2201
|
+
Selectable choices for SELECT / RADIO / CHECKBOX fields; empty for free-input types (TEXT, NUMBER, …).
|
|
2202
|
+
"""
|
|
2203
|
+
options: [ConfiguratorOption!]!
|
|
2204
|
+
|
|
2205
|
+
"""
|
|
2206
|
+
If a choice adds cost, how it is billed — BUNDLED (folded into the product price) or SEPARATE_LINE (its own order line). Null when the field has no price impact.
|
|
2207
|
+
"""
|
|
2208
|
+
pricingMode: AttributeBillingMode
|
|
2209
|
+
|
|
2210
|
+
"""
|
|
2211
|
+
Whether the shopper must provide a value before adding the product to the cart.
|
|
2212
|
+
"""
|
|
2213
|
+
required: Boolean!
|
|
2214
|
+
|
|
2215
|
+
"""Order in which to render this field."""
|
|
2216
|
+
sortOrder: Int!
|
|
2217
|
+
|
|
2218
|
+
"""
|
|
2219
|
+
Input type — controls how to render the field (TEXT, TEXTAREA, SELECT, RADIO, CHECKBOX, NUMBER, COLOR, …).
|
|
2220
|
+
"""
|
|
2221
|
+
type: AttributeType!
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
"""Filter for the configuratorFields query."""
|
|
2225
|
+
input ConfiguratorFieldFilterInput {
|
|
2226
|
+
"""
|
|
2227
|
+
Return only fields with this filledBy value. The storefront configurator typically requests CUSTOMER + BOTH (the fields a shopper can edit).
|
|
2228
|
+
"""
|
|
2229
|
+
filledBy: AttributeFillingMode
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
"""
|
|
2233
|
+
A selectable choice within a product configurator field (e.g. a size, finish or add-on).
|
|
2234
|
+
"""
|
|
2235
|
+
type ConfiguratorOption {
|
|
2236
|
+
"""Hex colour for swatch rendering (COLOR fields)."""
|
|
2237
|
+
colorHex: String
|
|
2238
|
+
|
|
2239
|
+
"""Stable identifier of this choice."""
|
|
2240
|
+
id: ID!
|
|
2241
|
+
|
|
2242
|
+
"""Whether this choice is pre-selected by default."""
|
|
2243
|
+
isDefault: Boolean!
|
|
2244
|
+
|
|
2245
|
+
"""Human-readable label shown to the shopper."""
|
|
2246
|
+
label: String!
|
|
2247
|
+
|
|
2248
|
+
"""
|
|
2249
|
+
The stocked variant this choice maps to (used for inventory-backed components). Null when the choice maps to no variant or the variant no longer exists.
|
|
2250
|
+
"""
|
|
2251
|
+
linkedVariant: LinkedVariantSummary
|
|
2252
|
+
|
|
2253
|
+
"""Order in which to render this choice."""
|
|
2254
|
+
sortOrder: Int!
|
|
2255
|
+
|
|
2256
|
+
"""
|
|
2257
|
+
Extra charge applied when this choice is selected. With surchargeType FIXED it is an amount in minor currency units (e.g. 500 = 5.00). With PERCENT it is thousandths of a percent (e.g. 1500 = 1.5%).
|
|
2258
|
+
"""
|
|
2259
|
+
surchargeAmount: Int
|
|
2260
|
+
|
|
2261
|
+
"""How to interpret surchargeAmount — FIXED (a money amount) or PERCENT."""
|
|
2262
|
+
surchargeType: AttributeOptionSurchargeType
|
|
2263
|
+
|
|
2264
|
+
"""
|
|
2265
|
+
Machine value (slug-style) — use it for form state and when submitting the choice to the cart.
|
|
2266
|
+
"""
|
|
2267
|
+
value: String!
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2170
2270
|
"""Format of stored content (HTML or MARKDOWN)"""
|
|
2171
2271
|
enum ContentFormat {
|
|
2172
2272
|
HTML
|
|
@@ -3455,7 +3555,7 @@ enum LanguageDirection {
|
|
|
3455
3555
|
}
|
|
3456
3556
|
|
|
3457
3557
|
"""
|
|
3458
|
-
Summary of
|
|
3558
|
+
Summary of the stocked ProductVariant a configurator option maps to (component-style choice). Exposed via `ConfiguratorOption.linkedVariant`.
|
|
3459
3559
|
"""
|
|
3460
3560
|
type LinkedVariantSummary {
|
|
3461
3561
|
"""Available stock (stock − active reservations, always ≥ 0)."""
|
|
@@ -5273,18 +5373,15 @@ type PricingTier {
|
|
|
5273
5373
|
|
|
5274
5374
|
"""Product - main catalog item"""
|
|
5275
5375
|
type Product implements Node {
|
|
5276
|
-
"""Assigned AttributeSet ID (shared template fields)"""
|
|
5277
|
-
attributeSetId: ID
|
|
5278
|
-
|
|
5279
5376
|
"""
|
|
5280
|
-
|
|
5377
|
+
This product's stored custom-field values — merchant-managed metadata such as manufacturer, licence, material or EAN. Only fields the merchant marked visible are returned. Pass `namespace` to fetch a single group.
|
|
5281
5378
|
"""
|
|
5282
5379
|
attributes(
|
|
5283
5380
|
"""
|
|
5284
|
-
Optional filter —
|
|
5381
|
+
Optional group filter — return only attributes in this namespace (e.g. "specs").
|
|
5285
5382
|
"""
|
|
5286
|
-
|
|
5287
|
-
): [
|
|
5383
|
+
namespace: String
|
|
5384
|
+
): [EntityAttributeField!]!
|
|
5288
5385
|
|
|
5289
5386
|
"""Average rating (1-5)"""
|
|
5290
5387
|
averageRating: Float
|
|
@@ -5307,6 +5404,16 @@ type Product implements Node {
|
|
|
5307
5404
|
"""Opt-in: compare-at price range with conversion transparency."""
|
|
5308
5405
|
compareAtPriceRangeWithConversion: ConvertedPriceRange
|
|
5309
5406
|
|
|
5407
|
+
"""
|
|
5408
|
+
Configurable fields shown on the product page for the shopper to fill in or choose (combines shared template fields and product-specific ones). Pass `{ filledBy: CUSTOMER }` to return only the fields a shopper can edit.
|
|
5409
|
+
"""
|
|
5410
|
+
configuratorFields(
|
|
5411
|
+
"""
|
|
5412
|
+
Optional filter — pass `{ filledBy: CUSTOMER }` to return only the fields a shopper can edit.
|
|
5413
|
+
"""
|
|
5414
|
+
filter: ConfiguratorFieldFilterInput
|
|
5415
|
+
): [ConfiguratorField!]!
|
|
5416
|
+
|
|
5310
5417
|
"""Creation timestamp"""
|
|
5311
5418
|
createdAt: DateTime!
|
|
5312
5419
|
|
|
@@ -5433,103 +5540,6 @@ type Product implements Node {
|
|
|
5433
5540
|
visibility: ProductVisibility!
|
|
5434
5541
|
}
|
|
5435
5542
|
|
|
5436
|
-
"""Product attribute definition (configurator)"""
|
|
5437
|
-
type ProductAttributeDefinition {
|
|
5438
|
-
"""Billing mode — BUNDLED | SEPARATE_LINE; null = informational only"""
|
|
5439
|
-
billingMode: AttributeBillingMode
|
|
5440
|
-
|
|
5441
|
-
"""Customer-facing description"""
|
|
5442
|
-
description: String
|
|
5443
|
-
|
|
5444
|
-
"""Display order"""
|
|
5445
|
-
displayOrder: Int!
|
|
5446
|
-
|
|
5447
|
-
"""Filling mode — MERCHANT | CUSTOMER | BOTH"""
|
|
5448
|
-
fillingMode: AttributeFillingMode!
|
|
5449
|
-
|
|
5450
|
-
"""URL-friendly handle"""
|
|
5451
|
-
handle: String!
|
|
5452
|
-
|
|
5453
|
-
"""Definition ID"""
|
|
5454
|
-
id: ID!
|
|
5455
|
-
|
|
5456
|
-
"""Required validation flag"""
|
|
5457
|
-
isRequired: Boolean!
|
|
5458
|
-
|
|
5459
|
-
"""Visibility flag"""
|
|
5460
|
-
isVisible: Boolean!
|
|
5461
|
-
|
|
5462
|
-
"""Max value (NUMBER) / max length (TEXT)"""
|
|
5463
|
-
maxValue: Float
|
|
5464
|
-
|
|
5465
|
-
"""Min value (NUMBER) / min length (TEXT)"""
|
|
5466
|
-
minValue: Float
|
|
5467
|
-
|
|
5468
|
-
"""Field name (e.g. "Finiszer")"""
|
|
5469
|
-
name: String!
|
|
5470
|
-
|
|
5471
|
-
"""Options for SELECT/RADIO/CHECKBOX types"""
|
|
5472
|
-
options: [ProductAttributeOption!]!
|
|
5473
|
-
|
|
5474
|
-
"""
|
|
5475
|
-
Per-product scope — set to product ID for unique configurator fields, null for shared (in AttributeSet)
|
|
5476
|
-
"""
|
|
5477
|
-
scopeProductId: ID
|
|
5478
|
-
|
|
5479
|
-
"""Tax class ID; null = inherit from variant"""
|
|
5480
|
-
taxClassId: ID
|
|
5481
|
-
|
|
5482
|
-
"""Field type — TEXT/SELECT/RADIO/CHECKBOX/etc."""
|
|
5483
|
-
type: AttributeType!
|
|
5484
|
-
}
|
|
5485
|
-
|
|
5486
|
-
"""Filter for product attributes query"""
|
|
5487
|
-
input ProductAttributeFilterInput {
|
|
5488
|
-
"""
|
|
5489
|
-
Filter by filling mode — MERCHANT | CUSTOMER | BOTH (configurator UI uses CUSTOMER + BOTH)
|
|
5490
|
-
"""
|
|
5491
|
-
fillingMode: AttributeFillingMode
|
|
5492
|
-
}
|
|
5493
|
-
|
|
5494
|
-
"""Selectable option of a product attribute (configurator)"""
|
|
5495
|
-
type ProductAttributeOption {
|
|
5496
|
-
"""Hex color (for COLOR/SWATCH types)"""
|
|
5497
|
-
colorHex: String
|
|
5498
|
-
|
|
5499
|
-
"""Option ID"""
|
|
5500
|
-
id: ID!
|
|
5501
|
-
|
|
5502
|
-
"""Default option marker"""
|
|
5503
|
-
isDefault: Boolean!
|
|
5504
|
-
|
|
5505
|
-
"""Display label shown to customer"""
|
|
5506
|
-
label: String!
|
|
5507
|
-
|
|
5508
|
-
"""
|
|
5509
|
-
Summary of the linked ProductVariant. Null when the option has no linkedVariantId or the variant was deleted.
|
|
5510
|
-
"""
|
|
5511
|
-
linkedVariant: LinkedVariantSummary
|
|
5512
|
-
|
|
5513
|
-
"""
|
|
5514
|
-
Linked ProductVariant ID for component stock decrement (hidden-products pattern).
|
|
5515
|
-
"""
|
|
5516
|
-
linkedVariantId: ID
|
|
5517
|
-
|
|
5518
|
-
"""Sort order"""
|
|
5519
|
-
sortOrder: Int!
|
|
5520
|
-
|
|
5521
|
-
"""
|
|
5522
|
-
Surcharge amount when selected (FIXED = minor currency units; PERCENT = thousandths of percent).
|
|
5523
|
-
"""
|
|
5524
|
-
surchargeAmount: Int
|
|
5525
|
-
|
|
5526
|
-
"""Surcharge type — FIXED | PERCENT."""
|
|
5527
|
-
surchargeType: AttributeOptionSurchargeType
|
|
5528
|
-
|
|
5529
|
-
"""Internal value (slug-style)"""
|
|
5530
|
-
value: String!
|
|
5531
|
-
}
|
|
5532
|
-
|
|
5533
5543
|
"""Paginated product list"""
|
|
5534
5544
|
type ProductConnection {
|
|
5535
5545
|
"""Product edges with cursors"""
|