@scayle/storefront-core 7.57.0 → 7.58.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,13 @@
1
1
  # @scayle/storefront-core
2
2
 
3
+ ## 7.58.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Deprecate `storefrontAccessToken` of `UserAuthentication`. Use `getAccessToken` RPC to get a valid access token instead.
8
+ Deprecated `loginShopId`. `loginShopId` is no longer needed, because each shop now has its own session cookie.
9
+ - Add `getAccessToken` RPC to retrieve refreshed access tokens
10
+
3
11
  ## 7.57.0
4
12
 
5
13
  ### Minor Changes
@@ -5,10 +5,17 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.getCheckoutToken = void 0;
7
7
  var _jose = require("jose");
8
- const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutToken2(jwtPayload, context) {
8
+ var _user = require("../user.cjs");
9
+ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}, context) {
9
10
  if (!context.accessToken) {
10
11
  throw new Error("No access token present");
11
12
  }
13
+ const refreshedAccessToken = await (0, _user.getAccessToken)({
14
+ forceTokenRefresh: true
15
+ }, context);
16
+ if (refreshedAccessToken instanceof Response) {
17
+ return refreshedAccessToken;
18
+ }
12
19
  const secret = new TextEncoder().encode(context.checkout.secret);
13
20
  const now = /* @__PURE__ */new Date();
14
21
  const {
@@ -16,7 +23,7 @@ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutTo
16
23
  customData,
17
24
  preferredCollectionPoint,
18
25
  carrier
19
- } = jwtPayload || {};
26
+ } = jwtPayload;
20
27
  const checkoutJwt = await new _jose.SignJWT({
21
28
  voucher,
22
29
  customData,
@@ -24,12 +31,12 @@ const getCheckoutToken = exports.getCheckoutToken = async function getCheckoutTo
24
31
  carrier,
25
32
  basketId: context.basketKey,
26
33
  campaignKey: context.campaignKey
27
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.56.0"}`).setProtectedHeader({
34
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.57.0"}`).setProtectedHeader({
28
35
  alg: "HS256",
29
36
  typ: "JWT"
30
37
  }).sign(secret);
31
38
  return {
32
- accessToken: context.accessToken,
39
+ accessToken: refreshedAccessToken,
33
40
  checkoutJwt
34
41
  };
35
42
  };
@@ -8,7 +8,7 @@ interface CheckoutJwtPayload {
8
8
  };
9
9
  carrier?: string;
10
10
  }
11
- export declare const getCheckoutToken: (jwtPayload: CheckoutJwtPayload | undefined, context: RpcContext) => Promise<{
11
+ export declare const getCheckoutToken: (jwtPayload: CheckoutJwtPayload | undefined, context: RpcContext) => Promise<Response | {
12
12
  accessToken: string;
13
13
  checkoutJwt: string;
14
14
  }>;
@@ -1,11 +1,19 @@
1
1
  import { SignJWT } from "jose";
2
- export const getCheckoutToken = async function getCheckoutToken2(jwtPayload, context) {
2
+ import { getAccessToken } from "../user.mjs";
3
+ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload = {}, context) {
3
4
  if (!context.accessToken) {
4
5
  throw new Error("No access token present");
5
6
  }
7
+ const refreshedAccessToken = await getAccessToken(
8
+ { forceTokenRefresh: true },
9
+ context
10
+ );
11
+ if (refreshedAccessToken instanceof Response) {
12
+ return refreshedAccessToken;
13
+ }
6
14
  const secret = new TextEncoder().encode(context.checkout.secret);
7
15
  const now = /* @__PURE__ */ new Date();
8
- const { voucher, customData, preferredCollectionPoint, carrier } = jwtPayload || {};
16
+ const { voucher, customData, preferredCollectionPoint, carrier } = jwtPayload;
9
17
  const checkoutJwt = await new SignJWT({
10
18
  voucher,
11
19
  customData,
@@ -13,9 +21,9 @@ export const getCheckoutToken = async function getCheckoutToken2(jwtPayload, con
13
21
  carrier,
14
22
  basketId: context.basketKey,
15
23
  campaignKey: context.campaignKey
16
- }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.56.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
24
+ }).setIssuedAt(now).setNotBefore(now).setExpirationTime("1h").setIssuer(`${"@scayle/storefront-core"}@${"7.57.0"}`).setProtectedHeader({ alg: "HS256", typ: "JWT" }).sign(secret);
17
25
  return {
18
- accessToken: context.accessToken,
26
+ accessToken: refreshedAccessToken,
19
27
  checkoutJwt
20
28
  };
21
29
  };
@@ -23,8 +23,7 @@ const convertErrorForRpcCall = (error, httpStatuses) => {
23
23
  };
24
24
  async function postLogin(context, tokens) {
25
25
  const user = await (0, _response.unwrap)((0, _user2.fetchUser)({
26
- accessToken: tokens.access_token,
27
- callback: ""
26
+ accessToken: tokens.access_token
28
27
  }, context));
29
28
  context.updateTokens({
30
29
  accessToken: tokens.access_token,
@@ -13,7 +13,7 @@ const convertErrorForRpcCall = (error, httpStatuses) => {
13
13
  };
14
14
  export async function postLogin(context, tokens) {
15
15
  const user = await unwrap(
16
- fetchUser({ accessToken: tokens.access_token, callback: "" }, context)
16
+ fetchUser({ accessToken: tokens.access_token }, context)
17
17
  );
18
18
  context.updateTokens({
19
19
  accessToken: tokens.access_token,
@@ -3,9 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.refreshUser = exports.getUser = exports.fetchUser = void 0;
6
+ exports.refreshUser = exports.getUser = exports.getAccessToken = exports.fetchUser = void 0;
7
7
  var _types = require("../../types/index.cjs");
8
8
  var _customer = require("../../api/customer.cjs");
9
+ var _oauth = require("../../api/oauth.cjs");
9
10
  const getUser = exports.getUser = function getUser2(context) {
10
11
  const {
11
12
  user,
@@ -23,10 +24,9 @@ const getUser = exports.getUser = function getUser2(context) {
23
24
  user
24
25
  };
25
26
  };
26
- const fetchUser = exports.fetchUser = async function fetchUser2(payload, context) {
27
- const {
28
- accessToken
29
- } = payload;
27
+ const fetchUser = exports.fetchUser = async function fetchUser2({
28
+ accessToken
29
+ }, context) {
30
30
  const {
31
31
  shopId
32
32
  } = context;
@@ -44,36 +44,56 @@ const fetchUser = exports.fetchUser = async function fetchUser2(payload, context
44
44
  const refreshUser = exports.refreshUser = async function refreshUser2(context) {
45
45
  (0, _types.assertSession)(context);
46
46
  const {
47
- accessToken,
48
- shopId,
49
- user
47
+ accessToken
50
48
  } = context;
51
49
  if (!accessToken) {
52
50
  return {
53
51
  user: void 0
54
52
  };
55
53
  }
56
- const isLoggedIn = !!user;
57
- const client = new _customer.CustomerAPIClient(context);
58
54
  try {
59
- const user2 = await client.getMe(shopId);
60
- if (!user2.authentication) {
61
- user2.authentication = {
62
- type: "idp"
63
- };
64
- }
65
- user2.authentication.storefrontAccessToken = accessToken;
66
- user2.loginShopId = shopId;
67
- context.updateUser(user2);
55
+ const user = await fetchUser({
56
+ accessToken
57
+ }, context);
58
+ context.updateUser(user);
68
59
  return {
69
- user: user2
60
+ user
70
61
  };
71
62
  } catch {
72
- if (isLoggedIn) {
73
- await context.destroySession();
74
- }
63
+ await context.destroySession();
75
64
  return {
76
65
  user: void 0
77
66
  };
78
67
  }
68
+ };
69
+ const getAccessToken = exports.getAccessToken = async function getAccessToken2({
70
+ forceTokenRefresh = false
71
+ }, context) {
72
+ (0, _types.assertSession)(context);
73
+ if (!context.accessToken) {
74
+ return new Response("No access token present", {
75
+ status: 401
76
+ });
77
+ }
78
+ if (!forceTokenRefresh) {
79
+ if (!context.refreshToken) {
80
+ return new Response("No refresh token present", {
81
+ status: 401
82
+ });
83
+ }
84
+ const client = (0, _oauth.getOAuthClient)(context);
85
+ const tokens = await client.refreshToken({
86
+ grant_type: "refresh_token",
87
+ refresh_token: context.refreshToken
88
+ });
89
+ context.updateTokens({
90
+ accessToken: tokens.access_token,
91
+ refreshToken: tokens.refresh_token
92
+ });
93
+ const user = await fetchUser({
94
+ accessToken: tokens.access_token
95
+ }, context);
96
+ context.updateUser(user);
97
+ }
98
+ return context.accessToken;
79
99
  };
@@ -1,8 +1,10 @@
1
- import type { AuthConfig, RpcContext, ShopUser } from '../../types';
1
+ import type { RpcContext, ShopUser } from '../../types';
2
2
  declare const getUser: (context: RpcContext) => {
3
3
  user: ShopUser | undefined;
4
4
  };
5
- declare const fetchUser: (payload: AuthConfig, context: RpcContext) => Promise<ShopUser>;
5
+ declare const fetchUser: ({ accessToken }: {
6
+ accessToken?: string;
7
+ }, context: RpcContext) => Promise<ShopUser>;
6
8
  /**
7
9
  * This function adds a way to force fetch the user from checkout.
8
10
  * In case the user is not logged in any longer the session will be destroyed and the returned user will be undefined.
@@ -14,4 +16,7 @@ declare const refreshUser: (context: RpcContext) => Promise<{
14
16
  } | {
15
17
  user: ShopUser;
16
18
  }>;
17
- export { getUser, fetchUser, refreshUser };
19
+ declare const getAccessToken: ({ forceTokenRefresh }: {
20
+ forceTokenRefresh?: boolean | undefined;
21
+ }, context: RpcContext) => Promise<string | Response>;
22
+ export { getUser, fetchUser, refreshUser, getAccessToken };
@@ -1,5 +1,6 @@
1
1
  import { assertSession } from "../../types/index.mjs";
2
2
  import { CustomerAPIClient } from "../../api/customer.mjs";
3
+ import { getOAuthClient } from "../../api/oauth.mjs";
3
4
  const getUser = function getUser2(context) {
4
5
  const { user, accessToken, shopId } = context;
5
6
  if (user) {
@@ -13,8 +14,7 @@ const getUser = function getUser2(context) {
13
14
  user
14
15
  };
15
16
  };
16
- const fetchUser = async function fetchUser2(payload, context) {
17
- const { accessToken } = payload;
17
+ const fetchUser = async function fetchUser2({ accessToken }, context) {
18
18
  const { shopId } = context;
19
19
  const client = new CustomerAPIClient(context);
20
20
  const user = await client.getMe(shopId, accessToken);
@@ -29,28 +29,43 @@ const fetchUser = async function fetchUser2(payload, context) {
29
29
  };
30
30
  const refreshUser = async function refreshUser2(context) {
31
31
  assertSession(context);
32
- const { accessToken, shopId, user } = context;
32
+ const { accessToken } = context;
33
33
  if (!accessToken) {
34
34
  return { user: void 0 };
35
35
  }
36
- const isLoggedIn = !!user;
37
- const client = new CustomerAPIClient(context);
38
36
  try {
39
- const user2 = await client.getMe(shopId);
40
- if (!user2.authentication) {
41
- user2.authentication = {
42
- type: "idp"
43
- };
44
- }
45
- user2.authentication.storefrontAccessToken = accessToken;
46
- user2.loginShopId = shopId;
47
- context.updateUser(user2);
48
- return { user: user2 };
37
+ const user = await fetchUser({ accessToken }, context);
38
+ context.updateUser(user);
39
+ return { user };
49
40
  } catch {
50
- if (isLoggedIn) {
51
- await context.destroySession();
52
- }
41
+ await context.destroySession();
53
42
  return { user: void 0 };
54
43
  }
55
44
  };
56
- export { getUser, fetchUser, refreshUser };
45
+ const getAccessToken = async function getAccessToken2({ forceTokenRefresh = false }, context) {
46
+ assertSession(context);
47
+ if (!context.accessToken) {
48
+ return new Response("No access token present", { status: 401 });
49
+ }
50
+ if (!forceTokenRefresh) {
51
+ if (!context.refreshToken) {
52
+ return new Response("No refresh token present", { status: 401 });
53
+ }
54
+ const client = getOAuthClient(context);
55
+ const tokens = await client.refreshToken({
56
+ grant_type: "refresh_token",
57
+ refresh_token: context.refreshToken
58
+ });
59
+ context.updateTokens({
60
+ accessToken: tokens.access_token,
61
+ refreshToken: tokens.refresh_token
62
+ });
63
+ const user = await fetchUser(
64
+ { accessToken: tokens.access_token },
65
+ context
66
+ );
67
+ context.updateUser(user);
68
+ }
69
+ return context.accessToken;
70
+ };
71
+ export { getUser, fetchUser, refreshUser, getAccessToken };
package/dist/server.cjs CHANGED
@@ -3,6 +3,13 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _exportNames = {
7
+ createClient: true,
8
+ RedisCache: true,
9
+ UnstorageCache: true,
10
+ CACHE_TIMEOUT: true,
11
+ initBapi: true
12
+ };
6
13
  Object.defineProperty(exports, "CACHE_TIMEOUT", {
7
14
  enumerable: true,
8
15
  get: function () {
@@ -36,4 +43,28 @@ Object.defineProperty(exports, "initBapi", {
36
43
  var _redis = require("./cache/providers/redis.cjs");
37
44
  var _unstorage = require("./cache/providers/unstorage.cjs");
38
45
  var _cache = require("./constants/cache.cjs");
39
- var _init = require("./bapi/init.cjs");
46
+ var _init = require("./bapi/init.cjs");
47
+ var _customer = require("./api/customer.cjs");
48
+ Object.keys(_customer).forEach(function (key) {
49
+ if (key === "default" || key === "__esModule") return;
50
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
51
+ if (key in exports && exports[key] === _customer[key]) return;
52
+ Object.defineProperty(exports, key, {
53
+ enumerable: true,
54
+ get: function () {
55
+ return _customer[key];
56
+ }
57
+ });
58
+ });
59
+ var _oauth = require("./api/oauth.cjs");
60
+ Object.keys(_oauth).forEach(function (key) {
61
+ if (key === "default" || key === "__esModule") return;
62
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
63
+ if (key in exports && exports[key] === _oauth[key]) return;
64
+ Object.defineProperty(exports, key, {
65
+ enumerable: true,
66
+ get: function () {
67
+ return _oauth[key];
68
+ }
69
+ });
70
+ });
package/dist/server.d.ts CHANGED
@@ -3,3 +3,5 @@ export { UnstorageCache } from './cache/providers/unstorage';
3
3
  export { CACHE_TIMEOUT } from './constants/cache';
4
4
  export type { RedisOptions } from './cache/providers/redis';
5
5
  export { init as initBapi } from './bapi/init';
6
+ export * from './api/customer';
7
+ export * from './api/oauth';
package/dist/server.mjs CHANGED
@@ -2,3 +2,5 @@ export { createClient, RedisCache } from "./cache/providers/redis.mjs";
2
2
  export { UnstorageCache } from "./cache/providers/unstorage.mjs";
3
3
  export { CACHE_TIMEOUT } from "./constants/cache.mjs";
4
4
  export { init as initBapi } from "./bapi/init.mjs";
5
+ export * from "./api/customer.mjs";
6
+ export * from "./api/oauth.mjs";
@@ -1,4 +1,7 @@
1
1
  import type { Gender } from '../user';
2
+ /**
3
+ * @deprecated
4
+ */
2
5
  export interface AuthConfig {
3
6
  callback: string;
4
7
  scopes?: string[];
@@ -20,6 +20,7 @@ interface UserAuthentication {
20
20
  accessToken?: string;
21
21
  userId?: string;
22
22
  };
23
+ /** @deprecated use `getAccessToken` RPC instead */
23
24
  storefrontAccessToken?: string;
24
25
  type: AuthenticationType;
25
26
  }
@@ -90,6 +91,7 @@ export interface ShopUser {
90
91
  customData?: {
91
92
  memberRoles?: MemberRole[];
92
93
  };
94
+ /** @deprecated `loginShopId` is no longer needed, because each shop now has it's own session cookie */
93
95
  loginShopId?: number;
94
96
  }
95
97
  export interface UseUserFacetParams {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scayle/storefront-core",
3
- "version": "7.57.0",
3
+ "version": "7.58.0",
4
4
  "description": "Collection of essential utilities to work with the Storefront API",
5
5
  "author": "SCAYLE Commerce Engine",
6
6
  "license": "MIT",
@@ -71,7 +71,7 @@
71
71
  "devDependencies": {
72
72
  "@scayle/eslint-config-storefront": "4.2.0",
73
73
  "@types/crypto-js": "4.2.2",
74
- "@types/node": "20.14.2",
74
+ "@types/node": "20.14.5",
75
75
  "@types/webpack-env": "1.18.5",
76
76
  "@vitest/coverage-v8": "1.6.0",
77
77
  "dprint": "0.46.2",