omni-sync-sdk 0.1.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 ADDED
@@ -0,0 +1,790 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/client.ts
9
+ var DEFAULT_BASE_URL = "https://api.omni-sync.com";
10
+ var DEFAULT_TIMEOUT = 3e4;
11
+ var OmniSyncClient = class {
12
+ constructor(options) {
13
+ if (!options.apiKey) {
14
+ throw new Error("OmniSyncClient: apiKey is required");
15
+ }
16
+ if (!options.apiKey.startsWith("omni_")) {
17
+ console.warn('OmniSyncClient: apiKey should start with "omni_"');
18
+ }
19
+ this.apiKey = options.apiKey;
20
+ this.baseUrl = (options.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
21
+ this.timeout = options.timeout || DEFAULT_TIMEOUT;
22
+ }
23
+ // -------------------- Private Methods --------------------
24
+ async request(method, path, body, queryParams) {
25
+ const url = new URL(`${this.baseUrl}${path}`);
26
+ if (queryParams) {
27
+ Object.entries(queryParams).forEach(([key, value]) => {
28
+ if (value !== void 0) {
29
+ url.searchParams.set(key, String(value));
30
+ }
31
+ });
32
+ }
33
+ const controller = new AbortController();
34
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
35
+ try {
36
+ const response = await fetch(url.toString(), {
37
+ method,
38
+ headers: {
39
+ Authorization: `Bearer ${this.apiKey}`,
40
+ "Content-Type": "application/json",
41
+ "X-SDK-Version": "0.1.0"
42
+ },
43
+ body: body ? JSON.stringify(body) : void 0,
44
+ signal: controller.signal
45
+ });
46
+ clearTimeout(timeoutId);
47
+ if (!response.ok) {
48
+ const errorData = await response.json().catch(() => ({}));
49
+ throw new OmniSyncError(
50
+ errorData.message || `Request failed with status ${response.status}`,
51
+ response.status,
52
+ errorData
53
+ );
54
+ }
55
+ const text = await response.text();
56
+ if (!text) return {};
57
+ return JSON.parse(text);
58
+ } catch (error) {
59
+ clearTimeout(timeoutId);
60
+ if (error instanceof OmniSyncError) {
61
+ throw error;
62
+ }
63
+ if (error instanceof Error) {
64
+ if (error.name === "AbortError") {
65
+ throw new OmniSyncError("Request timeout", 408);
66
+ }
67
+ throw new OmniSyncError(error.message, 0);
68
+ }
69
+ throw new OmniSyncError("Unknown error occurred", 0);
70
+ }
71
+ }
72
+ // -------------------- Products --------------------
73
+ /**
74
+ * Get a list of products with pagination
75
+ */
76
+ async getProducts(params) {
77
+ return this.request("GET", "/api/v1/products", void 0, {
78
+ page: params?.page,
79
+ limit: params?.limit,
80
+ search: params?.search,
81
+ status: params?.status,
82
+ type: params?.type,
83
+ sortBy: params?.sortBy,
84
+ sortOrder: params?.sortOrder
85
+ });
86
+ }
87
+ /**
88
+ * Get a single product by ID
89
+ */
90
+ async getProduct(productId) {
91
+ return this.request("GET", `/api/v1/products/${productId}`);
92
+ }
93
+ /**
94
+ * Create a new product
95
+ */
96
+ async createProduct(data) {
97
+ return this.request("POST", "/api/v1/products", data);
98
+ }
99
+ /**
100
+ * Update an existing product
101
+ */
102
+ async updateProduct(productId, data) {
103
+ return this.request("PATCH", `/api/v1/products/${productId}`, data);
104
+ }
105
+ /**
106
+ * Delete a product
107
+ */
108
+ async deleteProduct(productId) {
109
+ await this.request("DELETE", `/api/v1/products/${productId}`);
110
+ }
111
+ // -------------------- Orders --------------------
112
+ /**
113
+ * Get a list of orders with pagination
114
+ */
115
+ async getOrders(params) {
116
+ return this.request("GET", "/api/v1/orders", void 0, {
117
+ page: params?.page,
118
+ limit: params?.limit,
119
+ status: params?.status,
120
+ sortBy: params?.sortBy,
121
+ sortOrder: params?.sortOrder
122
+ });
123
+ }
124
+ /**
125
+ * Get a single order by ID
126
+ */
127
+ async getOrder(orderId) {
128
+ return this.request("GET", `/api/v1/orders/${orderId}`);
129
+ }
130
+ /**
131
+ * Create a new order
132
+ * This will automatically deduct inventory and sync to connected platforms
133
+ */
134
+ async createOrder(data) {
135
+ return this.request("POST", "/api/v1/orders", data);
136
+ }
137
+ /**
138
+ * Update an order (e.g., change status)
139
+ */
140
+ async updateOrder(orderId, data) {
141
+ return this.request("PATCH", `/api/v1/orders/${orderId}`, data);
142
+ }
143
+ // -------------------- Inventory --------------------
144
+ /**
145
+ * Update inventory for a product
146
+ * This will sync inventory to all connected platforms
147
+ */
148
+ async updateInventory(productId, data) {
149
+ await this.request("PUT", `/api/v1/products/${productId}/inventory`, data);
150
+ }
151
+ /**
152
+ * Get current inventory for a product
153
+ */
154
+ async getInventory(productId) {
155
+ return this.request("GET", `/api/v1/products/${productId}/inventory`);
156
+ }
157
+ // -------------------- Sync --------------------
158
+ /**
159
+ * Trigger a sync to a specific platform or all platforms
160
+ */
161
+ async triggerSync(platform) {
162
+ return this.request("POST", "/api/v1/sync", { platform });
163
+ }
164
+ /**
165
+ * Get the status of a sync job
166
+ */
167
+ async getSyncStatus(jobId) {
168
+ return this.request("GET", `/api/v1/sync/${jobId}`);
169
+ }
170
+ // -------------------- Store Info --------------------
171
+ /**
172
+ * Get information about the connected store
173
+ */
174
+ async getStoreInfo() {
175
+ return this.request("GET", "/api/v1/store");
176
+ }
177
+ // -------------------- Coupons --------------------
178
+ /**
179
+ * Get a list of coupons with pagination
180
+ */
181
+ async getCoupons(params) {
182
+ return this.request("GET", "/api/v1/coupons", void 0, {
183
+ page: params?.page,
184
+ limit: params?.limit,
185
+ search: params?.search,
186
+ status: params?.status,
187
+ type: params?.type,
188
+ platform: params?.platform,
189
+ sortBy: params?.sortBy,
190
+ sortOrder: params?.sortOrder
191
+ });
192
+ }
193
+ /**
194
+ * Get a single coupon by ID
195
+ */
196
+ async getCoupon(couponId) {
197
+ return this.request("GET", `/api/v1/coupons/${couponId}`);
198
+ }
199
+ /**
200
+ * Create a new coupon.
201
+ * Returns validation warnings if syncing to platforms that don't support certain features.
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * const coupon = await omni.createCoupon({
206
+ * code: 'SUMMER20',
207
+ * type: 'PERCENTAGE',
208
+ * value: 20,
209
+ * applicableCategories: ['cat_electronics'],
210
+ * excludedProducts: ['prod_clearance_item'],
211
+ * platforms: ['WOOCOMMERCE', 'SHOPIFY'],
212
+ * });
213
+ *
214
+ * // Check for platform limitations
215
+ * if (coupon.validationWarnings?.length) {
216
+ * console.warn('Some features not supported:', coupon.validationWarnings);
217
+ * }
218
+ * ```
219
+ */
220
+ async createCoupon(data) {
221
+ return this.request("POST", "/api/v1/coupons", data);
222
+ }
223
+ /**
224
+ * Update an existing coupon
225
+ */
226
+ async updateCoupon(couponId, data) {
227
+ return this.request("PATCH", `/api/v1/coupons/${couponId}`, data);
228
+ }
229
+ /**
230
+ * Delete a coupon
231
+ */
232
+ async deleteCoupon(couponId) {
233
+ await this.request("DELETE", `/api/v1/coupons/${couponId}`);
234
+ }
235
+ /**
236
+ * Sync a coupon to all connected platforms.
237
+ * Returns a sync job that can be tracked with getSyncStatus().
238
+ */
239
+ async syncCoupon(couponId) {
240
+ return this.request("POST", `/api/v1/coupons/${couponId}/sync`);
241
+ }
242
+ /**
243
+ * Publish a coupon to specific platforms.
244
+ * Use this for selective syncing instead of syncing to all platforms.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * // Only sync to WooCommerce and Shopify
249
+ * await omni.publishCoupon('coupon_123', ['WOOCOMMERCE', 'SHOPIFY']);
250
+ * ```
251
+ */
252
+ async publishCoupon(couponId, platforms) {
253
+ return this.request("POST", `/api/v1/coupons/${couponId}/publish`, { platforms });
254
+ }
255
+ /**
256
+ * Get platform capabilities for coupon features.
257
+ * Use this to understand what features each platform supports.
258
+ *
259
+ * @example
260
+ * ```typescript
261
+ * const capabilities = await omni.getCouponPlatformCapabilities();
262
+ * if (!capabilities.SHOPIFY.supportsProductExclusions) {
263
+ * console.log('Shopify does not support product exclusions');
264
+ * }
265
+ * ```
266
+ */
267
+ async getCouponPlatformCapabilities() {
268
+ return this.request(
269
+ "GET",
270
+ "/api/v1/coupons/platform-capabilities"
271
+ );
272
+ }
273
+ // -------------------- Customers --------------------
274
+ /**
275
+ * Create a new customer
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * const customer = await omni.createCustomer({
280
+ * email: 'customer@example.com',
281
+ * firstName: 'John',
282
+ * lastName: 'Doe',
283
+ * acceptsMarketing: true,
284
+ * });
285
+ * ```
286
+ */
287
+ async createCustomer(data) {
288
+ return this.request("POST", "/api/v1/customers", data);
289
+ }
290
+ /**
291
+ * Get a customer by ID
292
+ */
293
+ async getCustomer(customerId) {
294
+ return this.request("GET", `/api/v1/customers/${customerId}`);
295
+ }
296
+ /**
297
+ * Update a customer
298
+ */
299
+ async updateCustomer(customerId, data) {
300
+ return this.request("PATCH", `/api/v1/customers/${customerId}`, data);
301
+ }
302
+ /**
303
+ * Get a customer by email
304
+ */
305
+ async getCustomerByEmail(email) {
306
+ return this.request("GET", "/api/v1/customers/by-email", void 0, { email });
307
+ }
308
+ /**
309
+ * Login an existing customer (returns JWT token)
310
+ *
311
+ * @example
312
+ * ```typescript
313
+ * const auth = await omni.loginCustomer('customer@example.com', 'password123');
314
+ * console.log('Customer logged in:', auth.customer.email);
315
+ * // Store auth.token for subsequent authenticated requests
316
+ * ```
317
+ */
318
+ async loginCustomer(email, password) {
319
+ return this.request("POST", "/api/v1/customers/login", {
320
+ email,
321
+ password
322
+ });
323
+ }
324
+ /**
325
+ * Register a new customer with password (creates account)
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * const auth = await omni.registerCustomer({
330
+ * email: 'newcustomer@example.com',
331
+ * password: 'securepassword123',
332
+ * firstName: 'Jane',
333
+ * lastName: 'Doe',
334
+ * });
335
+ * ```
336
+ */
337
+ async registerCustomer(data) {
338
+ return this.request("POST", "/api/v1/customers/register", data);
339
+ }
340
+ /**
341
+ * Request a password reset email for a customer
342
+ */
343
+ async forgotPassword(email) {
344
+ return this.request("POST", "/api/v1/customers/forgot-password", {
345
+ email
346
+ });
347
+ }
348
+ /**
349
+ * Get all addresses for a customer
350
+ */
351
+ async getCustomerAddresses(customerId) {
352
+ return this.request("GET", `/api/v1/customers/${customerId}/addresses`);
353
+ }
354
+ /**
355
+ * Add an address to a customer
356
+ *
357
+ * @example
358
+ * ```typescript
359
+ * const address = await omni.addCustomerAddress('cust_123', {
360
+ * firstName: 'John',
361
+ * lastName: 'Doe',
362
+ * line1: '123 Main St',
363
+ * city: 'New York',
364
+ * region: 'NY',
365
+ * postalCode: '10001',
366
+ * country: 'US',
367
+ * isDefault: true,
368
+ * });
369
+ * ```
370
+ */
371
+ async addCustomerAddress(customerId, address) {
372
+ return this.request(
373
+ "POST",
374
+ `/api/v1/customers/${customerId}/addresses`,
375
+ address
376
+ );
377
+ }
378
+ /**
379
+ * Update a customer address
380
+ */
381
+ async updateCustomerAddress(customerId, addressId, address) {
382
+ return this.request(
383
+ "PATCH",
384
+ `/api/v1/customers/${customerId}/addresses/${addressId}`,
385
+ address
386
+ );
387
+ }
388
+ /**
389
+ * Delete a customer address
390
+ */
391
+ async deleteCustomerAddress(customerId, addressId) {
392
+ await this.request("DELETE", `/api/v1/customers/${customerId}/addresses/${addressId}`);
393
+ }
394
+ /**
395
+ * Get orders for a customer
396
+ *
397
+ * @example
398
+ * ```typescript
399
+ * const orders = await omni.getCustomerOrders('cust_123', { page: 1, limit: 10 });
400
+ * console.log(`Customer has ${orders.meta.total} total orders`);
401
+ * ```
402
+ */
403
+ async getCustomerOrders(customerId, params) {
404
+ return this.request(
405
+ "GET",
406
+ `/api/v1/customers/${customerId}/orders`,
407
+ void 0,
408
+ { page: params?.page, limit: params?.limit }
409
+ );
410
+ }
411
+ // -------------------- Cart --------------------
412
+ /**
413
+ * Create a new cart for a guest user
414
+ * Returns a cart with a sessionToken that identifies this cart
415
+ *
416
+ * @example
417
+ * ```typescript
418
+ * const cart = await omni.createCart();
419
+ * console.log('Cart session:', cart.sessionToken);
420
+ * // Store sessionToken in localStorage or cookie
421
+ * ```
422
+ */
423
+ async createCart() {
424
+ return this.request("POST", "/api/v1/cart");
425
+ }
426
+ /**
427
+ * Get a cart by session token (for guest users)
428
+ *
429
+ * @example
430
+ * ```typescript
431
+ * const cart = await omni.getCartBySession('sess_abc123');
432
+ * console.log('Items in cart:', cart.itemCount);
433
+ * ```
434
+ */
435
+ async getCartBySession(sessionToken) {
436
+ return this.request("GET", `/api/v1/cart/session/${sessionToken}`);
437
+ }
438
+ /**
439
+ * Get a cart by customer ID (for authenticated users)
440
+ *
441
+ * @example
442
+ * ```typescript
443
+ * const cart = await omni.getCartByCustomer('cust_123');
444
+ * console.log('Customer cart total:', cart.subtotal);
445
+ * ```
446
+ */
447
+ async getCartByCustomer(customerId) {
448
+ return this.request("GET", `/api/v1/cart/customer/${customerId}`);
449
+ }
450
+ /**
451
+ * Get a cart by ID
452
+ */
453
+ async getCart(cartId) {
454
+ return this.request("GET", `/api/v1/cart/${cartId}`);
455
+ }
456
+ /**
457
+ * Add an item to the cart
458
+ *
459
+ * @example
460
+ * ```typescript
461
+ * const cart = await omni.addToCart('cart_123', {
462
+ * productId: 'prod_abc',
463
+ * quantity: 2,
464
+ * notes: 'Gift wrap please',
465
+ * });
466
+ * ```
467
+ */
468
+ async addToCart(cartId, item) {
469
+ return this.request("POST", `/api/v1/cart/${cartId}/items`, item);
470
+ }
471
+ /**
472
+ * Update an item quantity in the cart
473
+ *
474
+ * @example
475
+ * ```typescript
476
+ * const cart = await omni.updateCartItem('cart_123', 'item_456', { quantity: 3 });
477
+ * ```
478
+ */
479
+ async updateCartItem(cartId, itemId, data) {
480
+ return this.request("PATCH", `/api/v1/cart/${cartId}/items/${itemId}`, data);
481
+ }
482
+ /**
483
+ * Remove an item from the cart
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * const cart = await omni.removeCartItem('cart_123', 'item_456');
488
+ * ```
489
+ */
490
+ async removeCartItem(cartId, itemId) {
491
+ return this.request("DELETE", `/api/v1/cart/${cartId}/items/${itemId}`);
492
+ }
493
+ /**
494
+ * Clear all items from the cart
495
+ *
496
+ * @example
497
+ * ```typescript
498
+ * await omni.clearCart('cart_123');
499
+ * ```
500
+ */
501
+ async clearCart(cartId) {
502
+ await this.request("DELETE", `/api/v1/cart/${cartId}/items`);
503
+ }
504
+ /**
505
+ * Apply a coupon to the cart
506
+ *
507
+ * @example
508
+ * ```typescript
509
+ * const cart = await omni.applyCoupon('cart_123', 'SAVE20');
510
+ * console.log('Discount:', cart.discountAmount);
511
+ * ```
512
+ */
513
+ async applyCoupon(cartId, code) {
514
+ return this.request("POST", `/api/v1/cart/${cartId}/coupon`, { code });
515
+ }
516
+ /**
517
+ * Remove a coupon from the cart
518
+ *
519
+ * @example
520
+ * ```typescript
521
+ * const cart = await omni.removeCoupon('cart_123');
522
+ * ```
523
+ */
524
+ async removeCoupon(cartId) {
525
+ return this.request("DELETE", `/api/v1/cart/${cartId}/coupon`);
526
+ }
527
+ /**
528
+ * Merge a guest cart into a customer's cart (after login)
529
+ * The guest cart items are moved to the customer's cart
530
+ *
531
+ * @example
532
+ * ```typescript
533
+ * // After customer logs in, merge their guest cart
534
+ * const mergedCart = await omni.mergeCarts({
535
+ * sourceSessionToken: 'sess_guest_abc',
536
+ * targetCustomerId: 'cust_123',
537
+ * });
538
+ * ```
539
+ */
540
+ async mergeCarts(data) {
541
+ return this.request("POST", "/api/v1/cart/merge", data);
542
+ }
543
+ // -------------------- Checkout --------------------
544
+ /**
545
+ * Create a checkout from a cart
546
+ * Starts the checkout process and returns checkout with available options
547
+ *
548
+ * @example
549
+ * ```typescript
550
+ * const checkout = await omni.createCheckout({ cartId: 'cart_123' });
551
+ * console.log('Checkout created:', checkout.id);
552
+ * ```
553
+ */
554
+ async createCheckout(data) {
555
+ return this.request("POST", "/api/v1/checkout", data);
556
+ }
557
+ /**
558
+ * Get a checkout by ID
559
+ *
560
+ * @example
561
+ * ```typescript
562
+ * const checkout = await omni.getCheckout('checkout_123');
563
+ * console.log('Status:', checkout.status);
564
+ * ```
565
+ */
566
+ async getCheckout(checkoutId) {
567
+ return this.request("GET", `/api/v1/checkout/${checkoutId}`);
568
+ }
569
+ /**
570
+ * Set customer information on checkout
571
+ *
572
+ * @example
573
+ * ```typescript
574
+ * const checkout = await omni.setCheckoutCustomer('checkout_123', {
575
+ * email: 'customer@example.com',
576
+ * firstName: 'John',
577
+ * lastName: 'Doe',
578
+ * });
579
+ * ```
580
+ */
581
+ async setCheckoutCustomer(checkoutId, data) {
582
+ return this.request("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
583
+ }
584
+ /**
585
+ * Set shipping address on checkout
586
+ * Returns the checkout and available shipping rates for the address
587
+ *
588
+ * @example
589
+ * ```typescript
590
+ * const { checkout, rates } = await omni.setShippingAddress('checkout_123', {
591
+ * firstName: 'John',
592
+ * lastName: 'Doe',
593
+ * line1: '123 Main St',
594
+ * city: 'New York',
595
+ * region: 'NY',
596
+ * postalCode: '10001',
597
+ * country: 'US',
598
+ * });
599
+ * console.log('Available rates:', rates);
600
+ * ```
601
+ */
602
+ async setShippingAddress(checkoutId, address) {
603
+ return this.request(
604
+ "PATCH",
605
+ `/api/v1/checkout/${checkoutId}/shipping-address`,
606
+ address
607
+ );
608
+ }
609
+ /**
610
+ * Get available shipping rates for a checkout
611
+ * Requires shipping address to be set first
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * const rates = await omni.getShippingRates('checkout_123');
616
+ * console.log('Shipping options:', rates);
617
+ * ```
618
+ */
619
+ async getShippingRates(checkoutId) {
620
+ return this.request("GET", `/api/v1/checkout/${checkoutId}/shipping-rates`);
621
+ }
622
+ /**
623
+ * Select a shipping method for checkout
624
+ *
625
+ * @example
626
+ * ```typescript
627
+ * const checkout = await omni.selectShippingMethod('checkout_123', 'rate_express');
628
+ * console.log('Shipping cost:', checkout.shippingAmount);
629
+ * ```
630
+ */
631
+ async selectShippingMethod(checkoutId, shippingRateId) {
632
+ return this.request("PATCH", `/api/v1/checkout/${checkoutId}/shipping-method`, {
633
+ shippingRateId
634
+ });
635
+ }
636
+ /**
637
+ * Set billing address on checkout
638
+ * Can optionally use shipping address as billing address
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * // Use same as shipping
643
+ * const checkout = await omni.setBillingAddress('checkout_123', {
644
+ * ...shippingAddress,
645
+ * sameAsShipping: true,
646
+ * });
647
+ *
648
+ * // Or set different billing address
649
+ * const checkout = await omni.setBillingAddress('checkout_123', {
650
+ * firstName: 'John',
651
+ * lastName: 'Doe',
652
+ * line1: '456 Business Ave',
653
+ * city: 'New York',
654
+ * region: 'NY',
655
+ * postalCode: '10002',
656
+ * country: 'US',
657
+ * });
658
+ * ```
659
+ */
660
+ async setBillingAddress(checkoutId, address) {
661
+ return this.request(
662
+ "PATCH",
663
+ `/api/v1/checkout/${checkoutId}/billing-address`,
664
+ address
665
+ );
666
+ }
667
+ /**
668
+ * Complete the checkout and create an order
669
+ * Requires customer email, shipping address, and shipping method to be set
670
+ *
671
+ * @example
672
+ * ```typescript
673
+ * const { orderId } = await omni.completeCheckout('checkout_123');
674
+ * console.log('Order created:', orderId);
675
+ * ```
676
+ */
677
+ async completeCheckout(checkoutId) {
678
+ return this.request(
679
+ "POST",
680
+ `/api/v1/checkout/${checkoutId}/complete`
681
+ );
682
+ }
683
+ };
684
+ var OmniSyncError = class extends Error {
685
+ constructor(message, statusCode, details) {
686
+ super(message);
687
+ this.name = "OmniSyncError";
688
+ this.statusCode = statusCode;
689
+ this.details = details;
690
+ }
691
+ };
692
+
693
+ // src/webhooks.ts
694
+ function verifyWebhook(payload, signature, secret) {
695
+ if (!signature || !secret) {
696
+ return false;
697
+ }
698
+ const payloadString = typeof payload === "string" ? payload : JSON.stringify(payload);
699
+ return verifyHmacSignature(payloadString, signature, secret);
700
+ }
701
+ function verifyHmacSignature(payload, signature, secret) {
702
+ try {
703
+ if (typeof globalThis.crypto === "undefined") {
704
+ const crypto2 = __require("crypto");
705
+ const expectedSignature2 = crypto2.createHmac("sha256", secret).update(payload).digest("hex");
706
+ return timingSafeEqual(signature, expectedSignature2);
707
+ }
708
+ const crypto = __require("crypto");
709
+ const expectedSignature = crypto.createHmac("sha256", secret).update(payload).digest("hex");
710
+ return timingSafeEqual(signature, expectedSignature);
711
+ } catch (error) {
712
+ console.error("Webhook signature verification failed:", error);
713
+ return false;
714
+ }
715
+ }
716
+ function timingSafeEqual(a, b) {
717
+ if (a.length !== b.length) {
718
+ return false;
719
+ }
720
+ let result = 0;
721
+ for (let i = 0; i < a.length; i++) {
722
+ result |= a.charCodeAt(i) ^ b.charCodeAt(i);
723
+ }
724
+ return result === 0;
725
+ }
726
+ function parseWebhookEvent(payload) {
727
+ if (typeof payload !== "object" || payload === null) {
728
+ throw new Error("Invalid webhook payload: expected object");
729
+ }
730
+ const event = payload;
731
+ if (typeof event.event !== "string") {
732
+ throw new Error("Invalid webhook payload: missing or invalid event type");
733
+ }
734
+ if (typeof event.storeId !== "string") {
735
+ throw new Error("Invalid webhook payload: missing storeId");
736
+ }
737
+ if (typeof event.entityId !== "string") {
738
+ throw new Error("Invalid webhook payload: missing entityId");
739
+ }
740
+ return {
741
+ event: event.event,
742
+ storeId: event.storeId,
743
+ entityId: event.entityId,
744
+ platform: event.platform || "CUSTOM",
745
+ data: event.data,
746
+ timestamp: event.timestamp || (/* @__PURE__ */ new Date()).toISOString()
747
+ };
748
+ }
749
+ function isWebhookEventType(event, type) {
750
+ return event.event === type;
751
+ }
752
+ function createWebhookHandler(handlers) {
753
+ return async (payload) => {
754
+ const event = parseWebhookEvent(payload);
755
+ const handler = handlers[event.event];
756
+ if (handler) {
757
+ await handler(event);
758
+ }
759
+ };
760
+ }
761
+
762
+ // src/types.ts
763
+ function isCouponApplicableToProduct(coupon, productId, productCategoryIds) {
764
+ if (coupon.excludedProducts?.includes(productId)) {
765
+ return false;
766
+ }
767
+ if (coupon.excludedCategories?.some((cat) => productCategoryIds.includes(cat))) {
768
+ return false;
769
+ }
770
+ if (coupon.applicableProducts && coupon.applicableProducts.length > 0) {
771
+ if (!coupon.applicableProducts.includes(productId)) {
772
+ return false;
773
+ }
774
+ }
775
+ if (coupon.applicableCategories && coupon.applicableCategories.length > 0) {
776
+ if (!coupon.applicableCategories.some((cat) => productCategoryIds.includes(cat))) {
777
+ return false;
778
+ }
779
+ }
780
+ return true;
781
+ }
782
+ export {
783
+ OmniSyncClient,
784
+ OmniSyncError,
785
+ createWebhookHandler,
786
+ isCouponApplicableToProduct,
787
+ isWebhookEventType,
788
+ parseWebhookEvent,
789
+ verifyWebhook
790
+ };