@salesforce/commerce-sdk-react 1.0.0-preview.2 → 1.0.0-preview.4

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,6 +1,5 @@
1
- ## v1.0.0-preview.2 (Jun 05, 2023)
2
- ## v1.0.0-preview.1 (Jun 02, 2023)
3
- ## v1.0.0-preview.0 (May 31, 2023)
1
+ ## v1.0.0-preview.4 (Jun 14, 2023)
2
+ ## v1.0.0-preview.3 (Jun 13, 2023)
4
3
  ## v1.0.0-dev (May 29, 2023)
5
4
  ## v3.0.0-dev (May 12, 2023)
6
5
 
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
- - 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
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,10 +43,11 @@ 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.
50
+ // retry is always disabled on server side regardless of the value from the options
50
51
  const options = {
51
52
  queryClientConfig: {
52
53
  defaultOptions: {
@@ -65,13 +66,12 @@ export default withReactQuery(AppConfig, options)
65
66
 
66
67
  ## ⚡️ Quickstart (Generic React App)
67
68
 
68
- You can use this library in any React application by creating a new QueryClient and wrap your application with `QueryClientProvider`. For example:
69
+ You can use this library in any React application by creating a new QueryClient and wrap your application with `QueryClientProvider`. For example:
69
70
 
70
71
  ```jsx
71
72
  import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
72
73
  import {QueryClient, QueryClientProvider} from '@tanstack/react-query'
73
74
 
74
-
75
75
  const App = ({children}) => {
76
76
  const queryClient = new QueryClient()
77
77
 
@@ -91,7 +91,7 @@ const App = ({children}) => {
91
91
  </CommerceApiProvider>
92
92
  </QueryClientProvider>
93
93
  )
94
- }
94
+ }
95
95
 
96
96
  export default App
97
97
  ```
@@ -104,7 +104,7 @@ To help reduce boilerplate code for managing shopper authentication, by default,
104
104
 
105
105
  ### Shopper Session Initialization
106
106
 
107
- 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.
107
+ 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
108
 
109
109
  ### Authenticate request queue
110
110
 
@@ -136,19 +136,15 @@ You have the option of handling shopper authentication externally, by providing
136
136
 
137
137
  ```jsx
138
138
  const MyComponent = ({children}) => {
139
- return (
140
- <CommerceApiProvider fetchedToken="xxxxxxxxxxxx">
141
- {children}
142
- </CommerceApiProvider>
143
- )
144
- }
139
+ return <CommerceApiProvider fetchedToken="xxxxxxxxxxxx">{children}</CommerceApiProvider>
140
+ }
145
141
  ```
146
142
 
147
143
  ## Hooks
148
144
 
149
145
  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
146
 
151
- The hooks can be categorized into __Query hooks__ and __Mutation hooks__.
147
+ The hooks can be categorized into **Query hooks** and **Mutation hooks**.
152
148
 
153
149
  ### Query hooks
154
150
 
@@ -158,7 +154,7 @@ The query hooks correspond to the http GET endpoints from the SCAPI. The query h
158
154
  use<EntityName>(CommerceClientOptions, ReactQueryOptions)
159
155
  ```
160
156
 
161
- Both the __required__ and __optional__ parameters for the underlying `commerce-sdk-isomorphic` call is passed as the first parameter:
157
+ Both the **required** and **optional** parameters for the underlying `commerce-sdk-isomorphic` call is passed as the first parameter:
162
158
 
163
159
  ```jsx
164
160
  import {useProduct} from '@salesforce/commerce-sdk-react'
@@ -171,10 +167,12 @@ const Example = () => {
171
167
  }
172
168
  })
173
169
 
174
- return <>
175
- <p>isLoading: {query.isLoading}</p>
176
- <p>name: {query.data?.name}</p>
177
- </>
170
+ return (
171
+ <>
172
+ <p>isLoading: {query.isLoading}</p>
173
+ <p>name: {query.data?.name}</p>
174
+ </>
175
+ )
178
176
  }
179
177
  ```
180
178
 
@@ -186,15 +184,18 @@ import {useBasket} from '@salesforce/commerce-sdk-react'
186
184
  const onServer = typeof window === undefined
187
185
 
188
186
  const Example = ({basketId}) => {
189
- const query = useBasket({
190
- parameters: {
191
- basketId: basketId
187
+ const query = useBasket(
188
+ {
189
+ parameters: {
190
+ basketId: basketId
191
+ }
192
192
  },
193
- }, {
194
- // A common use case for `enabled` is
195
- // to conditionally fetch based on environment
196
- enabled: !onServer && basketId
197
- })
193
+ {
194
+ // A common use case for `enabled` is
195
+ // to conditionally fetch based on environment
196
+ enabled: !onServer && basketId
197
+ }
198
+ )
198
199
  }
199
200
  ```
200
201
 
@@ -215,16 +216,22 @@ const Example = ({basketId}) => {
215
216
  // Typescript IDE intellisense for available options
216
217
  const addItemToBasket = useShopperBasketsMutation('addItemToBasket')
217
218
 
218
- return <button onClick={() => addItemToBasket.mutate({
219
- parameters: {
220
- basketId
221
- },
222
- body: {
223
- productId: '25592770M',
224
- price: 55,
225
- quantity: 1
226
- }
227
- })} />
219
+ return (
220
+ <button
221
+ onClick={() =>
222
+ addItemToBasket.mutate({
223
+ parameters: {
224
+ basketId
225
+ },
226
+ body: {
227
+ productId: '25592770M',
228
+ price: 55,
229
+ quantity: 1
230
+ }
231
+ })
232
+ }
233
+ />
234
+ )
228
235
  }
229
236
  ```
230
237
 
@@ -247,7 +254,7 @@ const Example = ({basketId}) => {
247
254
 
248
255
  Since mutations changes data on the server, the cache entries that are potentially affected by the mutation is automatically invalidated.
249
256
 
250
- 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.
257
+ 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
258
 
252
259
  _💡 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
260
 
@@ -269,14 +276,13 @@ const Example = () => {
269
276
  const fetchProducts = async () => {
270
277
  const token = await getTokenWhenReady()
271
278
  const products = await api.shopperProducts.getProducts({
272
- parameters: {ids: ids.join(',')},
273
- headers: {
274
- Authorization: `Bearer ${token}`
275
- }
276
- })
279
+ parameters: {ids: ids.join(',')},
280
+ headers: {
281
+ Authorization: `Bearer ${token}`
282
+ }
283
+ })
277
284
  return products
278
285
  }
279
-
280
286
  }
281
287
  ```
282
288
 
@@ -303,18 +309,19 @@ useCustomerId() => null | 'guest' | 'registered'
303
309
  ### `useEncUserId()`
304
310
 
305
311
  ```ts
306
- useEncUserId() => null | string
312
+ useEncUserId() => {encUserId: String, getEncUserIdWhenReady: Promise}
307
313
  ```
308
314
 
309
315
  ### `useUsid()`
310
316
 
311
317
  ```ts
312
- useUsid() => null | string
318
+ useUsid() => {usid: String, getUsidWhenReady: Promise}
313
319
  ```
314
320
 
315
321
  ## Roadmap
316
- - Optimistic update support
317
- - SLAS private client support
322
+
323
+ - Optimistic update support
324
+ - SLAS private client support
318
325
 
319
326
  ## Useful Links:
320
327
 
@@ -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: () => string | null;
17
+ declare const useEncUserId: () => EncUserId;
11
18
  export default useEncUserId;
12
19
  //# sourceMappingURL=useEncUserId.d.ts.map
@@ -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
- return onClient ?
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)(`$enc_user_id_${config.siteId}`) : auth.get('enc_user_id');
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/useQuery.js CHANGED
@@ -7,6 +7,7 @@ exports.useQuery = void 0;
7
7
  var _reactQuery = require("@tanstack/react-query");
8
8
  var _useAuthorizationHeader = require("./useAuthorizationHeader");
9
9
  var _utils = require("./utils");
10
+ var _utils2 = require("../utils");
10
11
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
11
12
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
12
13
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
@@ -45,13 +46,17 @@ const useQuery = (apiOptions, queryOptions, hookConfig) => {
45
46
  return _ref.apply(this, arguments);
46
47
  };
47
48
  }();
48
- return (0, _reactQuery.useQuery)(hookConfig.queryKey, wrappedMethod, _objectSpread({
49
+ return (0, _reactQuery.useQuery)(hookConfig.queryKey, wrappedMethod, _objectSpread(_objectSpread(_objectSpread({
49
50
  enabled:
50
51
  // Individual hooks can provide `enabled` checks that are done in ADDITION to
51
52
  // the required parameter check
52
53
  hookConfig.enabled !== false &&
53
54
  // The default `enabled` is "has all required parameters"
54
55
  (0, _utils.hasAllKeys)(apiOptions.parameters, hookConfig.requiredParameters)
55
- }, queryOptions));
56
+ }, queryOptions), queryOptions !== null && queryOptions !== void 0 && queryOptions.retry ? {
57
+ retry: (0, _utils2.onClient)() ? queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.retry : false
58
+ } : {}), queryOptions !== null && queryOptions !== void 0 && queryOptions.retryOnMount ? {
59
+ retryOnMount: (0, _utils2.onClient)() ? queryOptions === null || queryOptions === void 0 ? void 0 : queryOptions.retryOnMount : false
60
+ } : {}));
56
61
  };
57
62
  exports.useQuery = useQuery;
@@ -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: () => string | null;
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
- const onClient = typeof window !== 'undefined';
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
- return onClient ?
30
- // This conditional is a constant value based on the environment, so the same path will
31
- // always be followed., and the "rule of hooks" is not violated.
32
- // eslint-disable-next-line react-hooks/rules-of-hooks
33
- (0, _useLocalStorage.default)(`usid_${config.siteId}`) : auth.get('usid');
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.2",
3
+ "version": "1.0.0-preview.4",
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.2",
50
+ "@salesforce/pwa-kit-dev": "3.0.0-preview.4",
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.2",
62
+ "internal-lib-build": "3.0.0-preview.4",
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": "a2476c090ce48fd09e9116437aedc6cc45ae60bd"
89
+ "gitHead": "06b3f17fd233777136fdb699aa93df4c52874217"
90
90
  }