omni-sync-sdk 0.14.2 → 0.15.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 CHANGED
@@ -479,7 +479,7 @@ function SearchInput() {
479
479
  {suggestions && (
480
480
  <div className="suggestions">
481
481
  {suggestions.products.map((product) => (
482
- <a key={product.id} href={`/products/${product.id}`}>
482
+ <a key={product.id} href={`/products/${product.slug}`}>
483
483
  <img src={product.image || '/placeholder.png'} alt={product.name} />
484
484
  <span>{product.name}</span>
485
485
  <span>${product.basePrice}</span>
@@ -2128,7 +2128,7 @@ export default function HomePage() {
2128
2128
  return (
2129
2129
  <div className="grid grid-cols-2 md:grid-cols-4 gap-6">
2130
2130
  {products.map((product) => (
2131
- <a key={product.id} href={`/products/${product.id}`} className="group">
2131
+ <a key={product.id} href={`/products/${product.slug}`} className="group">
2132
2132
  <img
2133
2133
  src={product.images?.[0]?.url || '/placeholder.jpg'}
2134
2134
  alt={product.name}
@@ -2185,7 +2185,7 @@ export default function ProductsPage() {
2185
2185
  <div>
2186
2186
  <div className="grid grid-cols-3 gap-6">
2187
2187
  {data.data.map((product) => (
2188
- <a key={product.id} href={`/products/${product.id}`}>
2188
+ <a key={product.id} href={`/products/${product.slug}`}>
2189
2189
  <img src={product.images?.[0]?.url} alt={product.name} />
2190
2190
  <h3>{product.name}</h3>
2191
2191
  <p>${product.salePrice || product.basePrice}</p>
@@ -2217,7 +2217,8 @@ import { omni } from '@/lib/omni-sync';
2217
2217
  import { isHtmlDescription } from 'omni-sync-sdk';
2218
2218
  import type { Product } from 'omni-sync-sdk';
2219
2219
 
2220
- export default function ProductPage({ params }: { params: { id: string } }) {
2220
+ // Route: /products/[slug]/page.tsx - uses URL-friendly slug instead of ID
2221
+ export default function ProductPage({ params }: { params: { slug: string } }) {
2221
2222
  const [product, setProduct] = useState<Product | null>(null);
2222
2223
  const [selectedVariant, setSelectedVariant] = useState<string | null>(null);
2223
2224
  const [quantity, setQuantity] = useState(1);
@@ -2226,7 +2227,8 @@ export default function ProductPage({ params }: { params: { id: string } }) {
2226
2227
  useEffect(() => {
2227
2228
  async function load() {
2228
2229
  try {
2229
- const p = await omni.getProduct(params.id);
2230
+ // Use getProductBySlug for SEO-friendly URLs
2231
+ const p = await omni.getProductBySlug(params.slug);
2230
2232
  setProduct(p);
2231
2233
  if (p.variants && p.variants.length > 0) {
2232
2234
  setSelectedVariant(p.variants[0].id);
@@ -2236,7 +2238,7 @@ export default function ProductPage({ params }: { params: { id: string } }) {
2236
2238
  }
2237
2239
  }
2238
2240
  load();
2239
- }, [params.id]);
2241
+ }, [params.slug]);
2240
2242
 
2241
2243
  const handleAddToCart = () => {
2242
2244
  if (!product) return;
@@ -3336,7 +3338,7 @@ When building a store, implement these pages:
3336
3338
 
3337
3339
  - [ ] **Home** (`/`) - Product grid
3338
3340
  - [ ] **Products** (`/products`) - Product list with pagination
3339
- - [ ] **Product Detail** (`/products/[id]`) - Single product with Add to Cart
3341
+ - [ ] **Product Detail** (`/products/[slug]`) - Single product with Add to Cart (use `getProductBySlug(slug)`)
3340
3342
  - [ ] **Cart** (`/cart`) - Cart items, update quantity, remove
3341
3343
  - [ ] **Checkout** (`/checkout`) - Multi-step checkout flow
3342
3344
  - [ ] **⚠️ Payment** (`/checkout/payment`) - **REQUIRED!** Use `getPaymentProviders()` to show Stripe/PayPal forms
package/dist/index.d.mts CHANGED
@@ -349,6 +349,7 @@ interface ProductQueryParams {
349
349
  interface ProductSuggestion {
350
350
  id: string;
351
351
  name: string;
352
+ slug: string | null;
352
353
  image: string | null;
353
354
  basePrice: number;
354
355
  salePrice?: number | null;
@@ -914,6 +915,12 @@ interface Cart {
914
915
  createdAt: string;
915
916
  /** ISO timestamp when cart was last updated */
916
917
  updatedAt: string;
918
+ /**
919
+ * Reservation information (only present when reservation strategy is ON_CART).
920
+ * Use this to display countdown timer to customers.
921
+ * @see ReservationInfo
922
+ */
923
+ reservation?: ReservationInfo;
917
924
  }
918
925
  interface AddToCartDto {
919
926
  productId: string;
@@ -1256,12 +1263,13 @@ interface ShippingRate {
1256
1263
  /**
1257
1264
  * Represents a checkout session for completing a purchase.
1258
1265
  *
1259
- * **Checkout Flow:**
1260
- * 1. Create checkout from cart: `createCheckout({ cartId })`
1261
- * 2. Set customer info: `setCheckoutCustomer(id, { email, ... })`
1262
- * 3. Set shipping address: `setShippingAddress(id, address)` - returns available rates
1263
- * 4. Select shipping method: `selectShippingMethod(id, rateId)`
1264
- * 5. Complete checkout: `completeCheckout(id)` - creates the order
1266
+ * **Simplified Checkout Flow (3 steps):**
1267
+ * 1. Set shipping address (includes email): `setShippingAddress(id, { email, ...address })` - returns rates
1268
+ * 2. Select shipping method: `selectShippingMethod(id, rateId)`
1269
+ * 3. Pay with Stripe: `createPaymentIntent(id)` → `stripe.confirmPayment()` Order created automatically!
1270
+ *
1271
+ * **Note:** Order is created automatically via webhook when payment succeeds.
1272
+ * No need to call `completeCheckout()` - it happens automatically.
1265
1273
  *
1266
1274
  * **IMPORTANT: Price fields are strings**
1267
1275
  * All monetary fields (subtotal, discountAmount, shippingAmount, taxAmount, total)
@@ -1342,6 +1350,12 @@ interface Checkout {
1342
1350
  createdAt: string;
1343
1351
  /** Last update timestamp */
1344
1352
  updatedAt: string;
1353
+ /**
1354
+ * Reservation information (present when reservation strategy is ON_CHECKOUT or ON_CART).
1355
+ * Use this to display countdown timer to customers.
1356
+ * @see ReservationInfo
1357
+ */
1358
+ reservation?: ReservationInfo;
1345
1359
  }
1346
1360
  interface CreateCheckoutDto {
1347
1361
  cartId: string;
@@ -1354,7 +1368,13 @@ interface SetCheckoutCustomerDto {
1354
1368
  phone?: string;
1355
1369
  acceptsMarketing?: boolean;
1356
1370
  }
1371
+ /**
1372
+ * Shipping address with customer email (required for checkout).
1373
+ * Email is included here to simplify the checkout flow - no need for separate setCheckoutCustomer call.
1374
+ */
1357
1375
  interface SetShippingAddressDto {
1376
+ /** Customer email (required) - used for order confirmation */
1377
+ email: string;
1358
1378
  firstName: string;
1359
1379
  lastName: string;
1360
1380
  company?: string;
@@ -1365,8 +1385,23 @@ interface SetShippingAddressDto {
1365
1385
  postalCode: string;
1366
1386
  country: string;
1367
1387
  phone?: string;
1388
+ /** Whether customer accepts marketing emails */
1389
+ acceptsMarketing?: boolean;
1368
1390
  }
1369
- interface SetBillingAddressDto extends SetShippingAddressDto {
1391
+ /**
1392
+ * Billing address (email not required - already set in shipping address)
1393
+ */
1394
+ interface SetBillingAddressDto {
1395
+ firstName: string;
1396
+ lastName: string;
1397
+ company?: string;
1398
+ line1: string;
1399
+ line2?: string;
1400
+ city: string;
1401
+ region?: string;
1402
+ postalCode: string;
1403
+ country: string;
1404
+ phone?: string;
1370
1405
  sameAsShipping?: boolean;
1371
1406
  }
1372
1407
  interface SelectShippingMethodDto {
@@ -1667,6 +1702,8 @@ interface PaymentProviderConfig {
1667
1702
  name: string;
1668
1703
  /** Public/publishable key (safe to expose) */
1669
1704
  publicKey: string;
1705
+ /** Stripe Connect account ID (for OAuth-connected accounts) */
1706
+ stripeAccountId?: string;
1670
1707
  /** Supported payment methods: ['card', 'ideal', 'bancontact'] */
1671
1708
  supportedMethods: string[];
1672
1709
  /** Whether this is test/sandbox mode */
@@ -1692,7 +1729,10 @@ interface PaymentProviderConfig {
1692
1729
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
1693
1730
  *
1694
1731
  * if (stripeProvider) {
1695
- * // Initialize Stripe.js with stripeProvider.publicKey
1732
+ * // Initialize Stripe.js with options for Connect
1733
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
1734
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
1735
+ * });
1696
1736
  * }
1697
1737
  * if (paypalProvider) {
1698
1738
  * // Initialize PayPal SDK with paypalProvider.publicKey as clientId
@@ -1756,6 +1796,83 @@ interface PaymentStatus {
1756
1796
  /** Payment intent ID from provider */
1757
1797
  paymentIntentId?: string;
1758
1798
  }
1799
+ /**
1800
+ * When inventory is reserved for customers.
1801
+ * Configured per vibe-coded connection by the store owner.
1802
+ *
1803
+ * - ON_PAYMENT: Stock is only reserved when payment is completed (default, safest)
1804
+ * - ON_CHECKOUT: Stock is reserved when checkout is created
1805
+ * - ON_CART: Stock is reserved immediately when added to cart (most aggressive)
1806
+ */
1807
+ type InventoryReservationStrategy = 'ON_PAYMENT' | 'ON_CHECKOUT' | 'ON_CART';
1808
+ /**
1809
+ * Information about a customer's inventory reservation.
1810
+ * Included in cart/checkout responses when reservations are active.
1811
+ *
1812
+ * @example
1813
+ * ```typescript
1814
+ * const cart = await omni.getCart(cartId);
1815
+ * if (cart.reservation?.hasReservation) {
1816
+ * const remaining = cart.reservation.remainingSeconds;
1817
+ * console.log(`Items reserved for ${remaining} seconds`);
1818
+ * }
1819
+ * ```
1820
+ */
1821
+ interface ReservationInfo {
1822
+ /** Whether there is an active reservation */
1823
+ hasReservation: boolean;
1824
+ /** ISO timestamp when reservation expires */
1825
+ expiresAt?: string;
1826
+ /** Remaining time in seconds before reservation expires */
1827
+ remainingSeconds?: number;
1828
+ /** The reservation strategy in use */
1829
+ strategy: InventoryReservationStrategy;
1830
+ /** Custom message from store owner (supports {time} placeholder) */
1831
+ countdownMessage?: string;
1832
+ }
1833
+ /**
1834
+ * Product availability including reserved quantities.
1835
+ * Use this to show accurate stock to customers when reservations are enabled.
1836
+ *
1837
+ * @example
1838
+ * ```typescript
1839
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
1840
+ * availability.forEach(item => {
1841
+ * if (!item.canPurchase) {
1842
+ * console.log(`${item.productId}: Cannot purchase`);
1843
+ * } else if (item.lowStock) {
1844
+ * console.log(`${item.productId}: Only ${item.available} left!`);
1845
+ * }
1846
+ * });
1847
+ * ```
1848
+ */
1849
+ interface ProductAvailability {
1850
+ /** Product ID */
1851
+ productId: string;
1852
+ /** Variant ID (null for simple products) */
1853
+ variantId?: string | null;
1854
+ /** Inventory tracking mode */
1855
+ trackingMode: InventoryTrackingMode;
1856
+ /** Total stock quantity */
1857
+ total: number;
1858
+ /** Quantity currently reserved by other customers */
1859
+ reserved: number;
1860
+ /** Available for purchase (total - reserved) */
1861
+ available: number;
1862
+ /** Whether the product can be purchased */
1863
+ canPurchase: boolean;
1864
+ /** Whether stock is below low stock threshold */
1865
+ lowStock?: boolean;
1866
+ }
1867
+ /**
1868
+ * Response from extending a reservation
1869
+ */
1870
+ interface ExtendReservationResponse {
1871
+ /** Whether the extension was successful */
1872
+ success: boolean;
1873
+ /** Updated reservation info */
1874
+ reservation: ReservationInfo;
1875
+ }
1759
1876
  interface OmniSyncApiError {
1760
1877
  statusCode: number;
1761
1878
  message: string;
@@ -2870,12 +2987,16 @@ declare class OmniSyncClient {
2870
2987
  */
2871
2988
  setCheckoutCustomer(checkoutId: string, data: SetCheckoutCustomerDto): Promise<Checkout>;
2872
2989
  /**
2873
- * Set shipping address on checkout
2874
- * Returns the checkout and available shipping rates for the address
2990
+ * Set shipping address on checkout (includes customer email).
2991
+ * Returns the checkout and available shipping rates for the address.
2992
+ *
2993
+ * **This is the first step of the simplified checkout flow.**
2994
+ * Email is required and will be used for order confirmation.
2875
2995
  *
2876
2996
  * @example
2877
2997
  * ```typescript
2878
2998
  * const { checkout, rates } = await omni.setShippingAddress('checkout_123', {
2999
+ * email: 'customer@example.com', // Required!
2879
3000
  * firstName: 'John',
2880
3001
  * lastName: 'Doe',
2881
3002
  * line1: '123 Main St',
@@ -2992,9 +3113,11 @@ declare class OmniSyncClient {
2992
3113
  * const stripeProvider = providers.find(p => p.provider === 'stripe');
2993
3114
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
2994
3115
  *
2995
- * // Initialize Stripe if available
3116
+ * // Initialize Stripe if available (with Connect account support)
2996
3117
  * if (stripeProvider) {
2997
- * const stripe = await loadStripe(stripeProvider.publicKey);
3118
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
3119
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
3120
+ * });
2998
3121
  * // Show Stripe payment form
2999
3122
  * }
3000
3123
  *
@@ -3398,6 +3521,72 @@ declare class OmniSyncClient {
3398
3521
  * ```
3399
3522
  */
3400
3523
  testCustomApiConnection(integrationId: string): Promise<CustomApiTestResult>;
3524
+ /**
3525
+ * Get product availability including reserved quantities.
3526
+ * Use this to show accurate stock to customers when reservations are enabled.
3527
+ *
3528
+ * **Vibe-coded mode only** - requires connectionId
3529
+ *
3530
+ * @param productIds - Array of product IDs to check availability for
3531
+ * @returns Array of availability info for each product
3532
+ *
3533
+ * @example
3534
+ * ```typescript
3535
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
3536
+ * availability.forEach(item => {
3537
+ * if (!item.canPurchase) {
3538
+ * console.log(`${item.productId}: Cannot purchase`);
3539
+ * } else if (item.lowStock) {
3540
+ * console.log(`${item.productId}: Only ${item.available} left!`);
3541
+ * } else {
3542
+ * console.log(`${item.productId}: ${item.available} available`);
3543
+ * }
3544
+ * });
3545
+ * ```
3546
+ */
3547
+ getAvailability(productIds: string[]): Promise<ProductAvailability[]>;
3548
+ /**
3549
+ * Extend an active reservation to prevent it from expiring.
3550
+ * Call this when a customer is still active in checkout to keep their items reserved.
3551
+ *
3552
+ * **Vibe-coded mode only** - requires connectionId
3553
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
3554
+ *
3555
+ * @param options - Either cartId or checkoutId to identify the reservation
3556
+ * @returns Updated reservation info
3557
+ *
3558
+ * @example
3559
+ * ```typescript
3560
+ * // Extend reservation when customer shows activity
3561
+ * const result = await omni.extendReservation({ checkoutId: 'chk_123' });
3562
+ * if (result.success) {
3563
+ * console.log(`Reservation extended until ${result.reservation.expiresAt}`);
3564
+ * }
3565
+ * ```
3566
+ */
3567
+ extendReservation(options: {
3568
+ cartId?: string;
3569
+ checkoutId?: string;
3570
+ }): Promise<ExtendReservationResponse>;
3571
+ /**
3572
+ * Release an active reservation, returning items to available stock.
3573
+ * Call this when a customer abandons their cart/checkout.
3574
+ *
3575
+ * **Vibe-coded mode only** - requires connectionId
3576
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
3577
+ *
3578
+ * @param options - Either cartId or checkoutId to identify the reservation
3579
+ *
3580
+ * @example
3581
+ * ```typescript
3582
+ * // Release reservation when customer abandons checkout
3583
+ * await omni.releaseReservation({ checkoutId: 'chk_123' });
3584
+ * ```
3585
+ */
3586
+ releaseReservation(options: {
3587
+ cartId?: string;
3588
+ checkoutId?: string;
3589
+ }): Promise<void>;
3401
3590
  }
3402
3591
  /**
3403
3592
  * Custom error class for Omni-Sync API errors
package/dist/index.d.ts CHANGED
@@ -349,6 +349,7 @@ interface ProductQueryParams {
349
349
  interface ProductSuggestion {
350
350
  id: string;
351
351
  name: string;
352
+ slug: string | null;
352
353
  image: string | null;
353
354
  basePrice: number;
354
355
  salePrice?: number | null;
@@ -914,6 +915,12 @@ interface Cart {
914
915
  createdAt: string;
915
916
  /** ISO timestamp when cart was last updated */
916
917
  updatedAt: string;
918
+ /**
919
+ * Reservation information (only present when reservation strategy is ON_CART).
920
+ * Use this to display countdown timer to customers.
921
+ * @see ReservationInfo
922
+ */
923
+ reservation?: ReservationInfo;
917
924
  }
918
925
  interface AddToCartDto {
919
926
  productId: string;
@@ -1256,12 +1263,13 @@ interface ShippingRate {
1256
1263
  /**
1257
1264
  * Represents a checkout session for completing a purchase.
1258
1265
  *
1259
- * **Checkout Flow:**
1260
- * 1. Create checkout from cart: `createCheckout({ cartId })`
1261
- * 2. Set customer info: `setCheckoutCustomer(id, { email, ... })`
1262
- * 3. Set shipping address: `setShippingAddress(id, address)` - returns available rates
1263
- * 4. Select shipping method: `selectShippingMethod(id, rateId)`
1264
- * 5. Complete checkout: `completeCheckout(id)` - creates the order
1266
+ * **Simplified Checkout Flow (3 steps):**
1267
+ * 1. Set shipping address (includes email): `setShippingAddress(id, { email, ...address })` - returns rates
1268
+ * 2. Select shipping method: `selectShippingMethod(id, rateId)`
1269
+ * 3. Pay with Stripe: `createPaymentIntent(id)` → `stripe.confirmPayment()` Order created automatically!
1270
+ *
1271
+ * **Note:** Order is created automatically via webhook when payment succeeds.
1272
+ * No need to call `completeCheckout()` - it happens automatically.
1265
1273
  *
1266
1274
  * **IMPORTANT: Price fields are strings**
1267
1275
  * All monetary fields (subtotal, discountAmount, shippingAmount, taxAmount, total)
@@ -1342,6 +1350,12 @@ interface Checkout {
1342
1350
  createdAt: string;
1343
1351
  /** Last update timestamp */
1344
1352
  updatedAt: string;
1353
+ /**
1354
+ * Reservation information (present when reservation strategy is ON_CHECKOUT or ON_CART).
1355
+ * Use this to display countdown timer to customers.
1356
+ * @see ReservationInfo
1357
+ */
1358
+ reservation?: ReservationInfo;
1345
1359
  }
1346
1360
  interface CreateCheckoutDto {
1347
1361
  cartId: string;
@@ -1354,7 +1368,13 @@ interface SetCheckoutCustomerDto {
1354
1368
  phone?: string;
1355
1369
  acceptsMarketing?: boolean;
1356
1370
  }
1371
+ /**
1372
+ * Shipping address with customer email (required for checkout).
1373
+ * Email is included here to simplify the checkout flow - no need for separate setCheckoutCustomer call.
1374
+ */
1357
1375
  interface SetShippingAddressDto {
1376
+ /** Customer email (required) - used for order confirmation */
1377
+ email: string;
1358
1378
  firstName: string;
1359
1379
  lastName: string;
1360
1380
  company?: string;
@@ -1365,8 +1385,23 @@ interface SetShippingAddressDto {
1365
1385
  postalCode: string;
1366
1386
  country: string;
1367
1387
  phone?: string;
1388
+ /** Whether customer accepts marketing emails */
1389
+ acceptsMarketing?: boolean;
1368
1390
  }
1369
- interface SetBillingAddressDto extends SetShippingAddressDto {
1391
+ /**
1392
+ * Billing address (email not required - already set in shipping address)
1393
+ */
1394
+ interface SetBillingAddressDto {
1395
+ firstName: string;
1396
+ lastName: string;
1397
+ company?: string;
1398
+ line1: string;
1399
+ line2?: string;
1400
+ city: string;
1401
+ region?: string;
1402
+ postalCode: string;
1403
+ country: string;
1404
+ phone?: string;
1370
1405
  sameAsShipping?: boolean;
1371
1406
  }
1372
1407
  interface SelectShippingMethodDto {
@@ -1667,6 +1702,8 @@ interface PaymentProviderConfig {
1667
1702
  name: string;
1668
1703
  /** Public/publishable key (safe to expose) */
1669
1704
  publicKey: string;
1705
+ /** Stripe Connect account ID (for OAuth-connected accounts) */
1706
+ stripeAccountId?: string;
1670
1707
  /** Supported payment methods: ['card', 'ideal', 'bancontact'] */
1671
1708
  supportedMethods: string[];
1672
1709
  /** Whether this is test/sandbox mode */
@@ -1692,7 +1729,10 @@ interface PaymentProviderConfig {
1692
1729
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
1693
1730
  *
1694
1731
  * if (stripeProvider) {
1695
- * // Initialize Stripe.js with stripeProvider.publicKey
1732
+ * // Initialize Stripe.js with options for Connect
1733
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
1734
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
1735
+ * });
1696
1736
  * }
1697
1737
  * if (paypalProvider) {
1698
1738
  * // Initialize PayPal SDK with paypalProvider.publicKey as clientId
@@ -1756,6 +1796,83 @@ interface PaymentStatus {
1756
1796
  /** Payment intent ID from provider */
1757
1797
  paymentIntentId?: string;
1758
1798
  }
1799
+ /**
1800
+ * When inventory is reserved for customers.
1801
+ * Configured per vibe-coded connection by the store owner.
1802
+ *
1803
+ * - ON_PAYMENT: Stock is only reserved when payment is completed (default, safest)
1804
+ * - ON_CHECKOUT: Stock is reserved when checkout is created
1805
+ * - ON_CART: Stock is reserved immediately when added to cart (most aggressive)
1806
+ */
1807
+ type InventoryReservationStrategy = 'ON_PAYMENT' | 'ON_CHECKOUT' | 'ON_CART';
1808
+ /**
1809
+ * Information about a customer's inventory reservation.
1810
+ * Included in cart/checkout responses when reservations are active.
1811
+ *
1812
+ * @example
1813
+ * ```typescript
1814
+ * const cart = await omni.getCart(cartId);
1815
+ * if (cart.reservation?.hasReservation) {
1816
+ * const remaining = cart.reservation.remainingSeconds;
1817
+ * console.log(`Items reserved for ${remaining} seconds`);
1818
+ * }
1819
+ * ```
1820
+ */
1821
+ interface ReservationInfo {
1822
+ /** Whether there is an active reservation */
1823
+ hasReservation: boolean;
1824
+ /** ISO timestamp when reservation expires */
1825
+ expiresAt?: string;
1826
+ /** Remaining time in seconds before reservation expires */
1827
+ remainingSeconds?: number;
1828
+ /** The reservation strategy in use */
1829
+ strategy: InventoryReservationStrategy;
1830
+ /** Custom message from store owner (supports {time} placeholder) */
1831
+ countdownMessage?: string;
1832
+ }
1833
+ /**
1834
+ * Product availability including reserved quantities.
1835
+ * Use this to show accurate stock to customers when reservations are enabled.
1836
+ *
1837
+ * @example
1838
+ * ```typescript
1839
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
1840
+ * availability.forEach(item => {
1841
+ * if (!item.canPurchase) {
1842
+ * console.log(`${item.productId}: Cannot purchase`);
1843
+ * } else if (item.lowStock) {
1844
+ * console.log(`${item.productId}: Only ${item.available} left!`);
1845
+ * }
1846
+ * });
1847
+ * ```
1848
+ */
1849
+ interface ProductAvailability {
1850
+ /** Product ID */
1851
+ productId: string;
1852
+ /** Variant ID (null for simple products) */
1853
+ variantId?: string | null;
1854
+ /** Inventory tracking mode */
1855
+ trackingMode: InventoryTrackingMode;
1856
+ /** Total stock quantity */
1857
+ total: number;
1858
+ /** Quantity currently reserved by other customers */
1859
+ reserved: number;
1860
+ /** Available for purchase (total - reserved) */
1861
+ available: number;
1862
+ /** Whether the product can be purchased */
1863
+ canPurchase: boolean;
1864
+ /** Whether stock is below low stock threshold */
1865
+ lowStock?: boolean;
1866
+ }
1867
+ /**
1868
+ * Response from extending a reservation
1869
+ */
1870
+ interface ExtendReservationResponse {
1871
+ /** Whether the extension was successful */
1872
+ success: boolean;
1873
+ /** Updated reservation info */
1874
+ reservation: ReservationInfo;
1875
+ }
1759
1876
  interface OmniSyncApiError {
1760
1877
  statusCode: number;
1761
1878
  message: string;
@@ -2870,12 +2987,16 @@ declare class OmniSyncClient {
2870
2987
  */
2871
2988
  setCheckoutCustomer(checkoutId: string, data: SetCheckoutCustomerDto): Promise<Checkout>;
2872
2989
  /**
2873
- * Set shipping address on checkout
2874
- * Returns the checkout and available shipping rates for the address
2990
+ * Set shipping address on checkout (includes customer email).
2991
+ * Returns the checkout and available shipping rates for the address.
2992
+ *
2993
+ * **This is the first step of the simplified checkout flow.**
2994
+ * Email is required and will be used for order confirmation.
2875
2995
  *
2876
2996
  * @example
2877
2997
  * ```typescript
2878
2998
  * const { checkout, rates } = await omni.setShippingAddress('checkout_123', {
2999
+ * email: 'customer@example.com', // Required!
2879
3000
  * firstName: 'John',
2880
3001
  * lastName: 'Doe',
2881
3002
  * line1: '123 Main St',
@@ -2992,9 +3113,11 @@ declare class OmniSyncClient {
2992
3113
  * const stripeProvider = providers.find(p => p.provider === 'stripe');
2993
3114
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
2994
3115
  *
2995
- * // Initialize Stripe if available
3116
+ * // Initialize Stripe if available (with Connect account support)
2996
3117
  * if (stripeProvider) {
2997
- * const stripe = await loadStripe(stripeProvider.publicKey);
3118
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
3119
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
3120
+ * });
2998
3121
  * // Show Stripe payment form
2999
3122
  * }
3000
3123
  *
@@ -3398,6 +3521,72 @@ declare class OmniSyncClient {
3398
3521
  * ```
3399
3522
  */
3400
3523
  testCustomApiConnection(integrationId: string): Promise<CustomApiTestResult>;
3524
+ /**
3525
+ * Get product availability including reserved quantities.
3526
+ * Use this to show accurate stock to customers when reservations are enabled.
3527
+ *
3528
+ * **Vibe-coded mode only** - requires connectionId
3529
+ *
3530
+ * @param productIds - Array of product IDs to check availability for
3531
+ * @returns Array of availability info for each product
3532
+ *
3533
+ * @example
3534
+ * ```typescript
3535
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
3536
+ * availability.forEach(item => {
3537
+ * if (!item.canPurchase) {
3538
+ * console.log(`${item.productId}: Cannot purchase`);
3539
+ * } else if (item.lowStock) {
3540
+ * console.log(`${item.productId}: Only ${item.available} left!`);
3541
+ * } else {
3542
+ * console.log(`${item.productId}: ${item.available} available`);
3543
+ * }
3544
+ * });
3545
+ * ```
3546
+ */
3547
+ getAvailability(productIds: string[]): Promise<ProductAvailability[]>;
3548
+ /**
3549
+ * Extend an active reservation to prevent it from expiring.
3550
+ * Call this when a customer is still active in checkout to keep their items reserved.
3551
+ *
3552
+ * **Vibe-coded mode only** - requires connectionId
3553
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
3554
+ *
3555
+ * @param options - Either cartId or checkoutId to identify the reservation
3556
+ * @returns Updated reservation info
3557
+ *
3558
+ * @example
3559
+ * ```typescript
3560
+ * // Extend reservation when customer shows activity
3561
+ * const result = await omni.extendReservation({ checkoutId: 'chk_123' });
3562
+ * if (result.success) {
3563
+ * console.log(`Reservation extended until ${result.reservation.expiresAt}`);
3564
+ * }
3565
+ * ```
3566
+ */
3567
+ extendReservation(options: {
3568
+ cartId?: string;
3569
+ checkoutId?: string;
3570
+ }): Promise<ExtendReservationResponse>;
3571
+ /**
3572
+ * Release an active reservation, returning items to available stock.
3573
+ * Call this when a customer abandons their cart/checkout.
3574
+ *
3575
+ * **Vibe-coded mode only** - requires connectionId
3576
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
3577
+ *
3578
+ * @param options - Either cartId or checkoutId to identify the reservation
3579
+ *
3580
+ * @example
3581
+ * ```typescript
3582
+ * // Release reservation when customer abandons checkout
3583
+ * await omni.releaseReservation({ checkoutId: 'chk_123' });
3584
+ * ```
3585
+ */
3586
+ releaseReservation(options: {
3587
+ cartId?: string;
3588
+ checkoutId?: string;
3589
+ }): Promise<void>;
3401
3590
  }
3402
3591
  /**
3403
3592
  * Custom error class for Omni-Sync API errors
package/dist/index.js CHANGED
@@ -1897,12 +1897,16 @@ var OmniSyncClient = class {
1897
1897
  return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
1898
1898
  }
1899
1899
  /**
1900
- * Set shipping address on checkout
1901
- * Returns the checkout and available shipping rates for the address
1900
+ * Set shipping address on checkout (includes customer email).
1901
+ * Returns the checkout and available shipping rates for the address.
1902
+ *
1903
+ * **This is the first step of the simplified checkout flow.**
1904
+ * Email is required and will be used for order confirmation.
1902
1905
  *
1903
1906
  * @example
1904
1907
  * ```typescript
1905
1908
  * const { checkout, rates } = await omni.setShippingAddress('checkout_123', {
1909
+ * email: 'customer@example.com', // Required!
1906
1910
  * firstName: 'John',
1907
1911
  * lastName: 'Doe',
1908
1912
  * line1: '123 Main St',
@@ -2117,9 +2121,11 @@ var OmniSyncClient = class {
2117
2121
  * const stripeProvider = providers.find(p => p.provider === 'stripe');
2118
2122
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
2119
2123
  *
2120
- * // Initialize Stripe if available
2124
+ * // Initialize Stripe if available (with Connect account support)
2121
2125
  * if (stripeProvider) {
2122
- * const stripe = await loadStripe(stripeProvider.publicKey);
2126
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
2127
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
2128
+ * });
2123
2129
  * // Show Stripe payment form
2124
2130
  * }
2125
2131
  *
@@ -2447,7 +2453,11 @@ var OmniSyncClient = class {
2447
2453
  const trackingResult = await this.startGuestCheckout();
2448
2454
  if (trackingResult.tracked) {
2449
2455
  await this.updateGuestCheckoutAddress(trackingResult.checkoutId, {
2450
- shippingAddress: cart.shippingAddress,
2456
+ shippingAddress: {
2457
+ ...cart.shippingAddress,
2458
+ email: cart.customer.email
2459
+ // Already validated above
2460
+ },
2451
2461
  billingAddress: cart.billingAddress
2452
2462
  });
2453
2463
  const orderResult = await this.completeGuestCheckout(trackingResult.checkoutId, {
@@ -2866,6 +2876,99 @@ var OmniSyncClient = class {
2866
2876
  `/api/v1/custom-api/${integrationId}/test`
2867
2877
  );
2868
2878
  }
2879
+ // -------------------- Inventory Reservations --------------------
2880
+ // These methods are only available in vibe-coded mode when reservation strategy
2881
+ // is set to ON_CART or ON_CHECKOUT
2882
+ /**
2883
+ * Get product availability including reserved quantities.
2884
+ * Use this to show accurate stock to customers when reservations are enabled.
2885
+ *
2886
+ * **Vibe-coded mode only** - requires connectionId
2887
+ *
2888
+ * @param productIds - Array of product IDs to check availability for
2889
+ * @returns Array of availability info for each product
2890
+ *
2891
+ * @example
2892
+ * ```typescript
2893
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
2894
+ * availability.forEach(item => {
2895
+ * if (!item.canPurchase) {
2896
+ * console.log(`${item.productId}: Cannot purchase`);
2897
+ * } else if (item.lowStock) {
2898
+ * console.log(`${item.productId}: Only ${item.available} left!`);
2899
+ * } else {
2900
+ * console.log(`${item.productId}: ${item.available} available`);
2901
+ * }
2902
+ * });
2903
+ * ```
2904
+ */
2905
+ async getAvailability(productIds) {
2906
+ if (!this.isVibeCodedMode()) {
2907
+ throw new OmniSyncError(
2908
+ "getAvailability is only available in vibe-coded mode (use connectionId)",
2909
+ 400
2910
+ );
2911
+ }
2912
+ return this.vibeCodedRequest("POST", "/availability", { productIds });
2913
+ }
2914
+ /**
2915
+ * Extend an active reservation to prevent it from expiring.
2916
+ * Call this when a customer is still active in checkout to keep their items reserved.
2917
+ *
2918
+ * **Vibe-coded mode only** - requires connectionId
2919
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
2920
+ *
2921
+ * @param options - Either cartId or checkoutId to identify the reservation
2922
+ * @returns Updated reservation info
2923
+ *
2924
+ * @example
2925
+ * ```typescript
2926
+ * // Extend reservation when customer shows activity
2927
+ * const result = await omni.extendReservation({ checkoutId: 'chk_123' });
2928
+ * if (result.success) {
2929
+ * console.log(`Reservation extended until ${result.reservation.expiresAt}`);
2930
+ * }
2931
+ * ```
2932
+ */
2933
+ async extendReservation(options) {
2934
+ if (!this.isVibeCodedMode()) {
2935
+ throw new OmniSyncError(
2936
+ "extendReservation is only available in vibe-coded mode (use connectionId)",
2937
+ 400
2938
+ );
2939
+ }
2940
+ if (!options.cartId && !options.checkoutId) {
2941
+ throw new OmniSyncError("Either cartId or checkoutId is required", 400);
2942
+ }
2943
+ return this.vibeCodedRequest("POST", "/reservation/extend", options);
2944
+ }
2945
+ /**
2946
+ * Release an active reservation, returning items to available stock.
2947
+ * Call this when a customer abandons their cart/checkout.
2948
+ *
2949
+ * **Vibe-coded mode only** - requires connectionId
2950
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
2951
+ *
2952
+ * @param options - Either cartId or checkoutId to identify the reservation
2953
+ *
2954
+ * @example
2955
+ * ```typescript
2956
+ * // Release reservation when customer abandons checkout
2957
+ * await omni.releaseReservation({ checkoutId: 'chk_123' });
2958
+ * ```
2959
+ */
2960
+ async releaseReservation(options) {
2961
+ if (!this.isVibeCodedMode()) {
2962
+ throw new OmniSyncError(
2963
+ "releaseReservation is only available in vibe-coded mode (use connectionId)",
2964
+ 400
2965
+ );
2966
+ }
2967
+ if (!options.cartId && !options.checkoutId) {
2968
+ throw new OmniSyncError("Either cartId or checkoutId is required", 400);
2969
+ }
2970
+ await this.vibeCodedRequest("POST", "/reservation/release", options);
2971
+ }
2869
2972
  };
2870
2973
  var OmniSyncError = class extends Error {
2871
2974
  constructor(message, statusCode, details) {
package/dist/index.mjs CHANGED
@@ -1868,12 +1868,16 @@ var OmniSyncClient = class {
1868
1868
  return this.adminRequest("PATCH", `/api/v1/checkout/${checkoutId}/customer`, data);
1869
1869
  }
1870
1870
  /**
1871
- * Set shipping address on checkout
1872
- * Returns the checkout and available shipping rates for the address
1871
+ * Set shipping address on checkout (includes customer email).
1872
+ * Returns the checkout and available shipping rates for the address.
1873
+ *
1874
+ * **This is the first step of the simplified checkout flow.**
1875
+ * Email is required and will be used for order confirmation.
1873
1876
  *
1874
1877
  * @example
1875
1878
  * ```typescript
1876
1879
  * const { checkout, rates } = await omni.setShippingAddress('checkout_123', {
1880
+ * email: 'customer@example.com', // Required!
1877
1881
  * firstName: 'John',
1878
1882
  * lastName: 'Doe',
1879
1883
  * line1: '123 Main St',
@@ -2088,9 +2092,11 @@ var OmniSyncClient = class {
2088
2092
  * const stripeProvider = providers.find(p => p.provider === 'stripe');
2089
2093
  * const paypalProvider = providers.find(p => p.provider === 'paypal');
2090
2094
  *
2091
- * // Initialize Stripe if available
2095
+ * // Initialize Stripe if available (with Connect account support)
2092
2096
  * if (stripeProvider) {
2093
- * const stripe = await loadStripe(stripeProvider.publicKey);
2097
+ * const stripe = await loadStripe(stripeProvider.publicKey, {
2098
+ * stripeAccount: stripeProvider.stripeAccountId, // For Stripe Connect
2099
+ * });
2094
2100
  * // Show Stripe payment form
2095
2101
  * }
2096
2102
  *
@@ -2418,7 +2424,11 @@ var OmniSyncClient = class {
2418
2424
  const trackingResult = await this.startGuestCheckout();
2419
2425
  if (trackingResult.tracked) {
2420
2426
  await this.updateGuestCheckoutAddress(trackingResult.checkoutId, {
2421
- shippingAddress: cart.shippingAddress,
2427
+ shippingAddress: {
2428
+ ...cart.shippingAddress,
2429
+ email: cart.customer.email
2430
+ // Already validated above
2431
+ },
2422
2432
  billingAddress: cart.billingAddress
2423
2433
  });
2424
2434
  const orderResult = await this.completeGuestCheckout(trackingResult.checkoutId, {
@@ -2837,6 +2847,99 @@ var OmniSyncClient = class {
2837
2847
  `/api/v1/custom-api/${integrationId}/test`
2838
2848
  );
2839
2849
  }
2850
+ // -------------------- Inventory Reservations --------------------
2851
+ // These methods are only available in vibe-coded mode when reservation strategy
2852
+ // is set to ON_CART or ON_CHECKOUT
2853
+ /**
2854
+ * Get product availability including reserved quantities.
2855
+ * Use this to show accurate stock to customers when reservations are enabled.
2856
+ *
2857
+ * **Vibe-coded mode only** - requires connectionId
2858
+ *
2859
+ * @param productIds - Array of product IDs to check availability for
2860
+ * @returns Array of availability info for each product
2861
+ *
2862
+ * @example
2863
+ * ```typescript
2864
+ * const availability = await omni.getAvailability(['prod_123', 'prod_456']);
2865
+ * availability.forEach(item => {
2866
+ * if (!item.canPurchase) {
2867
+ * console.log(`${item.productId}: Cannot purchase`);
2868
+ * } else if (item.lowStock) {
2869
+ * console.log(`${item.productId}: Only ${item.available} left!`);
2870
+ * } else {
2871
+ * console.log(`${item.productId}: ${item.available} available`);
2872
+ * }
2873
+ * });
2874
+ * ```
2875
+ */
2876
+ async getAvailability(productIds) {
2877
+ if (!this.isVibeCodedMode()) {
2878
+ throw new OmniSyncError(
2879
+ "getAvailability is only available in vibe-coded mode (use connectionId)",
2880
+ 400
2881
+ );
2882
+ }
2883
+ return this.vibeCodedRequest("POST", "/availability", { productIds });
2884
+ }
2885
+ /**
2886
+ * Extend an active reservation to prevent it from expiring.
2887
+ * Call this when a customer is still active in checkout to keep their items reserved.
2888
+ *
2889
+ * **Vibe-coded mode only** - requires connectionId
2890
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
2891
+ *
2892
+ * @param options - Either cartId or checkoutId to identify the reservation
2893
+ * @returns Updated reservation info
2894
+ *
2895
+ * @example
2896
+ * ```typescript
2897
+ * // Extend reservation when customer shows activity
2898
+ * const result = await omni.extendReservation({ checkoutId: 'chk_123' });
2899
+ * if (result.success) {
2900
+ * console.log(`Reservation extended until ${result.reservation.expiresAt}`);
2901
+ * }
2902
+ * ```
2903
+ */
2904
+ async extendReservation(options) {
2905
+ if (!this.isVibeCodedMode()) {
2906
+ throw new OmniSyncError(
2907
+ "extendReservation is only available in vibe-coded mode (use connectionId)",
2908
+ 400
2909
+ );
2910
+ }
2911
+ if (!options.cartId && !options.checkoutId) {
2912
+ throw new OmniSyncError("Either cartId or checkoutId is required", 400);
2913
+ }
2914
+ return this.vibeCodedRequest("POST", "/reservation/extend", options);
2915
+ }
2916
+ /**
2917
+ * Release an active reservation, returning items to available stock.
2918
+ * Call this when a customer abandons their cart/checkout.
2919
+ *
2920
+ * **Vibe-coded mode only** - requires connectionId
2921
+ * Only works when reservation strategy is ON_CART or ON_CHECKOUT
2922
+ *
2923
+ * @param options - Either cartId or checkoutId to identify the reservation
2924
+ *
2925
+ * @example
2926
+ * ```typescript
2927
+ * // Release reservation when customer abandons checkout
2928
+ * await omni.releaseReservation({ checkoutId: 'chk_123' });
2929
+ * ```
2930
+ */
2931
+ async releaseReservation(options) {
2932
+ if (!this.isVibeCodedMode()) {
2933
+ throw new OmniSyncError(
2934
+ "releaseReservation is only available in vibe-coded mode (use connectionId)",
2935
+ 400
2936
+ );
2937
+ }
2938
+ if (!options.cartId && !options.checkoutId) {
2939
+ throw new OmniSyncError("Either cartId or checkoutId is required", 400);
2940
+ }
2941
+ await this.vibeCodedRequest("POST", "/reservation/release", options);
2942
+ }
2840
2943
  };
2841
2944
  var OmniSyncError = class extends Error {
2842
2945
  constructor(message, statusCode, details) {
package/package.json CHANGED
@@ -1,76 +1,76 @@
1
- {
2
- "name": "omni-sync-sdk",
3
- "version": "0.14.2",
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
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "require": "./dist/index.js",
12
- "import": "./dist/index.mjs"
13
- }
14
- },
15
- "files": [
16
- "dist",
17
- "README.md"
18
- ],
19
- "scripts": {
20
- "build": "tsup src/index.ts --format cjs,esm --dts",
21
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
- "lint": "eslint \"src/**/*.ts\"",
23
- "test": "vitest run",
24
- "test:watch": "vitest",
25
- "prepublishOnly": "pnpm build"
26
- },
27
- "keywords": [
28
- "omni-sync",
29
- "e-commerce",
30
- "ecommerce",
31
- "sdk",
32
- "vibe-coding",
33
- "vibe-coded",
34
- "ai-commerce",
35
- "storefront",
36
- "headless-commerce",
37
- "multi-platform",
38
- "shopify",
39
- "tiktok",
40
- "cursor",
41
- "lovable",
42
- "v0",
43
- "cart",
44
- "checkout",
45
- "products",
46
- "sync"
47
- ],
48
- "author": "Omni-Sync Platform",
49
- "license": "MIT",
50
- "repository": {
51
- "type": "git",
52
- "url": "https://github.com/omni-sync/omni-sync-platform.git",
53
- "directory": "packages/sdk"
54
- },
55
- "homepage": "https://omni-sync.com",
56
- "bugs": {
57
- "url": "https://github.com/omni-sync/omni-sync-platform/issues"
58
- },
59
- "devDependencies": {
60
- "@types/node": "^25.0.3",
61
- "@typescript-eslint/eslint-plugin": "^8.50.1",
62
- "@typescript-eslint/parser": "^8.50.1",
63
- "eslint": "^9.39.2",
64
- "tsup": "^8.0.0",
65
- "typescript": "^5.3.0",
66
- "vitest": "^1.0.0"
67
- },
68
- "peerDependencies": {
69
- "typescript": ">=4.7.0"
70
- },
71
- "peerDependenciesMeta": {
72
- "typescript": {
73
- "optional": true
74
- }
75
- }
76
- }
1
+ {
2
+ "name": "omni-sync-sdk",
3
+ "version": "0.15.0",
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
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "require": "./dist/index.js",
12
+ "import": "./dist/index.mjs"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format cjs,esm --dts",
21
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
+ "lint": "eslint \"src/**/*.ts\"",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "prepublishOnly": "pnpm build"
26
+ },
27
+ "keywords": [
28
+ "omni-sync",
29
+ "e-commerce",
30
+ "ecommerce",
31
+ "sdk",
32
+ "vibe-coding",
33
+ "vibe-coded",
34
+ "ai-commerce",
35
+ "storefront",
36
+ "headless-commerce",
37
+ "multi-platform",
38
+ "shopify",
39
+ "tiktok",
40
+ "cursor",
41
+ "lovable",
42
+ "v0",
43
+ "cart",
44
+ "checkout",
45
+ "products",
46
+ "sync"
47
+ ],
48
+ "author": "Omni-Sync Platform",
49
+ "license": "MIT",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/omni-sync/omni-sync-platform.git",
53
+ "directory": "packages/sdk"
54
+ },
55
+ "homepage": "https://omni-sync.com",
56
+ "bugs": {
57
+ "url": "https://github.com/omni-sync/omni-sync-platform/issues"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^25.0.3",
61
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
62
+ "@typescript-eslint/parser": "^8.50.1",
63
+ "eslint": "^9.39.2",
64
+ "tsup": "^8.0.0",
65
+ "typescript": "^5.3.0",
66
+ "vitest": "^1.0.0"
67
+ },
68
+ "peerDependencies": {
69
+ "typescript": ">=4.7.0"
70
+ },
71
+ "peerDependenciesMeta": {
72
+ "typescript": {
73
+ "optional": true
74
+ }
75
+ }
76
+ }