@scayle/storefront-core 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 +124 -87
- package/dist/api/INFO.md +1 -1
- package/dist/cache/providers/unstorage.mjs +3 -1
- package/dist/constants/withParameters.mjs +16 -2
- package/dist/helpers/productHelpers.mjs +3 -1
- package/dist/helpers/sanitizationHelpers.mjs +4 -1
- package/dist/rpc/methods/basket/basket.mjs +10 -9
- package/dist/rpc/methods/brands.mjs +2 -2
- package/dist/rpc/methods/campaign.mjs +2 -2
- package/dist/rpc/methods/categories.mjs +5 -5
- package/dist/rpc/methods/cbd.mjs +1 -1
- package/dist/rpc/methods/checkout/checkout.mjs +2 -2
- package/dist/rpc/methods/checkout/order.mjs +2 -2
- package/dist/rpc/methods/checkout/shopUser.mjs +2 -2
- package/dist/rpc/methods/checkout/shopUserAddresses.mjs +3 -1
- package/dist/rpc/methods/navigationTrees.mjs +3 -3
- package/dist/rpc/methods/oauth/idp.mjs +2 -2
- package/dist/rpc/methods/products.mjs +65 -61
- package/dist/rpc/methods/promotion.mjs +3 -3
- package/dist/rpc/methods/search.mjs +2 -2
- package/dist/rpc/methods/session.mjs +7 -7
- package/dist/rpc/methods/shopConfiguration.mjs +1 -1
- package/dist/rpc/methods/user.mjs +6 -4
- package/dist/rpc/methods/variants.mjs +1 -1
- package/dist/rpc/methods/wishlist.mjs +14 -6
- package/dist/types/api/rpc.d.ts +15 -2
- package/dist/utils/hash.mjs +7 -2
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/utils/rpc.d.ts +23 -6
- package/dist/utils/rpc.mjs +4 -3
- package/package.json +12 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# @scayle/storefront-core
|
|
2
2
|
|
|
3
|
+
## 8.61.1
|
|
4
|
+
|
|
5
|
+
No changes in this release.
|
|
6
|
+
|
|
7
|
+
## 8.61.0
|
|
8
|
+
|
|
9
|
+
### Minor Changes
|
|
10
|
+
|
|
11
|
+
- **[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.
|
|
12
|
+
|
|
13
|
+
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.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { defineRpcHandler, type RpcContext } from "@scayle/storefront-core";
|
|
17
|
+
|
|
18
|
+
// Safe, public read — eligible for CDN/browser caching
|
|
19
|
+
export const getNavigation = defineRpcHandler(
|
|
20
|
+
async (context: RpcContext) => {
|
|
21
|
+
/* ... */
|
|
22
|
+
},
|
|
23
|
+
{ method: "GET" }
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// User-specific / Mutation — uses POST to prevent cache leakage
|
|
27
|
+
export const getBasket = defineRpcHandler(
|
|
28
|
+
async (context: RpcContext) => {
|
|
29
|
+
/* ... */
|
|
30
|
+
}
|
|
31
|
+
// method defaults to 'POST'
|
|
32
|
+
);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- Updated dependency `@scayle/storefront-api@workspace:*` to `@scayle/storefront-api@catalog:`
|
|
38
|
+
- Updated dependency `@scayle/unstorage-scayle-kv-driver@workspace:*` to `@scayle/unstorage-scayle-kv-driver@catalog:`
|
|
39
|
+
|
|
3
40
|
## 8.60.1
|
|
4
41
|
|
|
5
42
|
### Patch Changes
|
|
@@ -58,33 +95,33 @@
|
|
|
58
95
|
**Migration:**
|
|
59
96
|
|
|
60
97
|
```ts
|
|
61
|
-
import baseSlugify from
|
|
98
|
+
import baseSlugify from "slugify";
|
|
62
99
|
|
|
63
100
|
const slugify = (url: string | undefined): string => {
|
|
64
|
-
return baseSlugify(url ??
|
|
101
|
+
return baseSlugify(url ?? "", {
|
|
65
102
|
lower: true,
|
|
66
103
|
remove: /[*+~.()'"!:@/#?]/g,
|
|
67
|
-
})
|
|
68
|
-
}
|
|
104
|
+
});
|
|
105
|
+
};
|
|
69
106
|
|
|
70
|
-
const localePath = useLocalePath()
|
|
107
|
+
const localePath = useLocalePath();
|
|
71
108
|
|
|
72
109
|
const getProductDetailRoute = (
|
|
73
110
|
id: number,
|
|
74
111
|
name?: string,
|
|
75
|
-
locale?: Locale
|
|
112
|
+
locale?: Locale
|
|
76
113
|
): string => {
|
|
77
114
|
return localePath(
|
|
78
115
|
{
|
|
79
|
-
name:
|
|
116
|
+
name: "p-productName-id",
|
|
80
117
|
params: {
|
|
81
118
|
productName: slugify(name),
|
|
82
119
|
id: `${id}`,
|
|
83
120
|
},
|
|
84
121
|
},
|
|
85
|
-
locale
|
|
86
|
-
)
|
|
87
|
-
}
|
|
122
|
+
locale
|
|
123
|
+
);
|
|
124
|
+
};
|
|
88
125
|
```
|
|
89
126
|
|
|
90
127
|
## 8.59.1
|
|
@@ -265,10 +302,10 @@
|
|
|
265
302
|
Example:
|
|
266
303
|
|
|
267
304
|
```ts
|
|
268
|
-
import { sha256 } from
|
|
305
|
+
import { sha256 } from "@scayle/storefront-core";
|
|
269
306
|
|
|
270
|
-
const hash = await sha256(
|
|
271
|
-
console.log(hash) // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
|
|
307
|
+
const hash = await sha256("hello");
|
|
308
|
+
console.log(hash); // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
|
|
272
309
|
```
|
|
273
310
|
|
|
274
311
|
### Patch Changes
|
|
@@ -328,8 +365,8 @@
|
|
|
328
365
|
customer: {
|
|
329
366
|
groups: context.user?.groups,
|
|
330
367
|
},
|
|
331
|
-
}
|
|
332
|
-
})
|
|
368
|
+
};
|
|
369
|
+
});
|
|
333
370
|
```
|
|
334
371
|
|
|
335
372
|
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).
|
|
@@ -362,32 +399,32 @@
|
|
|
362
399
|
#### Looking up by name (existing, now renamed):
|
|
363
400
|
|
|
364
401
|
```typescript
|
|
365
|
-
import { getAttributeValuesByName } from
|
|
402
|
+
import { getAttributeValuesByName } from "@scayle/storefront-core";
|
|
366
403
|
|
|
367
404
|
// Single-select attribute
|
|
368
|
-
const sizes = getAttributeValuesByName(product.attributes,
|
|
405
|
+
const sizes = getAttributeValuesByName(product.attributes, "size");
|
|
369
406
|
// Returns: [{ id: 1, label: 'M', value: 'medium' }]
|
|
370
407
|
|
|
371
408
|
// Multi-select attribute
|
|
372
|
-
const colors = getAttributeValuesByName(product.attributes,
|
|
409
|
+
const colors = getAttributeValuesByName(product.attributes, "color");
|
|
373
410
|
// Returns: [{ id: 1, label: 'Red' }, { id: 2, label: 'Blue' }]
|
|
374
411
|
|
|
375
412
|
// Non-existent attribute
|
|
376
|
-
const missing = getAttributeValuesByName(product.attributes,
|
|
413
|
+
const missing = getAttributeValuesByName(product.attributes, "doesNotExist");
|
|
377
414
|
// Returns: []
|
|
378
415
|
```
|
|
379
416
|
|
|
380
417
|
#### Looking up by group ID (new):
|
|
381
418
|
|
|
382
419
|
```typescript
|
|
383
|
-
import { getAttributeValuesByGroupId } from
|
|
420
|
+
import { getAttributeValuesByGroupId } from "@scayle/storefront-core";
|
|
384
421
|
|
|
385
422
|
// Look up attribute by its numeric ID from the SCAYLE API
|
|
386
|
-
const promotionValues = getAttributeValuesByGroupId(product.attributes, 42)
|
|
423
|
+
const promotionValues = getAttributeValuesByGroupId(product.attributes, 42);
|
|
387
424
|
// Returns: [{ id: 123, label: 'Summer Sale', value: 'summer-2024' }]
|
|
388
425
|
|
|
389
426
|
// Non-existent attribute group
|
|
390
|
-
const missing = getAttributeValuesByGroupId(product.attributes, 9999)
|
|
427
|
+
const missing = getAttributeValuesByGroupId(product.attributes, 9999);
|
|
391
428
|
// Returns: []
|
|
392
429
|
```
|
|
393
430
|
|
|
@@ -483,10 +520,10 @@
|
|
|
483
520
|
|
|
484
521
|
```ts
|
|
485
522
|
const isComboDealType = (
|
|
486
|
-
promotion?: Promotion | null
|
|
523
|
+
promotion?: Promotion | null
|
|
487
524
|
): promotion is Promotion<ComboDealEffect> => {
|
|
488
|
-
return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL
|
|
489
|
-
}
|
|
525
|
+
return promotion?.effect?.type === PromotionEffectType.COMBO_DEAL;
|
|
526
|
+
};
|
|
490
527
|
```
|
|
491
528
|
|
|
492
529
|
### Patch Changes
|
|
@@ -758,23 +795,23 @@
|
|
|
758
795
|
- 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.
|
|
759
796
|
|
|
760
797
|
```ts
|
|
761
|
-
const { data } = useRpc(
|
|
798
|
+
const { data } = useRpc("getFilters", "getFiltersKey", () => ({
|
|
762
799
|
where: {
|
|
763
800
|
minReduction: 10,
|
|
764
801
|
maxReduction: 20,
|
|
765
802
|
},
|
|
766
|
-
}))
|
|
803
|
+
}));
|
|
767
804
|
|
|
768
805
|
const { data } = useRpc(
|
|
769
|
-
|
|
770
|
-
|
|
806
|
+
"getProductsByCategory",
|
|
807
|
+
"getProductsByCategoryKey",
|
|
771
808
|
() => ({
|
|
772
809
|
where: {
|
|
773
810
|
minReduction: 10,
|
|
774
811
|
maxReduction: 20,
|
|
775
812
|
},
|
|
776
|
-
})
|
|
777
|
-
)
|
|
813
|
+
})
|
|
814
|
+
);
|
|
778
815
|
```
|
|
779
816
|
|
|
780
817
|
## 8.30.3
|
|
@@ -805,28 +842,28 @@ No changes in this release.
|
|
|
805
842
|
|
|
806
843
|
```ts
|
|
807
844
|
export const existingHandlerWithoutParams = async (_context: RpcContext) => {
|
|
808
|
-
return
|
|
809
|
-
}
|
|
845
|
+
return "existing handler";
|
|
846
|
+
};
|
|
810
847
|
|
|
811
848
|
export const existingHandlerWithParams = async (
|
|
812
849
|
{ name }: { name: string },
|
|
813
|
-
_context: RpcContext
|
|
850
|
+
_context: RpcContext
|
|
814
851
|
) => {
|
|
815
|
-
return name
|
|
816
|
-
}
|
|
852
|
+
return name;
|
|
853
|
+
};
|
|
817
854
|
|
|
818
855
|
// will become
|
|
819
856
|
|
|
820
857
|
export const existingHandlerWithoutParams = defineRpcHandler(
|
|
821
858
|
async (_context: RpcContext) => {
|
|
822
|
-
return
|
|
823
|
-
}
|
|
824
|
-
)
|
|
859
|
+
return "existing handler";
|
|
860
|
+
}
|
|
861
|
+
);
|
|
825
862
|
export const existingHandlerWithParams = defineRpcHandler(
|
|
826
863
|
async ({ name }: { name: string }, _context: RpcContext) => {
|
|
827
|
-
return name
|
|
828
|
-
}
|
|
829
|
-
)
|
|
864
|
+
return name;
|
|
865
|
+
}
|
|
866
|
+
);
|
|
830
867
|
```
|
|
831
868
|
|
|
832
869
|
### Patch Changes
|
|
@@ -843,15 +880,15 @@ No changes in this release.
|
|
|
843
880
|
- 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.
|
|
844
881
|
|
|
845
882
|
```ts
|
|
846
|
-
import { rpcMethods } from
|
|
883
|
+
import { rpcMethods } from "@scayle/storefront-core";
|
|
847
884
|
|
|
848
|
-
rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext)
|
|
885
|
+
rpcMethods.getCategoryTree({ hideEmptyCategories: true }, rpcContext);
|
|
849
886
|
```
|
|
850
887
|
|
|
851
888
|
or
|
|
852
889
|
|
|
853
890
|
```ts
|
|
854
|
-
import { useCategoryTree } from
|
|
891
|
+
import { useCategoryTree } from "#storefront/composables";
|
|
855
892
|
|
|
856
893
|
const { data: rootCategories, status } = useCategoryTree(
|
|
857
894
|
{
|
|
@@ -859,8 +896,8 @@ No changes in this release.
|
|
|
859
896
|
hideEmptyCategories: true,
|
|
860
897
|
},
|
|
861
898
|
},
|
|
862
|
-
|
|
863
|
-
)
|
|
899
|
+
"category-navigation-tree"
|
|
900
|
+
);
|
|
864
901
|
```
|
|
865
902
|
|
|
866
903
|
### Patch Changes
|
|
@@ -1292,12 +1329,12 @@ To get the default campaign key, you can call the RPC method:
|
|
|
1292
1329
|
```typescript
|
|
1293
1330
|
// Before
|
|
1294
1331
|
async function rpcMethod(context) {
|
|
1295
|
-
const campaignKey = { context }
|
|
1332
|
+
const campaignKey = { context };
|
|
1296
1333
|
// ...
|
|
1297
1334
|
}
|
|
1298
1335
|
// After
|
|
1299
1336
|
async function rpcMethod(context) {
|
|
1300
|
-
const campaignKey = await context.callRpc?.(
|
|
1337
|
+
const campaignKey = await context.callRpc?.("getCampaignKey");
|
|
1301
1338
|
// ...
|
|
1302
1339
|
}
|
|
1303
1340
|
```
|
|
@@ -1486,43 +1523,43 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1486
1523
|
|
|
1487
1524
|
```ts
|
|
1488
1525
|
const BadgeLabel = {
|
|
1489
|
-
NEW:
|
|
1490
|
-
SOLD_OUT:
|
|
1491
|
-
ONLINE_EXCLUSIVE:
|
|
1492
|
-
SUSTAINABLE:
|
|
1493
|
-
PREMIUM:
|
|
1494
|
-
DEFAULT:
|
|
1495
|
-
} as const
|
|
1526
|
+
NEW: "new",
|
|
1527
|
+
SOLD_OUT: "sold_out",
|
|
1528
|
+
ONLINE_EXCLUSIVE: "online_exclusive",
|
|
1529
|
+
SUSTAINABLE: "sustainable",
|
|
1530
|
+
PREMIUM: "premium",
|
|
1531
|
+
DEFAULT: "",
|
|
1532
|
+
} as const;
|
|
1496
1533
|
|
|
1497
1534
|
type BadgeLabelParamsKeys =
|
|
1498
|
-
|
|
|
1499
|
-
|
|
|
1500
|
-
|
|
|
1501
|
-
|
|
|
1502
|
-
|
|
|
1503
|
-
type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean
|
|
1535
|
+
| "isNew"
|
|
1536
|
+
| "isSoldOut"
|
|
1537
|
+
| "isOnlineOnly"
|
|
1538
|
+
| "isSustainable"
|
|
1539
|
+
| "isPremium";
|
|
1540
|
+
type BadgeLabelParams = Partial<Record<BadgeLabelParamsKeys, boolean>>;
|
|
1504
1541
|
|
|
1505
1542
|
const getBadgeLabel = (params: BadgeLabelParams = {}): string => {
|
|
1506
1543
|
if (!params) {
|
|
1507
|
-
return BadgeLabel.DEFAULT
|
|
1544
|
+
return BadgeLabel.DEFAULT;
|
|
1508
1545
|
}
|
|
1509
1546
|
const { isNew, isSoldOut, isOnlineOnly, isSustainable, isPremium } =
|
|
1510
|
-
params
|
|
1547
|
+
params;
|
|
1511
1548
|
|
|
1512
1549
|
if (isNew) {
|
|
1513
|
-
return BadgeLabel.NEW
|
|
1550
|
+
return BadgeLabel.NEW;
|
|
1514
1551
|
} else if (isSoldOut) {
|
|
1515
|
-
return BadgeLabel.SOLD_OUT
|
|
1552
|
+
return BadgeLabel.SOLD_OUT;
|
|
1516
1553
|
} else if (isOnlineOnly) {
|
|
1517
|
-
return BadgeLabel.ONLINE_EXCLUSIVE
|
|
1554
|
+
return BadgeLabel.ONLINE_EXCLUSIVE;
|
|
1518
1555
|
} else if (isSustainable) {
|
|
1519
|
-
return BadgeLabel.SUSTAINABLE
|
|
1556
|
+
return BadgeLabel.SUSTAINABLE;
|
|
1520
1557
|
} else if (isPremium) {
|
|
1521
|
-
return BadgeLabel.PREMIUM
|
|
1558
|
+
return BadgeLabel.PREMIUM;
|
|
1522
1559
|
} else {
|
|
1523
|
-
return BadgeLabel.DEFAULT
|
|
1560
|
+
return BadgeLabel.DEFAULT;
|
|
1524
1561
|
}
|
|
1525
|
-
}
|
|
1562
|
+
};
|
|
1526
1563
|
```
|
|
1527
1564
|
|
|
1528
1565
|
- **\[💥 BREAKING\]** We've standardized our configuration to use `sapi` (Storefront API) throughout the codebase, replacing the deprecated `bapi` keyword. This change improves clarity and consistency by removing the `initBapi` function, replacing the `bapiClient` property with `sapiClient` within the `RPCContext`, and updating all code references accordingly. `BapiConfig` is not exported anymore and has been superseded by `SapiConfig`.
|
|
@@ -1538,15 +1575,15 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1538
1575
|
storefront: {
|
|
1539
1576
|
// ...
|
|
1540
1577
|
bapi: {
|
|
1541
|
-
host:
|
|
1542
|
-
token:
|
|
1578
|
+
host: "...",
|
|
1579
|
+
token: "...",
|
|
1543
1580
|
},
|
|
1544
1581
|
// ...
|
|
1545
1582
|
},
|
|
1546
1583
|
// ...
|
|
1547
1584
|
},
|
|
1548
1585
|
// ...
|
|
1549
|
-
}
|
|
1586
|
+
};
|
|
1550
1587
|
```
|
|
1551
1588
|
|
|
1552
1589
|
- _Legacy Environment Variables:_
|
|
@@ -1566,15 +1603,15 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1566
1603
|
storefront: {
|
|
1567
1604
|
// ...
|
|
1568
1605
|
sapi: {
|
|
1569
|
-
host:
|
|
1570
|
-
token:
|
|
1606
|
+
host: "...",
|
|
1607
|
+
token: "...",
|
|
1571
1608
|
},
|
|
1572
1609
|
// ...
|
|
1573
1610
|
},
|
|
1574
1611
|
// ...
|
|
1575
1612
|
},
|
|
1576
1613
|
// ...
|
|
1577
|
-
}
|
|
1614
|
+
};
|
|
1578
1615
|
```
|
|
1579
1616
|
|
|
1580
1617
|
- _New Environment Variables:_
|
|
@@ -1592,19 +1629,19 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1592
1629
|
|
|
1593
1630
|
```ts
|
|
1594
1631
|
const { data, fetching, fetch, error, status } = useUser(
|
|
1595
|
-
|
|
1632
|
+
"getUser"
|
|
1596
1633
|
// ...
|
|
1597
|
-
)
|
|
1598
|
-
data.value.user.authentication.storefrontAccessToken
|
|
1634
|
+
);
|
|
1635
|
+
data.value.user.authentication.storefrontAccessToken;
|
|
1599
1636
|
```
|
|
1600
1637
|
|
|
1601
1638
|
- _Current Usage of dedicated `getAccessToken` RPC method:_
|
|
1602
1639
|
|
|
1603
1640
|
```ts
|
|
1604
1641
|
const { data: accessToken } = useRpc(
|
|
1605
|
-
|
|
1642
|
+
"getAccessToken"
|
|
1606
1643
|
// ...
|
|
1607
|
-
)
|
|
1644
|
+
);
|
|
1608
1645
|
```
|
|
1609
1646
|
|
|
1610
1647
|
- **\[💥 BREAKING\]** We've enhanced security for basket and wishlist keys by switching the default hashing algorithm from MD5 to the more robust SHA256.
|
|
@@ -1627,7 +1664,7 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1627
1664
|
// ...
|
|
1628
1665
|
},
|
|
1629
1666
|
// ...
|
|
1630
|
-
})
|
|
1667
|
+
});
|
|
1631
1668
|
```
|
|
1632
1669
|
|
|
1633
1670
|
- **\[💥 BREAKING\]** The attribute `loginShopId` is removed from the `ShopUser` interface as the shop now uses session cookies.
|
|
@@ -1636,23 +1673,23 @@ See [Overriding core RPC Methods](https://scayle.dev/en/core-documentation/store
|
|
|
1636
1673
|
- _Previous Usage of `searchProducts` RPC method:_
|
|
1637
1674
|
|
|
1638
1675
|
```ts
|
|
1639
|
-
const getSearchSuggestionsRpc = useRpcCall(
|
|
1676
|
+
const getSearchSuggestionsRpc = useRpcCall("searchProducts");
|
|
1640
1677
|
|
|
1641
1678
|
data.value = await searchProducts({
|
|
1642
1679
|
term: String(searchQuery.value),
|
|
1643
1680
|
...params,
|
|
1644
|
-
})
|
|
1681
|
+
});
|
|
1645
1682
|
```
|
|
1646
1683
|
|
|
1647
1684
|
- _Current Usage of `getSearchSuggestions` RPC method:_
|
|
1648
1685
|
|
|
1649
1686
|
```ts
|
|
1650
|
-
const getSearchSuggestionsRpc = useRpcCall(
|
|
1687
|
+
const getSearchSuggestionsRpc = useRpcCall("getSearchSuggestions");
|
|
1651
1688
|
|
|
1652
1689
|
data.value = await getSearchSuggestionsRpc({
|
|
1653
1690
|
term: String(searchQuery.value),
|
|
1654
1691
|
...params,
|
|
1655
|
-
})
|
|
1692
|
+
});
|
|
1656
1693
|
```
|
|
1657
1694
|
|
|
1658
1695
|
- **\[💥 BREAKING\]** Improved basket updating: Adding an item to your basket with a reduced quantity will now correctly update the basket contents.
|
package/dist/api/INFO.md
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
|
|
5
5
|
This directory is the home of "mini" API clients. While some SCAYLE APIs provide a TypeScript SDK as an npm package (e.g. SAPI) others do not. When the API is simple enough, we may create a "mini" SDK within `storefront-core`. This way we can provide a TypeScript native abstraction over the API but not suffer the overhead of an additional package to maintain.
|
|
6
6
|
|
|
7
|
-
The SDKs created here should generally be a single file. The goal should be to make them as self-contained as possible, but it is ok if they need to pull a type or utility function from elsewhere in `storefront-core`.
|
|
7
|
+
The SDKs created here should generally be a single file. The goal should be to make them as self-contained as possible, but it is ok if they need to pull a type or utility function from elsewhere in `storefront-core`.
|
|
@@ -53,7 +53,9 @@ export class UnstorageCache {
|
|
|
53
53
|
* @param tag The tag to purge.
|
|
54
54
|
*/
|
|
55
55
|
async purgeTag(tag) {
|
|
56
|
-
const keys = await this.storage.getItem(
|
|
56
|
+
const keys = await this.storage.getItem(
|
|
57
|
+
this.getKey(`tag:${tag}`)
|
|
58
|
+
);
|
|
57
59
|
await this.purgeKeys(keys ?? []);
|
|
58
60
|
await this.storage.removeItem(this.getKey(`tag:${tag}`));
|
|
59
61
|
}
|
|
@@ -67,7 +67,14 @@ const MIN_WITH_PARAMS_BASKET = {
|
|
|
67
67
|
},
|
|
68
68
|
variants: {
|
|
69
69
|
attributes: {
|
|
70
|
-
withKey: [
|
|
70
|
+
withKey: [
|
|
71
|
+
"brand",
|
|
72
|
+
"name",
|
|
73
|
+
"price",
|
|
74
|
+
"size",
|
|
75
|
+
"shopSize",
|
|
76
|
+
"vendorSize"
|
|
77
|
+
]
|
|
71
78
|
}
|
|
72
79
|
},
|
|
73
80
|
images: {
|
|
@@ -96,7 +103,14 @@ const MIN_WITH_PARAMS_WISHLIST = {
|
|
|
96
103
|
},
|
|
97
104
|
variants: {
|
|
98
105
|
attributes: {
|
|
99
|
-
withKey: [
|
|
106
|
+
withKey: [
|
|
107
|
+
"brand",
|
|
108
|
+
"name",
|
|
109
|
+
"price",
|
|
110
|
+
"size",
|
|
111
|
+
"shopSize",
|
|
112
|
+
"vendorSize"
|
|
113
|
+
]
|
|
100
114
|
}
|
|
101
115
|
},
|
|
102
116
|
images: {
|
|
@@ -50,7 +50,9 @@ export const getAllSizesFromVariants = (variantsAttributes, attributeName = "sho
|
|
|
50
50
|
const array = variantsAttributes.map(
|
|
51
51
|
(variant) => getFirstAttributeValue(variant.attributes, attributeName)
|
|
52
52
|
).filter(Boolean);
|
|
53
|
-
return [
|
|
53
|
+
return [
|
|
54
|
+
...new Map(array.map((item) => [item?.id ?? item, item])).values()
|
|
55
|
+
];
|
|
54
56
|
};
|
|
55
57
|
export const getProductSiblings = (product, colorAttributeName = "colorDetail") => {
|
|
56
58
|
if (!product) {
|
|
@@ -15,7 +15,10 @@ export const purifySensitiveData = (data = {}, blacklistedKeys = ["password", "t
|
|
|
15
15
|
(excludedKey) => key.includes(excludedKey)
|
|
16
16
|
);
|
|
17
17
|
if (isSensitiveData && value) {
|
|
18
|
-
purifiedPayload[key] = purifySensitiveValue(
|
|
18
|
+
purifiedPayload[key] = purifySensitiveValue(
|
|
19
|
+
value,
|
|
20
|
+
showFirstAndLastChar
|
|
21
|
+
);
|
|
19
22
|
} else {
|
|
20
23
|
purifiedPayload[key] = value;
|
|
21
24
|
}
|
|
@@ -95,7 +95,7 @@ export const addItemToBasket = defineRpcHandler(async ({
|
|
|
95
95
|
}
|
|
96
96
|
);
|
|
97
97
|
}
|
|
98
|
-
});
|
|
98
|
+
}, { method: "PUT" });
|
|
99
99
|
export const addItemsToBasket = defineRpcHandler(async (params, context) => {
|
|
100
100
|
if (!hasSession(context)) {
|
|
101
101
|
return new ErrorResponse(
|
|
@@ -162,7 +162,7 @@ export const addItemsToBasket = defineRpcHandler(async (params, context) => {
|
|
|
162
162
|
}
|
|
163
163
|
);
|
|
164
164
|
}
|
|
165
|
-
});
|
|
165
|
+
}, { method: "PUT" });
|
|
166
166
|
export const getBasket = defineRpcHandler(async (options, context) => {
|
|
167
167
|
if (!hasSession(context)) {
|
|
168
168
|
return new ErrorResponse(
|
|
@@ -200,7 +200,7 @@ export const getBasket = defineRpcHandler(async (options, context) => {
|
|
|
200
200
|
);
|
|
201
201
|
}
|
|
202
202
|
return { basket: response.basket };
|
|
203
|
-
});
|
|
203
|
+
}, { method: "POST" });
|
|
204
204
|
export const removeItemFromBasket = defineRpcHandler(async (options, context) => {
|
|
205
205
|
if (!hasSession(context)) {
|
|
206
206
|
return new ErrorResponse(
|
|
@@ -235,7 +235,7 @@ export const removeItemFromBasket = defineRpcHandler(async (options, context) =>
|
|
|
235
235
|
);
|
|
236
236
|
}
|
|
237
237
|
return { basket: response };
|
|
238
|
-
});
|
|
238
|
+
}, { method: "DELETE" });
|
|
239
239
|
export const clearBasket = defineRpcHandler(
|
|
240
240
|
async (context) => {
|
|
241
241
|
const getBasketResponse = await getBasket({}, context);
|
|
@@ -253,7 +253,8 @@ export const clearBasket = defineRpcHandler(
|
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
255
|
return true;
|
|
256
|
-
}
|
|
256
|
+
},
|
|
257
|
+
{ method: "DELETE" }
|
|
257
258
|
);
|
|
258
259
|
export const mergeBaskets = defineRpcHandler(async ({ fromBasketKey, toBasketKey, with: _with, orderCustomData }, context) => {
|
|
259
260
|
const resolvedWith = getWithParams(
|
|
@@ -270,7 +271,7 @@ export const mergeBaskets = defineRpcHandler(async ({ fromBasketKey, toBasketKey
|
|
|
270
271
|
},
|
|
271
272
|
context
|
|
272
273
|
);
|
|
273
|
-
});
|
|
274
|
+
}, { method: "POST" });
|
|
274
275
|
export const updateBasketItem = defineRpcHandler(async ({ basketItemKey, update, with: _with, orderCustomData }, context) => {
|
|
275
276
|
if (!hasSession(context)) {
|
|
276
277
|
return new ErrorResponse(
|
|
@@ -317,7 +318,7 @@ export const updateBasketItem = defineRpcHandler(async ({ basketItemKey, update,
|
|
|
317
318
|
}
|
|
318
319
|
);
|
|
319
320
|
}
|
|
320
|
-
});
|
|
321
|
+
}, { method: "PUT" });
|
|
321
322
|
export const getApplicablePromotionsByCode = defineRpcHandler(async ({ promotionCode, with: _with }, context) => {
|
|
322
323
|
if (!hasSession(context)) {
|
|
323
324
|
return new ErrorResponse(
|
|
@@ -358,7 +359,7 @@ export const getApplicablePromotionsByCode = defineRpcHandler(async ({ promotion
|
|
|
358
359
|
} else {
|
|
359
360
|
return { basket: result.basket };
|
|
360
361
|
}
|
|
361
|
-
});
|
|
362
|
+
}, { method: "POST" });
|
|
362
363
|
export const updatePromotions = defineRpcHandler(async (params, context) => {
|
|
363
364
|
if (!hasSession(context)) {
|
|
364
365
|
return new ErrorResponse(
|
|
@@ -398,7 +399,7 @@ export const updatePromotions = defineRpcHandler(async (params, context) => {
|
|
|
398
399
|
);
|
|
399
400
|
}
|
|
400
401
|
return { basket: result.basket };
|
|
401
|
-
});
|
|
402
|
+
}, { method: "PUT" });
|
|
402
403
|
function parseBasketError(response) {
|
|
403
404
|
const parsedError = {
|
|
404
405
|
message: "",
|
|
@@ -11,7 +11,7 @@ export const getBrands = defineRpcHandler(async ({ pagination }, context) => {
|
|
|
11
11
|
perPage: pagination?.perPage ? Math.min(pagination.perPage, MAX_PER_PAGE) : void 0
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
|
-
});
|
|
14
|
+
}, { method: "GET" });
|
|
15
15
|
export const getBrandById = defineRpcHandler(async ({ brandId }, context) => {
|
|
16
16
|
const { sapiClient, cached } = context;
|
|
17
17
|
return await cached(
|
|
@@ -20,4 +20,4 @@ export const getBrandById = defineRpcHandler(async ({ brandId }, context) => {
|
|
|
20
20
|
cacheKeyPrefix: `getBrandById-${brandId}`
|
|
21
21
|
}
|
|
22
22
|
)(brandId);
|
|
23
|
-
});
|
|
23
|
+
}, { method: "GET" });
|
|
@@ -22,7 +22,7 @@ const getCampaigns = async (context) => {
|
|
|
22
22
|
export const getCampaign = defineRpcHandler(async (context) => {
|
|
23
23
|
const campaigns = await getCampaigns(context);
|
|
24
24
|
return campaigns.find(isCampaignActive);
|
|
25
|
-
});
|
|
25
|
+
}, { method: "GET" });
|
|
26
26
|
export const getCampaignKey = defineRpcHandler(async (context) => {
|
|
27
27
|
if (context.campaignKey) {
|
|
28
28
|
return context.campaignKey;
|
|
@@ -30,4 +30,4 @@ export const getCampaignKey = defineRpcHandler(async (context) => {
|
|
|
30
30
|
const campaigns = await getCampaigns(context);
|
|
31
31
|
const campaign = campaigns.find(isCampaignActive);
|
|
32
32
|
return campaign?.key;
|
|
33
|
-
});
|
|
33
|
+
}, { method: "GET" });
|
|
@@ -13,7 +13,7 @@ export const getRootCategories = defineRpcHandler(async ({ children = 1, include
|
|
|
13
13
|
categories: result,
|
|
14
14
|
activeNode: void 0
|
|
15
15
|
};
|
|
16
|
-
});
|
|
16
|
+
}, { method: "GET" });
|
|
17
17
|
export const getCategoryByPath = defineRpcHandler(async ({ path, children = 1, includeHidden, properties, includeProductSorting }, context) => {
|
|
18
18
|
const { cached, sapiClient } = context;
|
|
19
19
|
const sanitizedPath = splitAndRemoveEmpty(path);
|
|
@@ -26,7 +26,7 @@ export const getCategoryByPath = defineRpcHandler(async ({ path, children = 1, i
|
|
|
26
26
|
with: { children, properties, includeProductSorting },
|
|
27
27
|
includeHidden
|
|
28
28
|
});
|
|
29
|
-
});
|
|
29
|
+
}, { method: "GET" });
|
|
30
30
|
export const getCategoriesByPath = defineRpcHandler(async ({ path, children = 1, includeHidden, properties, includeProductSorting }, context) => {
|
|
31
31
|
const { cached, sapiClient } = context;
|
|
32
32
|
if (path === "/") {
|
|
@@ -79,7 +79,7 @@ export const getCategoriesByPath = defineRpcHandler(async ({ path, children = 1,
|
|
|
79
79
|
lastNode = rootPath[i];
|
|
80
80
|
}
|
|
81
81
|
return { categories: tree, activeNode: result };
|
|
82
|
-
});
|
|
82
|
+
}, { method: "GET" });
|
|
83
83
|
export const getCategoryById = defineRpcHandler(async ({ id, children = 1, includeHidden, properties, includeProductSorting }, context) => {
|
|
84
84
|
const { cached, sapiClient } = context;
|
|
85
85
|
return await cached(
|
|
@@ -96,7 +96,7 @@ export const getCategoryById = defineRpcHandler(async ({ id, children = 1, inclu
|
|
|
96
96
|
},
|
|
97
97
|
includeHidden
|
|
98
98
|
});
|
|
99
|
-
});
|
|
99
|
+
}, { method: "GET" });
|
|
100
100
|
export const getCategoryTree = defineRpcHandler(async ({
|
|
101
101
|
children,
|
|
102
102
|
includeHidden,
|
|
@@ -143,4 +143,4 @@ export const getCategoryTree = defineRpcHandler(async ({
|
|
|
143
143
|
return categoryTree.filter(
|
|
144
144
|
(category) => categoryProductCountTable[category.id] > 0
|
|
145
145
|
);
|
|
146
|
-
});
|
|
146
|
+
}, { method: "GET" });
|
package/dist/rpc/methods/cbd.mjs
CHANGED