omni-sync-sdk 0.1.1 → 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.
package/dist/index.js CHANGED
@@ -35,18 +35,86 @@ var DEFAULT_BASE_URL = "https://api.omni-sync.com";
35
35
  var DEFAULT_TIMEOUT = 3e4;
36
36
  var OmniSyncClient = class {
37
37
  constructor(options) {
38
- if (!options.apiKey) {
39
- throw new Error("OmniSyncClient: apiKey is required");
38
+ this.customerToken = null;
39
+ if (!options.apiKey && !options.storeId && !options.connectionId) {
40
+ throw new Error("OmniSyncClient: either connectionId, apiKey, or storeId is required");
40
41
  }
41
- if (!options.apiKey.startsWith("omni_")) {
42
+ if (options.apiKey && !options.apiKey.startsWith("omni_")) {
42
43
  console.warn('OmniSyncClient: apiKey should start with "omni_"');
43
44
  }
45
+ if (options.connectionId && !options.connectionId.startsWith("vc_")) {
46
+ console.warn('OmniSyncClient: connectionId should start with "vc_"');
47
+ }
48
+ if (options.apiKey && typeof window !== "undefined") {
49
+ console.warn(
50
+ "OmniSyncClient: WARNING - API key detected in browser environment. This is a security risk! Use connectionId or storeId for frontend applications."
51
+ );
52
+ }
44
53
  this.apiKey = options.apiKey;
54
+ this.storeId = options.storeId;
55
+ this.connectionId = options.connectionId;
45
56
  this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
46
57
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
47
58
  }
59
+ // -------------------- Mode Detection --------------------
60
+ /**
61
+ * Check if client is in vibe-coded mode (using connectionId)
62
+ */
63
+ isVibeCodedMode() {
64
+ return !!this.connectionId && !this.apiKey;
65
+ }
66
+ /**
67
+ * Check if client is in storefront mode (using storeId)
68
+ */
69
+ isStorefrontMode() {
70
+ return !!this.storeId && !this.apiKey && !this.connectionId;
71
+ }
72
+ /**
73
+ * Check if client is in admin mode (using apiKey)
74
+ */
75
+ isAdminMode() {
76
+ return !!this.apiKey;
77
+ }
78
+ // -------------------- Customer Token Management --------------------
79
+ /**
80
+ * Set the customer authentication token (obtained from login/register).
81
+ * Required for accessing customer-specific data in storefront mode.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const auth = await omni.loginCustomer('user@example.com', 'password');
86
+ * omni.setCustomerToken(auth.token);
87
+ *
88
+ * // Now can access customer data
89
+ * const profile = await omni.getMyProfile();
90
+ * ```
91
+ */
92
+ setCustomerToken(token) {
93
+ this.customerToken = token;
94
+ }
95
+ /**
96
+ * Get the current customer token
97
+ */
98
+ getCustomerToken() {
99
+ return this.customerToken;
100
+ }
101
+ /**
102
+ * Clear the customer token (logout)
103
+ */
104
+ clearCustomerToken() {
105
+ this.customerToken = null;
106
+ }
48
107
  // -------------------- Private Methods --------------------
49
- async request(method, path, body, queryParams) {
108
+ /**
109
+ * Make a request to the Admin API (requires apiKey)
110
+ */
111
+ async adminRequest(method, path, body, queryParams) {
112
+ if (!this.apiKey) {
113
+ throw new OmniSyncError(
114
+ "This operation requires an API key. Initialize with apiKey instead of storeId.",
115
+ 403
116
+ );
117
+ }
50
118
  const url = new URL(`${this.baseUrl}${path}`);
51
119
  if (queryParams) {
52
120
  Object.entries(queryParams).forEach(([key, value]) => {
@@ -63,9 +131,8 @@ var OmniSyncClient = class {
63
131
  headers: {
64
132
  Authorization: `Bearer ${this.apiKey}`,
65
133
  "Content-Type": "application/json",
66
- "X-SDK-Version": "0.1.0",
134
+ "X-SDK-Version": "0.3.0",
67
135
  "ngrok-skip-browser-warning": "true"
68
- // Skip ngrok warning page for dev tunnels
69
136
  },
70
137
  body: body ? JSON.stringify(body) : void 0,
71
138
  signal: controller.signal
@@ -96,12 +163,149 @@ var OmniSyncClient = class {
96
163
  throw new OmniSyncError("Unknown error occurred", 0);
97
164
  }
98
165
  }
166
+ /**
167
+ * Make a request to the Vibe-Coded API (public, uses connectionId)
168
+ */
169
+ async vibeCodedRequest(method, path, body, queryParams) {
170
+ if (!this.connectionId) {
171
+ throw new OmniSyncError("connectionId is required for vibe-coded requests", 400);
172
+ }
173
+ const url = new URL(`${this.baseUrl}/api/vc/${this.connectionId}${path}`);
174
+ if (queryParams) {
175
+ Object.entries(queryParams).forEach(([key, value]) => {
176
+ if (value !== void 0) {
177
+ url.searchParams.set(key, String(value));
178
+ }
179
+ });
180
+ }
181
+ const controller = new AbortController();
182
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
183
+ try {
184
+ const headers = {
185
+ "Content-Type": "application/json",
186
+ "X-SDK-Version": "0.3.0",
187
+ "ngrok-skip-browser-warning": "true"
188
+ };
189
+ const response = await fetch(url.toString(), {
190
+ method,
191
+ headers,
192
+ body: body ? JSON.stringify(body) : void 0,
193
+ signal: controller.signal
194
+ });
195
+ clearTimeout(timeoutId);
196
+ if (!response.ok) {
197
+ const errorData = await response.json().catch(() => ({}));
198
+ throw new OmniSyncError(
199
+ errorData.message || `Request failed with status ${response.status}`,
200
+ response.status,
201
+ errorData
202
+ );
203
+ }
204
+ const text = await response.text();
205
+ if (!text) return {};
206
+ return JSON.parse(text);
207
+ } catch (error) {
208
+ clearTimeout(timeoutId);
209
+ if (error instanceof OmniSyncError) {
210
+ throw error;
211
+ }
212
+ if (error instanceof Error) {
213
+ if (error.name === "AbortError") {
214
+ throw new OmniSyncError("Request timeout", 408);
215
+ }
216
+ throw new OmniSyncError(error.message, 0);
217
+ }
218
+ throw new OmniSyncError("Unknown error occurred", 0);
219
+ }
220
+ }
221
+ /**
222
+ * Make a request to the Storefront API (public, uses storeId)
223
+ */
224
+ async storefrontRequest(method, path, body, queryParams) {
225
+ if (!this.storeId) {
226
+ throw new OmniSyncError("storeId is required for storefront requests", 400);
227
+ }
228
+ const url = new URL(`${this.baseUrl}/stores/${this.storeId}${path}`);
229
+ if (queryParams) {
230
+ Object.entries(queryParams).forEach(([key, value]) => {
231
+ if (value !== void 0) {
232
+ url.searchParams.set(key, String(value));
233
+ }
234
+ });
235
+ }
236
+ const controller = new AbortController();
237
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
238
+ try {
239
+ const headers = {
240
+ "Content-Type": "application/json",
241
+ "X-SDK-Version": "0.3.0",
242
+ "ngrok-skip-browser-warning": "true"
243
+ };
244
+ if (this.customerToken) {
245
+ headers["Authorization"] = `Bearer ${this.customerToken}`;
246
+ }
247
+ const response = await fetch(url.toString(), {
248
+ method,
249
+ headers,
250
+ body: body ? JSON.stringify(body) : void 0,
251
+ signal: controller.signal
252
+ });
253
+ clearTimeout(timeoutId);
254
+ if (!response.ok) {
255
+ const errorData = await response.json().catch(() => ({}));
256
+ throw new OmniSyncError(
257
+ errorData.message || `Request failed with status ${response.status}`,
258
+ response.status,
259
+ errorData
260
+ );
261
+ }
262
+ const text = await response.text();
263
+ if (!text) return {};
264
+ return JSON.parse(text);
265
+ } catch (error) {
266
+ clearTimeout(timeoutId);
267
+ if (error instanceof OmniSyncError) {
268
+ throw error;
269
+ }
270
+ if (error instanceof Error) {
271
+ if (error.name === "AbortError") {
272
+ throw new OmniSyncError("Request timeout", 408);
273
+ }
274
+ throw new OmniSyncError(error.message, 0);
275
+ }
276
+ throw new OmniSyncError("Unknown error occurred", 0);
277
+ }
278
+ }
279
+ /**
280
+ * Smart request - uses storefront or admin API based on client mode
281
+ */
282
+ async request(method, path, body, queryParams) {
283
+ if (this.apiKey) {
284
+ return this.adminRequest(method, path, body, queryParams);
285
+ }
286
+ return this.storefrontRequest(method, path, body, queryParams);
287
+ }
288
+ // -------------------- Store Info --------------------
289
+ /**
290
+ * Get store information
291
+ * Works in vibe-coded, storefront, and admin mode
292
+ */
293
+ async getStoreInfo() {
294
+ if (this.isVibeCodedMode()) {
295
+ return this.vibeCodedRequest("GET", "/info");
296
+ }
297
+ if (this.storeId && !this.apiKey) {
298
+ return this.storefrontRequest("GET", "/info");
299
+ }
300
+ return this.adminRequest("GET", "/api/v1/store");
301
+ }
99
302
  // -------------------- Products --------------------
100
303
  /**
101
304
  * Get a list of products with pagination
305
+ * Works in vibe-coded, storefront (public), and admin mode
102
306
  */
103
307
  async getProducts(params) {
104
- return this.request("GET", "/api/v1/products", void 0, {
308
+ const queryParams = {
105
309
  page: params?.page,
106
310
  limit: params?.limit,
107
311
  search: params?.search,
@@ -109,13 +313,42 @@ var OmniSyncClient = class {
109
313
  type: params?.type,
110
314
  sortBy: params?.sortBy,
111
315
  sortOrder: params?.sortOrder
112
- });
316
+ };
317
+ if (this.isVibeCodedMode()) {
318
+ return this.vibeCodedRequest(
319
+ "GET",
320
+ "/products",
321
+ void 0,
322
+ queryParams
323
+ );
324
+ }
325
+ if (this.storeId && !this.apiKey) {
326
+ return this.storefrontRequest(
327
+ "GET",
328
+ "/products",
329
+ void 0,
330
+ queryParams
331
+ );
332
+ }
333
+ return this.adminRequest(
334
+ "GET",
335
+ "/api/v1/products",
336
+ void 0,
337
+ queryParams
338
+ );
113
339
  }
114
340
  /**
115
341
  * Get a single product by ID
342
+ * Works in vibe-coded, storefront (public), and admin mode
116
343
  */
117
344
  async getProduct(productId) {
118
- return this.request("GET", `/api/v1/products/${productId}`);
345
+ if (this.isVibeCodedMode()) {
346
+ return this.vibeCodedRequest("GET", `/products/${productId}`);
347
+ }
348
+ if (this.storeId && !this.apiKey) {
349
+ return this.storefrontRequest("GET", `/products/${productId}`);
350
+ }
351
+ return this.adminRequest("GET", `/api/v1/products/${productId}`);
119
352
  }
120
353
  /**
121
354
  * Create a new product
@@ -135,6 +368,147 @@ var OmniSyncClient = class {
135
368
  async deleteProduct(productId) {
136
369
  await this.request("DELETE", `/api/v1/products/${productId}`);
137
370
  }
371
+ /**
372
+ * Convert a SIMPLE product to VARIABLE product
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * const product = await omni.convertToVariable('prod_123');
377
+ * console.log('Product type:', product.type); // 'VARIABLE'
378
+ * ```
379
+ */
380
+ async convertToVariable(productId) {
381
+ return this.request("PATCH", `/api/v1/products/${productId}/convert-to-variable`);
382
+ }
383
+ /**
384
+ * Convert a VARIABLE product to SIMPLE product
385
+ * Note: This will delete all variants
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * const product = await omni.convertToSimple('prod_123');
390
+ * console.log('Product type:', product.type); // 'SIMPLE'
391
+ * ```
392
+ */
393
+ async convertToSimple(productId) {
394
+ return this.request("PATCH", `/api/v1/products/${productId}/convert-to-simple`);
395
+ }
396
+ /**
397
+ * Publish a product to specific platforms
398
+ *
399
+ * @example
400
+ * ```typescript
401
+ * const result = await omni.publishProduct('prod_123', ['SHOPIFY', 'WOOCOMMERCE']);
402
+ * console.log('Publish results:', result.results);
403
+ * ```
404
+ */
405
+ async publishProduct(productId, platforms) {
406
+ return this.request("POST", `/api/v1/products/${productId}/publish`, {
407
+ platforms
408
+ });
409
+ }
410
+ // -------------------- Variants --------------------
411
+ /**
412
+ * Create a new variant for a product
413
+ *
414
+ * @example
415
+ * ```typescript
416
+ * const variant = await omni.createVariant('prod_123', {
417
+ * sku: 'PROD-SM-RED',
418
+ * name: 'Small / Red',
419
+ * attributes: { size: 'S', color: 'Red' },
420
+ * price: 29.99,
421
+ * inventory: 100,
422
+ * });
423
+ * ```
424
+ */
425
+ async createVariant(productId, data) {
426
+ return this.request("POST", `/api/v1/products/${productId}/variants`, data);
427
+ }
428
+ /**
429
+ * Bulk save variants (create, update, delete in one operation)
430
+ *
431
+ * @example
432
+ * ```typescript
433
+ * const result = await omni.bulkSaveVariants('prod_123', {
434
+ * variants: [
435
+ * { sku: 'SM-RED', attributes: { size: 'S', color: 'Red' }, stock: 10, isEnabled: true },
436
+ * { id: 'var_456', sku: 'MD-BLUE', attributes: { size: 'M', color: 'Blue' }, stock: 5, isEnabled: true },
437
+ * { id: 'var_789', sku: 'LG-GREEN', attributes: {}, stock: 0, isEnabled: false, isDeleted: true },
438
+ * ],
439
+ * });
440
+ * console.log(`Created: ${result.created}, Updated: ${result.updated}, Deleted: ${result.deleted}`);
441
+ * ```
442
+ */
443
+ async bulkSaveVariants(productId, data) {
444
+ return this.request(
445
+ "POST",
446
+ `/api/v1/products/${productId}/variants/bulk`,
447
+ data
448
+ );
449
+ }
450
+ /**
451
+ * Update a variant
452
+ *
453
+ * @example
454
+ * ```typescript
455
+ * const variant = await omni.updateVariant('prod_123', 'var_456', {
456
+ * price: 34.99,
457
+ * salePrice: 29.99,
458
+ * });
459
+ * ```
460
+ */
461
+ async updateVariant(productId, variantId, data) {
462
+ return this.request(
463
+ "PATCH",
464
+ `/api/v1/products/${productId}/variants/${variantId}`,
465
+ data
466
+ );
467
+ }
468
+ /**
469
+ * Delete a variant
470
+ *
471
+ * @example
472
+ * ```typescript
473
+ * await omni.deleteVariant('prod_123', 'var_456');
474
+ * ```
475
+ */
476
+ async deleteVariant(productId, variantId) {
477
+ await this.request("DELETE", `/api/v1/products/${productId}/variants/${variantId}`);
478
+ }
479
+ /**
480
+ * Get inventory for a specific variant
481
+ *
482
+ * @example
483
+ * ```typescript
484
+ * const inventory = await omni.getVariantInventory('prod_123', 'var_456');
485
+ * console.log('Available:', inventory.available);
486
+ * ```
487
+ */
488
+ async getVariantInventory(productId, variantId) {
489
+ return this.request(
490
+ "GET",
491
+ `/api/v1/products/${productId}/variants/${variantId}/inventory`
492
+ );
493
+ }
494
+ /**
495
+ * Update inventory for a specific variant
496
+ *
497
+ * @example
498
+ * ```typescript
499
+ * const inventory = await omni.updateVariantInventory('prod_123', 'var_456', {
500
+ * newTotal: 50,
501
+ * reason: 'Restocked from supplier',
502
+ * });
503
+ * ```
504
+ */
505
+ async updateVariantInventory(productId, variantId, data) {
506
+ return this.request(
507
+ "PATCH",
508
+ `/api/v1/products/${productId}/variants/${variantId}/inventory`,
509
+ data
510
+ );
511
+ }
138
512
  // -------------------- Orders --------------------
139
513
  /**
140
514
  * Get a list of orders with pagination
@@ -167,6 +541,209 @@ var OmniSyncClient = class {
167
541
  async updateOrder(orderId, data) {
168
542
  return this.request("PATCH", `/api/v1/orders/${orderId}`, data);
169
543
  }
544
+ /**
545
+ * Update order status
546
+ *
547
+ * @example
548
+ * ```typescript
549
+ * const order = await omni.updateOrderStatus('order_123', 'shipped');
550
+ * ```
551
+ */
552
+ async updateOrderStatus(orderId, status) {
553
+ return this.request("PATCH", `/api/v1/orders/${orderId}/status`, { status });
554
+ }
555
+ /**
556
+ * Update order payment method
557
+ * Note: Only WooCommerce supports syncing payment method changes back to platform
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * const order = await omni.updatePaymentMethod('order_123', 'credit_card');
562
+ * ```
563
+ */
564
+ async updatePaymentMethod(orderId, paymentMethod) {
565
+ return this.request("PATCH", `/api/v1/orders/${orderId}/payment-method`, {
566
+ paymentMethod
567
+ });
568
+ }
569
+ /**
570
+ * Update order notes
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * const order = await omni.updateOrderNotes('order_123', 'Customer requested gift wrapping');
575
+ * ```
576
+ */
577
+ async updateOrderNotes(orderId, notes) {
578
+ return this.request("PATCH", `/api/v1/orders/${orderId}/notes`, { notes });
579
+ }
580
+ /**
581
+ * Get refunds for an order
582
+ * Returns refunds from the source platform (Shopify/WooCommerce only)
583
+ *
584
+ * @example
585
+ * ```typescript
586
+ * const refunds = await omni.getOrderRefunds('order_123');
587
+ * console.log('Total refunds:', refunds.length);
588
+ * ```
589
+ */
590
+ async getOrderRefunds(orderId) {
591
+ return this.request("GET", `/api/v1/orders/${orderId}/refunds`);
592
+ }
593
+ /**
594
+ * Create a refund for an order
595
+ * Creates refund on the source platform (Shopify/WooCommerce only)
596
+ *
597
+ * @example
598
+ * ```typescript
599
+ * // Full refund
600
+ * const refund = await omni.createRefund('order_123', {
601
+ * type: 'full',
602
+ * restockInventory: true,
603
+ * notifyCustomer: true,
604
+ * reason: 'Customer request',
605
+ * });
606
+ *
607
+ * // Partial refund
608
+ * const partialRefund = await omni.createRefund('order_123', {
609
+ * type: 'partial',
610
+ * items: [
611
+ * { lineItemId: 'item_456', quantity: 1 },
612
+ * ],
613
+ * restockInventory: true,
614
+ * });
615
+ * ```
616
+ */
617
+ async createRefund(orderId, data) {
618
+ return this.request("POST", `/api/v1/orders/${orderId}/refunds`, data);
619
+ }
620
+ /**
621
+ * Update order shipping address
622
+ * Syncs to source platform (Shopify/WooCommerce only)
623
+ *
624
+ * @example
625
+ * ```typescript
626
+ * const order = await omni.updateOrderShipping('order_123', {
627
+ * firstName: 'John',
628
+ * lastName: 'Doe',
629
+ * line1: '456 New Address',
630
+ * city: 'Los Angeles',
631
+ * state: 'CA',
632
+ * country: 'US',
633
+ * postalCode: '90001',
634
+ * });
635
+ * ```
636
+ */
637
+ async updateOrderShipping(orderId, data) {
638
+ return this.request("PATCH", `/api/v1/orders/${orderId}/shipping`, data);
639
+ }
640
+ /**
641
+ * Cancel an order
642
+ * Works for Shopify and WooCommerce orders that haven't been fulfilled
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * const order = await omni.cancelOrder('order_123');
647
+ * console.log('Order status:', order.status); // 'cancelled'
648
+ * ```
649
+ */
650
+ async cancelOrder(orderId) {
651
+ return this.request("POST", `/api/v1/orders/${orderId}/cancel`);
652
+ }
653
+ /**
654
+ * Fulfill an order (mark as shipped)
655
+ * Works for Shopify and WooCommerce orders
656
+ *
657
+ * @example
658
+ * ```typescript
659
+ * const order = await omni.fulfillOrder('order_123', {
660
+ * trackingNumber: '1Z999AA10123456784',
661
+ * trackingCompany: 'UPS',
662
+ * notifyCustomer: true,
663
+ * });
664
+ * ```
665
+ */
666
+ async fulfillOrder(orderId, data) {
667
+ return this.request("POST", `/api/v1/orders/${orderId}/fulfill`, data || {});
668
+ }
669
+ /**
670
+ * Sync draft orders from connected platforms
671
+ *
672
+ * @example
673
+ * ```typescript
674
+ * const result = await omni.syncDraftOrders();
675
+ * console.log('Draft orders synced');
676
+ * ```
677
+ */
678
+ async syncDraftOrders() {
679
+ return this.request("POST", "/api/v1/orders/sync-drafts");
680
+ }
681
+ /**
682
+ * Complete a draft order (convert to regular order)
683
+ *
684
+ * @example
685
+ * ```typescript
686
+ * const order = await omni.completeDraftOrder('draft_123', {
687
+ * paymentPending: false,
688
+ * });
689
+ * ```
690
+ */
691
+ async completeDraftOrder(orderId, data) {
692
+ return this.request("POST", `/api/v1/orders/${orderId}/complete-draft`, data || {});
693
+ }
694
+ /**
695
+ * Send invoice for a draft order
696
+ *
697
+ * @example
698
+ * ```typescript
699
+ * await omni.sendDraftInvoice('draft_123', {
700
+ * to: 'customer@example.com',
701
+ * subject: 'Your Invoice',
702
+ * customMessage: 'Thank you for your order!',
703
+ * });
704
+ * ```
705
+ */
706
+ async sendDraftInvoice(orderId, data) {
707
+ return this.request(
708
+ "POST",
709
+ `/api/v1/orders/${orderId}/send-invoice`,
710
+ data || {}
711
+ );
712
+ }
713
+ /**
714
+ * Delete a draft order
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * await omni.deleteDraftOrder('draft_123');
719
+ * ```
720
+ */
721
+ async deleteDraftOrder(orderId) {
722
+ await this.request("DELETE", `/api/v1/orders/${orderId}/draft`);
723
+ }
724
+ /**
725
+ * Update a draft order
726
+ *
727
+ * @example
728
+ * ```typescript
729
+ * const order = await omni.updateDraftOrder('draft_123', {
730
+ * note: 'Updated customer note',
731
+ * email: 'newemail@example.com',
732
+ * shippingAddress: {
733
+ * firstName: 'John',
734
+ * lastName: 'Doe',
735
+ * address1: '123 Main St',
736
+ * city: 'New York',
737
+ * province: 'NY',
738
+ * country: 'US',
739
+ * zip: '10001',
740
+ * },
741
+ * });
742
+ * ```
743
+ */
744
+ async updateDraftOrder(orderId, data) {
745
+ return this.request("PATCH", `/api/v1/orders/${orderId}/draft`, data);
746
+ }
170
747
  // -------------------- Inventory --------------------
171
748
  /**
172
749
  * Update inventory for a product
@@ -179,7 +756,74 @@ var OmniSyncClient = class {
179
756
  * Get current inventory for a product
180
757
  */
181
758
  async getInventory(productId) {
182
- return this.request("GET", `/api/v1/products/${productId}/inventory`);
759
+ return this.request("GET", `/api/v1/inventory/${productId}`);
760
+ }
761
+ /**
762
+ * Edit inventory manually with reason for audit trail
763
+ *
764
+ * @example
765
+ * ```typescript
766
+ * const inventory = await omni.editInventory({
767
+ * productId: 'prod_123',
768
+ * newTotal: 100,
769
+ * reason: 'Restocked from warehouse',
770
+ * });
771
+ * ```
772
+ */
773
+ async editInventory(data) {
774
+ return this.request("POST", "/api/v1/inventory/edit", data);
775
+ }
776
+ /**
777
+ * Get inventory sync status for all products in the store
778
+ *
779
+ * @example
780
+ * ```typescript
781
+ * const status = await omni.getInventorySyncStatus();
782
+ * console.log(`${status.pending} products pending sync`);
783
+ * console.log(`Last sync: ${status.lastSyncAt}`);
784
+ * ```
785
+ */
786
+ async getInventorySyncStatus() {
787
+ return this.request("GET", "/api/v1/inventory/sync-status");
788
+ }
789
+ /**
790
+ * Get inventory for multiple products at once
791
+ *
792
+ * @example
793
+ * ```typescript
794
+ * const inventories = await omni.getBulkInventory(['prod_123', 'prod_456', 'prod_789']);
795
+ * inventories.forEach(inv => {
796
+ * console.log(`${inv.productId}: ${inv.available} available`);
797
+ * });
798
+ * ```
799
+ */
800
+ async getBulkInventory(productIds) {
801
+ return this.request("POST", "/api/v1/inventory/bulk", { productIds });
802
+ }
803
+ /**
804
+ * Reconcile inventory between OmniSync and connected platforms
805
+ * Detects and optionally fixes discrepancies
806
+ *
807
+ * @example
808
+ * ```typescript
809
+ * // Reconcile single product (dry run)
810
+ * const result = await omni.reconcileInventory({ productId: 'prod_123' });
811
+ *
812
+ * // Reconcile all products with auto-fix
813
+ * const summary = await omni.reconcileInventory({ autoFix: true });
814
+ * console.log(`Reconciled ${summary.reconciled} products`);
815
+ * ```
816
+ */
817
+ async reconcileInventory(options) {
818
+ const queryParams = {};
819
+ if (options?.productId) queryParams.productId = options.productId;
820
+ if (options?.autoFix) queryParams.autoFix = "true";
821
+ return this.request(
822
+ "POST",
823
+ "/api/v1/inventory/reconcile",
824
+ void 0,
825
+ queryParams
826
+ );
183
827
  }
184
828
  // -------------------- Sync --------------------
185
829
  /**
@@ -194,13 +838,6 @@ var OmniSyncClient = class {
194
838
  async getSyncStatus(jobId) {
195
839
  return this.request("GET", `/api/v1/sync/${jobId}`);
196
840
  }
197
- // -------------------- Store Info --------------------
198
- /**
199
- * Get information about the connected store
200
- */
201
- async getStoreInfo() {
202
- return this.request("GET", "/api/v1/store");
203
- }
204
841
  // -------------------- Coupons --------------------
205
842
  /**
206
843
  * Get a list of coupons with pagination
@@ -343,7 +980,13 @@ var OmniSyncClient = class {
343
980
  * ```
344
981
  */
345
982
  async loginCustomer(email, password) {
346
- return this.request("POST", "/api/v1/customers/login", {
983
+ if (this.storeId && !this.apiKey) {
984
+ return this.storefrontRequest("POST", "/customers/login", {
985
+ email,
986
+ password
987
+ });
988
+ }
989
+ return this.adminRequest("POST", "/api/v1/customers/login", {
347
990
  email,
348
991
  password
349
992
  });
@@ -362,13 +1005,21 @@ var OmniSyncClient = class {
362
1005
  * ```
363
1006
  */
364
1007
  async registerCustomer(data) {
365
- return this.request("POST", "/api/v1/customers/register", data);
1008
+ if (this.storeId && !this.apiKey) {
1009
+ return this.storefrontRequest("POST", "/customers/register", data);
1010
+ }
1011
+ return this.adminRequest("POST", "/api/v1/customers/register", data);
366
1012
  }
367
1013
  /**
368
1014
  * Request a password reset email for a customer
369
1015
  */
370
1016
  async forgotPassword(email) {
371
- return this.request("POST", "/api/v1/customers/forgot-password", {
1017
+ if (this.storeId && !this.apiKey) {
1018
+ return this.storefrontRequest("POST", "/customers/forgot-password", {
1019
+ email
1020
+ });
1021
+ }
1022
+ return this.adminRequest("POST", "/api/v1/customers/forgot-password", {
372
1023
  email
373
1024
  });
374
1025
  }
@@ -448,7 +1099,10 @@ var OmniSyncClient = class {
448
1099
  * ```
449
1100
  */
450
1101
  async createCart() {
451
- return this.request("POST", "/api/v1/cart");
1102
+ if (this.storeId && !this.apiKey) {
1103
+ return this.storefrontRequest("POST", "/cart");
1104
+ }
1105
+ return this.adminRequest("POST", "/api/v1/cart");
452
1106
  }
453
1107
  /**
454
1108
  * Get a cart by session token (for guest users)
@@ -460,7 +1114,10 @@ var OmniSyncClient = class {
460
1114
  * ```
461
1115
  */
462
1116
  async getCartBySession(sessionToken) {
463
- return this.request("GET", `/api/v1/cart/session/${sessionToken}`);
1117
+ if (this.storeId && !this.apiKey) {
1118
+ return this.storefrontRequest("GET", `/cart/session/${sessionToken}`);
1119
+ }
1120
+ return this.adminRequest("GET", `/api/v1/cart/session/${sessionToken}`);
464
1121
  }
465
1122
  /**
466
1123
  * Get a cart by customer ID (for authenticated users)
@@ -472,13 +1129,19 @@ var OmniSyncClient = class {
472
1129
  * ```
473
1130
  */
474
1131
  async getCartByCustomer(customerId) {
475
- return this.request("GET", `/api/v1/cart/customer/${customerId}`);
1132
+ if (this.storeId && !this.apiKey) {
1133
+ return this.storefrontRequest("GET", `/cart/customer/${customerId}`);
1134
+ }
1135
+ return this.adminRequest("GET", `/api/v1/cart/customer/${customerId}`);
476
1136
  }
477
1137
  /**
478
1138
  * Get a cart by ID
479
1139
  */
480
1140
  async getCart(cartId) {
481
- return this.request("GET", `/api/v1/cart/${cartId}`);
1141
+ if (this.storeId && !this.apiKey) {
1142
+ return this.storefrontRequest("GET", `/cart/${cartId}`);
1143
+ }
1144
+ return this.adminRequest("GET", `/api/v1/cart/${cartId}`);
482
1145
  }
483
1146
  /**
484
1147
  * Add an item to the cart
@@ -493,7 +1156,10 @@ var OmniSyncClient = class {
493
1156
  * ```
494
1157
  */
495
1158
  async addToCart(cartId, item) {
496
- return this.request("POST", `/api/v1/cart/${cartId}/items`, item);
1159
+ if (this.storeId && !this.apiKey) {
1160
+ return this.storefrontRequest("POST", `/cart/${cartId}/items`, item);
1161
+ }
1162
+ return this.adminRequest("POST", `/api/v1/cart/${cartId}/items`, item);
497
1163
  }
498
1164
  /**
499
1165
  * Update an item quantity in the cart
@@ -504,7 +1170,10 @@ var OmniSyncClient = class {
504
1170
  * ```
505
1171
  */
506
1172
  async updateCartItem(cartId, itemId, data) {
507
- return this.request("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data);
1173
+ if (this.storeId && !this.apiKey) {
1174
+ return this.storefrontRequest("PATCH", `/cart/${cartId}/items/${itemId}`, data);
1175
+ }
1176
+ return this.adminRequest("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data);
508
1177
  }
509
1178
  /**
510
1179
  * Remove an item from the cart
@@ -515,7 +1184,10 @@ var OmniSyncClient = class {
515
1184
  * ```
516
1185
  */
517
1186
  async removeCartItem(cartId, itemId) {
518
- return this.request("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`);
1187
+ if (this.storeId && !this.apiKey) {
1188
+ return this.storefrontRequest("DELETE", `/cart/${cartId}/items/${itemId}`);
1189
+ }
1190
+ return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`);
519
1191
  }
520
1192
  /**
521
1193
  * Clear all items from the cart
@@ -526,7 +1198,11 @@ var OmniSyncClient = class {
526
1198
  * ```
527
1199
  */
528
1200
  async clearCart(cartId) {
529
- await this.request("DELETE", `/api/v1/cart/${cartId}/items`);
1201
+ if (this.storeId && !this.apiKey) {
1202
+ await this.storefrontRequest("DELETE", `/cart/${cartId}/items`);
1203
+ return;
1204
+ }
1205
+ await this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items`);
530
1206
  }
531
1207
  /**
532
1208
  * Apply a coupon to the cart
@@ -538,7 +1214,10 @@ var OmniSyncClient = class {
538
1214
  * ```
539
1215
  */
540
1216
  async applyCoupon(cartId, code) {
541
- return this.request("POST", `/api/v1/cart/${cartId}/coupon`, { code });
1217
+ if (this.storeId && !this.apiKey) {
1218
+ return this.storefrontRequest("POST", `/cart/${cartId}/coupon`, { code });
1219
+ }
1220
+ return this.adminRequest("POST", `/api/v1/cart/${cartId}/coupon`, { code });
542
1221
  }
543
1222
  /**
544
1223
  * Remove a coupon from the cart
@@ -549,7 +1228,10 @@ var OmniSyncClient = class {
549
1228
  * ```
550
1229
  */
551
1230
  async removeCoupon(cartId) {
552
- return this.request("DELETE", `/api/v1/cart/${cartId}/coupon`);
1231
+ if (this.storeId && !this.apiKey) {
1232
+ return this.storefrontRequest("DELETE", `/cart/${cartId}/coupon`);
1233
+ }
1234
+ return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/coupon`);
553
1235
  }
554
1236
  /**
555
1237
  * Merge a guest cart into a customer's cart (after login)
@@ -565,7 +1247,10 @@ var OmniSyncClient = class {
565
1247
  * ```
566
1248
  */
567
1249
  async mergeCarts(data) {
568
- return this.request("POST", "/api/v1/cart/merge", data);
1250
+ if (this.storeId && !this.apiKey) {
1251
+ return this.storefrontRequest("POST", "/cart/merge", data);
1252
+ }
1253
+ return this.adminRequest("POST", "/api/v1/cart/merge", data);
569
1254
  }
570
1255
  // -------------------- Checkout --------------------
571
1256
  /**
@@ -579,7 +1264,10 @@ var OmniSyncClient = class {
579
1264
  * ```
580
1265
  */
581
1266
  async createCheckout(data) {
582
- return this.request("POST", "/api/v1/checkout", data);
1267
+ if (this.storeId && !this.apiKey) {
1268
+ return this.storefrontRequest("POST", "/checkout", data);
1269
+ }
1270
+ return this.adminRequest("POST", "/api/v1/checkout", data);
583
1271
  }
584
1272
  /**
585
1273
  * Get a checkout by ID
@@ -591,7 +1279,10 @@ var OmniSyncClient = class {
591
1279
  * ```
592
1280
  */
593
1281
  async getCheckout(checkoutId) {
594
- return this.request("GET", `/api/v1/checkout/${checkoutId}`);
1282
+ if (this.storeId && !this.apiKey) {
1283
+ return this.storefrontRequest("GET", `/checkout/${checkoutId}`);
1284
+ }
1285
+ return this.adminRequest("GET", `/api/v1/checkout/${checkoutId}`);
595
1286
  }
596
1287
  /**
597
1288
  * Set customer information on checkout
@@ -606,7 +1297,10 @@ var OmniSyncClient = class {
606
1297
  * ```
607
1298
  */
608
1299
  async setCheckoutCustomer(checkoutId, data) {
609
- return this.request("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
1300
+ if (this.storeId && !this.apiKey) {
1301
+ return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/customer`, data);
1302
+ }
1303
+ return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
610
1304
  }
611
1305
  /**
612
1306
  * Set shipping address on checkout
@@ -627,7 +1321,14 @@ var OmniSyncClient = class {
627
1321
  * ```
628
1322
  */
629
1323
  async setShippingAddress(checkoutId, address) {
630
- return this.request(
1324
+ if (this.storeId && !this.apiKey) {
1325
+ return this.storefrontRequest(
1326
+ "PATCH",
1327
+ `/checkout/${checkoutId}/shipping-address`,
1328
+ address
1329
+ );
1330
+ }
1331
+ return this.adminRequest(
631
1332
  "PATCH",
632
1333
  `/api/v1/checkout/${checkoutId}/shipping-address`,
633
1334
  address
@@ -644,7 +1345,16 @@ var OmniSyncClient = class {
644
1345
  * ```
645
1346
  */
646
1347
  async getShippingRates(checkoutId) {
647
- return this.request("GET", `/api/v1/checkout/${checkoutId}/shipping-rates`);
1348
+ if (this.storeId && !this.apiKey) {
1349
+ return this.storefrontRequest(
1350
+ "GET",
1351
+ `/checkout/${checkoutId}/shipping-rates`
1352
+ );
1353
+ }
1354
+ return this.adminRequest(
1355
+ "GET",
1356
+ `/api/v1/checkout/${checkoutId}/shipping-rates`
1357
+ );
648
1358
  }
649
1359
  /**
650
1360
  * Select a shipping method for checkout
@@ -656,7 +1366,12 @@ var OmniSyncClient = class {
656
1366
  * ```
657
1367
  */
658
1368
  async selectShippingMethod(checkoutId, shippingRateId) {
659
- return this.request("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
1369
+ if (this.storeId && !this.apiKey) {
1370
+ return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/shipping-method`, {
1371
+ shippingRateId
1372
+ });
1373
+ }
1374
+ return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
660
1375
  shippingRateId
661
1376
  });
662
1377
  }
@@ -685,7 +1400,14 @@ var OmniSyncClient = class {
685
1400
  * ```
686
1401
  */
687
1402
  async setBillingAddress(checkoutId, address) {
688
- return this.request(
1403
+ if (this.storeId && !this.apiKey) {
1404
+ return this.storefrontRequest(
1405
+ "PATCH",
1406
+ `/checkout/${checkoutId}/billing-address`,
1407
+ address
1408
+ );
1409
+ }
1410
+ return this.adminRequest(
689
1411
  "PATCH",
690
1412
  `/api/v1/checkout/${checkoutId}/billing-address`,
691
1413
  address
@@ -702,11 +1424,143 @@ var OmniSyncClient = class {
702
1424
  * ```
703
1425
  */
704
1426
  async completeCheckout(checkoutId) {
705
- return this.request(
1427
+ if (this.storeId && !this.apiKey) {
1428
+ return this.storefrontRequest(
1429
+ "POST",
1430
+ `/checkout/${checkoutId}/complete`
1431
+ );
1432
+ }
1433
+ return this.adminRequest(
706
1434
  "POST",
707
1435
  `/api/v1/checkout/${checkoutId}/complete`
708
1436
  );
709
1437
  }
1438
+ // -------------------- Storefront Customer Self-Service --------------------
1439
+ // These methods require customerToken to be set (call setCustomerToken after login)
1440
+ /**
1441
+ * Get the current customer's profile (requires customerToken)
1442
+ * Only available in storefront mode
1443
+ *
1444
+ * @example
1445
+ * ```typescript
1446
+ * const auth = await omni.loginCustomer('user@example.com', 'password');
1447
+ * omni.setCustomerToken(auth.token);
1448
+ * const profile = await omni.getMyProfile();
1449
+ * ```
1450
+ */
1451
+ async getMyProfile() {
1452
+ if (!this.storeId) {
1453
+ throw new OmniSyncError("getMyProfile is only available in storefront mode", 400);
1454
+ }
1455
+ if (!this.customerToken) {
1456
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1457
+ }
1458
+ return this.storefrontRequest("GET", "/customers/me");
1459
+ }
1460
+ /**
1461
+ * Update the current customer's profile (requires customerToken)
1462
+ * Only available in storefront mode
1463
+ */
1464
+ async updateMyProfile(data) {
1465
+ if (!this.storeId) {
1466
+ throw new OmniSyncError("updateMyProfile is only available in storefront mode", 400);
1467
+ }
1468
+ if (!this.customerToken) {
1469
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1470
+ }
1471
+ return this.storefrontRequest("PATCH", "/customers/me", data);
1472
+ }
1473
+ /**
1474
+ * Get the current customer's orders (requires customerToken)
1475
+ * Only available in storefront mode
1476
+ */
1477
+ async getMyOrders(params) {
1478
+ if (!this.storeId) {
1479
+ throw new OmniSyncError("getMyOrders is only available in storefront mode", 400);
1480
+ }
1481
+ if (!this.customerToken) {
1482
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1483
+ }
1484
+ return this.storefrontRequest(
1485
+ "GET",
1486
+ "/customers/me/orders",
1487
+ void 0,
1488
+ {
1489
+ page: params?.page,
1490
+ limit: params?.limit
1491
+ }
1492
+ );
1493
+ }
1494
+ /**
1495
+ * Get the current customer's addresses (requires customerToken)
1496
+ * Only available in storefront mode
1497
+ */
1498
+ async getMyAddresses() {
1499
+ if (!this.storeId) {
1500
+ throw new OmniSyncError("getMyAddresses is only available in storefront mode", 400);
1501
+ }
1502
+ if (!this.customerToken) {
1503
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1504
+ }
1505
+ return this.storefrontRequest("GET", "/customers/me/addresses");
1506
+ }
1507
+ /**
1508
+ * Add an address to the current customer (requires customerToken)
1509
+ * Only available in storefront mode
1510
+ */
1511
+ async addMyAddress(address) {
1512
+ if (!this.storeId) {
1513
+ throw new OmniSyncError("addMyAddress is only available in storefront mode", 400);
1514
+ }
1515
+ if (!this.customerToken) {
1516
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1517
+ }
1518
+ return this.storefrontRequest("POST", "/customers/me/addresses", address);
1519
+ }
1520
+ /**
1521
+ * Update a customer address (requires customerToken)
1522
+ * Only available in storefront mode
1523
+ */
1524
+ async updateMyAddress(addressId, data) {
1525
+ if (!this.storeId) {
1526
+ throw new OmniSyncError("updateMyAddress is only available in storefront mode", 400);
1527
+ }
1528
+ if (!this.customerToken) {
1529
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1530
+ }
1531
+ return this.storefrontRequest(
1532
+ "PATCH",
1533
+ `/customers/me/addresses/${addressId}`,
1534
+ data
1535
+ );
1536
+ }
1537
+ /**
1538
+ * Delete a customer address (requires customerToken)
1539
+ * Only available in storefront mode
1540
+ */
1541
+ async deleteMyAddress(addressId) {
1542
+ if (!this.storeId) {
1543
+ throw new OmniSyncError("deleteMyAddress is only available in storefront mode", 400);
1544
+ }
1545
+ if (!this.customerToken) {
1546
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1547
+ }
1548
+ await this.storefrontRequest("DELETE", `/customers/me/addresses/${addressId}`);
1549
+ }
1550
+ /**
1551
+ * Get the current customer's cart (requires customerToken)
1552
+ * Creates a new cart if none exists
1553
+ * Only available in storefront mode
1554
+ */
1555
+ async getMyCart() {
1556
+ if (!this.storeId) {
1557
+ throw new OmniSyncError("getMyCart is only available in storefront mode", 400);
1558
+ }
1559
+ if (!this.customerToken) {
1560
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1561
+ }
1562
+ return this.storefrontRequest("GET", "/customers/me/cart");
1563
+ }
710
1564
  };
711
1565
  var OmniSyncError = class extends Error {
712
1566
  constructor(message, statusCode, details) {