@doswiftly/storefront-operations 13.1.0 → 15.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/operations.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "schemaVersion": "13.1.0",
2
+ "schemaVersion": "15.1.0",
3
3
  "queries": [
4
4
  {
5
5
  "name": "Shop",
@@ -16,7 +16,7 @@
16
16
  "name": "Product",
17
17
  "kind": "query",
18
18
  "section": "Products",
19
- "description": "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).",
19
+ "description": "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).",
20
20
  "variables": [
21
21
  {
22
22
  "name": "id",
@@ -236,7 +236,7 @@
236
236
  "name": "Category",
237
237
  "kind": "query",
238
238
  "section": "Categories",
239
- "description": "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.",
239
+ "description": "Fetches a single category by `id` or `handle` 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.",
240
240
  "variables": [
241
241
  {
242
242
  "name": "id",
@@ -244,7 +244,7 @@
244
244
  "defaultValue": null
245
245
  },
246
246
  {
247
- "name": "slug",
247
+ "name": "handle",
248
248
  "type": "String",
249
249
  "defaultValue": null
250
250
  }
@@ -252,7 +252,7 @@
252
252
  "fragmentRefs": [
253
253
  "Category"
254
254
  ],
255
- "body": "query Category($id: ID, $slug: String) {\n category(id: $id, slug: $slug) {\n ...Category\n parent {\n ...Category\n }\n children {\n ...Category\n }\n }\n}"
255
+ "body": "query Category($id: ID, $handle: String) {\n category(id: $id, handle: $handle) {\n ...Category\n parent {\n ...Category\n }\n children {\n ...Category\n }\n }\n}"
256
256
  },
257
257
  {
258
258
  "name": "Categories",
@@ -307,6 +307,18 @@
307
307
  ],
308
308
  "body": "query CustomerProfile {\n customer {\n ...Customer\n }\n}"
309
309
  },
310
+ {
311
+ "name": "CustomerAddresses",
312
+ "kind": "query",
313
+ "section": "Customer (requires auth)",
314
+ "description": "Authenticated customer's saved address book — used on checkout to let the buyer pick a previously-used shipping / billing address instead of typing it. Each entry carries B2B invoicing fields (`taxId`, `vatNumber`) and the `isDefault` flag so the same list serves both as the shipping picker and as the billing/invoice picker. Returns up to 50 addresses (Relay Connection — buyers rarely keep more); for the unauthenticated case the connection is empty (no error). The default address is also surfaced as `Customer.defaultAddress`.",
315
+ "variables": [],
316
+ "fragmentRefs": [
317
+ "MailingAddress",
318
+ "PageInfo"
319
+ ],
320
+ "body": "query CustomerAddresses {\n customer {\n addresses(first: 50) {\n nodes {\n ...MailingAddress\n }\n pageInfo {\n ...PageInfo\n }\n totalCount\n }\n }\n}"
321
+ },
310
322
  {
311
323
  "name": "CustomerOrder",
312
324
  "kind": "query",
@@ -758,7 +770,7 @@
758
770
  "name": "BlogPosts",
759
771
  "kind": "query",
760
772
  "section": "Blog",
761
- "description": "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.",
773
+ "description": "Paginated list of published blog posts. Filter by `categoryHandle`, `tagHandle`, or `featured` (boolean flag, not enum). Sort: `PUBLISHED_AT` (default), `TITLE`, `VIEW_COUNT`, or `CREATED_AT`. Public; no auth required.",
762
774
  "variables": [
763
775
  {
764
776
  "name": "first",
@@ -771,12 +783,12 @@
771
783
  "defaultValue": null
772
784
  },
773
785
  {
774
- "name": "categorySlug",
786
+ "name": "categoryHandle",
775
787
  "type": "String",
776
788
  "defaultValue": null
777
789
  },
778
790
  {
779
- "name": "tagSlug",
791
+ "name": "tagHandle",
780
792
  "type": "String",
781
793
  "defaultValue": null
782
794
  },
@@ -800,13 +812,13 @@
800
812
  "BlogPost",
801
813
  "PageInfo"
802
814
  ],
803
- "body": "query BlogPosts($first: Int = 20, $after: String, $categorySlug: String, $tagSlug: String, $featured: Boolean, $sortKey: BlogPostSortKey = PUBLISHED_AT, $reverse: Boolean = false) {\n blogPosts(\n first: $first\n after: $after\n categorySlug: $categorySlug\n tagSlug: $tagSlug\n featured: $featured\n sortKey: $sortKey\n reverse: $reverse\n ) {\n edges {\n node {\n ...BlogPost\n }\n cursor\n }\n pageInfo {\n ...PageInfo\n }\n totalCount\n }\n}"
815
+ "body": "query BlogPosts($first: Int = 20, $after: String, $categoryHandle: String, $tagHandle: String, $featured: Boolean, $sortKey: BlogPostSortKey = PUBLISHED_AT, $reverse: Boolean = false) {\n blogPosts(\n first: $first\n after: $after\n categoryHandle: $categoryHandle\n tagHandle: $tagHandle\n featured: $featured\n sortKey: $sortKey\n reverse: $reverse\n ) {\n edges {\n node {\n ...BlogPost\n }\n cursor\n }\n pageInfo {\n ...PageInfo\n }\n totalCount\n }\n}"
804
816
  },
805
817
  {
806
818
  "name": "BlogPost",
807
819
  "kind": "query",
808
820
  "section": "Blog",
809
- "description": "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).",
821
+ "description": "Fetches a single blog post by `id` or `handle`. 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).",
810
822
  "variables": [
811
823
  {
812
824
  "name": "id",
@@ -814,7 +826,7 @@
814
826
  "defaultValue": null
815
827
  },
816
828
  {
817
- "name": "slug",
829
+ "name": "handle",
818
830
  "type": "String",
819
831
  "defaultValue": null
820
832
  }
@@ -822,7 +834,7 @@
822
834
  "fragmentRefs": [
823
835
  "BlogPost"
824
836
  ],
825
- "body": "query BlogPost($id: ID, $slug: String) {\n blogPost(id: $id, slug: $slug) {\n ...BlogPost\n }\n}"
837
+ "body": "query BlogPost($id: ID, $handle: String) {\n blogPost(id: $id, handle: $handle) {\n ...BlogPost\n }\n}"
826
838
  },
827
839
  {
828
840
  "name": "BlogCategories",
@@ -937,7 +949,7 @@
937
949
  "name": "Menu",
938
950
  "kind": "query",
939
951
  "section": "Content: Navigation Menus",
940
- "description": "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.",
952
+ "description": "Fetches a navigation menu by `handle` (e.g. `\"main-menu\"`, `\"footer\"`, `\"mobile\"`). Returns the nested item tree (up to 3 levels). Each item is typed as one of: `HTTP`, `FRONTPAGE`, `SEARCH`, `CATALOG`, `BLOG`, `PRODUCT`, `COLLECTION`, `CATEGORY`, `PAGE`, or `BRAND` — switch on the type to render the right link target. Each resource-linked item exposes both a pre-resolved `url` (standard `/categories|/collections|/pages|/products|/brands/<handle>` convention) and a typed `resource` union with the raw handle so storefronts with custom routing can construct their own paths instead. All resource lookups are batched per request — no N+1 even for deep menus.",
941
953
  "variables": [
942
954
  {
943
955
  "name": "handle",
@@ -1944,7 +1956,7 @@
1944
1956
  "ImageCard",
1945
1957
  "Money"
1946
1958
  ],
1947
- "body": "fragment ProductCard on Product {\n id\n handle\n title\n vendor\n categories {\n id\n slug\n name\n }\n isAvailable\n averageRating\n reviewCount\n tags\n featuredImage {\n ...ImageCard\n }\n priceRange {\n minVariantPrice {\n ...Money\n }\n maxVariantPrice {\n ...Money\n }\n }\n compareAtPriceRange {\n minVariantPrice {\n ...Money\n }\n maxVariantPrice {\n ...Money\n }\n }\n}",
1959
+ "body": "fragment ProductCard on Product {\n id\n handle\n title\n vendor\n categories {\n id\n handle\n name\n }\n isAvailable\n averageRating\n reviewCount\n tags\n featuredImage {\n ...ImageCard\n }\n priceRange {\n minVariantPrice {\n ...Money\n }\n maxVariantPrice {\n ...Money\n }\n }\n compareAtPriceRange {\n minVariantPrice {\n ...Money\n }\n maxVariantPrice {\n ...Money\n }\n }\n}",
1948
1960
  "onType": "Product"
1949
1961
  },
1950
1962
  {
@@ -1990,22 +2002,34 @@
1990
2002
  "name": "Category",
1991
2003
  "kind": "fragment",
1992
2004
  "section": "Categories",
1993
- "description": "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.",
2005
+ "description": "Category node in the shop's taxonomy — name, handle, 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.",
1994
2006
  "variables": [],
1995
2007
  "fragmentRefs": [
1996
2008
  "ImageCard"
1997
2009
  ],
1998
- "body": "fragment Category on Category {\n id\n name\n slug\n description\n image {\n ...ImageCard\n }\n level\n path\n productCount\n sortOrder\n}",
2010
+ "body": "fragment Category on Category {\n id\n name\n handle\n description\n image {\n ...ImageCard\n }\n level\n path\n productCount\n sortOrder\n}",
1999
2011
  "onType": "Category"
2000
2012
  },
2001
2013
  {
2002
- "name": "MailingAddress",
2014
+ "name": "PickupPoint",
2003
2015
  "kind": "fragment",
2004
2016
  "section": "Customer",
2005
- "description": "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.",
2017
+ "description": "Selected pickup point (parcel locker or collection point) attached to a delivery address. Returned on `MailingAddress.pickupPoint` when the buyer chose a non-home delivery method (`deliveryType` other than `HOME`). Null for home delivery.",
2006
2018
  "variables": [],
2007
2019
  "fragmentRefs": [],
2008
- "body": "fragment MailingAddress on MailingAddress {\n id\n streetLine1\n streetLine2\n city\n company\n country\n countryCode\n firstName\n lastName\n name\n phone\n state\n stateCode\n postalCode\n isDefault\n}",
2020
+ "body": "fragment PickupPoint on PickupPoint {\n provider\n pointId\n name\n address\n}",
2021
+ "onType": "PickupPoint"
2022
+ },
2023
+ {
2024
+ "name": "MailingAddress",
2025
+ "kind": "fragment",
2026
+ "section": "Customer",
2027
+ "description": "Customer mailing address — full street/city/state/country/postal code with names and phone. `isDefault` flips when this address is the default for shipping. Carries B2B invoicing fields (`taxId`, `vatNumber`) and the selected `pickupPoint` for parcel locker / collection point deliveries. Spread on the address book UI, checkout shipping/billing forms, and order summaries.",
2028
+ "variables": [],
2029
+ "fragmentRefs": [
2030
+ "PickupPoint"
2031
+ ],
2032
+ "body": "fragment MailingAddress on MailingAddress {\n id\n streetLine1\n streetLine2\n city\n company\n country\n countryCode\n firstName\n lastName\n name\n phone\n state\n stateCode\n postalCode\n isDefault\n taxId\n vatNumber\n pickupPoint {\n ...PickupPoint\n }\n}",
2009
2033
  "onType": "MailingAddress"
2010
2034
  },
2011
2035
  {
@@ -2161,12 +2185,12 @@
2161
2185
  "name": "CartAppliedGiftCard",
2162
2186
  "kind": "fragment",
2163
2187
  "section": "Cart",
2164
- "description": "Gift card applied to a cart — masked code for display, last 4 chars for matching, applied amount + remaining balance. Balance NIE debited yet — actual deduction atomically at `cartComplete`.",
2188
+ "description": "Gift card applied to a cart — `id` is the stable handle the storefront passes to `cartRemoveGiftCard` (no need to keep the raw code around). Plus masked code for display, last 4 chars for matching, applied amount + remaining balance. Balance NIE debited yet — actual deduction atomically at `cartComplete`.",
2165
2189
  "variables": [],
2166
2190
  "fragmentRefs": [
2167
2191
  "Money"
2168
2192
  ],
2169
- "body": "fragment CartAppliedGiftCard on CartAppliedGiftCard {\n maskedCode\n lastCharacters\n appliedAmount {\n ...Money\n }\n remainingBalance {\n ...Money\n }\n}",
2193
+ "body": "fragment CartAppliedGiftCard on CartAppliedGiftCard {\n id\n maskedCode\n lastCharacters\n appliedAmount {\n ...Money\n }\n remainingBalance {\n ...Money\n }\n}",
2170
2194
  "onType": "CartAppliedGiftCard"
2171
2195
  },
2172
2196
  {
@@ -2498,7 +2522,7 @@
2498
2522
  "name": "AvailableShippingMethod",
2499
2523
  "kind": "fragment",
2500
2524
  "section": "Shipping Methods",
2501
- "description": "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.",
2525
+ "description": "One shipping method offered for the destination + cart — id, name, carrier, price, free-shipping progress, estimated delivery, sort order. `deliveryType` signals whether to render a pickup-point / locker picker (`HOME` vs `PICKUP_POINT` / `LOCKER`) so the storefront does not have to infer it from the method name. Spread on the checkout shipping step.",
2502
2526
  "variables": [],
2503
2527
  "fragmentRefs": [
2504
2528
  "DeliveryEstimate",
@@ -2506,7 +2530,7 @@
2506
2530
  "Money",
2507
2531
  "ShippingCarrier"
2508
2532
  ],
2509
- "body": "fragment AvailableShippingMethod on AvailableShippingMethod {\n id\n name\n description\n carrier {\n ...ShippingCarrier\n }\n price {\n ...Money\n }\n isFree\n estimatedDelivery {\n ...DeliveryEstimate\n }\n freeShippingProgress {\n ...FreeShippingProgress\n }\n sortOrder\n}",
2533
+ "body": "fragment AvailableShippingMethod on AvailableShippingMethod {\n id\n name\n description\n deliveryType\n carrier {\n ...ShippingCarrier\n }\n price {\n ...Money\n }\n isFree\n estimatedDelivery {\n ...DeliveryEstimate\n }\n freeShippingProgress {\n ...FreeShippingProgress\n }\n sortOrder\n}",
2510
2534
  "onType": "AvailableShippingMethod"
2511
2535
  },
2512
2536
  {
@@ -2571,10 +2595,10 @@
2571
2595
  "name": "CategoryFilterOption",
2572
2596
  "kind": "fragment",
2573
2597
  "section": "Attribute Filters",
2574
- "description": "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.",
2598
+ "description": "One category option in the categories filter — id, name, handle, count of products in this category within the current listing context, level + parentId for tree rendering.",
2575
2599
  "variables": [],
2576
2600
  "fragmentRefs": [],
2577
- "body": "fragment CategoryFilterOption on CategoryFilterOption {\n id\n name\n slug\n productCount\n level\n parentId\n}",
2601
+ "body": "fragment CategoryFilterOption on CategoryFilterOption {\n id\n name\n handle\n productCount\n level\n parentId\n}",
2578
2602
  "onType": "CategoryFilterOption"
2579
2603
  },
2580
2604
  {
@@ -2672,7 +2696,7 @@
2672
2696
  "LoyaltyTier",
2673
2697
  "Money"
2674
2698
  ],
2675
- "body": "fragment LoyaltyReward on LoyaltyReward {\n id\n name\n slug\n type\n pointsCost\n discountPercent\n discountAmount {\n ...Money\n }\n description\n image {\n ...ImageCard\n }\n isAvailable\n tierRequired {\n ...LoyaltyTier\n }\n redemptionsRemaining\n}",
2699
+ "body": "fragment LoyaltyReward on LoyaltyReward {\n id\n name\n handle\n type\n pointsCost\n discountPercent\n discountAmount {\n ...Money\n }\n description\n image {\n ...ImageCard\n }\n isAvailable\n tierRequired {\n ...LoyaltyTier\n }\n redemptionsRemaining\n}",
2676
2700
  "onType": "LoyaltyReward"
2677
2701
  },
2678
2702
  {
@@ -2790,27 +2814,27 @@
2790
2814
  "name": "BlogCategory",
2791
2815
  "kind": "fragment",
2792
2816
  "section": "Blog",
2793
- "description": "Blog category — name, slug, description, post count. Spread on category navigation and post category labels.",
2817
+ "description": "Blog category — name, handle, description, post count. Spread on category navigation and post category labels.",
2794
2818
  "variables": [],
2795
2819
  "fragmentRefs": [],
2796
- "body": "fragment BlogCategory on BlogCategory {\n id\n name\n slug\n description\n postCount\n}",
2820
+ "body": "fragment BlogCategory on BlogCategory {\n id\n name\n handle\n description\n postCount\n}",
2797
2821
  "onType": "BlogCategory"
2798
2822
  },
2799
2823
  {
2800
2824
  "name": "BlogTag",
2801
2825
  "kind": "fragment",
2802
2826
  "section": "Blog",
2803
- "description": "Blog tag — name, slug, post count. Spread on tag clouds and post tag labels.",
2827
+ "description": "Blog tag — name, handle, post count. Spread on tag clouds and post tag labels.",
2804
2828
  "variables": [],
2805
2829
  "fragmentRefs": [],
2806
- "body": "fragment BlogTag on BlogTag {\n id\n name\n slug\n postCount\n}",
2830
+ "body": "fragment BlogTag on BlogTag {\n id\n name\n handle\n postCount\n}",
2807
2831
  "onType": "BlogTag"
2808
2832
  },
2809
2833
  {
2810
2834
  "name": "BlogPost",
2811
2835
  "kind": "fragment",
2812
2836
  "section": "Blog",
2813
- "description": "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.",
2837
+ "description": "Full blog post — title, handle, 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.",
2814
2838
  "variables": [],
2815
2839
  "fragmentRefs": [
2816
2840
  "BlogCategory",
@@ -2818,7 +2842,7 @@
2818
2842
  "ImageCard",
2819
2843
  "ImageThumbnail"
2820
2844
  ],
2821
- "body": "fragment BlogPost on BlogPost {\n id\n title\n slug\n excerpt\n content\n contentFormat\n featuredImage {\n ...ImageCard\n }\n author {\n id\n name\n bio\n avatar {\n ...ImageThumbnail\n }\n }\n category {\n ...BlogCategory\n }\n tags {\n ...BlogTag\n }\n publishedAt\n readingTimeMinutes\n viewCount\n commentCount\n allowComments\n isFeatured\n status\n seo {\n title\n description\n }\n createdAt\n updatedAt\n}",
2845
+ "body": "fragment BlogPost on BlogPost {\n id\n title\n handle\n excerpt\n content\n contentFormat\n featuredImage {\n ...ImageCard\n }\n author {\n id\n name\n bio\n avatar {\n ...ImageThumbnail\n }\n }\n category {\n ...BlogCategory\n }\n tags {\n ...BlogTag\n }\n publishedAt\n readingTimeMinutes\n viewCount\n commentCount\n allowComments\n isFeatured\n status\n seo {\n title\n description\n }\n createdAt\n updatedAt\n}",
2822
2846
  "onType": "BlogPost"
2823
2847
  },
2824
2848
  {
@@ -2907,7 +2931,7 @@
2907
2931
  "name": "ShopPage",
2908
2932
  "kind": "fragment",
2909
2933
  "section": "Pages",
2910
- "description": "CMS page — handle (URL slug), title, body (HTML), excerpt, SEO metadata, publish date. Spread on About / Privacy / Terms / Returns Policy pages.",
2934
+ "description": "CMS page — handle (URL-friendly identifier), title, body (HTML), excerpt, SEO metadata, publish date. Spread on About / Privacy / Terms / Returns Policy pages.",
2911
2935
  "variables": [],
2912
2936
  "fragmentRefs": [],
2913
2937
  "body": "fragment ShopPage on ShopPage {\n id\n handle\n title\n body\n excerpt\n seo {\n title\n description\n }\n publishedAt\n createdAt\n updatedAt\n}",
@@ -2917,12 +2941,12 @@
2917
2941
  "name": "MenuItem",
2918
2942
  "kind": "fragment",
2919
2943
  "section": "Navigation Menus",
2920
- "description": "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.",
2944
+ "description": "One menu item with up to 3 levels of nested children — title, URL, type (`HTTP` / `FRONTPAGE` / `SEARCH` / `CATALOG` / `BLOG` / `PRODUCT` / `COLLECTION` / `CATEGORY` / `PAGE` / `BRAND`), `resourceId` for typed items, optional image, and a typed `resource` union (Category / Collection / ShopPage / Product / Brand) carrying the linked resource's handle. Two ways to render the link target: (1) use the pre-resolved `url` if your storefront follows the standard `/categories|/collections|/pages|/products|/brands/<handle>` route convention; (2) read `resource.__typename` + the per-type `handle` and build your own paths if your storefront uses different routing. Switch on `type` to decide which static (FRONTPAGE/SEARCH/CATALOG/BLOG) or dynamic target to render.",
2921
2945
  "variables": [],
2922
2946
  "fragmentRefs": [
2923
2947
  "Image"
2924
2948
  ],
2925
- "body": "fragment MenuItem on MenuItem {\n id\n title\n url\n type\n resourceId\n image {\n ...Image\n }\n items {\n id\n title\n url\n type\n resourceId\n items {\n id\n title\n url\n type\n resourceId\n }\n }\n}",
2949
+ "body": "fragment MenuItem on MenuItem {\n id\n title\n url\n type\n resourceId\n resource {\n __typename\n ... on Category {\n id\n handle\n name\n }\n ... on Collection {\n id\n handle\n title\n }\n ... on ShopPage {\n id\n handle\n title\n }\n ... on Product {\n id\n handle\n title\n }\n ... on Brand {\n id\n handle\n name\n logo\n }\n }\n image {\n ...Image\n }\n items {\n id\n title\n url\n type\n resourceId\n resource {\n __typename\n ... on Category {\n id\n handle\n name\n }\n ... on Collection {\n id\n handle\n title\n }\n ... on ShopPage {\n id\n handle\n title\n }\n ... on Product {\n id\n handle\n title\n }\n ... on Brand {\n id\n handle\n name\n logo\n }\n }\n items {\n id\n title\n url\n type\n resourceId\n resource {\n __typename\n ... on Category {\n id\n handle\n name\n }\n ... on Collection {\n id\n handle\n title\n }\n ... on ShopPage {\n id\n handle\n title\n }\n ... on Product {\n id\n handle\n title\n }\n ... on Brand {\n id\n handle\n name\n logo\n }\n }\n }\n }\n}",
2926
2950
  "onType": "MenuItem"
2927
2951
  },
2928
2952
  {
@@ -2978,7 +3002,7 @@
2978
3002
  "fragmentRefs": [
2979
3003
  "ProductAttributeOption"
2980
3004
  ],
2981
- "body": "fragment ProductAttributeDefinition on ProductAttributeDefinition {\n id\n name\n slug\n description\n type\n fillingMode\n billingMode\n taxClassId\n scopeProductId\n isRequired\n isVisible\n displayOrder\n minValue\n maxValue\n options {\n ...ProductAttributeOption\n }\n}",
3005
+ "body": "fragment ProductAttributeDefinition on ProductAttributeDefinition {\n id\n name\n handle\n description\n type\n fillingMode\n billingMode\n taxClassId\n scopeProductId\n isRequired\n isVisible\n displayOrder\n minValue\n maxValue\n options {\n ...ProductAttributeOption\n }\n}",
2982
3006
  "onType": "ProductAttributeDefinition"
2983
3007
  }
2984
3008
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-operations",
3
- "version": "13.1.0",
3
+ "version": "15.1.0",
4
4
  "description": "GraphQL operations for DoSwiftly Storefront - SSOT from backend",
5
5
  "homepage": "https://doswiftly.pl",
6
6
  "publishConfig": {
package/queries.graphql CHANGED
@@ -18,7 +18,7 @@ query Shop {
18
18
  # Products
19
19
  # ============================================
20
20
 
21
- # 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).
21
+ # 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).
22
22
  query Product($id: ID, $handle: String) {
23
23
  product(id: $id, handle: $handle) {
24
24
  ...ProductFull
@@ -139,9 +139,9 @@ query Collections($first: Int = 20, $after: String, $query: String, $sortKey: Co
139
139
  # Categories
140
140
  # ============================================
141
141
 
142
- # 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.
143
- query Category($id: ID, $slug: String) {
144
- category(id: $id, slug: $slug) {
142
+ # Fetches a single category by `id` or `handle` 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.
143
+ query Category($id: ID, $handle: String) {
144
+ category(id: $id, handle: $handle) {
145
145
  ...Category
146
146
  parent {
147
147
  ...Category
@@ -224,6 +224,21 @@ query CustomerProfile {
224
224
  }
225
225
  }
226
226
 
227
+ # Authenticated customer's saved address book — used on checkout to let the buyer pick a previously-used shipping / billing address instead of typing it. Each entry carries B2B invoicing fields (`taxId`, `vatNumber`) and the `isDefault` flag so the same list serves both as the shipping picker and as the billing/invoice picker. Returns up to 50 addresses (Relay Connection — buyers rarely keep more); for the unauthenticated case the connection is empty (no error). The default address is also surfaced as `Customer.defaultAddress`.
228
+ query CustomerAddresses {
229
+ customer {
230
+ addresses(first: 50) {
231
+ nodes {
232
+ ...MailingAddress
233
+ }
234
+ pageInfo {
235
+ ...PageInfo
236
+ }
237
+ totalCount
238
+ }
239
+ }
240
+ }
241
+
227
242
  # 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.
228
243
  query CustomerOrder($orderId: ID!) {
229
244
  customerOrder(orderId: $orderId) {
@@ -539,9 +554,9 @@ query WishlistById($id: ID!) {
539
554
  # Blog
540
555
  # ============================================
541
556
 
542
- # 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.
543
- query BlogPosts($first: Int = 20, $after: String, $categorySlug: String, $tagSlug: String, $featured: Boolean, $sortKey: BlogPostSortKey = PUBLISHED_AT, $reverse: Boolean = false) {
544
- blogPosts(first: $first, after: $after, categorySlug: $categorySlug, tagSlug: $tagSlug, featured: $featured, sortKey: $sortKey, reverse: $reverse) {
557
+ # Paginated list of published blog posts. Filter by `categoryHandle`, `tagHandle`, or `featured` (boolean flag, not enum). Sort: `PUBLISHED_AT` (default), `TITLE`, `VIEW_COUNT`, or `CREATED_AT`. Public; no auth required.
558
+ query BlogPosts($first: Int = 20, $after: String, $categoryHandle: String, $tagHandle: String, $featured: Boolean, $sortKey: BlogPostSortKey = PUBLISHED_AT, $reverse: Boolean = false) {
559
+ blogPosts(first: $first, after: $after, categoryHandle: $categoryHandle, tagHandle: $tagHandle, featured: $featured, sortKey: $sortKey, reverse: $reverse) {
545
560
  edges {
546
561
  node {
547
562
  ...BlogPost
@@ -555,9 +570,9 @@ query BlogPosts($first: Int = 20, $after: String, $categorySlug: String, $tagSlu
555
570
  }
556
571
  }
557
572
 
558
- # 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).
559
- query BlogPost($id: ID, $slug: String) {
560
- blogPost(id: $id, slug: $slug) {
573
+ # Fetches a single blog post by `id` or `handle`. 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).
574
+ query BlogPost($id: ID, $handle: String) {
575
+ blogPost(id: $id, handle: $handle) {
561
576
  ...BlogPost
562
577
  }
563
578
  }
@@ -618,7 +633,7 @@ query Pages($first: Int = 20, $after: String, $sortKey: PageSortKeys = TITLE, $r
618
633
  # Content: Navigation Menus
619
634
  # ============================================
620
635
 
621
- # 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.
636
+ # Fetches a navigation menu by `handle` (e.g. `"main-menu"`, `"footer"`, `"mobile"`). Returns the nested item tree (up to 3 levels). Each item is typed as one of: `HTTP`, `FRONTPAGE`, `SEARCH`, `CATALOG`, `BLOG`, `PRODUCT`, `COLLECTION`, `CATEGORY`, `PAGE`, or `BRAND` — switch on the type to render the right link target. Each resource-linked item exposes both a pre-resolved `url` (standard `/categories|/collections|/pages|/products|/brands/<handle>` convention) and a typed `resource` union with the raw handle so storefronts with custom routing can construct their own paths instead. All resource lookups are batched per request — no N+1 even for deep menus.
622
637
  query Menu($handle: String!) {
623
638
  menu(handle: $handle) {
624
639
  ...Menu