@commercengine/storefront-sdk 0.2.0 → 0.3.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.
@@ -15,19 +15,19 @@ export declare class CartClient extends StorefrontAPIClient {
15
15
  /**
16
16
  * Get the stored cart ID
17
17
  *
18
- * @returns The cart ID or null if not found
18
+ * @returns Promise that resolves to the cart ID or null if not found
19
19
  */
20
- getCartId(): string | null;
20
+ getCartId(): Promise<string | null>;
21
21
  /**
22
22
  * Set the cart ID in storage
23
23
  *
24
24
  * @param cartId - The cart ID to store
25
25
  */
26
- setCartId(cartId: string): void;
26
+ setCartId(cartId: string): Promise<void>;
27
27
  /**
28
28
  * Clear the stored cart ID
29
29
  */
30
- clearCartId(): void;
30
+ clearCartId(): Promise<void>;
31
31
  /**
32
32
  * Create a new cart
33
33
  *
package/dist/lib/cart.js CHANGED
@@ -21,24 +21,24 @@ class CartClient extends client_1.StorefrontAPIClient {
21
21
  /**
22
22
  * Get the stored cart ID
23
23
  *
24
- * @returns The cart ID or null if not found
24
+ * @returns Promise that resolves to the cart ID or null if not found
25
25
  */
26
- getCartId() {
27
- return this.clientStorage?.getCartId() || null;
26
+ async getCartId() {
27
+ return this.clientStorage?.getCartId() ?? null;
28
28
  }
29
29
  /**
30
30
  * Set the cart ID in storage
31
31
  *
32
32
  * @param cartId - The cart ID to store
33
33
  */
34
- setCartId(cartId) {
35
- this.clientStorage?.setCartId(cartId);
34
+ async setCartId(cartId) {
35
+ await this.clientStorage?.setCartId(cartId);
36
36
  }
37
37
  /**
38
38
  * Clear the stored cart ID
39
39
  */
40
- clearCartId() {
41
- this.clientStorage?.clearCartId();
40
+ async clearCartId() {
41
+ await this.clientStorage?.clearCartId();
42
42
  }
43
43
  /**
44
44
  * Create a new cart
@@ -56,7 +56,7 @@ class CartClient extends client_1.StorefrontAPIClient {
56
56
  }
57
57
  // Store the cart ID
58
58
  if (data?.content?.cart?.id) {
59
- this.setCartId(data.content.cart.id);
59
+ await this.setCartId(data.content.cart.id);
60
60
  }
61
61
  return data?.content;
62
62
  });
@@ -70,7 +70,7 @@ class CartClient extends client_1.StorefrontAPIClient {
70
70
  */
71
71
  async getCart(cartId) {
72
72
  // Use provided cartId or stored cartId
73
- const id = cartId || this.getCartId();
73
+ const id = cartId || (await this.getCartId());
74
74
  if (!id) {
75
75
  throw new Error("Cart ID is required but not provided");
76
76
  }
@@ -95,23 +95,26 @@ class CartClient extends client_1.StorefrontAPIClient {
95
95
  */
96
96
  async deleteCart(cartId) {
97
97
  // Use provided cartId or stored cartId
98
- const id = cartId || this.getCartId();
98
+ const id = cartId || (await this.getCartId());
99
99
  if (!id) {
100
100
  throw new Error("Cart ID is required but not provided");
101
101
  }
102
- const { error } = await this.client.DELETE("/carts/{id}", {
103
- params: {
104
- path: { id },
105
- },
106
- body: undefined,
102
+ return this.executeRequest(async () => {
103
+ const { error } = await this.client.DELETE("/carts/{id}", {
104
+ params: {
105
+ path: { id },
106
+ },
107
+ body: undefined,
108
+ });
109
+ if (error) {
110
+ this.handleError(error);
111
+ }
112
+ // Clear the stored cart ID if we deleted the current cart
113
+ const storedCartId = await this.getCartId();
114
+ if (cartId === undefined || cartId === storedCartId) {
115
+ await this.clearCartId();
116
+ }
107
117
  });
108
- if (error) {
109
- this.handleError(error);
110
- }
111
- // Clear the stored cart ID if we deleted the current cart
112
- if (cartId === undefined || cartId === this.getCartId()) {
113
- this.clearCartId();
114
- }
115
118
  }
116
119
  /**
117
120
  * Add item to cart - either by specified ID or stored cart ID
@@ -123,7 +126,7 @@ class CartClient extends client_1.StorefrontAPIClient {
123
126
  */
124
127
  async addItem(item, cartId) {
125
128
  // Check if we have a cart ID (either provided or stored)
126
- const id = cartId || this.getCartId();
129
+ const id = cartId || (await this.getCartId());
127
130
  // If we don't have a cart ID, create a new cart
128
131
  if (!id) {
129
132
  return this.createCart({ items: [item] });
@@ -141,20 +144,22 @@ class CartClient extends client_1.StorefrontAPIClient {
141
144
  */
142
145
  async updateCartItem(cartId, item) {
143
146
  // Use provided cartId or stored cartId
144
- const id = cartId || this.getCartId();
147
+ const id = cartId || (await this.getCartId());
145
148
  if (!id) {
146
149
  throw new Error("Cart ID is required but not provided");
147
150
  }
148
- const { data, error } = await this.client.POST("/carts/{id}/items", {
149
- params: {
150
- path: { id },
151
- },
152
- body: item,
151
+ return this.executeRequest(async () => {
152
+ const { data, error } = await this.client.POST("/carts/{id}/items", {
153
+ params: {
154
+ path: { id },
155
+ },
156
+ body: item,
157
+ });
158
+ if (error) {
159
+ this.handleError(error);
160
+ }
161
+ return data?.content;
153
162
  });
154
- if (error) {
155
- this.handleError(error);
156
- }
157
- return data?.content;
158
163
  }
159
164
  /**
160
165
  * Get cart details by user ID
@@ -163,15 +168,21 @@ class CartClient extends client_1.StorefrontAPIClient {
163
168
  * @returns Promise with cart details
164
169
  */
165
170
  async getUserCart(userId) {
166
- const { data, error } = await this.client.GET("/carts/users/{user_id}", {
167
- params: {
168
- path: { user_id: userId },
169
- },
171
+ return this.executeRequest(async () => {
172
+ const { data, error } = await this.client.GET("/carts/users/{user_id}", {
173
+ params: {
174
+ path: { user_id: userId },
175
+ },
176
+ });
177
+ if (error) {
178
+ this.handleError(error);
179
+ }
180
+ // Store the cart ID if present
181
+ if (data?.content?.cart?.id) {
182
+ await this.setCartId(data.content.cart.id);
183
+ }
184
+ return data?.content;
170
185
  });
171
- if (error) {
172
- this.handleError(error);
173
- }
174
- return data?.content;
175
186
  }
176
187
  /**
177
188
  * Delete a cart by user ID
@@ -180,15 +191,19 @@ class CartClient extends client_1.StorefrontAPIClient {
180
191
  * @returns Promise that resolves when the cart is deleted
181
192
  */
182
193
  async deleteUserCart(userId) {
183
- const { error } = await this.client.DELETE("/carts/users/{user_id}", {
184
- params: {
185
- path: { user_id: userId },
186
- },
187
- body: undefined,
194
+ return this.executeRequest(async () => {
195
+ const { error } = await this.client.DELETE("/carts/users/{user_id}", {
196
+ params: {
197
+ path: { user_id: userId },
198
+ },
199
+ body: undefined,
200
+ });
201
+ if (error) {
202
+ this.handleError(error);
203
+ }
204
+ // Clear the stored cart ID since we deleted the user's cart
205
+ await this.clearCartId();
188
206
  });
189
- if (error) {
190
- this.handleError(error);
191
- }
192
207
  }
193
208
  /**
194
209
  * Update cart addresses
@@ -198,16 +213,18 @@ class CartClient extends client_1.StorefrontAPIClient {
198
213
  * @returns Promise with updated cart
199
214
  */
200
215
  async updateCartAddress(cartId, addressData) {
201
- const { data, error } = await this.client.POST("/carts/{id}/address", {
202
- params: {
203
- path: { id: cartId },
204
- },
205
- body: addressData,
216
+ return this.executeRequest(async () => {
217
+ const { data, error } = await this.client.POST("/carts/{id}/address", {
218
+ params: {
219
+ path: { id: cartId },
220
+ },
221
+ body: addressData,
222
+ });
223
+ if (error) {
224
+ this.handleError(error);
225
+ }
226
+ return data?.content;
206
227
  });
207
- if (error) {
208
- this.handleError(error);
209
- }
210
- return data?.content;
211
228
  }
212
229
  /**
213
230
  * Apply a coupon to the cart
@@ -217,16 +234,18 @@ class CartClient extends client_1.StorefrontAPIClient {
217
234
  * @returns Promise with updated cart
218
235
  */
219
236
  async applyCoupon(cartId, couponCode) {
220
- const { data, error } = await this.client.POST("/carts/{id}/coupon", {
221
- params: {
222
- path: { id: cartId },
223
- },
224
- body: { coupon_code: couponCode },
237
+ return this.executeRequest(async () => {
238
+ const { data, error } = await this.client.POST("/carts/{id}/coupon", {
239
+ params: {
240
+ path: { id: cartId },
241
+ },
242
+ body: { coupon_code: couponCode },
243
+ });
244
+ if (error) {
245
+ this.handleError(error);
246
+ }
247
+ return data?.content;
225
248
  });
226
- if (error) {
227
- this.handleError(error);
228
- }
229
- return data?.content;
230
249
  }
231
250
  /**
232
251
  * Remove a coupon from the cart
@@ -235,16 +254,18 @@ class CartClient extends client_1.StorefrontAPIClient {
235
254
  * @returns Promise with updated cart
236
255
  */
237
256
  async removeCoupon(cartId) {
238
- const { data, error } = await this.client.DELETE("/carts/{id}/coupon", {
239
- params: {
240
- path: { id: cartId },
241
- },
242
- body: undefined,
257
+ return this.executeRequest(async () => {
258
+ const { data, error } = await this.client.DELETE("/carts/{id}/coupon", {
259
+ params: {
260
+ path: { id: cartId },
261
+ },
262
+ body: undefined,
263
+ });
264
+ if (error) {
265
+ this.handleError(error);
266
+ }
267
+ return data?.content;
243
268
  });
244
- if (error) {
245
- this.handleError(error);
246
- }
247
- return data?.content;
248
269
  }
249
270
  /**
250
271
  * Redeem loyalty points
@@ -254,16 +275,18 @@ class CartClient extends client_1.StorefrontAPIClient {
254
275
  * @returns Promise with updated cart
255
276
  */
256
277
  async redeemLoyaltyPoints(cartId, points) {
257
- const { data, error } = await this.client.POST("/carts/{id}/loyalty-points", {
258
- params: {
259
- path: { id: cartId },
260
- },
261
- body: { loyalty_point_redeemed: points },
278
+ return this.executeRequest(async () => {
279
+ const { data, error } = await this.client.POST("/carts/{id}/loyalty-points", {
280
+ params: {
281
+ path: { id: cartId },
282
+ },
283
+ body: { loyalty_point_redeemed: points },
284
+ });
285
+ if (error) {
286
+ this.handleError(error);
287
+ }
288
+ return data?.content;
262
289
  });
263
- if (error) {
264
- this.handleError(error);
265
- }
266
- return data?.content;
267
290
  }
268
291
  /**
269
292
  * Remove loyalty points
@@ -272,16 +295,18 @@ class CartClient extends client_1.StorefrontAPIClient {
272
295
  * @returns Promise with updated cart
273
296
  */
274
297
  async removeLoyaltyPoints(cartId) {
275
- const { data, error } = await this.client.DELETE("/carts/{id}/loyalty-points", {
276
- params: {
277
- path: { id: cartId },
278
- },
279
- body: undefined,
298
+ return this.executeRequest(async () => {
299
+ const { data, error } = await this.client.DELETE("/carts/{id}/loyalty-points", {
300
+ params: {
301
+ path: { id: cartId },
302
+ },
303
+ body: undefined,
304
+ });
305
+ if (error) {
306
+ this.handleError(error);
307
+ }
308
+ return data?.content;
280
309
  });
281
- if (error) {
282
- this.handleError(error);
283
- }
284
- return data?.content;
285
310
  }
286
311
  }
287
312
  exports.CartClient = CartClient;
@@ -31,16 +31,18 @@ class CatalogClient extends client_1.StorefrontAPIClient {
31
31
  * @returns Promise with product details
32
32
  */
33
33
  async getProductDetail(productId, options) {
34
- const { data, error } = await this.client.GET("/catalog/products/{product_id}", {
35
- params: {
36
- path: { product_id: productId },
37
- query: options,
38
- },
34
+ return this.executeRequest(async () => {
35
+ const { data, error } = await this.client.GET("/catalog/products/{product_id}", {
36
+ params: {
37
+ path: { product_id: productId },
38
+ query: options,
39
+ },
40
+ });
41
+ if (error) {
42
+ this.handleError(error);
43
+ }
44
+ return data?.content;
39
45
  });
40
- if (error) {
41
- this.handleError(error);
42
- }
43
- return data?.content;
44
46
  }
45
47
  /**
46
48
  * List variants for a specific product
@@ -50,16 +52,18 @@ class CatalogClient extends client_1.StorefrontAPIClient {
50
52
  * @returns Promise with variants
51
53
  */
52
54
  async listProductVariants(productId, options) {
53
- const { data, error } = await this.client.GET("/catalog/products/{product_id}/variants", {
54
- params: {
55
- path: { product_id: productId },
56
- query: options,
57
- },
55
+ return this.executeRequest(async () => {
56
+ const { data, error } = await this.client.GET("/catalog/products/{product_id}/variants", {
57
+ params: {
58
+ path: { product_id: productId },
59
+ query: options,
60
+ },
61
+ });
62
+ if (error) {
63
+ this.handleError(error);
64
+ }
65
+ return data?.content;
58
66
  });
59
- if (error) {
60
- this.handleError(error);
61
- }
62
- return data?.content;
63
67
  }
64
68
  /**
65
69
  * Get details for a specific variant
@@ -70,19 +74,21 @@ class CatalogClient extends client_1.StorefrontAPIClient {
70
74
  * @returns Promise with variant details
71
75
  */
72
76
  async getVariantDetail(productId, variantId, options) {
73
- const { data, error } = await this.client.GET("/catalog/products/{product_id}/variants/{variant_id}", {
74
- params: {
75
- path: {
76
- product_id: productId,
77
- variant_id: variantId,
77
+ return this.executeRequest(async () => {
78
+ const { data, error } = await this.client.GET("/catalog/products/{product_id}/variants/{variant_id}", {
79
+ params: {
80
+ path: {
81
+ product_id: productId,
82
+ variant_id: variantId,
83
+ },
84
+ query: options,
78
85
  },
79
- query: options,
80
- },
86
+ });
87
+ if (error) {
88
+ this.handleError(error);
89
+ }
90
+ return data?.content;
81
91
  });
82
- if (error) {
83
- this.handleError(error);
84
- }
85
- return data?.content;
86
92
  }
87
93
  /**
88
94
  * List all categories
@@ -91,13 +97,15 @@ class CatalogClient extends client_1.StorefrontAPIClient {
91
97
  * @returns Promise with categories and pagination info
92
98
  */
93
99
  async listCategories(options) {
94
- const { data, error } = await this.client.GET("/catalog/categories", {
95
- params: { query: options },
100
+ return this.executeRequest(async () => {
101
+ const { data, error } = await this.client.GET("/catalog/categories", {
102
+ params: { query: options },
103
+ });
104
+ if (error) {
105
+ this.handleError(error);
106
+ }
107
+ return data?.content;
96
108
  });
97
- if (error) {
98
- this.handleError(error);
99
- }
100
- return data?.content;
101
109
  }
102
110
  /**
103
111
  * List reviews for a specific product
@@ -107,16 +115,18 @@ class CatalogClient extends client_1.StorefrontAPIClient {
107
115
  * @returns Promise with reviews and pagination info
108
116
  */
109
117
  async listProductReviews(productId, options) {
110
- const { data, error } = await this.client.GET("/catalog/products/{product_id}/reviews", {
111
- params: {
112
- path: { product_id: productId },
113
- query: options,
114
- },
118
+ return this.executeRequest(async () => {
119
+ const { data, error } = await this.client.GET("/catalog/products/{product_id}/reviews", {
120
+ params: {
121
+ path: { product_id: productId },
122
+ query: options,
123
+ },
124
+ });
125
+ if (error) {
126
+ this.handleError(error);
127
+ }
128
+ return data?.content;
115
129
  });
116
- if (error) {
117
- this.handleError(error);
118
- }
119
- return data?.content;
120
130
  }
121
131
  /**
122
132
  * Create a review for a specific product
@@ -128,16 +138,18 @@ class CatalogClient extends client_1.StorefrontAPIClient {
128
138
  async createProductReview(productId, reviewData) {
129
139
  // Note: In a real implementation, you would need to handle multipart/form-data
130
140
  // This would require FormData and may need additional handling
131
- const { error } = await this.client.POST("/catalog/products/{product_id}/reviews", {
132
- params: {
133
- path: { product_id: productId },
134
- },
135
- body: reviewData,
136
- // This is simplified as we're not properly handling multipart/form-data
141
+ return this.executeRequest(async () => {
142
+ const { error } = await this.client.POST("/catalog/products/{product_id}/reviews", {
143
+ params: {
144
+ path: { product_id: productId },
145
+ },
146
+ body: reviewData,
147
+ // This is simplified as we're not properly handling multipart/form-data
148
+ });
149
+ if (error) {
150
+ this.handleError(error);
151
+ }
137
152
  });
138
- if (error) {
139
- this.handleError(error);
140
- }
141
153
  }
142
154
  /**
143
155
  * Search for products
@@ -146,13 +158,15 @@ class CatalogClient extends client_1.StorefrontAPIClient {
146
158
  * @returns Promise with search results
147
159
  */
148
160
  async searchProducts(searchData) {
149
- const { data, error } = await this.client.POST("/catalog/products/search", {
150
- body: searchData,
161
+ return this.executeRequest(async () => {
162
+ const { data, error } = await this.client.POST("/catalog/products/search", {
163
+ body: searchData,
164
+ });
165
+ if (error) {
166
+ this.handleError(error);
167
+ }
168
+ return data?.content;
151
169
  });
152
- if (error) {
153
- this.handleError(error);
154
- }
155
- return data?.content;
156
170
  }
157
171
  /**
158
172
  * Get product details by ID (alternative implementation)
@@ -61,6 +61,7 @@ export declare class StorefrontAPIClient {
61
61
  private headers;
62
62
  private readonly baseUrl;
63
63
  private isRefreshing;
64
+ private static sharedConfigs;
64
65
  /**
65
66
  * Create a new StorefrontAPIClient
66
67
  *
@@ -44,25 +44,51 @@ class StorefrontAPIClient {
44
44
  */
45
45
  constructor(config) {
46
46
  this.isRefreshing = false;
47
- this.config = config;
47
+ // Use shared config reference for the same storeId to ensure all clients use the same config
48
+ const storeKey = config.storeId + (config.baseUrl || config.environment || "");
49
+ if (!StorefrontAPIClient.sharedConfigs.has(storeKey)) {
50
+ StorefrontAPIClient.sharedConfigs.set(storeKey, { ...config });
51
+ }
52
+ // Use the shared config reference
53
+ this.config = StorefrontAPIClient.sharedConfigs.get(storeKey);
54
+ // Copy non-shared values from the provided config
55
+ if (config.token && !this.config.token) {
56
+ this.config.token = config.token;
57
+ }
58
+ if (config.apiKey && !this.config.apiKey) {
59
+ this.config.apiKey = config.apiKey;
60
+ }
48
61
  this.headers = {
49
62
  "Content-Type": "application/json",
50
63
  };
51
- if (config.token) {
52
- this.headers["Authorization"] = `Bearer ${config.token}`;
64
+ if (this.config.token) {
65
+ this.headers["Authorization"] = `Bearer ${this.config.token}`;
53
66
  }
54
- if (config.apiKey) {
55
- this.headers["X-Api-Key"] = config.apiKey;
67
+ if (this.config.apiKey) {
68
+ this.headers["X-Api-Key"] = this.config.apiKey;
56
69
  }
57
70
  // Determine base URL from environment or use custom URL if provided
58
- this.baseUrl = this.getBaseUrlFromConfig(config);
71
+ this.baseUrl = this.getBaseUrlFromConfig(this.config);
59
72
  this.client = (0, openapi_fetch_1.default)({
60
73
  baseUrl: this.baseUrl,
61
74
  fetch: (input, init) => {
62
75
  // Add timeout if configured
63
- const timeoutSignal = config.timeout
64
- ? AbortSignal.timeout(config.timeout)
76
+ const timeoutSignal = this.config.timeout
77
+ ? AbortSignal.timeout(this.config.timeout)
65
78
  : undefined;
79
+ // Always check for the most current token and API key before each request
80
+ if (this.config.token) {
81
+ this.headers["Authorization"] = `Bearer ${this.config.token}`;
82
+ }
83
+ else {
84
+ delete this.headers["Authorization"];
85
+ }
86
+ if (this.config.apiKey) {
87
+ this.headers["X-Api-Key"] = this.config.apiKey;
88
+ }
89
+ else {
90
+ delete this.headers["X-Api-Key"];
91
+ }
66
92
  // Merge headers
67
93
  const headers = {
68
94
  ...this.headers,
@@ -237,3 +263,5 @@ class StorefrontAPIClient {
237
263
  }
238
264
  }
239
265
  exports.StorefrontAPIClient = StorefrontAPIClient;
266
+ // Shared static reference for configs by storeId to ensure all clients use the same config
267
+ StorefrontAPIClient.sharedConfigs = new Map();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercengine/storefront-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "TypeScript SDK for the Storefront API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",