omni-sync-sdk 0.8.0 → 0.8.2
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 +340 -8
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,8 +30,37 @@ const omni = new OmniSyncClient({
|
|
|
30
30
|
|
|
31
31
|
// Fetch products
|
|
32
32
|
const { data: products } = await omni.getProducts();
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Checkout: Guest vs Logged-In Customer
|
|
38
|
+
|
|
39
|
+
> **IMPORTANT:** There are TWO different checkout flows. You MUST use the correct one based on whether the customer is logged in or not.
|
|
33
40
|
|
|
34
|
-
|
|
41
|
+
| Customer Type | Cart Type | Checkout Method | Orders Linked to Account? |
|
|
42
|
+
|---------------|-----------|-----------------|---------------------------|
|
|
43
|
+
| **Guest** | Local Cart (localStorage) | `submitGuestOrder()` | No |
|
|
44
|
+
| **Logged In** | Server Cart | `completeCheckout()` | Yes |
|
|
45
|
+
|
|
46
|
+
### Decision Flow
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
// ALWAYS check this at checkout!
|
|
50
|
+
if (isLoggedIn()) {
|
|
51
|
+
// ✅ Logged-in customer → Server Cart + Checkout flow
|
|
52
|
+
// Orders will be linked to their account
|
|
53
|
+
const order = await completeServerCheckout();
|
|
54
|
+
} else {
|
|
55
|
+
// ✅ Guest → Local Cart + submitGuestOrder
|
|
56
|
+
// Orders are standalone (not linked to any account)
|
|
57
|
+
const order = await omni.submitGuestOrder();
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Guest Checkout (for visitors without account)
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
35
64
|
// Cart stored locally - NO API calls until checkout!
|
|
36
65
|
|
|
37
66
|
// Add to local cart (stored in localStorage)
|
|
@@ -58,11 +87,60 @@ const order = await omni.submitGuestOrder();
|
|
|
58
87
|
console.log('Order created:', order.orderId);
|
|
59
88
|
```
|
|
60
89
|
|
|
90
|
+
### Logged-In Customer Checkout (orders linked to account)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// 1. Make sure customer token is set (after login)
|
|
94
|
+
omni.setCustomerToken(authResponse.token);
|
|
95
|
+
|
|
96
|
+
// 2. Create server cart (auto-linked to customer!)
|
|
97
|
+
const cart = await omni.createCart();
|
|
98
|
+
localStorage.setItem('cartId', cart.id);
|
|
99
|
+
|
|
100
|
+
// 3. Add items to server cart
|
|
101
|
+
await omni.addToCart(cart.id, {
|
|
102
|
+
productId: products[0].id,
|
|
103
|
+
quantity: 1,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// 4. Create checkout from cart
|
|
107
|
+
const checkout = await omni.createCheckout({ cartId: cart.id });
|
|
108
|
+
|
|
109
|
+
// 5. Set customer info (REQUIRED - email is needed for order!)
|
|
110
|
+
await omni.setCheckoutCustomer(checkout.id, {
|
|
111
|
+
email: 'customer@example.com',
|
|
112
|
+
firstName: 'John',
|
|
113
|
+
lastName: 'Doe',
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// 6. Set shipping address
|
|
117
|
+
await omni.setShippingAddress(checkout.id, {
|
|
118
|
+
firstName: 'John',
|
|
119
|
+
lastName: 'Doe',
|
|
120
|
+
line1: '123 Main St',
|
|
121
|
+
city: 'New York',
|
|
122
|
+
postalCode: '10001',
|
|
123
|
+
country: 'US',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// 7. Get shipping rates and select one
|
|
127
|
+
const rates = await omni.getShippingRates(checkout.id);
|
|
128
|
+
await omni.selectShippingMethod(checkout.id, rates[0].id);
|
|
129
|
+
|
|
130
|
+
// 8. Complete checkout - order is linked to customer!
|
|
131
|
+
const { orderId } = await omni.completeCheckout(checkout.id);
|
|
132
|
+
console.log('Order created:', orderId);
|
|
133
|
+
|
|
134
|
+
// Customer can now see this order in omni.getMyOrders()
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
> **WARNING:** Do NOT use `submitGuestOrder()` for logged-in customers! Their orders won't be linked to their account and won't appear in their order history.
|
|
138
|
+
|
|
61
139
|
---
|
|
62
140
|
|
|
63
141
|
## Two Ways to Handle Cart
|
|
64
142
|
|
|
65
|
-
### Option 1: Local Cart (Guest Users)
|
|
143
|
+
### Option 1: Local Cart (Guest Users)
|
|
66
144
|
|
|
67
145
|
For guest users, the cart is stored in **localStorage** - exactly like Amazon, Shopify, and other major platforms do. This means:
|
|
68
146
|
|
|
@@ -89,19 +167,34 @@ omni.removeFromLocalCart('prod_123');
|
|
|
89
167
|
const order = await omni.submitGuestOrder();
|
|
90
168
|
```
|
|
91
169
|
|
|
92
|
-
### Option 2: Server Cart (
|
|
170
|
+
### Option 2: Server Cart (Logged-In Customers)
|
|
93
171
|
|
|
94
|
-
For logged-in customers, use server-side cart:
|
|
172
|
+
For logged-in customers, **you MUST use server-side cart** to link orders to their account:
|
|
95
173
|
|
|
96
174
|
- ✅ Cart syncs across devices
|
|
97
175
|
- ✅ Abandoned cart recovery
|
|
98
|
-
- ✅
|
|
176
|
+
- ✅ Orders linked to customer account
|
|
177
|
+
- ✅ Customer can see orders in "My Orders"
|
|
99
178
|
|
|
100
179
|
```typescript
|
|
180
|
+
// 1. Set customer token (after login)
|
|
181
|
+
omni.setCustomerToken(token);
|
|
182
|
+
|
|
183
|
+
// 2. Create cart (auto-linked to customer)
|
|
101
184
|
const cart = await omni.createCart();
|
|
185
|
+
localStorage.setItem('cartId', cart.id);
|
|
186
|
+
|
|
187
|
+
// 3. Add items
|
|
102
188
|
await omni.addToCart(cart.id, { productId: 'prod_123', quantity: 2 });
|
|
189
|
+
|
|
190
|
+
// 4. At checkout - create checkout and complete
|
|
191
|
+
const checkout = await omni.createCheckout({ cartId: cart.id });
|
|
192
|
+
// ... set shipping address, select shipping method ...
|
|
193
|
+
const { orderId } = await omni.completeCheckout(checkout.id);
|
|
103
194
|
```
|
|
104
195
|
|
|
196
|
+
> **⚠️ CRITICAL:** If you use `submitGuestOrder()` for a logged-in customer, their order will NOT be linked to their account!
|
|
197
|
+
|
|
105
198
|
---
|
|
106
199
|
|
|
107
200
|
## Complete Store Setup
|
|
@@ -322,6 +415,62 @@ interface InventoryInfo {
|
|
|
322
415
|
}
|
|
323
416
|
```
|
|
324
417
|
|
|
418
|
+
#### Displaying Price Range for Variable Products
|
|
419
|
+
|
|
420
|
+
For products with `type: 'VARIABLE'` and multiple variants with different prices, display a **price range** instead of a single price:
|
|
421
|
+
|
|
422
|
+
```typescript
|
|
423
|
+
// Helper function to get price range from variants
|
|
424
|
+
function getPriceRange(product: Product): { min: number; max: number } | null {
|
|
425
|
+
if (product.type !== 'VARIABLE' || !product.variants?.length) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const prices = product.variants
|
|
430
|
+
.map(v => v.price ?? product.basePrice)
|
|
431
|
+
.filter((p): p is number => p !== null);
|
|
432
|
+
|
|
433
|
+
if (prices.length === 0) return null;
|
|
434
|
+
|
|
435
|
+
const min = Math.min(...prices);
|
|
436
|
+
const max = Math.max(...prices);
|
|
437
|
+
|
|
438
|
+
// Return null if all variants have the same price
|
|
439
|
+
return min !== max ? { min, max } : null;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Usage in component
|
|
443
|
+
function ProductPrice({ product }: { product: Product }) {
|
|
444
|
+
const priceRange = getPriceRange(product);
|
|
445
|
+
|
|
446
|
+
if (priceRange) {
|
|
447
|
+
// Variable product with different variant prices - show range
|
|
448
|
+
return <span>${priceRange.min} - ${priceRange.max}</span>;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Simple product or all variants same price - show single price
|
|
452
|
+
return product.salePrice ? (
|
|
453
|
+
<>
|
|
454
|
+
<span className="text-red-600">${product.salePrice}</span>
|
|
455
|
+
<span className="line-through text-gray-400 ml-2">${product.basePrice}</span>
|
|
456
|
+
</>
|
|
457
|
+
) : (
|
|
458
|
+
<span>${product.basePrice}</span>
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
**When to show price range:**
|
|
464
|
+
|
|
465
|
+
- Product `type` is `'VARIABLE'`
|
|
466
|
+
- Has 2+ variants with **different** prices
|
|
467
|
+
- Example: T-shirt sizes S/M/L at $29, XL/XXL at $34 → Display "$29 - $34"
|
|
468
|
+
|
|
469
|
+
**When to show single price:**
|
|
470
|
+
|
|
471
|
+
- Product `type` is `'SIMPLE'`
|
|
472
|
+
- Variable product where all variants have the same price
|
|
473
|
+
|
|
325
474
|
#### Rendering Product Descriptions
|
|
326
475
|
|
|
327
476
|
**IMPORTANT**: Product descriptions may contain HTML (from Shopify/WooCommerce) or plain text. Always check `descriptionFormat` before rendering:
|
|
@@ -1789,9 +1938,190 @@ export default function CartPage() {
|
|
|
1789
1938
|
}
|
|
1790
1939
|
```
|
|
1791
1940
|
|
|
1941
|
+
### Universal Checkout (Handles Both Guest & Logged-In)
|
|
1942
|
+
|
|
1943
|
+
> **RECOMMENDED:** Use this pattern to properly handle both guest and logged-in customers in a single checkout page.
|
|
1944
|
+
|
|
1945
|
+
```typescript
|
|
1946
|
+
'use client';
|
|
1947
|
+
import { useState, useEffect } from 'react';
|
|
1948
|
+
import { omni, isLoggedIn, getServerCartId, setServerCartId, restoreCustomerToken } from '@/lib/omni-sync';
|
|
1949
|
+
|
|
1950
|
+
export default function CheckoutPage() {
|
|
1951
|
+
const [loading, setLoading] = useState(true);
|
|
1952
|
+
const [submitting, setSubmitting] = useState(false);
|
|
1953
|
+
const [customerLoggedIn, setCustomerLoggedIn] = useState(false);
|
|
1954
|
+
|
|
1955
|
+
// Form state
|
|
1956
|
+
const [email, setEmail] = useState('');
|
|
1957
|
+
const [shippingAddress, setShippingAddress] = useState({
|
|
1958
|
+
firstName: '', lastName: '', line1: '', city: '', postalCode: '', country: 'US'
|
|
1959
|
+
});
|
|
1960
|
+
|
|
1961
|
+
// Server checkout state (for logged-in customers)
|
|
1962
|
+
const [checkoutId, setCheckoutId] = useState<string | null>(null);
|
|
1963
|
+
const [shippingRates, setShippingRates] = useState<any[]>([]);
|
|
1964
|
+
const [selectedRate, setSelectedRate] = useState<string | null>(null);
|
|
1965
|
+
|
|
1966
|
+
useEffect(() => {
|
|
1967
|
+
restoreCustomerToken();
|
|
1968
|
+
const loggedIn = isLoggedIn();
|
|
1969
|
+
setCustomerLoggedIn(loggedIn);
|
|
1970
|
+
|
|
1971
|
+
async function initCheckout() {
|
|
1972
|
+
if (loggedIn) {
|
|
1973
|
+
// Logged-in customer: Create server cart + checkout
|
|
1974
|
+
let cartId = getServerCartId();
|
|
1975
|
+
|
|
1976
|
+
if (!cartId) {
|
|
1977
|
+
// Create new cart (auto-linked to customer)
|
|
1978
|
+
const cart = await omni.createCart();
|
|
1979
|
+
cartId = cart.id;
|
|
1980
|
+
setServerCartId(cartId);
|
|
1981
|
+
|
|
1982
|
+
// Migrate local cart items to server cart
|
|
1983
|
+
const localCart = omni.getLocalCart();
|
|
1984
|
+
for (const item of localCart.items) {
|
|
1985
|
+
await omni.addToCart(cartId, {
|
|
1986
|
+
productId: item.productId,
|
|
1987
|
+
variantId: item.variantId,
|
|
1988
|
+
quantity: item.quantity,
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
omni.clearLocalCart(); // Clear local cart after migration
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
// Create checkout from server cart
|
|
1995
|
+
const checkout = await omni.createCheckout({ cartId });
|
|
1996
|
+
setCheckoutId(checkout.id);
|
|
1997
|
+
|
|
1998
|
+
// Pre-fill from customer profile if available
|
|
1999
|
+
try {
|
|
2000
|
+
const profile = await omni.getMyOrders({ limit: 1 }); // Just to check auth works
|
|
2001
|
+
} catch (e) {
|
|
2002
|
+
console.log('Could not fetch profile');
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
setLoading(false);
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
initCheckout();
|
|
2009
|
+
}, []);
|
|
2010
|
+
|
|
2011
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
2012
|
+
e.preventDefault();
|
|
2013
|
+
setSubmitting(true);
|
|
2014
|
+
|
|
2015
|
+
try {
|
|
2016
|
+
if (customerLoggedIn && checkoutId) {
|
|
2017
|
+
// ===== LOGGED-IN CUSTOMER: Server Checkout =====
|
|
2018
|
+
|
|
2019
|
+
// 1. Set customer info (REQUIRED - even for logged-in customers!)
|
|
2020
|
+
await omni.setCheckoutCustomer(checkoutId, {
|
|
2021
|
+
email: email, // Get from form or customer profile
|
|
2022
|
+
firstName: shippingAddress.firstName,
|
|
2023
|
+
lastName: shippingAddress.lastName,
|
|
2024
|
+
});
|
|
2025
|
+
|
|
2026
|
+
// 2. Set shipping address
|
|
2027
|
+
await omni.setShippingAddress(checkoutId, shippingAddress);
|
|
2028
|
+
|
|
2029
|
+
// 3. Get and select shipping rate
|
|
2030
|
+
const rates = await omni.getShippingRates(checkoutId);
|
|
2031
|
+
if (rates.length > 0) {
|
|
2032
|
+
await omni.selectShippingMethod(checkoutId, selectedRate || rates[0].id);
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
// 4. Complete checkout - ORDER IS LINKED TO CUSTOMER!
|
|
2036
|
+
const { orderId } = await omni.completeCheckout(checkoutId);
|
|
2037
|
+
|
|
2038
|
+
// Clear cart ID
|
|
2039
|
+
localStorage.removeItem('cartId');
|
|
2040
|
+
|
|
2041
|
+
// Redirect to success page
|
|
2042
|
+
window.location.href = `/order-success?orderId=${orderId}`;
|
|
2043
|
+
|
|
2044
|
+
} else {
|
|
2045
|
+
// ===== GUEST: Local Cart + submitGuestOrder =====
|
|
2046
|
+
|
|
2047
|
+
// Set customer and shipping info on local cart
|
|
2048
|
+
omni.setLocalCartCustomer({ email });
|
|
2049
|
+
omni.setLocalCartShippingAddress(shippingAddress);
|
|
2050
|
+
|
|
2051
|
+
// Submit guest order (single API call)
|
|
2052
|
+
const order = await omni.submitGuestOrder();
|
|
2053
|
+
|
|
2054
|
+
// Redirect to success page
|
|
2055
|
+
window.location.href = `/order-success?orderId=${order.orderId}`;
|
|
2056
|
+
}
|
|
2057
|
+
} catch (error) {
|
|
2058
|
+
console.error('Checkout failed:', error);
|
|
2059
|
+
alert('Checkout failed. Please try again.');
|
|
2060
|
+
} finally {
|
|
2061
|
+
setSubmitting(false);
|
|
2062
|
+
}
|
|
2063
|
+
};
|
|
2064
|
+
|
|
2065
|
+
if (loading) return <div>Loading checkout...</div>;
|
|
2066
|
+
|
|
2067
|
+
return (
|
|
2068
|
+
<form onSubmit={handleSubmit}>
|
|
2069
|
+
{/* Show email field only for guests */}
|
|
2070
|
+
{!customerLoggedIn && (
|
|
2071
|
+
<input
|
|
2072
|
+
type="email"
|
|
2073
|
+
value={email}
|
|
2074
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
2075
|
+
placeholder="Email"
|
|
2076
|
+
required
|
|
2077
|
+
/>
|
|
2078
|
+
)}
|
|
2079
|
+
|
|
2080
|
+
{/* Shipping address fields */}
|
|
2081
|
+
<input value={shippingAddress.firstName} onChange={(e) => setShippingAddress({...shippingAddress, firstName: e.target.value})} placeholder="First Name" required />
|
|
2082
|
+
<input value={shippingAddress.lastName} onChange={(e) => setShippingAddress({...shippingAddress, lastName: e.target.value})} placeholder="Last Name" required />
|
|
2083
|
+
<input value={shippingAddress.line1} onChange={(e) => setShippingAddress({...shippingAddress, line1: e.target.value})} placeholder="Address" required />
|
|
2084
|
+
<input value={shippingAddress.city} onChange={(e) => setShippingAddress({...shippingAddress, city: e.target.value})} placeholder="City" required />
|
|
2085
|
+
<input value={shippingAddress.postalCode} onChange={(e) => setShippingAddress({...shippingAddress, postalCode: e.target.value})} placeholder="Postal Code" required />
|
|
2086
|
+
|
|
2087
|
+
{/* Shipping rates (for logged-in customers) */}
|
|
2088
|
+
{customerLoggedIn && shippingRates.length > 0 && (
|
|
2089
|
+
<select value={selectedRate || ''} onChange={(e) => setSelectedRate(e.target.value)}>
|
|
2090
|
+
{shippingRates.map((rate) => (
|
|
2091
|
+
<option key={rate.id} value={rate.id}>
|
|
2092
|
+
{rate.name} - ${rate.price}
|
|
2093
|
+
</option>
|
|
2094
|
+
))}
|
|
2095
|
+
</select>
|
|
2096
|
+
)}
|
|
2097
|
+
|
|
2098
|
+
<button type="submit" disabled={submitting}>
|
|
2099
|
+
{submitting ? 'Processing...' : 'Place Order'}
|
|
2100
|
+
</button>
|
|
2101
|
+
|
|
2102
|
+
{customerLoggedIn && (
|
|
2103
|
+
<p className="text-sm text-green-600">
|
|
2104
|
+
✓ Logged in - Order will be saved to your account
|
|
2105
|
+
</p>
|
|
2106
|
+
)}
|
|
2107
|
+
</form>
|
|
2108
|
+
);
|
|
2109
|
+
}
|
|
2110
|
+
```
|
|
2111
|
+
|
|
2112
|
+
> **Key Points:**
|
|
2113
|
+
> - `isLoggedIn()` determines which flow to use
|
|
2114
|
+
> - Logged-in customers use `createCart()` → `createCheckout()` → `completeCheckout()`
|
|
2115
|
+
> - Guests use local cart + `submitGuestOrder()`
|
|
2116
|
+
> - Local cart items are migrated to server cart when customer logs in
|
|
2117
|
+
|
|
2118
|
+
---
|
|
2119
|
+
|
|
1792
2120
|
### Guest Checkout (Single API Call)
|
|
1793
2121
|
|
|
1794
|
-
This is
|
|
2122
|
+
This checkout is for **guest users only**. All cart data is in localStorage, and we submit it in one API call.
|
|
2123
|
+
|
|
2124
|
+
> **⚠️ WARNING:** Do NOT use this for logged-in customers! Use the Universal Checkout pattern above instead.
|
|
1795
2125
|
|
|
1796
2126
|
```typescript
|
|
1797
2127
|
'use client';
|
|
@@ -1957,9 +2287,11 @@ export default function CheckoutPage() {
|
|
|
1957
2287
|
}
|
|
1958
2288
|
```
|
|
1959
2289
|
|
|
1960
|
-
### Multi-Step Checkout (Server Cart - For
|
|
2290
|
+
### Multi-Step Checkout (Server Cart - For Logged-In Customers Only)
|
|
2291
|
+
|
|
2292
|
+
> **IMPORTANT:** This checkout pattern is ONLY for logged-in customers. For a checkout page that handles both guests and logged-in customers, see the "Universal Checkout" example above.
|
|
1961
2293
|
|
|
1962
|
-
For logged-in users with server-side cart:
|
|
2294
|
+
For logged-in users with server-side cart - orders will be linked to their account:
|
|
1963
2295
|
|
|
1964
2296
|
```typescript
|
|
1965
2297
|
'use client';
|
package/dist/index.d.mts
CHANGED
|
@@ -76,6 +76,7 @@ interface Product {
|
|
|
76
76
|
costPrice?: number | null;
|
|
77
77
|
status: 'active' | 'draft' | 'archived';
|
|
78
78
|
type: 'SIMPLE' | 'VARIABLE';
|
|
79
|
+
isDownloadable?: boolean;
|
|
79
80
|
images?: ProductImage[];
|
|
80
81
|
inventory?: InventoryInfo | null;
|
|
81
82
|
variants?: ProductVariant[];
|
|
@@ -110,6 +111,7 @@ interface ProductQueryParams {
|
|
|
110
111
|
search?: string;
|
|
111
112
|
status?: 'active' | 'draft' | 'archived';
|
|
112
113
|
type?: 'SIMPLE' | 'VARIABLE';
|
|
114
|
+
isDownloadable?: boolean;
|
|
113
115
|
sortBy?: 'name' | 'createdAt' | 'updatedAt' | 'basePrice';
|
|
114
116
|
sortOrder?: 'asc' | 'desc';
|
|
115
117
|
}
|
|
@@ -157,6 +159,7 @@ interface CreateProductDto {
|
|
|
157
159
|
costPrice?: number;
|
|
158
160
|
status?: 'active' | 'draft';
|
|
159
161
|
type?: 'SIMPLE' | 'VARIABLE';
|
|
162
|
+
isDownloadable?: boolean;
|
|
160
163
|
categories?: string[];
|
|
161
164
|
tags?: string[];
|
|
162
165
|
images?: ProductImage[];
|
|
@@ -169,6 +172,7 @@ interface UpdateProductDto {
|
|
|
169
172
|
salePrice?: number | null;
|
|
170
173
|
costPrice?: number | null;
|
|
171
174
|
status?: 'active' | 'draft' | 'archived';
|
|
175
|
+
isDownloadable?: boolean;
|
|
172
176
|
categories?: string[];
|
|
173
177
|
tags?: string[];
|
|
174
178
|
images?: ProductImage[];
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,7 @@ interface Product {
|
|
|
76
76
|
costPrice?: number | null;
|
|
77
77
|
status: 'active' | 'draft' | 'archived';
|
|
78
78
|
type: 'SIMPLE' | 'VARIABLE';
|
|
79
|
+
isDownloadable?: boolean;
|
|
79
80
|
images?: ProductImage[];
|
|
80
81
|
inventory?: InventoryInfo | null;
|
|
81
82
|
variants?: ProductVariant[];
|
|
@@ -110,6 +111,7 @@ interface ProductQueryParams {
|
|
|
110
111
|
search?: string;
|
|
111
112
|
status?: 'active' | 'draft' | 'archived';
|
|
112
113
|
type?: 'SIMPLE' | 'VARIABLE';
|
|
114
|
+
isDownloadable?: boolean;
|
|
113
115
|
sortBy?: 'name' | 'createdAt' | 'updatedAt' | 'basePrice';
|
|
114
116
|
sortOrder?: 'asc' | 'desc';
|
|
115
117
|
}
|
|
@@ -157,6 +159,7 @@ interface CreateProductDto {
|
|
|
157
159
|
costPrice?: number;
|
|
158
160
|
status?: 'active' | 'draft';
|
|
159
161
|
type?: 'SIMPLE' | 'VARIABLE';
|
|
162
|
+
isDownloadable?: boolean;
|
|
160
163
|
categories?: string[];
|
|
161
164
|
tags?: string[];
|
|
162
165
|
images?: ProductImage[];
|
|
@@ -169,6 +172,7 @@ interface UpdateProductDto {
|
|
|
169
172
|
salePrice?: number | null;
|
|
170
173
|
costPrice?: number | null;
|
|
171
174
|
status?: 'active' | 'draft' | 'archived';
|
|
175
|
+
isDownloadable?: boolean;
|
|
172
176
|
categories?: string[];
|
|
173
177
|
tags?: string[];
|
|
174
178
|
images?: ProductImage[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omni-sync-sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Official SDK for building e-commerce storefronts with OmniSync Platform. Perfect for vibe-coded sites, AI-built stores (Cursor, Lovable, v0), and custom storefronts.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|