@scayle/storefront-nuxt 8.60.0 → 8.61.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 CHANGED
@@ -1,5 +1,74 @@
1
1
  # @scayle/storefront-nuxt
2
2
 
3
+ ## 8.61.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **[RPC]** Added HTTP method support so read-only RPCs can use `GET` and unlock CDN and browser caching for public data — no changes needed for existing handlers.
8
+
9
+ Pass `{ method }` as the second argument to `defineRpcHandler`. Omit it to keep the default `POST`.
10
+
11
+ ```ts
12
+ // Safe reads — eligible for CDN / browser caching
13
+ export const getNavigation = defineRpcHandler(handler, { method: "GET" });
14
+
15
+ // Mutations
16
+ export const updateBasketItem = defineRpcHandler(handler, { method: "PUT" });
17
+ export const deleteWishlistItem = defineRpcHandler(handler, {
18
+ method: "DELETE",
19
+ });
20
+ ```
21
+
22
+ RPCs returning user-specific data (basket, wishlist, tokens) should stay on `POST` to prevent unintended caching.
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependency `@scayle/unstorage-compression-driver@workspace:*` to `@scayle/unstorage-compression-driver@catalog:`
27
+
28
+ **Dependencies**
29
+
30
+ **@scayle/storefront-core v8.61.0**
31
+
32
+ - Minor
33
+
34
+ - **[RPC]** `defineRpcHandler` now accepts an optional `method` option (`'GET' | 'POST' | 'PUT' | 'DELETE'`) to declare the HTTP method for the handler. Defaults to `'POST'`, so existing handlers behave exactly as before. Updated built-in RPC methods to use `GET` for safe, cacheable reads and `PUT`/`POST`/`DELETE` for mutations, enabling CDN and browser caching for public data fetches.
35
+
36
+ User- and session-specific RPCs (`getBasket`, `getUser`, `fetchUser`, `getWishlist`, `getAccessToken`, `getCheckoutToken`, `getOrderById`, `getCheckoutDataByCbd`, `getShopUserAddress`) intentionally stay on `POST` so their responses are never eligible for CDN or browser caching.
37
+
38
+ ```ts
39
+ import { defineRpcHandler, type RpcContext } from "@scayle/storefront-core";
40
+
41
+ // Safe, public read — eligible for CDN/browser caching
42
+ export const getNavigation = defineRpcHandler(
43
+ async (context: RpcContext) => {
44
+ /* ... */
45
+ },
46
+ { method: "GET" }
47
+ );
48
+
49
+ // User-specific / Mutation — uses POST to prevent cache leakage
50
+ export const getBasket = defineRpcHandler(
51
+ async (context: RpcContext) => {
52
+ /* ... */
53
+ }
54
+ // method defaults to 'POST'
55
+ );
56
+ ```
57
+
58
+ - Patch
59
+ - Updated dependency `@scayle/storefront-api@workspace:*` to `@scayle/storefront-api@catalog:`
60
+ - Updated dependency `@scayle/unstorage-scayle-kv-driver@workspace:*` to `@scayle/unstorage-scayle-kv-driver@catalog:`
61
+
62
+ ## 8.60.1
63
+
64
+ ### Patch Changes
65
+
66
+ **Dependencies**
67
+
68
+ **@scayle/storefront-core v8.60.1**
69
+
70
+ - No changes in this release.
71
+
3
72
  ## 8.60.0
4
73
 
5
74
  ### Minor Changes
@@ -105,33 +174,33 @@
105
174
  **Migration:**
106
175
 
107
176
  ```ts
108
- import baseSlugify from 'slugify'
177
+ import baseSlugify from "slugify";
109
178
 
110
179
  const slugify = (url: string | undefined): string => {
111
- return baseSlugify(url ?? '', {
180
+ return baseSlugify(url ?? "", {
112
181
  lower: true,
113
182
  remove: /[*+~.()'"!:@/#?]/g,
114
- })
115
- }
183
+ });
184
+ };
116
185
 
117
- const localePath = useLocalePath()
186
+ const localePath = useLocalePath();
118
187
 
119
188
  const getProductDetailRoute = (
120
189
  id: number,
121
190
  name?: string,
122
- locale?: Locale,
191
+ locale?: Locale
123
192
  ): string => {
124
193
  return localePath(
125
194
  {
126
- name: 'p-productName-id',
195
+ name: "p-productName-id",
127
196
  params: {
128
197
  productName: slugify(name),
129
198
  id: `${id}`,
130
199
  },
131
200
  },
132
- locale,
133
- )
134
- }
201
+ locale
202
+ );
203
+ };
135
204
  ```
136
205
 
137
206
  ## 8.59.1
@@ -292,39 +361,39 @@
292
361
 
293
362
  ```ts
294
363
  // server/plugins/session-plugin.ts
295
- import { hasSession } from '@scayle/storefront-nuxt'
296
- import { defineNitroPlugin } from '#imports'
364
+ import { hasSession } from "@scayle/storefront-nuxt";
365
+ import { defineNitroPlugin } from "#imports";
297
366
 
298
367
  export default defineNitroPlugin((nitroApp) => {
299
- nitroApp.hooks.hook('storefront:afterLogin', async (_data, context) => {
368
+ nitroApp.hooks.hook("storefront:afterLogin", async (_data, context) => {
300
369
  // Check if we actually have a RpcContext with proper session data
301
370
  if (!hasSession(context)) {
302
- return
371
+ return;
303
372
  }
304
373
 
305
374
  // Should you have set custom session data already in another hook,
306
375
  // it might be necessary to get existing data first.
307
- const sessionCustomData = context.sessionCustomData
376
+ const sessionCustomData = context.sessionCustomData;
308
377
 
309
378
  // The update functions overrides the customData object on a session.
310
379
  // Should you have set custom session data already in another hooks,
311
380
  // you need to pass it in addition to your new custom session data.
312
381
  context.updateSessionCustomData({
313
382
  ...sessionCustomData,
314
- yourCustomDataKey: 'Your Session CustomData Value',
315
- })
383
+ yourCustomDataKey: "Your Session CustomData Value",
384
+ });
316
385
 
317
386
  // Before accessing your session custom data, you might want to use an
318
387
  // explicit early return conditional.
319
388
  if (!sessionCustomData) {
320
- return
389
+ return;
321
390
  }
322
391
 
323
392
  // Your custom session data can also be accessedd directly via
324
393
  // nullish coalescing depending on your needs.
325
- console.log(context.sessionCustomData?.yourCustomDataKey)
326
- })
327
- })
394
+ console.log(context.sessionCustomData?.yourCustomDataKey);
395
+ });
396
+ });
328
397
  ```
329
398
 
330
399
  ### Patch Changes
@@ -384,20 +453,20 @@
384
453
 
385
454
  ```ts
386
455
  // Before
387
- const { data } = await useRpc('getProduct', 'my-static-product-key', {
456
+ const { data } = await useRpc("getProduct", "my-static-product-key", {
388
457
  productId: 123,
389
- })
458
+ });
390
459
 
391
460
  // After
392
- const productId = ref(123)
461
+ const productId = ref(123);
393
462
 
394
463
  // The key is now reactive. If `productId` changes, the key updates
395
464
  // to 'product-456' (for example) and triggers a new fetch.
396
465
  const { data } = await useRpc(
397
- 'getProduct',
466
+ "getProduct",
398
467
  () => `product-${productId.value}`,
399
- { productId },
400
- )
468
+ { productId }
469
+ );
401
470
  ```
402
471
 
403
472
  - Deprecated the `CheckoutEvent` type, which will be removed in the next major version.
@@ -409,22 +478,22 @@
409
478
  The type definition remains unchanged, so you can copy it directly:
410
479
 
411
480
  ```ts
412
- import type { ShopUser } from '@scayle/storefront-nuxt'
481
+ import type { ShopUser } from "@scayle/storefront-nuxt";
413
482
 
414
483
  export interface CheckoutEvent {
415
484
  /** Action. */
416
- action?: 'authenticated'
485
+ action?: "authenticated";
417
486
  /** Type. */
418
- type?: 'tracking'
487
+ type?: "tracking";
419
488
  /** User. */
420
- user: ShopUser
489
+ user: ShopUser;
421
490
  /**
422
491
  * The OAuth 2.0 access token for the authenticated user.
423
492
  * This token can be used to access protected resources on behalf of the user.
424
493
  *
425
494
  * @see https://www.rfc-editor.org/rfc/rfc6749
426
495
  */
427
- accessToken: string
496
+ accessToken: string;
428
497
  /**
429
498
  * Details about a specific event within the checkout process.
430
499
  * This field is optional and is only used when tracking specific actions
@@ -434,25 +503,25 @@
434
503
  */
435
504
  event?: {
436
505
  /** Event name. */
437
- event: 'login' | 'add_to_cart' | 'remove_from_cart'
506
+ event: "login" | "add_to_cart" | "remove_from_cart";
438
507
  /** Event status. */
439
- status: 'successful' | 'error'
440
- }
508
+ status: "successful" | "error";
509
+ };
441
510
  }
442
511
  ```
443
512
 
444
513
  - Updated the `StorefrontRuntimeConfig` type to ensure configured `shops` correctly incorporates all extended properties from `AdditionalShopConfig`.
445
514
 
446
515
  ```ts
447
- declare module '@scayle/storefront-nuxt' {
516
+ declare module "@scayle/storefront-nuxt" {
448
517
  // Extend the shop config
449
518
  export interface AdditionalShopConfig {
450
- extendedProp: string
519
+ extendedProp: string;
451
520
  }
452
521
  }
453
522
 
454
523
  // `extendedProp` is now properly typed
455
- useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp
524
+ useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp;
456
525
  ```
457
526
 
458
527
  **Dependencies**
@@ -472,11 +541,11 @@
472
541
  ```ts
473
542
  // Before (or when `rpcDefaultLazy: false`)
474
543
  // You had to explicitly opt-in to lazy behavior
475
- const { data } = useRpc('someMethod', { some: 'param' }, { lazy: true })
544
+ const { data } = useRpc("someMethod", { some: "param" }, { lazy: true });
476
545
 
477
546
  // After (when `rpcDefaultLazy: true`)
478
547
  // Lazy behavior is now the default
479
- const { data } = useRpc('someMethod', { some: 'param' })
548
+ const { data } = useRpc("someMethod", { some: "param" });
480
549
  ```
481
550
 
482
551
  **Dependencies**
@@ -588,10 +657,10 @@
588
657
  Example:
589
658
 
590
659
  ```ts
591
- import { sha256 } from '@scayle/storefront-core'
660
+ import { sha256 } from "@scayle/storefront-core";
592
661
 
593
- const hash = await sha256('hello')
594
- console.log(hash) // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
662
+ const hash = await sha256("hello");
663
+ console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
595
664
  ```
596
665
 
597
666
  ## 8.48.1
@@ -671,8 +740,8 @@
671
740
  customer: {
672
741
  groups: context.user?.groups,
673
742
  },
674
- }
675
- })
743
+ };
744
+ });
676
745
  ```
677
746
 
678
747
  For further information, please refer to the [Overriding Core RPC Methods](https://scayle.dev/en/core-documentation/storefront-guide/storefront-application/technical-foundation/rpc-methods?sourceText=RPC%2520Methods#overriding-core-rpc-methods).
@@ -706,32 +775,32 @@
706
775
  #### Looking up by name (existing, now renamed):
707
776
 
708
777
  ```typescript
709
- import { getAttributeValuesByName } from '@scayle/storefront-core'
778
+ import { getAttributeValuesByName } from "@scayle/storefront-core";
710
779
 
711
780
  // Single-select attribute
712
- const sizes = getAttributeValuesByName(product.attributes, 'size')
781
+ const sizes = getAttributeValuesByName(product.attributes, "size");
713
782
  // Returns: [{ id: 1, label: 'M', value: 'medium' }]
714
783
 
715
784
  // Multi-select attribute
716
- const colors = getAttributeValuesByName(product.attributes, 'color')
785
+ const colors = getAttributeValuesByName(product.attributes, "color");
717
786
  // Returns: [{ id: 1, label: 'Red' }, { id: 2, label: 'Blue' }]
718
787
 
719
788
  // Non-existent attribute
720
- const missing = getAttributeValuesByName(product.attributes, 'doesNotExist')
789
+ const missing = getAttributeValuesByName(product.attributes, "doesNotExist");
721
790
  // Returns: []
722
791
  ```
723
792
 
724
793
  #### Looking up by group ID (new):
725
794
 
726
795
  ```typescript
727
- import { getAttributeValuesByGroupId } from '@scayle/storefront-core'
796
+ import { getAttributeValuesByGroupId } from "@scayle/storefront-core";
728
797
 
729
798
  // Look up attribute by its numeric ID from the SCAYLE API
730
- const promotionValues = getAttributeValuesByGroupId(product.attributes, 42)
799
+ const promotionValues = getAttributeValuesByGroupId(product.attributes, 42);
731
800
  // Returns: [{ id: 123, label: 'Summer Sale', value: 'summer-2024' }]
732
801
 
733
802
  // Non-existent attribute group
734
- const missing = getAttributeValuesByGroupId(product.attributes, 9999)
803
+ const missing = getAttributeValuesByGroupId(product.attributes, 9999);
735
804
  // Returns: []
736
805
  ```
737
806
 
@@ -794,27 +863,27 @@
794
863
  // nuxt.config.ts
795
864
  export default defineNuxtConfig({
796
865
  storefront: {
797
- apiBasePath: '/custom-api', // ✅ Configure globally for all shops
866
+ apiBasePath: "/custom-api", // ✅ Configure globally for all shops
798
867
  },
799
868
  runtimeConfig: {
800
869
  storefront: {
801
870
  shops: {
802
871
  1001: {
803
872
  shopId: 1001,
804
- path: 'de',
873
+ path: "de",
805
874
  // ✅ apiBasePath removed from shop config
806
875
  // ... other shop config
807
876
  },
808
877
  1002: {
809
878
  shopId: 1002,
810
- path: 'en',
879
+ path: "en",
811
880
  // ✅ apiBasePath removed from shop config
812
881
  // ... other shop config
813
882
  },
814
883
  },
815
884
  },
816
885
  },
817
- })
886
+ });
818
887
  ```
819
888
 
820
889
  Additionally, the types for the Storefront module options and Storefront runtime configuration have been cleaned up to properly reflect which settings can be set at runtime and which cannot. This clarifies the distinction between configuration that is static (set at build/module level) and configuration that is dynamic (set at runtime), improving type safety and developer experience.
@@ -930,10 +999,10 @@
930
999
 
931
1000
  ```ts
932
1001
  const isComboDealType = (
933
- promotion?: Promotion | null,
1002
+ promotion?: Promotion | null
934
1003
  ): promotion is Promotion<ComboDealEffect> => {
935
- return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL
936
- }
1004
+ return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL;
1005
+ };
937
1006
  ```
938
1007
 
939
1008
  ## 8.42.2
@@ -997,68 +1066,68 @@
997
1066
  Before:
998
1067
 
999
1068
  ```ts
1000
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1001
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1069
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1070
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1002
1071
 
1003
1072
  updateBasketItemRpc({
1004
1073
  // ...
1005
- promotionId: 'promotionId',
1006
- promotionCode: 'promotionCode',
1007
- })
1074
+ promotionId: "promotionId",
1075
+ promotionCode: "promotionCode",
1076
+ });
1008
1077
 
1009
1078
  addItemToBasketRpc({
1010
1079
  // ...
1011
- promotionId: 'promotionId',
1012
- promotionCode: 'promotionCode',
1013
- })
1080
+ promotionId: "promotionId",
1081
+ promotionCode: "promotionCode",
1082
+ });
1014
1083
 
1015
1084
  // Or with useBasket composable
1016
1085
 
1017
- const { addItem } = useBasket()
1086
+ const { addItem } = useBasket();
1018
1087
  addItem({
1019
1088
  // ...
1020
- promotionId: 'promotionId',
1021
- })
1089
+ promotionId: "promotionId",
1090
+ });
1022
1091
  ```
1023
1092
 
1024
1093
  After:
1025
1094
 
1026
1095
  ```ts
1027
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1028
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1096
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1097
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1029
1098
 
1030
1099
  updateBasketItemRpc({
1031
1100
  // ...
1032
1101
  promotions: [
1033
- { id: 'promotionId', code: 'promotionCode' },
1102
+ { id: "promotionId", code: "promotionCode" },
1034
1103
  {
1035
- id: 'promotionId2',
1104
+ id: "promotionId2",
1036
1105
  },
1037
1106
  ],
1038
- })
1107
+ });
1039
1108
 
1040
1109
  addItemToBasketRpc({
1041
1110
  // ...
1042
1111
  promotions: [
1043
- { id: 'promotionId', code: 'promotionCode' },
1112
+ { id: "promotionId", code: "promotionCode" },
1044
1113
  {
1045
- id: 'promotionId2',
1114
+ id: "promotionId2",
1046
1115
  },
1047
1116
  ],
1048
- })
1117
+ });
1049
1118
 
1050
1119
  // Or for useBasket with composable
1051
1120
 
1052
- const { addItem } = useBasket()
1121
+ const { addItem } = useBasket();
1053
1122
  addItem({
1054
1123
  // ...
1055
1124
  promotions: [
1056
- { id: 'promotionId', code: 'promotionCode' },
1125
+ { id: "promotionId", code: "promotionCode" },
1057
1126
  {
1058
- id: 'promotionId2',
1127
+ id: "promotionId2",
1059
1128
  },
1060
1129
  ],
1061
- })
1130
+ });
1062
1131
  ```
1063
1132
 
1064
1133
  For more details, see the [Add a variant](https://scayle.dev/en/api-guides/storefront-api/resources/baskets/add-a-variant) and [Update an item](https://scayle.dev/en/api-guides/storefront-api/resources/baskets/update-an-item) guides.
@@ -1463,23 +1532,23 @@
1463
1532
  - Added `minReduction` and `maxReduction` filter parameters to `FetchProductsByCategoryParams.where` and `FetchFiltersParams.where` types, and updated the `getProductsByCategory` and `getFilters` RPC methods to accept and handle these new reduction-based filtering conditions.
1464
1533
 
1465
1534
  ```ts
1466
- const { data } = useRpc('getFilters', 'getFiltersKey', () => ({
1535
+ const { data } = useRpc("getFilters", "getFiltersKey", () => ({
1467
1536
  where: {
1468
1537
  minReduction: 10,
1469
1538
  maxReduction: 20,
1470
1539
  },
1471
- }))
1540
+ }));
1472
1541
 
1473
1542
  const { data } = useRpc(
1474
- 'getProductsByCategory',
1475
- 'getProductsByCategoryKey',
1543
+ "getProductsByCategory",
1544
+ "getProductsByCategoryKey",
1476
1545
  () => ({
1477
1546
  where: {
1478
1547
  minReduction: 10,
1479
1548
  maxReduction: 20,
1480
1549
  },
1481
- }),
1482
- )
1550
+ })
1551
+ );
1483
1552
  ```
1484
1553
 
1485
1554
  ## 8.30.3
@@ -1531,28 +1600,28 @@
1531
1600
 
1532
1601
  ```ts
1533
1602
  export const existingHandlerWithoutParams = async (_context: RpcContext) => {
1534
- return 'existing handler'
1535
- }
1603
+ return "existing handler";
1604
+ };
1536
1605
 
1537
1606
  export const existingHandlerWithParams = async (
1538
1607
  { name }: { name: string },
1539
- _context: RpcContext,
1608
+ _context: RpcContext
1540
1609
  ) => {
1541
- return name
1542
- }
1610
+ return name;
1611
+ };
1543
1612
 
1544
1613
  // will become
1545
1614
 
1546
1615
  export const existingHandlerWithoutParams = defineRpcHandler(
1547
1616
  async (_context: RpcContext) => {
1548
- return 'existing handler'
1549
- },
1550
- )
1617
+ return "existing handler";
1618
+ }
1619
+ );
1551
1620
  export const existingHandlerWithParams = defineRpcHandler(
1552
1621
  async ({ name }: { name: string }, _context: RpcContext) => {
1553
- return name
1554
- },
1555
- )
1622
+ return name;
1623
+ }
1624
+ );
1556
1625
  ```
1557
1626
 
1558
1627
  - Patch
@@ -1574,15 +1643,15 @@
1574
1643
  - Added an optional `hideEmptyCategories` parameter to `getCategoryTree`. When enabled, the product count for each category is retrieved, and categories (including their children) without any products are removed. Enabling this option may increase response times, especially for large category trees.
1575
1644
 
1576
1645
  ```ts
1577
- import { rpcMethods } from '@scayle/storefront-core'
1646
+ import { rpcMethods } from "@scayle/storefront-core";
1578
1647
 
1579
- rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext)
1648
+ rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext);
1580
1649
  ```
1581
1650
 
1582
1651
  or
1583
1652
 
1584
1653
  ```ts
1585
- import { useCategoryTree } from '#storefront/composables'
1654
+ import { useCategoryTree } from "#storefront/composables";
1586
1655
 
1587
1656
  const { data: rootCategories, status } = useCategoryTree(
1588
1657
  {
@@ -1590,8 +1659,8 @@
1590
1659
  hideEmptyCategories: true,
1591
1660
  },
1592
1661
  },
1593
- 'category-navigation-tree',
1594
- )
1662
+ "category-navigation-tree"
1663
+ );
1595
1664
  ```
1596
1665
 
1597
1666
  ## 8.28.7
@@ -1688,9 +1757,9 @@
1688
1757
  params: {
1689
1758
  children: 10,
1690
1759
  includeHidden: true,
1691
- properties: { withName: ['sale'] },
1760
+ properties: { withName: ["sale"] },
1692
1761
  },
1693
- })
1762
+ });
1694
1763
  ```
1695
1764
 
1696
1765
  ### Patch Changes
@@ -1861,16 +1930,16 @@
1861
1930
  nitro: {
1862
1931
  storage: {
1863
1932
  redis: {
1864
- driver: 'redis',
1865
- host: 'localhost',
1933
+ driver: "redis",
1934
+ host: "localhost",
1866
1935
  },
1867
1936
  db: {
1868
- driver: 'fs',
1869
- base: './.data/db',
1937
+ driver: "fs",
1938
+ base: "./.data/db",
1870
1939
  },
1871
1940
  },
1872
1941
  },
1873
- })
1942
+ });
1874
1943
  ```
1875
1944
 
1876
1945
  With the introduction of the new approach for configuring storefront storage mounts, the global and shop-specific `storage` option within the `@scayle/storefront-nuxt` runtime configuration has been deprecated.
@@ -1943,9 +2012,9 @@
1943
2012
  ```typescript
1944
2013
  const idp = useIDP({
1945
2014
  authUrlParameters: {
1946
- theme: 'dark',
2015
+ theme: "dark",
1947
2016
  },
1948
- })
2017
+ });
1949
2018
  ```
1950
2019
 
1951
2020
  ### Patch Changes
@@ -2087,11 +2156,11 @@
2087
2156
  storefront: {
2088
2157
  redirects: {
2089
2158
  enabled: true,
2090
- strategy: 'on-missing',
2159
+ strategy: "on-missing",
2091
2160
  },
2092
2161
  },
2093
2162
  },
2094
- })
2163
+ });
2095
2164
  ```
2096
2165
 
2097
2166
  Also, keep in mind that when this option is enabled, the redirect logic will only be executed when the request would otherwise result in a 404. There are three ways in which a 404 can occur.
@@ -2105,7 +2174,7 @@
2105
2174
  If the request handler returns a `Response` object with a `status` of 404, a 404 response will be returned to the client.
2106
2175
 
2107
2176
  ```typescript
2108
- return new Response(null, { status: 404 })
2177
+ return new Response(null, { status: 404 });
2109
2178
  ```
2110
2179
 
2111
2180
  3. Thrown H3Error with 404 status
@@ -2113,8 +2182,8 @@
2113
2182
  If the request handler throws an H3Error with a `statusCode` 404, a 404 response will be returned to the client.
2114
2183
 
2115
2184
  ```typescript
2116
- import { createError } from 'h3'
2117
- throw createError({ statusCode: 404 })
2185
+ import { createError } from "h3";
2186
+ throw createError({ statusCode: 404 });
2118
2187
  ```
2119
2188
 
2120
2189
  ### Patch Changes
@@ -2556,28 +2625,28 @@
2556
2625
  **rpc-methods.ts**
2557
2626
 
2558
2627
  ```typescript
2559
- import type { RpcContext, RpcHandler } from '@scayle/storefront-nuxt'
2628
+ import type { RpcContext, RpcHandler } from "@scayle/storefront-nuxt";
2560
2629
 
2561
2630
  export const foo: RpcHandler<string, number> = function testing(
2562
2631
  param: string,
2563
- _: RpcContext,
2632
+ _: RpcContext
2564
2633
  ) {
2565
- return param.length
2566
- }
2634
+ return param.length;
2635
+ };
2567
2636
  ```
2568
2637
 
2569
2638
  **module.ts**
2570
2639
 
2571
2640
  ```typescript
2572
2641
  function setup() {
2573
- const resolver = createResolver(import.meta.url)
2642
+ const resolver = createResolver(import.meta.url);
2574
2643
 
2575
- nuxt.hook('storefront:custom-rpc:extend', (customRpcImports) => {
2644
+ nuxt.hook("storefront:custom-rpc:extend", (customRpcImports) => {
2576
2645
  customRpcImports.push({
2577
- source: resolver.resolve('./rpc-methods.ts'),
2578
- names: ['foo'],
2579
- })
2580
- })
2646
+ source: resolver.resolve("./rpc-methods.ts"),
2647
+ names: ["foo"],
2648
+ });
2649
+ });
2581
2650
  }
2582
2651
  ```
2583
2652
 
@@ -2799,23 +2868,23 @@
2799
2868
  storefront: {
2800
2869
  // ...
2801
2870
  redis: {
2802
- host: 'localhost',
2871
+ host: "localhost",
2803
2872
  port: 6379,
2804
- prefix: '',
2805
- user: '',
2806
- password: '',
2873
+ prefix: "",
2874
+ user: "",
2875
+ password: "",
2807
2876
  sslTransit: false,
2808
2877
  },
2809
2878
  // ...
2810
2879
  session: {
2811
2880
  // ...
2812
- provider: 'redis',
2881
+ provider: "redis",
2813
2882
  },
2814
2883
  },
2815
2884
  // ...
2816
2885
  },
2817
2886
  // ...
2818
- })
2887
+ });
2819
2888
  ```
2820
2889
 
2821
2890
  - _Current Unified Storage Approach (`nuxt.config.ts`):_
@@ -2829,13 +2898,13 @@
2829
2898
  // ...
2830
2899
  storage: {
2831
2900
  cache: {
2832
- driver: 'redis',
2833
- host: 'localhost',
2901
+ driver: "redis",
2902
+ host: "localhost",
2834
2903
  port: 6379,
2835
2904
  },
2836
2905
  session: {
2837
- driver: 'redis',
2838
- host: 'localhost',
2906
+ driver: "redis",
2907
+ host: "localhost",
2839
2908
  port: 6379,
2840
2909
  },
2841
2910
  // ...
@@ -2845,7 +2914,7 @@
2845
2914
  // ...
2846
2915
  },
2847
2916
  // ...
2848
- })
2917
+ });
2849
2918
  ```
2850
2919
 
2851
2920
  - **\[💥 BREAKING\]** The composable `useSearch` has been replaced by `useStorefrontSearch`, consolidating and transitioning to SCAYLE Search v2.
@@ -2912,9 +2981,9 @@
2912
2981
 
2913
2982
  ```ts
2914
2983
  const { activeFilters, applyFilters, resetFilterUrl, productConditions } =
2915
- useQueryFilterState()
2984
+ useQueryFilterState();
2916
2985
 
2917
- applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 })
2986
+ applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 });
2918
2987
  ```
2919
2988
 
2920
2989
  - _Current Usage of `useFilter` and `useAppliedFilters`:_
@@ -2927,20 +2996,20 @@
2927
2996
  resetFilters,
2928
2997
  resetPriceFilter,
2929
2998
  resetFilter,
2930
- } = useFilter()
2999
+ } = useFilter();
2931
3000
 
2932
- applyPriceFilter([0, 100])
2933
- applyBooleanFilter('sale', true)
2934
- applyAttributeFilter('brand', 23)
3001
+ applyPriceFilter([0, 100]);
3002
+ applyBooleanFilter("sale", true);
3003
+ applyAttributeFilter("brand", 23);
2935
3004
 
2936
- const route = useRoute()
3005
+ const route = useRoute();
2937
3006
  const {
2938
3007
  appliedFilter,
2939
3008
  appliedFiltersCount,
2940
3009
  appliedAttributeValues,
2941
3010
  appliedBooleanValues,
2942
3011
  areFiltersApplied,
2943
- } = useAppliedFilters(route)
3012
+ } = useAppliedFilters(route);
2944
3013
  ```
2945
3014
 
2946
3015
  - **\[💥 BREAKING\]** The `getBadgeLabel` helper function has been removed, giving you more control over badge label display.
@@ -2950,43 +3019,43 @@
2950
3019
 
2951
3020
  ```ts
2952
3021
  const BadgeLabel = {
2953
- NEW: 'new',
2954
- SOLD_OUT: 'sold_out',
2955
- ONLINE_EXCLUSIVE: 'online_exclusive',
2956
- SUSTAINABLE: 'sustainable',
2957
- PREMIUM: 'premium',
2958
- DEFAULT: '',
2959
- } as const
3022
+ NEW: "new",
3023
+ SOLD_OUT: "sold_out",
3024
+ ONLINE_EXCLUSIVE: "online_exclusive",
3025
+ SUSTAINABLE: "sustainable",
3026
+ PREMIUM: "premium",
3027
+ DEFAULT: "",
3028
+ } as const;
2960
3029
 
2961
3030
  type BadgeLabelParamsKeys =
2962
- | 'isNew'
2963
- | 'isSoldOut'
2964
- | 'isOnlineOnly'
2965
- | 'isSustainable'
2966
- | 'isPremium'
2967
- type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>
3031
+ | "isNew"
3032
+ | "isSoldOut"
3033
+ | "isOnlineOnly"
3034
+ | "isSustainable"
3035
+ | "isPremium";
3036
+ type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>;
2968
3037
 
2969
3038
  const getBadgeLabel = (params: BadgeLabelParams = {}): string => {
2970
3039
  if (!params) {
2971
- return BadgeLabel.DEFAULT
3040
+ return BadgeLabel.DEFAULT;
2972
3041
  }
2973
3042
  const { isNew, isSoldOut, isOnlineOnly, isSustainable, isPremium } =
2974
- params
3043
+ params;
2975
3044
 
2976
3045
  if (isNew) {
2977
- return BadgeLabel.NEW
3046
+ return BadgeLabel.NEW;
2978
3047
  } else if (isSoldOut) {
2979
- return BadgeLabel.SOLD_OUT
3048
+ return BadgeLabel.SOLD_OUT;
2980
3049
  } else if (isOnlineOnly) {
2981
- return BadgeLabel.ONLINE_EXCLUSIVE
3050
+ return BadgeLabel.ONLINE_EXCLUSIVE;
2982
3051
  } else if (isSustainable) {
2983
- return BadgeLabel.SUSTAINABLE
3052
+ return BadgeLabel.SUSTAINABLE;
2984
3053
  } else if (isPremium) {
2985
- return BadgeLabel.PREMIUM
3054
+ return BadgeLabel.PREMIUM;
2986
3055
  } else {
2987
- return BadgeLabel.DEFAULT
3056
+ return BadgeLabel.DEFAULT;
2988
3057
  }
2989
- }
3058
+ };
2990
3059
  ```
2991
3060
 
2992
3061
  - **\[💥 BREAKING\]** The `store` option in the module configuration has been removed. `@scayle/storefront-nuxt@7.84.0` introduced the `shops` option as a replacement, but maintained backward compatibility with the `store` option. Going forward, configuring shops must be done using the `shops` keyword.
@@ -3010,7 +3079,7 @@
3010
3079
  // ...
3011
3080
  },
3012
3081
  // ...
3013
- })
3082
+ });
3014
3083
  ```
3015
3084
 
3016
3085
  - _Previous Environment Variables for Store Configuration:_
@@ -3039,7 +3108,7 @@
3039
3108
  // ...
3040
3109
  },
3041
3110
  // ...
3042
- })
3111
+ });
3043
3112
  ```
3044
3113
 
3045
3114
  - _Current Environment Variables for Shops Configuration:_
@@ -3059,8 +3128,8 @@
3059
3128
  ```ts
3060
3129
  useProduct({
3061
3130
  // ...
3062
- key: 'productKey',
3063
- })
3131
+ key: "productKey",
3132
+ });
3064
3133
  ```
3065
3134
 
3066
3135
  - _Current `key` as dedicated composables argument:_
@@ -3070,8 +3139,8 @@
3070
3139
  {
3071
3140
  // ...
3072
3141
  },
3073
- 'productKey',
3074
- )
3142
+ "productKey"
3143
+ );
3075
3144
  ```
3076
3145
 
3077
3146
  - **\[💥 BREAKING\]** Introducing a new feature flag `storefront.legacy.enableSessionMigration` to control the automatic migration of legacy session data, set to `false` by default. Starting with `@scayle/storefront-nuxt@7.68.0` Storefront uses unique session cookie names for each shop, simplifying implementation and enhancing stability.
@@ -3088,27 +3157,27 @@
3088
3157
  - _Previous Usage of `handleIDPLoginCallback`:_
3089
3158
 
3090
3159
  ```ts
3091
- const { handleIDPLoginCallback } = await useIDP()
3160
+ const { handleIDPLoginCallback } = await useIDP();
3092
3161
 
3093
3162
  watch(
3094
3163
  () => route.query,
3095
3164
  async (query) => {
3096
3165
  if (query.code && isString(query.code)) {
3097
- await handleIDPLoginCallback(query.code)
3166
+ await handleIDPLoginCallback(query.code);
3098
3167
  }
3099
3168
  },
3100
- { immediate: true },
3101
- )
3169
+ { immediate: true }
3170
+ );
3102
3171
  ```
3103
3172
 
3104
3173
  - _Current Usage of `loginIDP`:_
3105
3174
 
3106
3175
  ```ts
3107
- const { loginIDP } = useAuthentication('login')
3176
+ const { loginIDP } = useAuthentication("login");
3108
3177
 
3109
3178
  onMounted(async () => {
3110
- await loginIDP(props.code)
3111
- })
3179
+ await loginIDP(props.code);
3180
+ });
3112
3181
  ```
3113
3182
 
3114
3183
  - **\[🧹 NON-BREAKING\]** Addressed various type resolution errors that were present when using the `@scayle/storefront-nuxt` package with different Node.js versions and module systems. These errors manifested as internal resolution errors or ESM dynamic import only warnings. With this fix, the package now more consistently resolves types correctly across Node.js 16 (CJS and ESM), and bundlers, ensuring a smoother developer experience.
@@ -3118,17 +3187,17 @@
3118
3187
  - _Previous `useRpc` with `autoFetch`:_
3119
3188
 
3120
3189
  ```ts
3121
- useRpc('rpcMethod', key, params, { autoFetch: true })
3190
+ useRpc("rpcMethod", key, params, { autoFetch: true });
3122
3191
 
3123
- useUser({ autoFetch: true })
3192
+ useUser({ autoFetch: true });
3124
3193
  ```
3125
3194
 
3126
3195
  - _Current `useRpc` with `immediate`:_
3127
3196
 
3128
3197
  ```ts
3129
- useRpc('rpcMethod', key, params, { immediate: true })
3198
+ useRpc("rpcMethod", key, params, { immediate: true });
3130
3199
 
3131
- useUser({ immediate: true })
3200
+ useUser({ immediate: true });
3132
3201
  ```
3133
3202
 
3134
3203
  - **\[💥 BREAKING\]** The attribute `isCmsPreview` has been removed from `RpcContext`.
@@ -3148,18 +3217,18 @@
3148
3217
  getSearchSuggestions,
3149
3218
  fetching,
3150
3219
  ...searchData
3151
- } = useStorefrontSearch(searchQuery, { key })
3220
+ } = useStorefrontSearch(searchQuery, { key });
3152
3221
 
3153
- fetching.value // true or false
3222
+ fetching.value; // true or false
3154
3223
  ```
3155
3224
 
3156
3225
  - _Current `useStorefrontSearch` returning `status`:_
3157
3226
 
3158
3227
  ```ts
3159
3228
  const { data, resolveSearch, getSearchSuggestions, status, ...searchData } =
3160
- useStorefrontSearch(searchQuery, {}, key)
3229
+ useStorefrontSearch(searchQuery, {}, key);
3161
3230
 
3162
- status.value // 'idle', 'pending', 'error' or 'success'
3231
+ status.value; // 'idle', 'pending', 'error' or 'success'
3163
3232
  ```
3164
3233
 
3165
3234
  - **\[💥 BREAKING\]** We've simplified composable caching and clarified the control you have over shared state behavior. The configuration option `disableDefaultGetCachedDataOverride` has been replaced with `legacy.enableDefaultGetCachedDataOverride`, and its logic has been reversed. Now, when `legacy.enableDefaultGetCachedDataOverride` is not set or set to `false`, the default behavior maintains the shared state functionality of `useRpc`, where multiple calls with the same key use the same cached data. Setting the option to `true` bypasses this shared caching, providing data isolation between calls. To maintain your existing caching behavior, simply change the value of `disableDefaultGetCachedDataOverride` to its opposite in your `nuxt.config.ts` file.
@@ -3184,7 +3253,7 @@
3184
3253
  // ...
3185
3254
  },
3186
3255
  // ...
3187
- })
3256
+ });
3188
3257
  ```
3189
3258
 
3190
3259
  - _Current `enableDefaultGetCachedDataOverride`in `nuxt.config.ts`:_
@@ -3209,7 +3278,7 @@
3209
3278
  // ...
3210
3279
  },
3211
3280
  // ...
3212
- })
3281
+ });
3213
3282
  ```
3214
3283
 
3215
3284
  - **\[💥 BREAKING\]** The `useRpc` composable has been updated to provide a more modern and robust data fetching experience, aligning its interface with the current and underlying [Nuxt 3 `useAsyncData`.](https://nuxt.com/docs/api/composables/use-async-data#return-values).
@@ -3231,7 +3300,7 @@
3231
3300
  function myCustomRpc() {
3232
3301
  // ...
3233
3302
 
3234
- throw new BaseError(404)
3303
+ throw new BaseError(404);
3235
3304
  }
3236
3305
  ```
3237
3306
 
@@ -3241,7 +3310,7 @@
3241
3310
  function myCustomRpc() {
3242
3311
  // ...
3243
3312
 
3244
- return new Response(null, { status: 404 })
3313
+ return new Response(null, { status: 404 });
3245
3314
  }
3246
3315
  ```
3247
3316