@commercengine/storefront-sdk 0.3.10 → 0.3.12

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/README.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Storefront SDK
2
2
 
3
- TypeScript SDK for the CommerceEngine Storefront API.
3
+ A powerful, type-safe TypeScript SDK for the CommerceEngine Storefront API. Built with modern JavaScript patterns, automatic token management, and comprehensive error handling.
4
+
5
+ **✨ Key Features:**
6
+ - **100% Type Safe**: Every API endpoint is fully typed with TypeScript
7
+ - **Automatic Token Management**: Built-in refresh token logic for seamless authentication
8
+ - **Universal Compatibility**: Works in browser, Node.js, and hybrid rendering environments
9
+ - **Production Ready**: Implements all API best practices out of the box
10
+ - **Zero Configuration**: Works with sensible defaults, extensive customization available
4
11
 
5
12
  ## Installation
6
13
 
@@ -8,104 +15,398 @@ TypeScript SDK for the CommerceEngine Storefront API.
8
15
  npm install @commercengine/storefront-sdk
9
16
  ```
10
17
 
11
- Or with yarn:
12
-
13
18
  ```bash
14
19
  yarn add @commercengine/storefront-sdk
15
20
  ```
16
21
 
17
- Or with pnpm:
18
-
19
22
  ```bash
20
23
  pnpm add @commercengine/storefront-sdk
21
24
  ```
22
25
 
23
- ## Usage
24
-
25
- ### Initializing the SDK
26
-
27
- You can initialize the SDK in just a few lines:
26
+ ## Quick Start
28
27
 
29
28
  ```typescript
30
29
  import StorefrontSDK, { Environment } from "@commercengine/storefront-sdk";
31
30
 
32
- // Initialize with environment and store ID
31
+ // Basic initialization
32
+ const sdk = new StorefrontSDK({
33
+ storeId: "your-store-id",
34
+ environment: Environment.Staging,
35
+ apiKey: "your-api-key", // Required for authentication
36
+ });
37
+
38
+ // Get started with anonymous authentication
39
+ const { data, error } = await sdk.auth.getAnonymousToken();
40
+ if (error) {
41
+ console.log(error)
42
+ } else {
43
+ accessToken = data.accessToken
44
+ }
45
+ ```
46
+
47
+ ## Configuration Options
48
+
49
+ The SDK supports extensive configuration to fit your needs:
50
+
51
+ ### Basic Configuration
52
+
53
+ ```typescript
33
54
  const sdk = new StorefrontSDK({
55
+ // Required
34
56
  storeId: "your-store-id",
57
+
58
+ // Environment (optional, defaults to Production)
35
59
  environment: Environment.Staging, // or Environment.Production
60
+
61
+ // API key for authentication (required for auth endpoints)
62
+ apiKey: "your-api-key",
36
63
  });
64
+ ```
65
+
66
+ ### Advanced Configuration
37
67
 
38
- // Or with a custom base URL (if needed)
39
- const customSdk = new StorefrontSDK({
68
+ ```typescript
69
+ const sdk = new StorefrontSDK({
40
70
  storeId: "your-store-id",
41
- baseUrl: "https://custom-api.example.com",
71
+ environment: Environment.Production,
72
+
73
+ // Token Management
74
+ accessToken: "initial-access-token", // Initial access token
75
+ refreshToken: "initial-refresh-token", // Initial refresh token (for automatic mode)
76
+
77
+ // Custom base URL (optional, overrides environment) - Not needed for most implementations
78
+ baseUrl: "https://your-custom-api.example.com",
79
+
80
+ // Request Configuration
81
+ timeout: 10000, // Request timeout in milliseconds
82
+
83
+ // Default Headers (auto applied to all applicable requests)
84
+ defaultHeaders: {
85
+ customer_group_id: "01JHS28V83KDWTRBXXJQRTEKA0", // For pricing and promotions
86
+ },
87
+
88
+ // Debug and Logging
89
+ debug: true, // Enable detailed request/response logging - Uses console.log by default
90
+ logger: console.log, // Custom logger function - structure your logs any way you want. Also helpful to pipe logs into external services
42
91
  });
43
92
  ```
44
93
 
45
- ### Authentication
94
+ ## Token Management
95
+
96
+ The SDK offers two approaches to token management:
97
+
98
+ ### 1. Manual Token Management (Simple)
46
99
 
47
- The SDK supports various authentication methods:
100
+ For basic use cases where you manage tokens yourself:
48
101
 
49
102
  ```typescript
50
- // Anonymous authentication
51
- const { access_token, refresh_token, user } =
52
- await sdk.auth.getAnonymousToken();
103
+ const sdk = new StorefrontSDK({
104
+ storeId: "your-store-id",
105
+ apiKey: "your-api-key",
106
+ });
53
107
 
54
- // Phone login
55
- const { otp_token, otp_action } = await sdk.auth.loginWithPhone("9876543210");
108
+ // Login and set tokens manually
109
+ const { data: loginData } = await sdk.auth.loginWithPassword({
110
+ email: "user@example.com",
111
+ password: "password",
112
+ });
56
113
 
57
- // Email login
58
- const { otp_token, otp_action } = await sdk.auth.loginWithEmail(
59
- "user@example.com"
60
- );
114
+ if (loginData) {
115
+ await sdk.setTokens(loginData.access_token);
116
+ }
117
+ ```
61
118
 
62
- // Verify OTP
63
- const { user, access_token, refresh_token } = await sdk.auth.verifyOtp(
64
- "123456",
65
- otp_token,
66
- "login"
67
- );
119
+ ### 2. Automatic Token Management (Recommended)
68
120
 
69
- // Password login
70
- const { user, access_token, refresh_token } = await sdk.auth.loginWithPassword({
71
- email: "user@example.com",
72
- password: "your-password",
121
+ For production applications with automatic token refresh and persistence:
122
+
123
+ ```typescript
124
+ import StorefrontSDK, { BrowserTokenStorage } from "@commercengine/storefront-sdk";
125
+
126
+ const sdk = new StorefrontSDK({
127
+ storeId: "your-store-id",
128
+ apiKey: "your-api-key",
129
+
130
+ // Enable automatic token management
131
+ tokenStorage: new BrowserTokenStorage("myapp_"), // Prefix for localStorage keys
132
+
133
+ // Optional callbacks
134
+ onTokensUpdated: (accessToken, refreshToken) => {
135
+ console.log("Tokens updated!");
136
+ },
137
+ onTokensCleared: () => {
138
+ console.log("User logged out");
139
+ },
140
+ });
141
+ ```
142
+
143
+ ### Token Storage Options
144
+
145
+ Choose the storage method that fits your environment:
146
+
147
+ #### Browser localStorage
148
+ ```typescript
149
+ import { BrowserTokenStorage } from "@commercengine/storefront-sdk";
150
+
151
+ const tokenStorage = new BrowserTokenStorage("myapp_"); // Optional prefix
152
+ ```
153
+
154
+ #### Cookies (for SSR or cross-tab sync)
155
+ ```typescript
156
+ import { CookieTokenStorage } from "@commercengine/storefront-sdk";
157
+
158
+ const tokenStorage = new CookieTokenStorage({
159
+ prefix: "myapp_",
160
+ maxAge: 7 * 24 * 60 * 60, // 7 days
161
+ secure: true,
162
+ sameSite: "Lax",
73
163
  });
164
+ ```
165
+
166
+ #### Memory (for server-side or temporary storage)
167
+ ```typescript
168
+ import { MemoryTokenStorage } from "@commercengine/storefront-sdk";
169
+
170
+ const tokenStorage = new MemoryTokenStorage();
171
+ ```
172
+
173
+ #### Custom Storage
174
+ ```typescript
175
+ class CustomTokenStorage implements TokenStorage {
176
+ async getAccessToken(): Promise<string | null> {
177
+ // Your implementation
178
+ }
179
+
180
+ async setAccessToken(token: string): Promise<void> {
181
+ // Your implementation
182
+ }
183
+
184
+ // ... implement other required methods
185
+ }
186
+ ```
74
187
 
75
- // Registration
76
- const { user, access_token, refresh_token } = await sdk.auth.registerWithPhone({
188
+ ## Authentication
189
+
190
+ ### Anonymous Authentication
191
+ ```typescript
192
+ // Get anonymous token for guest users
193
+ const { data } = await sdk.auth.getAnonymousToken();
194
+ if (data) {
195
+ await sdk.setTokens(data.access_token, data.refresh_token);
196
+ }
197
+ ```
198
+
199
+ ### Phone/Email Authentication
200
+ ```typescript
201
+ // Step 1: Initiate login
202
+ const { data: otpData } = await sdk.auth.loginWithPhone({
77
203
  phone: "9876543210",
204
+ country_code: "+91",
205
+ register_if_not_exists: true,
206
+ });
207
+
208
+ // Step 2: Verify OTP
209
+ if (otpData) {
210
+ const { data: authData } = await sdk.auth.verifyOtp({
211
+ otp: "123456",
212
+ otp_token: otpData.otp_token,
213
+ otp_action: otpData.otp_action,
214
+ });
215
+
216
+ if (authData) {
217
+ await sdk.setTokens(authData.access_token, authData.refresh_token);
218
+ }
219
+ }
220
+ ```
221
+
222
+ ### Password Authentication
223
+ ```typescript
224
+ const { data } = await sdk.auth.loginWithPassword({
78
225
  email: "user@example.com",
79
- first_name: "John",
80
- last_name: "Doe",
226
+ password: "your-password",
227
+ });
228
+
229
+ if (data) {
230
+ await sdk.setTokens(data.access_token, data.refresh_token);
231
+ }
232
+ ```
233
+
234
+ ## API Clients & Complete Type Safety
235
+
236
+ The SDK provides **complete access to every CommerceEngine API endpoint** with full TypeScript support. All clients are automatically generated from the OpenAPI specification, ensuring 100% accuracy and type safety.
237
+
238
+ ### Available Clients
239
+
240
+ ```typescript
241
+ // Authentication & User Management
242
+ sdk.auth.* // Login, registration, OTP, password management
243
+ sdk.customer.* // Customer profiles, addresses, preferences
244
+
245
+ // E-commerce Core
246
+ sdk.catalog.* // Products, categories, search, variants
247
+ sdk.cart.* // Cart management, coupons, promotions
248
+ sdk.order.* // Order creation, tracking, history
249
+
250
+ // Supporting Services
251
+ sdk.shipping.* // Shipping methods, rates, tracking
252
+ sdk.helpers.* // Countries, currencies, utilities
253
+ ```
254
+
255
+ ### Example Usage
256
+
257
+ ```typescript
258
+ // Every method is fully typed - IntelliSense shows all available parameters
259
+ const { data: products } = await sdk.catalog.listProducts({
260
+ query: {
261
+ page: 1,
262
+ limit: 20,
263
+ category_id: "electronics",
264
+ sort: "price_asc",
265
+ }
266
+ });
267
+
268
+ // Get product details
269
+ const { data: product } = await sdk.catalog.getProduct({
270
+ product_id_or_slug: "product-id"
81
271
  });
82
272
 
83
- // Token management
84
- sdk.setToken(access_token); // Set token for all clients
85
- sdk.clearToken(); // Clear token from all clients
273
+ // Create a cart with full type checking
274
+ const { data: cart } = await sdk.cart.createCart({
275
+ items: [
276
+ {
277
+ product_id: "product-id",
278
+ quantity: 2,
279
+ variant_id: "variant-id",
280
+ }
281
+ ]
282
+ });
283
+ ```
284
+
285
+ > **📚 API Reference**: For complete endpoint documentation, parameters, and response schemas, visit [docs.commercengine.io/api-reference](https://docs.commercengine.io/api-reference)
286
+
287
+ ## User Information & JWT Utilities
288
+
289
+ Extract user information from tokens with built-in utilities:
290
+
291
+ ```typescript
292
+ // Get current user info
293
+ const userInfo = await sdk.getUserInfo();
294
+ console.log(userInfo?.userId, userInfo?.email, userInfo?.customerId);
295
+
296
+ // Check authentication status
297
+ const isLoggedIn = await sdk.isLoggedIn();
298
+ const isAnonymous = await sdk.isAnonymous();
299
+
300
+ // Get specific user data
301
+ const userId = await sdk.getUserId();
302
+ const customerId = await sdk.getCustomerId();
303
+ const customerGroupId = await sdk.getCustomerGroupId();
86
304
  ```
87
305
 
88
- ### Using the API Clients
306
+ ## Error Handling
307
+
308
+ All API calls return a consistent `ApiResult<T>` structure with full error information:
309
+
310
+ ```typescript
311
+ const { data, error, response } = await sdk.catalog.listProducts();
89
312
 
90
- The SDK provides dedicated clients for different API sections:
313
+ if (error) {
314
+ console.error("API Error:", error.message, error.code);
315
+ console.log("Status:", response.status);
316
+ } else {
317
+ console.log("Success:", data);
318
+ }
319
+ ```
91
320
 
321
+ ### Network Error Handling
92
322
  ```typescript
93
- // Catalog client example (product listing)
94
- const products = await sdk.catalog.listProducts();
323
+ const result = await sdk.catalog.getProduct({ product_id_or_slug: "invalid-id" });
95
324
 
96
- // Cart client example (add to cart)
97
- const cart = await sdk.cart.addToCart("product-id", 1);
325
+ if (result.error) {
326
+ switch (result.error.code) {
327
+ case "NETWORK_ERROR":
328
+ console.log("Network connection failed");
329
+ break;
330
+ case "UNAUTHORIZED":
331
+ console.log("Authentication required");
332
+ break;
333
+ default:
334
+ console.log("API Error:", result.error.message);
335
+ }
336
+ }
98
337
  ```
99
338
 
100
- ## Advanced Configuration
339
+ ## Debug Mode
101
340
 
102
- You can configure timeout and other options:
341
+ Enable detailed logging for development:
103
342
 
104
343
  ```typescript
105
344
  const sdk = new StorefrontSDK({
106
345
  storeId: "your-store-id",
107
- environment: Environment.Production,
108
- timeout: 5000, // 5 second timeout
109
- token: "existing-token", // Initialize with an existing token
346
+ debug: true,
347
+ // Optional: Pass a custom logger
348
+ logger: (message, data) => {
349
+ console.log(`[SDK Debug] ${message}`, data);
350
+ },
110
351
  });
111
352
  ```
353
+
354
+ Debug mode logs:
355
+ - Request URLs, methods, headers, and bodies
356
+ - Response status, headers, and bodies
357
+ - Token refresh attempts and results
358
+ - Network errors and retry attempts
359
+
360
+ ## TypeScript Support
361
+
362
+ The SDK is built with TypeScript-first design:
363
+
364
+ ```typescript
365
+ import type {
366
+ ApiResult,
367
+ UserInfo,
368
+ DebugLoggerFn,
369
+ SupportedDefaultHeaders
370
+ } from "@commercengine/storefront-sdk";
371
+
372
+ // All API responses are properly typed
373
+ const { data }: ApiResult<ProductListResponse> = await sdk.catalog.listProducts();
374
+
375
+ // IntelliSense works for all nested properties
376
+ console.log(data?.products[0].name);
377
+ ```
378
+
379
+ ## Universal Compatibility
380
+
381
+ The SDK works seamlessly across all JavaScript environments:
382
+
383
+ ### Client-Side Applications
384
+ - **React, Vue, Angular**: Use `BrowserTokenStorage` for persistent sessions
385
+ - **Automatic token refresh**: Handles token expiry transparently
386
+ - **Cross-tab synchronization**: With `CookieTokenStorage`
387
+
388
+ ### Server-Side Applications
389
+ - **Node.js, Bun, Deno**: Use `MemoryTokenStorage` or custom storage
390
+ - **API routes**: Perfect for Next.js API routes, Express middleware
391
+ - **Background jobs**: Reliable token management for long-running processes
392
+
393
+ ### Hybrid Rendering (SSR/SSG)
394
+ - **Next.js, Nuxt, SvelteKit**: Seamless client/server token handoff
395
+ - **Cookie-based storage**: Maintains sessions across server/client boundaries
396
+ - **Hydration-safe**: No client/server state mismatches
397
+
398
+ ## Best Practices Built-In
399
+
400
+ The SDK implements CommerceEngine API best practices automatically:
401
+
402
+ - ✅ **Automatic token refresh** before expiry
403
+ - ✅ **Proper error handling** for all edge cases
404
+ - ✅ **Request retries** for transient failures
405
+ - ✅ **Rate limiting compliance** with proper backoff
406
+ - ✅ **Security headers** and CSRF protection
407
+ - ✅ **Timeout handling** with configurable limits
408
+ - ✅ **Memory leak prevention** with proper cleanup
409
+
410
+ ## License
411
+
412
+ This project is licensed under the MIT License.
package/dist/index.js CHANGED
@@ -8,7 +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
+ import { ResponseUtils } from "./lib/logger-utils";
12
12
  /**
13
13
  * Main SDK class for the Storefront API
14
14
  */
@@ -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
  }
@@ -2,6 +2,7 @@ import createClient from "openapi-fetch";
2
2
  import { createDefaultAuthMiddleware } from "./middleware";
3
3
  import { getPathnameFromUrl, isAnonymousAuthEndpoint } from "./auth-utils";
4
4
  import { createDebugMiddleware } from "./logger-utils";
5
+ import { mergeHeaders } from "./header-utils";
5
6
  /**
6
7
  * Available API environments
7
8
  */
@@ -288,32 +289,9 @@ export class StorefrontAPIClient {
288
289
  * Method-level headers take precedence over default headers
289
290
  *
290
291
  * @param methodHeaders - Headers passed to the specific method call
291
- * @returns Merged headers object
292
+ * @returns Merged headers object with proper HTTP header names
292
293
  */
293
294
  mergeHeaders(methodHeaders) {
294
- if (!this.config.defaultHeaders && !methodHeaders) {
295
- return {};
296
- }
297
- // Start with default headers, but only include supported ones
298
- const merged = {};
299
- // Add default headers if they exist
300
- if (this.config.defaultHeaders) {
301
- if (this.config.defaultHeaders.customer_group_id !== undefined) {
302
- merged.customer_group_id =
303
- this.config.defaultHeaders.customer_group_id;
304
- }
305
- // Future: Add other supported headers here as they become available
306
- }
307
- if (methodHeaders) {
308
- // Method headers override default headers
309
- Object.assign(merged, methodHeaders);
310
- }
311
- // Remove undefined values
312
- Object.keys(merged).forEach((key) => {
313
- if (merged[key] === undefined) {
314
- delete merged[key];
315
- }
316
- });
317
- return merged;
295
+ return mergeHeaders(this.config.defaultHeaders, methodHeaders);
318
296
  }
319
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
+ }
@@ -58,6 +58,7 @@ export type ListCrosssellProductsQuery = paths['/catalog/products/cross-sell']['
58
58
  export type ListCrosssellProductsHeaderParams = paths['/catalog/products/cross-sell']['get']['parameters']['header'];
59
59
  export type SearchProductsResponse = paths['/catalog/products/search']['post']['responses'][200]['content']['application/json'];
60
60
  export type SearchProductsContent = SearchProductsResponse['content'];
61
+ export type SearchProductsHeaderParams = paths['/catalog/products/search']['post']['parameters']['header'];
61
62
  export type SearchProductsBody = NonNullable<paths['/catalog/products/search']['post']['requestBody']>['content']['application/json'];
62
63
  export type CreateCartResponse = paths['/carts']['post']['responses'][200]['content']['application/json'];
63
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.10",
3
+ "version": "0.3.12",
4
4
  "description": "TypeScript SDK for the Storefront API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",