@salesforce/commerce-sdk-react 3.2.0-preview.3 → 3.2.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,17 +1,21 @@
1
- ## v4.0.0-extensibility-preview.3 (Dec 13, 2024)
2
- ## v3.1.1-preview.3 (Dec 13, 2024)
3
- ## v3.1.1-preview.3 (Dec 13, 2024)
4
- ## v3.1.1-preview.2 (Dec 09, 2024)
5
- ## v3.1.1-preview.1 (Dec 09, 2024)
6
- ## v4.0.0-extensibility-preview.2 (Dec 09, 2024)
7
- ## v3.1.1-preview.1 (Dec 09, 2024)
8
- ## v3.1.1-preview.0 (Dec 02, 2024)
1
+ ## v3.2.0-preview.4 (Feb 14, 2025)
2
+ ## v3.2.0-preview.3 (Feb 13, 2025)
3
+ ## v3.2.0-preview.2 (Feb 13, 2025)
4
+ ## v3.9.0-preview.3 (Feb 13, 2025)
5
+ ## v3.2.0-preview.2 (Feb 13, 2025)
6
+ ## v3.2.0-preview.1 (Feb 13, 2025)
7
+ ## v3.9.0-preview.2 (Feb 13, 2025)
8
+ ## v3.2.0-preview.1 (Feb 12, 2025)
9
+ ## v3.2.0-preview.0 (Feb 03, 2025)
9
10
  ## v3.2.0-dev (Oct 29, 2024)
10
11
  - Allow cookies for ShopperLogin API [#2190](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2190
11
12
  - Fix refresh token TTL warning from firing when override is not provided [#2114](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2114)
12
-
13
+ - Readme updates for private clients [#2212](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2212)
13
14
  - Update CacheUpdateMatrix for mergeBasket mutation [#2138](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2092)
14
15
  - Clear auth state if session has been invalidated by a password change [#2092](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2092)
16
+ - DNT interface improvement [#2203](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2203)
17
+ - Support Node 22 [#2218](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2218)
18
+ - Add `authorizeIDP`, `loginIDPUser`, `authorizePasswordless`, `getPasswordLessAccessToken`, `getPasswordResetToken`, and `resetPassword` wrapper functions to support Social Login, Passwordless Login, and Password Reset [#2079] (https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2079)
15
19
 
16
20
  ## v3.1.0 (Oct 28, 2024)
17
21
 
package/README.md CHANGED
@@ -43,7 +43,7 @@ In practice, we recommend:
43
43
  npm install @salesforce/commerce-sdk-react @tanstack/react-query
44
44
  ```
45
45
 
46
- ## ⚡️ Quickstart (PWA Kit v2.3.0+)
46
+ ## ⚡️ Quickstart (PWA Kit v3.0+)
47
47
 
48
48
  To integrate this library with your PWA Kit application you can use the `CommerceApiProvider` directly assuming that you use the `withReactQuery` higher order component to wrap your `AppConfig` component. Below is a snippet of how this is accomplished.
49
49
 
@@ -54,6 +54,10 @@ import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
54
54
  import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
55
55
 
56
56
  const AppConfig = ({children}) => {
57
+ const headers = {
58
+ 'correlation-id': correlationId
59
+ }
60
+
57
61
  return (
58
62
  <CommerceApiProvider
59
63
  clientId="12345678-1234-1234-1234-123412341234"
@@ -64,6 +68,11 @@ const AppConfig = ({children}) => {
64
68
  shortCode="12345678"
65
69
  locale="en-US"
66
70
  currency="USD"
71
+ headers={headers}
72
+ // Uncomment 'enablePWAKitPrivateClient' to use SLAS private client login flows.
73
+ // Make sure to also enable useSLASPrivateClient in ssr.js when enabling this setting.
74
+ // enablePWAKitPrivateClient={true}
75
+ logger={createLogger({packageName: 'commerce-sdk-react'})}
67
76
  >
68
77
  {children}
69
78
  </CommerceApiProvider>
@@ -125,68 +134,10 @@ export default App
125
134
 
126
135
  _💡 This section assumes you have read and completed the [Authorization for Shopper APIs](https://developer.salesforce.com/docs/commerce/commerce-api/guide/authorization-for-shopper-apis.html) guide._
127
136
 
128
- To help reduce boilerplate code for managing shopper authentication, by default, this library automatically initializes shopper session and manages the tokens for developers. Currently, the library supports the [Public Client login flow](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-public-client.html).
129
-
130
- Commerce-react-sdk supports both public and private flow of the [Authorization for Shopper APIs](https://developer.salesforce.com/docs/commerce/commerce-api/guide/authorization-for-shopper-apis.html) guide._
131
- You can choose to use either public or private slas to login. By default, public flow is enabled.
132
-
133
- #### How private SLAS works
134
- This section assumes you read and understand how [private SLAS](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-private-client.html) flow works
135
-
136
- To enable private slas flow, you need to pass your secret into the CommercerProvider via clientSecret prop.
137
- **Note** You should only use private slas if you know you can secure your secret since commercer-sdk-react runs isomorphically.
138
-
139
- ```js
140
- // app/components/_app-config/index.jsx
141
-
142
- import {CommerceApiProvider} from '@salesforce/commerce-sdk-react'
143
- import {withReactQuery} from '@salesforce/pwa-kit-react-sdk/ssr/universal/components/with-react-query'
144
-
145
- const AppConfig = ({children}) => {
146
- return (
147
- <CommerceApiProvider
148
- clientId="12345678-1234-1234-1234-123412341234"
149
- organizationId="f_ecom_aaaa_001"
150
- proxy="localhost:3000/mobify/proxy/api"
151
- redirectURI="localhost:3000/callback"
152
- siteId="RefArch"
153
- shortCode="12345678"
154
- locale="en-US"
155
- currency="USD"
156
- clientSecret="<your-slas-private-secret>"
157
- >
158
- {children}
159
- </CommerceApiProvider>
160
- )
161
- }
162
- ```
163
- #### Disable slas private warnings
164
- By default, a warning as below will be displayed on client side to remind developers to always keep their secret safe and secured.
165
- ```js
166
- 'You are potentially exposing SLAS secret on browser. Make sure to keep it safe and secure!'
167
- ```
168
- You can disable this warning by using CommerceProvider prop `silenceWarnings`
137
+ To help reduce boilerplate code for managing shopper authentication, by default, this library automatically initializes shopper session and manages the tokens for developers. Commerce-sdk-react supports both the [SLAS Public Client login flow](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-public-client.html) and [SLAS Private Client login flow](https://developer.salesforce.com/docs/commerce/commerce-api/guide/slas-private-client.html). Authorization using a private client is supported in PWA Kit 3.5 and later, and is the recommended authorization workflow.
169
138
 
170
- ```js
171
- const AppConfig = ({children}) => {
172
- return (
173
- <CommerceApiProvider
174
- clientId="12345678-1234-1234-1234-123412341234"
175
- organizationId="f_ecom_aaaa_001"
176
- proxy="localhost:3000/mobify/proxy/api"
177
- redirectURI="localhost:3000/callback"
178
- siteId="RefArch"
179
- shortCode="12345678"
180
- locale="en-US"
181
- currency="USD"
182
- clientSecret="<your-slas-private-secret>"
183
- silenceWarnings={true}
184
- >
185
- {children}
186
- </CommerceApiProvider>
187
- )
188
- }
189
- ```
139
+ #### Using a private SLAS client
140
+ To enable a private client, see [Use a SLAS Private Client](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/use-a-slas-private-client.html).
190
141
 
191
142
  ### Shopper Session Initialization
192
143
 
package/auth/index.d.ts CHANGED
@@ -15,9 +15,15 @@ interface AuthConfig extends ApiClientConfigParams {
15
15
  silenceWarnings?: boolean;
16
16
  logger: Logger;
17
17
  defaultDnt?: boolean;
18
+ passwordlessLoginCallbackURI?: string;
18
19
  refreshTokenRegisteredCookieTTL?: number;
19
20
  refreshTokenGuestCookieTTL?: number;
20
21
  }
22
+ type AuthorizeIDPParams = Parameters<Helpers['authorizeIDP']>[1];
23
+ type LoginIDPUserParams = Parameters<Helpers['loginIDPUser']>[2];
24
+ type AuthorizePasswordlessParams = Parameters<Helpers['authorizePasswordless']>[2];
25
+ type LoginPasswordlessParams = Parameters<Helpers['getPasswordLessAccessToken']>[2];
26
+ type LoginRegisteredUserB2CCredentials = Parameters<Helpers['loginRegisteredUserB2C']>[1];
21
27
  /**
22
28
  * The extended field is not from api response, we manually store the auth type,
23
29
  * so we don't need to make another API call when we already have the data.
@@ -29,7 +35,10 @@ export type AuthData = Prettify<RemoveStringIndex<TokenResponse> & {
29
35
  idp_access_token: string;
30
36
  }>;
31
37
  /** A shopper could be guest or registered, so we store the refresh tokens individually. */
32
- type AuthDataKeys = Exclude<keyof AuthData, 'refresh_token'> | 'refresh_token_guest' | 'refresh_token_registered' | 'access_token_sfra' | typeof DNT_COOKIE_NAME | typeof DWSID_COOKIE_NAME;
38
+ type AuthDataKeys = Exclude<keyof AuthData, 'refresh_token'> | 'refresh_token_guest' | 'refresh_token_registered' | 'access_token_sfra' | typeof DNT_COOKIE_NAME | typeof DWSID_COOKIE_NAME | 'code_verifier' | 'uido';
39
+ type DntOptions = {
40
+ includeDefaults: boolean;
41
+ };
33
42
  export declare const DEFAULT_SLAS_REFRESH_TOKEN_REGISTERED_TTL: number;
34
43
  export declare const DEFAULT_SLAS_REFRESH_TOKEN_GUEST_TTL: number;
35
44
  /**
@@ -51,6 +60,8 @@ declare class Auth {
51
60
  private silenceWarnings;
52
61
  private logger;
53
62
  private defaultDnt;
63
+ private isPrivate;
64
+ private passwordlessLoginCallbackURI;
54
65
  private refreshTokenRegisteredCookieTTL;
55
66
  private refreshTokenGuestCookieTTL;
56
67
  private refreshTrustedAgentHandler;
@@ -58,7 +69,20 @@ declare class Auth {
58
69
  get(name: AuthDataKeys): string;
59
70
  private set;
60
71
  private delete;
61
- getDnt(): boolean | undefined;
72
+ /**
73
+ * Return the value of the DNT cookie or undefined if it is not set.
74
+ * The DNT cookie being undefined means that there is a necessity to
75
+ * get the user's input for consent tracking, but not that there is no
76
+ * DNT value to apply to analytics layers. DNT value will default to
77
+ * a certain value and this is reflected by effectiveDnt.
78
+ *
79
+ * If the cookie value is invalid, then it will be deleted in this function.
80
+ *
81
+ * If includeDefaults is true, then even if the cookie is not defined,
82
+ * defaultDnt will be returned, if it exists. If defaultDnt is not defined, then
83
+ * the SDK Default will return (false)
84
+ */
85
+ getDnt(options?: DntOptions): boolean | undefined;
62
86
  setDnt(preference: boolean | null): Promise<void>;
63
87
  private clearStorage;
64
88
  /**
@@ -69,11 +93,6 @@ declare class Auth {
69
93
  * Used to validate JWT token expiration.
70
94
  */
71
95
  private isTokenExpired;
72
- /**
73
- * Gets the Do-Not-Track (DNT) preference from the `dw_dnt` cookie.
74
- * If user has set their DNT preference, read the cookie, if not, use the default DNT pref. If the default DNT pref has not been set, default to false.
75
- */
76
- private getDntPreference;
77
96
  /**
78
97
  * Returns the SLAS access token or an empty string if the access token
79
98
  * is not found in local store or if SFRA wants PWA to trigger refresh token login.
@@ -224,6 +243,7 @@ declare class Auth {
224
243
  fax?: string | undefined;
225
244
  firstName?: string | undefined;
226
245
  gender?: number | undefined;
246
+ hashedLogin?: string | undefined;
227
247
  jobTitle?: string | undefined;
228
248
  lastLoginTime?: any;
229
249
  lastModified?: any;
@@ -283,7 +303,7 @@ declare class Auth {
283
303
  * A wrapper method for commerce-sdk-isomorphic helper: loginRegisteredUserB2C.
284
304
  *
285
305
  */
286
- loginRegisteredUserB2C(credentials: Parameters<Helpers['loginRegisteredUserB2C']>[1]): Promise<helpers.TokenResponse>;
306
+ loginRegisteredUserB2C(credentials: LoginRegisteredUserB2CCredentials): Promise<helpers.TokenResponse>;
287
307
  /**
288
308
  * Trusted agent authorization
289
309
  *
@@ -343,6 +363,34 @@ declare class Auth {
343
363
  currentPassword: string;
344
364
  shouldReloginCurrentSession?: boolean;
345
365
  }): Promise<void>;
366
+ /**
367
+ * A wrapper method for commerce-sdk-isomorphic helper: authorizeIDP.
368
+ *
369
+ */
370
+ authorizeIDP(parameters: AuthorizeIDPParams): Promise<void>;
371
+ /**
372
+ * A wrapper method for commerce-sdk-isomorphic helper: loginIDPUser.
373
+ *
374
+ */
375
+ loginIDPUser(parameters: LoginIDPUserParams): Promise<helpers.TokenResponse>;
376
+ /**
377
+ * A wrapper method for commerce-sdk-isomorphic helper: authorizePasswordless.
378
+ */
379
+ authorizePasswordless(parameters: AuthorizePasswordlessParams): Promise<Response>;
380
+ /**
381
+ * A wrapper method for commerce-sdk-isomorphic helper: getPasswordLessAccessToken.
382
+ */
383
+ getPasswordLessAccessToken(parameters: LoginPasswordlessParams): Promise<helpers.TokenResponse>;
384
+ /**
385
+ * A wrapper method for the SLAS endpoint: getPasswordResetToken.
386
+ *
387
+ */
388
+ getPasswordResetToken(parameters: ShopperLoginTypes.PasswordActionRequest): Promise<void>;
389
+ /**
390
+ * A wrapper method for the SLAS endpoint: resetPassword.
391
+ *
392
+ */
393
+ resetPassword(parameters: ShopperLoginTypes.PasswordActionVerifyRequest): Promise<void>;
346
394
  /**
347
395
  * Decode SLAS JWT and extract information such as customer id, usid, etc.
348
396
  *
@@ -355,6 +403,7 @@ declare class Auth {
355
403
  loginId: string;
356
404
  isAgent: boolean;
357
405
  agentId: string | null;
406
+ uido: string;
358
407
  };
359
408
  }
360
409
  export default Auth;
package/auth/index.js CHANGED
@@ -115,6 +115,14 @@ const DATA_MAP = {
115
115
  dwsid: {
116
116
  storageType: 'cookie',
117
117
  key: _constant.DWSID_COOKIE_NAME
118
+ },
119
+ code_verifier: {
120
+ storageType: 'local',
121
+ key: 'code_verifier'
122
+ },
123
+ uido: {
124
+ storageType: 'local',
125
+ key: 'uido'
118
126
  }
119
127
  };
120
128
  const DEFAULT_SLAS_REFRESH_TOKEN_REGISTERED_TTL = exports.DEFAULT_SLAS_REFRESH_TOKEN_REGISTERED_TTL = 90 * 24 * 60 * 60;
@@ -205,6 +213,9 @@ class Auth {
205
213
  // PWA users should not need to touch this.
206
214
  config.clientSecret || '';
207
215
  this.silenceWarnings = config.silenceWarnings || false;
216
+ this.isPrivate = !!this.clientSecret;
217
+ const passwordlessLoginCallbackURI = config.passwordlessLoginCallbackURI;
218
+ this.passwordlessLoginCallbackURI = passwordlessLoginCallbackURI ? (0, _utils.isAbsoluteUrl)(passwordlessLoginCallbackURI) ? passwordlessLoginCallbackURI : `${baseUrl}${passwordlessLoginCallbackURI}` : '';
208
219
  }
209
220
  get(name) {
210
221
  const {
@@ -232,9 +243,22 @@ class Auth {
232
243
  const storage = this.stores[storageType];
233
244
  storage.delete(key);
234
245
  }
235
- getDnt() {
246
+
247
+ /**
248
+ * Return the value of the DNT cookie or undefined if it is not set.
249
+ * The DNT cookie being undefined means that there is a necessity to
250
+ * get the user's input for consent tracking, but not that there is no
251
+ * DNT value to apply to analytics layers. DNT value will default to
252
+ * a certain value and this is reflected by effectiveDnt.
253
+ *
254
+ * If the cookie value is invalid, then it will be deleted in this function.
255
+ *
256
+ * If includeDefaults is true, then even if the cookie is not defined,
257
+ * defaultDnt will be returned, if it exists. If defaultDnt is not defined, then
258
+ * the SDK Default will return (false)
259
+ */
260
+ getDnt(options) {
236
261
  const dntCookieVal = this.get(_constant.DNT_COOKIE_NAME);
237
- // Only '1' or '0' are valid, and invalid values, lack of cookie, or value conflict with token must be an undefined DNT
238
262
  let dntCookieStatus = undefined;
239
263
  const accessToken = this.getAccessToken();
240
264
  let isInSync = true;
@@ -249,6 +273,19 @@ class Auth {
249
273
  } else {
250
274
  dntCookieStatus = Boolean(Number(dntCookieVal));
251
275
  }
276
+ if (options !== null && options !== void 0 && options.includeDefaults) {
277
+ const defaultDnt = this.defaultDnt;
278
+ let effectiveDnt;
279
+ const dntCookie = dntCookieVal === '1' ? true : dntCookieVal === '0' ? false : undefined;
280
+ if (dntCookie !== undefined) {
281
+ effectiveDnt = dntCookie;
282
+ } else {
283
+ // If the cookie is not set, read the defaultDnt preference.
284
+ // If defaultDnt doesn't exist, default to false, following SLAS default for dnt
285
+ effectiveDnt = defaultDnt !== undefined ? defaultDnt : false;
286
+ }
287
+ return effectiveDnt;
288
+ }
252
289
  return dntCookieStatus;
253
290
  }
254
291
  setDnt(preference) {
@@ -328,21 +365,6 @@ class Auth {
328
365
  return validTimeSeconds <= tokenAgeSeconds;
329
366
  }
330
367
 
331
- /**
332
- * Gets the Do-Not-Track (DNT) preference from the `dw_dnt` cookie.
333
- * If user has set their DNT preference, read the cookie, if not, use the default DNT pref. If the default DNT pref has not been set, default to false.
334
- */
335
- getDntPreference(dw_dnt, defaultDnt) {
336
- let dntPref;
337
- // Read `dw_dnt` cookie
338
- const dntCookie = dw_dnt === '1' ? true : dw_dnt === '0' ? false : undefined;
339
- dntPref = dntCookie;
340
-
341
- // If the cookie is not set, read the default DNT preference.
342
- if (dntCookie === undefined) dntPref = defaultDnt !== undefined ? defaultDnt : undefined;
343
- return dntPref;
344
- }
345
-
346
368
  /**
347
369
  * Returns the SLAS access token or an empty string if the access token
348
370
  * is not found in local store or if SFRA wants PWA to trigger refresh token login.
@@ -474,6 +496,12 @@ class Auth {
474
496
  const responseValue = res.refresh_token_expires_in;
475
497
  const defaultValue = isGuest ? DEFAULT_SLAS_REFRESH_TOKEN_GUEST_TTL : DEFAULT_SLAS_REFRESH_TOKEN_REGISTERED_TTL;
476
498
  const refreshTokenTTLValue = this.getRefreshTokenCookieTTLValue(overrideValue, responseValue, defaultValue);
499
+ if (res.access_token) {
500
+ const {
501
+ uido
502
+ } = this.parseSlasJWT(res.access_token);
503
+ this.set('uido', uido);
504
+ }
477
505
  const expiresDate = this.convertSecondsToDate(refreshTokenTTLValue);
478
506
  this.set('refresh_token_expires_in', refreshTokenTTLValue.toString());
479
507
  this.set(refreshTokenKey, res.refresh_token, {
@@ -483,17 +511,18 @@ class Auth {
483
511
  refreshAccessToken() {
484
512
  var _this2 = this;
485
513
  return _asyncToGenerator(function* () {
486
- const dntPref = _this2.getDntPreference(_this2.get(_constant.DNT_COOKIE_NAME), _this2.defaultDnt);
514
+ const dntPref = _this2.getDnt({
515
+ includeDefaults: true
516
+ });
487
517
  const refreshTokenRegistered = _this2.get('refresh_token_registered');
488
518
  const refreshTokenGuest = _this2.get('refresh_token_guest');
489
519
  const refreshToken = refreshTokenRegistered || refreshTokenGuest;
490
520
  if (refreshToken) {
491
521
  try {
492
- return yield _this2.queueRequest(() => _commerceSdkIsomorphic.helpers.refreshAccessToken(_this2.client, _objectSpread({
493
- refreshToken
494
- }, dntPref !== undefined && {
522
+ return yield _this2.queueRequest(() => _commerceSdkIsomorphic.helpers.refreshAccessToken(_this2.client, {
523
+ refreshToken,
495
524
  dnt: dntPref
496
- }), {
525
+ }, {
497
526
  clientSecret: _this2.clientSecret
498
527
  }), !!refreshTokenGuest);
499
528
  } catch (error) {
@@ -553,7 +582,7 @@ class Auth {
553
582
  var _this3 = this;
554
583
  return _asyncToGenerator(function* () {
555
584
  const queue = _this3.pendingToken ?? Promise.resolve();
556
- _this3.pendingToken = queue.then(/*#__PURE__*/_asyncToGenerator(function* () {
585
+ _this3.pendingToken = queue.then( /*#__PURE__*/_asyncToGenerator(function* () {
557
586
  const token = yield fn();
558
587
  _this3.handleTokenResponse(token, isGuest);
559
588
  // Q: Why don't we just return token? Why re-construct the same object again?
@@ -670,20 +699,21 @@ class Auth {
670
699
  _this6.logWarning(_constant.SLAS_SECRET_WARNING_MSG);
671
700
  }
672
701
  const usid = _this6.get('usid');
673
- const dntPref = _this6.getDntPreference(_this6.get(_constant.DNT_COOKIE_NAME), _this6.defaultDnt);
702
+ const dntPref = _this6.getDnt({
703
+ includeDefaults: true
704
+ });
674
705
  const isGuest = true;
675
- const guestPrivateArgs = [_this6.client, _objectSpread(_objectSpread({}, dntPref !== undefined && {
706
+ const guestPrivateArgs = [_this6.client, _objectSpread({
676
707
  dnt: dntPref
677
- }), usid && {
708
+ }, usid && {
678
709
  usid
679
710
  }), {
680
711
  clientSecret: _this6.clientSecret
681
712
  }];
682
- const guestPublicArgs = [_this6.client, _objectSpread(_objectSpread({
683
- redirectURI: _this6.redirectURI
684
- }, dntPref !== undefined && {
713
+ const guestPublicArgs = [_this6.client, _objectSpread({
714
+ redirectURI: _this6.redirectURI,
685
715
  dnt: dntPref
686
- }), usid && {
716
+ }, usid && {
687
717
  usid
688
718
  })];
689
719
  const callback = _this6.clientSecret ? () => _commerceSdkIsomorphic.helpers.loginGuestUserPrivate(...guestPrivateArgs) : () => _commerceSdkIsomorphic.helpers.loginGuestUser(...guestPublicArgs);
@@ -748,15 +778,16 @@ class Auth {
748
778
  }
749
779
  const redirectURI = _this8.redirectURI;
750
780
  const usid = _this8.get('usid');
751
- const dntPref = _this8.getDntPreference(_this8.get(_constant.DNT_COOKIE_NAME), _this8.defaultDnt);
781
+ const dntPref = _this8.getDnt({
782
+ includeDefaults: true
783
+ });
752
784
  const isGuest = false;
753
785
  const token = yield _commerceSdkIsomorphic.helpers.loginRegisteredUserB2C(_this8.client, _objectSpread(_objectSpread({}, credentials), {}, {
754
786
  clientSecret: _this8.clientSecret
755
- }), _objectSpread(_objectSpread({
756
- redirectURI
757
- }, dntPref !== undefined && {
787
+ }), _objectSpread({
788
+ redirectURI,
758
789
  dnt: dntPref
759
- }), usid && {
790
+ }, usid && {
760
791
  usid
761
792
  }));
762
793
  _this8.handleTokenResponse(token, isGuest);
@@ -916,6 +947,186 @@ class Auth {
916
947
  })();
917
948
  }
918
949
 
950
+ /**
951
+ * A wrapper method for commerce-sdk-isomorphic helper: authorizeIDP.
952
+ *
953
+ */
954
+ authorizeIDP(parameters) {
955
+ var _this14 = this;
956
+ return _asyncToGenerator(function* () {
957
+ const redirectURI = parameters.redirectURI || _this14.redirectURI;
958
+ const usid = _this14.get('usid');
959
+ const {
960
+ url,
961
+ codeVerifier
962
+ } = yield _commerceSdkIsomorphic.helpers.authorizeIDP(_this14.client, _objectSpread({
963
+ redirectURI,
964
+ hint: parameters.hint
965
+ }, usid && {
966
+ usid
967
+ }), _this14.isPrivate);
968
+ if ((0, _utils.onClient)()) {
969
+ window.location.assign(url);
970
+ } else {
971
+ console.warn('Something went wrong, this client side method is invoked on the server.');
972
+ }
973
+ _this14.set('code_verifier', codeVerifier);
974
+ })();
975
+ }
976
+
977
+ /**
978
+ * A wrapper method for commerce-sdk-isomorphic helper: loginIDPUser.
979
+ *
980
+ */
981
+ loginIDPUser(parameters) {
982
+ var _this15 = this;
983
+ return _asyncToGenerator(function* () {
984
+ const codeVerifier = _this15.get('code_verifier');
985
+ const code = parameters.code;
986
+ const usid = parameters.usid || _this15.get('usid');
987
+ const redirectURI = parameters.redirectURI || _this15.redirectURI;
988
+ const dntPref = _this15.getDnt({
989
+ includeDefaults: true
990
+ });
991
+ const token = yield _commerceSdkIsomorphic.helpers.loginIDPUser(_this15.client, {
992
+ codeVerifier,
993
+ clientSecret: _this15.clientSecret
994
+ }, _objectSpread({
995
+ redirectURI,
996
+ code,
997
+ dnt: dntPref
998
+ }, usid && {
999
+ usid
1000
+ }));
1001
+ const isGuest = false;
1002
+ _this15.handleTokenResponse(token, isGuest);
1003
+ // Delete the code verifier once the user has logged in
1004
+ _this15.delete('code_verifier');
1005
+ if ((0, _utils.onClient)()) {
1006
+ void _this15.clearECOMSession();
1007
+ }
1008
+ return token;
1009
+ })();
1010
+ }
1011
+
1012
+ /**
1013
+ * A wrapper method for commerce-sdk-isomorphic helper: authorizePasswordless.
1014
+ */
1015
+ authorizePasswordless(parameters) {
1016
+ var _this16 = this;
1017
+ return _asyncToGenerator(function* () {
1018
+ const userid = parameters.userid;
1019
+ const callbackURI = parameters.callbackURI || _this16.passwordlessLoginCallbackURI;
1020
+ const usid = _this16.get('usid');
1021
+ const mode = callbackURI ? 'callback' : 'sms';
1022
+ const res = yield _commerceSdkIsomorphic.helpers.authorizePasswordless(_this16.client, {
1023
+ clientSecret: _this16.clientSecret
1024
+ }, _objectSpread(_objectSpread(_objectSpread({}, callbackURI && {
1025
+ callbackURI: callbackURI
1026
+ }), usid && {
1027
+ usid
1028
+ }), {}, {
1029
+ userid,
1030
+ mode
1031
+ }));
1032
+ if (res && res.status !== 200) {
1033
+ const errorData = yield res.json();
1034
+ throw new Error(`${res.status} ${String(errorData.message)}`);
1035
+ }
1036
+ return res;
1037
+ })();
1038
+ }
1039
+
1040
+ /**
1041
+ * A wrapper method for commerce-sdk-isomorphic helper: getPasswordLessAccessToken.
1042
+ */
1043
+ getPasswordLessAccessToken(parameters) {
1044
+ var _this17 = this;
1045
+ return _asyncToGenerator(function* () {
1046
+ const pwdlessLoginToken = parameters.pwdlessLoginToken;
1047
+ const dntPref = _this17.getDnt({
1048
+ includeDefaults: true
1049
+ });
1050
+ const token = yield _commerceSdkIsomorphic.helpers.getPasswordLessAccessToken(_this17.client, {
1051
+ clientSecret: _this17.clientSecret
1052
+ }, {
1053
+ pwdlessLoginToken,
1054
+ dnt: dntPref !== undefined ? String(dntPref) : undefined
1055
+ });
1056
+ const isGuest = false;
1057
+ _this17.handleTokenResponse(token, isGuest);
1058
+ if ((0, _utils.onClient)()) {
1059
+ void _this17.clearECOMSession();
1060
+ }
1061
+ return token;
1062
+ })();
1063
+ }
1064
+
1065
+ /**
1066
+ * A wrapper method for the SLAS endpoint: getPasswordResetToken.
1067
+ *
1068
+ */
1069
+ getPasswordResetToken(parameters) {
1070
+ var _this18 = this;
1071
+ return _asyncToGenerator(function* () {
1072
+ const slasClient = _this18.client;
1073
+ const callbackURI = parameters.callback_uri;
1074
+ const options = {
1075
+ headers: {
1076
+ Authorization: ''
1077
+ },
1078
+ body: {
1079
+ user_id: parameters.user_id,
1080
+ mode: 'callback',
1081
+ channel_id: slasClient.clientConfig.parameters.siteId,
1082
+ client_id: slasClient.clientConfig.parameters.clientId,
1083
+ callback_uri: callbackURI,
1084
+ hint: 'cross_device'
1085
+ }
1086
+ };
1087
+
1088
+ // Only set authorization header if using private client
1089
+ if (_this18.clientSecret) {
1090
+ options.headers.Authorization = `Basic ${(0, _utils.stringToBase64)(`${slasClient.clientConfig.parameters.clientId}:${_this18.clientSecret}`)}`;
1091
+ }
1092
+ const res = yield slasClient.getPasswordResetToken(options);
1093
+ return res;
1094
+ })();
1095
+ }
1096
+
1097
+ /**
1098
+ * A wrapper method for the SLAS endpoint: resetPassword.
1099
+ *
1100
+ */
1101
+ resetPassword(parameters) {
1102
+ var _this19 = this;
1103
+ return _asyncToGenerator(function* () {
1104
+ const slasClient = _this19.client;
1105
+ const options = {
1106
+ headers: {
1107
+ Authorization: ''
1108
+ },
1109
+ body: {
1110
+ pwd_action_token: parameters.pwd_action_token,
1111
+ channel_id: slasClient.clientConfig.parameters.siteId,
1112
+ client_id: slasClient.clientConfig.parameters.clientId,
1113
+ new_password: parameters.new_password,
1114
+ user_id: parameters.user_id
1115
+ }
1116
+ };
1117
+
1118
+ // Only set authorization header if using private client
1119
+ if (_this19.clientSecret) {
1120
+ options.headers.Authorization = `Basic ${(0, _utils.stringToBase64)(`${slasClient.clientConfig.parameters.clientId}:${_this19.clientSecret}`)}`;
1121
+ }
1122
+ // TODO: no code verifier needed with the fix blair has made, delete this when the fix has been merged to production
1123
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
1124
+ // @ts-ignore
1125
+ const res = yield _this19.client.resetPassword(options);
1126
+ return res;
1127
+ })();
1128
+ }
1129
+
919
1130
  /**
920
1131
  * Decode SLAS JWT and extract information such as customer id, usid, etc.
921
1132
  *
@@ -935,6 +1146,7 @@ class Auth {
935
1146
  // ISB format
936
1147
  // 'uido:ecom::upn:Guest||xxxEmailxxx::uidn:FirstName LastName::gcid:xxxGuestCustomerIdxxx::rcid:xxxRegisteredCustomerIdxxx::chid:xxxSiteIdxxx',
937
1148
  const isbParts = isb.split('::');
1149
+ const uido = isbParts[0].split('uido:')[1];
938
1150
  const isGuest = isbParts[1] === 'upn:Guest';
939
1151
  const customerId = isGuest ? isbParts[3].replace('gcid:', '') : isbParts[4].replace('rcid:', '');
940
1152
  const loginId = isGuest ? 'guest' : isbParts[1].replace('upn:', '');
@@ -951,7 +1163,8 @@ class Auth {
951
1163
  dnt,
952
1164
  loginId,
953
1165
  isAgent,
954
- agentId
1166
+ agentId,
1167
+ uido
955
1168
  };
956
1169
  }
957
1170
  }
@@ -15,8 +15,8 @@ const _excluded = ["data"];
15
15
  */
16
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
17
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
18
- function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
19
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
18
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], t.indexOf(o) >= 0 || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
19
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
20
20
  const ComponentNotFound = ({
21
21
  typeId
22
22
  }) => /*#__PURE__*/_react.default.createElement("div", null, `Component type '${typeId}' not found!`);
@@ -22,8 +22,8 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
22
22
  function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
23
23
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
24
24
  function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
25
- function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
26
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
25
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], t.indexOf(o) >= 0 || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
26
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
27
27
  // This context will hold the component map as well as any other future context.
28
28
  const PageContext = exports.PageContext = /*#__PURE__*/_react.default.createContext(undefined);
29
29
 
@@ -17,8 +17,8 @@ const _excluded = ["region", "className"];
17
17
  */
18
18
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
19
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
20
- function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
21
- function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }
20
+ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], t.indexOf(o) >= 0 || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
21
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.indexOf(n) >= 0) continue; t[n] = r[n]; } return t; }
22
22
  /**
23
23
  * This PropType represents a `region` object from the ShopperExperience API.
24
24
  */
@@ -6,10 +6,16 @@ import Auth from '../auth';
6
6
  * @enum
7
7
  */
8
8
  export declare const AuthHelpers: {
9
+ readonly AuthorizePasswordless: "authorizePasswordless";
10
+ readonly LoginPasswordlessUser: "getPasswordLessAccessToken";
11
+ readonly AuthorizeIDP: "authorizeIDP";
12
+ readonly GetPasswordResetToken: "getPasswordResetToken";
13
+ readonly LoginIDPUser: "loginIDPUser";
9
14
  readonly LoginGuestUser: "loginGuestUser";
10
15
  readonly LoginRegisteredUserB2C: "loginRegisteredUserB2C";
11
16
  readonly Logout: "logout";
12
17
  readonly Register: "register";
18
+ readonly ResetPassword: "resetPassword";
13
19
  readonly UpdateCustomerPassword: "updateCustomerPassword";
14
20
  };
15
21
  /**
@@ -25,6 +31,8 @@ export type AuthHelper = (typeof AuthHelpers)[keyof typeof AuthHelpers];
25
31
  * For more, see https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic/#public-client-shopper-login-helpers
26
32
  *
27
33
  * Avaliable helpers:
34
+ * - authorizeIDP
35
+ * - loginIDPUser
28
36
  * - loginRegisteredUserB2C
29
37
  * - loginGuestUser
30
38
  * - logout
@@ -22,10 +22,16 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
22
22
  * @enum
23
23
  */
24
24
  const AuthHelpers = exports.AuthHelpers = {
25
+ AuthorizePasswordless: 'authorizePasswordless',
26
+ LoginPasswordlessUser: 'getPasswordLessAccessToken',
27
+ AuthorizeIDP: 'authorizeIDP',
28
+ GetPasswordResetToken: 'getPasswordResetToken',
29
+ LoginIDPUser: 'loginIDPUser',
25
30
  LoginGuestUser: 'loginGuestUser',
26
31
  LoginRegisteredUserB2C: 'loginRegisteredUserB2C',
27
32
  Logout: 'logout',
28
33
  Register: 'register',
34
+ ResetPassword: 'resetPassword',
29
35
  UpdateCustomerPassword: 'updateCustomerPassword'
30
36
  };
31
37
  /**
@@ -47,6 +53,8 @@ const noop = () => ({});
47
53
  * For more, see https://github.com/SalesforceCommerceCloud/commerce-sdk-isomorphic/#public-client-shopper-login-helpers
48
54
  *
49
55
  * Avaliable helpers:
56
+ * - authorizeIDP
57
+ * - loginIDPUser
50
58
  * - loginRegisteredUserB2C
51
59
  * - loginGuestUser
52
60
  * - logout
@@ -42,7 +42,7 @@ const useAuthorizationHeader = method => {
42
42
  headers: _objectSpread({
43
43
  Authorization: `Bearer ${access_token}`
44
44
  }, options.headers)
45
- })).catch(/*#__PURE__*/function () {
45
+ })).catch( /*#__PURE__*/function () {
46
46
  var _ref2 = _asyncToGenerator(function* (error) {
47
47
  const {
48
48
  access_token
@@ -3,6 +3,7 @@ type useCustomerType = {
3
3
  customerType: CustomerType;
4
4
  isGuest: boolean;
5
5
  isRegistered: boolean;
6
+ isExternal: boolean;
6
7
  };
7
8
  /**
8
9
  * A hook to return customer auth type.
@@ -44,10 +44,18 @@ const useCustomerType = () => {
44
44
  if (customerType !== null && customerType !== 'guest' && customerType !== 'registered') {
45
45
  customerType = null;
46
46
  }
47
+
48
+ // The `uido` is a value within the `isb` claim of the SLAS access token that denotes the IDP origin of the user
49
+ // If `uido` is not equal to `slas` or `ecom`, the user is considered an external user
50
+ const uido = onClient ?
51
+ // eslint-disable-next-line react-hooks/rules-of-hooks
52
+ (0, _useLocalStorage.default)(`uido_${config.siteId}`) : auth.get('uido');
53
+ const isExternal = customerType === 'registered' && uido !== 'slas' && uido !== 'ecom';
47
54
  return {
48
55
  customerType,
49
56
  isGuest,
50
- isRegistered
57
+ isRegistered,
58
+ isExternal
51
59
  };
52
60
  };
53
61
  var _default = exports.default = useCustomerType;
package/hooks/useDNT.d.ts CHANGED
@@ -1,16 +1,26 @@
1
1
  interface useDntReturn {
2
+ selectedDnt: boolean | undefined;
2
3
  dntStatus: boolean | undefined;
4
+ effectiveDnt: boolean | undefined;
3
5
  updateDNT: (preference: boolean | null) => Promise<void>;
6
+ updateDnt: (preference: boolean | null) => Promise<void>;
4
7
  }
5
8
  /**
6
- * Hook that returns
7
- * dntStatus - a boolean indicating the current DNT preference
8
- * updateDNT - a function that takes a DNT preference and creates the dw_dnt
9
- * cookie and reauthroizes with SLAS
10
- *
11
9
  * @group Helpers
12
10
  * @category DNT
13
11
  *
12
+ * @returns {Object} - The returned object containing DNT states and function to update preference
13
+ * @property {boolean} selectedDnt - DNT user preference. Used to determine
14
+ * if the consent tracking form should be rendered
15
+ * @property {boolean} effectiveDnt - effective DNT value to apply to
16
+ * analytics layers. Takes defaultDnt into account when selectedDnt is undefined.
17
+ * If defaultDnt is undefined as well, then SDK default is used.
18
+ * @property {function} updateDnt - takes a DNT choice and creates the dw_dnt
19
+ * cookie and reauthorizes with SLAS
20
+ * @property {function} updateDNT - @deprecated Deprecated since version 3.1.0. Use updateDnt instead.
21
+ * @property {boolean} dntStatus - @deprecated Deprecated since version 3.1.0. Use selectedDnt instead.
22
+ *
23
+ *
14
24
  */
15
25
  declare const useDNT: () => useDntReturn;
16
26
  export default useDNT;
package/hooks/useDNT.js CHANGED
@@ -14,29 +14,44 @@ function _asyncToGenerator(n) { return function () { var t = this, e = arguments
14
14
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
15
15
  */
16
16
  /**
17
- * Hook that returns
18
- * dntStatus - a boolean indicating the current DNT preference
19
- * updateDNT - a function that takes a DNT preference and creates the dw_dnt
20
- * cookie and reauthroizes with SLAS
21
- *
22
17
  * @group Helpers
23
18
  * @category DNT
24
19
  *
20
+ * @returns {Object} - The returned object containing DNT states and function to update preference
21
+ * @property {boolean} selectedDnt - DNT user preference. Used to determine
22
+ * if the consent tracking form should be rendered
23
+ * @property {boolean} effectiveDnt - effective DNT value to apply to
24
+ * analytics layers. Takes defaultDnt into account when selectedDnt is undefined.
25
+ * If defaultDnt is undefined as well, then SDK default is used.
26
+ * @property {function} updateDnt - takes a DNT choice and creates the dw_dnt
27
+ * cookie and reauthorizes with SLAS
28
+ * @property {function} updateDNT - @deprecated Deprecated since version 3.1.0. Use updateDnt instead.
29
+ * @property {boolean} dntStatus - @deprecated Deprecated since version 3.1.0. Use selectedDnt instead.
30
+ *
31
+ *
25
32
  */
26
33
  const useDNT = () => {
27
34
  const auth = (0, _useAuthContext.default)();
28
- const dntStatus = auth.getDnt();
29
- const updateDNT = /*#__PURE__*/function () {
35
+ const selectedDnt = auth.getDnt();
36
+ const effectiveDnt = auth.getDnt({
37
+ includeDefaults: true
38
+ });
39
+ const updateDnt = /*#__PURE__*/function () {
30
40
  var _ref = _asyncToGenerator(function* (preference) {
31
41
  yield auth.setDnt(preference);
32
42
  });
33
- return function updateDNT(_x) {
43
+ return function updateDnt(_x) {
34
44
  return _ref.apply(this, arguments);
35
45
  };
36
46
  }();
47
+ const updateDNT = updateDnt;
48
+ const dntStatus = selectedDnt;
37
49
  return {
50
+ selectedDnt,
51
+ effectiveDnt,
38
52
  dntStatus,
39
- updateDNT
53
+ updateDNT,
54
+ updateDnt
40
55
  };
41
56
  };
42
57
  var _default = exports.default = useDNT;
@@ -61,7 +61,7 @@ const useCustomMutation = (apiOptions, mutationOptions) => {
61
61
  const {
62
62
  access_token
63
63
  } = yield auth.ready();
64
- return yield _commerceSdkIsomorphic.helpers.callCustomEndpoint((0, _helpers.generateCustomEndpointOptions)(apiOptions, globalConfig, access_token, args)).catch(/*#__PURE__*/function () {
64
+ return yield _commerceSdkIsomorphic.helpers.callCustomEndpoint((0, _helpers.generateCustomEndpointOptions)(apiOptions, globalConfig, access_token, args)).catch( /*#__PURE__*/function () {
65
65
  var _ref2 = _asyncToGenerator(function* (error) {
66
66
  const {
67
67
  access_token
package/hooks/useQuery.js CHANGED
@@ -86,7 +86,7 @@ const useCustomQuery = (apiOptions, queryOptions) => {
86
86
  access_token
87
87
  } = yield auth.ready();
88
88
  const customEndpointOptions = (0, _helpers.generateCustomEndpointOptions)(options, config, access_token);
89
- return yield _commerceSdkIsomorphic.helpers.callCustomEndpoint(customEndpointOptions).catch(/*#__PURE__*/function () {
89
+ return yield _commerceSdkIsomorphic.helpers.callCustomEndpoint(customEndpointOptions).catch( /*#__PURE__*/function () {
90
90
  var _ref3 = _asyncToGenerator(function* (error) {
91
91
  const {
92
92
  access_token
@@ -127,7 +127,7 @@ const useTrustedAgent = () => {
127
127
  const authorizeTrustedAgent = (0, _reactQuery.useMutation)(auth.authorizeTrustedAgent.bind(auth));
128
128
  const loginTrustedAgent = (0, _reactQuery.useMutation)(auth.loginTrustedAgent.bind(auth));
129
129
  const logoutTrustedAgent = (0, _reactQuery.useMutation)(auth.logout.bind(auth));
130
- const login = (0, _react.useCallback)(/*#__PURE__*/function () {
130
+ const login = (0, _react.useCallback)( /*#__PURE__*/function () {
131
131
  var _ref2 = _asyncToGenerator(function* (loginId, usid, refresh = false) {
132
132
  if (!(0, _utils.onClient)()) {
133
133
  throw new Error('Something went wrong, this client side method is invoked on the server.');
@@ -154,7 +154,7 @@ const useTrustedAgent = () => {
154
154
  return _ref2.apply(this, arguments);
155
155
  };
156
156
  }(), [auth]);
157
- const logout = (0, _react.useCallback)(/*#__PURE__*/_asyncToGenerator(function* () {
157
+ const logout = (0, _react.useCallback)( /*#__PURE__*/_asyncToGenerator(function* () {
158
158
  return yield logoutTrustedAgent.mutateAsync();
159
159
  }), [auth]);
160
160
  (0, _react.useEffect)(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/commerce-sdk-react",
3
- "version": "3.2.0-preview.3",
3
+ "version": "3.2.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": {
@@ -40,12 +40,12 @@
40
40
  "version": "node ./scripts/version.js"
41
41
  },
42
42
  "dependencies": {
43
- "commerce-sdk-isomorphic": "^3.1.1",
43
+ "commerce-sdk-isomorphic": "^3.2.0",
44
44
  "js-cookie": "^3.0.1",
45
45
  "jwt-decode": "^4.0.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@salesforce/pwa-kit-dev": "4.0.0-extensibility-preview.3",
48
+ "@salesforce/pwa-kit-dev": "3.9.0-preview.4",
49
49
  "@tanstack/react-query": "^4.28.0",
50
50
  "@testing-library/jest-dom": "^5.16.5",
51
51
  "@testing-library/react": "^14.0.0",
@@ -60,7 +60,7 @@
60
60
  "@types/react-helmet": "~6.1.6",
61
61
  "@types/react-router-dom": "~5.3.3",
62
62
  "cross-env": "^5.2.1",
63
- "internal-lib-build": "4.0.0-extensibility-preview.3",
63
+ "internal-lib-build": "3.9.0-preview.4",
64
64
  "jsonwebtoken": "^9.0.0",
65
65
  "nock": "^13.3.0",
66
66
  "nodemon": "^2.0.22",
@@ -84,11 +84,11 @@
84
84
  "react-router-dom": "^5.3.4"
85
85
  },
86
86
  "engines": {
87
- "node": "^16.11.0 || ^18.0.0 || ^20.0.0",
88
- "npm": "^8.0.0 || ^9.0.0 || ^10.0.0"
87
+ "node": "^16.11.0 || ^18.0.0 || ^20.0.0 || ^22.0.0",
88
+ "npm": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0"
89
89
  },
90
90
  "publishConfig": {
91
91
  "directory": "dist"
92
92
  },
93
- "gitHead": "904de01e826117febeea952e034478349e16ea4d"
93
+ "gitHead": "1f16c75dcb6939a4edc76bb477888239fa76357b"
94
94
  }
package/provider.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface CommerceApiProviderProps extends ApiClientConfigParams {
17
17
  silenceWarnings?: boolean;
18
18
  logger?: Logger;
19
19
  defaultDnt?: boolean;
20
+ passwordlessLoginCallbackURI?: string;
20
21
  refreshTokenRegisteredCookieTTL?: number;
21
22
  refreshTokenGuestCookieTTL?: number;
22
23
  }
package/provider.js CHANGED
@@ -97,6 +97,7 @@ const CommerceApiProvider = props => {
97
97
  silenceWarnings,
98
98
  logger,
99
99
  defaultDnt,
100
+ passwordlessLoginCallbackURI,
100
101
  refreshTokenRegisteredCookieTTL,
101
102
  refreshTokenGuestCookieTTL
102
103
  } = props;
@@ -118,10 +119,11 @@ const CommerceApiProvider = props => {
118
119
  silenceWarnings,
119
120
  logger: configLogger,
120
121
  defaultDnt,
122
+ passwordlessLoginCallbackURI,
121
123
  refreshTokenRegisteredCookieTTL,
122
124
  refreshTokenGuestCookieTTL
123
125
  });
124
- }, [clientId, organizationId, shortCode, siteId, proxy, redirectURI, fetchOptions, fetchedToken, enablePWAKitPrivateClient, clientSecret, silenceWarnings, configLogger, refreshTokenRegisteredCookieTTL, refreshTokenGuestCookieTTL]);
126
+ }, [clientId, organizationId, shortCode, siteId, proxy, redirectURI, fetchOptions, fetchedToken, enablePWAKitPrivateClient, clientSecret, silenceWarnings, configLogger, defaultDnt, passwordlessLoginCallbackURI, refreshTokenRegisteredCookieTTL, refreshTokenGuestCookieTTL]);
125
127
  const dwsid = auth.get(_constant.DWSID_COOKIE_NAME);
126
128
  const serverAffinityHeader = {};
127
129
  if (dwsid) {
@@ -179,6 +181,7 @@ const CommerceApiProvider = props => {
179
181
  silenceWarnings,
180
182
  logger: configLogger,
181
183
  defaultDnt,
184
+ passwordlessLoginCallbackURI,
182
185
  refreshTokenRegisteredCookieTTL,
183
186
  refreshTokenGuestCookieTTL
184
187
  }
package/utils.d.ts CHANGED
@@ -33,4 +33,29 @@ export declare const getDefaultCookieAttributes: () => CookieAttributes;
33
33
  export declare function detectLocalStorageAvailable(): boolean;
34
34
  /** Determines whether cookies are available by trying to set a test value. */
35
35
  export declare function detectCookiesAvailable(options?: CookieAttributes): boolean;
36
+ /**
37
+ * Determines whether the given URL string is a valid absolute URL.
38
+ *
39
+ * Valid absolute URLs:
40
+ * - https://example.com
41
+ * - http://example.com
42
+ *
43
+ * Invalid or relative URLs:
44
+ * - http://example
45
+ * - example.com
46
+ * - /relative/path
47
+ *
48
+ * @param {string} url - The URL string to be checked.
49
+ * @returns {boolean} - Returns true if the given string is a valid absolute URL, false otherwise.
50
+ */
51
+ export declare function isAbsoluteUrl(url: string): boolean;
52
+ /**
53
+ * Provides a platform-specific method for Base64 encoding.
54
+ *
55
+ * - In a browser environment (where `window` and `document` are defined),
56
+ * the native `btoa` function is used.
57
+ * - In a non-browser environment (like Node.js), a fallback is provided
58
+ * that uses `Buffer` to perform the Base64 encoding.
59
+ */
60
+ export declare const stringToBase64: typeof btoa;
36
61
  //# sourceMappingURL=utils.d.ts.map
package/utils.js CHANGED
@@ -7,7 +7,9 @@ exports.DEVELOPMENT_ORIGIN = void 0;
7
7
  exports.detectCookiesAvailable = detectCookiesAvailable;
8
8
  exports.detectInIframe = void 0;
9
9
  exports.detectLocalStorageAvailable = detectLocalStorageAvailable;
10
- exports.onClient = exports.isOriginTrusted = exports.getParentOrigin = exports.getDefaultCookieAttributes = exports.getCookieSameSiteAttribute = void 0;
10
+ exports.getParentOrigin = exports.getDefaultCookieAttributes = exports.getCookieSameSiteAttribute = void 0;
11
+ exports.isAbsoluteUrl = isAbsoluteUrl;
12
+ exports.stringToBase64 = exports.onClient = exports.isOriginTrusted = void 0;
11
13
  var _jsCookie = _interopRequireDefault(require("js-cookie"));
12
14
  var _constant = require("./constant");
13
15
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
@@ -123,4 +125,33 @@ function detectCookiesAvailable(options) {
123
125
  } catch {
124
126
  return false;
125
127
  }
126
- }
128
+ }
129
+
130
+ /**
131
+ * Determines whether the given URL string is a valid absolute URL.
132
+ *
133
+ * Valid absolute URLs:
134
+ * - https://example.com
135
+ * - http://example.com
136
+ *
137
+ * Invalid or relative URLs:
138
+ * - http://example
139
+ * - example.com
140
+ * - /relative/path
141
+ *
142
+ * @param {string} url - The URL string to be checked.
143
+ * @returns {boolean} - Returns true if the given string is a valid absolute URL, false otherwise.
144
+ */
145
+ function isAbsoluteUrl(url) {
146
+ return /^(https?:\/\/)/i.test(url);
147
+ }
148
+
149
+ /**
150
+ * Provides a platform-specific method for Base64 encoding.
151
+ *
152
+ * - In a browser environment (where `window` and `document` are defined),
153
+ * the native `btoa` function is used.
154
+ * - In a non-browser environment (like Node.js), a fallback is provided
155
+ * that uses `Buffer` to perform the Base64 encoding.
156
+ */
157
+ const stringToBase64 = exports.stringToBase64 = typeof window === 'object' && typeof window.document === 'object' ? btoa : unencoded => Buffer.from(unencoded).toString('base64');