@doswiftly/storefront-operations 1.0.6 → 5.4.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/fragments.graphql CHANGED
@@ -20,6 +20,7 @@ fragment UserError on UserError {
20
20
  field
21
21
  }
22
22
 
23
+ # Base Image — no transform (for logos, favicons, branding assets that are already small)
23
24
  fragment Image on Image {
24
25
  id
25
26
  url
@@ -28,6 +29,37 @@ fragment Image on Image {
28
29
  height
29
30
  }
30
31
 
32
+ # Thumbnail — cart items, variant swatches, author avatars (rendered at ~96px, 300px covers 3x DPI)
33
+ # No preferredContentType — imgproxy auto-negotiates AVIF/WEBP from Accept header
34
+ fragment ImageThumbnail on Image {
35
+ id
36
+ url(transform: { maxWidth: 300 })
37
+ altText
38
+ width
39
+ height
40
+ thumbhash
41
+ }
42
+
43
+ # Card — product cards, collection/category cards, blog posts (rendered at ~400px, 800px covers 2x DPI)
44
+ fragment ImageCard on Image {
45
+ id
46
+ url(transform: { maxWidth: 800 })
47
+ altText
48
+ width
49
+ height
50
+ thumbhash
51
+ }
52
+
53
+ # Full — product detail gallery, hero images (rendered at ~800px, 1600px covers 2x DPI)
54
+ fragment ImageFull on Image {
55
+ id
56
+ url(transform: { maxWidth: 1600 })
57
+ altText
58
+ width
59
+ height
60
+ thumbhash
61
+ }
62
+
31
63
  # Simple money (for originalPrice fields and non-converted prices)
32
64
  fragment Money on Money {
33
65
  amount
@@ -79,7 +111,7 @@ fragment ProductVariant on ProductVariant {
79
111
  available
80
112
  quantityAvailable
81
113
  image {
82
- ...Image
114
+ ...ImageThumbnail
83
115
  }
84
116
  selectedOptions {
85
117
  ...SelectedOption
@@ -102,7 +134,7 @@ fragment ProductCard on Product {
102
134
  reviewCount
103
135
  tags
104
136
  featuredImage {
105
- ...Image
137
+ ...ImageCard
106
138
  }
107
139
  priceRange {
108
140
  minVariantPrice {
@@ -146,6 +178,9 @@ fragment ProductBase on Product {
146
178
  totalInventory
147
179
  type
148
180
  collectRecipientInfo
181
+ # Faza 1.5 (Decision D-A v3 + D-B)
182
+ visibility
183
+ attributeSetId
149
184
  createdAt
150
185
  updatedAt
151
186
  }
@@ -153,7 +188,7 @@ fragment ProductBase on Product {
153
188
  fragment ProductFull on Product {
154
189
  ...ProductBase
155
190
  images(first: 20) {
156
- ...Image
191
+ ...ImageFull
157
192
  }
158
193
  variants(first: 100) {
159
194
  ...ProductVariant
@@ -175,7 +210,7 @@ fragment Collection on Collection {
175
210
  description
176
211
  descriptionHtml
177
212
  image {
178
- ...Image
213
+ ...ImageCard
179
214
  }
180
215
  seo {
181
216
  title
@@ -195,7 +230,7 @@ fragment Category on Category {
195
230
  slug
196
231
  description
197
232
  image {
198
- ...Image
233
+ ...ImageCard
199
234
  }
200
235
  level
201
236
  path
@@ -311,6 +346,24 @@ fragment CartLineCost on CartLineCost {
311
346
  }
312
347
  }
313
348
 
349
+ # Typed customer-filled attribute snapshot (Faza 1 R5 + Decision D-A v3 + D-I).
350
+ # Distinct from CartLine.attributes (Shopify raw KV line item properties).
351
+ fragment AttributeSelection on AttributeSelection {
352
+ attributeDefinitionId
353
+ attributeName
354
+ type
355
+ fillingMode
356
+ billingMode
357
+ optionId
358
+ optionLabel
359
+ optionIds
360
+ textValue
361
+ surchargeAmount
362
+ surchargeType
363
+ taxClassId
364
+ linkedVariantId
365
+ }
366
+
314
367
  fragment CartLine on CartLine {
315
368
  id
316
369
  quantity
@@ -324,6 +377,9 @@ fragment CartLine on CartLine {
324
377
  key
325
378
  value
326
379
  }
380
+ attributeSelections {
381
+ ...AttributeSelection
382
+ }
327
383
  productId
328
384
  productTitle
329
385
  productHandle
@@ -587,7 +643,7 @@ fragment CheckoutLineItem on CheckoutLineItem {
587
643
  productId
588
644
  sku
589
645
  image {
590
- ...Image
646
+ ...ImageThumbnail
591
647
  }
592
648
  }
593
649
 
@@ -1092,7 +1148,7 @@ fragment LoyaltyReward on LoyaltyReward {
1092
1148
  }
1093
1149
  description
1094
1150
  image {
1095
- ...Image
1151
+ ...ImageCard
1096
1152
  }
1097
1153
  available
1098
1154
  tierRequired {
@@ -1153,24 +1209,363 @@ fragment GenerateReferralCodePayload on GenerateReferralCodePayload {
1153
1209
  }
1154
1210
 
1155
1211
  # ============================================
1156
- # Inventory Level Fragments (Multi-Warehouse)
1212
+ # Review Fragments
1213
+ # ============================================
1214
+
1215
+ fragment ProductReview on ProductReview {
1216
+ id
1217
+ productId
1218
+ rating
1219
+ title
1220
+ content
1221
+ pros
1222
+ cons
1223
+ images
1224
+ authorName
1225
+ isVerifiedPurchase
1226
+ helpfulCount
1227
+ response
1228
+ responseAt
1229
+ createdAt
1230
+ }
1231
+
1232
+ fragment ReviewStats on ReviewStats {
1233
+ averageRating
1234
+ totalCount
1235
+ fiveStarCount
1236
+ fourStarCount
1237
+ threeStarCount
1238
+ twoStarCount
1239
+ oneStarCount
1240
+ }
1241
+
1242
+ # ============================================
1243
+ # Wishlist Fragments
1157
1244
  # ============================================
1158
1245
 
1159
- fragment InventoryLevel on InventoryLevel {
1160
- locationId
1161
- locationName
1162
- locationType
1246
+ fragment WishlistItem on WishlistItem {
1247
+ id
1248
+ productId
1249
+ variantId
1250
+ product {
1251
+ ...ProductCard
1252
+ }
1253
+ priceAtAdd {
1254
+ ...Money
1255
+ }
1256
+ notifyOnSale
1257
+ notifyOnRestock
1258
+ addedAt
1259
+ }
1260
+
1261
+ fragment Wishlist on Wishlist {
1262
+ id
1263
+ name
1264
+ isPublic
1265
+ shareToken
1266
+ items {
1267
+ ...WishlistItem
1268
+ }
1269
+ itemCount
1270
+ createdAt
1271
+ updatedAt
1272
+ }
1273
+
1274
+ # ============================================
1275
+ # Blog Fragments
1276
+ # ============================================
1277
+
1278
+ fragment BlogCategory on BlogCategory {
1279
+ id
1280
+ name
1281
+ slug
1282
+ description
1283
+ postCount
1284
+ }
1285
+
1286
+ fragment BlogTag on BlogTag {
1287
+ id
1288
+ name
1289
+ slug
1290
+ postCount
1291
+ }
1292
+
1293
+ fragment BlogPost on BlogPost {
1294
+ id
1295
+ title
1296
+ slug
1297
+ excerpt
1298
+ content
1299
+ contentType
1300
+ featuredImage {
1301
+ ...ImageCard
1302
+ }
1303
+ author {
1304
+ id
1305
+ name
1306
+ bio
1307
+ avatar {
1308
+ ...ImageThumbnail
1309
+ }
1310
+ }
1311
+ category {
1312
+ ...BlogCategory
1313
+ }
1314
+ tags {
1315
+ ...BlogTag
1316
+ }
1317
+ publishedAt
1318
+ readingTime
1319
+ viewCount
1320
+ commentCount
1321
+ allowComments
1322
+ isFeatured
1323
+ status
1324
+ seo {
1325
+ title
1326
+ description
1327
+ }
1328
+ createdAt
1329
+ updatedAt
1330
+ }
1331
+
1332
+ # ============================================
1333
+ # Recommendation Fragments
1334
+ # ============================================
1335
+
1336
+ fragment ProductRecommendation on ProductRecommendation {
1337
+ product {
1338
+ ...ProductCard
1339
+ }
1340
+ type
1341
+ score
1342
+ reason
1343
+ }
1344
+
1345
+ fragment CartRecommendation on CartRecommendations {
1346
+ frequentlyBoughtTogether {
1347
+ product {
1348
+ ...ProductCard
1349
+ }
1350
+ type
1351
+ score
1352
+ reason
1353
+ }
1354
+ youMayAlsoLike {
1355
+ product {
1356
+ ...ProductCard
1357
+ }
1358
+ type
1359
+ score
1360
+ reason
1361
+ }
1362
+ }
1363
+
1364
+ # ============================================
1365
+ # Store Availability Fragments (Shopify parity — BOPIS / multi-location)
1366
+ # ============================================
1367
+ # Field access:
1368
+ # - `available: Boolean!` — always public.
1369
+ # - `pickUpTime: String` — public, localized merchant-configured string.
1370
+ # - `quantityAvailable: Int` — TOKEN-GATED (null for anonymous, Int for authenticated).
1371
+ # - `location: Location!` — public, includes coords + businessHours when configured.
1372
+
1373
+ fragment LocationAddress on LocationAddress {
1374
+ address1
1375
+ address2
1376
+ city
1377
+ country
1378
+ countryCode
1379
+ province
1380
+ provinceCode
1381
+ zip
1382
+ phone
1383
+ latitude
1384
+ longitude
1385
+ formatted
1386
+ }
1387
+
1388
+ fragment BusinessHoursWindow on BusinessHoursWindow {
1389
+ openHour
1390
+ closeHour
1391
+ }
1392
+
1393
+ fragment BusinessHours on BusinessHours {
1394
+ monday { ...BusinessHoursWindow }
1395
+ tuesday { ...BusinessHoursWindow }
1396
+ wednesday { ...BusinessHoursWindow }
1397
+ thursday { ...BusinessHoursWindow }
1398
+ friday { ...BusinessHoursWindow }
1399
+ saturday { ...BusinessHoursWindow }
1400
+ sunday { ...BusinessHoursWindow }
1401
+ }
1402
+
1403
+ fragment Location on Location {
1404
+ id
1405
+ name
1406
+ type
1407
+ pickupEnabled
1408
+ timezone
1409
+ pickupInstructions
1410
+ address {
1411
+ ...LocationAddress
1412
+ }
1413
+ businessHours {
1414
+ ...BusinessHours
1415
+ }
1416
+ }
1417
+
1418
+ fragment StoreAvailability on StoreAvailability {
1163
1419
  available
1164
- onHand
1420
+ quantityAvailable
1421
+ pickUpTime
1422
+ location {
1423
+ ...Location
1424
+ }
1425
+ }
1426
+
1427
+ fragment StoreAvailabilityConnection on StoreAvailabilityConnection {
1428
+ totalCount
1429
+ pageInfo {
1430
+ ...PageInfo
1431
+ }
1432
+ edges {
1433
+ cursor
1434
+ node {
1435
+ ...StoreAvailability
1436
+ }
1437
+ }
1165
1438
  }
1166
1439
 
1167
- fragment VariantInventoryLevels on ProductVariant {
1440
+ fragment VariantStoreAvailability on ProductVariant {
1168
1441
  id
1169
1442
  title
1170
1443
  sku
1171
1444
  available
1172
1445
  quantityAvailable
1173
- inventoryLevels {
1174
- ...InventoryLevel
1446
+ storeAvailability(first: 10) {
1447
+ ...StoreAvailabilityConnection
1448
+ }
1449
+ }
1450
+
1451
+ # ============================================
1452
+ # Content: Pages
1453
+ # ============================================
1454
+
1455
+ fragment ShopPage on ShopPage {
1456
+ id
1457
+ handle
1458
+ title
1459
+ body
1460
+ bodySummary
1461
+ seo {
1462
+ title
1463
+ description
1464
+ }
1465
+ publishedAt
1466
+ createdAt
1467
+ updatedAt
1468
+ }
1469
+
1470
+ # ============================================
1471
+ # Content: Navigation Menus
1472
+ # ============================================
1473
+
1474
+ fragment MenuItem on MenuItem {
1475
+ id
1476
+ title
1477
+ url
1478
+ type
1479
+ resourceId
1480
+ image {
1481
+ ...Image
1482
+ }
1483
+ items {
1484
+ id
1485
+ title
1486
+ url
1487
+ type
1488
+ resourceId
1489
+ items {
1490
+ id
1491
+ title
1492
+ url
1493
+ type
1494
+ resourceId
1495
+ }
1496
+ }
1497
+ }
1498
+
1499
+ fragment Menu on Menu {
1500
+ id
1501
+ handle
1502
+ title
1503
+ itemsCount
1504
+ items {
1505
+ ...MenuItem
1506
+ }
1507
+ }
1508
+
1509
+ # ============================================
1510
+ # Content: URL Redirects
1511
+ # ============================================
1512
+
1513
+ fragment UrlRedirect on UrlRedirect {
1514
+ path
1515
+ target
1516
+ }
1517
+
1518
+ # ============================================
1519
+ # Unified Product Configurator (Faza 1 + Faza 1.5 — Decision D-A v3 + D-I)
1520
+ # ============================================
1521
+ # Hybrid Magento binding:
1522
+ # - Product.attributes returns UNION of set definitions (via Product.attributeSetId)
1523
+ # and per-product scoped definitions (AttributeDefinition.scopeProductId = product.id)
1524
+ # - CUSTOMER fillingMode → rendered in storefront configurator UX
1525
+ # - MERCHANT fillingMode → product metadata (filtering, display)
1526
+ # - BOTH fillingMode → admin default + customer override in cart
1527
+
1528
+ fragment LinkedVariantSummary on LinkedVariantSummary {
1529
+ id
1530
+ productId
1531
+ title
1532
+ sku
1533
+ quantityAvailable
1534
+ isAvailable
1535
+ trackQuantity
1536
+ }
1537
+
1538
+ fragment ProductAttributeOption on ProductAttributeOption {
1539
+ id
1540
+ value
1541
+ label
1542
+ sortOrder
1543
+ colorHex
1544
+ surchargeAmount
1545
+ surchargeType
1546
+ isDefault
1547
+ linkedVariantId
1548
+ linkedVariant {
1549
+ ...LinkedVariantSummary
1550
+ }
1551
+ }
1552
+
1553
+ fragment ProductAttributeDefinition on ProductAttributeDefinition {
1554
+ id
1555
+ name
1556
+ slug
1557
+ description
1558
+ type
1559
+ fillingMode
1560
+ billingMode
1561
+ taxClassId
1562
+ scopeProductId
1563
+ isRequired
1564
+ isVisible
1565
+ displayOrder
1566
+ minValue
1567
+ maxValue
1568
+ options {
1569
+ ...ProductAttributeOption
1175
1570
  }
1176
1571
  }
package/mutations.graphql CHANGED
@@ -431,3 +431,84 @@ mutation GenerateReferralCode {
431
431
  ...GenerateReferralCodePayload
432
432
  }
433
433
  }
434
+
435
+ # ============================================
436
+ # Review Mutations
437
+ # ============================================
438
+
439
+ mutation ReviewCreate($input: ReviewCreateInput!) {
440
+ reviewCreate(input: $input) {
441
+ review {
442
+ ...ProductReview
443
+ }
444
+ userErrors {
445
+ ...UserError
446
+ }
447
+ }
448
+ }
449
+
450
+ mutation ReviewVote($reviewId: ID!, $isHelpful: Boolean!) {
451
+ reviewVote(reviewId: $reviewId, isHelpful: $isHelpful) {
452
+ review {
453
+ ...ProductReview
454
+ }
455
+ userErrors {
456
+ ...UserError
457
+ }
458
+ }
459
+ }
460
+
461
+ # ============================================
462
+ # Wishlist Mutations
463
+ # ============================================
464
+
465
+ mutation WishlistCreate($input: WishlistCreateInput!) {
466
+ wishlistCreate(input: $input) {
467
+ wishlist {
468
+ ...Wishlist
469
+ }
470
+ userErrors
471
+ }
472
+ }
473
+
474
+ mutation WishlistAddItem($wishlistId: ID!, $input: WishlistItemInput!) {
475
+ wishlistAddItem(wishlistId: $wishlistId, input: $input) {
476
+ wishlist {
477
+ ...Wishlist
478
+ }
479
+ userErrors
480
+ }
481
+ }
482
+
483
+ mutation WishlistRemoveItem($wishlistId: ID!, $itemId: ID!) {
484
+ wishlistRemoveItem(wishlistId: $wishlistId, itemId: $itemId) {
485
+ wishlist {
486
+ ...Wishlist
487
+ }
488
+ userErrors
489
+ }
490
+ }
491
+
492
+ mutation WishlistDelete($wishlistId: ID!) {
493
+ wishlistDelete(wishlistId: $wishlistId) {
494
+ wishlist {
495
+ ...Wishlist
496
+ }
497
+ userErrors
498
+ }
499
+ }
500
+
501
+ # ============================================
502
+ # Cart Attributes
503
+ # ============================================
504
+
505
+ mutation CartAttributesUpdate($cartId: ID!, $attributes: [CartAttributeInput!]!) {
506
+ cartAttributesUpdate(cartId: $cartId, attributes: $attributes) {
507
+ cart {
508
+ ...Cart
509
+ }
510
+ userErrors {
511
+ ...UserError
512
+ }
513
+ }
514
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doswiftly/storefront-operations",
3
- "version": "1.0.6",
3
+ "version": "5.4.0",
4
4
  "description": "GraphQL operations for DoSwiftly Storefront - SSOT from backend",
5
5
  "homepage": "https://doswiftly.pl",
6
6
  "publishConfig": {
@@ -14,10 +14,6 @@
14
14
  "./fragments.graphql": "./fragments.graphql",
15
15
  "./*.graphql": "./*.graphql"
16
16
  },
17
- "scripts": {
18
- "sync": "node scripts/sync-operations.js",
19
- "build": "npm run sync"
20
- },
21
17
  "keywords": [
22
18
  "graphql",
23
19
  "operations",
@@ -33,5 +29,9 @@
33
29
  "mutations.graphql",
34
30
  "fragments.graphql",
35
31
  "README.md"
36
- ]
37
- }
32
+ ],
33
+ "scripts": {
34
+ "sync": "node scripts/sync-operations.js",
35
+ "build": "npm run sync"
36
+ }
37
+ }