@doswiftly/storefront-operations 13.1.0 → 14.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/schema.graphql CHANGED
@@ -63,7 +63,9 @@ type AttributeDefinition {
63
63
  """Attribute ID"""
64
64
  id: ID!
65
65
 
66
- """Whether attribute is filterable"""
66
+ """
67
+ Whether attribute is filterable (admin toggle). For storefront UI rendering signal use `isUsableAsFilter` (computed).
68
+ """
67
69
  isFilterable: Boolean!
68
70
 
69
71
  """Whether attribute is visible on product pages"""
@@ -140,6 +142,34 @@ type AttributeFilterValue {
140
142
  value: String!
141
143
  }
142
144
 
145
+ """Paginated + searchable attribute options (Relay Connection)"""
146
+ type AttributeFilterValueConnection {
147
+ """Paginated edges z cursorami"""
148
+ edges: [AttributeFilterValueEdge!]!
149
+
150
+ """Shortcut: edges.map(e => e.node)"""
151
+ nodes: [AttributeFilterValue!]!
152
+
153
+ """Relay pagination info (hasNextPage, hasPreviousPage, cursors)"""
154
+ pageInfo: PageInfo!
155
+
156
+ """
157
+ Total number of attribute options matching the filter (po zastosowaniu search + context). NIE zmienia się przy paginacji — pokazuje pełną liczbę dla counter UI.
158
+ """
159
+ totalCount: Int!
160
+ }
161
+
162
+ """Edge w AttributeFilterValueConnection (Relay spec)"""
163
+ type AttributeFilterValueEdge {
164
+ """
165
+ Opaque pagination cursor (base64-encoded). Echo as `after` for next page.
166
+ """
167
+ cursor: String!
168
+
169
+ """Attribute filter value (option + product count + swatch)"""
170
+ node: AttributeFilterValue!
171
+ }
172
+
143
173
  """Attribute input"""
144
174
  input AttributeInput {
145
175
  """Attribute key"""
@@ -157,6 +187,37 @@ enum AttributeOptionSurchargeType {
157
187
  PERCENT
158
188
  }
159
189
 
190
+ """Input dla attributeOptionsSearch query"""
191
+ input AttributeOptionsSearchInput {
192
+ """Opaque cursor z pageInfo.endCursor poprzedniej strony"""
193
+ after: String
194
+
195
+ """
196
+ Produktowy kontekst (categoryId/collectionId/searchQuery/currentFilters) dla accurate productCount. Exclude-self: gdy currentFilters zawiera ten sam atrybut, jest pomijany.
197
+ """
198
+ contextInput: AvailableFiltersInput
199
+
200
+ """Liczba zwracanych opcji (default 50, max 100)"""
201
+ first: Int
202
+
203
+ """Attribute handle (URL-friendly identifier, np. "licencja")"""
204
+ handle: String!
205
+
206
+ """Wyszukiwanie po value/label (case-insensitive ILIKE, max 100 znaków)"""
207
+ search: String
208
+
209
+ """
210
+ Sort — COUNT_DESC default (most popular first), LABEL_ASC dla alphabetical
211
+ """
212
+ sort: AttributeOptionsSearchSort
213
+ }
214
+
215
+ """Sort order for attributeOptionsSearch results"""
216
+ enum AttributeOptionsSearchSort {
217
+ COUNT_DESC
218
+ LABEL_ASC
219
+ }
220
+
160
221
  """Min/max bounds for numeric attributes"""
161
222
  type AttributeRangeBounds {
162
223
  """Currency code for CURRENCY type"""
@@ -271,7 +332,7 @@ type AvailableFilters {
271
332
  availableCount: Int!
272
333
 
273
334
  """
274
- Faza 3 (2026-05-17): canonical Brand entities z product counts w current context. Storefront UI renderuje checkbox list / dropdown z logo per brand. Klik → `filters: [{brand: {slug}}]`. Tylko brandy z >0 produktów w current product set + isActive=true.
335
+ Faza 3 (2026-05-17): canonical Brand entities z product counts w current context. Storefront UI renderuje checkbox list / dropdown z logo per brand. Klik → `filters: [{brand: {handle}}]`. Tylko brandy z >0 produktów w current product set + isActive=true.
275
336
  """
276
337
  brands: [BrandFilterValue!]
277
338
 
@@ -431,6 +492,9 @@ type BlogCategory {
431
492
  """Category description"""
432
493
  description: String
433
494
 
495
+ """URL-friendly handle"""
496
+ handle: String!
497
+
434
498
  """Category ID"""
435
499
  id: ID!
436
500
 
@@ -445,9 +509,6 @@ type BlogCategory {
445
509
 
446
510
  """SEO metadata"""
447
511
  seo: SEO
448
-
449
- """URL-friendly slug"""
450
- slug: String!
451
512
  }
452
513
 
453
514
  """Blog post"""
@@ -479,6 +540,9 @@ type BlogPost {
479
540
  """Featured image"""
480
541
  featuredImage: Image
481
542
 
543
+ """URL-friendly handle"""
544
+ handle: String!
545
+
482
546
  """Post ID"""
483
547
  id: ID!
484
548
 
@@ -494,9 +558,6 @@ type BlogPost {
494
558
  """SEO metadata"""
495
559
  seo: SEO
496
560
 
497
- """URL-friendly slug"""
498
- slug: String!
499
-
500
561
  """Post status"""
501
562
  status: BlogPostStatus!
502
563
 
@@ -552,6 +613,9 @@ enum BlogPostStatus {
552
613
 
553
614
  """Blog tag"""
554
615
  type BlogTag {
616
+ """URL-friendly handle"""
617
+ handle: String!
618
+
555
619
  """Tag ID"""
556
620
  id: ID!
557
621
 
@@ -560,9 +624,6 @@ type BlogTag {
560
624
 
561
625
  """Number of posts with this tag"""
562
626
  postCount: Int!
563
-
564
- """URL-friendly slug"""
565
- slug: String!
566
627
  }
567
628
 
568
629
  """Bot protection configuration (platform-level)"""
@@ -589,25 +650,21 @@ type BotProtectionProviderInfo {
589
650
  siteKey: String!
590
651
  }
591
652
 
592
- """Shop brand metadata (logo, colors, slogan)"""
653
+ """
654
+ Canonical product brand entity (np. Funko, Nike). Distinct od ShopBrand (shop branding metadata).
655
+ """
593
656
  type Brand {
594
- """Primary + secondary brand colors"""
595
- colors: BrandColors
596
-
597
- """Cover image / hero banner"""
598
- coverImage: Image
599
-
600
- """Primary logo"""
601
- logo: Image
657
+ """URL-friendly handle (e.g. "funko" → /brands/funko). Stable per-shop."""
658
+ handle: String!
602
659
 
603
- """Short brand description"""
604
- shortDescription: String
660
+ """Brand unique identifier"""
661
+ id: ID!
605
662
 
606
- """Marketing slogan / tagline"""
607
- slogan: String
663
+ """Brand logo URL (CDN-served, storefront-rendered)"""
664
+ logo: String
608
665
 
609
- """Square logo variant (favicons, app tiles)"""
610
- squareLogo: Image
666
+ """Brand display name (e.g. "Funko", "Nintendo")"""
667
+ name: String!
611
668
  }
612
669
 
613
670
  """Single brand color group (background + foreground hex)"""
@@ -627,17 +684,20 @@ type BrandColors {
627
684
 
628
685
  """Filter products po brand (canonical entity)"""
629
686
  input BrandFilter {
630
- """Brand ID — exact UUID match"""
631
- id: ID
632
-
633
687
  """
634
- Brand slug — URL-friendly identifier. Preferowany over `id` dla storefront refetch (stable po URL share).
688
+ Brand handle — URL-friendly identifier. Preferowany over `id` dla storefront refetch (stable po URL share).
635
689
  """
636
- slug: String
690
+ handle: String
691
+
692
+ """Brand ID — exact UUID match"""
693
+ id: ID
637
694
  }
638
695
 
639
696
  """Brand filter value z product count"""
640
697
  type BrandFilterValue {
698
+ """Brand handle (refetch payload — paste w ProductFilter.brand.handle)"""
699
+ handle: String!
700
+
641
701
  """Brand ID"""
642
702
  id: ID!
643
703
 
@@ -649,26 +709,6 @@ type BrandFilterValue {
649
709
 
650
710
  """Liczba produktów z tym brandem w current product set"""
651
711
  productCount: Int!
652
-
653
- """Brand slug (refetch payload — paste w ProductFilter.brand.slug)"""
654
- slug: String!
655
- }
656
-
657
- """
658
- Brand summary — minimalna projekcja dla storefront catalog + filter rendering
659
- """
660
- type BrandSummary {
661
- """Brand unique identifier"""
662
- id: ID!
663
-
664
- """Brand logo URL (CDN-served, storefront-rendered)"""
665
- logo: String
666
-
667
- """Brand display name (e.g. "Funko", "Nintendo")"""
668
- name: String!
669
-
670
- """URL-friendly slug — używane dla future /marka/[slug] landing pages"""
671
- slug: String!
672
712
  }
673
713
 
674
714
  """Business hours for a day"""
@@ -1506,6 +1546,7 @@ enum CartWarningCode {
1506
1546
  MERCHANDISE_NOT_AVAILABLE
1507
1547
  MERCHANDISE_NOT_ENOUGH_STOCK
1508
1548
  PAYMENTS_AMOUNT_REGION_MISMATCH
1549
+ SHIPPING_METHOD_AUTO_CLEARED
1509
1550
  }
1510
1551
 
1511
1552
  """Product category - hierarchical organization"""
@@ -1516,6 +1557,11 @@ type Category {
1516
1557
  """Category description"""
1517
1558
  description: String
1518
1559
 
1560
+ """
1561
+ URL-friendly handle (e.g. "electronics" -> /categories/electronics). Stable per-shop.
1562
+ """
1563
+ handle: String!
1564
+
1519
1565
  """Unique identifier"""
1520
1566
  id: ID!
1521
1567
 
@@ -1543,9 +1589,6 @@ type Category {
1543
1589
  """SEO metadata"""
1544
1590
  seo: SEO
1545
1591
 
1546
- """URL-friendly slug"""
1547
- slug: String!
1548
-
1549
1592
  """Sort order within parent"""
1550
1593
  sortOrder: Int!
1551
1594
  }
@@ -1582,6 +1625,9 @@ input CategoryFilter {
1582
1625
 
1583
1626
  """Category filter option"""
1584
1627
  type CategoryFilterOption {
1628
+ """URL-friendly handle"""
1629
+ handle: String!
1630
+
1585
1631
  """Category ID"""
1586
1632
  id: ID!
1587
1633
 
@@ -1596,9 +1642,6 @@ type CategoryFilterOption {
1596
1642
 
1597
1643
  """Number of products in this category"""
1598
1644
  productCount: Int!
1599
-
1600
- """URL-friendly slug"""
1601
- slug: String!
1602
1645
  }
1603
1646
 
1604
1647
  """Collection - curated group of products"""
@@ -3030,6 +3073,9 @@ type LoyaltyReward {
3030
3073
  """Discount percentage (if discount type)"""
3031
3074
  discountPercent: Float
3032
3075
 
3076
+ """URL-friendly handle"""
3077
+ handle: String!
3078
+
3033
3079
  """Reward ID"""
3034
3080
  id: ID!
3035
3081
 
@@ -3048,9 +3094,6 @@ type LoyaltyReward {
3048
3094
  """Redemptions remaining (null = unlimited)"""
3049
3095
  redemptionsRemaining: Int
3050
3096
 
3051
- """URL-friendly slug"""
3052
- slug: String!
3053
-
3054
3097
  """Minimum tier required"""
3055
3098
  tierRequired: LoyaltyTier
3056
3099
 
@@ -3363,16 +3406,17 @@ type MenuItem {
3363
3406
  type: MenuItemType!
3364
3407
 
3365
3408
  """
3366
- 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.
3409
+ Pre-resolved URL path computed server-side using a standard route convention: /categories/<handle>, /collections/<handle>, /pages/<handle>, /products/<handle>, /brands/<handle>. Static types resolve to /, /search, /products, /blog. HTTP returns the manually stored URL. Null when type is a resource link and the underlying resource was deleted. If your storefront uses non-standard routing (e.g. single-segment /<handle>), prefer reading the `resource` field instead and build URLs yourself from `resource.__typename` + `handle`.
3367
3410
  """
3368
3411
  url: URL
3369
3412
  }
3370
3413
 
3371
- union MenuItemResource = Category | Collection | Product | ShopPage
3414
+ union MenuItemResource = Brand | Category | Collection | Product | ShopPage
3372
3415
 
3373
3416
  """Menu item link type"""
3374
3417
  enum MenuItemType {
3375
3418
  BLOG
3419
+ BRAND
3376
3420
  CATALOG
3377
3421
  CATEGORY
3378
3422
  COLLECTION
@@ -4009,7 +4053,7 @@ type Product implements Node {
4009
4053
  """
4010
4054
  Canonical brand entity (Faza 3, 2026-05-17). Resolved via DataLoader (N+1 safe dla list queries). Null gdy product nie ma przypisanego brand_id.
4011
4055
  """
4012
- brand: BrandSummary
4056
+ brand: Brand
4013
4057
 
4014
4058
  """
4015
4059
  Wszystkie kategorie do których produkt należy (M2M przez ProductCategory junction). Posortowane po junction.sortOrder ASC. Empty list gdy produkt nie jest w żadnej kategorii.
@@ -4123,6 +4167,9 @@ type ProductAttributeDefinition {
4123
4167
  """Filling mode — MERCHANT | CUSTOMER | BOTH"""
4124
4168
  fillingMode: AttributeFillingMode!
4125
4169
 
4170
+ """URL-friendly handle"""
4171
+ handle: String!
4172
+
4126
4173
  """Definition ID"""
4127
4174
  id: ID!
4128
4175
 
@@ -4149,9 +4196,6 @@ type ProductAttributeDefinition {
4149
4196
  """
4150
4197
  scopeProductId: ID
4151
4198
 
4152
- """URL-friendly slug"""
4153
- slug: String!
4154
-
4155
4199
  """Tax class ID; null = inherit from variant"""
4156
4200
  taxClassId: ID
4157
4201
 
@@ -4537,6 +4581,11 @@ type Query {
4537
4581
  """List of all currencies supported by the system (ECB rates)"""
4538
4582
  allSupportedCurrencies: [Currency!]!
4539
4583
 
4584
+ """
4585
+ Paginated + searchable attribute options dla drill-into filter UI (np. dropdown z 800 licencjami + search input). Honors product context z exclude-self per attribute. Sort: COUNT_DESC default (most popular first), LABEL_ASC dla alfabetycznego z polskim collation.
4586
+ """
4587
+ attributeOptionsSearch(input: AttributeOptionsSearchInput!): AttributeFilterValueConnection!
4588
+
4540
4589
  """Get available payment methods"""
4541
4590
  availablePaymentMethods: AvailablePaymentMethods!
4542
4591
 
@@ -4554,11 +4603,11 @@ type Query {
4554
4603
 
4555
4604
  """Get single blog post"""
4556
4605
  blogPost(
4606
+ """Post handle"""
4607
+ handle: String
4608
+
4557
4609
  """Post ID"""
4558
4610
  id: ID
4559
-
4560
- """Post slug"""
4561
- slug: String
4562
4611
  ): BlogPost
4563
4612
 
4564
4613
  """List blog posts"""
@@ -4569,8 +4618,8 @@ type Query {
4569
4618
  """Filter by author ID"""
4570
4619
  authorId: String
4571
4620
 
4572
- """Filter by category slug"""
4573
- categorySlug: String
4621
+ """Filter by category handle"""
4622
+ categoryHandle: String
4574
4623
 
4575
4624
  """Filter featured posts only"""
4576
4625
  featured: Boolean
@@ -4584,8 +4633,8 @@ type Query {
4584
4633
  """Sort key"""
4585
4634
  sortKey: BlogPostSortKey = PUBLISHED_AT
4586
4635
 
4587
- """Filter by tag slug"""
4588
- tagSlug: String
4636
+ """Filter by tag handle"""
4637
+ tagHandle: String
4589
4638
  ): BlogPostConnection!
4590
4639
 
4591
4640
  """List blog tags"""
@@ -4624,11 +4673,11 @@ type Query {
4624
4673
 
4625
4674
  """Get category by ID or slug"""
4626
4675
  category(
4676
+ """Category handle (URL-friendly)"""
4677
+ handle: String
4678
+
4627
4679
  """Category ID"""
4628
4680
  id: ID
4629
-
4630
- """Category slug"""
4631
- slug: String
4632
4681
  ): Category
4633
4682
 
4634
4683
  """Get single collection"""
@@ -5562,8 +5611,10 @@ type Shop {
5562
5611
  """Bot protection configuration (platform-level)"""
5563
5612
  botProtection: BotProtectionInfo
5564
5613
 
5565
- """Industry-standard brand metadata (logo + slogan + colors)"""
5566
- brand: Brand
5614
+ """
5615
+ Shop brand metadata (logo + slogan + colors). Tenant-scoped (vs canonical product `Brand` entity used in `Product.brand`).
5616
+ """
5617
+ brand: ShopBrand
5567
5618
 
5568
5619
  """Complete branding configuration"""
5569
5620
  branding: ShopBranding
@@ -5670,6 +5721,27 @@ type ShopAddress {
5670
5721
  streetLine2: String
5671
5722
  }
5672
5723
 
5724
+ """Shop brand metadata (logo, colors, slogan)"""
5725
+ type ShopBrand {
5726
+ """Primary + secondary brand colors"""
5727
+ colors: BrandColors
5728
+
5729
+ """Cover image / hero banner"""
5730
+ coverImage: Image
5731
+
5732
+ """Primary logo"""
5733
+ logo: Image
5734
+
5735
+ """Short brand description"""
5736
+ shortDescription: String
5737
+
5738
+ """Marketing slogan / tagline"""
5739
+ slogan: String
5740
+
5741
+ """Square logo variant (favicons, app tiles)"""
5742
+ squareLogo: Image
5743
+ }
5744
+
5673
5745
  """Shop branding configuration"""
5674
5746
  type ShopBranding {
5675
5747
  """Brand colors"""