@scayle/storefront-core 7.47.0 → 7.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.48.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add support for dynamically adding query parameters to the IDP redirect callback URLs to be read back when the user returns from the IDP.
8
+
9
+ ```ts
10
+ const { data: externalIDPRedirects } = await useIDP({
11
+ queryParams: { redirectTo: '/account' },
12
+ })
13
+ ```
14
+
15
+ Please note that `code` and `state` are not supported as these are used by the SCAYLE Authentication API.
16
+
17
+ ### Patch Changes
18
+
19
+ - Added merge basket and merge wishlist functionality after login with IDP
20
+ - Updated dependencies
21
+ - @aboutyou/backbone@16.2.1
22
+
3
23
  ## 7.47.0
4
24
 
5
25
  ### Minor Changes
@@ -7,36 +7,44 @@ exports.handleIDPLoginCallback = exports.getExternalIdpRedirect = void 0;
7
7
  var _jose = require("jose");
8
8
  var _types = require("../../../types/index.cjs");
9
9
  var _oauth = require("../../../api/oauth.cjs");
10
- var _user = require("../user.cjs");
11
- const getExternalIdpRedirect = exports.getExternalIdpRedirect = async function getExternalIdpRedirect2(context) {
12
- const shopId = context.shopId.toString();
13
- const OAuthClient = (0, _oauth.getOAuthClient)(context);
14
- const checkoutSecret = context.checkout.secret;
10
+ var _session = require("../session.cjs");
11
+ const getExternalIdpRedirect = exports.getExternalIdpRedirect = async function getExternalIdpRedirect2({
12
+ queryParams
13
+ }, context) {
15
14
  if (!context.idp?.enabled) {
16
15
  return {};
17
16
  }
18
- const IDPKeys = context.idp.idpKeys;
19
- const IDPRedirectURL = context.idp.idpRedirectURL;
20
- if (!IDPKeys.length) {
21
- throw new Error("No IDP keys configured");
17
+ if (context.idp.idpKeys.length === 0) {
18
+ return new Response("No IDP keys are configured", {
19
+ status: 400
20
+ });
22
21
  }
23
- if (!IDPRedirectURL) {
24
- throw new Error("No redirect URL");
22
+ if (!context.idp.idpRedirectURL) {
23
+ return new Response("No IDP redirect url is configured", {
24
+ status: 400
25
+ });
25
26
  }
26
- if (!shopId) {
27
- throw new Error("Missing shopId");
27
+ const OAuthClient = (0, _oauth.getOAuthClient)(context);
28
+ const redirectUrl = new URL(context.idp.idpRedirectURL);
29
+ if (queryParams) {
30
+ for (const [key, value] of Object.entries(queryParams)) {
31
+ redirectUrl.searchParams.set(key, value);
32
+ }
28
33
  }
29
- const secret = new TextEncoder().encode(checkoutSecret);
30
- const results = await Promise.all(IDPKeys.map(async idpKey => {
34
+ const secret = new TextEncoder().encode(context.checkout.secret);
35
+ const results = await Promise.all(context.idp.idpKeys.map(async idpKey => {
31
36
  const jwtPayload = await new _jose.SignJWT({
32
37
  idpKey,
33
- callbackUrl: IDPRedirectURL,
38
+ callbackUrl: redirectUrl.toString(),
34
39
  clientId: OAuthClient.clientId.toString()
35
40
  }).setProtectedHeader({
36
41
  alg: "HS256",
37
42
  typ: "JWT"
38
43
  }).setIssuedAt().setExpirationTime("2h").sign(secret);
39
- return [idpKey, `${OAuthClient.baseURL}/auth/external/redirect?shopId=${shopId}&jwt=${jwtPayload}`];
44
+ const url = new URL(`${OAuthClient.baseURL}/auth/external/redirect`);
45
+ url.searchParams.set("shopId", `${context.shopId}`);
46
+ url.searchParams.set("jwt", jwtPayload);
47
+ return [idpKey, url.toString()];
40
48
  }));
41
49
  return Object.fromEntries(results);
42
50
  };
@@ -44,15 +52,8 @@ const handleIDPLoginCallback = exports.handleIDPLoginCallback = async function h
44
52
  (0, _types.assertSession)(context);
45
53
  const OAuthClient = (0, _oauth.getOAuthClient)(context);
46
54
  const code = typeof payload === "string" ? payload : payload.code;
47
- const {
48
- access_token: accessToken,
49
- refresh_token: refreshToken
50
- } = await OAuthClient.generateToken(code);
51
- context.updateTokens({
52
- accessToken,
53
- refreshToken
54
- });
55
- await (0, _user.refreshUser)(context);
55
+ const tokens = await OAuthClient.generateToken(code);
56
+ await (0, _session.postLogin)(context, tokens);
56
57
  return {
57
58
  message: "success"
58
59
  };
@@ -1,9 +1,11 @@
1
1
  import type { RpcContext } from '../../../types';
2
- export declare const getExternalIdpRedirect: (context: RpcContext) => Promise<{
2
+ export declare const getExternalIdpRedirect: ({ queryParams }: {
3
+ queryParams?: Record<string, string>;
4
+ }, context: RpcContext) => Promise<Response | {
3
5
  [k: string]: string;
4
6
  }>;
5
- export declare const handleIDPLoginCallback: (payload: string | {
7
+ export declare const handleIDPLoginCallback: (payload: {
6
8
  code: string;
7
- }, context: RpcContext) => Promise<{
9
+ } | string, context: RpcContext) => Promise<{
8
10
  message: string;
9
11
  }>;
@@ -1,37 +1,36 @@
1
1
  import { SignJWT } from "jose";
2
2
  import { assertSession } from "../../../types/index.mjs";
3
3
  import { getOAuthClient } from "../../../api/oauth.mjs";
4
- import { refreshUser } from "../user.mjs";
5
- export const getExternalIdpRedirect = async function getExternalIdpRedirect2(context) {
6
- const shopId = context.shopId.toString();
7
- const OAuthClient = getOAuthClient(context);
8
- const checkoutSecret = context.checkout.secret;
4
+ import { postLogin } from "../session.mjs";
5
+ export const getExternalIdpRedirect = async function getExternalIdpRedirect2({ queryParams }, context) {
9
6
  if (!context.idp?.enabled) {
10
7
  return {};
11
8
  }
12
- const IDPKeys = context.idp.idpKeys;
13
- const IDPRedirectURL = context.idp.idpRedirectURL;
14
- if (!IDPKeys.length) {
15
- throw new Error("No IDP keys configured");
9
+ if (context.idp.idpKeys.length === 0) {
10
+ return new Response("No IDP keys are configured", { status: 400 });
16
11
  }
17
- if (!IDPRedirectURL) {
18
- throw new Error("No redirect URL");
12
+ if (!context.idp.idpRedirectURL) {
13
+ return new Response("No IDP redirect url is configured", { status: 400 });
19
14
  }
20
- if (!shopId) {
21
- throw new Error("Missing shopId");
15
+ const OAuthClient = getOAuthClient(context);
16
+ const redirectUrl = new URL(context.idp.idpRedirectURL);
17
+ if (queryParams) {
18
+ for (const [key, value] of Object.entries(queryParams)) {
19
+ redirectUrl.searchParams.set(key, value);
20
+ }
22
21
  }
23
- const secret = new TextEncoder().encode(checkoutSecret);
22
+ const secret = new TextEncoder().encode(context.checkout.secret);
24
23
  const results = await Promise.all(
25
- IDPKeys.map(async (idpKey) => {
24
+ context.idp.idpKeys.map(async (idpKey) => {
26
25
  const jwtPayload = await new SignJWT({
27
26
  idpKey,
28
- callbackUrl: IDPRedirectURL,
27
+ callbackUrl: redirectUrl.toString(),
29
28
  clientId: OAuthClient.clientId.toString()
30
29
  }).setProtectedHeader({ alg: "HS256", typ: "JWT" }).setIssuedAt().setExpirationTime("2h").sign(secret);
31
- return [
32
- idpKey,
33
- `${OAuthClient.baseURL}/auth/external/redirect?shopId=${shopId}&jwt=${jwtPayload}`
34
- ];
30
+ const url = new URL(`${OAuthClient.baseURL}/auth/external/redirect`);
31
+ url.searchParams.set("shopId", `${context.shopId}`);
32
+ url.searchParams.set("jwt", jwtPayload);
33
+ return [idpKey, url.toString()];
35
34
  })
36
35
  );
37
36
  return Object.fromEntries(results);
@@ -40,12 +39,8 @@ export const handleIDPLoginCallback = async function handleIDPLoginCallback2(pay
40
39
  assertSession(context);
41
40
  const OAuthClient = getOAuthClient(context);
42
41
  const code = typeof payload === "string" ? payload : payload.code;
43
- const { access_token: accessToken, refresh_token: refreshToken } = await OAuthClient.generateToken(code);
44
- context.updateTokens({
45
- accessToken,
46
- refreshToken
47
- });
48
- await refreshUser(context);
42
+ const tokens = await OAuthClient.generateToken(code);
43
+ await postLogin(context, tokens);
49
44
  return {
50
45
  message: "success"
51
46
  };
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.updatePasswordByHash = exports.refreshAccessToken = exports.oauthRevokeToken = exports.oauthRegister = exports.oauthLogin = exports.oauthGuestLogin = exports.oauthForgetPassword = void 0;
6
+ exports.oauthRevokeToken = exports.oauthRegister = exports.oauthLogin = exports.oauthGuestLogin = exports.oauthForgetPassword = void 0;
7
+ exports.postLogin = postLogin;
8
+ exports.updatePasswordByHash = exports.refreshAccessToken = void 0;
7
9
  var _jose = require("jose");
8
10
  var _types = require("../../types/index.cjs");
9
11
  var _constants = require("../../constants/index.cjs");
@@ -1,5 +1,6 @@
1
1
  import type { Optional } from 'utility-types';
2
- import type { GuestRequest, LoginRequest, RegisterRequest, RpcContext, UpdatePasswordByHashRequest } from '../../types';
2
+ import type { GuestRequest, LoginRequest, Oauth, RegisterRequest, RpcContext, RpcContextWithSession, UpdatePasswordByHashRequest } from '../../types';
3
+ export declare function postLogin(context: RpcContextWithSession, tokens: Oauth): Promise<void>;
3
4
  export declare const oauthLogin: (login: Optional<LoginRequest, "shop_id">, context: RpcContext) => Promise<Response>;
4
5
  export declare const oauthRegister: (register: Optional<RegisterRequest, "shop_id">, context: RpcContext) => Promise<Response>;
5
6
  export declare const oauthGuestLogin: (guest: Optional<GuestRequest, "shop_id">, context: RpcContext) => Promise<Response>;
@@ -11,7 +11,7 @@ const convertErrorForRpcCall = (error, httpStatuses) => {
11
11
  return new Response(null, { status: error.response.status });
12
12
  }
13
13
  };
14
- async function postLogin(context, tokens) {
14
+ export async function postLogin(context, tokens) {
15
15
  const user = await unwrap(
16
16
  fetchUser({ accessToken: tokens.access_token, callback: "" }, context)
17
17
  );
@@ -1,24 +1,24 @@
1
1
  import type { Log } from '..';
2
2
  import { HashAlgorithm } from '../constants/hash';
3
3
  export declare const generateKey: ({ keyTemplate, hashAlgorithm, shopId, userId, log, }: {
4
- keyName?: string | undefined;
4
+ keyName?: string;
5
5
  keyTemplate: string;
6
6
  hashAlgorithm: HashAlgorithm;
7
7
  shopId: string;
8
8
  userId: string;
9
- log?: Log | undefined;
9
+ log?: Log;
10
10
  }) => Promise<string>;
11
11
  export declare const generateWishlistKey: ({ keyTemplate, hashAlgorithm, shopId, userId, log, }: {
12
12
  keyTemplate: string;
13
13
  hashAlgorithm: HashAlgorithm;
14
14
  shopId: string;
15
15
  userId: string;
16
- log?: Log | undefined;
16
+ log?: Log;
17
17
  }) => Promise<string>;
18
18
  export declare const generateBasketKey: ({ keyTemplate, hashAlgorithm, shopId, userId, log, }: {
19
19
  keyTemplate: string;
20
20
  hashAlgorithm: HashAlgorithm;
21
21
  shopId: string;
22
22
  userId: string;
23
- log?: Log | undefined;
23
+ log?: Log;
24
24
  }) => Promise<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.47.0",
3
+ "version": "7.48.0",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -59,7 +59,7 @@
59
59
  "test:ci": "vitest --run --passWithNoTests --coverage --reporter=default --reporter=junit"
60
60
  },
61
61
  "dependencies": {
62
- "@aboutyou/backbone": "16.2.0",
62
+ "@aboutyou/backbone": "16.2.1",
63
63
  "crypto-js": "4.2.0",
64
64
  "jose": "5.2.3",
65
65
  "radash": "12.1.0",
@@ -71,16 +71,16 @@
71
71
  "devDependencies": {
72
72
  "@scayle/eslint-config-storefront": "3.2.6",
73
73
  "@types/crypto-js": "4.2.2",
74
- "@types/node": "20.12.3",
74
+ "@types/node": "20.12.5",
75
75
  "@types/webpack-env": "1.18.4",
76
76
  "@vitest/coverage-v8": "1.4.0",
77
- "dprint": "0.45.0",
77
+ "dprint": "0.45.1",
78
78
  "eslint": "8.57.0",
79
79
  "eslint-formatter-gitlab": "5.1.0",
80
80
  "publint": "0.2.7",
81
81
  "rimraf": "5.0.5",
82
82
  "ts-node": "10.9.2",
83
- "typescript": "5.4.3",
83
+ "typescript": "5.4.4",
84
84
  "unbuild": "2.0.0",
85
85
  "unstorage": "1.10.2",
86
86
  "vitest": "1.4.0"