@wix/sdk 1.20.0 → 1.21.1

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.
@@ -1,10 +1,32 @@
1
- import { RefreshToken, Tokens } from './oauth2/types.js';
1
+ import { RefreshToken, Tokens, TokenStorage } from './oauth2/types.js';
2
2
  import { isVisitorCookieWarmedUp, preWarmVisitorCookie } from './pre-warm-cookie.js';
3
+ /**
4
+ * Site session authentication strategy for Wix SDK.
5
+ * @param config - Configuration object
6
+ * @param config.clientId - The OAuth client ID
7
+ * @param config.publicKey - Optional public key for token verification
8
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
9
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
10
+ * When provided, the strategy delegates all token persistence to this storage.
11
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
12
+ * @returns Site session auth instance
13
+ * @example
14
+ * // Default in-memory storage with initial tokens
15
+ * SiteSessionAuth({ clientId: 'xxx', tokens: myTokens })
16
+ * @example
17
+ * // Custom storage (e.g., cookies)
18
+ * SiteSessionAuth({ clientId: 'xxx', tokenStorage: myCookieStorage })
19
+ */
3
20
  export declare function SiteSessionAuth(config: {
4
21
  clientId: string;
5
22
  publicKey?: string;
23
+ } & ({
6
24
  tokens?: Tokens;
7
- }): {
25
+ tokenStorage?: never;
26
+ } | {
27
+ tokenStorage: TokenStorage;
28
+ tokens?: never;
29
+ })): {
8
30
  generateVisitorTokens: (tokens?: Partial<Tokens>) => Promise<Tokens>;
9
31
  renewToken: (refreshToken: RefreshToken) => Promise<Tokens>;
10
32
  getAuthHeaders: () => Promise<{
@@ -1,28 +1,56 @@
1
1
  import { biHeaderGenerator } from '../bi/biHeaderGenerator.js';
2
2
  import { DEFAULT_API_URL } from '../common.js';
3
3
  import { createAccessToken, isTokenExpired } from '../tokenHelpers.js';
4
- import { TokenRole } from './oauth2/types.js';
4
+ import { TokenRole, } from './oauth2/types.js';
5
+ import { EMPTY_TOKENS, createLocalTokenStorage, } from './oauth2/token-storage.js';
5
6
  import { isVisitorCookieWarmedUp, preWarmVisitorCookie, } from './pre-warm-cookie.js';
7
+ /**
8
+ * Site session authentication strategy for Wix SDK.
9
+ * @param config - Configuration object
10
+ * @param config.clientId - The OAuth client ID
11
+ * @param config.publicKey - Optional public key for token verification
12
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
13
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
14
+ * When provided, the strategy delegates all token persistence to this storage.
15
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
16
+ * @returns Site session auth instance
17
+ * @example
18
+ * // Default in-memory storage with initial tokens
19
+ * SiteSessionAuth({ clientId: 'xxx', tokens: myTokens })
20
+ * @example
21
+ * // Custom storage (e.g., cookies)
22
+ * SiteSessionAuth({ clientId: 'xxx', tokenStorage: myCookieStorage })
23
+ */
6
24
  export function SiteSessionAuth(config) {
7
- const _tokens = config.tokens || {
8
- accessToken: { value: '', expiresAt: 0 },
9
- refreshToken: { value: '', role: TokenRole.NONE },
10
- };
25
+ const _tokenStorage = config.tokenStorage ??
26
+ createLocalTokenStorage(config.tokens ?? EMPTY_TOKENS);
27
+ const getTokens = () => _tokenStorage.getTokens();
11
28
  const setTokens = (tokens) => {
12
- _tokens.accessToken = tokens.accessToken;
13
- _tokens.refreshToken = tokens.refreshToken;
29
+ _tokenStorage.setTokens(tokens);
14
30
  };
15
31
  const getAuthHeaders = async () => {
16
- if (!_tokens.accessToken?.value || isTokenExpired(_tokens.accessToken)) {
17
- const tokens = await generateVisitorTokens({
18
- refreshToken: _tokens.refreshToken,
32
+ const currentTokens = getTokens();
33
+ if (!currentTokens.accessToken?.value ||
34
+ isTokenExpired(currentTokens.accessToken)) {
35
+ const newTokens = await generateVisitorTokens({
36
+ refreshToken: currentTokens.refreshToken,
19
37
  });
20
- setTokens(tokens);
38
+ setTokens(newTokens);
21
39
  }
22
40
  return Promise.resolve({
23
- headers: { Authorization: _tokens.accessToken.value },
41
+ headers: { Authorization: getTokens().accessToken.value },
24
42
  });
25
43
  };
44
+ /**
45
+ * Name is misleading, it should be called generateTokens. Ensures valid tokens are available, refreshing or generating new ones as needed.
46
+ *
47
+ * Scenarios:
48
+ * 1. If valid (non-expired) access and refresh tokens are provided, returns them as-is.
49
+ * 2. If a refresh token is provided but access token is missing/expired, attempts to renew using the refresh token.
50
+ * 3. If renewal fails or no refresh token exists, generates new anonymous visitor tokens.
51
+ * @param tokens - Optional partial tokens (accessToken and/or refreshToken)
52
+ * @returns Valid tokens (accessToken + refreshToken)
53
+ */
26
54
  const generateVisitorTokens = async (tokens) => {
27
55
  if (tokens?.accessToken?.value &&
28
56
  tokens?.refreshToken?.value &&
@@ -62,7 +90,7 @@ export function SiteSessionAuth(config) {
62
90
  };
63
91
  };
64
92
  const loggedIn = () => {
65
- return _tokens.refreshToken.role === TokenRole.MEMBER;
93
+ return getTokens().refreshToken.role === TokenRole.MEMBER;
66
94
  };
67
95
  return {
68
96
  generateVisitorTokens,
@@ -70,7 +98,7 @@ export function SiteSessionAuth(config) {
70
98
  getAuthHeaders,
71
99
  setTokens,
72
100
  loggedIn,
73
- getTokens: () => _tokens,
101
+ getTokens,
74
102
  isSessionSynced: isVisitorCookieWarmedUp,
75
103
  syncToWixPages: preWarmVisitorCookie,
76
104
  shouldUseCDN: true,
@@ -1,9 +1,31 @@
1
- import { IOAuthStrategy, Tokens } from './types.js';
1
+ import { IOAuthStrategy, Tokens, TokenStorage } from './types.js';
2
+ /**
3
+ * OAuth authentication strategy for Wix SDK.
4
+ * @param config - Configuration object
5
+ * @param config.clientId - The OAuth client ID
6
+ * @param config.publicKey - Optional public key for token verification
7
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
8
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
9
+ * When provided, the strategy delegates all token persistence to this storage.
10
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
11
+ * @returns OAuth strategy instance
12
+ * @example
13
+ * // Default in-memory storage with initial tokens
14
+ * OAuthStrategy({ clientId: 'xxx', tokens: myTokens })
15
+ * @example
16
+ * // Custom storage (e.g., cookies)
17
+ * OAuthStrategy({ clientId: 'xxx', tokenStorage: myCookieStorage })
18
+ */
2
19
  export declare function OAuthStrategy(config: {
3
20
  clientId: string;
4
21
  publicKey?: string;
22
+ } & ({
5
23
  tokens?: Tokens;
6
- }): IOAuthStrategy;
24
+ tokenStorage?: never;
25
+ } | {
26
+ tokenStorage: TokenStorage;
27
+ tokens?: never;
28
+ })): IOAuthStrategy;
7
29
  export interface TokenResponse {
8
30
  access_token: string;
9
31
  expires_in: number;
@@ -9,34 +9,60 @@ import { EMAIL_EXISTS, INVALID_CAPTCHA, INVALID_PASSWORD, MISSING_CAPTCHA, RESET
9
9
  import { biHeaderGenerator } from '../../bi/biHeaderGenerator.js';
10
10
  import { pkceChallenge } from './pkce-challenge.js';
11
11
  import { isVisitorCookieWarmedUp, preWarmVisitorCookie, } from '../pre-warm-cookie.js';
12
+ import { EMPTY_TOKENS, createLocalTokenStorage } from './token-storage.js';
12
13
  const moduleWithTokens = { redirects, authentication, recovery, verification };
14
+ /**
15
+ * OAuth authentication strategy for Wix SDK.
16
+ * @param config - Configuration object
17
+ * @param config.clientId - The OAuth client ID
18
+ * @param config.publicKey - Optional public key for token verification
19
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
20
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
21
+ * When provided, the strategy delegates all token persistence to this storage.
22
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
23
+ * @returns OAuth strategy instance
24
+ * @example
25
+ * // Default in-memory storage with initial tokens
26
+ * OAuthStrategy({ clientId: 'xxx', tokens: myTokens })
27
+ * @example
28
+ * // Custom storage (e.g., cookies)
29
+ * OAuthStrategy({ clientId: 'xxx', tokenStorage: myCookieStorage })
30
+ */
13
31
  export function OAuthStrategy(config) {
14
- const _tokens = config.tokens || {
15
- accessToken: { value: '', expiresAt: 0 },
16
- refreshToken: { value: '', role: TokenRole.NONE },
17
- };
18
- const setTokens = (tokens) => {
19
- _tokens.accessToken = tokens.accessToken;
20
- _tokens.refreshToken = tokens.refreshToken;
21
- };
32
+ const _tokenStorage = config.tokenStorage ??
33
+ createLocalTokenStorage(config.tokens ?? EMPTY_TOKENS);
34
+ const getTokens = () => _tokenStorage.getTokens();
35
+ const setTokens = (tokens) => _tokenStorage.setTokens(tokens);
22
36
  let _state = {
23
37
  loginState: LoginState.INITIAL,
24
38
  };
25
39
  const getAuthHeaders = async () => {
26
- if (!_tokens.accessToken?.value || isTokenExpired(_tokens.accessToken)) {
27
- const tokens = await generateVisitorTokens({
28
- refreshToken: _tokens.refreshToken,
40
+ const currentTokens = getTokens();
41
+ if (!currentTokens.accessToken?.value ||
42
+ isTokenExpired(currentTokens.accessToken)) {
43
+ const newTokens = await generateVisitorTokens({
44
+ refreshToken: currentTokens.refreshToken,
29
45
  });
30
- setTokens(tokens);
46
+ setTokens(newTokens);
31
47
  }
32
48
  return Promise.resolve({
33
- headers: { Authorization: _tokens.accessToken.value },
49
+ headers: { Authorization: getTokens().accessToken.value },
34
50
  });
35
51
  };
36
52
  const wixClientWithTokens = createClient({
37
53
  modules: moduleWithTokens,
38
54
  auth: { getAuthHeaders },
39
55
  });
56
+ /**
57
+ * Name is misleading, it should be called generateTokens. Ensures valid tokens are available, refreshing or generating new ones as needed.
58
+ *
59
+ * Scenarios:
60
+ * 1. If valid (non-expired) access and refresh tokens are provided, returns them as-is.
61
+ * 2. If a refresh token is provided but access token is missing/expired, attempts to renew using the refresh token.
62
+ * 3. If renewal fails or no refresh token exists, generates new anonymous visitor tokens.
63
+ * @param tokens - Optional partial tokens (accessToken and/or refreshToken)
64
+ * @returns Valid tokens (accessToken + refreshToken)
65
+ */
40
66
  const generateVisitorTokens = async (tokens) => {
41
67
  if (tokens?.accessToken?.value &&
42
68
  tokens?.refreshToken?.value &&
@@ -165,8 +191,10 @@ export function OAuthStrategy(config) {
165
191
  postFlowUrl: originalUrl,
166
192
  },
167
193
  });
168
- _tokens.accessToken = { value: '', expiresAt: 0 };
169
- _tokens.refreshToken = { value: '', role: TokenRole.NONE };
194
+ setTokens({
195
+ accessToken: { value: '', expiresAt: 0 },
196
+ refreshToken: { value: '', role: TokenRole.NONE },
197
+ });
170
198
  return { logoutUrl: redirectSession.fullUrl };
171
199
  };
172
200
  const handleState = (response) => {
@@ -313,7 +341,7 @@ export function OAuthStrategy(config) {
313
341
  });
314
342
  };
315
343
  const loggedIn = () => {
316
- return _tokens.refreshToken.role === TokenRole.MEMBER;
344
+ return getTokens().refreshToken.role === TokenRole.MEMBER;
317
345
  };
318
346
  const getMemberTokensForExternalLogin = async (memberId, apiKey) => {
319
347
  const tokensResponse = await fetchTokens({
@@ -321,7 +349,7 @@ export function OAuthStrategy(config) {
321
349
  scope: 'offline_access',
322
350
  member_id: memberId,
323
351
  }, {
324
- Authorization: _tokens.accessToken.value + ',' + apiKey,
352
+ Authorization: getTokens().accessToken.value + ',' + apiKey,
325
353
  });
326
354
  return {
327
355
  accessToken: createAccessToken(tokensResponse.access_token, tokensResponse.expires_in),
@@ -340,7 +368,7 @@ export function OAuthStrategy(config) {
340
368
  generateOAuthData,
341
369
  getAuthHeaders,
342
370
  setTokens,
343
- getTokens: () => _tokens,
371
+ getTokens,
344
372
  loggedIn,
345
373
  logout,
346
374
  register,
@@ -0,0 +1,3 @@
1
+ import { type TokenStorage, type Tokens } from './types.js';
2
+ export declare const EMPTY_TOKENS: Tokens;
3
+ export declare function createLocalTokenStorage(initialTokens: Tokens): TokenStorage;
@@ -0,0 +1,15 @@
1
+ import { TokenRole } from './types.js';
2
+ // These tokens are considered empty tokens, and can be used as a fallback when no tokens are available.
3
+ export const EMPTY_TOKENS = {
4
+ accessToken: { value: '', expiresAt: 0 },
5
+ refreshToken: { value: '', role: TokenRole.NONE },
6
+ };
7
+ export function createLocalTokenStorage(initialTokens) {
8
+ let _tokens = initialTokens;
9
+ return {
10
+ getTokens: () => _tokens,
11
+ setTokens: (tokens) => {
12
+ _tokens = tokens;
13
+ },
14
+ };
15
+ }
@@ -4,6 +4,14 @@ export interface Tokens {
4
4
  accessToken: AccessToken;
5
5
  refreshToken: RefreshToken;
6
6
  }
7
+ /**
8
+ * Interface for custom token storage implementations.
9
+ * Storage must always return valid Tokens - use EMPTY_TOKENS as fallback when underlying storage is empty.
10
+ */
11
+ export interface TokenStorage {
12
+ getTokens(): Tokens;
13
+ setTokens(tokens: Tokens): void;
14
+ }
7
15
  export interface Token {
8
16
  value: string;
9
17
  }
package/build/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './wixClient.js';
2
2
  export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
+ export * from './auth/oauth2/token-storage.js';
5
6
  export * from './auth/ApiKeyAuthStrategy.js';
6
7
  export * from './auth/AppStrategy.js';
7
8
  export * from '@wix/sdk-types';
package/build/index.js CHANGED
@@ -2,6 +2,7 @@ export * from './wixClient.js';
2
2
  export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
+ export * from './auth/oauth2/token-storage.js';
5
6
  export * from './auth/ApiKeyAuthStrategy.js';
6
7
  export * from './auth/AppStrategy.js';
7
8
  export * from '@wix/sdk-types';
@@ -1,10 +1,32 @@
1
- import { RefreshToken, Tokens } from './oauth2/types.js';
1
+ import { RefreshToken, Tokens, TokenStorage } from './oauth2/types.js';
2
2
  import { isVisitorCookieWarmedUp, preWarmVisitorCookie } from './pre-warm-cookie.js';
3
+ /**
4
+ * Site session authentication strategy for Wix SDK.
5
+ * @param config - Configuration object
6
+ * @param config.clientId - The OAuth client ID
7
+ * @param config.publicKey - Optional public key for token verification
8
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
9
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
10
+ * When provided, the strategy delegates all token persistence to this storage.
11
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
12
+ * @returns Site session auth instance
13
+ * @example
14
+ * // Default in-memory storage with initial tokens
15
+ * SiteSessionAuth({ clientId: 'xxx', tokens: myTokens })
16
+ * @example
17
+ * // Custom storage (e.g., cookies)
18
+ * SiteSessionAuth({ clientId: 'xxx', tokenStorage: myCookieStorage })
19
+ */
3
20
  export declare function SiteSessionAuth(config: {
4
21
  clientId: string;
5
22
  publicKey?: string;
23
+ } & ({
6
24
  tokens?: Tokens;
7
- }): {
25
+ tokenStorage?: never;
26
+ } | {
27
+ tokenStorage: TokenStorage;
28
+ tokens?: never;
29
+ })): {
8
30
  generateVisitorTokens: (tokens?: Partial<Tokens>) => Promise<Tokens>;
9
31
  renewToken: (refreshToken: RefreshToken) => Promise<Tokens>;
10
32
  getAuthHeaders: () => Promise<{
@@ -5,27 +5,55 @@ const biHeaderGenerator_js_1 = require("../bi/biHeaderGenerator.js");
5
5
  const common_js_1 = require("../common.js");
6
6
  const tokenHelpers_js_1 = require("../tokenHelpers.js");
7
7
  const types_js_1 = require("./oauth2/types.js");
8
+ const token_storage_js_1 = require("./oauth2/token-storage.js");
8
9
  const pre_warm_cookie_js_1 = require("./pre-warm-cookie.js");
10
+ /**
11
+ * Site session authentication strategy for Wix SDK.
12
+ * @param config - Configuration object
13
+ * @param config.clientId - The OAuth client ID
14
+ * @param config.publicKey - Optional public key for token verification
15
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
16
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
17
+ * When provided, the strategy delegates all token persistence to this storage.
18
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
19
+ * @returns Site session auth instance
20
+ * @example
21
+ * // Default in-memory storage with initial tokens
22
+ * SiteSessionAuth({ clientId: 'xxx', tokens: myTokens })
23
+ * @example
24
+ * // Custom storage (e.g., cookies)
25
+ * SiteSessionAuth({ clientId: 'xxx', tokenStorage: myCookieStorage })
26
+ */
9
27
  function SiteSessionAuth(config) {
10
- const _tokens = config.tokens || {
11
- accessToken: { value: '', expiresAt: 0 },
12
- refreshToken: { value: '', role: types_js_1.TokenRole.NONE },
13
- };
28
+ const _tokenStorage = config.tokenStorage ??
29
+ (0, token_storage_js_1.createLocalTokenStorage)(config.tokens ?? token_storage_js_1.EMPTY_TOKENS);
30
+ const getTokens = () => _tokenStorage.getTokens();
14
31
  const setTokens = (tokens) => {
15
- _tokens.accessToken = tokens.accessToken;
16
- _tokens.refreshToken = tokens.refreshToken;
32
+ _tokenStorage.setTokens(tokens);
17
33
  };
18
34
  const getAuthHeaders = async () => {
19
- if (!_tokens.accessToken?.value || (0, tokenHelpers_js_1.isTokenExpired)(_tokens.accessToken)) {
20
- const tokens = await generateVisitorTokens({
21
- refreshToken: _tokens.refreshToken,
35
+ const currentTokens = getTokens();
36
+ if (!currentTokens.accessToken?.value ||
37
+ (0, tokenHelpers_js_1.isTokenExpired)(currentTokens.accessToken)) {
38
+ const newTokens = await generateVisitorTokens({
39
+ refreshToken: currentTokens.refreshToken,
22
40
  });
23
- setTokens(tokens);
41
+ setTokens(newTokens);
24
42
  }
25
43
  return Promise.resolve({
26
- headers: { Authorization: _tokens.accessToken.value },
44
+ headers: { Authorization: getTokens().accessToken.value },
27
45
  });
28
46
  };
47
+ /**
48
+ * Name is misleading, it should be called generateTokens. Ensures valid tokens are available, refreshing or generating new ones as needed.
49
+ *
50
+ * Scenarios:
51
+ * 1. If valid (non-expired) access and refresh tokens are provided, returns them as-is.
52
+ * 2. If a refresh token is provided but access token is missing/expired, attempts to renew using the refresh token.
53
+ * 3. If renewal fails or no refresh token exists, generates new anonymous visitor tokens.
54
+ * @param tokens - Optional partial tokens (accessToken and/or refreshToken)
55
+ * @returns Valid tokens (accessToken + refreshToken)
56
+ */
29
57
  const generateVisitorTokens = async (tokens) => {
30
58
  if (tokens?.accessToken?.value &&
31
59
  tokens?.refreshToken?.value &&
@@ -65,7 +93,7 @@ function SiteSessionAuth(config) {
65
93
  };
66
94
  };
67
95
  const loggedIn = () => {
68
- return _tokens.refreshToken.role === types_js_1.TokenRole.MEMBER;
96
+ return getTokens().refreshToken.role === types_js_1.TokenRole.MEMBER;
69
97
  };
70
98
  return {
71
99
  generateVisitorTokens,
@@ -73,7 +101,7 @@ function SiteSessionAuth(config) {
73
101
  getAuthHeaders,
74
102
  setTokens,
75
103
  loggedIn,
76
- getTokens: () => _tokens,
104
+ getTokens,
77
105
  isSessionSynced: pre_warm_cookie_js_1.isVisitorCookieWarmedUp,
78
106
  syncToWixPages: pre_warm_cookie_js_1.preWarmVisitorCookie,
79
107
  shouldUseCDN: true,
@@ -1,9 +1,31 @@
1
- import { IOAuthStrategy, Tokens } from './types.js';
1
+ import { IOAuthStrategy, Tokens, TokenStorage } from './types.js';
2
+ /**
3
+ * OAuth authentication strategy for Wix SDK.
4
+ * @param config - Configuration object
5
+ * @param config.clientId - The OAuth client ID
6
+ * @param config.publicKey - Optional public key for token verification
7
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
8
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
9
+ * When provided, the strategy delegates all token persistence to this storage.
10
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
11
+ * @returns OAuth strategy instance
12
+ * @example
13
+ * // Default in-memory storage with initial tokens
14
+ * OAuthStrategy({ clientId: 'xxx', tokens: myTokens })
15
+ * @example
16
+ * // Custom storage (e.g., cookies)
17
+ * OAuthStrategy({ clientId: 'xxx', tokenStorage: myCookieStorage })
18
+ */
2
19
  export declare function OAuthStrategy(config: {
3
20
  clientId: string;
4
21
  publicKey?: string;
22
+ } & ({
5
23
  tokens?: Tokens;
6
- }): IOAuthStrategy;
24
+ tokenStorage?: never;
25
+ } | {
26
+ tokenStorage: TokenStorage;
27
+ tokens?: never;
28
+ })): IOAuthStrategy;
7
29
  export interface TokenResponse {
8
30
  access_token: string;
9
31
  expires_in: number;
@@ -12,34 +12,60 @@ const constants_js_1 = require("./constants.js");
12
12
  const biHeaderGenerator_js_1 = require("../../bi/biHeaderGenerator.js");
13
13
  const pkce_challenge_js_1 = require("./pkce-challenge.js");
14
14
  const pre_warm_cookie_js_1 = require("../pre-warm-cookie.js");
15
+ const token_storage_js_1 = require("./token-storage.js");
15
16
  const moduleWithTokens = { redirects: redirects_1.redirects, authentication: identity_1.authentication, recovery: identity_1.recovery, verification: identity_1.verification };
17
+ /**
18
+ * OAuth authentication strategy for Wix SDK.
19
+ * @param config - Configuration object
20
+ * @param config.clientId - The OAuth client ID
21
+ * @param config.publicKey - Optional public key for token verification
22
+ * @param config.tokens - Initial tokens for in-memory storage (mutually exclusive with `tokenStorage`)
23
+ * @param config.tokenStorage - Custom storage implementation (mutually exclusive with `tokens`).
24
+ * When provided, the strategy delegates all token persistence to this storage.
25
+ * The storage's `getTokens()` must always return `Tokens` (use `EMPTY_TOKENS` as fallback).
26
+ * @returns OAuth strategy instance
27
+ * @example
28
+ * // Default in-memory storage with initial tokens
29
+ * OAuthStrategy({ clientId: 'xxx', tokens: myTokens })
30
+ * @example
31
+ * // Custom storage (e.g., cookies)
32
+ * OAuthStrategy({ clientId: 'xxx', tokenStorage: myCookieStorage })
33
+ */
16
34
  function OAuthStrategy(config) {
17
- const _tokens = config.tokens || {
18
- accessToken: { value: '', expiresAt: 0 },
19
- refreshToken: { value: '', role: types_js_1.TokenRole.NONE },
20
- };
21
- const setTokens = (tokens) => {
22
- _tokens.accessToken = tokens.accessToken;
23
- _tokens.refreshToken = tokens.refreshToken;
24
- };
35
+ const _tokenStorage = config.tokenStorage ??
36
+ (0, token_storage_js_1.createLocalTokenStorage)(config.tokens ?? token_storage_js_1.EMPTY_TOKENS);
37
+ const getTokens = () => _tokenStorage.getTokens();
38
+ const setTokens = (tokens) => _tokenStorage.setTokens(tokens);
25
39
  let _state = {
26
40
  loginState: types_js_1.LoginState.INITIAL,
27
41
  };
28
42
  const getAuthHeaders = async () => {
29
- if (!_tokens.accessToken?.value || (0, tokenHelpers_js_1.isTokenExpired)(_tokens.accessToken)) {
30
- const tokens = await generateVisitorTokens({
31
- refreshToken: _tokens.refreshToken,
43
+ const currentTokens = getTokens();
44
+ if (!currentTokens.accessToken?.value ||
45
+ (0, tokenHelpers_js_1.isTokenExpired)(currentTokens.accessToken)) {
46
+ const newTokens = await generateVisitorTokens({
47
+ refreshToken: currentTokens.refreshToken,
32
48
  });
33
- setTokens(tokens);
49
+ setTokens(newTokens);
34
50
  }
35
51
  return Promise.resolve({
36
- headers: { Authorization: _tokens.accessToken.value },
52
+ headers: { Authorization: getTokens().accessToken.value },
37
53
  });
38
54
  };
39
55
  const wixClientWithTokens = (0, wixClient_js_1.createClient)({
40
56
  modules: moduleWithTokens,
41
57
  auth: { getAuthHeaders },
42
58
  });
59
+ /**
60
+ * Name is misleading, it should be called generateTokens. Ensures valid tokens are available, refreshing or generating new ones as needed.
61
+ *
62
+ * Scenarios:
63
+ * 1. If valid (non-expired) access and refresh tokens are provided, returns them as-is.
64
+ * 2. If a refresh token is provided but access token is missing/expired, attempts to renew using the refresh token.
65
+ * 3. If renewal fails or no refresh token exists, generates new anonymous visitor tokens.
66
+ * @param tokens - Optional partial tokens (accessToken and/or refreshToken)
67
+ * @returns Valid tokens (accessToken + refreshToken)
68
+ */
43
69
  const generateVisitorTokens = async (tokens) => {
44
70
  if (tokens?.accessToken?.value &&
45
71
  tokens?.refreshToken?.value &&
@@ -168,8 +194,10 @@ function OAuthStrategy(config) {
168
194
  postFlowUrl: originalUrl,
169
195
  },
170
196
  });
171
- _tokens.accessToken = { value: '', expiresAt: 0 };
172
- _tokens.refreshToken = { value: '', role: types_js_1.TokenRole.NONE };
197
+ setTokens({
198
+ accessToken: { value: '', expiresAt: 0 },
199
+ refreshToken: { value: '', role: types_js_1.TokenRole.NONE },
200
+ });
173
201
  return { logoutUrl: redirectSession.fullUrl };
174
202
  };
175
203
  const handleState = (response) => {
@@ -316,7 +344,7 @@ function OAuthStrategy(config) {
316
344
  });
317
345
  };
318
346
  const loggedIn = () => {
319
- return _tokens.refreshToken.role === types_js_1.TokenRole.MEMBER;
347
+ return getTokens().refreshToken.role === types_js_1.TokenRole.MEMBER;
320
348
  };
321
349
  const getMemberTokensForExternalLogin = async (memberId, apiKey) => {
322
350
  const tokensResponse = await fetchTokens({
@@ -324,7 +352,7 @@ function OAuthStrategy(config) {
324
352
  scope: 'offline_access',
325
353
  member_id: memberId,
326
354
  }, {
327
- Authorization: _tokens.accessToken.value + ',' + apiKey,
355
+ Authorization: getTokens().accessToken.value + ',' + apiKey,
328
356
  });
329
357
  return {
330
358
  accessToken: (0, tokenHelpers_js_1.createAccessToken)(tokensResponse.access_token, tokensResponse.expires_in),
@@ -343,7 +371,7 @@ function OAuthStrategy(config) {
343
371
  generateOAuthData,
344
372
  getAuthHeaders,
345
373
  setTokens,
346
- getTokens: () => _tokens,
374
+ getTokens,
347
375
  loggedIn,
348
376
  logout,
349
377
  register,
@@ -0,0 +1,3 @@
1
+ import { type TokenStorage, type Tokens } from './types.js';
2
+ export declare const EMPTY_TOKENS: Tokens;
3
+ export declare function createLocalTokenStorage(initialTokens: Tokens): TokenStorage;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EMPTY_TOKENS = void 0;
4
+ exports.createLocalTokenStorage = createLocalTokenStorage;
5
+ const types_js_1 = require("./types.js");
6
+ // These tokens are considered empty tokens, and can be used as a fallback when no tokens are available.
7
+ exports.EMPTY_TOKENS = {
8
+ accessToken: { value: '', expiresAt: 0 },
9
+ refreshToken: { value: '', role: types_js_1.TokenRole.NONE },
10
+ };
11
+ function createLocalTokenStorage(initialTokens) {
12
+ let _tokens = initialTokens;
13
+ return {
14
+ getTokens: () => _tokens,
15
+ setTokens: (tokens) => {
16
+ _tokens = tokens;
17
+ },
18
+ };
19
+ }
@@ -4,6 +4,14 @@ export interface Tokens {
4
4
  accessToken: AccessToken;
5
5
  refreshToken: RefreshToken;
6
6
  }
7
+ /**
8
+ * Interface for custom token storage implementations.
9
+ * Storage must always return valid Tokens - use EMPTY_TOKENS as fallback when underlying storage is empty.
10
+ */
11
+ export interface TokenStorage {
12
+ getTokens(): Tokens;
13
+ setTokens(tokens: Tokens): void;
14
+ }
7
15
  export interface Token {
8
16
  value: string;
9
17
  }
@@ -2,6 +2,7 @@ export * from './wixClient.js';
2
2
  export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
+ export * from './auth/oauth2/token-storage.js';
5
6
  export * from './auth/ApiKeyAuthStrategy.js';
6
7
  export * from './auth/AppStrategy.js';
7
8
  export * from '@wix/sdk-types';
@@ -19,6 +19,7 @@ __exportStar(require("./wixClient.js"), exports);
19
19
  __exportStar(require("./wixMedia.js"), exports);
20
20
  __exportStar(require("./auth/oauth2/OAuthStrategy.js"), exports);
21
21
  __exportStar(require("./auth/oauth2/types.js"), exports);
22
+ __exportStar(require("./auth/oauth2/token-storage.js"), exports);
22
23
  __exportStar(require("./auth/ApiKeyAuthStrategy.js"), exports);
23
24
  __exportStar(require("./auth/AppStrategy.js"), exports);
24
25
  __exportStar(require("@wix/sdk-types"), exports);
package/package.json CHANGED
@@ -1,14 +1,42 @@
1
1
  {
2
2
  "name": "@wix/sdk",
3
- "version": "1.20.0",
4
- "license": "MIT",
3
+ "version": "1.21.1",
5
4
  "author": {
6
5
  "name": "Ronny Ringel",
7
6
  "email": "ronnyr@wix.com"
8
7
  },
9
- "main": "cjs/build/index.js",
10
- "module": "build/index.mjs",
11
- "type": "module",
8
+ "dependencies": {
9
+ "@wix/identity": "^1.0.104",
10
+ "@wix/image-kit": "^1.114.0",
11
+ "@wix/redirects": "^1.0.70",
12
+ "@wix/sdk-context": "0.0.1",
13
+ "@wix/sdk-runtime": "1.0.3",
14
+ "@wix/sdk-types": "1.17.1",
15
+ "jose": "^5.10.0",
16
+ "type-fest": "^4.41.0"
17
+ },
18
+ "devDependencies": {
19
+ "@types/is-ci": "^3.0.4",
20
+ "@types/node": "^20.19.25",
21
+ "@vitest/ui": "^1.6.1",
22
+ "@wix/ecom": "^1.0.886",
23
+ "@wix/events": "^1.0.382",
24
+ "@wix/metro": "^1.0.93",
25
+ "@wix/metro-runtime": "^1.1891.0",
26
+ "@wix/sdk-runtime": "1.0.3",
27
+ "eslint": "^8.57.1",
28
+ "eslint-config-sdk": "1.0.0",
29
+ "graphql": "^16.8.0",
30
+ "is-ci": "^3.0.1",
31
+ "jsdom": "^22.1.0",
32
+ "msw": "^2.12.2",
33
+ "typescript": "^5.9.3",
34
+ "vitest": "^1.6.1",
35
+ "vitest-teamcity-reporter": "^0.3.1"
36
+ },
37
+ "eslintConfig": {
38
+ "extends": "sdk"
39
+ },
12
40
  "exports": {
13
41
  ".": {
14
42
  "import": "./build/index.js",
@@ -48,7 +76,6 @@
48
76
  "require": "./cjs/build/media/helpers.js"
49
77
  }
50
78
  },
51
- "sideEffects": false,
52
79
  "files": [
53
80
  "build",
54
81
  "auth",
@@ -57,57 +84,30 @@
57
84
  "context",
58
85
  "media"
59
86
  ],
87
+ "license": "MIT",
88
+ "lint-staged": {
89
+ "*.{js,ts}": "yarn lint"
90
+ },
91
+ "main": "cjs/build/index.js",
92
+ "module": "build/index.mjs",
93
+ "optionalDependencies": {
94
+ "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
95
+ },
60
96
  "publishConfig": {
61
97
  "registry": "https://registry.npmjs.org/",
62
98
  "access": "public"
63
99
  },
64
100
  "scripts": {
65
101
  "build": "tsc && tsc --project tsconfig.cjs.json",
66
- "test": "vitest run",
67
102
  "lint": "eslint --max-warnings=0 .",
68
103
  "lint:fix": "eslint --max-warnings=0 . --fix",
104
+ "test": "vitest run",
69
105
  "typecheck": "tsc --noEmit"
70
106
  },
71
- "lint-staged": {
72
- "*.{js,ts}": "yarn lint"
73
- },
74
- "dependencies": {
75
- "@wix/identity": "^1.0.104",
76
- "@wix/image-kit": "^1.114.0",
77
- "@wix/redirects": "^1.0.70",
78
- "@wix/sdk-context": "0.0.1",
79
- "@wix/sdk-runtime": "1.0.2",
80
- "@wix/sdk-types": "1.16.0",
81
- "jose": "^5.10.0",
82
- "type-fest": "^4.41.0"
83
- },
84
- "optionalDependencies": {
85
- "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
86
- },
87
- "devDependencies": {
88
- "@types/is-ci": "^3.0.4",
89
- "@types/node": "^20.19.25",
90
- "@vitest/ui": "^1.6.1",
91
- "@wix/ecom": "^1.0.886",
92
- "@wix/events": "^1.0.382",
93
- "@wix/metro": "^1.0.93",
94
- "@wix/metro-runtime": "^1.1891.0",
95
- "@wix/sdk-runtime": "1.0.2",
96
- "eslint": "^8.57.1",
97
- "eslint-config-sdk": "1.0.0",
98
- "graphql": "^16.8.0",
99
- "is-ci": "^3.0.1",
100
- "jsdom": "^22.1.0",
101
- "msw": "^2.12.2",
102
- "typescript": "^5.9.3",
103
- "vitest": "^1.6.1",
104
- "vitest-teamcity-reporter": "^0.3.1"
105
- },
106
- "yoshiFlowLibrary": {
107
- "buildEsmWithBabel": true
108
- },
109
- "eslintConfig": {
110
- "extends": "sdk"
107
+ "sideEffects": false,
108
+ "type": "module",
109
+ "wallaby": {
110
+ "autoDetect": true
111
111
  },
112
112
  "wix": {
113
113
  "artifact": {
@@ -123,8 +123,8 @@
123
123
  ]
124
124
  }
125
125
  },
126
- "wallaby": {
127
- "autoDetect": true
126
+ "yoshiFlowLibrary": {
127
+ "buildEsmWithBabel": true
128
128
  },
129
- "falconPackageHash": "4073f5e283bbe708a3e8e45d798f3998874111ad3aab43d426686c29"
129
+ "falconPackageHash": "b15d34d496e485b7ec7be4a51298d0acccc5273ecb15b7b370d50b9b"
130
130
  }