@commercengine/storefront-sdk 0.3.9 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ import { HelpersClient } from "./lib/helper";
8
8
  import { CustomerClient } from "./lib/customer";
9
9
  import { TokenStorage, MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage } from "./lib/middleware";
10
10
  import { type UserInfo } from "./lib/jwt-utils";
11
+ import { ResponseUtils, type DebugLoggerFn } from "./lib/logger-utils";
11
12
  /**
12
13
  * Supported default headers that can be set at the SDK level
13
14
  * Only includes headers that are actually supported by API endpoints
@@ -75,6 +76,17 @@ export interface StorefrontSDKOptions {
75
76
  * Only supports headers that are actually available in the API
76
77
  */
77
78
  defaultHeaders?: SupportedDefaultHeaders;
79
+ /**
80
+ * Enable debug mode for detailed request/response logging
81
+ * When enabled, detailed debug information will be logged via the logger
82
+ * Note: Response objects are always included in ApiResult regardless of debug mode
83
+ */
84
+ debug?: boolean;
85
+ /**
86
+ * Custom logger function for debug information
87
+ * If not provided and debug is enabled, will use console.log
88
+ */
89
+ logger?: DebugLoggerFn;
78
90
  }
79
91
  /**
80
92
  * Main SDK class for the Storefront API
@@ -197,10 +209,11 @@ export declare class StorefrontSDK {
197
209
  getDefaultHeaders(): SupportedDefaultHeaders | undefined;
198
210
  }
199
211
  export default StorefrontSDK;
200
- export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, };
212
+ export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, ResponseUtils, };
201
213
  export { Environment };
202
214
  export { TokenStorage, MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage, };
203
215
  export type { CookieTokenStorageOptions } from "./lib/middleware";
204
216
  export type { UserInfo } from "./lib/jwt-utils";
217
+ export type { DebugLoggerFn } from "./lib/logger-utils";
205
218
  export type { components, operations, paths } from "./types/storefront";
206
219
  export type * from "./types/storefront-api-types";
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { HelpersClient } from "./lib/helper";
8
8
  import { CustomerClient } from "./lib/customer";
9
9
  import { MemoryTokenStorage, BrowserTokenStorage, CookieTokenStorage, } from "./lib/middleware";
10
10
  import { extractUserInfoFromToken, getUserIdFromToken, isUserLoggedIn, isUserAnonymous, } from "./lib/jwt-utils";
11
+ import { ResponseUtils } from "./lib/logger-utils";
11
12
  /**
12
13
  * Main SDK class for the Storefront API
13
14
  */
@@ -59,6 +60,8 @@ export class StorefrontSDK {
59
60
  onTokensUpdated: options.onTokensUpdated,
60
61
  onTokensCleared: options.onTokensCleared,
61
62
  defaultHeaders: options.defaultHeaders,
63
+ debug: options.debug,
64
+ logger: options.logger,
62
65
  };
63
66
  this.catalog = new CatalogClient(config);
64
67
  this.cart = new CartClient(config);
@@ -227,7 +230,7 @@ export class StorefrontSDK {
227
230
  // Export the main SDK class
228
231
  export default StorefrontSDK;
229
232
  // Export individual clients for advanced usage
230
- export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, };
233
+ export { StorefrontAPIClient, AuthClient, CartClient, CatalogClient, CustomerClient, HelpersClient, ShippingClient, OrderClient, ResponseUtils, };
231
234
  // Export environment enum
232
235
  export { Environment };
233
236
  // Export token storage types
@@ -1,5 +1,5 @@
1
1
  import { StorefrontAPIClient } from "./client";
2
- import type { ApiResult, GetProductDetailContent, GetProductDetailPathParams, GetProductDetailHeaderParams, GetVariantDetailContent, GetVariantDetailPathParams, GetVariantDetailHeaderParams, ListProductsContent, ListProductsQuery, ListProductsHeaderParams, ListProductVariantsContent, ListProductVariantsPathParams, ListProductVariantsHeaderParams, ListCategoriesQuery, ListCategoriesContent, ListProductReviewsQuery, ListProductReviewsPathParams, ListProductReviewsContent, CreateProductReviewPathParams, CreateProductReviewFormData, CreateProductReviewResponse, SearchProductsBody, SearchProductsContent, ListSkusQuery, ListSkusContent, ListSkusHeaderParams, ListCrosssellProductsContent, ListCrosssellProductsQuery, ListCrosssellProductsHeaderParams, ListUpsellProductsQuery, ListUpsellProductsContent, ListUpsellProductsHeaderParams, ListSimilarProductsQuery, ListSimilarProductsContent, ListSimilarProductsHeaderParams } from "../types/storefront-api-types";
2
+ import type { ApiResult, GetProductDetailContent, GetProductDetailPathParams, GetProductDetailHeaderParams, GetVariantDetailContent, GetVariantDetailPathParams, GetVariantDetailHeaderParams, ListProductsContent, ListProductsQuery, ListProductsHeaderParams, ListProductVariantsContent, ListProductVariantsPathParams, ListProductVariantsHeaderParams, ListCategoriesQuery, ListCategoriesContent, ListProductReviewsQuery, ListProductReviewsPathParams, ListProductReviewsContent, CreateProductReviewPathParams, CreateProductReviewFormData, CreateProductReviewResponse, SearchProductsBody, SearchProductsContent, ListSkusQuery, ListSkusContent, ListSkusHeaderParams, ListCrosssellProductsContent, ListCrosssellProductsQuery, ListCrosssellProductsHeaderParams, ListUpsellProductsQuery, ListUpsellProductsContent, ListUpsellProductsHeaderParams, ListSimilarProductsQuery, ListSimilarProductsContent, ListSimilarProductsHeaderParams, SearchProductsHeaderParams } from "../types/storefront-api-types";
3
3
  /**
4
4
  * Client for interacting with catalog endpoints
5
5
  */
@@ -73,7 +73,7 @@ export declare class CatalogClient extends StorefrontAPIClient {
73
73
  * @param searchData - The search parameters
74
74
  * @returns Promise with search results, facet distribution, facet stats, and pagination
75
75
  */
76
- searchProducts(searchData: SearchProductsBody): Promise<ApiResult<SearchProductsContent>>;
76
+ searchProducts(searchData: SearchProductsBody, headers?: SearchProductsHeaderParams): Promise<ApiResult<SearchProductsContent>>;
77
77
  /**
78
78
  * List cross-sell products
79
79
  *
@@ -146,9 +146,11 @@ export class CatalogClient extends StorefrontAPIClient {
146
146
  * @param searchData - The search parameters
147
147
  * @returns Promise with search results, facet distribution, facet stats, and pagination
148
148
  */
149
- async searchProducts(searchData) {
149
+ async searchProducts(searchData, headers) {
150
+ const mergedHeaders = this.mergeHeaders(headers);
150
151
  return this.executeRequest(() => this.client.POST("/catalog/products/search", {
151
152
  body: searchData,
153
+ header: mergedHeaders,
152
154
  }));
153
155
  }
154
156
  /**
@@ -107,7 +107,7 @@ export declare class StorefrontAPIClient {
107
107
  * Method-level headers take precedence over default headers
108
108
  *
109
109
  * @param methodHeaders - Headers passed to the specific method call
110
- * @returns Merged headers object
110
+ * @returns Merged headers object with proper HTTP header names
111
111
  */
112
112
  protected mergeHeaders<T extends Record<string, any> = Record<string, any>>(methodHeaders?: T): T;
113
113
  }
@@ -1,6 +1,8 @@
1
1
  import createClient from "openapi-fetch";
2
2
  import { createDefaultAuthMiddleware } from "./middleware";
3
3
  import { getPathnameFromUrl, isAnonymousAuthEndpoint } from "./auth-utils";
4
+ import { createDebugMiddleware } from "./logger-utils";
5
+ import { mergeHeaders } from "./header-utils";
4
6
  /**
5
7
  * Available API environments
6
8
  */
@@ -81,6 +83,11 @@ export class StorefrontAPIClient {
81
83
  if (this.config.timeout) {
82
84
  this.setupTimeoutMiddleware();
83
85
  }
86
+ // Set up debug middleware if enabled
87
+ if (this.config.debug) {
88
+ const debugMiddleware = createDebugMiddleware(this.config.logger);
89
+ this.client.use(debugMiddleware);
90
+ }
84
91
  }
85
92
  /**
86
93
  * Set up timeout middleware
@@ -215,21 +222,39 @@ export class StorefrontAPIClient {
215
222
  */
216
223
  async executeRequest(apiCall) {
217
224
  try {
218
- const { data, error } = await apiCall();
225
+ const { data, error, response } = await apiCall();
226
+ // Debug logging is now handled by middleware
219
227
  // openapi-fetch returns error for 4xx/5xx, data for 2xx
220
228
  if (error) {
221
- return { data: null, error };
229
+ return {
230
+ data: null,
231
+ error,
232
+ response,
233
+ };
222
234
  }
223
235
  // If response has content, return it directly
224
236
  if (data && data.content !== undefined) {
225
- return { data: data.content, error: null };
237
+ return {
238
+ data: data.content,
239
+ error: null,
240
+ response,
241
+ };
226
242
  }
227
243
  // If no content, return the response object (with message, success, etc.)
228
- return { data: data, error: null };
244
+ return {
245
+ data: data,
246
+ error: null,
247
+ response,
248
+ };
229
249
  }
230
250
  catch (err) {
231
251
  // This handles network errors or other unexpected errors
232
- return {
252
+ // Network errors don't have Response objects, so we create a mock response
253
+ const mockResponse = new Response(null, {
254
+ status: 0,
255
+ statusText: "Network Error",
256
+ });
257
+ const errorResult = {
233
258
  data: null,
234
259
  error: {
235
260
  success: false,
@@ -237,7 +262,10 @@ export class StorefrontAPIClient {
237
262
  message: "Network error occurred",
238
263
  error: err,
239
264
  },
265
+ response: mockResponse,
240
266
  };
267
+ // Network errors are logged by middleware if debug is enabled
268
+ return errorResult;
241
269
  }
242
270
  }
243
271
  /**
@@ -261,32 +289,9 @@ export class StorefrontAPIClient {
261
289
  * Method-level headers take precedence over default headers
262
290
  *
263
291
  * @param methodHeaders - Headers passed to the specific method call
264
- * @returns Merged headers object
292
+ * @returns Merged headers object with proper HTTP header names
265
293
  */
266
294
  mergeHeaders(methodHeaders) {
267
- if (!this.config.defaultHeaders && !methodHeaders) {
268
- return {};
269
- }
270
- // Start with default headers, but only include supported ones
271
- const merged = {};
272
- // Add default headers if they exist
273
- if (this.config.defaultHeaders) {
274
- if (this.config.defaultHeaders.customer_group_id !== undefined) {
275
- merged.customer_group_id =
276
- this.config.defaultHeaders.customer_group_id;
277
- }
278
- // Future: Add other supported headers here as they become available
279
- }
280
- if (methodHeaders) {
281
- // Method headers override default headers
282
- Object.assign(merged, methodHeaders);
283
- }
284
- // Remove undefined values
285
- Object.keys(merged).forEach((key) => {
286
- if (merged[key] === undefined) {
287
- delete merged[key];
288
- }
289
- });
290
- return merged;
295
+ return mergeHeaders(this.config.defaultHeaders, methodHeaders);
291
296
  }
292
297
  }
@@ -0,0 +1,26 @@
1
+ import type { SupportedDefaultHeaders } from "../index";
2
+ /**
3
+ * Transform SDK header parameters to actual HTTP header names
4
+ * Headers not in the transformation map are passed through unchanged
5
+ *
6
+ * @param headers - Headers object with SDK parameter names
7
+ * @returns Headers object with actual HTTP header names
8
+ */
9
+ export declare function transformHeaders(headers: SupportedDefaultHeaders): Record<string, string>;
10
+ /**
11
+ * Merge default headers with method-level headers
12
+ * Method-level headers take precedence over default headers
13
+ * Automatically transforms SDK parameter names to HTTP header names
14
+ *
15
+ * @param defaultHeaders - Default headers from SDK configuration
16
+ * @param methodHeaders - Headers passed to the specific method call
17
+ * @returns Merged headers object with proper HTTP header names
18
+ */
19
+ export declare function mergeHeaders<T extends Record<string, any> = Record<string, any>>(defaultHeaders?: SupportedDefaultHeaders, methodHeaders?: T): T;
20
+ /**
21
+ * Get the list of supported header transformations
22
+ * Useful for debugging or documentation purposes
23
+ *
24
+ * @returns Copy of the header transformations mapping
25
+ */
26
+ export declare function getHeaderTransformations(): Record<string, string>;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Mapping of SDK header parameter names to actual HTTP header names
3
+ * Only include headers that need transformation - others pass through as-is
4
+ */
5
+ const HEADER_TRANSFORMATIONS = {
6
+ customer_group_id: "x-customer-group-id",
7
+ // Future transformations can be added here:
8
+ // some_param: "X-Some-Header",
9
+ // another_param: "X-Another-Header",
10
+ };
11
+ /**
12
+ * Transform SDK header parameters to actual HTTP header names
13
+ * Headers not in the transformation map are passed through unchanged
14
+ *
15
+ * @param headers - Headers object with SDK parameter names
16
+ * @returns Headers object with actual HTTP header names
17
+ */
18
+ export function transformHeaders(headers) {
19
+ const transformed = {};
20
+ // Iterate through all headers in the input
21
+ for (const [key, value] of Object.entries(headers)) {
22
+ if (value !== undefined) {
23
+ // Use transformation if available, otherwise use the original key
24
+ const headerName = HEADER_TRANSFORMATIONS[key] || key;
25
+ transformed[headerName] = value;
26
+ }
27
+ }
28
+ return transformed;
29
+ }
30
+ /**
31
+ * Merge default headers with method-level headers
32
+ * Method-level headers take precedence over default headers
33
+ * Automatically transforms SDK parameter names to HTTP header names
34
+ *
35
+ * @param defaultHeaders - Default headers from SDK configuration
36
+ * @param methodHeaders - Headers passed to the specific method call
37
+ * @returns Merged headers object with proper HTTP header names
38
+ */
39
+ export function mergeHeaders(defaultHeaders, methodHeaders) {
40
+ const merged = {};
41
+ // Transform and add default headers if they exist
42
+ if (defaultHeaders) {
43
+ const transformedDefaults = transformHeaders(defaultHeaders);
44
+ Object.assign(merged, transformedDefaults);
45
+ }
46
+ // Method headers override default headers
47
+ if (methodHeaders) {
48
+ Object.assign(merged, methodHeaders);
49
+ }
50
+ // Remove undefined values
51
+ Object.keys(merged).forEach((key) => {
52
+ if (merged[key] === undefined) {
53
+ delete merged[key];
54
+ }
55
+ });
56
+ return merged;
57
+ }
58
+ /**
59
+ * Get the list of supported header transformations
60
+ * Useful for debugging or documentation purposes
61
+ *
62
+ * @returns Copy of the header transformations mapping
63
+ */
64
+ export function getHeaderTransformations() {
65
+ return { ...HEADER_TRANSFORMATIONS };
66
+ }
@@ -0,0 +1,88 @@
1
+ import type { Middleware } from "openapi-fetch";
2
+ /**
3
+ * Debug logger function interface
4
+ */
5
+ export interface DebugLoggerFn {
6
+ (level: "info" | "warn" | "error", message: string, data?: any): void;
7
+ }
8
+ /**
9
+ * Response utilities for debugging and working with Response objects
10
+ */
11
+ export declare class ResponseUtils {
12
+ /**
13
+ * Get response headers as a plain object
14
+ */
15
+ static getHeaders(response: Response): Record<string, string>;
16
+ /**
17
+ * Get specific header value
18
+ */
19
+ static getHeader(response: Response, name: string): string | null;
20
+ /**
21
+ * Check if response was successful
22
+ */
23
+ static isSuccess(response: Response): boolean;
24
+ /**
25
+ * Get response metadata
26
+ */
27
+ static getMetadata(response: Response): {
28
+ status: number;
29
+ statusText: string;
30
+ ok: boolean;
31
+ url: string;
32
+ redirected: boolean;
33
+ type: ResponseType;
34
+ headers: {
35
+ [k: string]: string;
36
+ };
37
+ };
38
+ /**
39
+ * Clone and read response as text (useful for debugging)
40
+ * Note: This can only be called once per response
41
+ */
42
+ static getText(response: Response): Promise<string>;
43
+ /**
44
+ * Clone and read response as JSON (useful for debugging)
45
+ * Note: This can only be called once per response
46
+ */
47
+ static getJSON(response: Response): Promise<any>;
48
+ /**
49
+ * Format response information for debugging
50
+ */
51
+ static format(response: Response): string;
52
+ }
53
+ /**
54
+ * Debug logging utilities
55
+ */
56
+ export declare class DebugLogger {
57
+ private logger;
58
+ private responseTextCache;
59
+ constructor(logger?: DebugLoggerFn);
60
+ /**
61
+ * Log debug information about API request
62
+ */
63
+ logRequest(request: Request, requestBody?: any): void;
64
+ /**
65
+ * Log debug information about API response
66
+ */
67
+ logResponse(response: Response, responseBody?: any): Promise<void>;
68
+ /**
69
+ * Log error information
70
+ */
71
+ logError(message: string, error: any): void;
72
+ /**
73
+ * Get cached response text for a URL (if available)
74
+ */
75
+ getCachedResponseText(url: string): string | null;
76
+ /**
77
+ * Clear cached response texts
78
+ */
79
+ clearCache(): void;
80
+ }
81
+ /**
82
+ * Extract request body for logging
83
+ */
84
+ export declare function extractRequestBody(request: Request): Promise<any>;
85
+ /**
86
+ * Create debug middleware for openapi-fetch (internal use)
87
+ */
88
+ export declare function createDebugMiddleware(logger?: DebugLoggerFn): Middleware;
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Response utilities for debugging and working with Response objects
3
+ */
4
+ export class ResponseUtils {
5
+ /**
6
+ * Get response headers as a plain object
7
+ */
8
+ static getHeaders(response) {
9
+ return Object.fromEntries(response.headers.entries());
10
+ }
11
+ /**
12
+ * Get specific header value
13
+ */
14
+ static getHeader(response, name) {
15
+ return response.headers.get(name);
16
+ }
17
+ /**
18
+ * Check if response was successful
19
+ */
20
+ static isSuccess(response) {
21
+ return response.ok;
22
+ }
23
+ /**
24
+ * Get response metadata
25
+ */
26
+ static getMetadata(response) {
27
+ return {
28
+ status: response.status,
29
+ statusText: response.statusText,
30
+ ok: response.ok,
31
+ url: response.url,
32
+ redirected: response.redirected,
33
+ type: response.type,
34
+ headers: Object.fromEntries(response.headers.entries()),
35
+ };
36
+ }
37
+ /**
38
+ * Clone and read response as text (useful for debugging)
39
+ * Note: This can only be called once per response
40
+ */
41
+ static async getText(response) {
42
+ const cloned = response.clone();
43
+ return await cloned.text();
44
+ }
45
+ /**
46
+ * Clone and read response as JSON (useful for debugging)
47
+ * Note: This can only be called once per response
48
+ */
49
+ static async getJSON(response) {
50
+ const cloned = response.clone();
51
+ return await cloned.json();
52
+ }
53
+ /**
54
+ * Format response information for debugging
55
+ */
56
+ static format(response) {
57
+ const metadata = this.getMetadata(response);
58
+ return `${metadata.status} ${metadata.statusText} - ${metadata.url}`;
59
+ }
60
+ }
61
+ /**
62
+ * Debug logging utilities
63
+ */
64
+ export class DebugLogger {
65
+ logger;
66
+ responseTextCache = new Map();
67
+ constructor(logger) {
68
+ this.logger =
69
+ logger ||
70
+ ((level, message, data) => {
71
+ console.log(`[${level.toUpperCase()}]`, message);
72
+ if (data)
73
+ console.log(data);
74
+ });
75
+ }
76
+ /**
77
+ * Log debug information about API request
78
+ */
79
+ logRequest(request, requestBody) {
80
+ this.logger("info", "API Request Debug Info", {
81
+ method: request.method,
82
+ url: request.url,
83
+ headers: Object.fromEntries(request.headers.entries()),
84
+ body: requestBody,
85
+ timestamp: new Date().toISOString(),
86
+ });
87
+ }
88
+ /**
89
+ * Log debug information about API response
90
+ */
91
+ async logResponse(response, responseBody) {
92
+ // Cache response text for later use by ResponseUtils
93
+ if (responseBody && typeof responseBody === "string") {
94
+ this.responseTextCache.set(response.url, responseBody);
95
+ }
96
+ // Log response metadata
97
+ this.logger("info", "API Response Debug Info", {
98
+ url: response.url,
99
+ status: response.status,
100
+ statusText: response.statusText,
101
+ ok: response.ok,
102
+ headers: Object.fromEntries(response.headers.entries()),
103
+ redirected: response.redirected,
104
+ type: response.type,
105
+ timestamp: new Date().toISOString(),
106
+ });
107
+ // Log response body if available
108
+ if (responseBody) {
109
+ this.logger("info", "API Response Data", {
110
+ data: responseBody,
111
+ contentType: response.headers.get("content-type"),
112
+ contentLength: response.headers.get("content-length"),
113
+ });
114
+ }
115
+ }
116
+ /**
117
+ * Log error information
118
+ */
119
+ logError(message, error) {
120
+ this.logger("error", message, error);
121
+ }
122
+ /**
123
+ * Get cached response text for a URL (if available)
124
+ */
125
+ getCachedResponseText(url) {
126
+ return this.responseTextCache.get(url) || null;
127
+ }
128
+ /**
129
+ * Clear cached response texts
130
+ */
131
+ clearCache() {
132
+ this.responseTextCache.clear();
133
+ }
134
+ }
135
+ /**
136
+ * Extract request body for logging
137
+ */
138
+ export async function extractRequestBody(request) {
139
+ if (request.method === "GET" || request.method === "HEAD") {
140
+ return null;
141
+ }
142
+ try {
143
+ const clonedRequest = request.clone();
144
+ const contentType = request.headers.get("content-type")?.toLowerCase();
145
+ if (contentType?.startsWith("application/json")) {
146
+ return await clonedRequest.json();
147
+ }
148
+ else if (contentType?.startsWith("multipart/form-data")) {
149
+ return "[FormData - cannot display]";
150
+ }
151
+ else if (contentType?.startsWith("text/")) {
152
+ return await clonedRequest.text();
153
+ }
154
+ return "[Request body - unknown format]";
155
+ }
156
+ catch (error) {
157
+ return "[Request body unavailable]";
158
+ }
159
+ }
160
+ /**
161
+ * Create debug middleware for openapi-fetch (internal use)
162
+ */
163
+ export function createDebugMiddleware(logger) {
164
+ const debugLogger = new DebugLogger(logger);
165
+ return {
166
+ async onRequest({ request }) {
167
+ // Log request information
168
+ const requestBody = await extractRequestBody(request);
169
+ debugLogger.logRequest(request, requestBody);
170
+ return request;
171
+ },
172
+ async onResponse({ response }) {
173
+ // Clone response to read body without consuming it
174
+ const cloned = response.clone();
175
+ let responseBody = null;
176
+ try {
177
+ const contentType = response.headers.get("content-type")?.toLowerCase();
178
+ if (contentType?.startsWith("application/json")) {
179
+ responseBody = await cloned.json();
180
+ }
181
+ else if (contentType?.startsWith("text/")) {
182
+ responseBody = await cloned.text();
183
+ }
184
+ }
185
+ catch (error) {
186
+ // Ignore body reading errors
187
+ }
188
+ // Log response information
189
+ await debugLogger.logResponse(response, responseBody);
190
+ return response;
191
+ },
192
+ async onError({ error, request }) {
193
+ // Log error information with request context
194
+ debugLogger.logError("API Request Failed", {
195
+ error: {
196
+ name: error instanceof Error ? error.name : "Unknown",
197
+ message: error instanceof Error ? error.message : String(error),
198
+ stack: error instanceof Error ? error.stack : undefined,
199
+ },
200
+ request: {
201
+ method: request.method,
202
+ url: request.url,
203
+ headers: Object.fromEntries(request.headers.entries()),
204
+ },
205
+ timestamp: new Date().toISOString(),
206
+ });
207
+ // Re-throw the error to maintain normal error handling
208
+ throw error;
209
+ },
210
+ };
211
+ }
@@ -2,9 +2,11 @@ import type { paths } from './storefront';
2
2
  export type ApiResult<T> = {
3
3
  data: T;
4
4
  error: null;
5
+ response: Response;
5
6
  } | {
6
7
  data: null;
7
8
  error: ApiErrorResponse;
9
+ response: Response;
8
10
  };
9
11
  export type ApiErrorResponse = {
10
12
  success?: boolean;
@@ -56,6 +58,7 @@ export type ListCrosssellProductsQuery = paths['/catalog/products/cross-sell']['
56
58
  export type ListCrosssellProductsHeaderParams = paths['/catalog/products/cross-sell']['get']['parameters']['header'];
57
59
  export type SearchProductsResponse = paths['/catalog/products/search']['post']['responses'][200]['content']['application/json'];
58
60
  export type SearchProductsContent = SearchProductsResponse['content'];
61
+ export type SearchProductsHeaderParams = paths['/catalog/products/search']['post']['parameters']['header'];
59
62
  export type SearchProductsBody = NonNullable<paths['/catalog/products/search']['post']['requestBody']>['content']['application/json'];
60
63
  export type CreateCartResponse = paths['/carts']['post']['responses'][200]['content']['application/json'];
61
64
  export type CreateCartContent = CreateCartResponse['content'];
@@ -2426,8 +2426,6 @@ export interface components {
2426
2426
  * @default 25
2427
2427
  */
2428
2428
  limit: number;
2429
- /** @description to return pricing, promotion and subscriptions data for a specific customer group. Otherwise it will return data as per default customer group. */
2430
- customer_group_id?: string;
2431
2429
  /** @description provide list of attributes for specific facets or * for all facets.
2432
2430
  * ```json
2433
2431
  * For specific facets: ["size", "color", "brand"]
@@ -4540,7 +4538,7 @@ export interface components {
4540
4538
  sortingParam: string;
4541
4539
  /** @description search keyword */
4542
4540
  searchKeyword: string;
4543
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4541
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4544
4542
  CustomerGroupId: string;
4545
4543
  };
4546
4544
  requestBodies: never;
@@ -4564,8 +4562,8 @@ export interface operations {
4564
4562
  category_slug?: string[];
4565
4563
  };
4566
4564
  header?: {
4567
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4568
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4565
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4566
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4569
4567
  };
4570
4568
  path?: never;
4571
4569
  cookie?: never;
@@ -4607,8 +4605,8 @@ export interface operations {
4607
4605
  sku?: string[];
4608
4606
  };
4609
4607
  header?: {
4610
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4611
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4608
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4609
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4612
4610
  };
4613
4611
  path?: never;
4614
4612
  cookie?: never;
@@ -4639,8 +4637,8 @@ export interface operations {
4639
4637
  parameters: {
4640
4638
  query?: never;
4641
4639
  header?: {
4642
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4643
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4640
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4641
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4644
4642
  };
4645
4643
  path: {
4646
4644
  /** @description The unique identifier of the product. Can be either the product ID or the slug. */
@@ -4673,8 +4671,8 @@ export interface operations {
4673
4671
  parameters: {
4674
4672
  query?: never;
4675
4673
  header?: {
4676
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4677
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4674
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4675
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4678
4676
  };
4679
4677
  path: {
4680
4678
  /** @description ID of a particular product */
@@ -4707,8 +4705,8 @@ export interface operations {
4707
4705
  parameters: {
4708
4706
  query?: never;
4709
4707
  header?: {
4710
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4711
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4708
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4709
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4712
4710
  };
4713
4711
  path: {
4714
4712
  /** @description product id */
@@ -4870,8 +4868,8 @@ export interface operations {
4870
4868
  sort_by?: string;
4871
4869
  };
4872
4870
  header?: {
4873
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4874
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4871
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4872
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4875
4873
  };
4876
4874
  path?: never;
4877
4875
  cookie?: never;
@@ -4911,8 +4909,8 @@ export interface operations {
4911
4909
  sort_by?: string;
4912
4910
  };
4913
4911
  header?: {
4914
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4915
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4912
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4913
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4916
4914
  };
4917
4915
  path?: never;
4918
4916
  cookie?: never;
@@ -4953,8 +4951,8 @@ export interface operations {
4953
4951
  sort_by?: string;
4954
4952
  };
4955
4953
  header?: {
4956
- /** @description The customer_group_id is used to determine product pricing, promotions, and subscription rates. If a valid customer_group_id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer_group_id, the system will fall back to the default customer_group_id. If no data is found for the default group either, the highest applicable price will be returned. */
4957
- customer_group_id?: components["parameters"]["CustomerGroupId"];
4954
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4955
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4958
4956
  };
4959
4957
  path?: never;
4960
4958
  cookie?: never;
@@ -4984,7 +4982,10 @@ export interface operations {
4984
4982
  "search-products": {
4985
4983
  parameters: {
4986
4984
  query?: never;
4987
- header?: never;
4985
+ header?: {
4986
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
4987
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
4988
+ };
4988
4989
  path?: never;
4989
4990
  cookie?: never;
4990
4991
  };
@@ -5608,8 +5609,8 @@ export interface operations {
5608
5609
  parameters: {
5609
5610
  query?: never;
5610
5611
  header?: {
5611
- /** @description Commercengine customer group id. */
5612
- ce_customer_group_id?: string | null;
5612
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
5613
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
5613
5614
  };
5614
5615
  path?: never;
5615
5616
  cookie?: never;
@@ -5640,8 +5641,8 @@ export interface operations {
5640
5641
  parameters: {
5641
5642
  query?: never;
5642
5643
  header?: {
5643
- /** @description Commercengine customer group id. */
5644
- ce_customer_group_id?: string | null;
5644
+ /** @description This param is used to determine product pricing, promotions, and subscription rates. If a valid customer group id is provided, pricing details will be retrieved accordingly. If no matching data is found for the specified customer group id, the system will fall back to the default customer group id. If no data is found for the default group either, the highest applicable price will be returned. */
5645
+ "x-customer-group-id"?: components["parameters"]["CustomerGroupId"];
5645
5646
  };
5646
5647
  path?: never;
5647
5648
  cookie?: never;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercengine/storefront-sdk",
3
- "version": "0.3.9",
3
+ "version": "0.3.11",
4
4
  "description": "TypeScript SDK for the Storefront API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",