@scayle/storefront-nuxt 8.60.1 → 8.61.1

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,77 @@
1
1
  # @scayle/storefront-nuxt
2
2
 
3
+ ## 8.61.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated to `@scayle/unstorage-compression-driver@1.5.0`.
8
+ New optional params option on `CompressionDriverOptions` (and matching third arg on compress/decompress) is forwarded verbatim to the underlying `zlib` call. Brotli encoding now defaults to `BROTLI_PARAM_QUALITY: 6` when no params are supplied, resulting in same compression ratio as the prior implicit quality `11` default at ~300x the encode speed, removing up to several hundred ms of CPU per cold cache write on payloads in the hundreds of KB. Decompression of pre-existing entries is unaffected.
9
+
10
+ **Dependencies**
11
+
12
+ **@scayle/storefront-core v8.61.1**
13
+
14
+ - No changes in this release.
15
+
16
+ ## 8.61.0
17
+
18
+ ### Minor Changes
19
+
20
+ - **[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.
21
+
22
+ Pass `{ method }` as the second argument to `defineRpcHandler`. Omit it to keep the default `POST`.
23
+
24
+ ```ts
25
+ // Safe reads — eligible for CDN / browser caching
26
+ export const getNavigation = defineRpcHandler(handler, { method: "GET" });
27
+
28
+ // Mutations
29
+ export const updateBasketItem = defineRpcHandler(handler, { method: "PUT" });
30
+ export const deleteWishlistItem = defineRpcHandler(handler, {
31
+ method: "DELETE",
32
+ });
33
+ ```
34
+
35
+ RPCs returning user-specific data (basket, wishlist, tokens) should stay on `POST` to prevent unintended caching.
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependency `@scayle/unstorage-compression-driver@workspace:*` to `@scayle/unstorage-compression-driver@catalog:`
40
+
41
+ **Dependencies**
42
+
43
+ **@scayle/storefront-core v8.61.0**
44
+
45
+ - Minor
46
+
47
+ - **[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.
48
+
49
+ 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.
50
+
51
+ ```ts
52
+ import { defineRpcHandler, type RpcContext } from "@scayle/storefront-core";
53
+
54
+ // Safe, public read — eligible for CDN/browser caching
55
+ export const getNavigation = defineRpcHandler(
56
+ async (context: RpcContext) => {
57
+ /* ... */
58
+ },
59
+ { method: "GET" }
60
+ );
61
+
62
+ // User-specific / Mutation — uses POST to prevent cache leakage
63
+ export const getBasket = defineRpcHandler(
64
+ async (context: RpcContext) => {
65
+ /* ... */
66
+ }
67
+ // method defaults to 'POST'
68
+ );
69
+ ```
70
+
71
+ - Patch
72
+ - Updated dependency `@scayle/storefront-api@workspace:*` to `@scayle/storefront-api@catalog:`
73
+ - Updated dependency `@scayle/unstorage-scayle-kv-driver@workspace:*` to `@scayle/unstorage-scayle-kv-driver@catalog:`
74
+
3
75
  ## 8.60.1
4
76
 
5
77
  ### Patch Changes
@@ -115,33 +187,33 @@
115
187
  **Migration:**
116
188
 
117
189
  ```ts
118
- import baseSlugify from 'slugify'
190
+ import baseSlugify from "slugify";
119
191
 
120
192
  const slugify = (url: string | undefined): string => {
121
- return baseSlugify(url ?? '', {
193
+ return baseSlugify(url ?? "", {
122
194
  lower: true,
123
195
  remove: /[*+~.()'"!:@/#?]/g,
124
- })
125
- }
196
+ });
197
+ };
126
198
 
127
- const localePath = useLocalePath()
199
+ const localePath = useLocalePath();
128
200
 
129
201
  const getProductDetailRoute = (
130
202
  id: number,
131
203
  name?: string,
132
- locale?: Locale,
204
+ locale?: Locale
133
205
  ): string => {
134
206
  return localePath(
135
207
  {
136
- name: 'p-productName-id',
208
+ name: "p-productName-id",
137
209
  params: {
138
210
  productName: slugify(name),
139
211
  id: `${id}`,
140
212
  },
141
213
  },
142
- locale,
143
- )
144
- }
214
+ locale
215
+ );
216
+ };
145
217
  ```
146
218
 
147
219
  ## 8.59.1
@@ -302,39 +374,39 @@
302
374
 
303
375
  ```ts
304
376
  // server/plugins/session-plugin.ts
305
- import { hasSession } from '@scayle/storefront-nuxt'
306
- import { defineNitroPlugin } from '#imports'
377
+ import { hasSession } from "@scayle/storefront-nuxt";
378
+ import { defineNitroPlugin } from "#imports";
307
379
 
308
380
  export default defineNitroPlugin((nitroApp) => {
309
- nitroApp.hooks.hook('storefront:afterLogin', async (_data, context) => {
381
+ nitroApp.hooks.hook("storefront:afterLogin", async (_data, context) => {
310
382
  // Check if we actually have a RpcContext with proper session data
311
383
  if (!hasSession(context)) {
312
- return
384
+ return;
313
385
  }
314
386
 
315
387
  // Should you have set custom session data already in another hook,
316
388
  // it might be necessary to get existing data first.
317
- const sessionCustomData = context.sessionCustomData
389
+ const sessionCustomData = context.sessionCustomData;
318
390
 
319
391
  // The update functions overrides the customData object on a session.
320
392
  // Should you have set custom session data already in another hooks,
321
393
  // you need to pass it in addition to your new custom session data.
322
394
  context.updateSessionCustomData({
323
395
  ...sessionCustomData,
324
- yourCustomDataKey: 'Your Session CustomData Value',
325
- })
396
+ yourCustomDataKey: "Your Session CustomData Value",
397
+ });
326
398
 
327
399
  // Before accessing your session custom data, you might want to use an
328
400
  // explicit early return conditional.
329
401
  if (!sessionCustomData) {
330
- return
402
+ return;
331
403
  }
332
404
 
333
405
  // Your custom session data can also be accessedd directly via
334
406
  // nullish coalescing depending on your needs.
335
- console.log(context.sessionCustomData?.yourCustomDataKey)
336
- })
337
- })
407
+ console.log(context.sessionCustomData?.yourCustomDataKey);
408
+ });
409
+ });
338
410
  ```
339
411
 
340
412
  ### Patch Changes
@@ -394,20 +466,20 @@
394
466
 
395
467
  ```ts
396
468
  // Before
397
- const { data } = await useRpc('getProduct', 'my-static-product-key', {
469
+ const { data } = await useRpc("getProduct", "my-static-product-key", {
398
470
  productId: 123,
399
- })
471
+ });
400
472
 
401
473
  // After
402
- const productId = ref(123)
474
+ const productId = ref(123);
403
475
 
404
476
  // The key is now reactive. If `productId` changes, the key updates
405
477
  // to 'product-456' (for example) and triggers a new fetch.
406
478
  const { data } = await useRpc(
407
- 'getProduct',
479
+ "getProduct",
408
480
  () => `product-${productId.value}`,
409
- { productId },
410
- )
481
+ { productId }
482
+ );
411
483
  ```
412
484
 
413
485
  - Deprecated the `CheckoutEvent` type, which will be removed in the next major version.
@@ -419,22 +491,22 @@
419
491
  The type definition remains unchanged, so you can copy it directly:
420
492
 
421
493
  ```ts
422
- import type { ShopUser } from '@scayle/storefront-nuxt'
494
+ import type { ShopUser } from "@scayle/storefront-nuxt";
423
495
 
424
496
  export interface CheckoutEvent {
425
497
  /** Action. */
426
- action?: 'authenticated'
498
+ action?: "authenticated";
427
499
  /** Type. */
428
- type?: 'tracking'
500
+ type?: "tracking";
429
501
  /** User. */
430
- user: ShopUser
502
+ user: ShopUser;
431
503
  /**
432
504
  * The OAuth 2.0 access token for the authenticated user.
433
505
  * This token can be used to access protected resources on behalf of the user.
434
506
  *
435
507
  * @see https://www.rfc-editor.org/rfc/rfc6749
436
508
  */
437
- accessToken: string
509
+ accessToken: string;
438
510
  /**
439
511
  * Details about a specific event within the checkout process.
440
512
  * This field is optional and is only used when tracking specific actions
@@ -444,25 +516,25 @@
444
516
  */
445
517
  event?: {
446
518
  /** Event name. */
447
- event: 'login' | 'add_to_cart' | 'remove_from_cart'
519
+ event: "login" | "add_to_cart" | "remove_from_cart";
448
520
  /** Event status. */
449
- status: 'successful' | 'error'
450
- }
521
+ status: "successful" | "error";
522
+ };
451
523
  }
452
524
  ```
453
525
 
454
526
  - Updated the `StorefrontRuntimeConfig` type to ensure configured `shops` correctly incorporates all extended properties from `AdditionalShopConfig`.
455
527
 
456
528
  ```ts
457
- declare module '@scayle/storefront-nuxt' {
529
+ declare module "@scayle/storefront-nuxt" {
458
530
  // Extend the shop config
459
531
  export interface AdditionalShopConfig {
460
- extendedProp: string
532
+ extendedProp: string;
461
533
  }
462
534
  }
463
535
 
464
536
  // `extendedProp` is now properly typed
465
- useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp
537
+ useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp;
466
538
  ```
467
539
 
468
540
  **Dependencies**
@@ -482,11 +554,11 @@
482
554
  ```ts
483
555
  // Before (or when `rpcDefaultLazy: false`)
484
556
  // You had to explicitly opt-in to lazy behavior
485
- const { data } = useRpc('someMethod', { some: 'param' }, { lazy: true })
557
+ const { data } = useRpc("someMethod", { some: "param" }, { lazy: true });
486
558
 
487
559
  // After (when `rpcDefaultLazy: true`)
488
560
  // Lazy behavior is now the default
489
- const { data } = useRpc('someMethod', { some: 'param' })
561
+ const { data } = useRpc("someMethod", { some: "param" });
490
562
  ```
491
563
 
492
564
  **Dependencies**
@@ -598,10 +670,10 @@
598
670
  Example:
599
671
 
600
672
  ```ts
601
- import { sha256 } from '@scayle/storefront-core'
673
+ import { sha256 } from "@scayle/storefront-core";
602
674
 
603
- const hash = await sha256('hello')
604
- console.log(hash) // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
675
+ const hash = await sha256("hello");
676
+ console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
605
677
  ```
606
678
 
607
679
  ## 8.48.1
@@ -681,8 +753,8 @@
681
753
  customer: {
682
754
  groups: context.user?.groups,
683
755
  },
684
- }
685
- })
756
+ };
757
+ });
686
758
  ```
687
759
 
688
760
  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).
@@ -716,32 +788,32 @@
716
788
  #### Looking up by name (existing, now renamed):
717
789
 
718
790
  ```typescript
719
- import { getAttributeValuesByName } from '@scayle/storefront-core'
791
+ import { getAttributeValuesByName } from "@scayle/storefront-core";
720
792
 
721
793
  // Single-select attribute
722
- const sizes = getAttributeValuesByName(product.attributes, 'size')
794
+ const sizes = getAttributeValuesByName(product.attributes, "size");
723
795
  // Returns: [{ id: 1, label: 'M', value: 'medium' }]
724
796
 
725
797
  // Multi-select attribute
726
- const colors = getAttributeValuesByName(product.attributes, 'color')
798
+ const colors = getAttributeValuesByName(product.attributes, "color");
727
799
  // Returns: [{ id: 1, label: 'Red' }, { id: 2, label: 'Blue' }]
728
800
 
729
801
  // Non-existent attribute
730
- const missing = getAttributeValuesByName(product.attributes, 'doesNotExist')
802
+ const missing = getAttributeValuesByName(product.attributes, "doesNotExist");
731
803
  // Returns: []
732
804
  ```
733
805
 
734
806
  #### Looking up by group ID (new):
735
807
 
736
808
  ```typescript
737
- import { getAttributeValuesByGroupId } from '@scayle/storefront-core'
809
+ import { getAttributeValuesByGroupId } from "@scayle/storefront-core";
738
810
 
739
811
  // Look up attribute by its numeric ID from the SCAYLE API
740
- const promotionValues = getAttributeValuesByGroupId(product.attributes, 42)
812
+ const promotionValues = getAttributeValuesByGroupId(product.attributes, 42);
741
813
  // Returns: [{ id: 123, label: 'Summer Sale', value: 'summer-2024' }]
742
814
 
743
815
  // Non-existent attribute group
744
- const missing = getAttributeValuesByGroupId(product.attributes, 9999)
816
+ const missing = getAttributeValuesByGroupId(product.attributes, 9999);
745
817
  // Returns: []
746
818
  ```
747
819
 
@@ -804,27 +876,27 @@
804
876
  // nuxt.config.ts
805
877
  export default defineNuxtConfig({
806
878
  storefront: {
807
- apiBasePath: '/custom-api', // ✅ Configure globally for all shops
879
+ apiBasePath: "/custom-api", // ✅ Configure globally for all shops
808
880
  },
809
881
  runtimeConfig: {
810
882
  storefront: {
811
883
  shops: {
812
884
  1001: {
813
885
  shopId: 1001,
814
- path: 'de',
886
+ path: "de",
815
887
  // ✅ apiBasePath removed from shop config
816
888
  // ... other shop config
817
889
  },
818
890
  1002: {
819
891
  shopId: 1002,
820
- path: 'en',
892
+ path: "en",
821
893
  // ✅ apiBasePath removed from shop config
822
894
  // ... other shop config
823
895
  },
824
896
  },
825
897
  },
826
898
  },
827
- })
899
+ });
828
900
  ```
829
901
 
830
902
  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.
@@ -940,10 +1012,10 @@
940
1012
 
941
1013
  ```ts
942
1014
  const isComboDealType = (
943
- promotion?: Promotion | null,
1015
+ promotion?: Promotion | null
944
1016
  ): promotion is Promotion<ComboDealEffect> => {
945
- return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL
946
- }
1017
+ return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL;
1018
+ };
947
1019
  ```
948
1020
 
949
1021
  ## 8.42.2
@@ -1007,68 +1079,68 @@
1007
1079
  Before:
1008
1080
 
1009
1081
  ```ts
1010
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1011
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1082
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1083
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1012
1084
 
1013
1085
  updateBasketItemRpc({
1014
1086
  // ...
1015
- promotionId: 'promotionId',
1016
- promotionCode: 'promotionCode',
1017
- })
1087
+ promotionId: "promotionId",
1088
+ promotionCode: "promotionCode",
1089
+ });
1018
1090
 
1019
1091
  addItemToBasketRpc({
1020
1092
  // ...
1021
- promotionId: 'promotionId',
1022
- promotionCode: 'promotionCode',
1023
- })
1093
+ promotionId: "promotionId",
1094
+ promotionCode: "promotionCode",
1095
+ });
1024
1096
 
1025
1097
  // Or with useBasket composable
1026
1098
 
1027
- const { addItem } = useBasket()
1099
+ const { addItem } = useBasket();
1028
1100
  addItem({
1029
1101
  // ...
1030
- promotionId: 'promotionId',
1031
- })
1102
+ promotionId: "promotionId",
1103
+ });
1032
1104
  ```
1033
1105
 
1034
1106
  After:
1035
1107
 
1036
1108
  ```ts
1037
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1038
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1109
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1110
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1039
1111
 
1040
1112
  updateBasketItemRpc({
1041
1113
  // ...
1042
1114
  promotions: [
1043
- { id: 'promotionId', code: 'promotionCode' },
1115
+ { id: "promotionId", code: "promotionCode" },
1044
1116
  {
1045
- id: 'promotionId2',
1117
+ id: "promotionId2",
1046
1118
  },
1047
1119
  ],
1048
- })
1120
+ });
1049
1121
 
1050
1122
  addItemToBasketRpc({
1051
1123
  // ...
1052
1124
  promotions: [
1053
- { id: 'promotionId', code: 'promotionCode' },
1125
+ { id: "promotionId", code: "promotionCode" },
1054
1126
  {
1055
- id: 'promotionId2',
1127
+ id: "promotionId2",
1056
1128
  },
1057
1129
  ],
1058
- })
1130
+ });
1059
1131
 
1060
1132
  // Or for useBasket with composable
1061
1133
 
1062
- const { addItem } = useBasket()
1134
+ const { addItem } = useBasket();
1063
1135
  addItem({
1064
1136
  // ...
1065
1137
  promotions: [
1066
- { id: 'promotionId', code: 'promotionCode' },
1138
+ { id: "promotionId", code: "promotionCode" },
1067
1139
  {
1068
- id: 'promotionId2',
1140
+ id: "promotionId2",
1069
1141
  },
1070
1142
  ],
1071
- })
1143
+ });
1072
1144
  ```
1073
1145
 
1074
1146
  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.
@@ -1473,23 +1545,23 @@
1473
1545
  - 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.
1474
1546
 
1475
1547
  ```ts
1476
- const { data } = useRpc('getFilters', 'getFiltersKey', () => ({
1548
+ const { data } = useRpc("getFilters", "getFiltersKey", () => ({
1477
1549
  where: {
1478
1550
  minReduction: 10,
1479
1551
  maxReduction: 20,
1480
1552
  },
1481
- }))
1553
+ }));
1482
1554
 
1483
1555
  const { data } = useRpc(
1484
- 'getProductsByCategory',
1485
- 'getProductsByCategoryKey',
1556
+ "getProductsByCategory",
1557
+ "getProductsByCategoryKey",
1486
1558
  () => ({
1487
1559
  where: {
1488
1560
  minReduction: 10,
1489
1561
  maxReduction: 20,
1490
1562
  },
1491
- }),
1492
- )
1563
+ })
1564
+ );
1493
1565
  ```
1494
1566
 
1495
1567
  ## 8.30.3
@@ -1541,28 +1613,28 @@
1541
1613
 
1542
1614
  ```ts
1543
1615
  export const existingHandlerWithoutParams = async (_context: RpcContext) => {
1544
- return 'existing handler'
1545
- }
1616
+ return "existing handler";
1617
+ };
1546
1618
 
1547
1619
  export const existingHandlerWithParams = async (
1548
1620
  { name }: { name: string },
1549
- _context: RpcContext,
1621
+ _context: RpcContext
1550
1622
  ) => {
1551
- return name
1552
- }
1623
+ return name;
1624
+ };
1553
1625
 
1554
1626
  // will become
1555
1627
 
1556
1628
  export const existingHandlerWithoutParams = defineRpcHandler(
1557
1629
  async (_context: RpcContext) => {
1558
- return 'existing handler'
1559
- },
1560
- )
1630
+ return "existing handler";
1631
+ }
1632
+ );
1561
1633
  export const existingHandlerWithParams = defineRpcHandler(
1562
1634
  async ({ name }: { name: string }, _context: RpcContext) => {
1563
- return name
1564
- },
1565
- )
1635
+ return name;
1636
+ }
1637
+ );
1566
1638
  ```
1567
1639
 
1568
1640
  - Patch
@@ -1584,15 +1656,15 @@
1584
1656
  - 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.
1585
1657
 
1586
1658
  ```ts
1587
- import { rpcMethods } from '@scayle/storefront-core'
1659
+ import { rpcMethods } from "@scayle/storefront-core";
1588
1660
 
1589
- rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext)
1661
+ rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext);
1590
1662
  ```
1591
1663
 
1592
1664
  or
1593
1665
 
1594
1666
  ```ts
1595
- import { useCategoryTree } from '#storefront/composables'
1667
+ import { useCategoryTree } from "#storefront/composables";
1596
1668
 
1597
1669
  const { data: rootCategories, status } = useCategoryTree(
1598
1670
  {
@@ -1600,8 +1672,8 @@
1600
1672
  hideEmptyCategories: true,
1601
1673
  },
1602
1674
  },
1603
- 'category-navigation-tree',
1604
- )
1675
+ "category-navigation-tree"
1676
+ );
1605
1677
  ```
1606
1678
 
1607
1679
  ## 8.28.7
@@ -1698,9 +1770,9 @@
1698
1770
  params: {
1699
1771
  children: 10,
1700
1772
  includeHidden: true,
1701
- properties: { withName: ['sale'] },
1773
+ properties: { withName: ["sale"] },
1702
1774
  },
1703
- })
1775
+ });
1704
1776
  ```
1705
1777
 
1706
1778
  ### Patch Changes
@@ -1871,16 +1943,16 @@
1871
1943
  nitro: {
1872
1944
  storage: {
1873
1945
  redis: {
1874
- driver: 'redis',
1875
- host: 'localhost',
1946
+ driver: "redis",
1947
+ host: "localhost",
1876
1948
  },
1877
1949
  db: {
1878
- driver: 'fs',
1879
- base: './.data/db',
1950
+ driver: "fs",
1951
+ base: "./.data/db",
1880
1952
  },
1881
1953
  },
1882
1954
  },
1883
- })
1955
+ });
1884
1956
  ```
1885
1957
 
1886
1958
  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.
@@ -1953,9 +2025,9 @@
1953
2025
  ```typescript
1954
2026
  const idp = useIDP({
1955
2027
  authUrlParameters: {
1956
- theme: 'dark',
2028
+ theme: "dark",
1957
2029
  },
1958
- })
2030
+ });
1959
2031
  ```
1960
2032
 
1961
2033
  ### Patch Changes
@@ -2097,11 +2169,11 @@
2097
2169
  storefront: {
2098
2170
  redirects: {
2099
2171
  enabled: true,
2100
- strategy: 'on-missing',
2172
+ strategy: "on-missing",
2101
2173
  },
2102
2174
  },
2103
2175
  },
2104
- })
2176
+ });
2105
2177
  ```
2106
2178
 
2107
2179
  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.
@@ -2115,7 +2187,7 @@
2115
2187
  If the request handler returns a `Response` object with a `status` of 404, a 404 response will be returned to the client.
2116
2188
 
2117
2189
  ```typescript
2118
- return new Response(null, { status: 404 })
2190
+ return new Response(null, { status: 404 });
2119
2191
  ```
2120
2192
 
2121
2193
  3. Thrown H3Error with 404 status
@@ -2123,8 +2195,8 @@
2123
2195
  If the request handler throws an H3Error with a `statusCode` 404, a 404 response will be returned to the client.
2124
2196
 
2125
2197
  ```typescript
2126
- import { createError } from 'h3'
2127
- throw createError({ statusCode: 404 })
2198
+ import { createError } from "h3";
2199
+ throw createError({ statusCode: 404 });
2128
2200
  ```
2129
2201
 
2130
2202
  ### Patch Changes
@@ -2566,28 +2638,28 @@
2566
2638
  **rpc-methods.ts**
2567
2639
 
2568
2640
  ```typescript
2569
- import type { RpcContext, RpcHandler } from '@scayle/storefront-nuxt'
2641
+ import type { RpcContext, RpcHandler } from "@scayle/storefront-nuxt";
2570
2642
 
2571
2643
  export const foo: RpcHandler<string, number> = function testing(
2572
2644
  param: string,
2573
- _: RpcContext,
2645
+ _: RpcContext
2574
2646
  ) {
2575
- return param.length
2576
- }
2647
+ return param.length;
2648
+ };
2577
2649
  ```
2578
2650
 
2579
2651
  **module.ts**
2580
2652
 
2581
2653
  ```typescript
2582
2654
  function setup() {
2583
- const resolver = createResolver(import.meta.url)
2655
+ const resolver = createResolver(import.meta.url);
2584
2656
 
2585
- nuxt.hook('storefront:custom-rpc:extend', (customRpcImports) => {
2657
+ nuxt.hook("storefront:custom-rpc:extend", (customRpcImports) => {
2586
2658
  customRpcImports.push({
2587
- source: resolver.resolve('./rpc-methods.ts'),
2588
- names: ['foo'],
2589
- })
2590
- })
2659
+ source: resolver.resolve("./rpc-methods.ts"),
2660
+ names: ["foo"],
2661
+ });
2662
+ });
2591
2663
  }
2592
2664
  ```
2593
2665
 
@@ -2809,23 +2881,23 @@
2809
2881
  storefront: {
2810
2882
  // ...
2811
2883
  redis: {
2812
- host: 'localhost',
2884
+ host: "localhost",
2813
2885
  port: 6379,
2814
- prefix: '',
2815
- user: '',
2816
- password: '',
2886
+ prefix: "",
2887
+ user: "",
2888
+ password: "",
2817
2889
  sslTransit: false,
2818
2890
  },
2819
2891
  // ...
2820
2892
  session: {
2821
2893
  // ...
2822
- provider: 'redis',
2894
+ provider: "redis",
2823
2895
  },
2824
2896
  },
2825
2897
  // ...
2826
2898
  },
2827
2899
  // ...
2828
- })
2900
+ });
2829
2901
  ```
2830
2902
 
2831
2903
  - _Current Unified Storage Approach (`nuxt.config.ts`):_
@@ -2839,13 +2911,13 @@
2839
2911
  // ...
2840
2912
  storage: {
2841
2913
  cache: {
2842
- driver: 'redis',
2843
- host: 'localhost',
2914
+ driver: "redis",
2915
+ host: "localhost",
2844
2916
  port: 6379,
2845
2917
  },
2846
2918
  session: {
2847
- driver: 'redis',
2848
- host: 'localhost',
2919
+ driver: "redis",
2920
+ host: "localhost",
2849
2921
  port: 6379,
2850
2922
  },
2851
2923
  // ...
@@ -2855,7 +2927,7 @@
2855
2927
  // ...
2856
2928
  },
2857
2929
  // ...
2858
- })
2930
+ });
2859
2931
  ```
2860
2932
 
2861
2933
  - **\[💥 BREAKING\]** The composable `useSearch` has been replaced by `useStorefrontSearch`, consolidating and transitioning to SCAYLE Search v2.
@@ -2922,9 +2994,9 @@
2922
2994
 
2923
2995
  ```ts
2924
2996
  const { activeFilters, applyFilters, resetFilterUrl, productConditions } =
2925
- useQueryFilterState()
2997
+ useQueryFilterState();
2926
2998
 
2927
- applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 })
2999
+ applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 });
2928
3000
  ```
2929
3001
 
2930
3002
  - _Current Usage of `useFilter` and `useAppliedFilters`:_
@@ -2937,20 +3009,20 @@
2937
3009
  resetFilters,
2938
3010
  resetPriceFilter,
2939
3011
  resetFilter,
2940
- } = useFilter()
3012
+ } = useFilter();
2941
3013
 
2942
- applyPriceFilter([0, 100])
2943
- applyBooleanFilter('sale', true)
2944
- applyAttributeFilter('brand', 23)
3014
+ applyPriceFilter([0, 100]);
3015
+ applyBooleanFilter("sale", true);
3016
+ applyAttributeFilter("brand", 23);
2945
3017
 
2946
- const route = useRoute()
3018
+ const route = useRoute();
2947
3019
  const {
2948
3020
  appliedFilter,
2949
3021
  appliedFiltersCount,
2950
3022
  appliedAttributeValues,
2951
3023
  appliedBooleanValues,
2952
3024
  areFiltersApplied,
2953
- } = useAppliedFilters(route)
3025
+ } = useAppliedFilters(route);
2954
3026
  ```
2955
3027
 
2956
3028
  - **\[💥 BREAKING\]** The `getBadgeLabel` helper function has been removed, giving you more control over badge label display.
@@ -2960,43 +3032,43 @@
2960
3032
 
2961
3033
  ```ts
2962
3034
  const BadgeLabel = {
2963
- NEW: 'new',
2964
- SOLD_OUT: 'sold_out',
2965
- ONLINE_EXCLUSIVE: 'online_exclusive',
2966
- SUSTAINABLE: 'sustainable',
2967
- PREMIUM: 'premium',
2968
- DEFAULT: '',
2969
- } as const
3035
+ NEW: "new",
3036
+ SOLD_OUT: "sold_out",
3037
+ ONLINE_EXCLUSIVE: "online_exclusive",
3038
+ SUSTAINABLE: "sustainable",
3039
+ PREMIUM: "premium",
3040
+ DEFAULT: "",
3041
+ } as const;
2970
3042
 
2971
3043
  type BadgeLabelParamsKeys =
2972
- | 'isNew'
2973
- | 'isSoldOut'
2974
- | 'isOnlineOnly'
2975
- | 'isSustainable'
2976
- | 'isPremium'
2977
- type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>
3044
+ | "isNew"
3045
+ | "isSoldOut"
3046
+ | "isOnlineOnly"
3047
+ | "isSustainable"
3048
+ | "isPremium";
3049
+ type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>;
2978
3050
 
2979
3051
  const getBadgeLabel = (params: BadgeLabelParams = {}): string => {
2980
3052
  if (!params) {
2981
- return BadgeLabel.DEFAULT
3053
+ return BadgeLabel.DEFAULT;
2982
3054
  }
2983
3055
  const { isNew, isSoldOut, isOnlineOnly, isSustainable, isPremium } =
2984
- params
3056
+ params;
2985
3057
 
2986
3058
  if (isNew) {
2987
- return BadgeLabel.NEW
3059
+ return BadgeLabel.NEW;
2988
3060
  } else if (isSoldOut) {
2989
- return BadgeLabel.SOLD_OUT
3061
+ return BadgeLabel.SOLD_OUT;
2990
3062
  } else if (isOnlineOnly) {
2991
- return BadgeLabel.ONLINE_EXCLUSIVE
3063
+ return BadgeLabel.ONLINE_EXCLUSIVE;
2992
3064
  } else if (isSustainable) {
2993
- return BadgeLabel.SUSTAINABLE
3065
+ return BadgeLabel.SUSTAINABLE;
2994
3066
  } else if (isPremium) {
2995
- return BadgeLabel.PREMIUM
3067
+ return BadgeLabel.PREMIUM;
2996
3068
  } else {
2997
- return BadgeLabel.DEFAULT
3069
+ return BadgeLabel.DEFAULT;
2998
3070
  }
2999
- }
3071
+ };
3000
3072
  ```
3001
3073
 
3002
3074
  - **\[💥 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.
@@ -3020,7 +3092,7 @@
3020
3092
  // ...
3021
3093
  },
3022
3094
  // ...
3023
- })
3095
+ });
3024
3096
  ```
3025
3097
 
3026
3098
  - _Previous Environment Variables for Store Configuration:_
@@ -3049,7 +3121,7 @@
3049
3121
  // ...
3050
3122
  },
3051
3123
  // ...
3052
- })
3124
+ });
3053
3125
  ```
3054
3126
 
3055
3127
  - _Current Environment Variables for Shops Configuration:_
@@ -3069,8 +3141,8 @@
3069
3141
  ```ts
3070
3142
  useProduct({
3071
3143
  // ...
3072
- key: 'productKey',
3073
- })
3144
+ key: "productKey",
3145
+ });
3074
3146
  ```
3075
3147
 
3076
3148
  - _Current `key` as dedicated composables argument:_
@@ -3080,8 +3152,8 @@
3080
3152
  {
3081
3153
  // ...
3082
3154
  },
3083
- 'productKey',
3084
- )
3155
+ "productKey"
3156
+ );
3085
3157
  ```
3086
3158
 
3087
3159
  - **\[💥 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.
@@ -3098,27 +3170,27 @@
3098
3170
  - _Previous Usage of `handleIDPLoginCallback`:_
3099
3171
 
3100
3172
  ```ts
3101
- const { handleIDPLoginCallback } = await useIDP()
3173
+ const { handleIDPLoginCallback } = await useIDP();
3102
3174
 
3103
3175
  watch(
3104
3176
  () => route.query,
3105
3177
  async (query) => {
3106
3178
  if (query.code && isString(query.code)) {
3107
- await handleIDPLoginCallback(query.code)
3179
+ await handleIDPLoginCallback(query.code);
3108
3180
  }
3109
3181
  },
3110
- { immediate: true },
3111
- )
3182
+ { immediate: true }
3183
+ );
3112
3184
  ```
3113
3185
 
3114
3186
  - _Current Usage of `loginIDP`:_
3115
3187
 
3116
3188
  ```ts
3117
- const { loginIDP } = useAuthentication('login')
3189
+ const { loginIDP } = useAuthentication("login");
3118
3190
 
3119
3191
  onMounted(async () => {
3120
- await loginIDP(props.code)
3121
- })
3192
+ await loginIDP(props.code);
3193
+ });
3122
3194
  ```
3123
3195
 
3124
3196
  - **\[🧹 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.
@@ -3128,17 +3200,17 @@
3128
3200
  - _Previous `useRpc` with `autoFetch`:_
3129
3201
 
3130
3202
  ```ts
3131
- useRpc('rpcMethod', key, params, { autoFetch: true })
3203
+ useRpc("rpcMethod", key, params, { autoFetch: true });
3132
3204
 
3133
- useUser({ autoFetch: true })
3205
+ useUser({ autoFetch: true });
3134
3206
  ```
3135
3207
 
3136
3208
  - _Current `useRpc` with `immediate`:_
3137
3209
 
3138
3210
  ```ts
3139
- useRpc('rpcMethod', key, params, { immediate: true })
3211
+ useRpc("rpcMethod", key, params, { immediate: true });
3140
3212
 
3141
- useUser({ immediate: true })
3213
+ useUser({ immediate: true });
3142
3214
  ```
3143
3215
 
3144
3216
  - **\[💥 BREAKING\]** The attribute `isCmsPreview` has been removed from `RpcContext`.
@@ -3158,18 +3230,18 @@
3158
3230
  getSearchSuggestions,
3159
3231
  fetching,
3160
3232
  ...searchData
3161
- } = useStorefrontSearch(searchQuery, { key })
3233
+ } = useStorefrontSearch(searchQuery, { key });
3162
3234
 
3163
- fetching.value // true or false
3235
+ fetching.value; // true or false
3164
3236
  ```
3165
3237
 
3166
3238
  - _Current `useStorefrontSearch` returning `status`:_
3167
3239
 
3168
3240
  ```ts
3169
3241
  const { data, resolveSearch, getSearchSuggestions, status, ...searchData } =
3170
- useStorefrontSearch(searchQuery, {}, key)
3242
+ useStorefrontSearch(searchQuery, {}, key);
3171
3243
 
3172
- status.value // 'idle', 'pending', 'error' or 'success'
3244
+ status.value; // 'idle', 'pending', 'error' or 'success'
3173
3245
  ```
3174
3246
 
3175
3247
  - **\[💥 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.
@@ -3194,7 +3266,7 @@
3194
3266
  // ...
3195
3267
  },
3196
3268
  // ...
3197
- })
3269
+ });
3198
3270
  ```
3199
3271
 
3200
3272
  - _Current `enableDefaultGetCachedDataOverride`in `nuxt.config.ts`:_
@@ -3219,7 +3291,7 @@
3219
3291
  // ...
3220
3292
  },
3221
3293
  // ...
3222
- })
3294
+ });
3223
3295
  ```
3224
3296
 
3225
3297
  - **\[💥 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).
@@ -3241,7 +3313,7 @@
3241
3313
  function myCustomRpc() {
3242
3314
  // ...
3243
3315
 
3244
- throw new BaseError(404)
3316
+ throw new BaseError(404);
3245
3317
  }
3246
3318
  ```
3247
3319
 
@@ -3251,7 +3323,7 @@
3251
3323
  function myCustomRpc() {
3252
3324
  // ...
3253
3325
 
3254
- return new Response(null, { status: 404 })
3326
+ return new Response(null, { status: 404 });
3255
3327
  }
3256
3328
  ```
3257
3329