@commercengine/storefront-sdk 0.3.6 → 0.3.8
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/dist/index.d.ts +4 -3
- package/dist/index.js +7 -5
- package/dist/lib/client.d.ts +5 -0
- package/dist/lib/client.js +27 -14
- package/dist/lib/middleware.d.ts +46 -0
- package/dist/lib/middleware.js +88 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { OrderClient } from "./lib/order";
|
|
|
6
6
|
import { ShippingClient } from "./lib/shipping";
|
|
7
7
|
import { HelpersClient } from "./lib/helper";
|
|
8
8
|
import { CustomerClient } from "./lib/customer";
|
|
9
|
-
import { TokenStorage, MemoryTokenStorage, BrowserTokenStorage } from "./lib/middleware";
|
|
9
|
+
import { TokenStorage, MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage } from "./lib/middleware";
|
|
10
10
|
import { type UserInfo } from "./lib/jwt-utils";
|
|
11
11
|
/**
|
|
12
12
|
* SDK initialization options
|
|
@@ -168,9 +168,10 @@ export declare class StorefrontSDK {
|
|
|
168
168
|
getCustomerGroupId(): Promise<string | null>;
|
|
169
169
|
}
|
|
170
170
|
export default StorefrontSDK;
|
|
171
|
-
export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient };
|
|
171
|
+
export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, };
|
|
172
172
|
export { Environment };
|
|
173
|
-
export { TokenStorage, MemoryTokenStorage, BrowserTokenStorage };
|
|
173
|
+
export { TokenStorage, MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage, };
|
|
174
|
+
export type { CookieTokenStorageOptions } from "./lib/middleware";
|
|
174
175
|
export type { UserInfo } from "./lib/jwt-utils";
|
|
175
176
|
export type { components, operations, paths } from "./types/storefront";
|
|
176
177
|
export type * from "./types/storefront-api-types";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StorefrontAPIClient, Environment
|
|
1
|
+
import { StorefrontAPIClient, Environment } from "./lib/client";
|
|
2
2
|
import { CatalogClient } from "./lib/catalog";
|
|
3
3
|
import { CartClient } from "./lib/cart";
|
|
4
4
|
import { AuthClient } from "./lib/auth";
|
|
@@ -6,7 +6,7 @@ import { OrderClient } from "./lib/order";
|
|
|
6
6
|
import { ShippingClient } from "./lib/shipping";
|
|
7
7
|
import { HelpersClient } from "./lib/helper";
|
|
8
8
|
import { CustomerClient } from "./lib/customer";
|
|
9
|
-
import { MemoryTokenStorage, BrowserTokenStorage, } from "./lib/middleware";
|
|
9
|
+
import { MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage, } from "./lib/middleware";
|
|
10
10
|
import { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous, } from "./lib/jwt-utils";
|
|
11
11
|
/**
|
|
12
12
|
* Main SDK class for the Storefront API
|
|
@@ -132,7 +132,9 @@ export class StorefrontSDK {
|
|
|
132
132
|
* Get the current access token if using token storage
|
|
133
133
|
*/
|
|
134
134
|
async getAccessToken() {
|
|
135
|
-
return await this.auth
|
|
135
|
+
return await this.auth
|
|
136
|
+
.getAuthorizationHeader()
|
|
137
|
+
.then((header) => header.startsWith("Bearer ") ? header.substring(7) : null);
|
|
136
138
|
}
|
|
137
139
|
/**
|
|
138
140
|
* Get user information from the current access token
|
|
@@ -200,8 +202,8 @@ export class StorefrontSDK {
|
|
|
200
202
|
// Export the main SDK class
|
|
201
203
|
export default StorefrontSDK;
|
|
202
204
|
// Export individual clients for advanced usage
|
|
203
|
-
export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient };
|
|
205
|
+
export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, };
|
|
204
206
|
// Export environment enum
|
|
205
207
|
export { Environment };
|
|
206
208
|
// Export token storage types
|
|
207
|
-
export { MemoryTokenStorage, BrowserTokenStorage };
|
|
209
|
+
export { MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage, };
|
package/dist/lib/client.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export declare class StorefrontAPIClient {
|
|
|
22
22
|
protected client: ReturnType<typeof createClient<paths>>;
|
|
23
23
|
protected config: StorefrontSDKOptions;
|
|
24
24
|
private readonly baseUrl;
|
|
25
|
+
private initializationPromise;
|
|
25
26
|
/**
|
|
26
27
|
* Create a new StorefrontAPIClient
|
|
27
28
|
*
|
|
@@ -97,4 +98,8 @@ export declare class StorefrontAPIClient {
|
|
|
97
98
|
error?: ApiErrorResponse;
|
|
98
99
|
response: Response;
|
|
99
100
|
}>): Promise<ApiResult<T>>;
|
|
101
|
+
/**
|
|
102
|
+
* Initialize tokens in storage (private helper method)
|
|
103
|
+
*/
|
|
104
|
+
private initializeTokens;
|
|
100
105
|
}
|
package/dist/lib/client.js
CHANGED
|
@@ -22,6 +22,7 @@ export class StorefrontAPIClient {
|
|
|
22
22
|
client;
|
|
23
23
|
config;
|
|
24
24
|
baseUrl;
|
|
25
|
+
initializationPromise = null;
|
|
25
26
|
/**
|
|
26
27
|
* Create a new StorefrontAPIClient
|
|
27
28
|
*
|
|
@@ -46,17 +47,9 @@ export class StorefrontAPIClient {
|
|
|
46
47
|
this.client.use(authMiddleware);
|
|
47
48
|
// If initial tokens were provided, store them in tokenStorage
|
|
48
49
|
if (this.config.accessToken) {
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
// Clear the manual token since we're using storage
|
|
50
|
+
this.initializationPromise = this.initializeTokens(this.config.accessToken, this.config.refreshToken);
|
|
51
|
+
// Clear the manual tokens since we're using storage
|
|
53
52
|
this.config.accessToken = undefined;
|
|
54
|
-
}
|
|
55
|
-
if (this.config.refreshToken) {
|
|
56
|
-
this.config.tokenStorage.setRefreshToken(this.config.refreshToken).catch(error => {
|
|
57
|
-
console.warn('Failed to set initial refresh token in storage:', error);
|
|
58
|
-
});
|
|
59
|
-
// Clear the manual refresh token since we're using storage
|
|
60
53
|
this.config.refreshToken = undefined;
|
|
61
54
|
}
|
|
62
55
|
}
|
|
@@ -100,14 +93,14 @@ export class StorefrontAPIClient {
|
|
|
100
93
|
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
101
94
|
// Merge with existing signal if present
|
|
102
95
|
if (request.signal) {
|
|
103
|
-
request.signal.addEventListener(
|
|
96
|
+
request.signal.addEventListener("abort", () => controller.abort());
|
|
104
97
|
}
|
|
105
98
|
// Create new request with timeout signal
|
|
106
99
|
const newRequest = new Request(request, {
|
|
107
100
|
signal: controller.signal,
|
|
108
101
|
});
|
|
109
102
|
// Clean up timeout when request completes
|
|
110
|
-
controller.signal.addEventListener(
|
|
103
|
+
controller.signal.addEventListener("abort", () => clearTimeout(timeoutId));
|
|
111
104
|
return newRequest;
|
|
112
105
|
},
|
|
113
106
|
});
|
|
@@ -149,6 +142,10 @@ export class StorefrontAPIClient {
|
|
|
149
142
|
* @returns The Authorization header value or empty string if no token is set
|
|
150
143
|
*/
|
|
151
144
|
async getAuthorizationHeader() {
|
|
145
|
+
// Wait for initialization to complete if using token storage
|
|
146
|
+
if (this.config.tokenStorage && this.initializationPromise) {
|
|
147
|
+
await this.initializationPromise;
|
|
148
|
+
}
|
|
152
149
|
if (this.config.tokenStorage) {
|
|
153
150
|
const token = await this.config.tokenStorage.getAccessToken();
|
|
154
151
|
return token ? `Bearer ${token}` : "";
|
|
@@ -236,11 +233,27 @@ export class StorefrontAPIClient {
|
|
|
236
233
|
data: null,
|
|
237
234
|
error: {
|
|
238
235
|
success: false,
|
|
239
|
-
code:
|
|
240
|
-
message:
|
|
236
|
+
code: "NETWORK_ERROR",
|
|
237
|
+
message: "Network error occurred",
|
|
241
238
|
error: err,
|
|
242
239
|
},
|
|
243
240
|
};
|
|
244
241
|
}
|
|
245
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* Initialize tokens in storage (private helper method)
|
|
245
|
+
*/
|
|
246
|
+
async initializeTokens(accessToken, refreshToken) {
|
|
247
|
+
try {
|
|
248
|
+
if (this.config.tokenStorage) {
|
|
249
|
+
await this.config.tokenStorage.setAccessToken(accessToken);
|
|
250
|
+
if (refreshToken) {
|
|
251
|
+
await this.config.tokenStorage.setRefreshToken(refreshToken);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.warn("Failed to initialize tokens in storage:", error);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
246
259
|
}
|
package/dist/lib/middleware.d.ts
CHANGED
|
@@ -34,6 +34,52 @@ export declare class BrowserTokenStorage implements TokenStorage {
|
|
|
34
34
|
setRefreshToken(token: string): Promise<void>;
|
|
35
35
|
clearTokens(): Promise<void>;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Cookie-based token storage implementation
|
|
39
|
+
*/
|
|
40
|
+
export declare class CookieTokenStorage implements TokenStorage {
|
|
41
|
+
private accessTokenKey;
|
|
42
|
+
private refreshTokenKey;
|
|
43
|
+
private options;
|
|
44
|
+
constructor(options?: CookieTokenStorageOptions);
|
|
45
|
+
getAccessToken(): Promise<string | null>;
|
|
46
|
+
setAccessToken(token: string): Promise<void>;
|
|
47
|
+
getRefreshToken(): Promise<string | null>;
|
|
48
|
+
setRefreshToken(token: string): Promise<void>;
|
|
49
|
+
clearTokens(): Promise<void>;
|
|
50
|
+
private getCookie;
|
|
51
|
+
private setCookie;
|
|
52
|
+
private deleteCookie;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Configuration options for CookieTokenStorage
|
|
56
|
+
*/
|
|
57
|
+
export interface CookieTokenStorageOptions {
|
|
58
|
+
/**
|
|
59
|
+
* Prefix for cookie names (default: "storefront_")
|
|
60
|
+
*/
|
|
61
|
+
prefix?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Maximum age of cookies in seconds (default: 7 days)
|
|
64
|
+
*/
|
|
65
|
+
maxAge?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Cookie path (default: "/")
|
|
68
|
+
*/
|
|
69
|
+
path?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Cookie domain (default: current domain)
|
|
72
|
+
*/
|
|
73
|
+
domain?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Whether cookies should be secure (default: auto-detect based on protocol)
|
|
76
|
+
*/
|
|
77
|
+
secure?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* SameSite cookie attribute (default: "Lax")
|
|
80
|
+
*/
|
|
81
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
82
|
+
}
|
|
37
83
|
/**
|
|
38
84
|
* Configuration for the auth middleware
|
|
39
85
|
*/
|
package/dist/lib/middleware.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isTokenExpired } from "./jwt-utils";
|
|
2
|
-
import { getPathnameFromUrl, isAnonymousAuthEndpoint, isTokenReturningEndpoint, isLogoutEndpoint } from "./auth-utils";
|
|
2
|
+
import { getPathnameFromUrl, isAnonymousAuthEndpoint, isTokenReturningEndpoint, isLogoutEndpoint, } from "./auth-utils";
|
|
3
3
|
/**
|
|
4
4
|
* Simple in-memory token storage implementation
|
|
5
5
|
*/
|
|
@@ -60,6 +60,90 @@ export class BrowserTokenStorage {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Cookie-based token storage implementation
|
|
65
|
+
*/
|
|
66
|
+
export class CookieTokenStorage {
|
|
67
|
+
accessTokenKey;
|
|
68
|
+
refreshTokenKey;
|
|
69
|
+
options;
|
|
70
|
+
constructor(options = {}) {
|
|
71
|
+
const prefix = options.prefix || "storefront_";
|
|
72
|
+
this.accessTokenKey = `${prefix}access_token`;
|
|
73
|
+
this.refreshTokenKey = `${prefix}refresh_token`;
|
|
74
|
+
this.options = {
|
|
75
|
+
maxAge: options.maxAge || 7 * 24 * 60 * 60, // 7 days default
|
|
76
|
+
path: options.path || "/",
|
|
77
|
+
domain: options.domain,
|
|
78
|
+
secure: options.secure ??
|
|
79
|
+
(typeof window !== "undefined" &&
|
|
80
|
+
window.location?.protocol === "https:"),
|
|
81
|
+
sameSite: options.sameSite || "Lax",
|
|
82
|
+
httpOnly: false, // Must be false for client-side access
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async getAccessToken() {
|
|
86
|
+
return this.getCookie(this.accessTokenKey);
|
|
87
|
+
}
|
|
88
|
+
async setAccessToken(token) {
|
|
89
|
+
this.setCookie(this.accessTokenKey, token);
|
|
90
|
+
}
|
|
91
|
+
async getRefreshToken() {
|
|
92
|
+
return this.getCookie(this.refreshTokenKey);
|
|
93
|
+
}
|
|
94
|
+
async setRefreshToken(token) {
|
|
95
|
+
this.setCookie(this.refreshTokenKey, token);
|
|
96
|
+
}
|
|
97
|
+
async clearTokens() {
|
|
98
|
+
this.deleteCookie(this.accessTokenKey);
|
|
99
|
+
this.deleteCookie(this.refreshTokenKey);
|
|
100
|
+
}
|
|
101
|
+
getCookie(name) {
|
|
102
|
+
if (typeof document === "undefined")
|
|
103
|
+
return null;
|
|
104
|
+
const value = `; ${document.cookie}`;
|
|
105
|
+
const parts = value.split(`; ${name}=`);
|
|
106
|
+
if (parts.length === 2) {
|
|
107
|
+
const cookieValue = parts.pop()?.split(";").shift();
|
|
108
|
+
return cookieValue ? decodeURIComponent(cookieValue) : null;
|
|
109
|
+
}
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
setCookie(name, value) {
|
|
113
|
+
if (typeof document === "undefined")
|
|
114
|
+
return;
|
|
115
|
+
const encodedValue = encodeURIComponent(value);
|
|
116
|
+
let cookieString = `${name}=${encodedValue}`;
|
|
117
|
+
if (this.options.maxAge) {
|
|
118
|
+
cookieString += `; Max-Age=${this.options.maxAge}`;
|
|
119
|
+
}
|
|
120
|
+
if (this.options.path) {
|
|
121
|
+
cookieString += `; Path=${this.options.path}`;
|
|
122
|
+
}
|
|
123
|
+
if (this.options.domain) {
|
|
124
|
+
cookieString += `; Domain=${this.options.domain}`;
|
|
125
|
+
}
|
|
126
|
+
if (this.options.secure) {
|
|
127
|
+
cookieString += `; Secure`;
|
|
128
|
+
}
|
|
129
|
+
if (this.options.sameSite) {
|
|
130
|
+
cookieString += `; SameSite=${this.options.sameSite}`;
|
|
131
|
+
}
|
|
132
|
+
document.cookie = cookieString;
|
|
133
|
+
}
|
|
134
|
+
deleteCookie(name) {
|
|
135
|
+
if (typeof document === "undefined")
|
|
136
|
+
return;
|
|
137
|
+
let cookieString = `${name}=; Max-Age=0`;
|
|
138
|
+
if (this.options.path) {
|
|
139
|
+
cookieString += `; Path=${this.options.path}`;
|
|
140
|
+
}
|
|
141
|
+
if (this.options.domain) {
|
|
142
|
+
cookieString += `; Domain=${this.options.domain}`;
|
|
143
|
+
}
|
|
144
|
+
document.cookie = cookieString;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
63
147
|
/**
|
|
64
148
|
* Create authentication middleware for openapi-fetch
|
|
65
149
|
*/
|
|
@@ -115,7 +199,7 @@ export function createAuthMiddleware(config) {
|
|
|
115
199
|
headers: {
|
|
116
200
|
"Content-Type": "application/json",
|
|
117
201
|
...(config.apiKey && { "X-Api-Key": config.apiKey }),
|
|
118
|
-
|
|
202
|
+
Authorization: `Bearer ${currentAccessToken}`, // For user_id continuity
|
|
119
203
|
},
|
|
120
204
|
});
|
|
121
205
|
if (!response.ok) {
|
|
@@ -184,7 +268,8 @@ export function createAuthMiddleware(config) {
|
|
|
184
268
|
const pathname = getPathnameFromUrl(request.url);
|
|
185
269
|
// Handle successful responses that return tokens
|
|
186
270
|
if (response.ok) {
|
|
187
|
-
if (isTokenReturningEndpoint(pathname) ||
|
|
271
|
+
if (isTokenReturningEndpoint(pathname) ||
|
|
272
|
+
isAnonymousAuthEndpoint(pathname)) {
|
|
188
273
|
try {
|
|
189
274
|
const data = await response.clone().json();
|
|
190
275
|
const content = data.content;
|