@commercengine/storefront-sdk 0.3.1 → 0.3.3

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 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, createDefaultAuthMiddleware, createAuthMiddleware, type AuthMiddlewareConfig } from "./lib/middleware";
9
+ import { TokenStorage, MemoryTokenStorage, BrowserTokenStorage } from "./lib/middleware";
10
10
  import { type UserInfo } from "./lib/jwt-utils";
11
11
  /**
12
12
  * SDK initialization options
@@ -25,9 +25,17 @@ export interface StorefrontSDKOptions {
25
25
  */
26
26
  baseUrl?: string;
27
27
  /**
28
- * Optional authentication token (for manual token management)
28
+ * Optional initial access token
29
+ * - If tokenStorage is provided: Used as initial token value, then managed automatically
30
+ * - If tokenStorage is not provided: Used for manual token management
29
31
  */
30
- token?: string;
32
+ accessToken?: string;
33
+ /**
34
+ * Optional initial refresh token
35
+ * - Only used when tokenStorage is provided
36
+ * - Allows initialization with both access and refresh tokens
37
+ */
38
+ refreshToken?: string;
31
39
  /**
32
40
  * X-Api-Key for anonymous authentication endpoints
33
41
  * Required for initial authentication
@@ -90,13 +98,24 @@ export declare class StorefrontSDK {
90
98
  */
91
99
  constructor(options: StorefrontSDKOptions);
92
100
  /**
93
- * Set the authentication token for all clients
101
+ * Set authentication tokens for all clients
102
+ *
103
+ * @param accessToken - The access token (required)
104
+ * @param refreshToken - The refresh token (optional)
105
+ *
106
+ * Behavior:
107
+ * - If tokenStorage is provided: Stores tokens for automatic management
108
+ * - If tokenStorage is not provided: Only stores access token for manual management
94
109
  */
95
- setToken(token: string): Promise<void>;
110
+ setTokens(accessToken: string, refreshToken?: string): Promise<void>;
96
111
  /**
97
- * Clear the authentication token from all clients
112
+ * Clear all authentication tokens from all clients
113
+ *
114
+ * Behavior:
115
+ * - If tokenStorage is provided: Clears both access and refresh tokens from storage
116
+ * - If tokenStorage is not provided: Clears the manual access token
98
117
  */
99
- clearToken(): Promise<void>;
118
+ clearTokens(): Promise<void>;
100
119
  /**
101
120
  * Set the API key for all clients
102
121
  *
@@ -151,7 +170,7 @@ export declare class StorefrontSDK {
151
170
  export default StorefrontSDK;
152
171
  export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient };
153
172
  export { Environment };
154
- export { TokenStorage, MemoryTokenStorage, BrowserTokenStorage, createDefaultAuthMiddleware, createAuthMiddleware, type AuthMiddlewareConfig };
155
- export { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous, isTokenExpired, type UserInfo, type JwtPayload } from "./lib/jwt-utils";
173
+ export { TokenStorage, MemoryTokenStorage, BrowserTokenStorage };
174
+ export type { UserInfo } from "./lib/jwt-utils";
156
175
  export type { components, operations, paths } from "./types/storefront";
157
176
  export type * from "./types/storefront-api-types";
package/dist/index.js CHANGED
@@ -6,8 +6,8 @@ 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, createDefaultAuthMiddleware, createAuthMiddleware } from "./lib/middleware";
10
- import { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous } from "./lib/jwt-utils";
9
+ import { MemoryTokenStorage, BrowserTokenStorage, } from "./lib/middleware";
10
+ import { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous, } from "./lib/jwt-utils";
11
11
  /**
12
12
  * Main SDK class for the Storefront API
13
13
  */
@@ -51,7 +51,8 @@ export class StorefrontSDK {
51
51
  storeId: options.storeId,
52
52
  environment: options.environment,
53
53
  baseUrl: options.baseUrl,
54
- token: options.token,
54
+ accessToken: options.accessToken,
55
+ refreshToken: options.refreshToken,
55
56
  apiKey: options.apiKey,
56
57
  timeout: options.timeout,
57
58
  tokenStorage: options.tokenStorage,
@@ -67,28 +68,39 @@ export class StorefrontSDK {
67
68
  this.order = new OrderClient(config);
68
69
  }
69
70
  /**
70
- * Set the authentication token for all clients
71
- */
72
- async setToken(token) {
73
- await this.catalog.setToken(token);
74
- await this.cart.setToken(token);
75
- await this.auth.setToken(token);
76
- await this.customer.setToken(token);
77
- await this.helpers.setToken(token);
78
- await this.shipping.setToken(token);
79
- await this.order.setToken(token);
71
+ * Set authentication tokens for all clients
72
+ *
73
+ * @param accessToken - The access token (required)
74
+ * @param refreshToken - The refresh token (optional)
75
+ *
76
+ * Behavior:
77
+ * - If tokenStorage is provided: Stores tokens for automatic management
78
+ * - If tokenStorage is not provided: Only stores access token for manual management
79
+ */
80
+ async setTokens(accessToken, refreshToken) {
81
+ await this.catalog.setTokens(accessToken, refreshToken);
82
+ await this.cart.setTokens(accessToken, refreshToken);
83
+ await this.auth.setTokens(accessToken, refreshToken);
84
+ await this.customer.setTokens(accessToken, refreshToken);
85
+ await this.helpers.setTokens(accessToken, refreshToken);
86
+ await this.shipping.setTokens(accessToken, refreshToken);
87
+ await this.order.setTokens(accessToken, refreshToken);
80
88
  }
81
89
  /**
82
- * Clear the authentication token from all clients
83
- */
84
- async clearToken() {
85
- await this.catalog.clearToken();
86
- await this.cart.clearToken();
87
- await this.auth.clearToken();
88
- await this.customer.clearToken();
89
- await this.helpers.clearToken();
90
- await this.shipping.clearToken();
91
- await this.order.clearToken();
90
+ * Clear all authentication tokens from all clients
91
+ *
92
+ * Behavior:
93
+ * - If tokenStorage is provided: Clears both access and refresh tokens from storage
94
+ * - If tokenStorage is not provided: Clears the manual access token
95
+ */
96
+ async clearTokens() {
97
+ await this.catalog.clearTokens();
98
+ await this.cart.clearTokens();
99
+ await this.auth.clearTokens();
100
+ await this.customer.clearTokens();
101
+ await this.helpers.clearTokens();
102
+ await this.shipping.clearTokens();
103
+ await this.order.clearTokens();
92
104
  }
93
105
  /**
94
106
  * Set the API key for all clients
@@ -191,7 +203,5 @@ export default StorefrontSDK;
191
203
  export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient };
192
204
  // Export environment enum
193
205
  export { Environment };
194
- // Export token storage types and middleware
195
- export { MemoryTokenStorage, BrowserTokenStorage, createDefaultAuthMiddleware, createAuthMiddleware };
196
- // Export JWT utilities
197
- export { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous, isTokenExpired } from "./lib/jwt-utils";
206
+ // Export token storage types
207
+ export { MemoryTokenStorage, BrowserTokenStorage };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Extract pathname from URL
3
+ */
4
+ export declare function getPathnameFromUrl(url: string): string;
5
+ /**
6
+ * Check if a URL path is an auth endpoint that should use API key
7
+ */
8
+ export declare function isAnonymousAuthEndpoint(pathname: string): boolean;
9
+ /**
10
+ * Check if a URL path is a login/register endpoint that returns tokens
11
+ */
12
+ export declare function isTokenReturningEndpoint(pathname: string): boolean;
13
+ /**
14
+ * Check if a URL path is the logout endpoint
15
+ */
16
+ export declare function isLogoutEndpoint(pathname: string): boolean;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Extract pathname from URL
3
+ */
4
+ export function getPathnameFromUrl(url) {
5
+ try {
6
+ const urlObj = new URL(url);
7
+ return urlObj.pathname;
8
+ }
9
+ catch {
10
+ // If URL parsing fails, assume it's a relative path
11
+ return url.split('?')[0];
12
+ }
13
+ }
14
+ /**
15
+ * Check if a URL path is an auth endpoint that should use API key
16
+ */
17
+ export function isAnonymousAuthEndpoint(pathname) {
18
+ return pathname.endsWith("/auth/anonymous");
19
+ }
20
+ /**
21
+ * Check if a URL path is a login/register endpoint that returns tokens
22
+ */
23
+ export function isTokenReturningEndpoint(pathname) {
24
+ const tokenEndpoints = [
25
+ "/auth/login/password",
26
+ "/auth/register/phone",
27
+ "/auth/register/email",
28
+ "/auth/verify-otp",
29
+ "/auth/refresh-token"
30
+ ];
31
+ return tokenEndpoints.some(endpoint => pathname.endsWith(endpoint));
32
+ }
33
+ /**
34
+ * Check if a URL path is the logout endpoint
35
+ */
36
+ export function isLogoutEndpoint(pathname) {
37
+ return pathname.endsWith("/auth/logout");
38
+ }
@@ -1,10 +1,9 @@
1
- import { StorefrontAPIClient, StorefrontAPIConfig } from "./client";
2
- import { AddProfileImageContent, AddProfileImageFormData, AddProfileImagePathParams, ApiResult, ChangePasswordBody, ChangePasswordContent, CheckVerificationStatusBody, CheckVerificationStatusContent, CreateNotificationPreferencesBody, CreateNotificationPreferencesContent, CreateNotificationPreferencesPathParams, DeactivateUserPathParams, DeactivateUserResponse, ForgotPasswordBody, ForgotPasswordContent, GenerateOtpBody, GenerateOtpContent, GetAnonymousTokenContent, GetNotificationPreferencesContent, GetNotificationPreferencesPathParams, GetProfileImageContent, GetProfileImagePathParams, GetUserDetailContent, GetUserDetailPathParams, LoginWithEmailBody, LoginWithEmailContent, LoginWithPasswordBody, LoginWithPasswordContent, LoginWithPhoneBody, LoginWithPhoneContent, LoginWithWhatsappBody, LoginWithWhatsappContent, LogoutContent, RefreshTokenBody, RefreshTokenContent, RegisterWithEmailBody, RegisterWithEmailContent, RegisterWithPhoneBody, RegisterWithPhoneContent, RemoveProfileImagePathParams, RemoveProfileImageResponse, ResetPasswordBody, ResetPasswordContent, UpdateNotificationPreferencesBody, UpdateNotificationPreferencesContent, UpdateNotificationPreferencesPathParams, UpdateProfileImageContent, UpdateProfileImageFormData, UpdateProfileImagePathParams, UpdateUserBody, UpdateUserContent, UpdateUserPathParams, VerifyOtpBody, VerifyOtpContent } from "../types/storefront-api-types";
1
+ import { StorefrontAPIClient } from "./client";
2
+ import type { AddProfileImageContent, AddProfileImageFormData, AddProfileImagePathParams, ApiResult, ChangePasswordBody, ChangePasswordContent, CheckVerificationStatusBody, CheckVerificationStatusContent, CreateNotificationPreferencesBody, CreateNotificationPreferencesContent, CreateNotificationPreferencesPathParams, DeactivateUserPathParams, DeactivateUserResponse, ForgotPasswordBody, ForgotPasswordContent, GenerateOtpBody, GenerateOtpContent, GetAnonymousTokenContent, GetNotificationPreferencesContent, GetNotificationPreferencesPathParams, GetProfileImageContent, GetProfileImagePathParams, GetUserDetailContent, GetUserDetailPathParams, LoginWithEmailBody, LoginWithEmailContent, LoginWithPasswordBody, LoginWithPasswordContent, LoginWithPhoneBody, LoginWithPhoneContent, LoginWithWhatsappBody, LoginWithWhatsappContent, LogoutContent, RefreshTokenBody, RefreshTokenContent, RegisterWithEmailBody, RegisterWithEmailContent, RegisterWithPhoneBody, RegisterWithPhoneContent, RemoveProfileImagePathParams, RemoveProfileImageResponse, ResetPasswordBody, ResetPasswordContent, UpdateNotificationPreferencesBody, UpdateNotificationPreferencesContent, UpdateNotificationPreferencesPathParams, UpdateProfileImageContent, UpdateProfileImageFormData, UpdateProfileImagePathParams, UpdateUserBody, UpdateUserContent, UpdateUserPathParams, VerifyOtpBody, VerifyOtpContent } from "../types/storefront-api-types";
3
3
  /**
4
4
  * Client for interacting with authentication endpoints
5
5
  */
6
6
  export declare class AuthClient extends StorefrontAPIClient {
7
- constructor(config: StorefrontAPIConfig);
8
7
  /**
9
8
  * Get anonymous token for guest users
10
9
  */
package/dist/lib/auth.js CHANGED
@@ -3,9 +3,6 @@ import { StorefrontAPIClient } from "./client";
3
3
  * Client for interacting with authentication endpoints
4
4
  */
5
5
  export class AuthClient extends StorefrontAPIClient {
6
- constructor(config) {
7
- super(config);
8
- }
9
6
  /**
10
7
  * Get anonymous token for guest users
11
8
  */
@@ -1,6 +1,5 @@
1
1
  import { StorefrontAPIClient } from "./client";
2
- import { AddToWishlistBody, AddToWishlistContent, AddToWishlistPathParams, ApiResult, ApplyCouponBody, ApplyCouponContent, ApplyCouponPathParams, CreateCartAddressBody, CreateCartAddressContent, CreateCartAddressPathParams, CreateCartBody, DeleteCartPathParams, DeleteCartResponse, DeleteFromWishlistBody, DeleteFromWishlistContent, DeleteFromWishlistPathParams, DeleteUserCartPathParams, DeleteUserCartResponse, GetCartContent, GetCartPathParams, GetUserCartContent, GetUserCartPathParams, GetWishlistContent, GetWishlistPathParams, RedeemCreditBalanceBody, RedeemCreditBalanceContent, RedeemCreditBalancePathParams, RedeemGiftCardBody, RedeemGiftCardContent, RedeemGiftCardPathParams, RedeemLoyaltyPointsBody, RedeemLoyaltyPointsContent, RedeemLoyaltyPointsPathParams, RemoveCouponContent, RemoveCouponPathParams, RemoveCreditBalanceContent, RemoveCreditBalancePathParams, RemoveGiftCardContent, RemoveGiftCardPathParams, RemoveLoyaltyPointsContent, RemoveLoyaltyPointsPathParams, UpdateCartBody, UpdateCartContent, UpdateCartPathParams, UpdateShippingMethodBody, UpdateShippingMethodContent, UpdateShippingMethodPathParams } from "../types/storefront-api-types";
3
- import { CreateCartContent } from "../types/storefront-api-types";
2
+ import type { AddToWishlistBody, AddToWishlistContent, AddToWishlistPathParams, ApiResult, ApplyCouponBody, ApplyCouponContent, ApplyCouponPathParams, CreateCartContent, CreateCartAddressBody, CreateCartAddressContent, CreateCartAddressPathParams, CreateCartBody, DeleteCartPathParams, DeleteCartResponse, DeleteFromWishlistBody, DeleteFromWishlistContent, DeleteFromWishlistPathParams, DeleteUserCartPathParams, DeleteUserCartResponse, GetCartContent, GetCartPathParams, GetUserCartContent, GetUserCartPathParams, GetWishlistContent, GetWishlistPathParams, RedeemCreditBalanceBody, RedeemCreditBalanceContent, RedeemCreditBalancePathParams, RedeemGiftCardBody, RedeemGiftCardContent, RedeemGiftCardPathParams, RedeemLoyaltyPointsBody, RedeemLoyaltyPointsContent, RedeemLoyaltyPointsPathParams, RemoveCouponContent, RemoveCouponPathParams, RemoveCreditBalanceContent, RemoveCreditBalancePathParams, RemoveGiftCardContent, RemoveGiftCardPathParams, RemoveLoyaltyPointsContent, RemoveLoyaltyPointsPathParams, UpdateCartBody, UpdateCartContent, UpdateCartPathParams, UpdateShippingMethodBody, UpdateShippingMethodContent, UpdateShippingMethodPathParams } from "../types/storefront-api-types";
4
3
  /**
5
4
  * Client for interacting with cart endpoints
6
5
  */
@@ -1,7 +1,7 @@
1
1
  import createClient from "openapi-fetch";
2
2
  import type { paths } from "../types/storefront";
3
3
  import { ApiErrorResponse, ApiResult } from "../types/storefront-api-types";
4
- import { type TokenStorage } from "./middleware";
4
+ import type { StorefrontSDKOptions } from "../index";
5
5
  /**
6
6
  * Available API environments
7
7
  */
@@ -15,62 +15,19 @@ export declare enum Environment {
15
15
  */
16
16
  Production = "production"
17
17
  }
18
- /**
19
- * Configuration options for the StorefrontAPI client
20
- */
21
- export interface StorefrontAPIConfig {
22
- /**
23
- * The store ID to use for API requests
24
- */
25
- storeId: string;
26
- /**
27
- * The environment to use (staging or production)
28
- */
29
- environment?: Environment;
30
- /**
31
- * Custom base URL (overrides environment-based URL if provided)
32
- */
33
- baseUrl?: string;
34
- /**
35
- * Optional authentication token (for manual token management)
36
- */
37
- token?: string;
38
- /**
39
- * X-Api-Key for anonymous authentication endpoints
40
- * Required for initial authentication
41
- */
42
- apiKey?: string;
43
- /**
44
- * Optional timeout in milliseconds
45
- */
46
- timeout?: number;
47
- /**
48
- * Optional token storage for automatic token management
49
- * If provided, enables automatic token refresh and management via middleware
50
- */
51
- tokenStorage?: TokenStorage;
52
- /**
53
- * Callback when tokens are updated (login/refresh)
54
- */
55
- onTokensUpdated?: (accessToken: string, refreshToken: string) => void;
56
- /**
57
- * Callback when tokens are cleared (logout/error)
58
- */
59
- onTokensCleared?: () => void;
60
- }
61
18
  /**
62
19
  * Base API client for Storefront API
63
20
  */
64
21
  export declare class StorefrontAPIClient {
65
22
  protected client: ReturnType<typeof createClient<paths>>;
66
- protected config: StorefrontAPIConfig;
23
+ protected config: StorefrontSDKOptions;
67
24
  private readonly baseUrl;
68
25
  /**
69
26
  * Create a new StorefrontAPIClient
70
27
  *
71
28
  * @param config - Configuration for the API client
72
29
  */
73
- constructor(config: StorefrontAPIConfig);
30
+ constructor(config: StorefrontSDKOptions);
74
31
  /**
75
32
  * Set up timeout middleware
76
33
  */
@@ -97,16 +54,24 @@ export declare class StorefrontAPIClient {
97
54
  */
98
55
  getAuthorizationHeader(): Promise<string>;
99
56
  /**
100
- * Set the authentication token
101
- * If using token storage, stores the token; otherwise sets manual token
57
+ * Set authentication tokens
58
+ *
59
+ * @param accessToken - The access token (required)
60
+ * @param refreshToken - The refresh token (optional)
102
61
  *
103
- * @param token - The authentication token
62
+ * Behavior:
63
+ * - If tokenStorage is provided: Stores tokens for automatic management
64
+ * - If tokenStorage is not provided: Only stores access token for manual management
104
65
  */
105
- setToken(token: string): Promise<void>;
66
+ setTokens(accessToken: string, refreshToken?: string): Promise<void>;
106
67
  /**
107
- * Clear the authentication token
68
+ * Clear all authentication tokens
69
+ *
70
+ * Behavior:
71
+ * - If tokenStorage is provided: Clears both access and refresh tokens from storage
72
+ * - If tokenStorage is not provided: Clears the manual access token
108
73
  */
109
- clearToken(): Promise<void>;
74
+ clearTokens(): Promise<void>;
110
75
  /**
111
76
  * Set the X-Api-Key header
112
77
  *
@@ -117,13 +82,6 @@ export declare class StorefrontAPIClient {
117
82
  * Clear the X-Api-Key header
118
83
  */
119
84
  clearApiKey(): void;
120
- /**
121
- * Handle API errors
122
- *
123
- * @param error - Error object from OpenAPI-Fetch
124
- * @throws Rethrows the error with additional context
125
- */
126
- protected handleError(error: any): Promise<never>;
127
85
  /**
128
86
  * Execute a request and handle the response
129
87
  *
@@ -1,5 +1,6 @@
1
1
  import createClient from "openapi-fetch";
2
2
  import { createDefaultAuthMiddleware } from "./middleware";
3
+ import { getPathnameFromUrl, isAnonymousAuthEndpoint } from "./auth-utils";
3
4
  /**
4
5
  * Available API environments
5
6
  */
@@ -43,6 +44,45 @@ export class StorefrontAPIClient {
43
44
  onTokensCleared: this.config.onTokensCleared,
44
45
  });
45
46
  this.client.use(authMiddleware);
47
+ // If initial tokens were provided, store them in tokenStorage
48
+ if (this.config.accessToken) {
49
+ this.config.tokenStorage.setAccessToken(this.config.accessToken).catch(error => {
50
+ console.warn('Failed to set initial access token in storage:', error);
51
+ });
52
+ // Clear the manual token since we're using storage
53
+ 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
+ this.config.refreshToken = undefined;
61
+ }
62
+ }
63
+ else {
64
+ // For manual token management, add simple header injection middleware
65
+ this.client.use({
66
+ onRequest: async ({ request }) => {
67
+ const pathname = getPathnameFromUrl(request.url);
68
+ // Handle anonymous auth endpoint - use API key
69
+ if (isAnonymousAuthEndpoint(pathname)) {
70
+ if (this.config.apiKey) {
71
+ request.headers.set("X-Api-Key", this.config.apiKey);
72
+ }
73
+ // Also send existing access token if available for continuity
74
+ if (this.config.accessToken) {
75
+ request.headers.set("Authorization", `Bearer ${this.config.accessToken}`);
76
+ }
77
+ return request;
78
+ }
79
+ // For all other endpoints, use access token
80
+ if (this.config.accessToken) {
81
+ request.headers.set("Authorization", `Bearer ${this.config.accessToken}`);
82
+ }
83
+ return request;
84
+ },
85
+ });
46
86
  }
47
87
  // Set up timeout middleware if configured
48
88
  if (this.config.timeout) {
@@ -113,31 +153,47 @@ export class StorefrontAPIClient {
113
153
  const token = await this.config.tokenStorage.getAccessToken();
114
154
  return token ? `Bearer ${token}` : "";
115
155
  }
116
- return this.config.token ? `Bearer ${this.config.token}` : "";
156
+ return this.config.accessToken ? `Bearer ${this.config.accessToken}` : "";
117
157
  }
118
158
  /**
119
- * Set the authentication token
120
- * If using token storage, stores the token; otherwise sets manual token
159
+ * Set authentication tokens
160
+ *
161
+ * @param accessToken - The access token (required)
162
+ * @param refreshToken - The refresh token (optional)
121
163
  *
122
- * @param token - The authentication token
164
+ * Behavior:
165
+ * - If tokenStorage is provided: Stores tokens for automatic management
166
+ * - If tokenStorage is not provided: Only stores access token for manual management
123
167
  */
124
- async setToken(token) {
168
+ async setTokens(accessToken, refreshToken) {
125
169
  if (this.config.tokenStorage) {
126
- await this.config.tokenStorage.setAccessToken(token);
170
+ // Automatic token management
171
+ await this.config.tokenStorage.setAccessToken(accessToken);
172
+ if (refreshToken) {
173
+ await this.config.tokenStorage.setRefreshToken(refreshToken);
174
+ }
127
175
  }
128
176
  else {
129
- this.config.token = token;
177
+ // Manual token management - only access token
178
+ this.config.accessToken = accessToken;
179
+ if (refreshToken) {
180
+ console.warn("Refresh token provided but ignored in manual token management mode. Use tokenStorage for automatic management.");
181
+ }
130
182
  }
131
183
  }
132
184
  /**
133
- * Clear the authentication token
185
+ * Clear all authentication tokens
186
+ *
187
+ * Behavior:
188
+ * - If tokenStorage is provided: Clears both access and refresh tokens from storage
189
+ * - If tokenStorage is not provided: Clears the manual access token
134
190
  */
135
- async clearToken() {
191
+ async clearTokens() {
136
192
  if (this.config.tokenStorage) {
137
193
  await this.config.tokenStorage.clearTokens();
138
194
  }
139
195
  else {
140
- this.config.token = undefined;
196
+ this.config.accessToken = undefined;
141
197
  }
142
198
  }
143
199
  /**
@@ -154,30 +210,6 @@ export class StorefrontAPIClient {
154
210
  clearApiKey() {
155
211
  this.config.apiKey = undefined;
156
212
  }
157
- /**
158
- * Handle API errors
159
- *
160
- * @param error - Error object from OpenAPI-Fetch
161
- * @throws Rethrows the error with additional context
162
- */
163
- async handleError(error) {
164
- // Extract status code and error data from OpenAPI-Fetch error response
165
- const statusCode = error.status || (error.response?.status ? error.response.status : 500);
166
- const errorData = error.data ||
167
- error.response?.data || { message: error.message || "Unknown error" };
168
- if (statusCode === 401) {
169
- throw new Error("Unauthorized: Please check your authentication token");
170
- }
171
- else if (statusCode === 404) {
172
- throw new Error("Resource not found");
173
- }
174
- else if (errorData?.message) {
175
- throw new Error(`API Error (${statusCode}): ${errorData.message}`);
176
- }
177
- else {
178
- throw new Error(`API Error (${statusCode})`);
179
- }
180
- }
181
213
  /**
182
214
  * Execute a request and handle the response
183
215
  *
@@ -1,13 +1,9 @@
1
- import { CreateAddressBody, CreateAddressContent, CreateAddressPathParams, CreateCustomerContent, DeleteAddressPathParams, DeleteAddressResponse, GetAddressDetailContent, GetAddressDetailPathParams, GetCustomerDetailContent, GetCustomerDetailPathParams, GetLoyaltyDetailsContent, GetLoyaltyDetailsPathParams, ListAddressesContent, ListAddressesPathParams, ListLoyaltyActivitiesContent, ListLoyaltyActivitiesPathParams, ListUserReviewsContent, ListUserReviewsPathParams, UpdateAddressDetailBody, UpdateAddressDetailContent, UpdateAddressDetailPathParams, UpdateCustomerBody, UpdateCustomerContent, UpdateCustomerPathParams } from "../types/storefront-api-types";
2
- import { CreateCustomerBody } from "../types/storefront-api-types";
3
- import { ApiResult } from "../types/storefront-api-types";
1
+ import type { ApiResult, CreateCustomerBody, CreateAddressBody, CreateAddressContent, CreateAddressPathParams, CreateCustomerContent, DeleteAddressPathParams, DeleteAddressResponse, GetAddressDetailContent, GetAddressDetailPathParams, GetCustomerDetailContent, GetCustomerDetailPathParams, GetLoyaltyDetailsContent, GetLoyaltyDetailsPathParams, ListAddressesContent, ListAddressesPathParams, ListLoyaltyActivitiesContent, ListLoyaltyActivitiesPathParams, ListUserReviewsContent, ListUserReviewsPathParams, UpdateAddressDetailBody, UpdateAddressDetailContent, UpdateAddressDetailPathParams, UpdateCustomerBody, UpdateCustomerContent, UpdateCustomerPathParams } from "../types/storefront-api-types";
4
2
  import { StorefrontAPIClient } from "./client";
5
- import { StorefrontAPIConfig } from "./client";
6
3
  /**
7
4
  * Client for interacting with customer endpoints
8
5
  */
9
6
  export declare class CustomerClient extends StorefrontAPIClient {
10
- constructor(config: StorefrontAPIConfig);
11
7
  /**
12
8
  * Create a customer
13
9
  *
@@ -3,9 +3,6 @@ import { StorefrontAPIClient } from "./client";
3
3
  * Client for interacting with customer endpoints
4
4
  */
5
5
  export class CustomerClient extends StorefrontAPIClient {
6
- constructor(config) {
7
- super(config);
8
- }
9
6
  /**
10
7
  * Create a customer
11
8
  *
@@ -1,10 +1,9 @@
1
- import { ApiResult, ListCountriesContent, ListCountryPincodesContent, ListCountryPincodesPathParams, ListCountryStatesContent, ListCountryStatesPathParams } from "../types/storefront-api-types";
2
- import { StorefrontAPIClient, StorefrontAPIConfig } from "./client";
1
+ import type { ApiResult, ListCountriesContent, ListCountryPincodesContent, ListCountryPincodesPathParams, ListCountryStatesContent, ListCountryStatesPathParams } from "../types/storefront-api-types";
2
+ import { StorefrontAPIClient } from "./client";
3
3
  /**
4
4
  * Client for interacting with helper endpoints
5
5
  */
6
6
  export declare class HelpersClient extends StorefrontAPIClient {
7
- constructor(config: StorefrontAPIConfig);
8
7
  /**
9
8
  * Get a list of countries
10
9
  *
@@ -3,9 +3,6 @@ import { StorefrontAPIClient } from "./client";
3
3
  * Client for interacting with helper endpoints
4
4
  */
5
5
  export class HelpersClient extends StorefrontAPIClient {
6
- constructor(config) {
7
- super(config);
8
- }
9
6
  /**
10
7
  * Get a list of countries
11
8
  *
@@ -1,4 +1,5 @@
1
1
  import { isTokenExpired } from "./jwt-utils";
2
+ import { getPathnameFromUrl, isAnonymousAuthEndpoint, isTokenReturningEndpoint, isLogoutEndpoint } from "./auth-utils";
2
3
  /**
3
4
  * Simple in-memory token storage implementation
4
5
  */
@@ -59,44 +60,6 @@ export class BrowserTokenStorage {
59
60
  }
60
61
  }
61
62
  }
62
- /**
63
- * Check if a URL path is an auth endpoint that should use API key
64
- */
65
- function isAnonymousAuthEndpoint(pathname) {
66
- return pathname.endsWith("/auth/anonymous");
67
- }
68
- /**
69
- * Check if a URL path is a login/register endpoint that returns tokens
70
- */
71
- function isTokenReturningEndpoint(pathname) {
72
- const tokenEndpoints = [
73
- "/auth/login/password",
74
- "/auth/register/phone",
75
- "/auth/register/email",
76
- "/auth/verify-otp",
77
- "/auth/refresh-token"
78
- ];
79
- return tokenEndpoints.some(endpoint => pathname.endsWith(endpoint));
80
- }
81
- /**
82
- * Check if a URL path is the logout endpoint
83
- */
84
- function isLogoutEndpoint(pathname) {
85
- return pathname.endsWith("/auth/logout");
86
- }
87
- /**
88
- * Extract pathname from URL
89
- */
90
- function getPathnameFromUrl(url) {
91
- try {
92
- const urlObj = new URL(url);
93
- return urlObj.pathname;
94
- }
95
- catch {
96
- // If URL parsing fails, assume it's a relative path
97
- return url.split('?')[0];
98
- }
99
- }
100
63
  /**
101
64
  * Create authentication middleware for openapi-fetch
102
65
  */
@@ -111,28 +74,56 @@ export function createAuthMiddleware(config) {
111
74
  refreshPromise = (async () => {
112
75
  try {
113
76
  const refreshToken = await config.tokenStorage.getRefreshToken();
114
- if (!refreshToken) {
115
- throw new Error("No refresh token available");
116
- }
117
77
  let newTokens;
118
- if (config.refreshTokenFn) {
119
- // Use provided refresh function
120
- newTokens = await config.refreshTokenFn(refreshToken);
78
+ if (refreshToken && !isTokenExpired(refreshToken)) {
79
+ // Try normal refresh token flow first (only if refresh token is not expired)
80
+ if (config.refreshTokenFn) {
81
+ // Use provided refresh function
82
+ newTokens = await config.refreshTokenFn(refreshToken);
83
+ }
84
+ else {
85
+ // Default refresh implementation
86
+ const response = await fetch(`${config.baseUrl}/auth/refresh-token`, {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ },
91
+ body: JSON.stringify({ refresh_token: refreshToken }),
92
+ });
93
+ if (!response.ok) {
94
+ throw new Error(`Token refresh failed: ${response.status}`);
95
+ }
96
+ const data = await response.json();
97
+ newTokens = data.content;
98
+ }
121
99
  }
122
100
  else {
123
- // Default refresh implementation
124
- const response = await fetch(`${config.baseUrl}/auth/refresh-token`, {
101
+ // No refresh token available OR refresh token is expired - try anonymous token fallback
102
+ // This handles cases where:
103
+ // 1. SDK was initialized with just an access token
104
+ // 2. Refresh token has expired
105
+ const currentAccessToken = await config.tokenStorage.getAccessToken();
106
+ if (!currentAccessToken) {
107
+ throw new Error("No tokens available for refresh");
108
+ }
109
+ const reason = refreshToken
110
+ ? "refresh token expired"
111
+ : "no refresh token available";
112
+ // Get new anonymous tokens while preserving user_id
113
+ const response = await fetch(`${config.baseUrl}/auth/anonymous`, {
125
114
  method: "POST",
126
115
  headers: {
127
116
  "Content-Type": "application/json",
117
+ ...(config.apiKey && { "X-Api-Key": config.apiKey }),
118
+ "Authorization": `Bearer ${currentAccessToken}`, // For user_id continuity
128
119
  },
129
- body: JSON.stringify({ refresh_token: refreshToken }),
130
120
  });
131
121
  if (!response.ok) {
132
- throw new Error(`Token refresh failed: ${response.status}`);
122
+ throw new Error(`Anonymous token fallback failed: ${response.status}`);
133
123
  }
134
124
  const data = await response.json();
135
125
  newTokens = data.content;
126
+ console.info(`Token refreshed via anonymous fallback (${reason}) - user may need to re-authenticate for privileged operations`);
136
127
  }
137
128
  // Store new tokens
138
129
  await config.tokenStorage.setAccessToken(newTokens.access_token);
@@ -1,10 +1,9 @@
1
- import { ApiResult, CancelOrderBody, CancelOrderContent, CancelOrderPathParams, CreateOrderBody, CreateOrderContent, GetOrderDetailContent, GetOrderDetailPathParams, GetPaymentStatusContent, ListOrderPaymentsContent, ListOrderPaymentsPathParams, ListOrderRefundsContent, ListOrderRefundsPathParams, ListOrdersContent, ListOrderShipmentsContent, ListOrderShipmentsPathParams, ListOrdersQuery, RetryOrderPaymentBody, RetryOrderPaymentContent, RetryOrderPaymentPathParams } from "../types/storefront-api-types";
2
- import { StorefrontAPIClient, StorefrontAPIConfig } from "./client";
1
+ import type { ApiResult, CancelOrderBody, CancelOrderContent, CancelOrderPathParams, CreateOrderBody, CreateOrderContent, GetOrderDetailContent, GetOrderDetailPathParams, GetPaymentStatusContent, ListOrderPaymentsContent, ListOrderPaymentsPathParams, ListOrderRefundsContent, ListOrderRefundsPathParams, ListOrdersContent, ListOrderShipmentsContent, ListOrderShipmentsPathParams, ListOrdersQuery, RetryOrderPaymentBody, RetryOrderPaymentContent, RetryOrderPaymentPathParams } from "../types/storefront-api-types";
2
+ import { StorefrontAPIClient } from "./client";
3
3
  /**
4
4
  * Client for interacting with order endpoints
5
5
  */
6
6
  export declare class OrderClient extends StorefrontAPIClient {
7
- constructor(config: StorefrontAPIConfig);
8
7
  /**
9
8
  * Get order details
10
9
  *
package/dist/lib/order.js CHANGED
@@ -3,9 +3,6 @@ import { StorefrontAPIClient } from "./client";
3
3
  * Client for interacting with order endpoints
4
4
  */
5
5
  export class OrderClient extends StorefrontAPIClient {
6
- constructor(config) {
7
- super(config);
8
- }
9
6
  /**
10
7
  * Get order details
11
8
  *
@@ -1,10 +1,9 @@
1
- import { ApiResult, ShippingMethodsBody, ShippingMethodsContent } from "../types/storefront-api-types";
2
- import { StorefrontAPIClient, StorefrontAPIConfig } from "./client";
1
+ import type { ApiResult, CheckDeliveryAvailabilityPathParams, CheckDeliveryAvailabilityResponse, ShippingMethodsBody, ShippingMethodsContent } from "../types/storefront-api-types";
2
+ import { StorefrontAPIClient } from "./client";
3
3
  /**
4
4
  * Client for interacting with shipping endpoints
5
5
  */
6
6
  export declare class ShippingClient extends StorefrontAPIClient {
7
- constructor(config: StorefrontAPIConfig);
8
7
  /**
9
8
  * Get shipping options for an order
10
9
  *
@@ -12,4 +11,11 @@ export declare class ShippingClient extends StorefrontAPIClient {
12
11
  * @returns Promise with shipping options
13
12
  */
14
13
  getShippingMethods(body: ShippingMethodsBody): Promise<ApiResult<ShippingMethodsContent>>;
14
+ /**
15
+ * Check pincode deliverability
16
+ *
17
+ * @param pathParams - Path parameters
18
+ * @returns Promise with pincode deliverability result
19
+ */
20
+ checkPincodeDeliverability(pathParams: CheckDeliveryAvailabilityPathParams): Promise<ApiResult<CheckDeliveryAvailabilityResponse>>;
15
21
  }
@@ -3,9 +3,6 @@ import { StorefrontAPIClient } from "./client";
3
3
  * Client for interacting with shipping endpoints
4
4
  */
5
5
  export class ShippingClient extends StorefrontAPIClient {
6
- constructor(config) {
7
- super(config);
8
- }
9
6
  /**
10
7
  * Get shipping options for an order
11
8
  *
@@ -17,4 +14,17 @@ export class ShippingClient extends StorefrontAPIClient {
17
14
  body: body,
18
15
  }));
19
16
  }
17
+ /**
18
+ * Check pincode deliverability
19
+ *
20
+ * @param pathParams - Path parameters
21
+ * @returns Promise with pincode deliverability result
22
+ */
23
+ async checkPincodeDeliverability(pathParams) {
24
+ return this.executeRequest(() => this.client.GET("/shipment/pincode-serviceability/{pincode}", {
25
+ params: {
26
+ path: pathParams,
27
+ },
28
+ }));
29
+ }
20
30
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercengine/storefront-sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "TypeScript SDK for the Storefront API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",