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.mjs CHANGED
@@ -10,18 +10,86 @@ var DEFAULT_BASE_URL = "https://api.omni-sync.com";
10
10
  var DEFAULT_TIMEOUT = 3e4;
11
11
  var OmniSyncClient = class {
12
12
  constructor(options) {
13
- if (!options.apiKey) {
14
- throw new Error("OmniSyncClient: apiKey is required");
13
+ this.customerToken = null;
14
+ if (!options.apiKey && !options.storeId && !options.connectionId) {
15
+ throw new Error("OmniSyncClient: either connectionId, apiKey, or storeId is required");
15
16
  }
16
- if (!options.apiKey.startsWith("omni_")) {
17
+ if (options.apiKey && !options.apiKey.startsWith("omni_")) {
17
18
  console.warn('OmniSyncClient: apiKey should start with "omni_"');
18
19
  }
20
+ if (options.connectionId && !options.connectionId.startsWith("vc_")) {
21
+ console.warn('OmniSyncClient: connectionId should start with "vc_"');
22
+ }
23
+ if (options.apiKey && typeof window !== "undefined") {
24
+ console.warn(
25
+ "OmniSyncClient: WARNING - API key detected in browser environment. This is a security risk! Use connectionId or storeId for frontend applications."
26
+ );
27
+ }
19
28
  this.apiKey = options.apiKey;
29
+ this.storeId = options.storeId;
30
+ this.connectionId = options.connectionId;
20
31
  this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
21
32
  this.timeout = options.timeout || DEFAULT_TIMEOUT;
22
33
  }
34
+ // -------------------- Mode Detection --------------------
35
+ /**
36
+ * Check if client is in vibe-coded mode (using connectionId)
37
+ */
38
+ isVibeCodedMode() {
39
+ return !!this.connectionId && !this.apiKey;
40
+ }
41
+ /**
42
+ * Check if client is in storefront mode (using storeId)
43
+ */
44
+ isStorefrontMode() {
45
+ return !!this.storeId && !this.apiKey && !this.connectionId;
46
+ }
47
+ /**
48
+ * Check if client is in admin mode (using apiKey)
49
+ */
50
+ isAdminMode() {
51
+ return !!this.apiKey;
52
+ }
53
+ // -------------------- Customer Token Management --------------------
54
+ /**
55
+ * Set the customer authentication token (obtained from login/register).
56
+ * Required for accessing customer-specific data in storefront mode.
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * const auth = await omni.loginCustomer('user@example.com', 'password');
61
+ * omni.setCustomerToken(auth.token);
62
+ *
63
+ * // Now can access customer data
64
+ * const profile = await omni.getMyProfile();
65
+ * ```
66
+ */
67
+ setCustomerToken(token) {
68
+ this.customerToken = token;
69
+ }
70
+ /**
71
+ * Get the current customer token
72
+ */
73
+ getCustomerToken() {
74
+ return this.customerToken;
75
+ }
76
+ /**
77
+ * Clear the customer token (logout)
78
+ */
79
+ clearCustomerToken() {
80
+ this.customerToken = null;
81
+ }
23
82
  // -------------------- Private Methods --------------------
24
- async request(method, path, body, queryParams) {
83
+ /**
84
+ * Make a request to the Admin API (requires apiKey)
85
+ */
86
+ async adminRequest(method, path, body, queryParams) {
87
+ if (!this.apiKey) {
88
+ throw new OmniSyncError(
89
+ "This operation requires an API key. Initialize with apiKey instead of storeId.",
90
+ 403
91
+ );
92
+ }
25
93
  const url = new URL(`${this.baseUrl}${path}`);
26
94
  if (queryParams) {
27
95
  Object.entries(queryParams).forEach(([key, value]) => {
@@ -38,9 +106,8 @@ var OmniSyncClient = class {
38
106
  headers: {
39
107
  Authorization: `Bearer ${this.apiKey}`,
40
108
  "Content-Type": "application/json",
41
- "X-SDK-Version": "0.1.0",
109
+ "X-SDK-Version": "0.3.0",
42
110
  "ngrok-skip-browser-warning": "true"
43
- // Skip ngrok warning page for dev tunnels
44
111
  },
45
112
  body: body ? JSON.stringify(body) : void 0,
46
113
  signal: controller.signal
@@ -71,12 +138,149 @@ var OmniSyncClient = class {
71
138
  throw new OmniSyncError("Unknown error occurred", 0);
72
139
  }
73
140
  }
141
+ /**
142
+ * Make a request to the Vibe-Coded API (public, uses connectionId)
143
+ */
144
+ async vibeCodedRequest(method, path, body, queryParams) {
145
+ if (!this.connectionId) {
146
+ throw new OmniSyncError("connectionId is required for vibe-coded requests", 400);
147
+ }
148
+ const url = new URL(`${this.baseUrl}/api/vc/${this.connectionId}${path}`);
149
+ if (queryParams) {
150
+ Object.entries(queryParams).forEach(([key, value]) => {
151
+ if (value !== void 0) {
152
+ url.searchParams.set(key, String(value));
153
+ }
154
+ });
155
+ }
156
+ const controller = new AbortController();
157
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
158
+ try {
159
+ const headers = {
160
+ "Content-Type": "application/json",
161
+ "X-SDK-Version": "0.3.0",
162
+ "ngrok-skip-browser-warning": "true"
163
+ };
164
+ const response = await fetch(url.toString(), {
165
+ method,
166
+ headers,
167
+ body: body ? JSON.stringify(body) : void 0,
168
+ signal: controller.signal
169
+ });
170
+ clearTimeout(timeoutId);
171
+ if (!response.ok) {
172
+ const errorData = await response.json().catch(() => ({}));
173
+ throw new OmniSyncError(
174
+ errorData.message || `Request failed with status ${response.status}`,
175
+ response.status,
176
+ errorData
177
+ );
178
+ }
179
+ const text = await response.text();
180
+ if (!text) return {};
181
+ return JSON.parse(text);
182
+ } catch (error) {
183
+ clearTimeout(timeoutId);
184
+ if (error instanceof OmniSyncError) {
185
+ throw error;
186
+ }
187
+ if (error instanceof Error) {
188
+ if (error.name === "AbortError") {
189
+ throw new OmniSyncError("Request timeout", 408);
190
+ }
191
+ throw new OmniSyncError(error.message, 0);
192
+ }
193
+ throw new OmniSyncError("Unknown error occurred", 0);
194
+ }
195
+ }
196
+ /**
197
+ * Make a request to the Storefront API (public, uses storeId)
198
+ */
199
+ async storefrontRequest(method, path, body, queryParams) {
200
+ if (!this.storeId) {
201
+ throw new OmniSyncError("storeId is required for storefront requests", 400);
202
+ }
203
+ const url = new URL(`${this.baseUrl}/stores/${this.storeId}${path}`);
204
+ if (queryParams) {
205
+ Object.entries(queryParams).forEach(([key, value]) => {
206
+ if (value !== void 0) {
207
+ url.searchParams.set(key, String(value));
208
+ }
209
+ });
210
+ }
211
+ const controller = new AbortController();
212
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
213
+ try {
214
+ const headers = {
215
+ "Content-Type": "application/json",
216
+ "X-SDK-Version": "0.3.0",
217
+ "ngrok-skip-browser-warning": "true"
218
+ };
219
+ if (this.customerToken) {
220
+ headers["Authorization"] = `Bearer ${this.customerToken}`;
221
+ }
222
+ const response = await fetch(url.toString(), {
223
+ method,
224
+ headers,
225
+ body: body ? JSON.stringify(body) : void 0,
226
+ signal: controller.signal
227
+ });
228
+ clearTimeout(timeoutId);
229
+ if (!response.ok) {
230
+ const errorData = await response.json().catch(() => ({}));
231
+ throw new OmniSyncError(
232
+ errorData.message || `Request failed with status ${response.status}`,
233
+ response.status,
234
+ errorData
235
+ );
236
+ }
237
+ const text = await response.text();
238
+ if (!text) return {};
239
+ return JSON.parse(text);
240
+ } catch (error) {
241
+ clearTimeout(timeoutId);
242
+ if (error instanceof OmniSyncError) {
243
+ throw error;
244
+ }
245
+ if (error instanceof Error) {
246
+ if (error.name === "AbortError") {
247
+ throw new OmniSyncError("Request timeout", 408);
248
+ }
249
+ throw new OmniSyncError(error.message, 0);
250
+ }
251
+ throw new OmniSyncError("Unknown error occurred", 0);
252
+ }
253
+ }
254
+ /**
255
+ * Smart request - uses storefront or admin API based on client mode
256
+ */
257
+ async request(method, path, body, queryParams) {
258
+ if (this.apiKey) {
259
+ return this.adminRequest(method, path, body, queryParams);
260
+ }
261
+ return this.storefrontRequest(method, path, body, queryParams);
262
+ }
263
+ // -------------------- Store Info --------------------
264
+ /**
265
+ * Get store information
266
+ * Works in vibe-coded, storefront, and admin mode
267
+ */
268
+ async getStoreInfo() {
269
+ if (this.isVibeCodedMode()) {
270
+ return this.vibeCodedRequest("GET", "/info");
271
+ }
272
+ if (this.storeId && !this.apiKey) {
273
+ return this.storefrontRequest("GET", "/info");
274
+ }
275
+ return this.adminRequest("GET", "/api/v1/store");
276
+ }
74
277
  // -------------------- Products --------------------
75
278
  /**
76
279
  * Get a list of products with pagination
280
+ * Works in vibe-coded, storefront (public), and admin mode
77
281
  */
78
282
  async getProducts(params) {
79
- return this.request("GET", "/api/v1/products", void 0, {
283
+ const queryParams = {
80
284
  page: params?.page,
81
285
  limit: params?.limit,
82
286
  search: params?.search,
@@ -84,13 +288,42 @@ var OmniSyncClient = class {
84
288
  type: params?.type,
85
289
  sortBy: params?.sortBy,
86
290
  sortOrder: params?.sortOrder
87
- });
291
+ };
292
+ if (this.isVibeCodedMode()) {
293
+ return this.vibeCodedRequest(
294
+ "GET",
295
+ "/products",
296
+ void 0,
297
+ queryParams
298
+ );
299
+ }
300
+ if (this.storeId && !this.apiKey) {
301
+ return this.storefrontRequest(
302
+ "GET",
303
+ "/products",
304
+ void 0,
305
+ queryParams
306
+ );
307
+ }
308
+ return this.adminRequest(
309
+ "GET",
310
+ "/api/v1/products",
311
+ void 0,
312
+ queryParams
313
+ );
88
314
  }
89
315
  /**
90
316
  * Get a single product by ID
317
+ * Works in vibe-coded, storefront (public), and admin mode
91
318
  */
92
319
  async getProduct(productId) {
93
- return this.request("GET", `/api/v1/products/${productId}`);
320
+ if (this.isVibeCodedMode()) {
321
+ return this.vibeCodedRequest("GET", `/products/${productId}`);
322
+ }
323
+ if (this.storeId && !this.apiKey) {
324
+ return this.storefrontRequest("GET", `/products/${productId}`);
325
+ }
326
+ return this.adminRequest("GET", `/api/v1/products/${productId}`);
94
327
  }
95
328
  /**
96
329
  * Create a new product
@@ -110,6 +343,147 @@ var OmniSyncClient = class {
110
343
  async deleteProduct(productId) {
111
344
  await this.request("DELETE", `/api/v1/products/${productId}`);
112
345
  }
346
+ /**
347
+ * Convert a SIMPLE product to VARIABLE product
348
+ *
349
+ * @example
350
+ * ```typescript
351
+ * const product = await omni.convertToVariable('prod_123');
352
+ * console.log('Product type:', product.type); // 'VARIABLE'
353
+ * ```
354
+ */
355
+ async convertToVariable(productId) {
356
+ return this.request("PATCH", `/api/v1/products/${productId}/convert-to-variable`);
357
+ }
358
+ /**
359
+ * Convert a VARIABLE product to SIMPLE product
360
+ * Note: This will delete all variants
361
+ *
362
+ * @example
363
+ * ```typescript
364
+ * const product = await omni.convertToSimple('prod_123');
365
+ * console.log('Product type:', product.type); // 'SIMPLE'
366
+ * ```
367
+ */
368
+ async convertToSimple(productId) {
369
+ return this.request("PATCH", `/api/v1/products/${productId}/convert-to-simple`);
370
+ }
371
+ /**
372
+ * Publish a product to specific platforms
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * const result = await omni.publishProduct('prod_123', ['SHOPIFY', 'WOOCOMMERCE']);
377
+ * console.log('Publish results:', result.results);
378
+ * ```
379
+ */
380
+ async publishProduct(productId, platforms) {
381
+ return this.request("POST", `/api/v1/products/${productId}/publish`, {
382
+ platforms
383
+ });
384
+ }
385
+ // -------------------- Variants --------------------
386
+ /**
387
+ * Create a new variant for a product
388
+ *
389
+ * @example
390
+ * ```typescript
391
+ * const variant = await omni.createVariant('prod_123', {
392
+ * sku: 'PROD-SM-RED',
393
+ * name: 'Small / Red',
394
+ * attributes: { size: 'S', color: 'Red' },
395
+ * price: 29.99,
396
+ * inventory: 100,
397
+ * });
398
+ * ```
399
+ */
400
+ async createVariant(productId, data) {
401
+ return this.request("POST", `/api/v1/products/${productId}/variants`, data);
402
+ }
403
+ /**
404
+ * Bulk save variants (create, update, delete in one operation)
405
+ *
406
+ * @example
407
+ * ```typescript
408
+ * const result = await omni.bulkSaveVariants('prod_123', {
409
+ * variants: [
410
+ * { sku: 'SM-RED', attributes: { size: 'S', color: 'Red' }, stock: 10, isEnabled: true },
411
+ * { id: 'var_456', sku: 'MD-BLUE', attributes: { size: 'M', color: 'Blue' }, stock: 5, isEnabled: true },
412
+ * { id: 'var_789', sku: 'LG-GREEN', attributes: {}, stock: 0, isEnabled: false, isDeleted: true },
413
+ * ],
414
+ * });
415
+ * console.log(`Created: ${result.created}, Updated: ${result.updated}, Deleted: ${result.deleted}`);
416
+ * ```
417
+ */
418
+ async bulkSaveVariants(productId, data) {
419
+ return this.request(
420
+ "POST",
421
+ `/api/v1/products/${productId}/variants/bulk`,
422
+ data
423
+ );
424
+ }
425
+ /**
426
+ * Update a variant
427
+ *
428
+ * @example
429
+ * ```typescript
430
+ * const variant = await omni.updateVariant('prod_123', 'var_456', {
431
+ * price: 34.99,
432
+ * salePrice: 29.99,
433
+ * });
434
+ * ```
435
+ */
436
+ async updateVariant(productId, variantId, data) {
437
+ return this.request(
438
+ "PATCH",
439
+ `/api/v1/products/${productId}/variants/${variantId}`,
440
+ data
441
+ );
442
+ }
443
+ /**
444
+ * Delete a variant
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * await omni.deleteVariant('prod_123', 'var_456');
449
+ * ```
450
+ */
451
+ async deleteVariant(productId, variantId) {
452
+ await this.request("DELETE", `/api/v1/products/${productId}/variants/${variantId}`);
453
+ }
454
+ /**
455
+ * Get inventory for a specific variant
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * const inventory = await omni.getVariantInventory('prod_123', 'var_456');
460
+ * console.log('Available:', inventory.available);
461
+ * ```
462
+ */
463
+ async getVariantInventory(productId, variantId) {
464
+ return this.request(
465
+ "GET",
466
+ `/api/v1/products/${productId}/variants/${variantId}/inventory`
467
+ );
468
+ }
469
+ /**
470
+ * Update inventory for a specific variant
471
+ *
472
+ * @example
473
+ * ```typescript
474
+ * const inventory = await omni.updateVariantInventory('prod_123', 'var_456', {
475
+ * newTotal: 50,
476
+ * reason: 'Restocked from supplier',
477
+ * });
478
+ * ```
479
+ */
480
+ async updateVariantInventory(productId, variantId, data) {
481
+ return this.request(
482
+ "PATCH",
483
+ `/api/v1/products/${productId}/variants/${variantId}/inventory`,
484
+ data
485
+ );
486
+ }
113
487
  // -------------------- Orders --------------------
114
488
  /**
115
489
  * Get a list of orders with pagination
@@ -142,6 +516,209 @@ var OmniSyncClient = class {
142
516
  async updateOrder(orderId, data) {
143
517
  return this.request("PATCH", `/api/v1/orders/${orderId}`, data);
144
518
  }
519
+ /**
520
+ * Update order status
521
+ *
522
+ * @example
523
+ * ```typescript
524
+ * const order = await omni.updateOrderStatus('order_123', 'shipped');
525
+ * ```
526
+ */
527
+ async updateOrderStatus(orderId, status) {
528
+ return this.request("PATCH", `/api/v1/orders/${orderId}/status`, { status });
529
+ }
530
+ /**
531
+ * Update order payment method
532
+ * Note: Only WooCommerce supports syncing payment method changes back to platform
533
+ *
534
+ * @example
535
+ * ```typescript
536
+ * const order = await omni.updatePaymentMethod('order_123', 'credit_card');
537
+ * ```
538
+ */
539
+ async updatePaymentMethod(orderId, paymentMethod) {
540
+ return this.request("PATCH", `/api/v1/orders/${orderId}/payment-method`, {
541
+ paymentMethod
542
+ });
543
+ }
544
+ /**
545
+ * Update order notes
546
+ *
547
+ * @example
548
+ * ```typescript
549
+ * const order = await omni.updateOrderNotes('order_123', 'Customer requested gift wrapping');
550
+ * ```
551
+ */
552
+ async updateOrderNotes(orderId, notes) {
553
+ return this.request("PATCH", `/api/v1/orders/${orderId}/notes`, { notes });
554
+ }
555
+ /**
556
+ * Get refunds for an order
557
+ * Returns refunds from the source platform (Shopify/WooCommerce only)
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * const refunds = await omni.getOrderRefunds('order_123');
562
+ * console.log('Total refunds:', refunds.length);
563
+ * ```
564
+ */
565
+ async getOrderRefunds(orderId) {
566
+ return this.request("GET", `/api/v1/orders/${orderId}/refunds`);
567
+ }
568
+ /**
569
+ * Create a refund for an order
570
+ * Creates refund on the source platform (Shopify/WooCommerce only)
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * // Full refund
575
+ * const refund = await omni.createRefund('order_123', {
576
+ * type: 'full',
577
+ * restockInventory: true,
578
+ * notifyCustomer: true,
579
+ * reason: 'Customer request',
580
+ * });
581
+ *
582
+ * // Partial refund
583
+ * const partialRefund = await omni.createRefund('order_123', {
584
+ * type: 'partial',
585
+ * items: [
586
+ * { lineItemId: 'item_456', quantity: 1 },
587
+ * ],
588
+ * restockInventory: true,
589
+ * });
590
+ * ```
591
+ */
592
+ async createRefund(orderId, data) {
593
+ return this.request("POST", `/api/v1/orders/${orderId}/refunds`, data);
594
+ }
595
+ /**
596
+ * Update order shipping address
597
+ * Syncs to source platform (Shopify/WooCommerce only)
598
+ *
599
+ * @example
600
+ * ```typescript
601
+ * const order = await omni.updateOrderShipping('order_123', {
602
+ * firstName: 'John',
603
+ * lastName: 'Doe',
604
+ * line1: '456 New Address',
605
+ * city: 'Los Angeles',
606
+ * state: 'CA',
607
+ * country: 'US',
608
+ * postalCode: '90001',
609
+ * });
610
+ * ```
611
+ */
612
+ async updateOrderShipping(orderId, data) {
613
+ return this.request("PATCH", `/api/v1/orders/${orderId}/shipping`, data);
614
+ }
615
+ /**
616
+ * Cancel an order
617
+ * Works for Shopify and WooCommerce orders that haven't been fulfilled
618
+ *
619
+ * @example
620
+ * ```typescript
621
+ * const order = await omni.cancelOrder('order_123');
622
+ * console.log('Order status:', order.status); // 'cancelled'
623
+ * ```
624
+ */
625
+ async cancelOrder(orderId) {
626
+ return this.request("POST", `/api/v1/orders/${orderId}/cancel`);
627
+ }
628
+ /**
629
+ * Fulfill an order (mark as shipped)
630
+ * Works for Shopify and WooCommerce orders
631
+ *
632
+ * @example
633
+ * ```typescript
634
+ * const order = await omni.fulfillOrder('order_123', {
635
+ * trackingNumber: '1Z999AA10123456784',
636
+ * trackingCompany: 'UPS',
637
+ * notifyCustomer: true,
638
+ * });
639
+ * ```
640
+ */
641
+ async fulfillOrder(orderId, data) {
642
+ return this.request("POST", `/api/v1/orders/${orderId}/fulfill`, data || {});
643
+ }
644
+ /**
645
+ * Sync draft orders from connected platforms
646
+ *
647
+ * @example
648
+ * ```typescript
649
+ * const result = await omni.syncDraftOrders();
650
+ * console.log('Draft orders synced');
651
+ * ```
652
+ */
653
+ async syncDraftOrders() {
654
+ return this.request("POST", "/api/v1/orders/sync-drafts");
655
+ }
656
+ /**
657
+ * Complete a draft order (convert to regular order)
658
+ *
659
+ * @example
660
+ * ```typescript
661
+ * const order = await omni.completeDraftOrder('draft_123', {
662
+ * paymentPending: false,
663
+ * });
664
+ * ```
665
+ */
666
+ async completeDraftOrder(orderId, data) {
667
+ return this.request("POST", `/api/v1/orders/${orderId}/complete-draft`, data || {});
668
+ }
669
+ /**
670
+ * Send invoice for a draft order
671
+ *
672
+ * @example
673
+ * ```typescript
674
+ * await omni.sendDraftInvoice('draft_123', {
675
+ * to: 'customer@example.com',
676
+ * subject: 'Your Invoice',
677
+ * customMessage: 'Thank you for your order!',
678
+ * });
679
+ * ```
680
+ */
681
+ async sendDraftInvoice(orderId, data) {
682
+ return this.request(
683
+ "POST",
684
+ `/api/v1/orders/${orderId}/send-invoice`,
685
+ data || {}
686
+ );
687
+ }
688
+ /**
689
+ * Delete a draft order
690
+ *
691
+ * @example
692
+ * ```typescript
693
+ * await omni.deleteDraftOrder('draft_123');
694
+ * ```
695
+ */
696
+ async deleteDraftOrder(orderId) {
697
+ await this.request("DELETE", `/api/v1/orders/${orderId}/draft`);
698
+ }
699
+ /**
700
+ * Update a draft order
701
+ *
702
+ * @example
703
+ * ```typescript
704
+ * const order = await omni.updateDraftOrder('draft_123', {
705
+ * note: 'Updated customer note',
706
+ * email: 'newemail@example.com',
707
+ * shippingAddress: {
708
+ * firstName: 'John',
709
+ * lastName: 'Doe',
710
+ * address1: '123 Main St',
711
+ * city: 'New York',
712
+ * province: 'NY',
713
+ * country: 'US',
714
+ * zip: '10001',
715
+ * },
716
+ * });
717
+ * ```
718
+ */
719
+ async updateDraftOrder(orderId, data) {
720
+ return this.request("PATCH", `/api/v1/orders/${orderId}/draft`, data);
721
+ }
145
722
  // -------------------- Inventory --------------------
146
723
  /**
147
724
  * Update inventory for a product
@@ -154,7 +731,74 @@ var OmniSyncClient = class {
154
731
  * Get current inventory for a product
155
732
  */
156
733
  async getInventory(productId) {
157
- return this.request("GET", `/api/v1/products/${productId}/inventory`);
734
+ return this.request("GET", `/api/v1/inventory/${productId}`);
735
+ }
736
+ /**
737
+ * Edit inventory manually with reason for audit trail
738
+ *
739
+ * @example
740
+ * ```typescript
741
+ * const inventory = await omni.editInventory({
742
+ * productId: 'prod_123',
743
+ * newTotal: 100,
744
+ * reason: 'Restocked from warehouse',
745
+ * });
746
+ * ```
747
+ */
748
+ async editInventory(data) {
749
+ return this.request("POST", "/api/v1/inventory/edit", data);
750
+ }
751
+ /**
752
+ * Get inventory sync status for all products in the store
753
+ *
754
+ * @example
755
+ * ```typescript
756
+ * const status = await omni.getInventorySyncStatus();
757
+ * console.log(`${status.pending} products pending sync`);
758
+ * console.log(`Last sync: ${status.lastSyncAt}`);
759
+ * ```
760
+ */
761
+ async getInventorySyncStatus() {
762
+ return this.request("GET", "/api/v1/inventory/sync-status");
763
+ }
764
+ /**
765
+ * Get inventory for multiple products at once
766
+ *
767
+ * @example
768
+ * ```typescript
769
+ * const inventories = await omni.getBulkInventory(['prod_123', 'prod_456', 'prod_789']);
770
+ * inventories.forEach(inv => {
771
+ * console.log(`${inv.productId}: ${inv.available} available`);
772
+ * });
773
+ * ```
774
+ */
775
+ async getBulkInventory(productIds) {
776
+ return this.request("POST", "/api/v1/inventory/bulk", { productIds });
777
+ }
778
+ /**
779
+ * Reconcile inventory between OmniSync and connected platforms
780
+ * Detects and optionally fixes discrepancies
781
+ *
782
+ * @example
783
+ * ```typescript
784
+ * // Reconcile single product (dry run)
785
+ * const result = await omni.reconcileInventory({ productId: 'prod_123' });
786
+ *
787
+ * // Reconcile all products with auto-fix
788
+ * const summary = await omni.reconcileInventory({ autoFix: true });
789
+ * console.log(`Reconciled ${summary.reconciled} products`);
790
+ * ```
791
+ */
792
+ async reconcileInventory(options) {
793
+ const queryParams = {};
794
+ if (options?.productId) queryParams.productId = options.productId;
795
+ if (options?.autoFix) queryParams.autoFix = "true";
796
+ return this.request(
797
+ "POST",
798
+ "/api/v1/inventory/reconcile",
799
+ void 0,
800
+ queryParams
801
+ );
158
802
  }
159
803
  // -------------------- Sync --------------------
160
804
  /**
@@ -169,13 +813,6 @@ var OmniSyncClient = class {
169
813
  async getSyncStatus(jobId) {
170
814
  return this.request("GET", `/api/v1/sync/${jobId}`);
171
815
  }
172
- // -------------------- Store Info --------------------
173
- /**
174
- * Get information about the connected store
175
- */
176
- async getStoreInfo() {
177
- return this.request("GET", "/api/v1/store");
178
- }
179
816
  // -------------------- Coupons --------------------
180
817
  /**
181
818
  * Get a list of coupons with pagination
@@ -318,7 +955,13 @@ var OmniSyncClient = class {
318
955
  * ```
319
956
  */
320
957
  async loginCustomer(email, password) {
321
- return this.request("POST", "/api/v1/customers/login", {
958
+ if (this.storeId && !this.apiKey) {
959
+ return this.storefrontRequest("POST", "/customers/login", {
960
+ email,
961
+ password
962
+ });
963
+ }
964
+ return this.adminRequest("POST", "/api/v1/customers/login", {
322
965
  email,
323
966
  password
324
967
  });
@@ -337,13 +980,21 @@ var OmniSyncClient = class {
337
980
  * ```
338
981
  */
339
982
  async registerCustomer(data) {
340
- return this.request("POST", "/api/v1/customers/register", data);
983
+ if (this.storeId && !this.apiKey) {
984
+ return this.storefrontRequest("POST", "/customers/register", data);
985
+ }
986
+ return this.adminRequest("POST", "/api/v1/customers/register", data);
341
987
  }
342
988
  /**
343
989
  * Request a password reset email for a customer
344
990
  */
345
991
  async forgotPassword(email) {
346
- return this.request("POST", "/api/v1/customers/forgot-password", {
992
+ if (this.storeId && !this.apiKey) {
993
+ return this.storefrontRequest("POST", "/customers/forgot-password", {
994
+ email
995
+ });
996
+ }
997
+ return this.adminRequest("POST", "/api/v1/customers/forgot-password", {
347
998
  email
348
999
  });
349
1000
  }
@@ -423,7 +1074,10 @@ var OmniSyncClient = class {
423
1074
  * ```
424
1075
  */
425
1076
  async createCart() {
426
- return this.request("POST", "/api/v1/cart");
1077
+ if (this.storeId && !this.apiKey) {
1078
+ return this.storefrontRequest("POST", "/cart");
1079
+ }
1080
+ return this.adminRequest("POST", "/api/v1/cart");
427
1081
  }
428
1082
  /**
429
1083
  * Get a cart by session token (for guest users)
@@ -435,7 +1089,10 @@ var OmniSyncClient = class {
435
1089
  * ```
436
1090
  */
437
1091
  async getCartBySession(sessionToken) {
438
- return this.request("GET", `/api/v1/cart/session/${sessionToken}`);
1092
+ if (this.storeId && !this.apiKey) {
1093
+ return this.storefrontRequest("GET", `/cart/session/${sessionToken}`);
1094
+ }
1095
+ return this.adminRequest("GET", `/api/v1/cart/session/${sessionToken}`);
439
1096
  }
440
1097
  /**
441
1098
  * Get a cart by customer ID (for authenticated users)
@@ -447,13 +1104,19 @@ var OmniSyncClient = class {
447
1104
  * ```
448
1105
  */
449
1106
  async getCartByCustomer(customerId) {
450
- return this.request("GET", `/api/v1/cart/customer/${customerId}`);
1107
+ if (this.storeId && !this.apiKey) {
1108
+ return this.storefrontRequest("GET", `/cart/customer/${customerId}`);
1109
+ }
1110
+ return this.adminRequest("GET", `/api/v1/cart/customer/${customerId}`);
451
1111
  }
452
1112
  /**
453
1113
  * Get a cart by ID
454
1114
  */
455
1115
  async getCart(cartId) {
456
- return this.request("GET", `/api/v1/cart/${cartId}`);
1116
+ if (this.storeId && !this.apiKey) {
1117
+ return this.storefrontRequest("GET", `/cart/${cartId}`);
1118
+ }
1119
+ return this.adminRequest("GET", `/api/v1/cart/${cartId}`);
457
1120
  }
458
1121
  /**
459
1122
  * Add an item to the cart
@@ -468,7 +1131,10 @@ var OmniSyncClient = class {
468
1131
  * ```
469
1132
  */
470
1133
  async addToCart(cartId, item) {
471
- return this.request("POST", `/api/v1/cart/${cartId}/items`, item);
1134
+ if (this.storeId && !this.apiKey) {
1135
+ return this.storefrontRequest("POST", `/cart/${cartId}/items`, item);
1136
+ }
1137
+ return this.adminRequest("POST", `/api/v1/cart/${cartId}/items`, item);
472
1138
  }
473
1139
  /**
474
1140
  * Update an item quantity in the cart
@@ -479,7 +1145,10 @@ var OmniSyncClient = class {
479
1145
  * ```
480
1146
  */
481
1147
  async updateCartItem(cartId, itemId, data) {
482
- return this.request("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data);
1148
+ if (this.storeId && !this.apiKey) {
1149
+ return this.storefrontRequest("PATCH", `/cart/${cartId}/items/${itemId}`, data);
1150
+ }
1151
+ return this.adminRequest("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data);
483
1152
  }
484
1153
  /**
485
1154
  * Remove an item from the cart
@@ -490,7 +1159,10 @@ var OmniSyncClient = class {
490
1159
  * ```
491
1160
  */
492
1161
  async removeCartItem(cartId, itemId) {
493
- return this.request("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`);
1162
+ if (this.storeId && !this.apiKey) {
1163
+ return this.storefrontRequest("DELETE", `/cart/${cartId}/items/${itemId}`);
1164
+ }
1165
+ return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`);
494
1166
  }
495
1167
  /**
496
1168
  * Clear all items from the cart
@@ -501,7 +1173,11 @@ var OmniSyncClient = class {
501
1173
  * ```
502
1174
  */
503
1175
  async clearCart(cartId) {
504
- await this.request("DELETE", `/api/v1/cart/${cartId}/items`);
1176
+ if (this.storeId && !this.apiKey) {
1177
+ await this.storefrontRequest("DELETE", `/cart/${cartId}/items`);
1178
+ return;
1179
+ }
1180
+ await this.adminRequest("DELETE", `/api/v1/cart/${cartId}/items`);
505
1181
  }
506
1182
  /**
507
1183
  * Apply a coupon to the cart
@@ -513,7 +1189,10 @@ var OmniSyncClient = class {
513
1189
  * ```
514
1190
  */
515
1191
  async applyCoupon(cartId, code) {
516
- return this.request("POST", `/api/v1/cart/${cartId}/coupon`, { code });
1192
+ if (this.storeId && !this.apiKey) {
1193
+ return this.storefrontRequest("POST", `/cart/${cartId}/coupon`, { code });
1194
+ }
1195
+ return this.adminRequest("POST", `/api/v1/cart/${cartId}/coupon`, { code });
517
1196
  }
518
1197
  /**
519
1198
  * Remove a coupon from the cart
@@ -524,7 +1203,10 @@ var OmniSyncClient = class {
524
1203
  * ```
525
1204
  */
526
1205
  async removeCoupon(cartId) {
527
- return this.request("DELETE", `/api/v1/cart/${cartId}/coupon`);
1206
+ if (this.storeId && !this.apiKey) {
1207
+ return this.storefrontRequest("DELETE", `/cart/${cartId}/coupon`);
1208
+ }
1209
+ return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/coupon`);
528
1210
  }
529
1211
  /**
530
1212
  * Merge a guest cart into a customer's cart (after login)
@@ -540,7 +1222,10 @@ var OmniSyncClient = class {
540
1222
  * ```
541
1223
  */
542
1224
  async mergeCarts(data) {
543
- return this.request("POST", "/api/v1/cart/merge", data);
1225
+ if (this.storeId && !this.apiKey) {
1226
+ return this.storefrontRequest("POST", "/cart/merge", data);
1227
+ }
1228
+ return this.adminRequest("POST", "/api/v1/cart/merge", data);
544
1229
  }
545
1230
  // -------------------- Checkout --------------------
546
1231
  /**
@@ -554,7 +1239,10 @@ var OmniSyncClient = class {
554
1239
  * ```
555
1240
  */
556
1241
  async createCheckout(data) {
557
- return this.request("POST", "/api/v1/checkout", data);
1242
+ if (this.storeId && !this.apiKey) {
1243
+ return this.storefrontRequest("POST", "/checkout", data);
1244
+ }
1245
+ return this.adminRequest("POST", "/api/v1/checkout", data);
558
1246
  }
559
1247
  /**
560
1248
  * Get a checkout by ID
@@ -566,7 +1254,10 @@ var OmniSyncClient = class {
566
1254
  * ```
567
1255
  */
568
1256
  async getCheckout(checkoutId) {
569
- return this.request("GET", `/api/v1/checkout/${checkoutId}`);
1257
+ if (this.storeId && !this.apiKey) {
1258
+ return this.storefrontRequest("GET", `/checkout/${checkoutId}`);
1259
+ }
1260
+ return this.adminRequest("GET", `/api/v1/checkout/${checkoutId}`);
570
1261
  }
571
1262
  /**
572
1263
  * Set customer information on checkout
@@ -581,7 +1272,10 @@ var OmniSyncClient = class {
581
1272
  * ```
582
1273
  */
583
1274
  async setCheckoutCustomer(checkoutId, data) {
584
- return this.request("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
1275
+ if (this.storeId && !this.apiKey) {
1276
+ return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/customer`, data);
1277
+ }
1278
+ return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
585
1279
  }
586
1280
  /**
587
1281
  * Set shipping address on checkout
@@ -602,7 +1296,14 @@ var OmniSyncClient = class {
602
1296
  * ```
603
1297
  */
604
1298
  async setShippingAddress(checkoutId, address) {
605
- return this.request(
1299
+ if (this.storeId && !this.apiKey) {
1300
+ return this.storefrontRequest(
1301
+ "PATCH",
1302
+ `/checkout/${checkoutId}/shipping-address`,
1303
+ address
1304
+ );
1305
+ }
1306
+ return this.adminRequest(
606
1307
  "PATCH",
607
1308
  `/api/v1/checkout/${checkoutId}/shipping-address`,
608
1309
  address
@@ -619,7 +1320,16 @@ var OmniSyncClient = class {
619
1320
  * ```
620
1321
  */
621
1322
  async getShippingRates(checkoutId) {
622
- return this.request("GET", `/api/v1/checkout/${checkoutId}/shipping-rates`);
1323
+ if (this.storeId && !this.apiKey) {
1324
+ return this.storefrontRequest(
1325
+ "GET",
1326
+ `/checkout/${checkoutId}/shipping-rates`
1327
+ );
1328
+ }
1329
+ return this.adminRequest(
1330
+ "GET",
1331
+ `/api/v1/checkout/${checkoutId}/shipping-rates`
1332
+ );
623
1333
  }
624
1334
  /**
625
1335
  * Select a shipping method for checkout
@@ -631,7 +1341,12 @@ var OmniSyncClient = class {
631
1341
  * ```
632
1342
  */
633
1343
  async selectShippingMethod(checkoutId, shippingRateId) {
634
- return this.request("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
1344
+ if (this.storeId && !this.apiKey) {
1345
+ return this.storefrontRequest("PATCH", `/checkout/${checkoutId}/shipping-method`, {
1346
+ shippingRateId
1347
+ });
1348
+ }
1349
+ return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
635
1350
  shippingRateId
636
1351
  });
637
1352
  }
@@ -660,7 +1375,14 @@ var OmniSyncClient = class {
660
1375
  * ```
661
1376
  */
662
1377
  async setBillingAddress(checkoutId, address) {
663
- return this.request(
1378
+ if (this.storeId && !this.apiKey) {
1379
+ return this.storefrontRequest(
1380
+ "PATCH",
1381
+ `/checkout/${checkoutId}/billing-address`,
1382
+ address
1383
+ );
1384
+ }
1385
+ return this.adminRequest(
664
1386
  "PATCH",
665
1387
  `/api/v1/checkout/${checkoutId}/billing-address`,
666
1388
  address
@@ -677,11 +1399,143 @@ var OmniSyncClient = class {
677
1399
  * ```
678
1400
  */
679
1401
  async completeCheckout(checkoutId) {
680
- return this.request(
1402
+ if (this.storeId && !this.apiKey) {
1403
+ return this.storefrontRequest(
1404
+ "POST",
1405
+ `/checkout/${checkoutId}/complete`
1406
+ );
1407
+ }
1408
+ return this.adminRequest(
681
1409
  "POST",
682
1410
  `/api/v1/checkout/${checkoutId}/complete`
683
1411
  );
684
1412
  }
1413
+ // -------------------- Storefront Customer Self-Service --------------------
1414
+ // These methods require customerToken to be set (call setCustomerToken after login)
1415
+ /**
1416
+ * Get the current customer's profile (requires customerToken)
1417
+ * Only available in storefront mode
1418
+ *
1419
+ * @example
1420
+ * ```typescript
1421
+ * const auth = await omni.loginCustomer('user@example.com', 'password');
1422
+ * omni.setCustomerToken(auth.token);
1423
+ * const profile = await omni.getMyProfile();
1424
+ * ```
1425
+ */
1426
+ async getMyProfile() {
1427
+ if (!this.storeId) {
1428
+ throw new OmniSyncError("getMyProfile is only available in storefront mode", 400);
1429
+ }
1430
+ if (!this.customerToken) {
1431
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1432
+ }
1433
+ return this.storefrontRequest("GET", "/customers/me");
1434
+ }
1435
+ /**
1436
+ * Update the current customer's profile (requires customerToken)
1437
+ * Only available in storefront mode
1438
+ */
1439
+ async updateMyProfile(data) {
1440
+ if (!this.storeId) {
1441
+ throw new OmniSyncError("updateMyProfile is only available in storefront mode", 400);
1442
+ }
1443
+ if (!this.customerToken) {
1444
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1445
+ }
1446
+ return this.storefrontRequest("PATCH", "/customers/me", data);
1447
+ }
1448
+ /**
1449
+ * Get the current customer's orders (requires customerToken)
1450
+ * Only available in storefront mode
1451
+ */
1452
+ async getMyOrders(params) {
1453
+ if (!this.storeId) {
1454
+ throw new OmniSyncError("getMyOrders is only available in storefront mode", 400);
1455
+ }
1456
+ if (!this.customerToken) {
1457
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1458
+ }
1459
+ return this.storefrontRequest(
1460
+ "GET",
1461
+ "/customers/me/orders",
1462
+ void 0,
1463
+ {
1464
+ page: params?.page,
1465
+ limit: params?.limit
1466
+ }
1467
+ );
1468
+ }
1469
+ /**
1470
+ * Get the current customer's addresses (requires customerToken)
1471
+ * Only available in storefront mode
1472
+ */
1473
+ async getMyAddresses() {
1474
+ if (!this.storeId) {
1475
+ throw new OmniSyncError("getMyAddresses is only available in storefront mode", 400);
1476
+ }
1477
+ if (!this.customerToken) {
1478
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1479
+ }
1480
+ return this.storefrontRequest("GET", "/customers/me/addresses");
1481
+ }
1482
+ /**
1483
+ * Add an address to the current customer (requires customerToken)
1484
+ * Only available in storefront mode
1485
+ */
1486
+ async addMyAddress(address) {
1487
+ if (!this.storeId) {
1488
+ throw new OmniSyncError("addMyAddress is only available in storefront mode", 400);
1489
+ }
1490
+ if (!this.customerToken) {
1491
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1492
+ }
1493
+ return this.storefrontRequest("POST", "/customers/me/addresses", address);
1494
+ }
1495
+ /**
1496
+ * Update a customer address (requires customerToken)
1497
+ * Only available in storefront mode
1498
+ */
1499
+ async updateMyAddress(addressId, data) {
1500
+ if (!this.storeId) {
1501
+ throw new OmniSyncError("updateMyAddress is only available in storefront mode", 400);
1502
+ }
1503
+ if (!this.customerToken) {
1504
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1505
+ }
1506
+ return this.storefrontRequest(
1507
+ "PATCH",
1508
+ `/customers/me/addresses/${addressId}`,
1509
+ data
1510
+ );
1511
+ }
1512
+ /**
1513
+ * Delete a customer address (requires customerToken)
1514
+ * Only available in storefront mode
1515
+ */
1516
+ async deleteMyAddress(addressId) {
1517
+ if (!this.storeId) {
1518
+ throw new OmniSyncError("deleteMyAddress is only available in storefront mode", 400);
1519
+ }
1520
+ if (!this.customerToken) {
1521
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1522
+ }
1523
+ await this.storefrontRequest("DELETE", `/customers/me/addresses/${addressId}`);
1524
+ }
1525
+ /**
1526
+ * Get the current customer's cart (requires customerToken)
1527
+ * Creates a new cart if none exists
1528
+ * Only available in storefront mode
1529
+ */
1530
+ async getMyCart() {
1531
+ if (!this.storeId) {
1532
+ throw new OmniSyncError("getMyCart is only available in storefront mode", 400);
1533
+ }
1534
+ if (!this.customerToken) {
1535
+ throw new OmniSyncError("Customer token required. Call setCustomerToken() after login.", 401);
1536
+ }
1537
+ return this.storefrontRequest("GET", "/customers/me/cart");
1538
+ }
685
1539
  };
686
1540
  var OmniSyncError = class extends Error {
687
1541
  constructor(message, statusCode, details) {