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