@salesforce/commerce-sdk-react 1.0.0-preview.2 → 1.0.0-preview.3
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 +1 -3
- package/README.md +58 -52
- package/hooks/useEncUserId.d.ts +8 -1
- package/hooks/useEncUserId.js +13 -2
- package/hooks/useUsid.d.ts +8 -1
- package/hooks/useUsid.js +17 -9
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -5,12 +5,12 @@ A collection of <a href="https://tanstack.com/query/latest/docs/react/overview">
|
|
|
5
5
|
|
|
6
6
|
## 🎯 Features
|
|
7
7
|
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
- Shopper authentication & token management via [SLAS](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-login)
|
|
9
|
+
- Server side data fetching (in conjuction with PWA Kit)
|
|
10
|
+
- Phased Launch support ([plugin_slas](https://github.com/SalesforceCommerceCloud/plugin_slas) compatible)
|
|
11
|
+
- Built-in caching for easy state management
|
|
12
|
+
- automatic cache invalidations/updates via the library's built-in mutations
|
|
13
|
+
- automatic cache key generation
|
|
14
14
|
|
|
15
15
|
## ⚙️ Installation
|
|
16
16
|
|
|
@@ -43,7 +43,7 @@ const AppConfig = ({children}) => {
|
|
|
43
43
|
{children}
|
|
44
44
|
</CommerceApiProvider>
|
|
45
45
|
)
|
|
46
|
-
}
|
|
46
|
+
}
|
|
47
47
|
|
|
48
48
|
// Set configuration options for react query.
|
|
49
49
|
// NOTE: This configuration will be used both on the server-side and client-side.
|
|
@@ -65,13 +65,12 @@ export default withReactQuery(AppConfig, options)
|
|
|
65
65
|
|
|
66
66
|
## ⚡️ Quickstart (Generic React App)
|
|
67
67
|
|
|
68
|
-
You can use this library in any React application by creating a new QueryClient and wrap your application with `QueryClientProvider`. For example:
|
|
68
|
+
You can use this library in any React application by creating a new QueryClient and wrap your application with `QueryClientProvider`. For example:
|
|
69
69
|
|
|
70
70
|
```jsx
|
|
71
71
|
import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
|
|
72
72
|
import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
|
|
73
73
|
|
|
74
|
-
|
|
75
74
|
const App = ({children}) => {
|
|
76
75
|
const queryClient = new QueryClient()
|
|
77
76
|
|
|
@@ -91,7 +90,7 @@ const App = ({children}) => {
|
|
|
91
90
|
</CommerceApiProvider>
|
|
92
91
|
</QueryClientProvider>
|
|
93
92
|
)
|
|
94
|
-
}
|
|
93
|
+
}
|
|
95
94
|
|
|
96
95
|
export default App
|
|
97
96
|
```
|
|
@@ -104,7 +103,7 @@ To help reduce boilerplate code for managing shopper authentication, by default,
|
|
|
104
103
|
|
|
105
104
|
### Shopper Session Initialization
|
|
106
105
|
|
|
107
|
-
On `CommerceApiProvider` mount, the provider initializes shopper session by initiating the SLAS
|
|
106
|
+
On `CommerceApiProvider` mount, the provider initializes shopper session by initiating the SLAS **Public Client** login flow. The tokens are stored/managed/refreshed by the library.
|
|
108
107
|
|
|
109
108
|
### Authenticate request queue
|
|
110
109
|
|
|
@@ -136,19 +135,15 @@ You have the option of handling shopper authentication externally, by providing
|
|
|
136
135
|
|
|
137
136
|
```jsx
|
|
138
137
|
const MyComponent = ({children}) => {
|
|
139
|
-
return
|
|
140
|
-
|
|
141
|
-
{children}
|
|
142
|
-
</CommerceApiProvider>
|
|
143
|
-
)
|
|
144
|
-
}
|
|
138
|
+
return <CommerceApiProvider fetchedToken="xxxxxxxxxxxx">{children}</CommerceApiProvider>
|
|
139
|
+
}
|
|
145
140
|
```
|
|
146
141
|
|
|
147
142
|
## Hooks
|
|
148
143
|
|
|
149
144
|
The majority of hooks provided in this library are built on top of the [useQuery](https://tanstack.com/query/latest/docs/react/reference/useQuery) and the [useMutation](https://tanstack.com/query/latest/docs/react/reference/useMutation) hook from [react-query](https://tanstack.com/query/latest). React-query provides a declarative way for fetching and updating data. This library takes advantage of the features provided by react-query and combine with the [commerce-sdk-isomorphic](https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic) API client to create a collection of hooks to simplify data fetching for SCAPI.
|
|
150
145
|
|
|
151
|
-
The hooks can be categorized into
|
|
146
|
+
The hooks can be categorized into **Query hooks** and **Mutation hooks**.
|
|
152
147
|
|
|
153
148
|
### Query hooks
|
|
154
149
|
|
|
@@ -158,7 +153,7 @@ The query hooks correspond to the http GET endpoints from the SCAPI. The query h
|
|
|
158
153
|
use<EntityName>(CommerceClientOptions, ReactQueryOptions)
|
|
159
154
|
```
|
|
160
155
|
|
|
161
|
-
Both the
|
|
156
|
+
Both the **required** and **optional** parameters for the underlying `commerce-sdk-isomorphic` call is passed as the first parameter:
|
|
162
157
|
|
|
163
158
|
```jsx
|
|
164
159
|
import {useProduct} from '@salesforce/commerce-sdk-react'
|
|
@@ -171,10 +166,12 @@ const Example = () => {
|
|
|
171
166
|
}
|
|
172
167
|
})
|
|
173
168
|
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
169
|
+
return (
|
|
170
|
+
<>
|
|
171
|
+
<p>isLoading: {query.isLoading}</p>
|
|
172
|
+
<p>name: {query.data?.name}</p>
|
|
173
|
+
</>
|
|
174
|
+
)
|
|
178
175
|
}
|
|
179
176
|
```
|
|
180
177
|
|
|
@@ -186,15 +183,18 @@ import {useBasket} from '@salesforce/commerce-sdk-react'
|
|
|
186
183
|
const onServer = typeof window === undefined
|
|
187
184
|
|
|
188
185
|
const Example = ({basketId}) => {
|
|
189
|
-
const query = useBasket(
|
|
190
|
-
|
|
191
|
-
|
|
186
|
+
const query = useBasket(
|
|
187
|
+
{
|
|
188
|
+
parameters: {
|
|
189
|
+
basketId: basketId
|
|
190
|
+
}
|
|
192
191
|
},
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
192
|
+
{
|
|
193
|
+
// A common use case for `enabled` is
|
|
194
|
+
// to conditionally fetch based on environment
|
|
195
|
+
enabled: !onServer && basketId
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
198
|
}
|
|
199
199
|
```
|
|
200
200
|
|
|
@@ -215,16 +215,22 @@ const Example = ({basketId}) => {
|
|
|
215
215
|
// Typescript IDE intellisense for available options
|
|
216
216
|
const addItemToBasket = useShopperBasketsMutation('addItemToBasket')
|
|
217
217
|
|
|
218
|
-
return
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
218
|
+
return (
|
|
219
|
+
<button
|
|
220
|
+
onClick={() =>
|
|
221
|
+
addItemToBasket.mutate({
|
|
222
|
+
parameters: {
|
|
223
|
+
basketId
|
|
224
|
+
},
|
|
225
|
+
body: {
|
|
226
|
+
productId: '25592770M',
|
|
227
|
+
price: 55,
|
|
228
|
+
quantity: 1
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
/>
|
|
233
|
+
)
|
|
228
234
|
}
|
|
229
235
|
```
|
|
230
236
|
|
|
@@ -247,7 +253,7 @@ const Example = ({basketId}) => {
|
|
|
247
253
|
|
|
248
254
|
Since mutations changes data on the server, the cache entries that are potentially affected by the mutation is automatically invalidated.
|
|
249
255
|
|
|
250
|
-
For example, an `addItemToBasket` mutation automatically update `useBasket`
|
|
256
|
+
For example, an `addItemToBasket` mutation automatically update `useBasket` and `useCustomerBaskets` query cache, because the mutation result contains the information for the updated basket. In other cases, when the mutation response do not have the updated data, the library will invalidate the cache and trigger a re-fetch. For the DELETE endpoints, the library removes the cache entries on successful mutations.
|
|
251
257
|
|
|
252
258
|
_💡 Debugging hint: install and include `@tanstack/react-query-devtools` in your React app to see the queries (inspect the query states and cache keys)._
|
|
253
259
|
|
|
@@ -269,14 +275,13 @@ const Example = () => {
|
|
|
269
275
|
const fetchProducts = async () => {
|
|
270
276
|
const token = await getTokenWhenReady()
|
|
271
277
|
const products = await api.shopperProducts.getProducts({
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
278
|
+
parameters: {ids: ids.join(',')},
|
|
279
|
+
headers: {
|
|
280
|
+
Authorization: `Bearer ${token}`
|
|
281
|
+
}
|
|
282
|
+
})
|
|
277
283
|
return products
|
|
278
284
|
}
|
|
279
|
-
|
|
280
285
|
}
|
|
281
286
|
```
|
|
282
287
|
|
|
@@ -303,18 +308,19 @@ useCustomerId() => null | 'guest' | 'registered'
|
|
|
303
308
|
### `useEncUserId()`
|
|
304
309
|
|
|
305
310
|
```ts
|
|
306
|
-
useEncUserId() =>
|
|
311
|
+
useEncUserId() => {encUserId: String, getEncUserIdWhenReady: Promise}
|
|
307
312
|
```
|
|
308
313
|
|
|
309
314
|
### `useUsid()`
|
|
310
315
|
|
|
311
316
|
```ts
|
|
312
|
-
useUsid() =>
|
|
317
|
+
useUsid() => {usid: String, getUsidWhenReady: Promise}
|
|
313
318
|
```
|
|
314
319
|
|
|
315
320
|
## Roadmap
|
|
316
|
-
|
|
317
|
-
-
|
|
321
|
+
|
|
322
|
+
- Optimistic update support
|
|
323
|
+
- SLAS private client support
|
|
318
324
|
|
|
319
325
|
## Useful Links:
|
|
320
326
|
|
package/hooks/useEncUserId.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @group Shopper Authentication helpers
|
|
3
|
+
*/
|
|
4
|
+
interface EncUserId {
|
|
5
|
+
encUserId: string | null;
|
|
6
|
+
getEncUserIdWhenReady: () => Promise<string>;
|
|
7
|
+
}
|
|
1
8
|
/**
|
|
2
9
|
* Hook that returns the ecom user ID.
|
|
3
10
|
*
|
|
@@ -7,6 +14,6 @@
|
|
|
7
14
|
* @category Shopper Authentication
|
|
8
15
|
*
|
|
9
16
|
*/
|
|
10
|
-
declare const useEncUserId: () =>
|
|
17
|
+
declare const useEncUserId: () => EncUserId;
|
|
11
18
|
export default useEncUserId;
|
|
12
19
|
//# sourceMappingURL=useEncUserId.d.ts.map
|
package/hooks/useEncUserId.js
CHANGED
|
@@ -17,6 +17,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
17
17
|
|
|
18
18
|
const onClient = typeof window !== 'undefined';
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @group Shopper Authentication helpers
|
|
22
|
+
*/
|
|
23
|
+
|
|
20
24
|
/**
|
|
21
25
|
* Hook that returns the ecom user ID.
|
|
22
26
|
*
|
|
@@ -29,11 +33,18 @@ const onClient = typeof window !== 'undefined';
|
|
|
29
33
|
const useEncUserId = () => {
|
|
30
34
|
const config = (0, _useConfig.default)();
|
|
31
35
|
const auth = (0, _useAuthContext.default)();
|
|
32
|
-
|
|
36
|
+
const encUserId = onClient ?
|
|
33
37
|
// This conditional is a constant value based on the environment, so the same path will
|
|
34
38
|
// always be followed., and the "rule of hooks" is not violated.
|
|
35
39
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
36
|
-
(0, _useLocalStorage.default)(
|
|
40
|
+
(0, _useLocalStorage.default)(`enc_user_id_${config.siteId}`) : auth.get('enc_user_id');
|
|
41
|
+
const getEncUserIdWhenReady = () => auth.ready().then(({
|
|
42
|
+
enc_user_id
|
|
43
|
+
}) => enc_user_id);
|
|
44
|
+
return {
|
|
45
|
+
encUserId,
|
|
46
|
+
getEncUserIdWhenReady
|
|
47
|
+
};
|
|
37
48
|
};
|
|
38
49
|
var _default = useEncUserId;
|
|
39
50
|
exports.default = _default;
|
package/hooks/useUsid.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @group Shopper Authentication helpers
|
|
3
|
+
*/
|
|
4
|
+
interface Usid {
|
|
5
|
+
usid: string | null;
|
|
6
|
+
getUsidWhenReady: () => Promise<string>;
|
|
7
|
+
}
|
|
1
8
|
/**
|
|
2
9
|
* Hook that returns the usid associated with the current access token.
|
|
3
10
|
*
|
|
4
11
|
* @group Helpers
|
|
5
12
|
* @category Shopper Authentication
|
|
6
13
|
*/
|
|
7
|
-
declare const useUsid: () =>
|
|
14
|
+
declare const useUsid: () => Usid;
|
|
8
15
|
export default useUsid;
|
|
9
16
|
//# sourceMappingURL=useUsid.d.ts.map
|
package/hooks/useUsid.js
CHANGED
|
@@ -5,8 +5,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _useAuthContext = _interopRequireDefault(require("./useAuthContext"));
|
|
8
|
-
var _useLocalStorage = _interopRequireDefault(require("./useLocalStorage"));
|
|
9
|
-
var _useConfig = _interopRequireDefault(require("./useConfig"));
|
|
10
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
9
|
/*
|
|
12
10
|
* Copyright (c) 2022, salesforce.com, inc.
|
|
@@ -15,7 +13,9 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
15
13
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
16
14
|
*/
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* @group Shopper Authentication helpers
|
|
18
|
+
*/
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Hook that returns the usid associated with the current access token.
|
|
@@ -24,13 +24,21 @@ const onClient = typeof window !== 'undefined';
|
|
|
24
24
|
* @category Shopper Authentication
|
|
25
25
|
*/
|
|
26
26
|
const useUsid = () => {
|
|
27
|
-
const config = (0, _useConfig.default)();
|
|
28
27
|
const auth = (0, _useAuthContext.default)();
|
|
29
|
-
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
|
|
28
|
+
|
|
29
|
+
// TODO: auth.get does not trigger a re-render.
|
|
30
|
+
// This is fine for now since the only time the usid changes is on logout
|
|
31
|
+
// and currently when we log out we redirect to the login page which
|
|
32
|
+
// causes components to unmount.
|
|
33
|
+
// This will need to change if we stay on the PDP after logout
|
|
34
|
+
const usid = auth.get('usid');
|
|
35
|
+
const getUsidWhenReady = () => auth.ready().then(({
|
|
36
|
+
usid
|
|
37
|
+
}) => usid);
|
|
38
|
+
return {
|
|
39
|
+
usid,
|
|
40
|
+
getUsidWhenReady
|
|
41
|
+
};
|
|
34
42
|
};
|
|
35
43
|
var _default = useUsid;
|
|
36
44
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/commerce-sdk-react",
|
|
3
|
-
"version": "1.0.0-preview.
|
|
3
|
+
"version": "1.0.0-preview.3",
|
|
4
4
|
"description": "A library that provides react hooks for fetching data from Commerce Cloud",
|
|
5
5
|
"homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/ecom-react-hooks#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"typedoc-plugin-missing-exports": "^2.0.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@salesforce/pwa-kit-dev": "3.0.0-preview.
|
|
50
|
+
"@salesforce/pwa-kit-dev": "3.0.0-preview.3",
|
|
51
51
|
"@tanstack/react-query": "^4.28.0",
|
|
52
52
|
"@testing-library/jest-dom": "^5.16.5",
|
|
53
53
|
"@testing-library/react": "^14.0.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"@types/react-dom": "^18.2.1",
|
|
60
60
|
"@types/react-helmet": "^6.1.6",
|
|
61
61
|
"cross-env": "^5.2.1",
|
|
62
|
-
"internal-lib-build": "3.0.0-preview.
|
|
62
|
+
"internal-lib-build": "3.0.0-preview.3",
|
|
63
63
|
"jsonwebtoken": "^9.0.0",
|
|
64
64
|
"nock": "^13.3.0",
|
|
65
65
|
"nodemon": "^2.0.22",
|
|
@@ -86,5 +86,5 @@
|
|
|
86
86
|
"publishConfig": {
|
|
87
87
|
"directory": "dist"
|
|
88
88
|
},
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "0d435ccfb378e46a536e0eb4da3c9d3364ce89ea"
|
|
90
90
|
}
|