@doswiftly/storefront-operations 5.4.0 → 5.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,117 @@
1
+ # Changelog
2
+
3
+ ## 5.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9a715e2: `menu(handle:)` query now resolves `MenuItem.url` and `MenuItem.resource` server-side via a batched DataLoader (~1 SQL query per resource type, no N+1).
8
+
9
+ **What changed**
10
+ - `MenuItem.url` for `CATEGORY` / `COLLECTION` / `PAGE` / `PRODUCT` types is now computed from the linked resource's slug/handle and follows the convention `/categories/{slug}`, `/collections/{handle}`, `/pages/{handle}`, `/products/{slug}`. Previously this field returned `null` whenever the menu item only stored a `resourceId` (the common admin-created case), making the menu unusable for navigation rendering.
11
+ - `MenuItem.resource` is now populated with the actual `Category` / `Collection` / `ShopPage` / `Product` object. Previously it was always `null`. Resolution is batched per resource type — fetching a 50-item menu with mixed types triggers at most 4 service calls.
12
+ - `Menu.itemsCount` now returns the count of top-level items (equal to `items.length`), matching the Shopify Storefront API. Previously it returned a recursive count of all items across all nesting levels, which produced confusing mismatches with `items.length`.
13
+ - Static types (`HTTP` / `FRONTPAGE` / `SEARCH` / `CATALOG` / `BLOG`) and orphaned resource references are unchanged in shape but now have clearer field descriptions.
14
+
15
+ **Migration**
16
+
17
+ If you relied on `Menu.itemsCount` as a recursive total, switch to client-side counting:
18
+
19
+ ```ts
20
+ function countAllItems(items: MenuItem[]): number {
21
+ return items.reduce((acc, item) => acc + 1 + countAllItems(item.items), 0);
22
+ }
23
+ ```
24
+
25
+ If you previously worked around the missing `url` / `resource` by fetching each linked resource individually after reading the menu, you can now drop that code path.
26
+
27
+ ## 5.4.1
28
+
29
+ ### Patch Changes
30
+
31
+ - 7846bdb: Fix `doswiftly dev` port pre-flight on Windows (and any host where another
32
+ process binds the port on IPv6 `::` only): the probe now checks IPv4 and
33
+ IPv6 in parallel and requires BOTH free before marking a port as available.
34
+ Previously an IPv6-only conflict (common on Windows, where Next.js binds
35
+ `::` by default) slipped past the IPv4-only probe — the banner advertised
36
+ `http://localhost:3000` and the framework immediately crashed with
37
+ `EADDRINUSE :::3000`. With this fix `doswiftly dev` falls back to the next
38
+ free port (3001, 3002, …) as documented.
39
+
40
+ Also ship `CHANGELOG.md` inside the npm tarball. Previous releases packed
41
+ only `dist`/`bin`/`templates` (and `schema.graphql`/operations for
42
+ `storefront-operations`, `dist` for `storefront-sdk`), so consumers who
43
+ `npm install @doswiftly/cli` got a version number with no user-visible
44
+ release notes.
45
+
46
+ ## 5.4.0
47
+
48
+ ### Minor Changes
49
+
50
+ - 770fcd3: Added `Product.purchasable: Boolean!` to the storefront schema. The field mirrors `visibility === 'PUBLIC'` server-side and lets templates hide the "Add to cart" / "Buy now" path for component products that are only reachable through a parent product's configurator.
51
+
52
+ Templates can render a non-purchasable banner on the PDP instead of exposing a purchase action that the server will reject. Requesting the field is additive — operations that omit it keep working.
53
+
54
+ All notable changes to @doswiftly/storefront-operations will be documented in this file.
55
+
56
+ ## [5.0.0] - 2026-04-12
57
+
58
+ ### Breaking
59
+
60
+ - Removed `type InventoryLevel`, `fragment InventoryLevel`, `fragment VariantInventoryLevels`, and `query ProductInventory`.
61
+ - Removed `ProductVariant.inventoryLevels(locationType)` field — replaced by `ProductVariant.storeAvailability`.
62
+
63
+ ### Added
64
+
65
+ - Shopify-parity `StoreAvailability` surface on `ProductVariant`:
66
+ - `type StoreAvailability { available, quantityAvailable (token-gated), pickUpTime, location }`
67
+ - `type Location`, `LocationAddress`, `BusinessHours`, `BusinessHoursWindow` — full pickup-aware payload.
68
+ - `type StoreAvailabilityConnection` + `StoreAvailabilityEdge` — cursor-paginated, supports `near`, `locationType`, `@inContext(preferredLocationId)`.
69
+ - Root-level queries: `locations(first, after, near, hasPickupEnabled, locationType)` and `location(id)`.
70
+ - `directive @inContext(preferredLocationId: ID) on QUERY | MUTATION | SUBSCRIPTION` — Shopify operation directive for contextual hints (country / language / buyer to follow).
71
+ - Fragments: `StoreAvailability`, `StoreAvailabilityConnection`, `Location`, `LocationAddress`, `BusinessHours`, `BusinessHoursWindow`, `VariantStoreAvailability`.
72
+ - Queries: `ProductStoreAvailability`, `Locations`, `Location`.
73
+
74
+ ### Migration
75
+
76
+ Replace:
77
+
78
+ ```graphql
79
+ query ProductInventory($handle: String) {
80
+ product(handle: $handle) {
81
+ variants {
82
+ ...VariantInventoryLevels
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ with:
89
+
90
+ ```graphql
91
+ query ProductStoreAvailability($handle: String) {
92
+ product(handle: $handle) {
93
+ variants {
94
+ ...VariantStoreAvailability
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ `quantityAvailable` is now token-gated (null for anonymous, Int when `x-customer-access-token` is sent) — matches Shopify Storefront API.
101
+
102
+ ## [1.0.0] - 2025-12-09
103
+
104
+ ### Added
105
+
106
+ - Initial release of @doswiftly/storefront-operations package
107
+ - GraphQL operations synced from backend SSOT
108
+ - Queries: Shop, Product, Products, ProductSearch, Collection, Collections, Category, Categories, Cart, Customer
109
+ - Mutations: Cart operations, Customer auth, Profile management, Address management, Password recovery
110
+ - Fragments: All reusable fragments for products, collections, cart, customer, etc.
111
+ - Sync script to copy operations from backend
112
+ - Package exports for .graphql files
113
+ - README with usage instructions
114
+
115
+ ### Purpose
116
+
117
+ Enable direct GraphQL codegen approach for Next.js storefronts while maintaining Single Source of Truth from backend.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-operations",
3
- "version": "5.4.0",
3
+ "version": "5.5.0",
4
4
  "description": "GraphQL operations for DoSwiftly Storefront - SSOT from backend",
5
5
  "homepage": "https://doswiftly.pl",
6
6
  "publishConfig": {
@@ -28,7 +28,8 @@
28
28
  "queries.graphql",
29
29
  "mutations.graphql",
30
30
  "fragments.graphql",
31
- "README.md"
31
+ "README.md",
32
+ "CHANGELOG.md"
32
33
  ],
33
34
  "scripts": {
34
35
  "sync": "node scripts/sync-operations.js",
package/schema.graphql CHANGED
@@ -2662,7 +2662,7 @@ type Menu {
2662
2662
  """Top-level menu items"""
2663
2663
  items: [MenuItem!]!
2664
2664
 
2665
- """Total count of items across all levels"""
2665
+ """The count of top-level items on the menu (equal to items.length)"""
2666
2666
  itemsCount: Int!
2667
2667
 
2668
2668
  """Menu title"""
@@ -2680,7 +2680,9 @@ type MenuItem {
2680
2680
  """Child menu items (max 3 levels)"""
2681
2681
  items: [MenuItem!]!
2682
2682
 
2683
- """Linked resource object (lazy, via DataLoader)"""
2683
+ """
2684
+ Linked resource object resolved server-side via DataLoader (batched per resource type — no N+1). Null when type is HTTP/FRONTPAGE/SEARCH/CATALOG/BLOG, or when resourceId points to a deleted resource.
2685
+ """
2684
2686
  resource: MenuItemResource
2685
2687
 
2686
2688
  """Linked resource ID"""
@@ -2692,7 +2694,9 @@ type MenuItem {
2692
2694
  """Link type"""
2693
2695
  type: MenuItemType!
2694
2696
 
2695
- """Resolved URL (always computed server-side)"""
2697
+ """
2698
+ Resolved URL path computed server-side (e.g., /categories/funko, /products/toy-1, /pages/about, /collections/sale). Static types resolve to /, /search, /products, /blog. HTTP type returns the manually stored URL. Null only when type is a resource link (CATEGORY/COLLECTION/PAGE/PRODUCT) and the resource was deleted.
2699
+ """
2696
2700
  url: String
2697
2701
  }
2698
2702