@scayle/storefront-nuxt 8.60.1 → 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,64 @@
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
+
3
62
  ## 8.60.1
4
63
 
5
64
  ### Patch Changes
@@ -115,33 +174,33 @@
115
174
  **Migration:**
116
175
 
117
176
  ```ts
118
- import baseSlugify from 'slugify'
177
+ import baseSlugify from "slugify";
119
178
 
120
179
  const slugify = (url: string | undefined): string => {
121
- return baseSlugify(url ?? '', {
180
+ return baseSlugify(url ?? "", {
122
181
  lower: true,
123
182
  remove: /[*+~.()'"!:@/#?]/g,
124
- })
125
- }
183
+ });
184
+ };
126
185
 
127
- const localePath = useLocalePath()
186
+ const localePath = useLocalePath();
128
187
 
129
188
  const getProductDetailRoute = (
130
189
  id: number,
131
190
  name?: string,
132
- locale?: Locale,
191
+ locale?: Locale
133
192
  ): string => {
134
193
  return localePath(
135
194
  {
136
- name: 'p-productName-id',
195
+ name: "p-productName-id",
137
196
  params: {
138
197
  productName: slugify(name),
139
198
  id: `${id}`,
140
199
  },
141
200
  },
142
- locale,
143
- )
144
- }
201
+ locale
202
+ );
203
+ };
145
204
  ```
146
205
 
147
206
  ## 8.59.1
@@ -302,39 +361,39 @@
302
361
 
303
362
  ```ts
304
363
  // server/plugins/session-plugin.ts
305
- import { hasSession } from '@scayle/storefront-nuxt'
306
- import { defineNitroPlugin } from '#imports'
364
+ import { hasSession } from "@scayle/storefront-nuxt";
365
+ import { defineNitroPlugin } from "#imports";
307
366
 
308
367
  export default defineNitroPlugin((nitroApp) => {
309
- nitroApp.hooks.hook('storefront:afterLogin', async (_data, context) => {
368
+ nitroApp.hooks.hook("storefront:afterLogin", async (_data, context) => {
310
369
  // Check if we actually have a RpcContext with proper session data
311
370
  if (!hasSession(context)) {
312
- return
371
+ return;
313
372
  }
314
373
 
315
374
  // Should you have set custom session data already in another hook,
316
375
  // it might be necessary to get existing data first.
317
- const sessionCustomData = context.sessionCustomData
376
+ const sessionCustomData = context.sessionCustomData;
318
377
 
319
378
  // The update functions overrides the customData object on a session.
320
379
  // Should you have set custom session data already in another hooks,
321
380
  // you need to pass it in addition to your new custom session data.
322
381
  context.updateSessionCustomData({
323
382
  ...sessionCustomData,
324
- yourCustomDataKey: 'Your Session CustomData Value',
325
- })
383
+ yourCustomDataKey: "Your Session CustomData Value",
384
+ });
326
385
 
327
386
  // Before accessing your session custom data, you might want to use an
328
387
  // explicit early return conditional.
329
388
  if (!sessionCustomData) {
330
- return
389
+ return;
331
390
  }
332
391
 
333
392
  // Your custom session data can also be accessedd directly via
334
393
  // nullish coalescing depending on your needs.
335
- console.log(context.sessionCustomData?.yourCustomDataKey)
336
- })
337
- })
394
+ console.log(context.sessionCustomData?.yourCustomDataKey);
395
+ });
396
+ });
338
397
  ```
339
398
 
340
399
  ### Patch Changes
@@ -394,20 +453,20 @@
394
453
 
395
454
  ```ts
396
455
  // Before
397
- const { data } = await useRpc('getProduct', 'my-static-product-key', {
456
+ const { data } = await useRpc("getProduct", "my-static-product-key", {
398
457
  productId: 123,
399
- })
458
+ });
400
459
 
401
460
  // After
402
- const productId = ref(123)
461
+ const productId = ref(123);
403
462
 
404
463
  // The key is now reactive. If `productId` changes, the key updates
405
464
  // to 'product-456' (for example) and triggers a new fetch.
406
465
  const { data } = await useRpc(
407
- 'getProduct',
466
+ "getProduct",
408
467
  () => `product-${productId.value}`,
409
- { productId },
410
- )
468
+ { productId }
469
+ );
411
470
  ```
412
471
 
413
472
  - Deprecated the `CheckoutEvent` type, which will be removed in the next major version.
@@ -419,22 +478,22 @@
419
478
  The type definition remains unchanged, so you can copy it directly:
420
479
 
421
480
  ```ts
422
- import type { ShopUser } from '@scayle/storefront-nuxt'
481
+ import type { ShopUser } from "@scayle/storefront-nuxt";
423
482
 
424
483
  export interface CheckoutEvent {
425
484
  /** Action. */
426
- action?: 'authenticated'
485
+ action?: "authenticated";
427
486
  /** Type. */
428
- type?: 'tracking'
487
+ type?: "tracking";
429
488
  /** User. */
430
- user: ShopUser
489
+ user: ShopUser;
431
490
  /**
432
491
  * The OAuth 2.0 access token for the authenticated user.
433
492
  * This token can be used to access protected resources on behalf of the user.
434
493
  *
435
494
  * @see https://www.rfc-editor.org/rfc/rfc6749
436
495
  */
437
- accessToken: string
496
+ accessToken: string;
438
497
  /**
439
498
  * Details about a specific event within the checkout process.
440
499
  * This field is optional and is only used when tracking specific actions
@@ -444,25 +503,25 @@
444
503
  */
445
504
  event?: {
446
505
  /** Event name. */
447
- event: 'login' | 'add_to_cart' | 'remove_from_cart'
506
+ event: "login" | "add_to_cart" | "remove_from_cart";
448
507
  /** Event status. */
449
- status: 'successful' | 'error'
450
- }
508
+ status: "successful" | "error";
509
+ };
451
510
  }
452
511
  ```
453
512
 
454
513
  - Updated the `StorefrontRuntimeConfig` type to ensure configured `shops` correctly incorporates all extended properties from `AdditionalShopConfig`.
455
514
 
456
515
  ```ts
457
- declare module '@scayle/storefront-nuxt' {
516
+ declare module "@scayle/storefront-nuxt" {
458
517
  // Extend the shop config
459
518
  export interface AdditionalShopConfig {
460
- extendedProp: string
519
+ extendedProp: string;
461
520
  }
462
521
  }
463
522
 
464
523
  // `extendedProp` is now properly typed
465
- useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp
524
+ useRuntimeConfig().storefront.shops?.[shopId]?.extendedProp;
466
525
  ```
467
526
 
468
527
  **Dependencies**
@@ -482,11 +541,11 @@
482
541
  ```ts
483
542
  // Before (or when `rpcDefaultLazy: false`)
484
543
  // You had to explicitly opt-in to lazy behavior
485
- const { data } = useRpc('someMethod', { some: 'param' }, { lazy: true })
544
+ const { data } = useRpc("someMethod", { some: "param" }, { lazy: true });
486
545
 
487
546
  // After (when `rpcDefaultLazy: true`)
488
547
  // Lazy behavior is now the default
489
- const { data } = useRpc('someMethod', { some: 'param' })
548
+ const { data } = useRpc("someMethod", { some: "param" });
490
549
  ```
491
550
 
492
551
  **Dependencies**
@@ -598,10 +657,10 @@
598
657
  Example:
599
658
 
600
659
  ```ts
601
- import { sha256 } from '@scayle/storefront-core'
660
+ import { sha256 } from "@scayle/storefront-core";
602
661
 
603
- const hash = await sha256('hello')
604
- console.log(hash) // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
662
+ const hash = await sha256("hello");
663
+ console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
605
664
  ```
606
665
 
607
666
  ## 8.48.1
@@ -681,8 +740,8 @@
681
740
  customer: {
682
741
  groups: context.user?.groups,
683
742
  },
684
- }
685
- })
743
+ };
744
+ });
686
745
  ```
687
746
 
688
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).
@@ -716,32 +775,32 @@
716
775
  #### Looking up by name (existing, now renamed):
717
776
 
718
777
  ```typescript
719
- import { getAttributeValuesByName } from '@scayle/storefront-core'
778
+ import { getAttributeValuesByName } from "@scayle/storefront-core";
720
779
 
721
780
  // Single-select attribute
722
- const sizes = getAttributeValuesByName(product.attributes, 'size')
781
+ const sizes = getAttributeValuesByName(product.attributes, "size");
723
782
  // Returns: [{ id: 1, label: 'M', value: 'medium' }]
724
783
 
725
784
  // Multi-select attribute
726
- const colors = getAttributeValuesByName(product.attributes, 'color')
785
+ const colors = getAttributeValuesByName(product.attributes, "color");
727
786
  // Returns: [{ id: 1, label: 'Red' }, { id: 2, label: 'Blue' }]
728
787
 
729
788
  // Non-existent attribute
730
- const missing = getAttributeValuesByName(product.attributes, 'doesNotExist')
789
+ const missing = getAttributeValuesByName(product.attributes, "doesNotExist");
731
790
  // Returns: []
732
791
  ```
733
792
 
734
793
  #### Looking up by group ID (new):
735
794
 
736
795
  ```typescript
737
- import { getAttributeValuesByGroupId } from '@scayle/storefront-core'
796
+ import { getAttributeValuesByGroupId } from "@scayle/storefront-core";
738
797
 
739
798
  // Look up attribute by its numeric ID from the SCAYLE API
740
- const promotionValues = getAttributeValuesByGroupId(product.attributes, 42)
799
+ const promotionValues = getAttributeValuesByGroupId(product.attributes, 42);
741
800
  // Returns: [{ id: 123, label: 'Summer Sale', value: 'summer-2024' }]
742
801
 
743
802
  // Non-existent attribute group
744
- const missing = getAttributeValuesByGroupId(product.attributes, 9999)
803
+ const missing = getAttributeValuesByGroupId(product.attributes, 9999);
745
804
  // Returns: []
746
805
  ```
747
806
 
@@ -804,27 +863,27 @@
804
863
  // nuxt.config.ts
805
864
  export default defineNuxtConfig({
806
865
  storefront: {
807
- apiBasePath: '/custom-api', // ✅ Configure globally for all shops
866
+ apiBasePath: "/custom-api", // ✅ Configure globally for all shops
808
867
  },
809
868
  runtimeConfig: {
810
869
  storefront: {
811
870
  shops: {
812
871
  1001: {
813
872
  shopId: 1001,
814
- path: 'de',
873
+ path: "de",
815
874
  // ✅ apiBasePath removed from shop config
816
875
  // ... other shop config
817
876
  },
818
877
  1002: {
819
878
  shopId: 1002,
820
- path: 'en',
879
+ path: "en",
821
880
  // ✅ apiBasePath removed from shop config
822
881
  // ... other shop config
823
882
  },
824
883
  },
825
884
  },
826
885
  },
827
- })
886
+ });
828
887
  ```
829
888
 
830
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.
@@ -940,10 +999,10 @@
940
999
 
941
1000
  ```ts
942
1001
  const isComboDealType = (
943
- promotion?: Promotion | null,
1002
+ promotion?: Promotion | null
944
1003
  ): promotion is Promotion<ComboDealEffect> => {
945
- return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL
946
- }
1004
+ return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL;
1005
+ };
947
1006
  ```
948
1007
 
949
1008
  ## 8.42.2
@@ -1007,68 +1066,68 @@
1007
1066
  Before:
1008
1067
 
1009
1068
  ```ts
1010
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1011
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1069
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1070
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1012
1071
 
1013
1072
  updateBasketItemRpc({
1014
1073
  // ...
1015
- promotionId: 'promotionId',
1016
- promotionCode: 'promotionCode',
1017
- })
1074
+ promotionId: "promotionId",
1075
+ promotionCode: "promotionCode",
1076
+ });
1018
1077
 
1019
1078
  addItemToBasketRpc({
1020
1079
  // ...
1021
- promotionId: 'promotionId',
1022
- promotionCode: 'promotionCode',
1023
- })
1080
+ promotionId: "promotionId",
1081
+ promotionCode: "promotionCode",
1082
+ });
1024
1083
 
1025
1084
  // Or with useBasket composable
1026
1085
 
1027
- const { addItem } = useBasket()
1086
+ const { addItem } = useBasket();
1028
1087
  addItem({
1029
1088
  // ...
1030
- promotionId: 'promotionId',
1031
- })
1089
+ promotionId: "promotionId",
1090
+ });
1032
1091
  ```
1033
1092
 
1034
1093
  After:
1035
1094
 
1036
1095
  ```ts
1037
- const updateBasketItemRpc = useRpcCall('updateBasketItem')
1038
- const addItemToBasketRpc = useRpcCall('addItemToBasket')
1096
+ const updateBasketItemRpc = useRpcCall("updateBasketItem");
1097
+ const addItemToBasketRpc = useRpcCall("addItemToBasket");
1039
1098
 
1040
1099
  updateBasketItemRpc({
1041
1100
  // ...
1042
1101
  promotions: [
1043
- { id: 'promotionId', code: 'promotionCode' },
1102
+ { id: "promotionId", code: "promotionCode" },
1044
1103
  {
1045
- id: 'promotionId2',
1104
+ id: "promotionId2",
1046
1105
  },
1047
1106
  ],
1048
- })
1107
+ });
1049
1108
 
1050
1109
  addItemToBasketRpc({
1051
1110
  // ...
1052
1111
  promotions: [
1053
- { id: 'promotionId', code: 'promotionCode' },
1112
+ { id: "promotionId", code: "promotionCode" },
1054
1113
  {
1055
- id: 'promotionId2',
1114
+ id: "promotionId2",
1056
1115
  },
1057
1116
  ],
1058
- })
1117
+ });
1059
1118
 
1060
1119
  // Or for useBasket with composable
1061
1120
 
1062
- const { addItem } = useBasket()
1121
+ const { addItem } = useBasket();
1063
1122
  addItem({
1064
1123
  // ...
1065
1124
  promotions: [
1066
- { id: 'promotionId', code: 'promotionCode' },
1125
+ { id: "promotionId", code: "promotionCode" },
1067
1126
  {
1068
- id: 'promotionId2',
1127
+ id: "promotionId2",
1069
1128
  },
1070
1129
  ],
1071
- })
1130
+ });
1072
1131
  ```
1073
1132
 
1074
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.
@@ -1473,23 +1532,23 @@
1473
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.
1474
1533
 
1475
1534
  ```ts
1476
- const { data } = useRpc('getFilters', 'getFiltersKey', () => ({
1535
+ const { data } = useRpc("getFilters", "getFiltersKey", () => ({
1477
1536
  where: {
1478
1537
  minReduction: 10,
1479
1538
  maxReduction: 20,
1480
1539
  },
1481
- }))
1540
+ }));
1482
1541
 
1483
1542
  const { data } = useRpc(
1484
- 'getProductsByCategory',
1485
- 'getProductsByCategoryKey',
1543
+ "getProductsByCategory",
1544
+ "getProductsByCategoryKey",
1486
1545
  () => ({
1487
1546
  where: {
1488
1547
  minReduction: 10,
1489
1548
  maxReduction: 20,
1490
1549
  },
1491
- }),
1492
- )
1550
+ })
1551
+ );
1493
1552
  ```
1494
1553
 
1495
1554
  ## 8.30.3
@@ -1541,28 +1600,28 @@
1541
1600
 
1542
1601
  ```ts
1543
1602
  export const existingHandlerWithoutParams = async (_context: RpcContext) => {
1544
- return 'existing handler'
1545
- }
1603
+ return "existing handler";
1604
+ };
1546
1605
 
1547
1606
  export const existingHandlerWithParams = async (
1548
1607
  { name }: { name: string },
1549
- _context: RpcContext,
1608
+ _context: RpcContext
1550
1609
  ) => {
1551
- return name
1552
- }
1610
+ return name;
1611
+ };
1553
1612
 
1554
1613
  // will become
1555
1614
 
1556
1615
  export const existingHandlerWithoutParams = defineRpcHandler(
1557
1616
  async (_context: RpcContext) => {
1558
- return 'existing handler'
1559
- },
1560
- )
1617
+ return "existing handler";
1618
+ }
1619
+ );
1561
1620
  export const existingHandlerWithParams = defineRpcHandler(
1562
1621
  async ({ name }: { name: string }, _context: RpcContext) => {
1563
- return name
1564
- },
1565
- )
1622
+ return name;
1623
+ }
1624
+ );
1566
1625
  ```
1567
1626
 
1568
1627
  - Patch
@@ -1584,15 +1643,15 @@
1584
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.
1585
1644
 
1586
1645
  ```ts
1587
- import { rpcMethods } from '@scayle/storefront-core'
1646
+ import { rpcMethods } from "@scayle/storefront-core";
1588
1647
 
1589
- rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext)
1648
+ rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext);
1590
1649
  ```
1591
1650
 
1592
1651
  or
1593
1652
 
1594
1653
  ```ts
1595
- import { useCategoryTree } from '#storefront/composables'
1654
+ import { useCategoryTree } from "#storefront/composables";
1596
1655
 
1597
1656
  const { data: rootCategories, status } = useCategoryTree(
1598
1657
  {
@@ -1600,8 +1659,8 @@
1600
1659
  hideEmptyCategories: true,
1601
1660
  },
1602
1661
  },
1603
- 'category-navigation-tree',
1604
- )
1662
+ "category-navigation-tree"
1663
+ );
1605
1664
  ```
1606
1665
 
1607
1666
  ## 8.28.7
@@ -1698,9 +1757,9 @@
1698
1757
  params: {
1699
1758
  children: 10,
1700
1759
  includeHidden: true,
1701
- properties: { withName: ['sale'] },
1760
+ properties: { withName: ["sale"] },
1702
1761
  },
1703
- })
1762
+ });
1704
1763
  ```
1705
1764
 
1706
1765
  ### Patch Changes
@@ -1871,16 +1930,16 @@
1871
1930
  nitro: {
1872
1931
  storage: {
1873
1932
  redis: {
1874
- driver: 'redis',
1875
- host: 'localhost',
1933
+ driver: "redis",
1934
+ host: "localhost",
1876
1935
  },
1877
1936
  db: {
1878
- driver: 'fs',
1879
- base: './.data/db',
1937
+ driver: "fs",
1938
+ base: "./.data/db",
1880
1939
  },
1881
1940
  },
1882
1941
  },
1883
- })
1942
+ });
1884
1943
  ```
1885
1944
 
1886
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.
@@ -1953,9 +2012,9 @@
1953
2012
  ```typescript
1954
2013
  const idp = useIDP({
1955
2014
  authUrlParameters: {
1956
- theme: 'dark',
2015
+ theme: "dark",
1957
2016
  },
1958
- })
2017
+ });
1959
2018
  ```
1960
2019
 
1961
2020
  ### Patch Changes
@@ -2097,11 +2156,11 @@
2097
2156
  storefront: {
2098
2157
  redirects: {
2099
2158
  enabled: true,
2100
- strategy: 'on-missing',
2159
+ strategy: "on-missing",
2101
2160
  },
2102
2161
  },
2103
2162
  },
2104
- })
2163
+ });
2105
2164
  ```
2106
2165
 
2107
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.
@@ -2115,7 +2174,7 @@
2115
2174
  If the request handler returns a `Response` object with a `status` of 404, a 404 response will be returned to the client.
2116
2175
 
2117
2176
  ```typescript
2118
- return new Response(null, { status: 404 })
2177
+ return new Response(null, { status: 404 });
2119
2178
  ```
2120
2179
 
2121
2180
  3. Thrown H3Error with 404 status
@@ -2123,8 +2182,8 @@
2123
2182
  If the request handler throws an H3Error with a `statusCode` 404, a 404 response will be returned to the client.
2124
2183
 
2125
2184
  ```typescript
2126
- import { createError } from 'h3'
2127
- throw createError({ statusCode: 404 })
2185
+ import { createError } from "h3";
2186
+ throw createError({ statusCode: 404 });
2128
2187
  ```
2129
2188
 
2130
2189
  ### Patch Changes
@@ -2566,28 +2625,28 @@
2566
2625
  **rpc-methods.ts**
2567
2626
 
2568
2627
  ```typescript
2569
- import type { RpcContext, RpcHandler } from '@scayle/storefront-nuxt'
2628
+ import type { RpcContext, RpcHandler } from "@scayle/storefront-nuxt";
2570
2629
 
2571
2630
  export const foo: RpcHandler<string, number> = function testing(
2572
2631
  param: string,
2573
- _: RpcContext,
2632
+ _: RpcContext
2574
2633
  ) {
2575
- return param.length
2576
- }
2634
+ return param.length;
2635
+ };
2577
2636
  ```
2578
2637
 
2579
2638
  **module.ts**
2580
2639
 
2581
2640
  ```typescript
2582
2641
  function setup() {
2583
- const resolver = createResolver(import.meta.url)
2642
+ const resolver = createResolver(import.meta.url);
2584
2643
 
2585
- nuxt.hook('storefront:custom-rpc:extend', (customRpcImports) => {
2644
+ nuxt.hook("storefront:custom-rpc:extend", (customRpcImports) => {
2586
2645
  customRpcImports.push({
2587
- source: resolver.resolve('./rpc-methods.ts'),
2588
- names: ['foo'],
2589
- })
2590
- })
2646
+ source: resolver.resolve("./rpc-methods.ts"),
2647
+ names: ["foo"],
2648
+ });
2649
+ });
2591
2650
  }
2592
2651
  ```
2593
2652
 
@@ -2809,23 +2868,23 @@
2809
2868
  storefront: {
2810
2869
  // ...
2811
2870
  redis: {
2812
- host: 'localhost',
2871
+ host: "localhost",
2813
2872
  port: 6379,
2814
- prefix: '',
2815
- user: '',
2816
- password: '',
2873
+ prefix: "",
2874
+ user: "",
2875
+ password: "",
2817
2876
  sslTransit: false,
2818
2877
  },
2819
2878
  // ...
2820
2879
  session: {
2821
2880
  // ...
2822
- provider: 'redis',
2881
+ provider: "redis",
2823
2882
  },
2824
2883
  },
2825
2884
  // ...
2826
2885
  },
2827
2886
  // ...
2828
- })
2887
+ });
2829
2888
  ```
2830
2889
 
2831
2890
  - _Current Unified Storage Approach (`nuxt.config.ts`):_
@@ -2839,13 +2898,13 @@
2839
2898
  // ...
2840
2899
  storage: {
2841
2900
  cache: {
2842
- driver: 'redis',
2843
- host: 'localhost',
2901
+ driver: "redis",
2902
+ host: "localhost",
2844
2903
  port: 6379,
2845
2904
  },
2846
2905
  session: {
2847
- driver: 'redis',
2848
- host: 'localhost',
2906
+ driver: "redis",
2907
+ host: "localhost",
2849
2908
  port: 6379,
2850
2909
  },
2851
2910
  // ...
@@ -2855,7 +2914,7 @@
2855
2914
  // ...
2856
2915
  },
2857
2916
  // ...
2858
- })
2917
+ });
2859
2918
  ```
2860
2919
 
2861
2920
  - **\[💥 BREAKING\]** The composable `useSearch` has been replaced by `useStorefrontSearch`, consolidating and transitioning to SCAYLE Search v2.
@@ -2922,9 +2981,9 @@
2922
2981
 
2923
2982
  ```ts
2924
2983
  const { activeFilters, applyFilters, resetFilterUrl, productConditions } =
2925
- useQueryFilterState()
2984
+ useQueryFilterState();
2926
2985
 
2927
- applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 })
2986
+ applyFilters({ brand: 23, sale: true, maxPrice: 100, minPrice: 0 });
2928
2987
  ```
2929
2988
 
2930
2989
  - _Current Usage of `useFilter` and `useAppliedFilters`:_
@@ -2937,20 +2996,20 @@
2937
2996
  resetFilters,
2938
2997
  resetPriceFilter,
2939
2998
  resetFilter,
2940
- } = useFilter()
2999
+ } = useFilter();
2941
3000
 
2942
- applyPriceFilter([0, 100])
2943
- applyBooleanFilter('sale', true)
2944
- applyAttributeFilter('brand', 23)
3001
+ applyPriceFilter([0, 100]);
3002
+ applyBooleanFilter("sale", true);
3003
+ applyAttributeFilter("brand", 23);
2945
3004
 
2946
- const route = useRoute()
3005
+ const route = useRoute();
2947
3006
  const {
2948
3007
  appliedFilter,
2949
3008
  appliedFiltersCount,
2950
3009
  appliedAttributeValues,
2951
3010
  appliedBooleanValues,
2952
3011
  areFiltersApplied,
2953
- } = useAppliedFilters(route)
3012
+ } = useAppliedFilters(route);
2954
3013
  ```
2955
3014
 
2956
3015
  - **\[💥 BREAKING\]** The `getBadgeLabel` helper function has been removed, giving you more control over badge label display.
@@ -2960,43 +3019,43 @@
2960
3019
 
2961
3020
  ```ts
2962
3021
  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
3022
+ NEW: "new",
3023
+ SOLD_OUT: "sold_out",
3024
+ ONLINE_EXCLUSIVE: "online_exclusive",
3025
+ SUSTAINABLE: "sustainable",
3026
+ PREMIUM: "premium",
3027
+ DEFAULT: "",
3028
+ } as const;
2970
3029
 
2971
3030
  type BadgeLabelParamsKeys =
2972
- | 'isNew'
2973
- | 'isSoldOut'
2974
- | 'isOnlineOnly'
2975
- | 'isSustainable'
2976
- | 'isPremium'
2977
- type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>
3031
+ | "isNew"
3032
+ | "isSoldOut"
3033
+ | "isOnlineOnly"
3034
+ | "isSustainable"
3035
+ | "isPremium";
3036
+ type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>;
2978
3037
 
2979
3038
  const getBadgeLabel = (params: BadgeLabelParams = {}): string => {
2980
3039
  if (!params) {
2981
- return BadgeLabel.DEFAULT
3040
+ return BadgeLabel.DEFAULT;
2982
3041
  }
2983
3042
  const { isNew, isSoldOut, isOnlineOnly, isSustainable, isPremium } =
2984
- params
3043
+ params;
2985
3044
 
2986
3045
  if (isNew) {
2987
- return BadgeLabel.NEW
3046
+ return BadgeLabel.NEW;
2988
3047
  } else if (isSoldOut) {
2989
- return BadgeLabel.SOLD_OUT
3048
+ return BadgeLabel.SOLD_OUT;
2990
3049
  } else if (isOnlineOnly) {
2991
- return BadgeLabel.ONLINE_EXCLUSIVE
3050
+ return BadgeLabel.ONLINE_EXCLUSIVE;
2992
3051
  } else if (isSustainable) {
2993
- return BadgeLabel.SUSTAINABLE
3052
+ return BadgeLabel.SUSTAINABLE;
2994
3053
  } else if (isPremium) {
2995
- return BadgeLabel.PREMIUM
3054
+ return BadgeLabel.PREMIUM;
2996
3055
  } else {
2997
- return BadgeLabel.DEFAULT
3056
+ return BadgeLabel.DEFAULT;
2998
3057
  }
2999
- }
3058
+ };
3000
3059
  ```
3001
3060
 
3002
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.
@@ -3020,7 +3079,7 @@
3020
3079
  // ...
3021
3080
  },
3022
3081
  // ...
3023
- })
3082
+ });
3024
3083
  ```
3025
3084
 
3026
3085
  - _Previous Environment Variables for Store Configuration:_
@@ -3049,7 +3108,7 @@
3049
3108
  // ...
3050
3109
  },
3051
3110
  // ...
3052
- })
3111
+ });
3053
3112
  ```
3054
3113
 
3055
3114
  - _Current Environment Variables for Shops Configuration:_
@@ -3069,8 +3128,8 @@
3069
3128
  ```ts
3070
3129
  useProduct({
3071
3130
  // ...
3072
- key: 'productKey',
3073
- })
3131
+ key: "productKey",
3132
+ });
3074
3133
  ```
3075
3134
 
3076
3135
  - _Current `key` as dedicated composables argument:_
@@ -3080,8 +3139,8 @@
3080
3139
  {
3081
3140
  // ...
3082
3141
  },
3083
- 'productKey',
3084
- )
3142
+ "productKey"
3143
+ );
3085
3144
  ```
3086
3145
 
3087
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.
@@ -3098,27 +3157,27 @@
3098
3157
  - _Previous Usage of `handleIDPLoginCallback`:_
3099
3158
 
3100
3159
  ```ts
3101
- const { handleIDPLoginCallback } = await useIDP()
3160
+ const { handleIDPLoginCallback } = await useIDP();
3102
3161
 
3103
3162
  watch(
3104
3163
  () => route.query,
3105
3164
  async (query) => {
3106
3165
  if (query.code && isString(query.code)) {
3107
- await handleIDPLoginCallback(query.code)
3166
+ await handleIDPLoginCallback(query.code);
3108
3167
  }
3109
3168
  },
3110
- { immediate: true },
3111
- )
3169
+ { immediate: true }
3170
+ );
3112
3171
  ```
3113
3172
 
3114
3173
  - _Current Usage of `loginIDP`:_
3115
3174
 
3116
3175
  ```ts
3117
- const { loginIDP } = useAuthentication('login')
3176
+ const { loginIDP } = useAuthentication("login");
3118
3177
 
3119
3178
  onMounted(async () => {
3120
- await loginIDP(props.code)
3121
- })
3179
+ await loginIDP(props.code);
3180
+ });
3122
3181
  ```
3123
3182
 
3124
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.
@@ -3128,17 +3187,17 @@
3128
3187
  - _Previous `useRpc` with `autoFetch`:_
3129
3188
 
3130
3189
  ```ts
3131
- useRpc('rpcMethod', key, params, { autoFetch: true })
3190
+ useRpc("rpcMethod", key, params, { autoFetch: true });
3132
3191
 
3133
- useUser({ autoFetch: true })
3192
+ useUser({ autoFetch: true });
3134
3193
  ```
3135
3194
 
3136
3195
  - _Current `useRpc` with `immediate`:_
3137
3196
 
3138
3197
  ```ts
3139
- useRpc('rpcMethod', key, params, { immediate: true })
3198
+ useRpc("rpcMethod", key, params, { immediate: true });
3140
3199
 
3141
- useUser({ immediate: true })
3200
+ useUser({ immediate: true });
3142
3201
  ```
3143
3202
 
3144
3203
  - **\[💥 BREAKING\]** The attribute `isCmsPreview` has been removed from `RpcContext`.
@@ -3158,18 +3217,18 @@
3158
3217
  getSearchSuggestions,
3159
3218
  fetching,
3160
3219
  ...searchData
3161
- } = useStorefrontSearch(searchQuery, { key })
3220
+ } = useStorefrontSearch(searchQuery, { key });
3162
3221
 
3163
- fetching.value // true or false
3222
+ fetching.value; // true or false
3164
3223
  ```
3165
3224
 
3166
3225
  - _Current `useStorefrontSearch` returning `status`:_
3167
3226
 
3168
3227
  ```ts
3169
3228
  const { data, resolveSearch, getSearchSuggestions, status, ...searchData } =
3170
- useStorefrontSearch(searchQuery, {}, key)
3229
+ useStorefrontSearch(searchQuery, {}, key);
3171
3230
 
3172
- status.value // 'idle', 'pending', 'error' or 'success'
3231
+ status.value; // 'idle', 'pending', 'error' or 'success'
3173
3232
  ```
3174
3233
 
3175
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.
@@ -3194,7 +3253,7 @@
3194
3253
  // ...
3195
3254
  },
3196
3255
  // ...
3197
- })
3256
+ });
3198
3257
  ```
3199
3258
 
3200
3259
  - _Current `enableDefaultGetCachedDataOverride`in `nuxt.config.ts`:_
@@ -3219,7 +3278,7 @@
3219
3278
  // ...
3220
3279
  },
3221
3280
  // ...
3222
- })
3281
+ });
3223
3282
  ```
3224
3283
 
3225
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).
@@ -3241,7 +3300,7 @@
3241
3300
  function myCustomRpc() {
3242
3301
  // ...
3243
3302
 
3244
- throw new BaseError(404)
3303
+ throw new BaseError(404);
3245
3304
  }
3246
3305
  ```
3247
3306
 
@@ -3251,7 +3310,7 @@
3251
3310
  function myCustomRpc() {
3252
3311
  // ...
3253
3312
 
3254
- return new Response(null, { status: 404 })
3313
+ return new Response(null, { status: 404 });
3255
3314
  }
3256
3315
  ```
3257
3316