@commercengine/storefront-sdk 0.13.3 → 0.14.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/MIGRATION.md +170 -0
- package/README.md +129 -53
- package/dist/index.d.mts +1763 -1382
- package/dist/index.iife.js +1598 -1359
- package/dist/index.iife.js.map +1 -1
- package/dist/index.mjs +1590 -1356
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/dist/index.mjs
CHANGED
|
@@ -75,7 +75,6 @@ var ResponseUtils = class {
|
|
|
75
75
|
*/
|
|
76
76
|
var DebugLogger = class {
|
|
77
77
|
logger;
|
|
78
|
-
responseTextCache = /* @__PURE__ */ new Map();
|
|
79
78
|
constructor(logger) {
|
|
80
79
|
this.logger = logger || ((level, message, data) => {
|
|
81
80
|
console.log(`[${level.toUpperCase()}]`, message);
|
|
@@ -98,7 +97,6 @@ var DebugLogger = class {
|
|
|
98
97
|
* Log debug information about API response
|
|
99
98
|
*/
|
|
100
99
|
async logResponse(response, responseBody) {
|
|
101
|
-
if (responseBody && typeof responseBody === "string") this.responseTextCache.set(response.url, responseBody);
|
|
102
100
|
this.logger("info", "API Response Debug Info", {
|
|
103
101
|
url: response.url,
|
|
104
102
|
status: response.status,
|
|
@@ -122,17 +120,17 @@ var DebugLogger = class {
|
|
|
122
120
|
this.logger("error", message, error);
|
|
123
121
|
}
|
|
124
122
|
/**
|
|
125
|
-
*
|
|
123
|
+
* Compatibility shim retained for older internal callers.
|
|
124
|
+
* Response bodies are no longer cached by the debug logger.
|
|
126
125
|
*/
|
|
127
|
-
getCachedResponseText(
|
|
128
|
-
return
|
|
126
|
+
getCachedResponseText(_url) {
|
|
127
|
+
return null;
|
|
129
128
|
}
|
|
130
129
|
/**
|
|
131
|
-
*
|
|
130
|
+
* Compatibility shim retained for older internal callers.
|
|
131
|
+
* Response bodies are no longer cached by the debug logger.
|
|
132
132
|
*/
|
|
133
|
-
clearCache() {
|
|
134
|
-
this.responseTextCache.clear();
|
|
135
|
-
}
|
|
133
|
+
clearCache() {}
|
|
136
134
|
info(message, data) {
|
|
137
135
|
this.logger("info", message, data);
|
|
138
136
|
}
|
|
@@ -218,14 +216,33 @@ function createDebugMiddleware(logger) {
|
|
|
218
216
|
* @returns Middleware object with onRequest handler
|
|
219
217
|
*/
|
|
220
218
|
function createTimeoutMiddleware(timeoutMs) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const timeoutId =
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
}
|
|
219
|
+
const timeouts = /* @__PURE__ */ new WeakMap();
|
|
220
|
+
const clearRequestTimeout = (signal) => {
|
|
221
|
+
const timeoutId = timeouts.get(signal);
|
|
222
|
+
if (timeoutId) {
|
|
223
|
+
clearTimeout(timeoutId);
|
|
224
|
+
timeouts.delete(signal);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
return {
|
|
228
|
+
onRequest: async ({ request }) => {
|
|
229
|
+
const controller = new AbortController();
|
|
230
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
231
|
+
if (request.signal) request.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
232
|
+
const newRequest = new Request(request, { signal: controller.signal });
|
|
233
|
+
timeouts.set(newRequest.signal, timeoutId);
|
|
234
|
+
controller.signal.addEventListener("abort", () => clearRequestTimeout(newRequest.signal), { once: true });
|
|
235
|
+
return newRequest;
|
|
236
|
+
},
|
|
237
|
+
onResponse: async ({ request, response }) => {
|
|
238
|
+
clearRequestTimeout(request.signal);
|
|
239
|
+
return response;
|
|
240
|
+
},
|
|
241
|
+
onError: async ({ request, error }) => {
|
|
242
|
+
clearRequestTimeout(request.signal);
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
229
246
|
}
|
|
230
247
|
/**
|
|
231
248
|
* Transform headers using a transformation mapping
|
|
@@ -291,8 +308,8 @@ async function executeRequest(apiCall) {
|
|
|
291
308
|
};
|
|
292
309
|
} catch (err) {
|
|
293
310
|
const mockResponse = new Response(null, {
|
|
294
|
-
status:
|
|
295
|
-
statusText: "
|
|
311
|
+
status: 503,
|
|
312
|
+
statusText: "Service Unavailable"
|
|
296
313
|
});
|
|
297
314
|
return {
|
|
298
315
|
data: null,
|
|
@@ -412,619 +429,228 @@ function getPathnameFromUrl(url) {
|
|
|
412
429
|
}
|
|
413
430
|
|
|
414
431
|
//#endregion
|
|
415
|
-
//#region src/lib/
|
|
432
|
+
//#region src/lib/shared/url-utils.ts
|
|
416
433
|
/**
|
|
417
|
-
*
|
|
418
|
-
* This is a lightweight replacement for jose's decodeJwt.
|
|
419
|
-
*
|
|
420
|
-
* @param token - The JWT token to decode
|
|
421
|
-
* @returns The decoded payload
|
|
422
|
-
* @throws Error if the token is malformed
|
|
434
|
+
* URL utility functions for the Storefront SDK
|
|
423
435
|
*/
|
|
424
|
-
function decodeJwt(token) {
|
|
425
|
-
if (typeof token !== "string") throw new Error("Invalid token: must be a string");
|
|
426
|
-
const parts = token.split(".");
|
|
427
|
-
if (parts.length !== 3) throw new Error("Invalid token: must have 3 parts");
|
|
428
|
-
const base64Url = parts[1];
|
|
429
|
-
if (!base64Url) throw new Error("Invalid token: missing payload");
|
|
430
|
-
let base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
431
|
-
const padding = base64.length % 4;
|
|
432
|
-
if (padding) base64 += "=".repeat(4 - padding);
|
|
433
|
-
const binaryStr = atob(base64);
|
|
434
|
-
const bytes = new Uint8Array(binaryStr.length);
|
|
435
|
-
for (let i = 0; i < binaryStr.length; i++) bytes[i] = binaryStr.charCodeAt(i);
|
|
436
|
-
const payload = JSON.parse(new TextDecoder().decode(bytes));
|
|
437
|
-
if (typeof payload !== "object" || payload === null) throw new Error("Invalid token: payload must be an object");
|
|
438
|
-
return payload;
|
|
439
|
-
}
|
|
440
436
|
/**
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
* @param token - The JWT token to decode
|
|
444
|
-
* @returns User information or null if token is invalid
|
|
437
|
+
* Available API environments for Commerce Engine
|
|
445
438
|
*/
|
|
446
|
-
function
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
isLoggedIn: payload.is_logged_in,
|
|
458
|
-
isAnonymous: payload.is_anonymous,
|
|
459
|
-
customerId: payload.customer_id,
|
|
460
|
-
customerGroupId: payload.customer_group_id,
|
|
461
|
-
anonymousId: payload.anonymous_id,
|
|
462
|
-
channel: payload.channel,
|
|
463
|
-
tokenExpiry: /* @__PURE__ */ new Date(payload.exp * 1e3),
|
|
464
|
-
tokenIssuedAt: /* @__PURE__ */ new Date(payload.iat * 1e3)
|
|
465
|
-
};
|
|
466
|
-
} catch (error) {
|
|
467
|
-
console.warn("Failed to decode JWT token:", error);
|
|
468
|
-
return null;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
439
|
+
let Environment = /* @__PURE__ */ function(Environment) {
|
|
440
|
+
/**
|
|
441
|
+
* Staging environment
|
|
442
|
+
*/
|
|
443
|
+
Environment["Staging"] = "staging";
|
|
444
|
+
/**
|
|
445
|
+
* Production environment
|
|
446
|
+
*/
|
|
447
|
+
Environment["Production"] = "production";
|
|
448
|
+
return Environment;
|
|
449
|
+
}({});
|
|
471
450
|
/**
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
* @param token - The JWT token to check
|
|
475
|
-
* @param bufferSeconds - Buffer time in seconds (default: 30)
|
|
476
|
-
* @returns True if token is expired or will expire within buffer time
|
|
451
|
+
* Build base URL for Storefront API
|
|
477
452
|
*/
|
|
478
|
-
function
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
console.warn("Failed to decode JWT token:", error);
|
|
485
|
-
return true;
|
|
453
|
+
function buildStorefrontURL(config) {
|
|
454
|
+
if (config.baseUrl) return config.baseUrl;
|
|
455
|
+
switch (config.environment || Environment.Production) {
|
|
456
|
+
case Environment.Staging: return `https://staging.api.commercengine.io/api/v1/${config.storeId}/storefront`;
|
|
457
|
+
case Environment.Production:
|
|
458
|
+
default: return `https://prod.api.commercengine.io/api/v1/${config.storeId}/storefront`;
|
|
486
459
|
}
|
|
487
460
|
}
|
|
488
|
-
/**
|
|
489
|
-
* Get the user ID from a JWT token
|
|
490
|
-
*
|
|
491
|
-
* @param token - The JWT token
|
|
492
|
-
* @returns User ID (ulid) or null if token is invalid
|
|
493
|
-
*/
|
|
494
|
-
function getUserIdFromToken(token) {
|
|
495
|
-
return extractUserInfoFromToken(token)?.id || null;
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* Check if user is logged in based on JWT token
|
|
499
|
-
*
|
|
500
|
-
* @param token - The JWT token
|
|
501
|
-
* @returns True if user is logged in, false otherwise
|
|
502
|
-
*/
|
|
503
|
-
function isUserLoggedIn(token) {
|
|
504
|
-
return extractUserInfoFromToken(token)?.isLoggedIn || false;
|
|
505
|
-
}
|
|
506
|
-
/**
|
|
507
|
-
* Check if user is anonymous based on JWT token
|
|
508
|
-
*
|
|
509
|
-
* @param token - The JWT token
|
|
510
|
-
* @returns True if user is anonymous, false otherwise
|
|
511
|
-
*/
|
|
512
|
-
function isUserAnonymous(token) {
|
|
513
|
-
return extractUserInfoFromToken(token)?.isAnonymous ?? true;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
//#endregion
|
|
517
|
-
//#region src/types/api-key-endpoints.ts
|
|
518
|
-
const API_KEY_ENDPOINTS = [
|
|
519
|
-
"/auth/anonymous",
|
|
520
|
-
"/store/check",
|
|
521
|
-
"/store/config"
|
|
522
|
-
];
|
|
523
461
|
|
|
524
462
|
//#endregion
|
|
525
|
-
//#region src/lib/
|
|
526
|
-
/**
|
|
527
|
-
* Check if a URL path is an auth endpoint that should use API key
|
|
528
|
-
*/
|
|
529
|
-
function isAnonymousAuthEndpoint(pathname) {
|
|
530
|
-
return pathname.endsWith("/auth/anonymous");
|
|
531
|
-
}
|
|
463
|
+
//#region src/lib/shared/client.ts
|
|
532
464
|
/**
|
|
533
|
-
*
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
/**
|
|
539
|
-
* Check if a URL path is a login/register endpoint that returns tokens
|
|
465
|
+
* Shared base class for Storefront API clients.
|
|
466
|
+
*
|
|
467
|
+
* This centralizes Storefront-specific URL construction, default header
|
|
468
|
+
* transformations, and shared API key state while leaving auth middleware
|
|
469
|
+
* decisions to the public and session-specific subclasses.
|
|
540
470
|
*/
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
471
|
+
var StorefrontAPIClientBase = class extends BaseAPIClient {
|
|
472
|
+
apiKey;
|
|
473
|
+
constructor(config) {
|
|
474
|
+
const baseUrl = buildStorefrontURL({
|
|
475
|
+
storeId: config.storeId,
|
|
476
|
+
environment: config.environment,
|
|
477
|
+
baseUrl: config.baseUrl
|
|
478
|
+
});
|
|
479
|
+
super({
|
|
480
|
+
baseUrl,
|
|
481
|
+
timeout: config.timeout,
|
|
482
|
+
defaultHeaders: config.defaultHeaders,
|
|
483
|
+
debug: config.debug,
|
|
484
|
+
logger: config.logger
|
|
485
|
+
}, baseUrl, {
|
|
486
|
+
customer_group_id: "x-customer-group-id",
|
|
487
|
+
debug_mode: "x-debug-mode"
|
|
488
|
+
});
|
|
489
|
+
this.apiKey = config.apiKey;
|
|
490
|
+
}
|
|
491
|
+
setApiKey(apiKey) {
|
|
492
|
+
this.apiKey = apiKey;
|
|
493
|
+
}
|
|
494
|
+
clearApiKey() {
|
|
495
|
+
this.apiKey = void 0;
|
|
496
|
+
}
|
|
497
|
+
useMiddleware(middleware) {
|
|
498
|
+
this.client.use(middleware);
|
|
499
|
+
}
|
|
500
|
+
};
|
|
551
501
|
|
|
552
502
|
//#endregion
|
|
553
|
-
//#region src/lib/
|
|
503
|
+
//#region src/lib/session/client.ts
|
|
504
|
+
function attachSessionAuth(client, sessionManager) {
|
|
505
|
+
client.useMiddleware(sessionManager.createAuthMiddleware());
|
|
506
|
+
}
|
|
554
507
|
/**
|
|
555
|
-
*
|
|
508
|
+
* Storefront API client that extends the generic BaseAPIClient
|
|
509
|
+
* Adds Commerce Engine specific authentication and token management
|
|
556
510
|
*/
|
|
557
|
-
var
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
511
|
+
var SessionStorefrontAPIClient = class extends StorefrontAPIClientBase {
|
|
512
|
+
config;
|
|
513
|
+
/**
|
|
514
|
+
* Create a new SessionStorefrontAPIClient
|
|
515
|
+
*
|
|
516
|
+
* @param config - Configuration for the API client
|
|
517
|
+
*/
|
|
518
|
+
constructor(config) {
|
|
519
|
+
super(config);
|
|
520
|
+
this.config = { ...config };
|
|
521
|
+
this.setupStorefrontAuth();
|
|
562
522
|
}
|
|
563
|
-
|
|
564
|
-
|
|
523
|
+
/**
|
|
524
|
+
* Set up Storefront-specific authentication middleware
|
|
525
|
+
*/
|
|
526
|
+
setupStorefrontAuth() {
|
|
527
|
+
attachSessionAuth(this, this.config.sessionManager);
|
|
565
528
|
}
|
|
566
|
-
|
|
567
|
-
|
|
529
|
+
/**
|
|
530
|
+
* Get the authorization header value
|
|
531
|
+
* without creating a new session.
|
|
532
|
+
*
|
|
533
|
+
* @returns The Authorization header value or empty string if no token is set
|
|
534
|
+
*/
|
|
535
|
+
async getAuthorizationHeader() {
|
|
536
|
+
return this.config.sessionManager.getAuthorizationHeader();
|
|
568
537
|
}
|
|
569
|
-
|
|
570
|
-
|
|
538
|
+
/**
|
|
539
|
+
* Set authentication tokens
|
|
540
|
+
*
|
|
541
|
+
* @param accessToken - The access token (required)
|
|
542
|
+
* @param refreshToken - The refresh token (optional)
|
|
543
|
+
*
|
|
544
|
+
* Behavior:
|
|
545
|
+
* - If tokenStorage is provided: Stores tokens for automatic management
|
|
546
|
+
* - If tokenStorage is not provided: Only stores access token for manual management
|
|
547
|
+
*/
|
|
548
|
+
async setTokens(accessToken, refreshToken) {
|
|
549
|
+
await this.config.sessionManager.setTokens(accessToken, refreshToken);
|
|
571
550
|
}
|
|
551
|
+
/**
|
|
552
|
+
* Clear all authentication tokens
|
|
553
|
+
*
|
|
554
|
+
* Behavior:
|
|
555
|
+
* - If tokenStorage is provided: Clears both access and refresh tokens from storage
|
|
556
|
+
* - If tokenStorage is not provided: Clears the manual access token
|
|
557
|
+
*/
|
|
572
558
|
async clearTokens() {
|
|
573
|
-
this.
|
|
574
|
-
this.refreshToken = null;
|
|
559
|
+
await this.config.sessionManager.clearTokens();
|
|
575
560
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
*
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
this.
|
|
585
|
-
this.refreshTokenKey = `${prefix}refresh_token`;
|
|
561
|
+
/**
|
|
562
|
+
* Set the X-Api-Key header
|
|
563
|
+
*
|
|
564
|
+
* @param apiKey - The API key to set
|
|
565
|
+
*/
|
|
566
|
+
setApiKey(apiKey) {
|
|
567
|
+
super.setApiKey(apiKey);
|
|
568
|
+
this.config.apiKey = apiKey;
|
|
569
|
+
this.config.sessionManager.setApiKey(apiKey);
|
|
586
570
|
}
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
571
|
+
/**
|
|
572
|
+
* Clear the X-Api-Key header
|
|
573
|
+
*/
|
|
574
|
+
clearApiKey() {
|
|
575
|
+
super.clearApiKey();
|
|
576
|
+
this.config.apiKey = void 0;
|
|
577
|
+
this.config.sessionManager.clearApiKey();
|
|
590
578
|
}
|
|
591
|
-
|
|
592
|
-
|
|
579
|
+
/**
|
|
580
|
+
* Resolve the current user ID from explicit parameters or the active session.
|
|
581
|
+
*
|
|
582
|
+
* @param explicitUserId - Optional user ID supplied by the caller
|
|
583
|
+
* @returns The resolved user ID
|
|
584
|
+
* @throws When no user ID is available
|
|
585
|
+
*/
|
|
586
|
+
async resolveCurrentUserId(explicitUserId) {
|
|
587
|
+
if (explicitUserId) return explicitUserId;
|
|
588
|
+
return this.config.sessionManager.ensureUserId();
|
|
593
589
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
590
|
+
/**
|
|
591
|
+
* Resolve path parameters that require `user_id`.
|
|
592
|
+
*
|
|
593
|
+
* @param pathParams - Path parameters with an optional `user_id`
|
|
594
|
+
* @returns Path parameters with a guaranteed `user_id`
|
|
595
|
+
*/
|
|
596
|
+
async resolveUserPathParams(pathParams) {
|
|
597
|
+
return {
|
|
598
|
+
...pathParams,
|
|
599
|
+
user_id: await this.resolveCurrentUserId(pathParams.user_id)
|
|
600
|
+
};
|
|
597
601
|
}
|
|
598
|
-
|
|
599
|
-
|
|
602
|
+
/**
|
|
603
|
+
* Resolve query parameters that require `user_id`.
|
|
604
|
+
*
|
|
605
|
+
* @param queryParams - Query parameters with an optional `user_id`
|
|
606
|
+
* @returns Query parameters with a guaranteed `user_id`
|
|
607
|
+
*/
|
|
608
|
+
async resolveUserQueryParams(queryParams) {
|
|
609
|
+
return {
|
|
610
|
+
...queryParams,
|
|
611
|
+
user_id: await this.resolveCurrentUserId(queryParams.user_id)
|
|
612
|
+
};
|
|
600
613
|
}
|
|
601
|
-
async clearTokens() {
|
|
602
|
-
if (typeof localStorage !== "undefined") {
|
|
603
|
-
localStorage.removeItem(this.accessTokenKey);
|
|
604
|
-
localStorage.removeItem(this.refreshTokenKey);
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
/**
|
|
609
|
-
* Cookie-based token storage implementation
|
|
610
|
-
*/
|
|
611
|
-
var CookieTokenStorage = class {
|
|
612
|
-
accessTokenKey;
|
|
613
|
-
refreshTokenKey;
|
|
614
|
-
options;
|
|
615
|
-
constructor(options = {}) {
|
|
616
|
-
const prefix = options.prefix || "storefront_";
|
|
617
|
-
this.accessTokenKey = `${prefix}access_token`;
|
|
618
|
-
this.refreshTokenKey = `${prefix}refresh_token`;
|
|
619
|
-
this.options = {
|
|
620
|
-
maxAge: options.maxAge || 10080 * 60,
|
|
621
|
-
path: options.path || "/",
|
|
622
|
-
domain: options.domain,
|
|
623
|
-
secure: options.secure ?? (typeof window !== "undefined" && window.location?.protocol === "https:"),
|
|
624
|
-
sameSite: options.sameSite || "Lax",
|
|
625
|
-
httpOnly: false
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
async getAccessToken() {
|
|
629
|
-
return this.getCookie(this.accessTokenKey);
|
|
630
|
-
}
|
|
631
|
-
async setAccessToken(token) {
|
|
632
|
-
this.setCookie(this.accessTokenKey, token);
|
|
633
|
-
}
|
|
634
|
-
async getRefreshToken() {
|
|
635
|
-
return this.getCookie(this.refreshTokenKey);
|
|
636
|
-
}
|
|
637
|
-
async setRefreshToken(token) {
|
|
638
|
-
this.setCookie(this.refreshTokenKey, token);
|
|
639
|
-
}
|
|
640
|
-
async clearTokens() {
|
|
641
|
-
this.deleteCookie(this.accessTokenKey);
|
|
642
|
-
this.deleteCookie(this.refreshTokenKey);
|
|
643
|
-
}
|
|
644
|
-
getCookie(name) {
|
|
645
|
-
if (typeof document === "undefined") return null;
|
|
646
|
-
const parts = `; ${document.cookie}`.split(`; ${name}=`);
|
|
647
|
-
if (parts.length === 2) {
|
|
648
|
-
const cookieValue = parts.pop()?.split(";").shift();
|
|
649
|
-
return cookieValue ? decodeURIComponent(cookieValue) : null;
|
|
650
|
-
}
|
|
651
|
-
return null;
|
|
652
|
-
}
|
|
653
|
-
setCookie(name, value) {
|
|
654
|
-
if (typeof document === "undefined") return;
|
|
655
|
-
let cookieString = `${name}=${encodeURIComponent(value)}`;
|
|
656
|
-
if (this.options.maxAge) cookieString += `; Max-Age=${this.options.maxAge}`;
|
|
657
|
-
if (this.options.path) cookieString += `; Path=${this.options.path}`;
|
|
658
|
-
if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
|
|
659
|
-
if (this.options.secure) cookieString += `; Secure`;
|
|
660
|
-
if (this.options.sameSite) cookieString += `; SameSite=${this.options.sameSite}`;
|
|
661
|
-
document.cookie = cookieString;
|
|
662
|
-
}
|
|
663
|
-
deleteCookie(name) {
|
|
664
|
-
if (typeof document === "undefined") return;
|
|
665
|
-
let cookieString = `${name}=; Max-Age=0`;
|
|
666
|
-
if (this.options.path) cookieString += `; Path=${this.options.path}`;
|
|
667
|
-
if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
|
|
668
|
-
document.cookie = cookieString;
|
|
669
|
-
}
|
|
670
|
-
};
|
|
671
|
-
/**
|
|
672
|
-
* Create authentication middleware for openapi-fetch
|
|
673
|
-
*/
|
|
674
|
-
function createAuthMiddleware(config) {
|
|
675
|
-
let isRefreshing = false;
|
|
676
|
-
let refreshPromise = null;
|
|
677
|
-
let hasAssessedTokens = false;
|
|
678
|
-
const assessTokenStateOnce = async () => {
|
|
679
|
-
if (hasAssessedTokens) return;
|
|
680
|
-
hasAssessedTokens = true;
|
|
681
|
-
try {
|
|
682
|
-
const accessToken = await config.tokenStorage.getAccessToken();
|
|
683
|
-
const refreshToken = await config.tokenStorage.getRefreshToken();
|
|
684
|
-
if (!accessToken && refreshToken) {
|
|
685
|
-
await config.tokenStorage.clearTokens();
|
|
686
|
-
console.info("Cleaned up orphaned refresh token");
|
|
687
|
-
}
|
|
688
|
-
} catch (error) {
|
|
689
|
-
console.warn("Token state assessment failed:", error);
|
|
690
|
-
}
|
|
691
|
-
};
|
|
692
|
-
const refreshTokens = async () => {
|
|
693
|
-
if (isRefreshing && refreshPromise) return refreshPromise;
|
|
694
|
-
isRefreshing = true;
|
|
695
|
-
refreshPromise = (async () => {
|
|
696
|
-
try {
|
|
697
|
-
const refreshToken = await config.tokenStorage.getRefreshToken();
|
|
698
|
-
let newTokens;
|
|
699
|
-
if (refreshToken && !isTokenExpired(refreshToken)) if (config.refreshTokenFn) newTokens = await config.refreshTokenFn(refreshToken);
|
|
700
|
-
else {
|
|
701
|
-
const response = await fetch(`${config.baseUrl}/auth/refresh-token`, {
|
|
702
|
-
method: "POST",
|
|
703
|
-
headers: { "Content-Type": "application/json" },
|
|
704
|
-
body: JSON.stringify({ refresh_token: refreshToken })
|
|
705
|
-
});
|
|
706
|
-
if (!response.ok) throw new Error(`Token refresh failed: ${response.status}`);
|
|
707
|
-
newTokens = (await response.json()).content;
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
const currentAccessToken = await config.tokenStorage.getAccessToken();
|
|
711
|
-
if (!currentAccessToken) throw new Error("No tokens available for refresh");
|
|
712
|
-
const reason = refreshToken ? "refresh token expired" : "no refresh token available";
|
|
713
|
-
const response = await fetch(`${config.baseUrl}/auth/anonymous`, {
|
|
714
|
-
method: "POST",
|
|
715
|
-
headers: {
|
|
716
|
-
"Content-Type": "application/json",
|
|
717
|
-
...config.apiKey && { "X-Api-Key": config.apiKey },
|
|
718
|
-
Authorization: `Bearer ${currentAccessToken}`
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
|
-
if (!response.ok) throw new Error(`Anonymous token fallback failed: ${response.status}`);
|
|
722
|
-
newTokens = (await response.json()).content;
|
|
723
|
-
console.info(`Token refreshed via anonymous fallback (${reason}) - user may need to re-authenticate for privileged operations`);
|
|
724
|
-
}
|
|
725
|
-
await config.tokenStorage.setAccessToken(newTokens.access_token);
|
|
726
|
-
await config.tokenStorage.setRefreshToken(newTokens.refresh_token);
|
|
727
|
-
config.onTokensUpdated?.(newTokens.access_token, newTokens.refresh_token);
|
|
728
|
-
} catch (error) {
|
|
729
|
-
console.error("Token refresh failed:", error);
|
|
730
|
-
await config.tokenStorage.clearTokens();
|
|
731
|
-
config.onTokensCleared?.();
|
|
732
|
-
throw error;
|
|
733
|
-
} finally {
|
|
734
|
-
isRefreshing = false;
|
|
735
|
-
refreshPromise = null;
|
|
736
|
-
}
|
|
737
|
-
})();
|
|
738
|
-
return refreshPromise;
|
|
739
|
-
};
|
|
740
|
-
return {
|
|
741
|
-
async onRequest({ request }) {
|
|
742
|
-
const pathname = getPathnameFromUrl(request.url);
|
|
743
|
-
await assessTokenStateOnce();
|
|
744
|
-
if (isAnonymousAuthEndpoint(pathname)) {
|
|
745
|
-
if (config.apiKey) request.headers.set("X-Api-Key", config.apiKey);
|
|
746
|
-
const existingToken = await config.tokenStorage.getAccessToken();
|
|
747
|
-
if (existingToken && !isTokenExpired(existingToken) && isUserLoggedIn(existingToken)) return new Response(JSON.stringify({
|
|
748
|
-
message: "Cannot create anonymous session while authenticated",
|
|
749
|
-
success: false,
|
|
750
|
-
code: "USER_ALREADY_AUTHENTICATED"
|
|
751
|
-
}), {
|
|
752
|
-
status: 400,
|
|
753
|
-
headers: { "Content-Type": "application/json" }
|
|
754
|
-
});
|
|
755
|
-
if (existingToken) request.headers.set("Authorization", `Bearer ${existingToken}`);
|
|
756
|
-
return request;
|
|
757
|
-
}
|
|
758
|
-
if (isApiKeyRequiredEndpoint(pathname)) {
|
|
759
|
-
if (config.apiKey) request.headers.set("X-Api-Key", config.apiKey);
|
|
760
|
-
return request;
|
|
761
|
-
}
|
|
762
|
-
let accessToken = await config.tokenStorage.getAccessToken();
|
|
763
|
-
if (!accessToken) try {
|
|
764
|
-
const response = await fetch(`${config.baseUrl}/auth/anonymous`, {
|
|
765
|
-
method: "POST",
|
|
766
|
-
headers: {
|
|
767
|
-
"Content-Type": "application/json",
|
|
768
|
-
...config.apiKey && { "X-Api-Key": config.apiKey }
|
|
769
|
-
}
|
|
770
|
-
});
|
|
771
|
-
if (response.ok) {
|
|
772
|
-
const tokens = (await response.json()).content;
|
|
773
|
-
if (tokens?.access_token && tokens?.refresh_token) {
|
|
774
|
-
await config.tokenStorage.setAccessToken(tokens.access_token);
|
|
775
|
-
await config.tokenStorage.setRefreshToken(tokens.refresh_token);
|
|
776
|
-
accessToken = tokens.access_token;
|
|
777
|
-
config.onTokensUpdated?.(tokens.access_token, tokens.refresh_token);
|
|
778
|
-
console.info("Automatically created anonymous session for first API request");
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
} catch (error) {
|
|
782
|
-
console.warn("Failed to automatically create anonymous tokens:", error);
|
|
783
|
-
}
|
|
784
|
-
if (accessToken && isTokenExpired(accessToken)) try {
|
|
785
|
-
await refreshTokens();
|
|
786
|
-
accessToken = await config.tokenStorage.getAccessToken();
|
|
787
|
-
} catch (error) {}
|
|
788
|
-
if (accessToken) request.headers.set("Authorization", `Bearer ${accessToken}`);
|
|
789
|
-
return request;
|
|
790
|
-
},
|
|
791
|
-
async onResponse({ request, response }) {
|
|
792
|
-
const pathname = getPathnameFromUrl(request.url);
|
|
793
|
-
if (response.ok) {
|
|
794
|
-
if (isTokenReturningEndpoint(pathname) || isAnonymousAuthEndpoint(pathname)) try {
|
|
795
|
-
const content = (await response.clone().json()).content;
|
|
796
|
-
if (content?.access_token && content?.refresh_token) {
|
|
797
|
-
await config.tokenStorage.setAccessToken(content.access_token);
|
|
798
|
-
await config.tokenStorage.setRefreshToken(content.refresh_token);
|
|
799
|
-
config.onTokensUpdated?.(content.access_token, content.refresh_token);
|
|
800
|
-
}
|
|
801
|
-
} catch (error) {
|
|
802
|
-
console.warn("Failed to extract tokens from response:", error);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
if (response.status === 401 && !isAnonymousAuthEndpoint(pathname)) {
|
|
806
|
-
const currentToken = await config.tokenStorage.getAccessToken();
|
|
807
|
-
if (currentToken && isTokenExpired(currentToken, 0)) try {
|
|
808
|
-
await refreshTokens();
|
|
809
|
-
const newToken = await config.tokenStorage.getAccessToken();
|
|
810
|
-
if (newToken) {
|
|
811
|
-
const retryRequest = request.clone();
|
|
812
|
-
retryRequest.headers.set("Authorization", `Bearer ${newToken}`);
|
|
813
|
-
return fetch(retryRequest);
|
|
814
|
-
}
|
|
815
|
-
} catch (error) {
|
|
816
|
-
console.warn("Token refresh failed on 401 response:", error);
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
return response;
|
|
820
|
-
}
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
/**
|
|
824
|
-
* Helper function to create auth middleware with sensible defaults
|
|
825
|
-
*/
|
|
826
|
-
function createDefaultAuthMiddleware(options) {
|
|
827
|
-
return createAuthMiddleware({
|
|
828
|
-
tokenStorage: options.tokenStorage || (typeof localStorage !== "undefined" ? new BrowserTokenStorage() : new MemoryTokenStorage()),
|
|
829
|
-
apiKey: options.apiKey,
|
|
830
|
-
baseUrl: options.baseUrl,
|
|
831
|
-
onTokensUpdated: options.onTokensUpdated,
|
|
832
|
-
onTokensCleared: options.onTokensCleared
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
//#endregion
|
|
837
|
-
//#region src/lib/url-utils.ts
|
|
838
|
-
/**
|
|
839
|
-
* URL utility functions for the Storefront SDK
|
|
840
|
-
*/
|
|
841
|
-
/**
|
|
842
|
-
* Available API environments for Commerce Engine
|
|
843
|
-
*/
|
|
844
|
-
let Environment = /* @__PURE__ */ function(Environment) {
|
|
845
614
|
/**
|
|
846
|
-
*
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
*
|
|
615
|
+
* Resolve path parameters that require `customer_id`.
|
|
616
|
+
*
|
|
617
|
+
* @param pathParams - Path parameters with an optional `customer_id`
|
|
618
|
+
* @returns Path parameters with a guaranteed `customer_id`
|
|
619
|
+
* @throws When the user is anonymous or no session can be established
|
|
851
620
|
*/
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
*/
|
|
858
|
-
function buildStorefrontURL(config) {
|
|
859
|
-
if (config.baseUrl) return config.baseUrl;
|
|
860
|
-
switch (config.environment || Environment.Production) {
|
|
861
|
-
case Environment.Staging: return `https://staging.api.commercengine.io/api/v1/${config.storeId}/storefront`;
|
|
862
|
-
case Environment.Production:
|
|
863
|
-
default: return `https://prod.api.commercengine.io/api/v1/${config.storeId}/storefront`;
|
|
621
|
+
async resolveCustomerPathParams(pathParams) {
|
|
622
|
+
return {
|
|
623
|
+
...pathParams,
|
|
624
|
+
customer_id: pathParams.customer_id ?? await this.config.sessionManager.ensureCustomerId()
|
|
625
|
+
};
|
|
864
626
|
}
|
|
865
|
-
}
|
|
627
|
+
};
|
|
866
628
|
|
|
867
629
|
//#endregion
|
|
868
|
-
//#region src/lib/
|
|
630
|
+
//#region src/lib/shared/catalog.ts
|
|
869
631
|
/**
|
|
870
|
-
*
|
|
871
|
-
* Adds Commerce Engine specific authentication and token management
|
|
632
|
+
* Client for interacting with catalog endpoints
|
|
872
633
|
*/
|
|
873
|
-
var
|
|
874
|
-
config;
|
|
875
|
-
initializationPromise = null;
|
|
876
|
-
/**
|
|
877
|
-
* Create a new StorefrontAPIClient
|
|
878
|
-
*
|
|
879
|
-
* @param config - Configuration for the API client
|
|
880
|
-
*/
|
|
881
|
-
constructor(config) {
|
|
882
|
-
const baseUrl = buildStorefrontURL({
|
|
883
|
-
storeId: config.storeId,
|
|
884
|
-
environment: config.environment,
|
|
885
|
-
baseUrl: config.baseUrl
|
|
886
|
-
});
|
|
887
|
-
super({
|
|
888
|
-
baseUrl,
|
|
889
|
-
timeout: config.timeout,
|
|
890
|
-
defaultHeaders: config.defaultHeaders,
|
|
891
|
-
debug: config.debug,
|
|
892
|
-
logger: config.logger
|
|
893
|
-
}, baseUrl, {
|
|
894
|
-
customer_group_id: "x-customer-group-id",
|
|
895
|
-
debug_mode: "x-debug-mode"
|
|
896
|
-
});
|
|
897
|
-
this.config = { ...config };
|
|
898
|
-
this.setupStorefrontAuth();
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* Set up Storefront-specific authentication middleware
|
|
902
|
-
*/
|
|
903
|
-
setupStorefrontAuth() {
|
|
904
|
-
const config = this.config;
|
|
905
|
-
if (config.tokenStorage) {
|
|
906
|
-
const authMiddleware = createDefaultAuthMiddleware({
|
|
907
|
-
apiKey: config.apiKey,
|
|
908
|
-
baseUrl: this.getBaseUrl(),
|
|
909
|
-
tokenStorage: config.tokenStorage,
|
|
910
|
-
onTokensUpdated: config.onTokensUpdated,
|
|
911
|
-
onTokensCleared: config.onTokensCleared
|
|
912
|
-
});
|
|
913
|
-
this.client.use(authMiddleware);
|
|
914
|
-
if (config.accessToken) {
|
|
915
|
-
this.initializationPromise = this.initializeTokens(config.accessToken, config.refreshToken);
|
|
916
|
-
config.accessToken = void 0;
|
|
917
|
-
config.refreshToken = void 0;
|
|
918
|
-
}
|
|
919
|
-
} else this.client.use({ onRequest: async ({ request }) => {
|
|
920
|
-
if (isAnonymousAuthEndpoint(getPathnameFromUrl(request.url))) {
|
|
921
|
-
if (config.apiKey) request.headers.set("X-Api-Key", config.apiKey);
|
|
922
|
-
if (config.accessToken) request.headers.set("Authorization", `Bearer ${config.accessToken}`);
|
|
923
|
-
return request;
|
|
924
|
-
}
|
|
925
|
-
if (config.accessToken) request.headers.set("Authorization", `Bearer ${config.accessToken}`);
|
|
926
|
-
return request;
|
|
927
|
-
} });
|
|
928
|
-
}
|
|
634
|
+
var BaseCatalogClient = class extends StorefrontAPIClientBase {
|
|
929
635
|
/**
|
|
930
|
-
*
|
|
931
|
-
* If using token storage, gets the current token from storage
|
|
932
|
-
* Otherwise returns the manual token
|
|
636
|
+
* List all products
|
|
933
637
|
*
|
|
934
|
-
* @
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
if (this.config.tokenStorage && this.initializationPromise) await this.initializationPromise;
|
|
938
|
-
if (this.config.tokenStorage) {
|
|
939
|
-
const token = await this.config.tokenStorage.getAccessToken();
|
|
940
|
-
return token ? `Bearer ${token}` : "";
|
|
941
|
-
}
|
|
942
|
-
return this.config.accessToken ? `Bearer ${this.config.accessToken}` : "";
|
|
943
|
-
}
|
|
944
|
-
/**
|
|
945
|
-
* Set authentication tokens
|
|
638
|
+
* @param options - Optional query parameters
|
|
639
|
+
* @param headers - Optional header parameters (customer_group_id, etc.)
|
|
640
|
+
* @returns Promise with products and pagination info
|
|
946
641
|
*
|
|
947
|
-
* @
|
|
948
|
-
*
|
|
642
|
+
* @example
|
|
643
|
+
* ```typescript
|
|
644
|
+
* // Basic product listing
|
|
645
|
+
* const { data, error } = await sdk.catalog.listProducts();
|
|
949
646
|
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
|
|
954
|
-
async setTokens(accessToken, refreshToken) {
|
|
955
|
-
if (this.config.tokenStorage) {
|
|
956
|
-
await this.config.tokenStorage.setAccessToken(accessToken);
|
|
957
|
-
if (refreshToken) await this.config.tokenStorage.setRefreshToken(refreshToken);
|
|
958
|
-
} else {
|
|
959
|
-
this.config.accessToken = accessToken;
|
|
960
|
-
if (refreshToken) console.warn("Refresh token provided but ignored in manual token management mode. Use tokenStorage for automatic management.");
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
/**
|
|
964
|
-
* Clear all authentication tokens
|
|
647
|
+
* if (error) {
|
|
648
|
+
* console.error("Failed to list products:", error);
|
|
649
|
+
* return;
|
|
650
|
+
* }
|
|
965
651
|
*
|
|
966
|
-
*
|
|
967
|
-
*
|
|
968
|
-
* - If tokenStorage is not provided: Clears the manual access token
|
|
969
|
-
*/
|
|
970
|
-
async clearTokens() {
|
|
971
|
-
if (this.config.tokenStorage) await this.config.tokenStorage.clearTokens();
|
|
972
|
-
else this.config.accessToken = void 0;
|
|
973
|
-
}
|
|
974
|
-
/**
|
|
975
|
-
* Set the X-Api-Key header
|
|
976
|
-
*
|
|
977
|
-
* @param apiKey - The API key to set
|
|
978
|
-
*/
|
|
979
|
-
setApiKey(apiKey) {
|
|
980
|
-
this.config.apiKey = apiKey;
|
|
981
|
-
}
|
|
982
|
-
/**
|
|
983
|
-
* Clear the X-Api-Key header
|
|
984
|
-
*/
|
|
985
|
-
clearApiKey() {
|
|
986
|
-
this.config.apiKey = void 0;
|
|
987
|
-
}
|
|
988
|
-
/**
|
|
989
|
-
* Initialize tokens in storage (private helper method)
|
|
990
|
-
*/
|
|
991
|
-
async initializeTokens(accessToken, refreshToken) {
|
|
992
|
-
try {
|
|
993
|
-
if (this.config.tokenStorage) {
|
|
994
|
-
await this.config.tokenStorage.setAccessToken(accessToken);
|
|
995
|
-
if (refreshToken) await this.config.tokenStorage.setRefreshToken(refreshToken);
|
|
996
|
-
}
|
|
997
|
-
} catch (error) {
|
|
998
|
-
console.warn("Failed to initialize tokens in storage:", error);
|
|
999
|
-
}
|
|
1000
|
-
}
|
|
1001
|
-
};
|
|
1002
|
-
|
|
1003
|
-
//#endregion
|
|
1004
|
-
//#region src/lib/catalog.ts
|
|
1005
|
-
/**
|
|
1006
|
-
* Client for interacting with catalog endpoints
|
|
1007
|
-
*/
|
|
1008
|
-
var CatalogClient = class extends StorefrontAPIClient {
|
|
1009
|
-
/**
|
|
1010
|
-
* List all products
|
|
1011
|
-
*
|
|
1012
|
-
* @param options - Optional query parameters
|
|
1013
|
-
* @param headers - Optional header parameters (customer_group_id, etc.)
|
|
1014
|
-
* @returns Promise with products and pagination info
|
|
1015
|
-
*
|
|
1016
|
-
* @example
|
|
1017
|
-
* ```typescript
|
|
1018
|
-
* // Basic product listing
|
|
1019
|
-
* const { data, error } = await sdk.catalog.listProducts();
|
|
1020
|
-
*
|
|
1021
|
-
* if (error) {
|
|
1022
|
-
* console.error("Failed to list products:", error);
|
|
1023
|
-
* return;
|
|
1024
|
-
* }
|
|
1025
|
-
*
|
|
1026
|
-
* console.log("Products found:", data.products?.length || 0);
|
|
1027
|
-
* console.log("Pagination:", data.pagination);
|
|
652
|
+
* console.log("Products found:", data.products?.length || 0);
|
|
653
|
+
* console.log("Pagination:", data.pagination);
|
|
1028
654
|
*
|
|
1029
655
|
* // With filtering and pagination
|
|
1030
656
|
* const { data: filteredData, error: filteredError } = await sdk.catalog.listProducts({
|
|
@@ -1121,7 +747,7 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1121
747
|
/**
|
|
1122
748
|
* Get details for a specific product
|
|
1123
749
|
*
|
|
1124
|
-
* @param pathParams - The path parameters
|
|
750
|
+
* @param pathParams - The path parameters. Accepts product ID or product slug.
|
|
1125
751
|
* @param headers - Optional header parameters (customer_group_id, etc.)
|
|
1126
752
|
* @returns Promise with product details
|
|
1127
753
|
*
|
|
@@ -1129,7 +755,7 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1129
755
|
* ```typescript
|
|
1130
756
|
* // Get product by ID
|
|
1131
757
|
* const { data, error } = await sdk.catalog.getProductDetail(
|
|
1132
|
-
* {
|
|
758
|
+
* { product_id: "prod_123" }
|
|
1133
759
|
* );
|
|
1134
760
|
*
|
|
1135
761
|
* if (error) {
|
|
@@ -1141,14 +767,15 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1141
767
|
* console.log("Price:", data.product.pricing?.selling_price);
|
|
1142
768
|
* console.log("Description:", data.product.short_description);
|
|
1143
769
|
*
|
|
1144
|
-
* // Get product by slug
|
|
770
|
+
* // Get product by slug (also accepted in place of product_id)
|
|
1145
771
|
* const { data: slugData, error: slugError } = await sdk.catalog.getProductDetail({
|
|
1146
|
-
*
|
|
772
|
+
* product_id: "detox-candy"
|
|
1147
773
|
* });
|
|
1148
774
|
*
|
|
1149
775
|
* // Override customer group ID for this specific request
|
|
1150
776
|
* const { data: overrideData, error: overrideError } = await sdk.catalog.getProductDetail(
|
|
1151
|
-
* {
|
|
777
|
+
* { product_id: "detox-candy" },
|
|
778
|
+
* undefined,
|
|
1152
779
|
* {
|
|
1153
780
|
* "x-customer-group-id": "premium_customers" // Override default SDK config
|
|
1154
781
|
* }
|
|
@@ -1164,7 +791,7 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1164
791
|
*/
|
|
1165
792
|
async getProductDetail(pathParams, options, headers) {
|
|
1166
793
|
const mergedHeaders = this.mergeHeaders(headers);
|
|
1167
|
-
return this.executeRequest(() => this.client.GET("/catalog/products/{
|
|
794
|
+
return this.executeRequest(() => this.client.GET("/catalog/products/{product_id}", { params: {
|
|
1168
795
|
path: pathParams,
|
|
1169
796
|
query: options,
|
|
1170
797
|
header: mergedHeaders
|
|
@@ -1173,12 +800,13 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1173
800
|
/**
|
|
1174
801
|
* List all variants for a specific product
|
|
1175
802
|
*
|
|
1176
|
-
* @param pathParams - The path parameters
|
|
803
|
+
* @param pathParams - The path parameters. Accepts product ID or product slug.
|
|
1177
804
|
* @param headers - Optional header parameters (customer_group_id, etc.)
|
|
1178
805
|
* @returns Promise with product variants and pagination info
|
|
1179
806
|
*
|
|
1180
807
|
* @example
|
|
1181
808
|
* ```typescript
|
|
809
|
+
* // By product ID
|
|
1182
810
|
* const { data, error } = await sdk.catalog.listProductVariants(
|
|
1183
811
|
* { product_id: "prod_123" }
|
|
1184
812
|
* );
|
|
@@ -1194,9 +822,15 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1194
822
|
* console.log(`Variant: ${variant.name} - SKU: ${variant.sku} - Price: ${variant.pricing?.selling_price}`);
|
|
1195
823
|
* });
|
|
1196
824
|
*
|
|
825
|
+
* // By product slug (also accepted in place of product_id)
|
|
826
|
+
* const { data: slugData, error: slugError } = await sdk.catalog.listProductVariants(
|
|
827
|
+
* { product_id: "detox-candy" }
|
|
828
|
+
* );
|
|
829
|
+
*
|
|
1197
830
|
* // Override customer group ID for this specific request
|
|
1198
831
|
* const { data: overrideData, error: overrideError } = await sdk.catalog.listProductVariants(
|
|
1199
832
|
* { product_id: "prod_123" },
|
|
833
|
+
* undefined,
|
|
1200
834
|
* {
|
|
1201
835
|
* "x-customer-group-id": "wholesale_customers" // Override default SDK config
|
|
1202
836
|
* }
|
|
@@ -1214,12 +848,13 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1214
848
|
/**
|
|
1215
849
|
* Get details for a specific product variant
|
|
1216
850
|
*
|
|
1217
|
-
* @param pathParams - The path parameters
|
|
851
|
+
* @param pathParams - The path parameters. Accepts product ID or slug for product_id, and variant ID or slug for variant_id.
|
|
1218
852
|
* @param headers - Optional header parameters (customer_group_id, etc.)
|
|
1219
853
|
* @returns Promise with variant details
|
|
1220
854
|
*
|
|
1221
855
|
* @example
|
|
1222
856
|
* ```typescript
|
|
857
|
+
* // By product ID and variant ID
|
|
1223
858
|
* const { data, error } = await sdk.catalog.getVariantDetail(
|
|
1224
859
|
* {
|
|
1225
860
|
* product_id: "prod_123",
|
|
@@ -1236,6 +871,14 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1236
871
|
* console.log("SKU:", data.variant.sku);
|
|
1237
872
|
* console.log("Price:", data.variant.pricing?.selling_price);
|
|
1238
873
|
* console.log("Stock available:", data.variant.stock_available);
|
|
874
|
+
*
|
|
875
|
+
* // By product slug and variant slug (also accepted in place of IDs)
|
|
876
|
+
* const { data: slugData, error: slugError } = await sdk.catalog.getVariantDetail(
|
|
877
|
+
* {
|
|
878
|
+
* product_id: "detox-candy",
|
|
879
|
+
* variant_id: "detox-candy-100g"
|
|
880
|
+
* }
|
|
881
|
+
* );
|
|
1239
882
|
* ```
|
|
1240
883
|
*/
|
|
1241
884
|
async getVariantDetail(pathParams, options, headers) {
|
|
@@ -1320,49 +963,6 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1320
963
|
} }));
|
|
1321
964
|
}
|
|
1322
965
|
/**
|
|
1323
|
-
* Create a product review
|
|
1324
|
-
*
|
|
1325
|
-
* @param pathParams - The path parameters (product ID)
|
|
1326
|
-
* @param formData - The review data including rating, comment, and optional images
|
|
1327
|
-
* @returns Promise with review creation response
|
|
1328
|
-
*
|
|
1329
|
-
* @example
|
|
1330
|
-
* ```typescript
|
|
1331
|
-
* const { data, error } = await sdk.catalog.createProductReview(
|
|
1332
|
-
* { product_id: "prod_123" },
|
|
1333
|
-
* {
|
|
1334
|
-
* user_id: "user_123",
|
|
1335
|
-
* order_number: "ORD-001",
|
|
1336
|
-
* rating: 5,
|
|
1337
|
-
* review_text: "Excellent product! Highly recommended.",
|
|
1338
|
-
* images: [
|
|
1339
|
-
* new File(["image data"], "review1.jpg", { type: "image/jpeg" }),
|
|
1340
|
-
* new File(["image data"], "review2.jpg", { type: "image/jpeg" })
|
|
1341
|
-
* ]
|
|
1342
|
-
* }
|
|
1343
|
-
* );
|
|
1344
|
-
*
|
|
1345
|
-
* if (error) {
|
|
1346
|
-
* console.error("Failed to create review:", error);
|
|
1347
|
-
* return;
|
|
1348
|
-
* }
|
|
1349
|
-
*
|
|
1350
|
-
* console.log("Review created successfully:", data.message);
|
|
1351
|
-
* ```
|
|
1352
|
-
*/
|
|
1353
|
-
async createProductReview(pathParams, formData) {
|
|
1354
|
-
return this.executeRequest(() => this.client.POST("/catalog/products/{product_id}/reviews", {
|
|
1355
|
-
params: { path: pathParams },
|
|
1356
|
-
body: formData,
|
|
1357
|
-
bodySerializer: (body) => {
|
|
1358
|
-
const fd = new FormData();
|
|
1359
|
-
for (const [key, value] of Object.entries(body)) if (value !== void 0 && value !== null) if (value instanceof File || value instanceof Blob) fd.append(key, value);
|
|
1360
|
-
else fd.append(key, String(value));
|
|
1361
|
-
return fd;
|
|
1362
|
-
}
|
|
1363
|
-
}));
|
|
1364
|
-
}
|
|
1365
|
-
/**
|
|
1366
966
|
* Search for products
|
|
1367
967
|
*
|
|
1368
968
|
* @param searchData - The search query, filters, sort, and pagination options
|
|
@@ -1602,12 +1202,74 @@ var CatalogClient = class extends StorefrontAPIClient {
|
|
|
1602
1202
|
}
|
|
1603
1203
|
};
|
|
1604
1204
|
|
|
1205
|
+
//#endregion
|
|
1206
|
+
//#region src/lib/public/catalog.ts
|
|
1207
|
+
/**
|
|
1208
|
+
* Client for interacting with catalog endpoints
|
|
1209
|
+
*/
|
|
1210
|
+
var PublicCatalogClient = class extends BaseCatalogClient {};
|
|
1211
|
+
|
|
1212
|
+
//#endregion
|
|
1213
|
+
//#region src/lib/catalog.ts
|
|
1214
|
+
/**
|
|
1215
|
+
* Client for interacting with catalog endpoints
|
|
1216
|
+
*/
|
|
1217
|
+
var CatalogClient = class extends BaseCatalogClient {
|
|
1218
|
+
constructor(config) {
|
|
1219
|
+
super(config);
|
|
1220
|
+
attachSessionAuth(this, config.sessionManager);
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Create a product review
|
|
1224
|
+
*
|
|
1225
|
+
* @param pathParams - The path parameters (product ID)
|
|
1226
|
+
* @param formData - The review data including rating, comment, and optional images
|
|
1227
|
+
* @returns Promise with review creation response
|
|
1228
|
+
*
|
|
1229
|
+
* @example
|
|
1230
|
+
* ```typescript
|
|
1231
|
+
* const { data, error } = await sdk.catalog.createProductReview(
|
|
1232
|
+
* { product_id: "prod_123" },
|
|
1233
|
+
* {
|
|
1234
|
+
* user_id: "user_123",
|
|
1235
|
+
* order_number: "ORD-001",
|
|
1236
|
+
* rating: 5,
|
|
1237
|
+
* review_text: "Excellent product! Highly recommended.",
|
|
1238
|
+
* images: [
|
|
1239
|
+
* new File(["image data"], "review1.jpg", { type: "image/jpeg" }),
|
|
1240
|
+
* new File(["image data"], "review2.jpg", { type: "image/jpeg" })
|
|
1241
|
+
* ]
|
|
1242
|
+
* }
|
|
1243
|
+
* );
|
|
1244
|
+
*
|
|
1245
|
+
* if (error) {
|
|
1246
|
+
* console.error("Failed to create review:", error);
|
|
1247
|
+
* return;
|
|
1248
|
+
* }
|
|
1249
|
+
*
|
|
1250
|
+
* console.log("Review created successfully:", data.message);
|
|
1251
|
+
* ```
|
|
1252
|
+
*/
|
|
1253
|
+
async createProductReview(pathParams, formData) {
|
|
1254
|
+
return this.executeRequest(() => this.client.POST("/catalog/products/{product_id}/reviews", {
|
|
1255
|
+
params: { path: pathParams },
|
|
1256
|
+
body: formData,
|
|
1257
|
+
bodySerializer: (body) => {
|
|
1258
|
+
const fd = new FormData();
|
|
1259
|
+
for (const [key, value] of Object.entries(body)) if (value !== void 0 && value !== null) if (value instanceof File || value instanceof Blob) fd.append(key, value);
|
|
1260
|
+
else fd.append(key, String(value));
|
|
1261
|
+
return fd;
|
|
1262
|
+
}
|
|
1263
|
+
}));
|
|
1264
|
+
}
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1605
1267
|
//#endregion
|
|
1606
1268
|
//#region src/lib/cart.ts
|
|
1607
1269
|
/**
|
|
1608
1270
|
* Client for interacting with cart endpoints
|
|
1609
1271
|
*/
|
|
1610
|
-
var CartClient = class extends
|
|
1272
|
+
var CartClient = class extends SessionStorefrontAPIClient {
|
|
1611
1273
|
/**
|
|
1612
1274
|
* Create a new cart
|
|
1613
1275
|
*
|
|
@@ -1729,49 +1391,14 @@ var CartClient = class extends StorefrontAPIClient {
|
|
|
1729
1391
|
body
|
|
1730
1392
|
}));
|
|
1731
1393
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
* @param userId - The ID of the user
|
|
1736
|
-
* @returns Promise with cart details
|
|
1737
|
-
* @example
|
|
1738
|
-
* ```typescript
|
|
1739
|
-
* const { data, error } = await sdk.cart.getUserCart({
|
|
1740
|
-
* user_id: "01H9USER12345ABCDE"
|
|
1741
|
-
* });
|
|
1742
|
-
*
|
|
1743
|
-
* if (error) {
|
|
1744
|
-
* console.error("Failed to get user cart:", error.message);
|
|
1745
|
-
* } else {
|
|
1746
|
-
* console.log("User cart ID:", data.cart.id);
|
|
1747
|
-
* console.log("Cart value:", data.cart.subtotal);
|
|
1748
|
-
* }
|
|
1749
|
-
* ```
|
|
1750
|
-
*/
|
|
1751
|
-
async getUserCart(userId) {
|
|
1752
|
-
return this.executeRequest(() => this.client.GET("/carts/users/{user_id}", { params: { path: userId } }));
|
|
1394
|
+
async getUserCart(pathParams = {}) {
|
|
1395
|
+
const resolvedPathParams = await this.resolveUserPathParams(pathParams);
|
|
1396
|
+
return this.executeRequest(() => this.client.GET("/carts/users/{user_id}", { params: { path: resolvedPathParams } }));
|
|
1753
1397
|
}
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
*
|
|
1757
|
-
* @param userId - The ID of the user
|
|
1758
|
-
* @returns Promise that resolves when the cart is deleted
|
|
1759
|
-
* @example
|
|
1760
|
-
* ```typescript
|
|
1761
|
-
* const { data, error } = await sdk.cart.deleteUserCart({
|
|
1762
|
-
* user_id: "01H9USER12345ABCDE"
|
|
1763
|
-
* });
|
|
1764
|
-
*
|
|
1765
|
-
* if (error) {
|
|
1766
|
-
* console.error("Failed to delete user cart:", error.message);
|
|
1767
|
-
* } else {
|
|
1768
|
-
* console.log("User cart cleared:", data.message);
|
|
1769
|
-
* }
|
|
1770
|
-
* ```
|
|
1771
|
-
*/
|
|
1772
|
-
async deleteUserCart(userId) {
|
|
1398
|
+
async deleteUserCart(pathParams = {}) {
|
|
1399
|
+
const resolvedPathParams = await this.resolveUserPathParams(pathParams);
|
|
1773
1400
|
return this.executeRequest(() => this.client.DELETE("/carts/users/{user_id}", {
|
|
1774
|
-
params: { path:
|
|
1401
|
+
params: { path: resolvedPathParams },
|
|
1775
1402
|
body: void 0
|
|
1776
1403
|
}));
|
|
1777
1404
|
}
|
|
@@ -2264,92 +1891,31 @@ var CartClient = class extends StorefrontAPIClient {
|
|
|
2264
1891
|
body: void 0
|
|
2265
1892
|
}));
|
|
2266
1893
|
}
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
* @returns Promise with wishlist items
|
|
2273
|
-
* @example
|
|
2274
|
-
* ```typescript
|
|
2275
|
-
* const { data, error } = await sdk.cart.getWishlist({
|
|
2276
|
-
* user_id: "01H9USER12345ABCDE"
|
|
2277
|
-
* });
|
|
2278
|
-
*
|
|
2279
|
-
* if (error) {
|
|
2280
|
-
* console.error("Failed to get wishlist:", error.message);
|
|
2281
|
-
* } else {
|
|
2282
|
-
* const products = data.products;
|
|
2283
|
-
* console.log("Wishlist items:", products.length);
|
|
2284
|
-
* products.forEach(product => {
|
|
2285
|
-
* console.log("Product:", product.product_name, "Price:", product.pricing?.selling_price);
|
|
2286
|
-
* });
|
|
2287
|
-
* }
|
|
2288
|
-
* ```
|
|
2289
|
-
*/
|
|
2290
|
-
async getWishlist(userId, options) {
|
|
1894
|
+
async getWishlist(pathParamsOrQuery, options) {
|
|
1895
|
+
const hasPathParams = options !== void 0 || !!pathParamsOrQuery && typeof pathParamsOrQuery === "object" && "user_id" in pathParamsOrQuery;
|
|
1896
|
+
const pathParams = hasPathParams ? pathParamsOrQuery : {};
|
|
1897
|
+
const queryParams = hasPathParams ? options : pathParamsOrQuery;
|
|
1898
|
+
const resolvedPathParams = await this.resolveUserPathParams(pathParams);
|
|
2291
1899
|
return this.executeRequest(() => this.client.GET("/wishlist/{user_id}", { params: {
|
|
2292
|
-
path:
|
|
2293
|
-
query:
|
|
1900
|
+
path: resolvedPathParams,
|
|
1901
|
+
query: queryParams
|
|
2294
1902
|
} }));
|
|
2295
1903
|
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
* @param itemId - The ID of the item
|
|
2301
|
-
* @returns Promise with updated wishlist
|
|
2302
|
-
* @example
|
|
2303
|
-
* ```typescript
|
|
2304
|
-
* const { data, error } = await sdk.cart.addToWishlist(
|
|
2305
|
-
* { user_id: "01H9USER12345ABCDE" },
|
|
2306
|
-
* {
|
|
2307
|
-
* product_id: "01F3Z7KG06J4ACWH1C4926KJEC",
|
|
2308
|
-
* variant_id: null
|
|
2309
|
-
* }
|
|
2310
|
-
* );
|
|
2311
|
-
*
|
|
2312
|
-
* if (error) {
|
|
2313
|
-
* console.error("Failed to add to wishlist:", error.message);
|
|
2314
|
-
* } else {
|
|
2315
|
-
* const products = data.products;
|
|
2316
|
-
* console.log("Item added to wishlist, total items:", products.length);
|
|
2317
|
-
* }
|
|
2318
|
-
* ```
|
|
2319
|
-
*/
|
|
2320
|
-
async addToWishlist(userId, itemId) {
|
|
1904
|
+
async addToWishlist(pathParamsOrBody, maybeBody) {
|
|
1905
|
+
const pathParams = maybeBody ? pathParamsOrBody : {};
|
|
1906
|
+
const body = maybeBody ?? pathParamsOrBody;
|
|
1907
|
+
const resolvedPathParams = await this.resolveUserPathParams(pathParams);
|
|
2321
1908
|
return this.executeRequest(() => this.client.POST("/wishlist/{user_id}", {
|
|
2322
|
-
params: { path:
|
|
2323
|
-
body
|
|
1909
|
+
params: { path: resolvedPathParams },
|
|
1910
|
+
body
|
|
2324
1911
|
}));
|
|
2325
1912
|
}
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
* @param body - The body containing product details to remove
|
|
2331
|
-
* @returns Promise with updated wishlist
|
|
2332
|
-
* @example
|
|
2333
|
-
* ```typescript
|
|
2334
|
-
* const { data, error } = await sdk.cart.removeFromWishlist(
|
|
2335
|
-
* { user_id: "01H9USER12345ABCDE" },
|
|
2336
|
-
* {
|
|
2337
|
-
* product_id: "01F3Z7KG06J4ACWH1C4926KJEC",
|
|
2338
|
-
* variant_id: null
|
|
2339
|
-
* }
|
|
2340
|
-
* );
|
|
2341
|
-
*
|
|
2342
|
-
* if (error) {
|
|
2343
|
-
* console.error("Failed to remove from wishlist:", error.message);
|
|
2344
|
-
* } else {
|
|
2345
|
-
* const products = data.products;
|
|
2346
|
-
* console.log("Item removed from wishlist, remaining items:", products.length);
|
|
2347
|
-
* }
|
|
2348
|
-
* ```
|
|
2349
|
-
*/
|
|
2350
|
-
async removeFromWishlist(userId, body) {
|
|
1913
|
+
async removeFromWishlist(pathParamsOrBody, maybeBody) {
|
|
1914
|
+
const pathParams = maybeBody ? pathParamsOrBody : {};
|
|
1915
|
+
const body = maybeBody ?? pathParamsOrBody;
|
|
1916
|
+
const resolvedPathParams = await this.resolveUserPathParams(pathParams);
|
|
2351
1917
|
return this.executeRequest(() => this.client.DELETE("/wishlist/{user_id}", {
|
|
2352
|
-
params: { path:
|
|
1918
|
+
params: { path: resolvedPathParams },
|
|
2353
1919
|
body
|
|
2354
1920
|
}));
|
|
2355
1921
|
}
|
|
@@ -2360,7 +1926,7 @@ var CartClient = class extends StorefrontAPIClient {
|
|
|
2360
1926
|
/**
|
|
2361
1927
|
* Client for interacting with authentication endpoints
|
|
2362
1928
|
*/
|
|
2363
|
-
var AuthClient = class extends
|
|
1929
|
+
var AuthClient = class extends SessionStorefrontAPIClient {
|
|
2364
1930
|
/**
|
|
2365
1931
|
* Get anonymous token for guest users
|
|
2366
1932
|
*
|
|
@@ -2493,13 +2059,14 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2493
2059
|
return this.executeRequest(() => this.client.POST("/auth/login/password", { body }));
|
|
2494
2060
|
}
|
|
2495
2061
|
/**
|
|
2496
|
-
*
|
|
2062
|
+
* Start forgot-password OTP flow
|
|
2497
2063
|
*
|
|
2498
|
-
* @param body - Request body containing email
|
|
2499
|
-
* @
|
|
2064
|
+
* @param body - Request body containing email or phone details
|
|
2065
|
+
* @param headers - Optional header parameters (for example `x-debug-mode`)
|
|
2066
|
+
* @returns Promise with OTP token and action for the reset flow
|
|
2500
2067
|
* @example
|
|
2501
2068
|
* ```typescript
|
|
2502
|
-
* // Send password reset
|
|
2069
|
+
* // Send password reset OTP
|
|
2503
2070
|
* const { data, error } = await sdk.auth.forgotPassword({
|
|
2504
2071
|
* email: "customer@example.com"
|
|
2505
2072
|
* });
|
|
@@ -2507,13 +2074,17 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2507
2074
|
* if (error) {
|
|
2508
2075
|
* console.error("Password reset failed:", error.message);
|
|
2509
2076
|
* } else {
|
|
2510
|
-
* console.log("
|
|
2511
|
-
*
|
|
2077
|
+
* console.log("OTP token:", data.otp_token);
|
|
2078
|
+
* console.log("Action:", data.otp_action);
|
|
2512
2079
|
* }
|
|
2513
2080
|
* ```
|
|
2514
2081
|
*/
|
|
2515
|
-
async forgotPassword(body) {
|
|
2516
|
-
|
|
2082
|
+
async forgotPassword(body, headers) {
|
|
2083
|
+
const mergedHeaders = this.mergeHeaders(headers);
|
|
2084
|
+
return this.executeRequest(() => this.client.POST("/auth/forgot-password", {
|
|
2085
|
+
body,
|
|
2086
|
+
params: { header: mergedHeaders }
|
|
2087
|
+
}));
|
|
2517
2088
|
}
|
|
2518
2089
|
/**
|
|
2519
2090
|
* Reset password
|
|
@@ -2595,7 +2166,8 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2595
2166
|
* Register with phone
|
|
2596
2167
|
*
|
|
2597
2168
|
* @param body - Registration details including phone number and user information
|
|
2598
|
-
* @
|
|
2169
|
+
* @param headers - Optional header parameters (for example `x-debug-mode`)
|
|
2170
|
+
* @returns Promise with OTP token and action for completing registration
|
|
2599
2171
|
* @example
|
|
2600
2172
|
* ```typescript
|
|
2601
2173
|
* // Register a new user with phone number
|
|
@@ -2610,20 +2182,24 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2610
2182
|
* if (error) {
|
|
2611
2183
|
* console.error("Phone registration failed:", error.message);
|
|
2612
2184
|
* } else {
|
|
2613
|
-
* console.log("
|
|
2614
|
-
* console.log("
|
|
2615
|
-
* console.log("Access token:", data.access_token);
|
|
2185
|
+
* console.log("OTP token:", data.otp_token);
|
|
2186
|
+
* console.log("Action:", data.otp_action);
|
|
2616
2187
|
* }
|
|
2617
2188
|
* ```
|
|
2618
2189
|
*/
|
|
2619
|
-
async registerWithPhone(body) {
|
|
2620
|
-
|
|
2190
|
+
async registerWithPhone(body, headers) {
|
|
2191
|
+
const mergedHeaders = this.mergeHeaders(headers);
|
|
2192
|
+
return this.executeRequest(() => this.client.POST("/auth/register/phone", {
|
|
2193
|
+
body,
|
|
2194
|
+
params: { header: mergedHeaders }
|
|
2195
|
+
}));
|
|
2621
2196
|
}
|
|
2622
2197
|
/**
|
|
2623
2198
|
* Register with email
|
|
2624
2199
|
*
|
|
2625
2200
|
* @param body - Registration details including email and user information
|
|
2626
|
-
* @
|
|
2201
|
+
* @param headers - Optional header parameters (for example `x-debug-mode`)
|
|
2202
|
+
* @returns Promise with OTP token and action for completing registration
|
|
2627
2203
|
* @example
|
|
2628
2204
|
* ```typescript
|
|
2629
2205
|
* // Register a new user with email address
|
|
@@ -2637,32 +2213,96 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2637
2213
|
* if (error) {
|
|
2638
2214
|
* console.error("Email registration failed:", error.message);
|
|
2639
2215
|
* } else {
|
|
2640
|
-
* console.log("
|
|
2641
|
-
* console.log("
|
|
2642
|
-
* console.log("Access token:", data.access_token);
|
|
2216
|
+
* console.log("OTP token:", data.otp_token);
|
|
2217
|
+
* console.log("Action:", data.otp_action);
|
|
2643
2218
|
* }
|
|
2644
2219
|
* ```
|
|
2645
2220
|
*/
|
|
2646
|
-
async registerWithEmail(body) {
|
|
2647
|
-
|
|
2221
|
+
async registerWithEmail(body, headers) {
|
|
2222
|
+
const mergedHeaders = this.mergeHeaders(headers);
|
|
2223
|
+
return this.executeRequest(() => this.client.POST("/auth/register/email", {
|
|
2224
|
+
body,
|
|
2225
|
+
params: { header: mergedHeaders }
|
|
2226
|
+
}));
|
|
2648
2227
|
}
|
|
2649
2228
|
/**
|
|
2650
|
-
*
|
|
2651
|
-
*
|
|
2652
|
-
* @
|
|
2229
|
+
* Register with WhatsApp
|
|
2230
|
+
*
|
|
2231
|
+
* @param body - Registration details including WhatsApp number and user information
|
|
2232
|
+
* @param headers - Optional header parameters (for example `x-debug-mode`)
|
|
2233
|
+
* @returns Promise with OTP token and action for completing registration
|
|
2653
2234
|
* @example
|
|
2654
2235
|
* ```typescript
|
|
2655
|
-
* //
|
|
2656
|
-
* const { data, error } = await sdk.auth.
|
|
2657
|
-
*
|
|
2236
|
+
* // Register a new user with WhatsApp number
|
|
2237
|
+
* const { data, error } = await sdk.auth.registerWithWhatsapp({
|
|
2238
|
+
* phone: "9876543210",
|
|
2239
|
+
* country_code: "+91",
|
|
2240
|
+
* first_name: "John",
|
|
2241
|
+
* last_name: "Doe",
|
|
2242
|
+
* email: "john.doe@example.com"
|
|
2658
2243
|
* });
|
|
2659
2244
|
*
|
|
2660
2245
|
* if (error) {
|
|
2661
|
-
* console.error("
|
|
2662
|
-
* // Redirect to login
|
|
2246
|
+
* console.error("WhatsApp registration failed:", error.message);
|
|
2663
2247
|
* } else {
|
|
2664
|
-
* console.log("
|
|
2665
|
-
* console.log("
|
|
2248
|
+
* console.log("OTP token:", data.otp_token);
|
|
2249
|
+
* console.log("Action:", data.otp_action);
|
|
2250
|
+
* }
|
|
2251
|
+
* ```
|
|
2252
|
+
*/
|
|
2253
|
+
async registerWithWhatsapp(body, headers) {
|
|
2254
|
+
const mergedHeaders = this.mergeHeaders(headers);
|
|
2255
|
+
return this.executeRequest(() => this.client.POST("/auth/register/whatsapp", {
|
|
2256
|
+
body,
|
|
2257
|
+
params: { header: mergedHeaders }
|
|
2258
|
+
}));
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Register with password
|
|
2262
|
+
*
|
|
2263
|
+
* @param body - Registration details including email or phone and password
|
|
2264
|
+
* @param headers - Optional header parameters (for example `x-debug-mode`)
|
|
2265
|
+
* @returns Promise with OTP token and action for completing registration
|
|
2266
|
+
* @example
|
|
2267
|
+
* ```typescript
|
|
2268
|
+
* const { data, error } = await sdk.auth.registerWithPassword({
|
|
2269
|
+
* email: "jane.smith@example.com",
|
|
2270
|
+
* password: "securePassword123",
|
|
2271
|
+
* confirm_password: "securePassword123",
|
|
2272
|
+
* });
|
|
2273
|
+
*
|
|
2274
|
+
* if (error) {
|
|
2275
|
+
* console.error("Password registration failed:", error.message);
|
|
2276
|
+
* } else {
|
|
2277
|
+
* console.log("OTP token:", data.otp_token);
|
|
2278
|
+
* console.log("Action:", data.otp_action);
|
|
2279
|
+
* }
|
|
2280
|
+
* ```
|
|
2281
|
+
*/
|
|
2282
|
+
async registerWithPassword(body, headers) {
|
|
2283
|
+
const mergedHeaders = this.mergeHeaders(headers);
|
|
2284
|
+
return this.executeRequest(() => this.client.POST("/auth/register/password", {
|
|
2285
|
+
body,
|
|
2286
|
+
params: { header: mergedHeaders }
|
|
2287
|
+
}));
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Refresh the access token using a refresh token
|
|
2291
|
+
* @param body - Request body containing the refresh token
|
|
2292
|
+
* @returns Promise with the new access token and refresh token
|
|
2293
|
+
* @example
|
|
2294
|
+
* ```typescript
|
|
2295
|
+
* // Refresh access token when it expires
|
|
2296
|
+
* const { data, error } = await sdk.auth.refreshToken({
|
|
2297
|
+
* refresh_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
2298
|
+
* });
|
|
2299
|
+
*
|
|
2300
|
+
* if (error) {
|
|
2301
|
+
* console.error("Token refresh failed:", error.message);
|
|
2302
|
+
* // Redirect to login
|
|
2303
|
+
* } else {
|
|
2304
|
+
* console.log("Token refreshed successfully");
|
|
2305
|
+
* console.log("New access token:", data.access_token);
|
|
2666
2306
|
* console.log("New refresh token:", data.refresh_token);
|
|
2667
2307
|
* }
|
|
2668
2308
|
* ```
|
|
@@ -2913,90 +2553,6 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
2913
2553
|
return this.executeRequest(() => this.client.PUT("/auth/user/{id}/deactivate", { params: { path: pathParams } }));
|
|
2914
2554
|
}
|
|
2915
2555
|
/**
|
|
2916
|
-
* Get user notification preferences
|
|
2917
|
-
*
|
|
2918
|
-
* @param pathParams - Path parameters containing user ID
|
|
2919
|
-
* @returns Promise with user's notification preferences
|
|
2920
|
-
* @example
|
|
2921
|
-
* ```typescript
|
|
2922
|
-
* // Get user's notification preferences
|
|
2923
|
-
* const { data, error } = await sdk.auth.getUserNotificationPreferences({
|
|
2924
|
-
* id: "01H9XYZ12345USERID"
|
|
2925
|
-
* });
|
|
2926
|
-
*
|
|
2927
|
-
* if (error) {
|
|
2928
|
-
* console.error("Failed to get preferences:", error.message);
|
|
2929
|
-
* } else {
|
|
2930
|
-
* console.log("Notification preferences:", data.notification_preferences);
|
|
2931
|
-
* }
|
|
2932
|
-
* ```
|
|
2933
|
-
*/
|
|
2934
|
-
async getUserNotificationPreferences(pathParams) {
|
|
2935
|
-
return this.executeRequest(() => this.client.GET("/auth/user/{id}/notification-preferences", { params: { path: pathParams } }));
|
|
2936
|
-
}
|
|
2937
|
-
/**
|
|
2938
|
-
* Update user notification preferences
|
|
2939
|
-
*
|
|
2940
|
-
* @param pathParams - Path parameters containing user ID
|
|
2941
|
-
* @param body - Updated notification preferences
|
|
2942
|
-
* @returns Promise with updated notification preferences
|
|
2943
|
-
* @example
|
|
2944
|
-
* ```typescript
|
|
2945
|
-
* // Update user's notification preferences
|
|
2946
|
-
* const { data, error } = await sdk.auth.updateUserNotificationPreferences(
|
|
2947
|
-
* { id: "01H9XYZ12345USERID" },
|
|
2948
|
-
* {
|
|
2949
|
-
* email_notifications: true,
|
|
2950
|
-
* sms_notifications: false,
|
|
2951
|
-
* push_notifications: true
|
|
2952
|
-
* }
|
|
2953
|
-
* );
|
|
2954
|
-
*
|
|
2955
|
-
* if (error) {
|
|
2956
|
-
* console.error("Failed to update preferences:", error.message);
|
|
2957
|
-
* } else {
|
|
2958
|
-
* console.log("Preferences updated successfully");
|
|
2959
|
-
* }
|
|
2960
|
-
* ```
|
|
2961
|
-
*/
|
|
2962
|
-
async updateUserNotificationPreferences(pathParams, body) {
|
|
2963
|
-
return this.executeRequest(() => this.client.PUT("/auth/user/{id}/notification-preferences", {
|
|
2964
|
-
params: { path: pathParams },
|
|
2965
|
-
body
|
|
2966
|
-
}));
|
|
2967
|
-
}
|
|
2968
|
-
/**
|
|
2969
|
-
* Create user notification preference
|
|
2970
|
-
*
|
|
2971
|
-
* @param pathParams - Path parameters containing user ID
|
|
2972
|
-
* @param body - Notification preferences to create
|
|
2973
|
-
* @returns Promise with created notification preferences
|
|
2974
|
-
* @example
|
|
2975
|
-
* ```typescript
|
|
2976
|
-
* // Create notification preferences for a user
|
|
2977
|
-
* const { data, error } = await sdk.auth.createUserNotificationPreference(
|
|
2978
|
-
* { id: "01H9XYZ12345USERID" },
|
|
2979
|
-
* {
|
|
2980
|
-
* email_notifications: true,
|
|
2981
|
-
* sms_notifications: true,
|
|
2982
|
-
* push_notifications: false
|
|
2983
|
-
* }
|
|
2984
|
-
* );
|
|
2985
|
-
*
|
|
2986
|
-
* if (error) {
|
|
2987
|
-
* console.error("Failed to create preferences:", error.message);
|
|
2988
|
-
* } else {
|
|
2989
|
-
* console.log("Preferences created successfully");
|
|
2990
|
-
* }
|
|
2991
|
-
* ```
|
|
2992
|
-
*/
|
|
2993
|
-
async createUserNotificationPreference(pathParams, body) {
|
|
2994
|
-
return this.executeRequest(() => this.client.POST("/auth/user/{id}/notification-preferences", {
|
|
2995
|
-
params: { path: pathParams },
|
|
2996
|
-
body
|
|
2997
|
-
}));
|
|
2998
|
-
}
|
|
2999
|
-
/**
|
|
3000
2556
|
* Generate OTP
|
|
3001
2557
|
*
|
|
3002
2558
|
* @param body - OTP generation body (phone or email)
|
|
@@ -3056,7 +2612,7 @@ var AuthClient = class extends StorefrontAPIClient {
|
|
|
3056
2612
|
/**
|
|
3057
2613
|
* Client for interacting with order endpoints
|
|
3058
2614
|
*/
|
|
3059
|
-
var OrderClient = class extends
|
|
2615
|
+
var OrderClient = class extends SessionStorefrontAPIClient {
|
|
3060
2616
|
/**
|
|
3061
2617
|
* Get order details
|
|
3062
2618
|
*
|
|
@@ -3187,41 +2743,9 @@ var OrderClient = class extends StorefrontAPIClient {
|
|
|
3187
2743
|
async createOrder(body) {
|
|
3188
2744
|
return this.executeRequest(() => this.client.POST("/orders", { body }));
|
|
3189
2745
|
}
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
* @param queryParams - Query parameters for filtering and pagination
|
|
3194
|
-
* @returns Promise with order list
|
|
3195
|
-
* @example
|
|
3196
|
-
* ```typescript
|
|
3197
|
-
* // Basic usage - only required parameter
|
|
3198
|
-
* const { data, error } = await sdk.order.listOrders({
|
|
3199
|
-
* user_id: "user_01H9XYZ12345ABCDE"
|
|
3200
|
-
* });
|
|
3201
|
-
*
|
|
3202
|
-
* // Advanced usage with optional parameters
|
|
3203
|
-
* const { data, error } = await sdk.order.listOrders({
|
|
3204
|
-
* user_id: "user_01H9XYZ12345ABCDE",
|
|
3205
|
-
* page: 1,
|
|
3206
|
-
* limit: 20,
|
|
3207
|
-
* sort_by: '{"created_at":"desc"}',
|
|
3208
|
-
* status: ["confirmed", "shipped", "delivered"]
|
|
3209
|
-
* });
|
|
3210
|
-
*
|
|
3211
|
-
* if (error) {
|
|
3212
|
-
* console.error("Failed to list orders:", error.message);
|
|
3213
|
-
* } else {
|
|
3214
|
-
* console.log("Orders found:", data.orders?.length || 0);
|
|
3215
|
-
* console.log("Pagination:", data.pagination);
|
|
3216
|
-
*
|
|
3217
|
-
* data.orders?.forEach(order => {
|
|
3218
|
-
* console.log(`Order ${order.order_number}: ${order.status}`);
|
|
3219
|
-
* });
|
|
3220
|
-
* }
|
|
3221
|
-
* ```
|
|
3222
|
-
*/
|
|
3223
|
-
async listOrders(queryParams) {
|
|
3224
|
-
return this.executeRequest(() => this.client.GET("/orders", { params: { query: queryParams } }));
|
|
2746
|
+
async listOrders(queryParams = {}) {
|
|
2747
|
+
const resolvedQueryParams = await this.resolveUserQueryParams(queryParams);
|
|
2748
|
+
return this.executeRequest(() => this.client.GET("/orders", { params: { query: resolvedQueryParams } }));
|
|
3225
2749
|
}
|
|
3226
2750
|
/**
|
|
3227
2751
|
* Get payment status for an order
|
|
@@ -3452,7 +2976,7 @@ var OrderClient = class extends StorefrontAPIClient {
|
|
|
3452
2976
|
/**
|
|
3453
2977
|
* Client for interacting with payment endpoints
|
|
3454
2978
|
*/
|
|
3455
|
-
var PaymentsClient = class extends
|
|
2979
|
+
var PaymentsClient = class extends SessionStorefrontAPIClient {
|
|
3456
2980
|
/**
|
|
3457
2981
|
* List all available payment methods
|
|
3458
2982
|
*
|
|
@@ -3595,11 +3119,11 @@ var PaymentsClient = class extends StorefrontAPIClient {
|
|
|
3595
3119
|
};
|
|
3596
3120
|
|
|
3597
3121
|
//#endregion
|
|
3598
|
-
//#region src/lib/helper.ts
|
|
3122
|
+
//#region src/lib/shared/helper.ts
|
|
3599
3123
|
/**
|
|
3600
3124
|
* Client for interacting with helper endpoints
|
|
3601
3125
|
*/
|
|
3602
|
-
var
|
|
3126
|
+
var BaseHelpersClient = class extends StorefrontAPIClientBase {
|
|
3603
3127
|
/**
|
|
3604
3128
|
* Get a list of countries
|
|
3605
3129
|
*
|
|
@@ -3622,446 +3146,1077 @@ var HelpersClient = class extends StorefrontAPIClient {
|
|
|
3622
3146
|
* });
|
|
3623
3147
|
* ```
|
|
3624
3148
|
*/
|
|
3625
|
-
async listCountries() {
|
|
3626
|
-
return this.executeRequest(() => this.client.GET("/common/countries", {}));
|
|
3149
|
+
async listCountries() {
|
|
3150
|
+
return this.executeRequest(() => this.client.GET("/common/countries", {}));
|
|
3151
|
+
}
|
|
3152
|
+
/**
|
|
3153
|
+
* Get a list of states for a country
|
|
3154
|
+
*
|
|
3155
|
+
* @param pathParams - Path parameters
|
|
3156
|
+
* @returns Promise with states
|
|
3157
|
+
*
|
|
3158
|
+
* @example
|
|
3159
|
+
* ```typescript
|
|
3160
|
+
* const { data, error } = await sdk.helpers.listCountryStates({
|
|
3161
|
+
* country_iso_code: "IN"
|
|
3162
|
+
* });
|
|
3163
|
+
*
|
|
3164
|
+
* if (error) {
|
|
3165
|
+
* console.error("Failed to get states:", error);
|
|
3166
|
+
* return;
|
|
3167
|
+
* }
|
|
3168
|
+
*
|
|
3169
|
+
* console.log("States found:", data.states?.length || 0);
|
|
3170
|
+
*
|
|
3171
|
+
* data.states?.forEach(state => {
|
|
3172
|
+
* console.log(`State: ${state.name} (${state.iso_code})`);
|
|
3173
|
+
* });
|
|
3174
|
+
*
|
|
3175
|
+
* // Get states for different country
|
|
3176
|
+
* const { data: usStates, error: usError } = await sdk.helpers.listCountryStates({
|
|
3177
|
+
* country_iso_code: "US"
|
|
3178
|
+
* });
|
|
3179
|
+
*
|
|
3180
|
+
* if (usError) {
|
|
3181
|
+
* console.error("Failed to get US states:", usError);
|
|
3182
|
+
* return;
|
|
3183
|
+
* }
|
|
3184
|
+
*
|
|
3185
|
+
* console.log("US States:", usStates.states?.map(s => s.name).join(", "));
|
|
3186
|
+
* ```
|
|
3187
|
+
*/
|
|
3188
|
+
async listCountryStates(pathParams) {
|
|
3189
|
+
return this.executeRequest(() => this.client.GET("/common/countries/{country_iso_code}/states", { params: { path: pathParams } }));
|
|
3190
|
+
}
|
|
3191
|
+
/**
|
|
3192
|
+
* Get pincodes for a country
|
|
3193
|
+
*
|
|
3194
|
+
* @param pathParams - Path parameters
|
|
3195
|
+
* @returns Promise with pincodes
|
|
3196
|
+
*
|
|
3197
|
+
* @example
|
|
3198
|
+
* ```typescript
|
|
3199
|
+
* const { data, error } = await sdk.helpers.listCountryPincodes({
|
|
3200
|
+
* country_iso_code: "IN"
|
|
3201
|
+
* });
|
|
3202
|
+
*
|
|
3203
|
+
* if (error) {
|
|
3204
|
+
* console.error("Failed to get pincodes:", error);
|
|
3205
|
+
* return;
|
|
3206
|
+
* }
|
|
3207
|
+
*
|
|
3208
|
+
* console.log("Pincodes found:", data.pincodes?.length || 0);
|
|
3209
|
+
*
|
|
3210
|
+
* data.pincodes?.forEach(pincode => {
|
|
3211
|
+
* console.log(`Pincode: ${pincode.pincode} - ${pincode.city}, ${pincode.state_name}`);
|
|
3212
|
+
* });
|
|
3213
|
+
*
|
|
3214
|
+
* // Get pincodes for different country
|
|
3215
|
+
* const { data: usPincodes, error: usError } = await sdk.helpers.listCountryPincodes({
|
|
3216
|
+
* country_iso_code: "US"
|
|
3217
|
+
* });
|
|
3218
|
+
*
|
|
3219
|
+
* if (usError) {
|
|
3220
|
+
* console.error("Failed to get US pincodes:", usError);
|
|
3221
|
+
* return;
|
|
3222
|
+
* }
|
|
3223
|
+
*
|
|
3224
|
+
* console.log("US Pincodes:", usPincodes.pincodes?.map(p => p.pincode).join(", "));
|
|
3225
|
+
* ```
|
|
3226
|
+
*/
|
|
3227
|
+
async listCountryPincodes(pathParams, queryParams) {
|
|
3228
|
+
return this.executeRequest(() => this.client.GET("/common/countries/{country_iso_code}/pincodes", { params: {
|
|
3229
|
+
path: pathParams,
|
|
3230
|
+
query: queryParams
|
|
3231
|
+
} }));
|
|
3232
|
+
}
|
|
3233
|
+
};
|
|
3234
|
+
|
|
3235
|
+
//#endregion
|
|
3236
|
+
//#region src/lib/public/helper.ts
|
|
3237
|
+
/**
|
|
3238
|
+
* Client for interacting with helper endpoints
|
|
3239
|
+
*/
|
|
3240
|
+
var PublicHelpersClient = class extends BaseHelpersClient {};
|
|
3241
|
+
|
|
3242
|
+
//#endregion
|
|
3243
|
+
//#region src/lib/helper.ts
|
|
3244
|
+
/**
|
|
3245
|
+
* Client for interacting with helper endpoints
|
|
3246
|
+
*/
|
|
3247
|
+
var HelpersClient = class extends BaseHelpersClient {
|
|
3248
|
+
constructor(config) {
|
|
3249
|
+
super(config);
|
|
3250
|
+
attachSessionAuth(this, config.sessionManager);
|
|
3251
|
+
}
|
|
3252
|
+
};
|
|
3253
|
+
|
|
3254
|
+
//#endregion
|
|
3255
|
+
//#region src/lib/customer.ts
|
|
3256
|
+
/**
|
|
3257
|
+
* Client for interacting with customer endpoints
|
|
3258
|
+
*/
|
|
3259
|
+
var CustomerClient = class extends SessionStorefrontAPIClient {
|
|
3260
|
+
async listAddresses(pathParamsOrQuery, queryParams) {
|
|
3261
|
+
const hasPathParams = queryParams !== void 0 || !!pathParamsOrQuery && typeof pathParamsOrQuery === "object" && "customer_id" in pathParamsOrQuery;
|
|
3262
|
+
const pathParams = hasPathParams ? pathParamsOrQuery : {};
|
|
3263
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3264
|
+
const resolvedQueryParams = hasPathParams ? queryParams : pathParamsOrQuery;
|
|
3265
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/addresses", { params: {
|
|
3266
|
+
path: resolvedPathParams,
|
|
3267
|
+
query: resolvedQueryParams
|
|
3268
|
+
} }));
|
|
3269
|
+
}
|
|
3270
|
+
async createAddress(pathParamsOrBody, maybeBody) {
|
|
3271
|
+
const pathParams = maybeBody ? pathParamsOrBody : {};
|
|
3272
|
+
const body = maybeBody ?? pathParamsOrBody;
|
|
3273
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3274
|
+
return this.executeRequest(() => this.client.POST("/customers/{customer_id}/addresses", {
|
|
3275
|
+
params: { path: resolvedPathParams },
|
|
3276
|
+
body
|
|
3277
|
+
}));
|
|
3278
|
+
}
|
|
3279
|
+
async getAddress(pathParams) {
|
|
3280
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3281
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/addresses/{address_id}", { params: { path: resolvedPathParams } }));
|
|
3282
|
+
}
|
|
3283
|
+
async updateAddress(pathParams, body) {
|
|
3284
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3285
|
+
return this.executeRequest(() => this.client.PUT("/customers/{customer_id}/addresses/{address_id}", {
|
|
3286
|
+
params: { path: resolvedPathParams },
|
|
3287
|
+
body
|
|
3288
|
+
}));
|
|
3289
|
+
}
|
|
3290
|
+
async deleteAddress(pathParams) {
|
|
3291
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3292
|
+
return this.executeRequest(() => this.client.DELETE("/customers/{customer_id}/addresses/{address_id}", { params: { path: resolvedPathParams } }));
|
|
3293
|
+
}
|
|
3294
|
+
async getLoyaltyDetails(pathParams = {}) {
|
|
3295
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3296
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/loyalty", { params: { path: resolvedPathParams } }));
|
|
3297
|
+
}
|
|
3298
|
+
async listLoyaltyPointsActivity(pathParamsOrQuery, queryParams) {
|
|
3299
|
+
const hasPathParams = queryParams !== void 0 || !!pathParamsOrQuery && typeof pathParamsOrQuery === "object" && "customer_id" in pathParamsOrQuery;
|
|
3300
|
+
const pathParams = hasPathParams ? pathParamsOrQuery : {};
|
|
3301
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3302
|
+
const resolvedQueryParams = hasPathParams ? queryParams : pathParamsOrQuery;
|
|
3303
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/loyalty-points-activity", { params: {
|
|
3304
|
+
path: resolvedPathParams,
|
|
3305
|
+
query: resolvedQueryParams
|
|
3306
|
+
} }));
|
|
3307
|
+
}
|
|
3308
|
+
async listCustomerReviews(pathParams = {}) {
|
|
3309
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3310
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/reviews", { params: { path: resolvedPathParams } }));
|
|
3311
|
+
}
|
|
3312
|
+
async listSavedPaymentMethods(pathParams = {}, queryParams) {
|
|
3313
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3314
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/payment-methods", { params: {
|
|
3315
|
+
path: resolvedPathParams,
|
|
3316
|
+
query: queryParams
|
|
3317
|
+
} }));
|
|
3318
|
+
}
|
|
3319
|
+
async listCustomerCards(pathParams = {}) {
|
|
3320
|
+
const resolvedPathParams = await this.resolveCustomerPathParams(pathParams);
|
|
3321
|
+
return this.executeRequest(() => this.client.GET("/customers/{customer_id}/cards", { params: { path: resolvedPathParams } }));
|
|
3322
|
+
}
|
|
3323
|
+
};
|
|
3324
|
+
|
|
3325
|
+
//#endregion
|
|
3326
|
+
//#region src/lib/shared/store-config.ts
|
|
3327
|
+
/**
|
|
3328
|
+
* Client for interacting with store config endpoints
|
|
3329
|
+
*/
|
|
3330
|
+
var BaseStoreConfigClient = class extends StorefrontAPIClientBase {
|
|
3331
|
+
/**
|
|
3332
|
+
* Check store existence
|
|
3333
|
+
*
|
|
3334
|
+
* @description Checks whether a store with the configured store ID exists.
|
|
3335
|
+
* Returns `success: true` if the store exists, `false` otherwise.
|
|
3336
|
+
*
|
|
3337
|
+
* @returns Promise with store existence check result
|
|
3338
|
+
* @example
|
|
3339
|
+
* ```typescript
|
|
3340
|
+
* const { data, error } = await sdk.store.checkStore();
|
|
3341
|
+
*
|
|
3342
|
+
* if (error) {
|
|
3343
|
+
* console.error("Failed to check store:", error.message);
|
|
3344
|
+
* } else {
|
|
3345
|
+
* console.log("Store exists:", data.success);
|
|
3346
|
+
* }
|
|
3347
|
+
* ```
|
|
3348
|
+
*/
|
|
3349
|
+
async checkStore() {
|
|
3350
|
+
return this.executeRequest(() => this.client.GET("/store/check"));
|
|
3351
|
+
}
|
|
3352
|
+
/**
|
|
3353
|
+
* Get store config
|
|
3354
|
+
*
|
|
3355
|
+
* @returns Promise with store configuration data
|
|
3356
|
+
*
|
|
3357
|
+
* @example
|
|
3358
|
+
* ```typescript
|
|
3359
|
+
* const { data, error } = await sdk.store.getStoreConfig();
|
|
3360
|
+
*
|
|
3361
|
+
* if (error) {
|
|
3362
|
+
* console.error('Failed to get store config:', error.message);
|
|
3363
|
+
* return;
|
|
3364
|
+
* }
|
|
3365
|
+
*
|
|
3366
|
+
* // Access store configuration data
|
|
3367
|
+
* const storeConfig = data.store_config;
|
|
3368
|
+
* console.log('Store brand:', storeConfig.brand.name);
|
|
3369
|
+
* console.log('Currency:', storeConfig.currency.code);
|
|
3370
|
+
* console.log('KYC enabled:', storeConfig.is_kyc_enabled);
|
|
3371
|
+
* console.log('Customer groups enabled:', storeConfig.is_customer_group_enabled);
|
|
3372
|
+
* ```
|
|
3373
|
+
*/
|
|
3374
|
+
async getStoreConfig() {
|
|
3375
|
+
return this.executeRequest(() => this.client.GET("/store/config"));
|
|
3376
|
+
}
|
|
3377
|
+
};
|
|
3378
|
+
|
|
3379
|
+
//#endregion
|
|
3380
|
+
//#region src/lib/public/store-config.ts
|
|
3381
|
+
/**
|
|
3382
|
+
* Client for interacting with store config endpoints
|
|
3383
|
+
*/
|
|
3384
|
+
var PublicStoreConfigClient = class extends BaseStoreConfigClient {};
|
|
3385
|
+
|
|
3386
|
+
//#endregion
|
|
3387
|
+
//#region src/lib/store-config.ts
|
|
3388
|
+
/**
|
|
3389
|
+
* Client for interacting with store config endpoints
|
|
3390
|
+
*/
|
|
3391
|
+
var StoreConfigClient = class extends BaseStoreConfigClient {
|
|
3392
|
+
constructor(config) {
|
|
3393
|
+
super(config);
|
|
3394
|
+
attachSessionAuth(this, config.sessionManager);
|
|
3395
|
+
}
|
|
3396
|
+
};
|
|
3397
|
+
|
|
3398
|
+
//#endregion
|
|
3399
|
+
//#region src/lib/storage/token-storage.ts
|
|
3400
|
+
/**
|
|
3401
|
+
* Simple in-memory token storage implementation
|
|
3402
|
+
*/
|
|
3403
|
+
var MemoryTokenStorage = class {
|
|
3404
|
+
accessToken = null;
|
|
3405
|
+
refreshToken = null;
|
|
3406
|
+
async getAccessToken() {
|
|
3407
|
+
return this.accessToken;
|
|
3408
|
+
}
|
|
3409
|
+
async setAccessToken(token) {
|
|
3410
|
+
this.accessToken = token;
|
|
3411
|
+
}
|
|
3412
|
+
async getRefreshToken() {
|
|
3413
|
+
return this.refreshToken;
|
|
3414
|
+
}
|
|
3415
|
+
async setRefreshToken(token) {
|
|
3416
|
+
this.refreshToken = token;
|
|
3417
|
+
}
|
|
3418
|
+
async clearTokens() {
|
|
3419
|
+
this.accessToken = null;
|
|
3420
|
+
this.refreshToken = null;
|
|
3421
|
+
}
|
|
3422
|
+
};
|
|
3423
|
+
/**
|
|
3424
|
+
* Browser localStorage token storage implementation
|
|
3425
|
+
*/
|
|
3426
|
+
var BrowserTokenStorage = class {
|
|
3427
|
+
accessTokenKey;
|
|
3428
|
+
refreshTokenKey;
|
|
3429
|
+
constructor(prefix = "storefront_") {
|
|
3430
|
+
this.accessTokenKey = `${prefix}access_token`;
|
|
3431
|
+
this.refreshTokenKey = `${prefix}refresh_token`;
|
|
3432
|
+
}
|
|
3433
|
+
async getAccessToken() {
|
|
3434
|
+
if (typeof localStorage === "undefined") return null;
|
|
3435
|
+
return localStorage.getItem(this.accessTokenKey);
|
|
3436
|
+
}
|
|
3437
|
+
async setAccessToken(token) {
|
|
3438
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(this.accessTokenKey, token);
|
|
3439
|
+
}
|
|
3440
|
+
async getRefreshToken() {
|
|
3441
|
+
if (typeof localStorage === "undefined") return null;
|
|
3442
|
+
return localStorage.getItem(this.refreshTokenKey);
|
|
3443
|
+
}
|
|
3444
|
+
async setRefreshToken(token) {
|
|
3445
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(this.refreshTokenKey, token);
|
|
3446
|
+
}
|
|
3447
|
+
async clearTokens() {
|
|
3448
|
+
if (typeof localStorage !== "undefined") {
|
|
3449
|
+
localStorage.removeItem(this.accessTokenKey);
|
|
3450
|
+
localStorage.removeItem(this.refreshTokenKey);
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
};
|
|
3454
|
+
/**
|
|
3455
|
+
* Cookie-based token storage implementation
|
|
3456
|
+
*/
|
|
3457
|
+
var CookieTokenStorage = class {
|
|
3458
|
+
accessTokenKey;
|
|
3459
|
+
refreshTokenKey;
|
|
3460
|
+
options;
|
|
3461
|
+
constructor(options = {}) {
|
|
3462
|
+
const prefix = options.prefix || "storefront_";
|
|
3463
|
+
this.accessTokenKey = `${prefix}access_token`;
|
|
3464
|
+
this.refreshTokenKey = `${prefix}refresh_token`;
|
|
3465
|
+
this.options = {
|
|
3466
|
+
maxAge: options.maxAge || 10080 * 60,
|
|
3467
|
+
path: options.path || "/",
|
|
3468
|
+
domain: options.domain,
|
|
3469
|
+
secure: options.secure ?? (typeof window !== "undefined" && window.location?.protocol === "https:"),
|
|
3470
|
+
sameSite: options.sameSite || "Lax",
|
|
3471
|
+
httpOnly: false
|
|
3472
|
+
};
|
|
3473
|
+
}
|
|
3474
|
+
async getAccessToken() {
|
|
3475
|
+
return this.getCookie(this.accessTokenKey);
|
|
3476
|
+
}
|
|
3477
|
+
async setAccessToken(token) {
|
|
3478
|
+
this.setCookie(this.accessTokenKey, token);
|
|
3479
|
+
}
|
|
3480
|
+
async getRefreshToken() {
|
|
3481
|
+
return this.getCookie(this.refreshTokenKey);
|
|
3482
|
+
}
|
|
3483
|
+
async setRefreshToken(token) {
|
|
3484
|
+
this.setCookie(this.refreshTokenKey, token);
|
|
3485
|
+
}
|
|
3486
|
+
async clearTokens() {
|
|
3487
|
+
this.deleteCookie(this.accessTokenKey);
|
|
3488
|
+
this.deleteCookie(this.refreshTokenKey);
|
|
3489
|
+
}
|
|
3490
|
+
getCookie(name) {
|
|
3491
|
+
if (typeof document === "undefined") return null;
|
|
3492
|
+
const parts = `; ${document.cookie}`.split(`; ${name}=`);
|
|
3493
|
+
if (parts.length === 2) {
|
|
3494
|
+
const cookieValue = parts.pop()?.split(";").shift();
|
|
3495
|
+
return cookieValue ? decodeURIComponent(cookieValue) : null;
|
|
3496
|
+
}
|
|
3497
|
+
return null;
|
|
3498
|
+
}
|
|
3499
|
+
setCookie(name, value) {
|
|
3500
|
+
if (typeof document === "undefined") return;
|
|
3501
|
+
let cookieString = `${name}=${encodeURIComponent(value)}`;
|
|
3502
|
+
if (this.options.maxAge) cookieString += `; Max-Age=${this.options.maxAge}`;
|
|
3503
|
+
if (this.options.path) cookieString += `; Path=${this.options.path}`;
|
|
3504
|
+
if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
|
|
3505
|
+
if (this.options.secure) cookieString += `; Secure`;
|
|
3506
|
+
if (this.options.sameSite) cookieString += `; SameSite=${this.options.sameSite}`;
|
|
3507
|
+
document.cookie = cookieString;
|
|
3508
|
+
}
|
|
3509
|
+
deleteCookie(name) {
|
|
3510
|
+
if (typeof document === "undefined") return;
|
|
3511
|
+
let cookieString = `${name}=; Max-Age=0`;
|
|
3512
|
+
if (this.options.path) cookieString += `; Path=${this.options.path}`;
|
|
3513
|
+
if (this.options.domain) cookieString += `; Domain=${this.options.domain}`;
|
|
3514
|
+
document.cookie = cookieString;
|
|
3515
|
+
}
|
|
3516
|
+
};
|
|
3517
|
+
|
|
3518
|
+
//#endregion
|
|
3519
|
+
//#region src/lib/session/jwt-utils.ts
|
|
3520
|
+
/**
|
|
3521
|
+
* Decode a JWT token payload without signature verification.
|
|
3522
|
+
* This is a lightweight replacement for jose's decodeJwt.
|
|
3523
|
+
*
|
|
3524
|
+
* @param token - The JWT token to decode
|
|
3525
|
+
* @returns The decoded payload
|
|
3526
|
+
* @throws Error if the token is malformed
|
|
3527
|
+
*/
|
|
3528
|
+
function decodeJwt(token) {
|
|
3529
|
+
if (typeof token !== "string") throw new Error("Invalid token: must be a string");
|
|
3530
|
+
const parts = token.split(".");
|
|
3531
|
+
if (parts.length !== 3) throw new Error("Invalid token: must have 3 parts");
|
|
3532
|
+
const base64Url = parts[1];
|
|
3533
|
+
if (!base64Url) throw new Error("Invalid token: missing payload");
|
|
3534
|
+
let base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
3535
|
+
const padding = base64.length % 4;
|
|
3536
|
+
if (padding) base64 += "=".repeat(4 - padding);
|
|
3537
|
+
const binaryStr = atob(base64);
|
|
3538
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
3539
|
+
for (let i = 0; i < binaryStr.length; i++) bytes[i] = binaryStr.charCodeAt(i);
|
|
3540
|
+
const payload = JSON.parse(new TextDecoder().decode(bytes));
|
|
3541
|
+
if (typeof payload !== "object" || payload === null) throw new Error("Invalid token: payload must be an object");
|
|
3542
|
+
return payload;
|
|
3543
|
+
}
|
|
3544
|
+
/**
|
|
3545
|
+
* Decode and extract user information from a JWT token
|
|
3546
|
+
*
|
|
3547
|
+
* @param token - The JWT token to decode
|
|
3548
|
+
* @returns User information or null if token is invalid
|
|
3549
|
+
*/
|
|
3550
|
+
function extractUserInfoFromToken(token) {
|
|
3551
|
+
try {
|
|
3552
|
+
const payload = decodeJwt(token);
|
|
3553
|
+
return {
|
|
3554
|
+
id: payload.ulid,
|
|
3555
|
+
email: payload.email,
|
|
3556
|
+
phone: payload.phone,
|
|
3557
|
+
username: payload.username,
|
|
3558
|
+
firstName: payload.first_name,
|
|
3559
|
+
lastName: payload.last_name,
|
|
3560
|
+
storeId: payload.store_id,
|
|
3561
|
+
isLoggedIn: payload.is_logged_in,
|
|
3562
|
+
isAnonymous: payload.is_anonymous,
|
|
3563
|
+
customerId: payload.customer_id,
|
|
3564
|
+
customerGroupId: payload.customer_group_id,
|
|
3565
|
+
anonymousId: payload.anonymous_id,
|
|
3566
|
+
channel: payload.channel,
|
|
3567
|
+
tokenExpiry: /* @__PURE__ */ new Date(payload.exp * 1e3),
|
|
3568
|
+
tokenIssuedAt: /* @__PURE__ */ new Date(payload.iat * 1e3)
|
|
3569
|
+
};
|
|
3570
|
+
} catch (error) {
|
|
3571
|
+
console.warn("Failed to decode JWT token:", error);
|
|
3572
|
+
return null;
|
|
3573
|
+
}
|
|
3574
|
+
}
|
|
3575
|
+
/**
|
|
3576
|
+
* Check if a JWT token is expired
|
|
3577
|
+
*
|
|
3578
|
+
* @param token - The JWT token to check
|
|
3579
|
+
* @param bufferSeconds - Buffer time in seconds (default: 30)
|
|
3580
|
+
* @returns True if token is expired or will expire within buffer time
|
|
3581
|
+
*/
|
|
3582
|
+
function isTokenExpired(token, bufferSeconds = 30) {
|
|
3583
|
+
try {
|
|
3584
|
+
const payload = decodeJwt(token);
|
|
3585
|
+
if (!payload.exp) return true;
|
|
3586
|
+
return Math.floor(Date.now() / 1e3) >= payload.exp - bufferSeconds;
|
|
3587
|
+
} catch (error) {
|
|
3588
|
+
console.warn("Failed to decode JWT token:", error);
|
|
3589
|
+
return true;
|
|
3590
|
+
}
|
|
3591
|
+
}
|
|
3592
|
+
/**
|
|
3593
|
+
* Get the user ID from a JWT token
|
|
3594
|
+
*
|
|
3595
|
+
* @param token - The JWT token
|
|
3596
|
+
* @returns User ID (ulid) or null if token is invalid
|
|
3597
|
+
*/
|
|
3598
|
+
function getUserIdFromToken(token) {
|
|
3599
|
+
return extractUserInfoFromToken(token)?.id || null;
|
|
3600
|
+
}
|
|
3601
|
+
/**
|
|
3602
|
+
* Check if user is logged in based on JWT token
|
|
3603
|
+
*
|
|
3604
|
+
* @param token - The JWT token
|
|
3605
|
+
* @returns True if user is logged in, false otherwise
|
|
3606
|
+
*/
|
|
3607
|
+
function isUserLoggedIn(token) {
|
|
3608
|
+
return extractUserInfoFromToken(token)?.isLoggedIn || false;
|
|
3609
|
+
}
|
|
3610
|
+
/**
|
|
3611
|
+
* Check if user is anonymous based on JWT token
|
|
3612
|
+
*
|
|
3613
|
+
* @param token - The JWT token
|
|
3614
|
+
* @returns True if user is anonymous, false otherwise
|
|
3615
|
+
*/
|
|
3616
|
+
function isUserAnonymous(token) {
|
|
3617
|
+
return extractUserInfoFromToken(token)?.isAnonymous ?? true;
|
|
3618
|
+
}
|
|
3619
|
+
|
|
3620
|
+
//#endregion
|
|
3621
|
+
//#region src/types/auth-operation-metadata.ts
|
|
3622
|
+
const API_KEY_ONLY_OPERATIONS = [
|
|
3623
|
+
{
|
|
3624
|
+
method: "POST",
|
|
3625
|
+
path: "/auth/anonymous"
|
|
3626
|
+
},
|
|
3627
|
+
{
|
|
3628
|
+
method: "GET",
|
|
3629
|
+
path: "/common/countries"
|
|
3630
|
+
},
|
|
3631
|
+
{
|
|
3632
|
+
method: "GET",
|
|
3633
|
+
path: "/common/countries/{country_iso_code}/pincodes"
|
|
3634
|
+
},
|
|
3635
|
+
{
|
|
3636
|
+
method: "GET",
|
|
3637
|
+
path: "/common/countries/{country_iso_code}/states"
|
|
3638
|
+
},
|
|
3639
|
+
{
|
|
3640
|
+
method: "GET",
|
|
3641
|
+
path: "/store/check"
|
|
3642
|
+
},
|
|
3643
|
+
{
|
|
3644
|
+
method: "GET",
|
|
3645
|
+
path: "/store/config"
|
|
3646
|
+
},
|
|
3647
|
+
{
|
|
3648
|
+
method: "GET",
|
|
3649
|
+
path: "/store/kyc-document"
|
|
3650
|
+
},
|
|
3651
|
+
{
|
|
3652
|
+
method: "GET",
|
|
3653
|
+
path: "/store/sellers/{id}"
|
|
3654
|
+
},
|
|
3655
|
+
{
|
|
3656
|
+
method: "GET",
|
|
3657
|
+
path: "/store/sellers/{id}/reviews"
|
|
3658
|
+
}
|
|
3659
|
+
];
|
|
3660
|
+
|
|
3661
|
+
//#endregion
|
|
3662
|
+
//#region src/lib/session/auth-utils.ts
|
|
3663
|
+
const TOKEN_RETURNING_OPERATIONS = [
|
|
3664
|
+
{
|
|
3665
|
+
method: "POST",
|
|
3666
|
+
path: "/auth/change-password"
|
|
3667
|
+
},
|
|
3668
|
+
{
|
|
3669
|
+
method: "POST",
|
|
3670
|
+
path: "/auth/login/password"
|
|
3671
|
+
},
|
|
3672
|
+
{
|
|
3673
|
+
method: "POST",
|
|
3674
|
+
path: "/auth/reset-password"
|
|
3675
|
+
},
|
|
3676
|
+
{
|
|
3677
|
+
method: "POST",
|
|
3678
|
+
path: "/auth/verify-otp"
|
|
3679
|
+
},
|
|
3680
|
+
{
|
|
3681
|
+
method: "POST",
|
|
3682
|
+
path: "/auth/refresh-token"
|
|
3683
|
+
},
|
|
3684
|
+
{
|
|
3685
|
+
method: "POST",
|
|
3686
|
+
path: "/auth/logout"
|
|
3687
|
+
}
|
|
3688
|
+
];
|
|
3689
|
+
const ANONYMOUS_AUTH_OPERATION = {
|
|
3690
|
+
method: "POST",
|
|
3691
|
+
path: "/auth/anonymous"
|
|
3692
|
+
};
|
|
3693
|
+
function normalizeMethod(method) {
|
|
3694
|
+
return method.toUpperCase();
|
|
3695
|
+
}
|
|
3696
|
+
function normalizePathname(pathname) {
|
|
3697
|
+
let normalizedPathname = pathname;
|
|
3698
|
+
const storefrontMarkerIndex = normalizedPathname.indexOf("/storefront");
|
|
3699
|
+
if (storefrontMarkerIndex !== -1) normalizedPathname = normalizedPathname.slice(storefrontMarkerIndex + 11) || "/";
|
|
3700
|
+
if (normalizedPathname.length > 1 && normalizedPathname.endsWith("/")) return normalizedPathname.slice(0, -1);
|
|
3701
|
+
return normalizedPathname;
|
|
3702
|
+
}
|
|
3703
|
+
function matchesPathTemplate(pathTemplate, pathname) {
|
|
3704
|
+
const normalizedTemplate = normalizePathname(pathTemplate);
|
|
3705
|
+
const normalizedPathname = normalizePathname(pathname);
|
|
3706
|
+
const templateSegments = normalizedTemplate.split("/").filter(Boolean);
|
|
3707
|
+
const pathSegments = normalizedPathname.split("/").filter(Boolean);
|
|
3708
|
+
if (templateSegments.length !== pathSegments.length) return false;
|
|
3709
|
+
return templateSegments.every((templateSegment, index) => {
|
|
3710
|
+
if (templateSegment.startsWith("{") && templateSegment.endsWith("}")) return true;
|
|
3711
|
+
return templateSegment === pathSegments[index];
|
|
3712
|
+
});
|
|
3713
|
+
}
|
|
3714
|
+
function matchesOperation(method, pathname, operation) {
|
|
3715
|
+
return normalizeMethod(method) === operation.method && matchesPathTemplate(operation.path, pathname);
|
|
3716
|
+
}
|
|
3717
|
+
function matchesOperationList(method, pathname, operations) {
|
|
3718
|
+
return operations.some((operation) => matchesOperation(method, pathname, operation));
|
|
3719
|
+
}
|
|
3720
|
+
/**
|
|
3721
|
+
* Check if a method+path pair is the anonymous auth operation.
|
|
3722
|
+
*/
|
|
3723
|
+
function isAnonymousAuthOperation(method, pathname) {
|
|
3724
|
+
return matchesOperation(method, pathname, ANONYMOUS_AUTH_OPERATION);
|
|
3725
|
+
}
|
|
3726
|
+
/**
|
|
3727
|
+
* Check if a method+path pair requires API key only authentication.
|
|
3728
|
+
*/
|
|
3729
|
+
function isApiKeyOnlyOperation(method, pathname) {
|
|
3730
|
+
return matchesOperationList(method, pathname, API_KEY_ONLY_OPERATIONS);
|
|
3731
|
+
}
|
|
3732
|
+
/**
|
|
3733
|
+
* Check if a method+path pair returns tokens in a successful response.
|
|
3734
|
+
*/
|
|
3735
|
+
function isTokenReturningOperation(method, pathname) {
|
|
3736
|
+
return matchesOperationList(method, pathname, TOKEN_RETURNING_OPERATIONS);
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
//#endregion
|
|
3740
|
+
//#region src/lib/session/manager.ts
|
|
3741
|
+
/**
|
|
3742
|
+
* Internal per-SDK session controller.
|
|
3743
|
+
*
|
|
3744
|
+
* A single instance is shared by all API clients created from the same
|
|
3745
|
+
* `SessionStorefrontSDK`. This keeps refresh locks, token assessment, and session
|
|
3746
|
+
* bootstrap logic coordinated in one place while preserving optional manual
|
|
3747
|
+
* token management when `tokenStorage` is not provided.
|
|
3748
|
+
*/
|
|
3749
|
+
var StorefrontSessionManager = class {
|
|
3750
|
+
tokenStorage;
|
|
3751
|
+
onTokensUpdated;
|
|
3752
|
+
onTokensCleared;
|
|
3753
|
+
baseUrl;
|
|
3754
|
+
refreshTokenFn;
|
|
3755
|
+
apiKey;
|
|
3756
|
+
accessToken;
|
|
3757
|
+
refreshToken;
|
|
3758
|
+
initializationPromise = null;
|
|
3759
|
+
refreshPromise = null;
|
|
3760
|
+
bootstrapPromise = null;
|
|
3761
|
+
hasAssessedTokens = false;
|
|
3762
|
+
constructor(options) {
|
|
3763
|
+
this.tokenStorage = options.tokenStorage;
|
|
3764
|
+
this.baseUrl = options.baseUrl;
|
|
3765
|
+
this.apiKey = options.apiKey;
|
|
3766
|
+
this.onTokensUpdated = options.onTokensUpdated;
|
|
3767
|
+
this.onTokensCleared = options.onTokensCleared;
|
|
3768
|
+
this.accessToken = options.accessToken ?? null;
|
|
3769
|
+
this.refreshToken = options.refreshToken ?? null;
|
|
3770
|
+
this.refreshTokenFn = options.refreshTokenFn;
|
|
3771
|
+
if (this.tokenStorage && this.accessToken) this.initializationPromise = this.initializeManagedTokens(this.accessToken, this.refreshToken);
|
|
3772
|
+
}
|
|
3773
|
+
/**
|
|
3774
|
+
* Update the API key used by session bootstrap and refresh flows.
|
|
3775
|
+
*/
|
|
3776
|
+
setApiKey(apiKey) {
|
|
3777
|
+
this.apiKey = apiKey;
|
|
3627
3778
|
}
|
|
3628
3779
|
/**
|
|
3629
|
-
*
|
|
3630
|
-
*
|
|
3631
|
-
* @param pathParams - Path parameters
|
|
3632
|
-
* @returns Promise with states
|
|
3633
|
-
*
|
|
3634
|
-
* @example
|
|
3635
|
-
* ```typescript
|
|
3636
|
-
* const { data, error } = await sdk.helpers.listCountryStates({
|
|
3637
|
-
* country_iso_code: "IN"
|
|
3638
|
-
* });
|
|
3639
|
-
*
|
|
3640
|
-
* if (error) {
|
|
3641
|
-
* console.error("Failed to get states:", error);
|
|
3642
|
-
* return;
|
|
3643
|
-
* }
|
|
3644
|
-
*
|
|
3645
|
-
* console.log("States found:", data.states?.length || 0);
|
|
3646
|
-
*
|
|
3647
|
-
* data.states?.forEach(state => {
|
|
3648
|
-
* console.log(`State: ${state.name} (${state.iso_code})`);
|
|
3649
|
-
* });
|
|
3650
|
-
*
|
|
3651
|
-
* // Get states for different country
|
|
3652
|
-
* const { data: usStates, error: usError } = await sdk.helpers.listCountryStates({
|
|
3653
|
-
* country_iso_code: "US"
|
|
3654
|
-
* });
|
|
3655
|
-
*
|
|
3656
|
-
* if (usError) {
|
|
3657
|
-
* console.error("Failed to get US states:", usError);
|
|
3658
|
-
* return;
|
|
3659
|
-
* }
|
|
3660
|
-
*
|
|
3661
|
-
* console.log("US States:", usStates.states?.map(s => s.name).join(", "));
|
|
3662
|
-
* ```
|
|
3780
|
+
* Remove the API key used by session bootstrap and refresh flows.
|
|
3663
3781
|
*/
|
|
3664
|
-
|
|
3665
|
-
|
|
3782
|
+
clearApiKey() {
|
|
3783
|
+
this.apiKey = void 0;
|
|
3666
3784
|
}
|
|
3667
3785
|
/**
|
|
3668
|
-
*
|
|
3669
|
-
*
|
|
3670
|
-
* @param pathParams - Path parameters
|
|
3671
|
-
* @returns Promise with pincodes
|
|
3672
|
-
*
|
|
3673
|
-
* @example
|
|
3674
|
-
* ```typescript
|
|
3675
|
-
* const { data, error } = await sdk.helpers.listCountryPincodes({
|
|
3676
|
-
* country_iso_code: "IN"
|
|
3677
|
-
* });
|
|
3678
|
-
*
|
|
3679
|
-
* if (error) {
|
|
3680
|
-
* console.error("Failed to get pincodes:", error);
|
|
3681
|
-
* return;
|
|
3682
|
-
* }
|
|
3683
|
-
*
|
|
3684
|
-
* console.log("Pincodes found:", data.pincodes?.length || 0);
|
|
3786
|
+
* Create the auth middleware used by each API client.
|
|
3685
3787
|
*
|
|
3686
|
-
*
|
|
3687
|
-
*
|
|
3688
|
-
* });
|
|
3689
|
-
*
|
|
3690
|
-
* // Get pincodes for different country
|
|
3691
|
-
* const { data: usPincodes, error: usError } = await sdk.helpers.listCountryPincodes({
|
|
3692
|
-
* country_iso_code: "US"
|
|
3693
|
-
* });
|
|
3694
|
-
*
|
|
3695
|
-
* if (usError) {
|
|
3696
|
-
* console.error("Failed to get US pincodes:", usError);
|
|
3697
|
-
* return;
|
|
3698
|
-
* }
|
|
3699
|
-
*
|
|
3700
|
-
* console.log("US Pincodes:", usPincodes.pincodes?.map(p => p.pincode).join(", "));
|
|
3701
|
-
* ```
|
|
3788
|
+
* The returned middleware shares the same session state and refresh locking
|
|
3789
|
+
* across all clients attached to a single `SessionStorefrontSDK` instance.
|
|
3702
3790
|
*/
|
|
3703
|
-
|
|
3704
|
-
return
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
}
|
|
3791
|
+
createAuthMiddleware() {
|
|
3792
|
+
return {
|
|
3793
|
+
onRequest: async ({ request }) => this.handleRequest(request),
|
|
3794
|
+
onResponse: async ({ request, response }) => this.handleResponse(request, response)
|
|
3795
|
+
};
|
|
3708
3796
|
}
|
|
3709
|
-
};
|
|
3710
|
-
|
|
3711
|
-
//#endregion
|
|
3712
|
-
//#region src/lib/customer.ts
|
|
3713
|
-
/**
|
|
3714
|
-
* Client for interacting with customer endpoints
|
|
3715
|
-
*/
|
|
3716
|
-
var CustomerClient = class extends StorefrontAPIClient {
|
|
3717
3797
|
/**
|
|
3718
|
-
*
|
|
3719
|
-
*
|
|
3720
|
-
* @param pathParams - Path parameters
|
|
3721
|
-
* @returns Promise with addresses
|
|
3798
|
+
* Read the current authorization header without creating a new session.
|
|
3722
3799
|
*
|
|
3723
|
-
* @
|
|
3724
|
-
* ```typescript
|
|
3725
|
-
* const { data, error } = await sdk.customer.listAddresses({
|
|
3726
|
-
* user_id: "user_456"
|
|
3727
|
-
* });
|
|
3728
|
-
*
|
|
3729
|
-
* if (error) {
|
|
3730
|
-
* console.error("Failed to list addresses:", error);
|
|
3731
|
-
* return;
|
|
3732
|
-
* }
|
|
3733
|
-
*
|
|
3734
|
-
* console.log("Addresses:", data.addresses);
|
|
3735
|
-
* console.log("Pagination:", data.pagination);
|
|
3736
|
-
*
|
|
3737
|
-
* // With pagination
|
|
3738
|
-
* const { data: page2, error: page2Error } = await sdk.customer.listAddresses({
|
|
3739
|
-
* user_id: "user_456",
|
|
3740
|
-
* page: 2,
|
|
3741
|
-
* limit: 10
|
|
3742
|
-
* });
|
|
3743
|
-
* ```
|
|
3800
|
+
* @returns A `Bearer` header value, or an empty string when no token exists
|
|
3744
3801
|
*/
|
|
3745
|
-
async
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
query: queryParams
|
|
3749
|
-
} }));
|
|
3802
|
+
async getAuthorizationHeader() {
|
|
3803
|
+
const token = await this.peekAccessToken();
|
|
3804
|
+
return token ? `Bearer ${token}` : "";
|
|
3750
3805
|
}
|
|
3751
3806
|
/**
|
|
3752
|
-
*
|
|
3753
|
-
*
|
|
3754
|
-
* @param pathParams - Path parameters
|
|
3755
|
-
* @param body - Address creation body
|
|
3756
|
-
* @returns Promise with address details
|
|
3757
|
-
*
|
|
3758
|
-
* @example
|
|
3759
|
-
* ```typescript
|
|
3760
|
-
* const { data, error } = await sdk.customer.createAddress(
|
|
3761
|
-
* { user_id: "user_456" },
|
|
3762
|
-
* {
|
|
3763
|
-
* address_line1: "123 Main Street",
|
|
3764
|
-
* address_line2: "Apt 4B",
|
|
3765
|
-
* city: "New York",
|
|
3766
|
-
* state: "NY",
|
|
3767
|
-
* country: "US",
|
|
3768
|
-
* pincode: "10001",
|
|
3769
|
-
* is_default_billing: true,
|
|
3770
|
-
* is_default_shipping: false
|
|
3771
|
-
* }
|
|
3772
|
-
* );
|
|
3773
|
-
*
|
|
3774
|
-
* if (error) {
|
|
3775
|
-
* console.error("Failed to create address:", error);
|
|
3776
|
-
* return;
|
|
3777
|
-
* }
|
|
3807
|
+
* Persist new session tokens.
|
|
3778
3808
|
*
|
|
3779
|
-
*
|
|
3780
|
-
*
|
|
3809
|
+
* In managed mode, tokens are written to the configured token storage. In
|
|
3810
|
+
* manual mode, they are stored in memory for header injection and session
|
|
3811
|
+
* inspection.
|
|
3781
3812
|
*/
|
|
3782
|
-
async
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
|
|
3813
|
+
async setTokens(accessToken, refreshToken) {
|
|
3814
|
+
const previousTokens = await this.getCurrentTokenState();
|
|
3815
|
+
if (this.tokenStorage) {
|
|
3816
|
+
await this.awaitInitialization();
|
|
3817
|
+
await this.storeManagedTokens(accessToken, refreshToken ?? null);
|
|
3818
|
+
} else {
|
|
3819
|
+
this.accessToken = accessToken;
|
|
3820
|
+
if (refreshToken) {
|
|
3821
|
+
this.refreshToken = refreshToken;
|
|
3822
|
+
console.warn("Refresh token provided but automatic refresh is disabled because tokenStorage is not configured.");
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
const nextTokens = await this.getCurrentTokenState();
|
|
3826
|
+
this.notifyTokensUpdatedIfChanged(previousTokens, nextTokens);
|
|
3787
3827
|
}
|
|
3788
3828
|
/**
|
|
3789
|
-
*
|
|
3790
|
-
*
|
|
3791
|
-
* @param pathParams - Path parameters
|
|
3792
|
-
* @returns Promise with address details
|
|
3793
|
-
*
|
|
3794
|
-
* @example
|
|
3795
|
-
* ```typescript
|
|
3796
|
-
* const { data, error } = await sdk.customer.getAddress({
|
|
3797
|
-
* user_id: "user_456",
|
|
3798
|
-
* address_id: "addr_789"
|
|
3799
|
-
* });
|
|
3800
|
-
*
|
|
3801
|
-
* if (error) {
|
|
3802
|
-
* console.error("Failed to get address:", error);
|
|
3803
|
-
* return;
|
|
3804
|
-
* }
|
|
3805
|
-
*
|
|
3806
|
-
* console.log("Address details:", data.address);
|
|
3807
|
-
* ```
|
|
3829
|
+
* Clear all session tokens managed by this controller.
|
|
3808
3830
|
*/
|
|
3809
|
-
async
|
|
3810
|
-
|
|
3831
|
+
async clearTokens() {
|
|
3832
|
+
if (this.tokenStorage) {
|
|
3833
|
+
await this.awaitInitialization();
|
|
3834
|
+
await this.tokenStorage.clearTokens();
|
|
3835
|
+
} else {
|
|
3836
|
+
this.accessToken = null;
|
|
3837
|
+
this.refreshToken = null;
|
|
3838
|
+
}
|
|
3839
|
+
this.onTokensCleared?.();
|
|
3840
|
+
}
|
|
3841
|
+
/**
|
|
3842
|
+
* Clear all session tokens through the public session interface.
|
|
3843
|
+
*/
|
|
3844
|
+
async clear() {
|
|
3845
|
+
await this.clearTokens();
|
|
3846
|
+
}
|
|
3847
|
+
async peekAccessToken() {
|
|
3848
|
+
await this.awaitInitialization();
|
|
3849
|
+
if (this.tokenStorage) return this.tokenStorage.getAccessToken();
|
|
3850
|
+
return this.accessToken;
|
|
3851
|
+
}
|
|
3852
|
+
async peekRefreshToken() {
|
|
3853
|
+
await this.awaitInitialization();
|
|
3854
|
+
if (this.tokenStorage) return this.tokenStorage.getRefreshToken();
|
|
3855
|
+
return this.refreshToken;
|
|
3856
|
+
}
|
|
3857
|
+
async peekUserInfo() {
|
|
3858
|
+
const token = await this.peekAccessToken();
|
|
3859
|
+
if (!token) return null;
|
|
3860
|
+
return extractUserInfoFromToken(token);
|
|
3861
|
+
}
|
|
3862
|
+
async peekUserId() {
|
|
3863
|
+
const token = await this.peekAccessToken();
|
|
3864
|
+
if (!token) return null;
|
|
3865
|
+
return getUserIdFromToken(token);
|
|
3866
|
+
}
|
|
3867
|
+
async peekCustomerId() {
|
|
3868
|
+
return (await this.peekUserInfo())?.customerId ?? null;
|
|
3869
|
+
}
|
|
3870
|
+
async peekCustomerGroupId() {
|
|
3871
|
+
return (await this.peekUserInfo())?.customerGroupId ?? null;
|
|
3872
|
+
}
|
|
3873
|
+
async ensureAccessToken() {
|
|
3874
|
+
const token = await this.getOrCreateAccessToken();
|
|
3875
|
+
if (!token) throw new Error("No session available. Configure tokenStorage + apiKey for automatic session management, or call setTokens() to set tokens manually.");
|
|
3876
|
+
return token;
|
|
3877
|
+
}
|
|
3878
|
+
async ensureUserInfo() {
|
|
3879
|
+
const userInfo = extractUserInfoFromToken(await this.ensureAccessToken());
|
|
3880
|
+
if (!userInfo) throw new Error("Failed to extract user information from access token.");
|
|
3881
|
+
return userInfo;
|
|
3882
|
+
}
|
|
3883
|
+
async ensureUserId() {
|
|
3884
|
+
const userId = getUserIdFromToken(await this.ensureAccessToken());
|
|
3885
|
+
if (!userId) throw new Error("Failed to extract user ID from access token.");
|
|
3886
|
+
return userId;
|
|
3887
|
+
}
|
|
3888
|
+
async ensureCustomerId() {
|
|
3889
|
+
const userInfo = await this.ensureUserInfo();
|
|
3890
|
+
if (!userInfo.customerId) throw new Error("No customer_id available. User must be logged in (not anonymous) for this operation. Pass customer_id explicitly or log in first.");
|
|
3891
|
+
return userInfo.customerId;
|
|
3892
|
+
}
|
|
3893
|
+
async handleRequest(request) {
|
|
3894
|
+
const method = request.method;
|
|
3895
|
+
const pathname = getPathnameFromUrl(request.url);
|
|
3896
|
+
if (this.tokenStorage) await this.assessTokenStateOnce();
|
|
3897
|
+
if (isAnonymousAuthOperation(method, pathname)) return this.prepareAnonymousAuthRequest(request);
|
|
3898
|
+
if (isApiKeyOnlyOperation(method, pathname)) {
|
|
3899
|
+
this.applyApiKeyHeader(request);
|
|
3900
|
+
return request;
|
|
3901
|
+
}
|
|
3902
|
+
const accessToken = await this.getOrCreateAccessToken();
|
|
3903
|
+
if (accessToken) request.headers.set("Authorization", `Bearer ${accessToken}`);
|
|
3904
|
+
return request;
|
|
3905
|
+
}
|
|
3906
|
+
async handleResponse(request, response) {
|
|
3907
|
+
if (!this.tokenStorage) return response;
|
|
3908
|
+
const method = request.method;
|
|
3909
|
+
const pathname = getPathnameFromUrl(request.url);
|
|
3910
|
+
if (response.ok) {
|
|
3911
|
+
await this.captureTokensFromResponse(method, pathname, response);
|
|
3912
|
+
return response;
|
|
3913
|
+
}
|
|
3914
|
+
if (response.status === 401 && !isAnonymousAuthOperation(method, pathname) && !isApiKeyOnlyOperation(method, pathname)) {
|
|
3915
|
+
const currentToken = await this.peekAccessToken();
|
|
3916
|
+
if (currentToken && isTokenExpired(currentToken, 0)) try {
|
|
3917
|
+
await this.refreshTokens();
|
|
3918
|
+
const refreshedToken = await this.peekAccessToken();
|
|
3919
|
+
if (refreshedToken) {
|
|
3920
|
+
const retryRequest = request.clone();
|
|
3921
|
+
retryRequest.headers.set("Authorization", `Bearer ${refreshedToken}`);
|
|
3922
|
+
return fetch(retryRequest);
|
|
3923
|
+
}
|
|
3924
|
+
} catch (error) {
|
|
3925
|
+
console.warn("Token refresh failed on 401 response:", error);
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
return response;
|
|
3929
|
+
}
|
|
3930
|
+
async prepareAnonymousAuthRequest(request) {
|
|
3931
|
+
this.applyApiKeyHeader(request);
|
|
3932
|
+
const existingToken = await this.peekAccessToken();
|
|
3933
|
+
if (this.tokenStorage && existingToken && !isTokenExpired(existingToken) && isUserLoggedIn(existingToken)) return new Response(JSON.stringify({
|
|
3934
|
+
message: "Cannot create anonymous session while authenticated",
|
|
3935
|
+
success: false,
|
|
3936
|
+
code: "USER_ALREADY_AUTHENTICATED"
|
|
3937
|
+
}), {
|
|
3938
|
+
status: 400,
|
|
3939
|
+
headers: { "Content-Type": "application/json" }
|
|
3940
|
+
});
|
|
3941
|
+
if (existingToken) request.headers.set("Authorization", `Bearer ${existingToken}`);
|
|
3942
|
+
return request;
|
|
3943
|
+
}
|
|
3944
|
+
applyApiKeyHeader(request) {
|
|
3945
|
+
if (this.apiKey) request.headers.set("X-Api-Key", this.apiKey);
|
|
3946
|
+
}
|
|
3947
|
+
/**
|
|
3948
|
+
* Snapshot the effective token pair from storage (managed mode) or
|
|
3949
|
+
* in-memory fields (manual mode). Used before and after `setTokens()` to
|
|
3950
|
+
* detect whether the tokens actually changed.
|
|
3951
|
+
*/
|
|
3952
|
+
async getCurrentTokenState() {
|
|
3953
|
+
await this.awaitInitialization();
|
|
3954
|
+
if (this.tokenStorage) return {
|
|
3955
|
+
accessToken: await this.tokenStorage.getAccessToken(),
|
|
3956
|
+
refreshToken: await this.tokenStorage.getRefreshToken()
|
|
3957
|
+
};
|
|
3958
|
+
return {
|
|
3959
|
+
accessToken: this.accessToken,
|
|
3960
|
+
refreshToken: this.refreshToken
|
|
3961
|
+
};
|
|
3962
|
+
}
|
|
3963
|
+
/**
|
|
3964
|
+
* Fire `onTokensUpdated` only when the effective token pair differs from
|
|
3965
|
+
* the previous snapshot. This prevents duplicate notifications when
|
|
3966
|
+
* `setTokens()` is called with the same values already in storage.
|
|
3967
|
+
*/
|
|
3968
|
+
notifyTokensUpdatedIfChanged(previousTokens, nextTokens) {
|
|
3969
|
+
if (!this.onTokensUpdated || !nextTokens.accessToken) return;
|
|
3970
|
+
if (previousTokens.accessToken === nextTokens.accessToken && previousTokens.refreshToken === nextTokens.refreshToken) return;
|
|
3971
|
+
this.onTokensUpdated(nextTokens.accessToken, nextTokens.refreshToken ?? "");
|
|
3972
|
+
}
|
|
3973
|
+
/**
|
|
3974
|
+
* Internal token acquisition — returns null on failure instead of throwing.
|
|
3975
|
+
* Used by middleware so requests degrade gracefully.
|
|
3976
|
+
*/
|
|
3977
|
+
async getOrCreateAccessToken() {
|
|
3978
|
+
if (!this.tokenStorage) return this.peekAccessToken();
|
|
3979
|
+
await this.awaitInitialization();
|
|
3980
|
+
await this.assessTokenStateOnce();
|
|
3981
|
+
let accessToken = await this.tokenStorage.getAccessToken();
|
|
3982
|
+
if (!accessToken) accessToken = await this.bootstrapAnonymousSession();
|
|
3983
|
+
if (accessToken && isTokenExpired(accessToken)) try {
|
|
3984
|
+
await this.refreshTokens();
|
|
3985
|
+
accessToken = await this.tokenStorage.getAccessToken();
|
|
3986
|
+
} catch {
|
|
3987
|
+
accessToken = await this.tokenStorage.getAccessToken();
|
|
3988
|
+
}
|
|
3989
|
+
return accessToken;
|
|
3990
|
+
}
|
|
3991
|
+
async initializeManagedTokens(accessToken, refreshToken) {
|
|
3992
|
+
try {
|
|
3993
|
+
await this.storeManagedTokens(accessToken, refreshToken);
|
|
3994
|
+
} catch (error) {
|
|
3995
|
+
console.warn("Failed to initialize tokens in storage:", error);
|
|
3996
|
+
} finally {
|
|
3997
|
+
this.accessToken = null;
|
|
3998
|
+
this.refreshToken = null;
|
|
3999
|
+
}
|
|
4000
|
+
}
|
|
4001
|
+
async awaitInitialization() {
|
|
4002
|
+
if (this.initializationPromise) {
|
|
4003
|
+
await this.initializationPromise;
|
|
4004
|
+
this.initializationPromise = null;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
async assessTokenStateOnce() {
|
|
4008
|
+
if (!this.tokenStorage || this.hasAssessedTokens) return;
|
|
4009
|
+
this.hasAssessedTokens = true;
|
|
4010
|
+
try {
|
|
4011
|
+
const accessToken = await this.tokenStorage.getAccessToken();
|
|
4012
|
+
const refreshToken = await this.tokenStorage.getRefreshToken();
|
|
4013
|
+
if (!accessToken && refreshToken) {
|
|
4014
|
+
await this.tokenStorage.clearTokens();
|
|
4015
|
+
console.info("Cleaned up orphaned refresh token");
|
|
4016
|
+
}
|
|
4017
|
+
} catch (error) {
|
|
4018
|
+
console.warn("Token state assessment failed:", error);
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
async bootstrapAnonymousSession() {
|
|
4022
|
+
if (!this.tokenStorage) return null;
|
|
4023
|
+
if (this.bootstrapPromise) return this.bootstrapPromise;
|
|
4024
|
+
this.bootstrapPromise = (async () => {
|
|
4025
|
+
try {
|
|
4026
|
+
const response = await fetch(`${this.baseUrl}/auth/anonymous`, {
|
|
4027
|
+
method: "POST",
|
|
4028
|
+
headers: {
|
|
4029
|
+
"Content-Type": "application/json",
|
|
4030
|
+
...this.apiKey && { "X-Api-Key": this.apiKey }
|
|
4031
|
+
}
|
|
4032
|
+
});
|
|
4033
|
+
if (!response.ok) return null;
|
|
4034
|
+
const tokens = (await response.json()).content;
|
|
4035
|
+
if (tokens?.access_token && tokens?.refresh_token) {
|
|
4036
|
+
await this.storeManagedTokens(tokens.access_token, tokens.refresh_token);
|
|
4037
|
+
this.onTokensUpdated?.(tokens.access_token, tokens.refresh_token);
|
|
4038
|
+
console.info("Automatically created anonymous session for first API request");
|
|
4039
|
+
return tokens.access_token;
|
|
4040
|
+
}
|
|
4041
|
+
return null;
|
|
4042
|
+
} catch (error) {
|
|
4043
|
+
console.warn("Failed to automatically create anonymous tokens:", error);
|
|
4044
|
+
return null;
|
|
4045
|
+
} finally {
|
|
4046
|
+
this.bootstrapPromise = null;
|
|
4047
|
+
}
|
|
4048
|
+
})();
|
|
4049
|
+
return this.bootstrapPromise;
|
|
4050
|
+
}
|
|
4051
|
+
async refreshTokens() {
|
|
4052
|
+
if (!this.tokenStorage) return;
|
|
4053
|
+
const tokenStorage = this.tokenStorage;
|
|
4054
|
+
if (this.refreshPromise) return this.refreshPromise;
|
|
4055
|
+
this.refreshPromise = (async () => {
|
|
4056
|
+
try {
|
|
4057
|
+
const refreshToken = await tokenStorage.getRefreshToken();
|
|
4058
|
+
let newTokens;
|
|
4059
|
+
if (refreshToken && !isTokenExpired(refreshToken)) if (this.refreshTokenFn) newTokens = await this.refreshTokenFn(refreshToken);
|
|
4060
|
+
else {
|
|
4061
|
+
const response = await fetch(`${this.baseUrl}/auth/refresh-token`, {
|
|
4062
|
+
method: "POST",
|
|
4063
|
+
headers: { "Content-Type": "application/json" },
|
|
4064
|
+
body: JSON.stringify({ refresh_token: refreshToken })
|
|
4065
|
+
});
|
|
4066
|
+
if (!response.ok) throw new Error(`Token refresh failed: ${response.status}`);
|
|
4067
|
+
newTokens = (await response.json()).content;
|
|
4068
|
+
}
|
|
4069
|
+
else {
|
|
4070
|
+
const currentAccessToken = await tokenStorage.getAccessToken();
|
|
4071
|
+
if (!currentAccessToken) throw new Error("No tokens available for refresh");
|
|
4072
|
+
const reason = refreshToken ? "refresh token expired" : "no refresh token available";
|
|
4073
|
+
const response = await fetch(`${this.baseUrl}/auth/anonymous`, {
|
|
4074
|
+
method: "POST",
|
|
4075
|
+
headers: {
|
|
4076
|
+
"Content-Type": "application/json",
|
|
4077
|
+
...this.apiKey && { "X-Api-Key": this.apiKey },
|
|
4078
|
+
Authorization: `Bearer ${currentAccessToken}`
|
|
4079
|
+
}
|
|
4080
|
+
});
|
|
4081
|
+
if (!response.ok) throw new Error(`Anonymous token fallback failed: ${response.status}`);
|
|
4082
|
+
newTokens = (await response.json()).content;
|
|
4083
|
+
console.info(`Token refreshed via anonymous fallback (${reason}) - user may need to re-authenticate for privileged operations`);
|
|
4084
|
+
}
|
|
4085
|
+
await this.storeManagedTokens(newTokens.access_token, newTokens.refresh_token);
|
|
4086
|
+
this.onTokensUpdated?.(newTokens.access_token, newTokens.refresh_token);
|
|
4087
|
+
} catch (error) {
|
|
4088
|
+
console.error("Token refresh failed:", error);
|
|
4089
|
+
await this.clearTokens();
|
|
4090
|
+
throw error;
|
|
4091
|
+
} finally {
|
|
4092
|
+
this.refreshPromise = null;
|
|
4093
|
+
}
|
|
4094
|
+
})();
|
|
4095
|
+
return this.refreshPromise;
|
|
4096
|
+
}
|
|
4097
|
+
async captureTokensFromResponse(method, pathname, response) {
|
|
4098
|
+
if (!this.tokenStorage || !(isTokenReturningOperation(method, pathname) || isAnonymousAuthOperation(method, pathname))) return;
|
|
4099
|
+
try {
|
|
4100
|
+
const content = (await response.clone().json()).content;
|
|
4101
|
+
if (content?.access_token && content?.refresh_token) {
|
|
4102
|
+
await this.storeManagedTokens(content.access_token, content.refresh_token);
|
|
4103
|
+
this.onTokensUpdated?.(content.access_token, content.refresh_token);
|
|
4104
|
+
}
|
|
4105
|
+
} catch (error) {
|
|
4106
|
+
console.warn("Failed to extract tokens from response:", error);
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
async storeManagedTokens(accessToken, refreshToken) {
|
|
4110
|
+
if (!this.tokenStorage) return;
|
|
4111
|
+
await this.tokenStorage.setAccessToken(accessToken);
|
|
4112
|
+
if (refreshToken) await this.tokenStorage.setRefreshToken(refreshToken);
|
|
4113
|
+
}
|
|
4114
|
+
};
|
|
4115
|
+
|
|
4116
|
+
//#endregion
|
|
4117
|
+
//#region src/lib/public/client.ts
|
|
4118
|
+
/**
|
|
4119
|
+
* Storefront API client that always authenticates with `X-Api-Key`.
|
|
4120
|
+
*
|
|
4121
|
+
* This client is used by the public storefront surface where no session or
|
|
4122
|
+
* token lifecycle should be involved.
|
|
4123
|
+
*/
|
|
4124
|
+
var PublicStorefrontAPIClient = class extends StorefrontAPIClientBase {
|
|
4125
|
+
constructor(config) {
|
|
4126
|
+
super(config);
|
|
4127
|
+
this.setupPublicAuth();
|
|
3811
4128
|
}
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
* @returns Promise with address details
|
|
3818
|
-
*
|
|
3819
|
-
* @example
|
|
3820
|
-
* ```typescript
|
|
3821
|
-
* const { data, error } = await sdk.customer.updateAddress(
|
|
3822
|
-
* {
|
|
3823
|
-
* user_id: "user_456",
|
|
3824
|
-
* address_id: "addr_789"
|
|
3825
|
-
* },
|
|
3826
|
-
* {
|
|
3827
|
-
* address_line1: "456 Oak Avenue",
|
|
3828
|
-
* city: "Los Angeles",
|
|
3829
|
-
* state: "CA",
|
|
3830
|
-
* pincode: "90210"
|
|
3831
|
-
* }
|
|
3832
|
-
* );
|
|
3833
|
-
*
|
|
3834
|
-
* if (error) {
|
|
3835
|
-
* console.error("Failed to update address:", error);
|
|
3836
|
-
* return;
|
|
3837
|
-
* }
|
|
3838
|
-
*
|
|
3839
|
-
* console.log("Address updated:", data.address);
|
|
3840
|
-
* ```
|
|
3841
|
-
*/
|
|
3842
|
-
async updateAddress(pathParams, body) {
|
|
3843
|
-
return this.executeRequest(() => this.client.PUT("/customers/{user_id}/addresses/{address_id}", {
|
|
3844
|
-
params: { path: pathParams },
|
|
3845
|
-
body
|
|
3846
|
-
}));
|
|
4129
|
+
setupPublicAuth() {
|
|
4130
|
+
this.client.use({ onRequest: async ({ request }) => {
|
|
4131
|
+
if (this.apiKey) request.headers.set("X-Api-Key", this.apiKey);
|
|
4132
|
+
return request;
|
|
4133
|
+
} });
|
|
3847
4134
|
}
|
|
4135
|
+
};
|
|
4136
|
+
|
|
4137
|
+
//#endregion
|
|
4138
|
+
//#region src/index.ts
|
|
4139
|
+
/**
|
|
4140
|
+
* Public SDK class for the Storefront API.
|
|
4141
|
+
*
|
|
4142
|
+
* This surface is intentionally limited to API-key-backed, public read
|
|
4143
|
+
* operations so it can be used safely during build and prerender flows.
|
|
4144
|
+
*/
|
|
4145
|
+
var PublicStorefrontSDK = class {
|
|
3848
4146
|
/**
|
|
3849
|
-
*
|
|
3850
|
-
*
|
|
3851
|
-
* @param pathParams - Path parameters
|
|
3852
|
-
* @returns Promise with deletion response
|
|
3853
|
-
*
|
|
3854
|
-
* @example
|
|
3855
|
-
* ```typescript
|
|
3856
|
-
* const { data, error } = await sdk.customer.deleteAddress({
|
|
3857
|
-
* user_id: "user_456",
|
|
3858
|
-
* address_id: "addr_789"
|
|
3859
|
-
* });
|
|
3860
|
-
*
|
|
3861
|
-
* if (error) {
|
|
3862
|
-
* console.error("Failed to delete address:", error);
|
|
3863
|
-
* return;
|
|
3864
|
-
* }
|
|
3865
|
-
*
|
|
3866
|
-
* console.log("Address deleted:", data.message);
|
|
3867
|
-
* ```
|
|
4147
|
+
* Client for catalog-related read-only endpoints
|
|
3868
4148
|
*/
|
|
3869
|
-
|
|
3870
|
-
return this.executeRequest(() => this.client.DELETE("/customers/{user_id}/addresses/{address_id}", { params: { path: pathParams } }));
|
|
3871
|
-
}
|
|
4149
|
+
catalog;
|
|
3872
4150
|
/**
|
|
3873
|
-
*
|
|
3874
|
-
*
|
|
3875
|
-
* @param pathParams - Path parameters
|
|
3876
|
-
* @returns Promise with loyalty details
|
|
3877
|
-
*
|
|
3878
|
-
* @example
|
|
3879
|
-
* ```typescript
|
|
3880
|
-
* const { data, error } = await sdk.customer.getLoyaltyDetails({
|
|
3881
|
-
* user_id: "user_456"
|
|
3882
|
-
* });
|
|
3883
|
-
*
|
|
3884
|
-
* if (error) {
|
|
3885
|
-
* console.error("Failed to get loyalty details:", error);
|
|
3886
|
-
* return;
|
|
3887
|
-
* }
|
|
3888
|
-
*
|
|
3889
|
-
* console.log("Loyalty info:", data.loyalty);
|
|
3890
|
-
* console.log("Points balance:", data.loyalty_point_balance);
|
|
3891
|
-
* ```
|
|
4151
|
+
* Client for helper-related endpoints
|
|
3892
4152
|
*/
|
|
3893
|
-
|
|
3894
|
-
return this.executeRequest(() => this.client.GET("/customers/{user_id}/loyalty", { params: { path: pathParams } }));
|
|
3895
|
-
}
|
|
4153
|
+
helpers;
|
|
3896
4154
|
/**
|
|
3897
|
-
*
|
|
3898
|
-
*
|
|
3899
|
-
* @param pathParams - Path parameters
|
|
3900
|
-
* @returns Promise with loyalty points activity
|
|
3901
|
-
*
|
|
3902
|
-
* @example
|
|
3903
|
-
* ```typescript
|
|
3904
|
-
* const { data, error } = await sdk.customer.listLoyaltyPointsActivity({
|
|
3905
|
-
* user_id: "user_456"
|
|
3906
|
-
* });
|
|
3907
|
-
*
|
|
3908
|
-
* if (error) {
|
|
3909
|
-
* console.error("Failed to get loyalty activity:", error);
|
|
3910
|
-
* return;
|
|
3911
|
-
* }
|
|
3912
|
-
*
|
|
3913
|
-
* console.log("Loyalty activity:", data.loyalty_points_activity);
|
|
3914
|
-
*
|
|
3915
|
-
* // With pagination and sorting
|
|
3916
|
-
* const { data: sortedData, error: sortedError } = await sdk.customer.listLoyaltyPointsActivity({
|
|
3917
|
-
* user_id: "user_456",
|
|
3918
|
-
* page: 1,
|
|
3919
|
-
* limit: 20,
|
|
3920
|
-
* sort_by: JSON.stringify({ "created_at": "desc" })
|
|
3921
|
-
* });
|
|
3922
|
-
* ```
|
|
4155
|
+
* Client for store config-related endpoints
|
|
3923
4156
|
*/
|
|
3924
|
-
|
|
3925
|
-
return this.executeRequest(() => this.client.GET("/customers/{user_id}/loyalty-points-activity", { params: {
|
|
3926
|
-
path: pathParams,
|
|
3927
|
-
query: queryParams
|
|
3928
|
-
} }));
|
|
3929
|
-
}
|
|
4157
|
+
store;
|
|
3930
4158
|
/**
|
|
3931
|
-
*
|
|
3932
|
-
*
|
|
3933
|
-
* @param pathParams - Path parameters
|
|
3934
|
-
* @returns Promise with reviews
|
|
3935
|
-
*
|
|
3936
|
-
* @example
|
|
3937
|
-
* ```typescript
|
|
3938
|
-
* const { data, error } = await sdk.customer.listCustomerReviews({
|
|
3939
|
-
* user_id: "user_456"
|
|
3940
|
-
* });
|
|
3941
|
-
*
|
|
3942
|
-
* if (error) {
|
|
3943
|
-
* console.error("Failed to get customer reviews:", error);
|
|
3944
|
-
* return;
|
|
3945
|
-
* }
|
|
3946
|
-
*
|
|
3947
|
-
* console.log("Customer reviews:", data.reviews);
|
|
3948
|
-
* console.log("Ready for review:", data.ready_for_review);
|
|
3949
|
-
* ```
|
|
4159
|
+
* Centrally stored default headers for consistency
|
|
3950
4160
|
*/
|
|
3951
|
-
|
|
3952
|
-
|
|
4161
|
+
defaultHeaders;
|
|
4162
|
+
constructor(options) {
|
|
4163
|
+
this.defaultHeaders = options.defaultHeaders;
|
|
4164
|
+
const config = {
|
|
4165
|
+
storeId: options.storeId,
|
|
4166
|
+
environment: options.environment,
|
|
4167
|
+
baseUrl: options.baseUrl,
|
|
4168
|
+
apiKey: options.apiKey,
|
|
4169
|
+
timeout: options.timeout,
|
|
4170
|
+
defaultHeaders: options.defaultHeaders,
|
|
4171
|
+
debug: options.debug,
|
|
4172
|
+
logger: options.logger
|
|
4173
|
+
};
|
|
4174
|
+
this.catalog = new PublicCatalogClient(config);
|
|
4175
|
+
this.helpers = new PublicHelpersClient(config);
|
|
4176
|
+
this.store = new PublicStoreConfigClient(config);
|
|
3953
4177
|
}
|
|
3954
4178
|
/**
|
|
3955
|
-
*
|
|
4179
|
+
* Set the API key for all public clients
|
|
3956
4180
|
*
|
|
3957
|
-
* @param
|
|
3958
|
-
* @returns Promise with payment methods
|
|
3959
|
-
*
|
|
3960
|
-
* @example
|
|
3961
|
-
* ```typescript
|
|
3962
|
-
* const { data, error } = await sdk.customer.listSavedPaymentMethods({
|
|
3963
|
-
* customer_id: "customer_123"
|
|
3964
|
-
* });
|
|
3965
|
-
*
|
|
3966
|
-
* if (error) {
|
|
3967
|
-
* console.error("Failed to list saved payment methods:", error);
|
|
3968
|
-
* return;
|
|
3969
|
-
* }
|
|
3970
|
-
*
|
|
3971
|
-
* console.log("Saved payment methods:", data.saved_payment_methods);
|
|
3972
|
-
* ```
|
|
4181
|
+
* @param apiKey - The API key to set
|
|
3973
4182
|
*/
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
} }));
|
|
4183
|
+
setApiKey(apiKey) {
|
|
4184
|
+
this.catalog.setApiKey(apiKey);
|
|
4185
|
+
this.helpers.setApiKey(apiKey);
|
|
4186
|
+
this.store.setApiKey(apiKey);
|
|
3979
4187
|
}
|
|
3980
4188
|
/**
|
|
3981
|
-
*
|
|
3982
|
-
*
|
|
3983
|
-
* @param pathParams - Path parameters
|
|
3984
|
-
* @returns Promise with cards
|
|
3985
|
-
*
|
|
3986
|
-
* @example
|
|
3987
|
-
* ```typescript
|
|
3988
|
-
* const { data, error } = await sdk.customer.listCustomerCards({
|
|
3989
|
-
* customer_id: "customer_123"
|
|
3990
|
-
* });
|
|
3991
|
-
*
|
|
3992
|
-
* if (error) {
|
|
3993
|
-
* console.error("Failed to list customer cards:", error);
|
|
3994
|
-
* return;
|
|
3995
|
-
* }
|
|
3996
|
-
*
|
|
3997
|
-
* console.log("Customer cards:", data.cards);
|
|
3998
|
-
* ```
|
|
4189
|
+
* Clear the API key from all public clients
|
|
3999
4190
|
*/
|
|
4000
|
-
|
|
4001
|
-
|
|
4191
|
+
clearApiKey() {
|
|
4192
|
+
this.catalog.clearApiKey();
|
|
4193
|
+
this.helpers.clearApiKey();
|
|
4194
|
+
this.store.clearApiKey();
|
|
4002
4195
|
}
|
|
4003
|
-
};
|
|
4004
|
-
|
|
4005
|
-
//#endregion
|
|
4006
|
-
//#region src/lib/store-config.ts
|
|
4007
|
-
/**
|
|
4008
|
-
* Client for interacting with store config endpoints
|
|
4009
|
-
*/
|
|
4010
|
-
var StoreConfigClient = class extends StorefrontAPIClient {
|
|
4011
4196
|
/**
|
|
4012
|
-
*
|
|
4013
|
-
*
|
|
4014
|
-
* @description Checks whether a store with the configured store ID exists.
|
|
4015
|
-
* Returns `success: true` if the store exists, `false` otherwise.
|
|
4016
|
-
*
|
|
4017
|
-
* @returns Promise with store existence check result
|
|
4018
|
-
* @example
|
|
4019
|
-
* ```typescript
|
|
4020
|
-
* const { data, error } = await sdk.storeConfig.checkStore();
|
|
4197
|
+
* Set default headers for all public clients
|
|
4021
4198
|
*
|
|
4022
|
-
*
|
|
4023
|
-
* console.error("Failed to check store:", error.message);
|
|
4024
|
-
* } else {
|
|
4025
|
-
* console.log("Store exists:", data.success);
|
|
4026
|
-
* }
|
|
4027
|
-
* ```
|
|
4199
|
+
* @param headers - Default headers to set (only supported headers allowed)
|
|
4028
4200
|
*/
|
|
4029
|
-
|
|
4030
|
-
|
|
4201
|
+
setDefaultHeaders(headers) {
|
|
4202
|
+
this.defaultHeaders = headers;
|
|
4203
|
+
this.catalog.setDefaultHeaders(headers);
|
|
4204
|
+
this.helpers.setDefaultHeaders(headers);
|
|
4205
|
+
this.store.setDefaultHeaders(headers);
|
|
4031
4206
|
}
|
|
4032
4207
|
/**
|
|
4033
|
-
* Get
|
|
4034
|
-
*
|
|
4035
|
-
* @returns Promise with store configuration data
|
|
4036
|
-
*
|
|
4037
|
-
* @example
|
|
4038
|
-
* ```typescript
|
|
4039
|
-
* const { data, error } = await sdk.storeConfig.getStoreConfig();
|
|
4040
|
-
*
|
|
4041
|
-
* if (error) {
|
|
4042
|
-
* console.error('Failed to get store config:', error.message);
|
|
4043
|
-
* return;
|
|
4044
|
-
* }
|
|
4208
|
+
* Get current default headers
|
|
4045
4209
|
*
|
|
4046
|
-
*
|
|
4047
|
-
* const storeConfig = data.store_config;
|
|
4048
|
-
* console.log('Store brand:', storeConfig.brand.name);
|
|
4049
|
-
* console.log('Currency:', storeConfig.currency.code);
|
|
4050
|
-
* console.log('KYC enabled:', storeConfig.is_kyc_enabled);
|
|
4051
|
-
* console.log('Customer groups enabled:', storeConfig.is_customer_group_enabled);
|
|
4052
|
-
* ```
|
|
4210
|
+
* @returns Current default headers from central storage (always consistent)
|
|
4053
4211
|
*/
|
|
4054
|
-
|
|
4055
|
-
return this.
|
|
4212
|
+
getDefaultHeaders() {
|
|
4213
|
+
return this.defaultHeaders;
|
|
4056
4214
|
}
|
|
4057
4215
|
};
|
|
4058
|
-
|
|
4059
|
-
//#endregion
|
|
4060
|
-
//#region src/index.ts
|
|
4061
4216
|
/**
|
|
4062
|
-
* Main SDK class for the Storefront API
|
|
4217
|
+
* Main session-aware SDK class for the Storefront API
|
|
4063
4218
|
*/
|
|
4064
|
-
var
|
|
4219
|
+
var SessionStorefrontSDK = class {
|
|
4065
4220
|
/**
|
|
4066
4221
|
* Client for catalog-related endpoints (products, categories, etc.)
|
|
4067
4222
|
*/
|
|
@@ -4099,12 +4254,33 @@ var StorefrontSDK = class {
|
|
|
4099
4254
|
*/
|
|
4100
4255
|
defaultHeaders;
|
|
4101
4256
|
/**
|
|
4102
|
-
*
|
|
4257
|
+
* Shared session helper and coordinator for all API clients in this SDK instance.
|
|
4258
|
+
*/
|
|
4259
|
+
session;
|
|
4260
|
+
sessionManager;
|
|
4261
|
+
/**
|
|
4262
|
+
* Create a new SessionStorefrontSDK instance
|
|
4103
4263
|
*
|
|
4104
4264
|
* @param options - Configuration options for the SDK
|
|
4105
4265
|
*/
|
|
4106
4266
|
constructor(options) {
|
|
4107
4267
|
this.defaultHeaders = options.defaultHeaders;
|
|
4268
|
+
const sessionManager = new StorefrontSessionManager({
|
|
4269
|
+
accessToken: options.accessToken,
|
|
4270
|
+
apiKey: options.apiKey,
|
|
4271
|
+
baseUrl: buildStorefrontURL({
|
|
4272
|
+
storeId: options.storeId,
|
|
4273
|
+
environment: options.environment,
|
|
4274
|
+
baseUrl: options.baseUrl
|
|
4275
|
+
}),
|
|
4276
|
+
onTokensCleared: options.onTokensCleared,
|
|
4277
|
+
onTokensUpdated: options.onTokensUpdated,
|
|
4278
|
+
refreshToken: options.refreshToken,
|
|
4279
|
+
refreshTokenFn: options.refreshTokenFn,
|
|
4280
|
+
tokenStorage: options.tokenStorage
|
|
4281
|
+
});
|
|
4282
|
+
this.sessionManager = sessionManager;
|
|
4283
|
+
this.session = sessionManager;
|
|
4108
4284
|
const config = {
|
|
4109
4285
|
storeId: options.storeId,
|
|
4110
4286
|
environment: options.environment,
|
|
@@ -4118,7 +4294,8 @@ var StorefrontSDK = class {
|
|
|
4118
4294
|
onTokensCleared: options.onTokensCleared,
|
|
4119
4295
|
defaultHeaders: options.defaultHeaders,
|
|
4120
4296
|
debug: options.debug,
|
|
4121
|
-
logger: options.logger
|
|
4297
|
+
logger: options.logger,
|
|
4298
|
+
sessionManager
|
|
4122
4299
|
};
|
|
4123
4300
|
this.catalog = new CatalogClient(config);
|
|
4124
4301
|
this.cart = new CartClient(config);
|
|
@@ -4140,14 +4317,7 @@ var StorefrontSDK = class {
|
|
|
4140
4317
|
* - If tokenStorage is not provided: Only stores access token for manual management
|
|
4141
4318
|
*/
|
|
4142
4319
|
async setTokens(accessToken, refreshToken) {
|
|
4143
|
-
await this.
|
|
4144
|
-
await this.cart.setTokens(accessToken, refreshToken);
|
|
4145
|
-
await this.auth.setTokens(accessToken, refreshToken);
|
|
4146
|
-
await this.customer.setTokens(accessToken, refreshToken);
|
|
4147
|
-
await this.helpers.setTokens(accessToken, refreshToken);
|
|
4148
|
-
await this.order.setTokens(accessToken, refreshToken);
|
|
4149
|
-
await this.payments.setTokens(accessToken, refreshToken);
|
|
4150
|
-
await this.store.setTokens(accessToken, refreshToken);
|
|
4320
|
+
await this.sessionManager.setTokens(accessToken, refreshToken);
|
|
4151
4321
|
}
|
|
4152
4322
|
/**
|
|
4153
4323
|
* Clear all authentication tokens from all clients
|
|
@@ -4157,14 +4327,7 @@ var StorefrontSDK = class {
|
|
|
4157
4327
|
* - If tokenStorage is not provided: Clears the manual access token
|
|
4158
4328
|
*/
|
|
4159
4329
|
async clearTokens() {
|
|
4160
|
-
await this.
|
|
4161
|
-
await this.cart.clearTokens();
|
|
4162
|
-
await this.auth.clearTokens();
|
|
4163
|
-
await this.customer.clearTokens();
|
|
4164
|
-
await this.helpers.clearTokens();
|
|
4165
|
-
await this.order.clearTokens();
|
|
4166
|
-
await this.payments.clearTokens();
|
|
4167
|
-
await this.store.clearTokens();
|
|
4330
|
+
await this.sessionManager.clearTokens();
|
|
4168
4331
|
}
|
|
4169
4332
|
/**
|
|
4170
4333
|
* Set the API key for all clients
|
|
@@ -4172,57 +4335,58 @@ var StorefrontSDK = class {
|
|
|
4172
4335
|
* @param apiKey - The API key to set
|
|
4173
4336
|
*/
|
|
4174
4337
|
setApiKey(apiKey) {
|
|
4175
|
-
this.
|
|
4176
|
-
this.cart.setApiKey(apiKey);
|
|
4177
|
-
this.auth.setApiKey(apiKey);
|
|
4178
|
-
this.customer.setApiKey(apiKey);
|
|
4179
|
-
this.helpers.setApiKey(apiKey);
|
|
4180
|
-
this.order.setApiKey(apiKey);
|
|
4181
|
-
this.payments.setApiKey(apiKey);
|
|
4182
|
-
this.store.setApiKey(apiKey);
|
|
4338
|
+
this.sessionManager.setApiKey(apiKey);
|
|
4183
4339
|
}
|
|
4184
4340
|
/**
|
|
4185
4341
|
* Clear the API key from all clients
|
|
4186
4342
|
*/
|
|
4187
4343
|
clearApiKey() {
|
|
4188
|
-
this.
|
|
4189
|
-
this.cart.clearApiKey();
|
|
4190
|
-
this.auth.clearApiKey();
|
|
4191
|
-
this.customer.clearApiKey();
|
|
4192
|
-
this.helpers.clearApiKey();
|
|
4193
|
-
this.order.clearApiKey();
|
|
4194
|
-
this.payments.clearApiKey();
|
|
4195
|
-
this.store.clearApiKey();
|
|
4344
|
+
this.sessionManager.clearApiKey();
|
|
4196
4345
|
}
|
|
4197
4346
|
/**
|
|
4198
4347
|
* Get the current access token if using token storage
|
|
4348
|
+
*
|
|
4349
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4199
4350
|
*/
|
|
4200
4351
|
async getAccessToken() {
|
|
4201
|
-
return
|
|
4352
|
+
return this.session.peekAccessToken();
|
|
4353
|
+
}
|
|
4354
|
+
/**
|
|
4355
|
+
* Ensure an access token is available for the current session.
|
|
4356
|
+
*
|
|
4357
|
+
* This may create or refresh a managed session when automatic token
|
|
4358
|
+
* management is configured.
|
|
4359
|
+
*
|
|
4360
|
+
* @returns A usable access token
|
|
4361
|
+
*/
|
|
4362
|
+
async ensureAccessToken() {
|
|
4363
|
+
return this.session.ensureAccessToken();
|
|
4202
4364
|
}
|
|
4203
4365
|
/**
|
|
4204
4366
|
* Get user information from the current access token
|
|
4205
4367
|
*
|
|
4368
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4369
|
+
*
|
|
4206
4370
|
* @returns User information extracted from JWT token, or null if no token or invalid token
|
|
4207
4371
|
*/
|
|
4208
4372
|
async getUserInfo() {
|
|
4209
|
-
|
|
4210
|
-
if (!token) return null;
|
|
4211
|
-
return extractUserInfoFromToken(token);
|
|
4373
|
+
return this.session.peekUserInfo();
|
|
4212
4374
|
}
|
|
4213
4375
|
/**
|
|
4214
4376
|
* Get the current user ID from the access token
|
|
4215
4377
|
*
|
|
4378
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4379
|
+
*
|
|
4216
4380
|
* @returns User ID (ulid) or null if no token or invalid token
|
|
4217
4381
|
*/
|
|
4218
4382
|
async getUserId() {
|
|
4219
|
-
|
|
4220
|
-
if (!token) return null;
|
|
4221
|
-
return getUserIdFromToken(token);
|
|
4383
|
+
return this.session.peekUserId();
|
|
4222
4384
|
}
|
|
4223
4385
|
/**
|
|
4224
4386
|
* Check if the current user is logged in (not anonymous)
|
|
4225
4387
|
*
|
|
4388
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4389
|
+
*
|
|
4226
4390
|
* @returns True if user is logged in, false if anonymous or no token
|
|
4227
4391
|
*/
|
|
4228
4392
|
async isLoggedIn() {
|
|
@@ -4233,6 +4397,8 @@ var StorefrontSDK = class {
|
|
|
4233
4397
|
/**
|
|
4234
4398
|
* Check if the current user is anonymous
|
|
4235
4399
|
*
|
|
4400
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4401
|
+
*
|
|
4236
4402
|
* @returns True if user is anonymous or no token, false if logged in
|
|
4237
4403
|
*/
|
|
4238
4404
|
async isAnonymous() {
|
|
@@ -4243,18 +4409,22 @@ var StorefrontSDK = class {
|
|
|
4243
4409
|
/**
|
|
4244
4410
|
* Get the customer ID from the current access token
|
|
4245
4411
|
*
|
|
4412
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4413
|
+
*
|
|
4246
4414
|
* @returns Customer ID or null if no token, invalid token, or user has no customer ID
|
|
4247
4415
|
*/
|
|
4248
4416
|
async getCustomerId() {
|
|
4249
|
-
return
|
|
4417
|
+
return this.session.peekCustomerId();
|
|
4250
4418
|
}
|
|
4251
4419
|
/**
|
|
4252
4420
|
* Get the customer group ID from the current access token
|
|
4253
4421
|
*
|
|
4422
|
+
* This is a passive lookup. It will not create or refresh a session.
|
|
4423
|
+
*
|
|
4254
4424
|
* @returns Customer group ID or null if no token, invalid token, or user has no customer group
|
|
4255
4425
|
*/
|
|
4256
4426
|
async getCustomerGroupId() {
|
|
4257
|
-
return
|
|
4427
|
+
return this.session.peekCustomerGroupId();
|
|
4258
4428
|
}
|
|
4259
4429
|
/**
|
|
4260
4430
|
* Set default headers for all clients
|
|
@@ -4281,7 +4451,71 @@ var StorefrontSDK = class {
|
|
|
4281
4451
|
return this.defaultHeaders;
|
|
4282
4452
|
}
|
|
4283
4453
|
};
|
|
4454
|
+
function buildPublicStorefrontOptions(options) {
|
|
4455
|
+
return {
|
|
4456
|
+
storeId: options.storeId,
|
|
4457
|
+
environment: options.environment,
|
|
4458
|
+
baseUrl: options.baseUrl,
|
|
4459
|
+
apiKey: options.apiKey,
|
|
4460
|
+
timeout: options.timeout,
|
|
4461
|
+
defaultHeaders: options.defaultHeaders,
|
|
4462
|
+
debug: options.debug,
|
|
4463
|
+
logger: options.logger
|
|
4464
|
+
};
|
|
4465
|
+
}
|
|
4466
|
+
function buildSessionStorefrontOptions(options, overrides) {
|
|
4467
|
+
return {
|
|
4468
|
+
...buildPublicStorefrontOptions(options),
|
|
4469
|
+
...options.session,
|
|
4470
|
+
...overrides
|
|
4471
|
+
};
|
|
4472
|
+
}
|
|
4473
|
+
/**
|
|
4474
|
+
* Create a configured storefront factory with explicit public and session
|
|
4475
|
+
* access patterns.
|
|
4476
|
+
*
|
|
4477
|
+
* @example
|
|
4478
|
+
* ```typescript
|
|
4479
|
+
* import {
|
|
4480
|
+
* BrowserTokenStorage,
|
|
4481
|
+
* createStorefront,
|
|
4482
|
+
* Environment,
|
|
4483
|
+
* } from "@commercengine/storefront-sdk";
|
|
4484
|
+
*
|
|
4485
|
+
* export const storefront = createStorefront({
|
|
4486
|
+
* storeId: "your-store-id",
|
|
4487
|
+
* apiKey: "your-api-key",
|
|
4488
|
+
* environment: Environment.Staging,
|
|
4489
|
+
* session: {
|
|
4490
|
+
* tokenStorage: new BrowserTokenStorage("myapp_"),
|
|
4491
|
+
* },
|
|
4492
|
+
* });
|
|
4493
|
+
*
|
|
4494
|
+
* const { data: products } = await storefront.public().catalog.listProducts();
|
|
4495
|
+
* const { data: cart } = await storefront.session().cart.getCart();
|
|
4496
|
+
* ```
|
|
4497
|
+
*
|
|
4498
|
+
* @param options - Shared public config plus optional default session config
|
|
4499
|
+
* @returns A storefront factory with explicit `public()` and `session()` accessors
|
|
4500
|
+
*/
|
|
4501
|
+
function createStorefront(options) {
|
|
4502
|
+
const publicOptions = buildPublicStorefrontOptions(options);
|
|
4503
|
+
let publicSDK = null;
|
|
4504
|
+
let sessionSDK = null;
|
|
4505
|
+
const session = (overrides) => {
|
|
4506
|
+
if (overrides && Object.keys(overrides).length > 0) return new SessionStorefrontSDK(buildSessionStorefrontOptions(options, overrides));
|
|
4507
|
+
if (!sessionSDK) sessionSDK = new SessionStorefrontSDK(buildSessionStorefrontOptions(options));
|
|
4508
|
+
return sessionSDK;
|
|
4509
|
+
};
|
|
4510
|
+
return {
|
|
4511
|
+
public: () => {
|
|
4512
|
+
if (!publicSDK) publicSDK = new PublicStorefrontSDK(publicOptions);
|
|
4513
|
+
return publicSDK;
|
|
4514
|
+
},
|
|
4515
|
+
session
|
|
4516
|
+
};
|
|
4517
|
+
}
|
|
4284
4518
|
|
|
4285
4519
|
//#endregion
|
|
4286
|
-
export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient,
|
|
4520
|
+
export { AuthClient, BrowserTokenStorage, CartClient, CatalogClient, CookieTokenStorage, CustomerClient, Environment, HelpersClient, MemoryTokenStorage, OrderClient, PaymentsClient, PublicCatalogClient, PublicHelpersClient, PublicStoreConfigClient, PublicStorefrontAPIClient, PublicStorefrontSDK, ResponseUtils, SessionStorefrontAPIClient, SessionStorefrontSDK, StoreConfigClient, createStorefront };
|
|
4287
4521
|
//# sourceMappingURL=index.mjs.map
|