omni-sync-sdk 0.7.10 → 0.8.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
@@ -853,8 +853,15 @@ const auth = await omni.registerCustomer({
853
853
  lastName: 'Doe',
854
854
  });
855
855
 
856
- setCustomerToken(auth.token);
857
- console.log('Registered:', auth.customer.email);
856
+ // Check if email verification is required
857
+ if (auth.requiresVerification) {
858
+ localStorage.setItem('verificationToken', auth.token);
859
+ window.location.href = '/verify-email';
860
+ } else {
861
+ setCustomerToken(auth.token);
862
+ // Redirect back to store, not /account
863
+ window.location.href = '/';
864
+ }
858
865
  ```
859
866
 
860
867
  #### Login Customer
@@ -862,12 +869,20 @@ console.log('Registered:', auth.customer.email);
862
869
  ```typescript
863
870
  const auth = await omni.loginCustomer('customer@example.com', 'password123');
864
871
  setCustomerToken(auth.token);
872
+
873
+ // Best practice: redirect back to previous page or home
874
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
875
+ localStorage.removeItem('returnUrl');
876
+ window.location.href = returnUrl;
865
877
  ```
866
878
 
879
+ > **Best Practice:** Before showing login page, save the current URL with `localStorage.setItem('returnUrl', window.location.pathname)`. After login, redirect back to that URL. This is how Amazon, Shopify, and most e-commerce sites work.
880
+
867
881
  #### Logout Customer
868
882
 
869
883
  ```typescript
870
884
  setCustomerToken(null);
885
+ window.location.href = '/'; // Return to store home
871
886
  ```
872
887
 
873
888
  #### Get Customer Profile
@@ -930,9 +945,9 @@ if (auth.requiresVerification) {
930
945
  // Redirect to verification page
931
946
  window.location.href = '/verify-email';
932
947
  } else {
933
- // No verification needed - proceed normally
948
+ // No verification needed - redirect back to store
934
949
  setCustomerToken(auth.token);
935
- window.location.href = '/account';
950
+ window.location.href = '/';
936
951
  }
937
952
  ```
938
953
 
@@ -951,7 +966,10 @@ if (result.verified) {
951
966
  // Email verified! Now set the token for normal use
952
967
  setCustomerToken(token);
953
968
  localStorage.removeItem('verificationToken');
954
- window.location.href = '/account';
969
+ // Redirect back to store (or returnUrl if saved)
970
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
971
+ localStorage.removeItem('returnUrl');
972
+ window.location.href = returnUrl;
955
973
  }
956
974
  ```
957
975
 
@@ -996,7 +1014,10 @@ export default function VerifyEmailPage() {
996
1014
  toast.success('Email verified!');
997
1015
  setCustomerToken(token);
998
1016
  localStorage.removeItem('verificationToken');
999
- window.location.href = '/account';
1017
+ // Redirect back to store
1018
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
1019
+ localStorage.removeItem('returnUrl');
1020
+ window.location.href = returnUrl;
1000
1021
  }
1001
1022
  } catch (error) {
1002
1023
  toast.error(error instanceof Error ? error.message : 'Verification failed');
@@ -1055,6 +1076,335 @@ export default function VerifyEmailPage() {
1055
1076
 
1056
1077
  ---
1057
1078
 
1079
+ ### Social Login (OAuth)
1080
+
1081
+ Allow customers to sign in with Google, Facebook, or GitHub. The store owner configures which providers are available in their OmniSync admin panel.
1082
+
1083
+ #### Check Available Providers
1084
+
1085
+ ```typescript
1086
+ // Returns only the providers the store owner has enabled
1087
+ const { providers } = await omni.getAvailableOAuthProviders();
1088
+ // providers = ['GOOGLE', 'FACEBOOK'] - varies by store configuration
1089
+ ```
1090
+
1091
+ #### OAuth Login Flow
1092
+
1093
+ **Step 1: User clicks "Sign in with Google"**
1094
+
1095
+ ```typescript
1096
+ // Save cart ID before redirect (user will leave your site!)
1097
+ const cartId = localStorage.getItem('cartId');
1098
+ if (cartId) sessionStorage.setItem('pendingCartId', cartId);
1099
+
1100
+ // Get authorization URL
1101
+ const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl('GOOGLE', {
1102
+ redirectUrl: window.location.origin + '/auth/callback', // Where Google sends them back
1103
+ });
1104
+
1105
+ // Save state for verification (CSRF protection)
1106
+ sessionStorage.setItem('oauthState', state);
1107
+
1108
+ // Redirect to Google
1109
+ window.location.href = authorizationUrl;
1110
+ ```
1111
+
1112
+ **Step 2: Create callback page (`/auth/callback`)**
1113
+
1114
+ ```typescript
1115
+ // pages/auth/callback.tsx or app/auth/callback/page.tsx
1116
+ 'use client';
1117
+ import { useEffect, useState } from 'react';
1118
+ import { useSearchParams } from 'next/navigation';
1119
+ import { omni, setCustomerToken } from '@/lib/omni-sync';
1120
+
1121
+ export default function AuthCallback() {
1122
+ const searchParams = useSearchParams();
1123
+ const [error, setError] = useState<string | null>(null);
1124
+
1125
+ useEffect(() => {
1126
+ async function handleCallback() {
1127
+ const code = searchParams.get('code');
1128
+ const state = searchParams.get('state');
1129
+ const errorParam = searchParams.get('error');
1130
+
1131
+ // Check for OAuth errors (user cancelled, etc.)
1132
+ if (errorParam) {
1133
+ window.location.href = '/login?error=cancelled';
1134
+ return;
1135
+ }
1136
+
1137
+ if (!code || !state) {
1138
+ setError('Missing OAuth parameters');
1139
+ return;
1140
+ }
1141
+
1142
+ // Verify state matches (CSRF protection)
1143
+ const savedState = sessionStorage.getItem('oauthState');
1144
+ if (state !== savedState) {
1145
+ setError('Invalid state - please try again');
1146
+ return;
1147
+ }
1148
+
1149
+ try {
1150
+ // Exchange code for customer token
1151
+ const { customer, token, isNewCustomer } = await omni.handleOAuthCallback(
1152
+ 'GOOGLE',
1153
+ code,
1154
+ state
1155
+ );
1156
+
1157
+ // Save the customer token
1158
+ setCustomerToken(token);
1159
+ sessionStorage.removeItem('oauthState');
1160
+
1161
+ // Link any pending cart to the now-logged-in customer
1162
+ const pendingCartId = sessionStorage.getItem('pendingCartId');
1163
+ if (pendingCartId) {
1164
+ try {
1165
+ await omni.linkCart(pendingCartId);
1166
+ } catch {
1167
+ // Cart may have expired - that's ok
1168
+ }
1169
+ sessionStorage.removeItem('pendingCartId');
1170
+ }
1171
+
1172
+ // Redirect to return URL or home
1173
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
1174
+ localStorage.removeItem('returnUrl');
1175
+ window.location.href = returnUrl;
1176
+ } catch (err) {
1177
+ setError(err instanceof Error ? err.message : 'Login failed');
1178
+ }
1179
+ }
1180
+
1181
+ handleCallback();
1182
+ }, [searchParams]);
1183
+
1184
+ if (error) {
1185
+ return (
1186
+ <div className="max-w-md mx-auto mt-12 text-center">
1187
+ <h1 className="text-xl font-bold text-red-600">Login Failed</h1>
1188
+ <p className="mt-2 text-gray-600">{error}</p>
1189
+ <a href="/login" className="mt-4 inline-block text-blue-600">
1190
+ Try again
1191
+ </a>
1192
+ </div>
1193
+ );
1194
+ }
1195
+
1196
+ return (
1197
+ <div className="max-w-md mx-auto mt-12 text-center">
1198
+ <div className="animate-spin h-8 w-8 border-4 border-blue-600 border-t-transparent rounded-full mx-auto"></div>
1199
+ <p className="mt-4 text-gray-600">Completing login...</p>
1200
+ </div>
1201
+ );
1202
+ }
1203
+ ```
1204
+
1205
+ #### Login Page with Social Buttons
1206
+
1207
+ ```typescript
1208
+ 'use client';
1209
+ import { useState, useEffect } from 'react';
1210
+ import { omni, setCustomerToken } from '@/lib/omni-sync';
1211
+
1212
+ export default function LoginPage() {
1213
+ const [providers, setProviders] = useState<string[]>([]);
1214
+ const [email, setEmail] = useState('');
1215
+ const [password, setPassword] = useState('');
1216
+ const [loading, setLoading] = useState(false);
1217
+ const [error, setError] = useState('');
1218
+
1219
+ // Load available OAuth providers
1220
+ useEffect(() => {
1221
+ omni.getAvailableOAuthProviders()
1222
+ .then(({ providers }) => setProviders(providers))
1223
+ .catch(() => {}); // OAuth not configured - that's ok
1224
+ }, []);
1225
+
1226
+ // Social login handler
1227
+ const handleSocialLogin = async (provider: string) => {
1228
+ try {
1229
+ // Save cart ID before redirect
1230
+ const cartId = localStorage.getItem('cartId');
1231
+ if (cartId) sessionStorage.setItem('pendingCartId', cartId);
1232
+
1233
+ const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl(
1234
+ provider as 'GOOGLE' | 'FACEBOOK' | 'GITHUB',
1235
+ { redirectUrl: window.location.origin + '/auth/callback' }
1236
+ );
1237
+
1238
+ sessionStorage.setItem('oauthState', state);
1239
+ window.location.href = authorizationUrl;
1240
+ } catch (err) {
1241
+ setError('Failed to start login');
1242
+ }
1243
+ };
1244
+
1245
+ // Regular email/password login
1246
+ const handleSubmit = async (e: React.FormEvent) => {
1247
+ e.preventDefault();
1248
+ setLoading(true);
1249
+ setError('');
1250
+ try {
1251
+ const auth = await omni.loginCustomer(email, password);
1252
+ setCustomerToken(auth.token);
1253
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
1254
+ localStorage.removeItem('returnUrl');
1255
+ window.location.href = returnUrl;
1256
+ } catch (err) {
1257
+ setError('Invalid email or password');
1258
+ } finally {
1259
+ setLoading(false);
1260
+ }
1261
+ };
1262
+
1263
+ return (
1264
+ <div className="max-w-md mx-auto mt-12">
1265
+ <h1 className="text-2xl font-bold mb-6">Login</h1>
1266
+
1267
+ {/* Social Login Buttons */}
1268
+ {providers.length > 0 && (
1269
+ <div className="space-y-3 mb-6">
1270
+ {providers.includes('GOOGLE') && (
1271
+ <button
1272
+ onClick={() => handleSocialLogin('GOOGLE')}
1273
+ className="w-full flex items-center justify-center gap-2 border py-3 rounded hover:bg-gray-50"
1274
+ >
1275
+ <GoogleIcon />
1276
+ Continue with Google
1277
+ </button>
1278
+ )}
1279
+ {providers.includes('FACEBOOK') && (
1280
+ <button
1281
+ onClick={() => handleSocialLogin('FACEBOOK')}
1282
+ className="w-full flex items-center justify-center gap-2 bg-[#1877F2] text-white py-3 rounded"
1283
+ >
1284
+ <FacebookIcon />
1285
+ Continue with Facebook
1286
+ </button>
1287
+ )}
1288
+ {providers.includes('GITHUB') && (
1289
+ <button
1290
+ onClick={() => handleSocialLogin('GITHUB')}
1291
+ className="w-full flex items-center justify-center gap-2 bg-[#24292F] text-white py-3 rounded"
1292
+ >
1293
+ <GithubIcon />
1294
+ Continue with GitHub
1295
+ </button>
1296
+ )}
1297
+ <div className="relative my-4">
1298
+ <div className="absolute inset-0 flex items-center">
1299
+ <div className="w-full border-t" />
1300
+ </div>
1301
+ <div className="relative flex justify-center text-sm">
1302
+ <span className="px-2 bg-white text-gray-500">or</span>
1303
+ </div>
1304
+ </div>
1305
+ </div>
1306
+ )}
1307
+
1308
+ {/* Email/Password Form */}
1309
+ {error && <div className="bg-red-100 text-red-600 p-3 rounded mb-4">{error}</div>}
1310
+ <form onSubmit={handleSubmit} className="space-y-4">
1311
+ <input
1312
+ type="email"
1313
+ placeholder="Email"
1314
+ value={email}
1315
+ onChange={(e) => setEmail(e.target.value)}
1316
+ required
1317
+ className="w-full border p-2 rounded"
1318
+ />
1319
+ <input
1320
+ type="password"
1321
+ placeholder="Password"
1322
+ value={password}
1323
+ onChange={(e) => setPassword(e.target.value)}
1324
+ required
1325
+ className="w-full border p-2 rounded"
1326
+ />
1327
+ <button
1328
+ type="submit"
1329
+ disabled={loading}
1330
+ className="w-full bg-black text-white py-3 rounded"
1331
+ >
1332
+ {loading ? 'Logging in...' : 'Login'}
1333
+ </button>
1334
+ </form>
1335
+
1336
+ <p className="mt-4 text-center">
1337
+ Don't have an account? <a href="/register" className="text-blue-600">Register</a>
1338
+ </p>
1339
+ </div>
1340
+ );
1341
+ }
1342
+
1343
+ // Simple SVG icons (or use lucide-react)
1344
+ const GoogleIcon = () => (
1345
+ <svg className="w-5 h-5" viewBox="0 0 24 24">
1346
+ <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/>
1347
+ <path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/>
1348
+ <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/>
1349
+ <path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/>
1350
+ </svg>
1351
+ );
1352
+
1353
+ const FacebookIcon = () => (
1354
+ <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
1355
+ <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
1356
+ </svg>
1357
+ );
1358
+
1359
+ const GithubIcon = () => (
1360
+ <svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
1361
+ <path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
1362
+ </svg>
1363
+ );
1364
+ ```
1365
+
1366
+ #### Account Linking (Add Social Account to Existing User)
1367
+
1368
+ Logged-in customers can link additional social accounts to their profile:
1369
+
1370
+ ```typescript
1371
+ // Get currently linked accounts
1372
+ const connections = await omni.getOAuthConnections();
1373
+ // [{ provider: 'GOOGLE', email: 'user@gmail.com', linkedAt: '...' }]
1374
+
1375
+ // Link a new provider (redirects to OAuth flow)
1376
+ const { authorizationUrl } = await omni.linkOAuthProvider('GITHUB');
1377
+ window.location.href = authorizationUrl;
1378
+
1379
+ // Unlink a provider
1380
+ await omni.unlinkOAuthProvider('GOOGLE');
1381
+ ```
1382
+
1383
+ #### Cart Linking After OAuth Login
1384
+
1385
+ When a customer logs in via OAuth, their guest cart should be linked to their account:
1386
+
1387
+ ```typescript
1388
+ // omni.linkCart() associates a guest cart with the logged-in customer
1389
+ await omni.linkCart(cartId);
1390
+ ```
1391
+
1392
+ This is automatically handled in the callback example above.
1393
+
1394
+ #### OAuth Method Reference
1395
+
1396
+ | Method | Description |
1397
+ | -------------------------------------------- | -------------------------------------------- |
1398
+ | `getAvailableOAuthProviders()` | Get list of enabled providers for this store |
1399
+ | `getOAuthAuthorizeUrl(provider, options?)` | Get URL to redirect user to OAuth provider |
1400
+ | `handleOAuthCallback(provider, code, state)` | Exchange OAuth code for customer token |
1401
+ | `linkOAuthProvider(provider)` | Link social account to current customer |
1402
+ | `unlinkOAuthProvider(provider)` | Remove linked social account |
1403
+ | `getOAuthConnections()` | Get list of linked social accounts |
1404
+ | `linkCart(cartId)` | Link guest cart to logged-in customer |
1405
+
1406
+ ---
1407
+
1058
1408
  ### Customer Addresses
1059
1409
 
1060
1410
  #### Get Addresses
@@ -1767,7 +2117,7 @@ export default function CheckoutPage() {
1767
2117
 
1768
2118
  ```typescript
1769
2119
  'use client';
1770
- import { useState } from 'react';
2120
+ import { useState, useEffect } from 'react';
1771
2121
  import { omni, setCustomerToken } from '@/lib/omni-sync';
1772
2122
 
1773
2123
  export default function LoginPage() {
@@ -1776,6 +2126,15 @@ export default function LoginPage() {
1776
2126
  const [error, setError] = useState('');
1777
2127
  const [loading, setLoading] = useState(false);
1778
2128
 
2129
+ // Save the page user came from (for redirect after login)
2130
+ useEffect(() => {
2131
+ const referrer = document.referrer;
2132
+ if (referrer && !referrer.includes('/login') && !referrer.includes('/register')) {
2133
+ const url = new URL(referrer);
2134
+ localStorage.setItem('returnUrl', url.pathname);
2135
+ }
2136
+ }, []);
2137
+
1779
2138
  const handleSubmit = async (e: React.FormEvent) => {
1780
2139
  e.preventDefault();
1781
2140
  setLoading(true);
@@ -1783,7 +2142,11 @@ export default function LoginPage() {
1783
2142
  try {
1784
2143
  const auth = await omni.loginCustomer(email, password);
1785
2144
  setCustomerToken(auth.token);
1786
- window.location.href = '/account';
2145
+
2146
+ // Redirect back to previous page or home (like Amazon/Shopify do)
2147
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
2148
+ localStorage.removeItem('returnUrl');
2149
+ window.location.href = returnUrl;
1787
2150
  } catch (err) {
1788
2151
  setError('Invalid email or password');
1789
2152
  } finally {
@@ -1814,7 +2177,7 @@ export default function LoginPage() {
1814
2177
 
1815
2178
  ```typescript
1816
2179
  'use client';
1817
- import { useState } from 'react';
2180
+ import { useState, useEffect } from 'react';
1818
2181
  import { omni, setCustomerToken } from '@/lib/omni-sync';
1819
2182
 
1820
2183
  export default function RegisterPage() {
@@ -1825,6 +2188,15 @@ export default function RegisterPage() {
1825
2188
  const [error, setError] = useState('');
1826
2189
  const [loading, setLoading] = useState(false);
1827
2190
 
2191
+ // Save the page user came from (for redirect after registration)
2192
+ useEffect(() => {
2193
+ const referrer = document.referrer;
2194
+ if (referrer && !referrer.includes('/login') && !referrer.includes('/register')) {
2195
+ const url = new URL(referrer);
2196
+ localStorage.setItem('returnUrl', url.pathname);
2197
+ }
2198
+ }, []);
2199
+
1828
2200
  const handleSubmit = async (e: React.FormEvent) => {
1829
2201
  e.preventDefault();
1830
2202
  setLoading(true);
@@ -1838,9 +2210,11 @@ export default function RegisterPage() {
1838
2210
  localStorage.setItem('verificationToken', auth.token);
1839
2211
  window.location.href = '/verify-email';
1840
2212
  } else {
1841
- // No verification needed - proceed normally
2213
+ // No verification needed - redirect back to store (like Amazon/Shopify)
1842
2214
  setCustomerToken(auth.token);
1843
- window.location.href = '/account';
2215
+ const returnUrl = localStorage.getItem('returnUrl') || '/';
2216
+ localStorage.removeItem('returnUrl');
2217
+ window.location.href = returnUrl;
1844
2218
  }
1845
2219
  } catch (err) {
1846
2220
  setError('Registration failed. Email may already be in use.');
@@ -2143,8 +2517,9 @@ When building a store, implement these pages:
2143
2517
  - [ ] **Product Detail** (`/products/[id]`) - Single product with Add to Cart
2144
2518
  - [ ] **Cart** (`/cart`) - Cart items, update quantity, remove
2145
2519
  - [ ] **Checkout** (`/checkout`) - Multi-step checkout flow
2146
- - [ ] **Login** (`/login`) - Customer login
2147
- - [ ] **Register** (`/register`) - Customer registration
2520
+ - [ ] **Login** (`/login`) - Customer login + social login buttons (Google/Facebook/GitHub if available)
2521
+ - [ ] **Register** (`/register`) - Customer registration + social signup buttons
2522
+ - [ ] **Auth Callback** (`/auth/callback`) - Handle OAuth redirects from Google/Facebook/GitHub
2148
2523
  - [ ] **Verify Email** (`/verify-email`) - Email verification with 6-digit code (if store requires it)
2149
2524
  - [ ] **Account** (`/account`) - Profile and order history
2150
2525
 
package/dist/index.d.mts CHANGED
@@ -505,6 +505,30 @@ interface EmailVerificationResponse {
505
505
  verified: boolean;
506
506
  message: string;
507
507
  }
508
+ type CustomerOAuthProvider = 'GOOGLE' | 'FACEBOOK' | 'GITHUB';
509
+ interface OAuthAuthorizeResponse {
510
+ authorizationUrl: string;
511
+ state: string;
512
+ provider: CustomerOAuthProvider;
513
+ }
514
+ interface OAuthCallbackResponse extends CustomerAuthResponse {
515
+ isNewCustomer: boolean;
516
+ linkedToExisting: boolean;
517
+ provider: CustomerOAuthProvider;
518
+ redirectUrl?: string;
519
+ }
520
+ interface OAuthConnection {
521
+ id: string;
522
+ provider: CustomerOAuthProvider;
523
+ email?: string;
524
+ createdAt: string;
525
+ }
526
+ interface OAuthProvidersResponse {
527
+ providers: CustomerOAuthProvider[];
528
+ }
529
+ interface OAuthConnectionsResponse {
530
+ connections: OAuthConnection[];
531
+ }
508
532
  interface RegisterCustomerDto {
509
533
  email: string;
510
534
  password: string;
@@ -1709,6 +1733,118 @@ declare class OmniSyncClient {
1709
1733
  resendVerificationEmail(token?: string): Promise<{
1710
1734
  message: string;
1711
1735
  }>;
1736
+ /**
1737
+ * Get available OAuth providers for this store
1738
+ * Works in vibe-coded and storefront modes
1739
+ *
1740
+ * @example
1741
+ * ```typescript
1742
+ * const { providers } = await omni.getAvailableOAuthProviders();
1743
+ * // providers: ['GOOGLE', 'FACEBOOK']
1744
+ * ```
1745
+ */
1746
+ getAvailableOAuthProviders(): Promise<OAuthProvidersResponse>;
1747
+ /**
1748
+ * Get OAuth authorization URL for a provider
1749
+ * Redirects user to provider's login page
1750
+ * Works in vibe-coded and storefront modes
1751
+ *
1752
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1753
+ * @param options - Optional configuration
1754
+ * @param options.redirectUrl - URL to redirect to after OAuth completes
1755
+ *
1756
+ * @example
1757
+ * ```typescript
1758
+ * // Get authorization URL
1759
+ * const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl('GOOGLE', {
1760
+ * redirectUrl: 'https://mysite.com/auth/callback'
1761
+ * });
1762
+ *
1763
+ * // Redirect user to authorizationUrl
1764
+ * window.location.href = authorizationUrl;
1765
+ * ```
1766
+ */
1767
+ getOAuthAuthorizeUrl(provider: CustomerOAuthProvider, options?: {
1768
+ redirectUrl?: string;
1769
+ }): Promise<OAuthAuthorizeResponse>;
1770
+ /**
1771
+ * Handle OAuth callback - exchange code for customer token
1772
+ * Call this after user is redirected back from OAuth provider
1773
+ * Works in vibe-coded and storefront modes
1774
+ *
1775
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1776
+ * @param code - Authorization code from OAuth provider
1777
+ * @param state - State parameter from OAuth callback
1778
+ *
1779
+ * @example
1780
+ * ```typescript
1781
+ * // After user is redirected back with code and state in URL
1782
+ * const urlParams = new URLSearchParams(window.location.search);
1783
+ * const code = urlParams.get('code');
1784
+ * const state = urlParams.get('state');
1785
+ *
1786
+ * const auth = await omni.handleOAuthCallback('GOOGLE', code, state);
1787
+ * omni.setCustomerToken(auth.token);
1788
+ *
1789
+ * if (auth.isNewCustomer) {
1790
+ * console.log('Welcome, new customer!');
1791
+ * }
1792
+ * ```
1793
+ */
1794
+ handleOAuthCallback(provider: CustomerOAuthProvider, code: string, state: string): Promise<OAuthCallbackResponse>;
1795
+ /**
1796
+ * Link OAuth provider to current logged-in customer
1797
+ * Returns authorization URL - redirect user there
1798
+ * Requires customer to be logged in (setCustomerToken called first)
1799
+ *
1800
+ * @param provider - OAuth provider to link ('GOOGLE', 'FACEBOOK', 'GITHUB')
1801
+ * @param options - Optional configuration
1802
+ * @param options.redirectUrl - URL to redirect to after linking
1803
+ *
1804
+ * @example
1805
+ * ```typescript
1806
+ * // Customer must be logged in first
1807
+ * omni.setCustomerToken(auth.token);
1808
+ *
1809
+ * // Get authorization URL for linking
1810
+ * const { authorizationUrl } = await omni.linkOAuthProvider('GITHUB', {
1811
+ * redirectUrl: '/settings'
1812
+ * });
1813
+ *
1814
+ * // Redirect user to link their GitHub account
1815
+ * window.location.href = authorizationUrl;
1816
+ * ```
1817
+ */
1818
+ linkOAuthProvider(provider: CustomerOAuthProvider, options?: {
1819
+ redirectUrl?: string;
1820
+ }): Promise<OAuthAuthorizeResponse>;
1821
+ /**
1822
+ * Unlink OAuth provider from current customer account
1823
+ * Requires customer to be logged in
1824
+ *
1825
+ * @param provider - OAuth provider to unlink ('GOOGLE', 'FACEBOOK', 'GITHUB')
1826
+ *
1827
+ * @example
1828
+ * ```typescript
1829
+ * omni.setCustomerToken(auth.token);
1830
+ * await omni.unlinkOAuthProvider('FACEBOOK');
1831
+ * ```
1832
+ */
1833
+ unlinkOAuthProvider(provider: CustomerOAuthProvider): Promise<{
1834
+ success: boolean;
1835
+ }>;
1836
+ /**
1837
+ * Get OAuth connections for current customer
1838
+ * Requires customer to be logged in
1839
+ *
1840
+ * @example
1841
+ * ```typescript
1842
+ * omni.setCustomerToken(auth.token);
1843
+ * const { connections } = await omni.getOAuthConnections();
1844
+ * // connections: [{ id: '...', provider: 'GOOGLE', email: 'user@gmail.com', createdAt: '...' }]
1845
+ * ```
1846
+ */
1847
+ getOAuthConnections(): Promise<OAuthConnectionsResponse>;
1712
1848
  /**
1713
1849
  * Get the current logged-in customer's profile
1714
1850
  * Requires a customer token to be set via setCustomerToken()
@@ -1870,6 +2006,20 @@ declare class OmniSyncClient {
1870
2006
  * ```
1871
2007
  */
1872
2008
  removeCoupon(cartId: string): Promise<Cart>;
2009
+ /**
2010
+ * Link a cart to the currently logged-in customer
2011
+ * Use this after customer logs in to associate their guest cart with their account
2012
+ * Requires customer token to be set via setCustomerToken()
2013
+ *
2014
+ * @example
2015
+ * ```typescript
2016
+ * // After customer logs in
2017
+ * omni.setCustomerToken(authResponse.token);
2018
+ * const cart = await omni.linkCart('cart_123');
2019
+ * // Cart is now linked to the customer
2020
+ * ```
2021
+ */
2022
+ linkCart(cartId: string): Promise<Cart>;
1873
2023
  /**
1874
2024
  * Merge a guest cart into a customer's cart (after login)
1875
2025
  * The guest cart items are moved to the customer's cart
@@ -2395,4 +2545,4 @@ declare function isWebhookEventType(event: WebhookEvent, type: WebhookEventType)
2395
2545
  */
2396
2546
  declare function createWebhookHandler(handlers: Partial<Record<WebhookEventType, (event: WebhookEvent) => Promise<void>>>): (payload: unknown) => Promise<void>;
2397
2547
 
2398
- export { type AddToCartDto, type AppliedDiscount, type ApplyCouponDto, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartItem, type CartStatus, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutLineItem, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConnectorPlatform, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateCheckoutDto, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateGuestOrderDto, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerProfile, type CustomerQueryParams, type DraftLineItem, type EditInventoryDto, type EmailVerificationResponse, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type InventoryInfo, type InventorySyncStatus, type LocalCart, type LocalCartItem, type MergeCartsDto, type OmniSyncApiError, OmniSyncClient, type OmniSyncClientOptions, OmniSyncError, type Order, type OrderAddress, type OrderCustomer, type OrderItem, type OrderQueryParams, type OrderStatus, type PaginatedResponse, type PlatformCouponCapabilities, type Product, type ProductAttributeInput, type ProductImage, type ProductQueryParams, type ProductSuggestion, type ProductVariant, type PublishProductResponse, type ReconcileInventoryResponse, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type SearchSuggestions, type SelectShippingMethodDto, type SendInvoiceDto, type SetBillingAddressDto, type SetCheckoutCustomerDto, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingLine, type ShippingRate, type StoreInfo, type SyncJob, type UpdateAddressDto, type UpdateCartItemDto, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateInventoryDto, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateVariantDto, type UpdateVariantInventoryDto, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WebhookEvent, type WebhookEventType, createWebhookHandler, isCouponApplicableToProduct, isWebhookEventType, parseWebhookEvent, verifyWebhook };
2548
+ export { type AddToCartDto, type AppliedDiscount, type ApplyCouponDto, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartItem, type CartStatus, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutLineItem, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConnectorPlatform, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateCheckoutDto, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateGuestOrderDto, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DraftLineItem, type EditInventoryDto, type EmailVerificationResponse, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type InventoryInfo, type InventorySyncStatus, type LocalCart, type LocalCartItem, type MergeCartsDto, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProvidersResponse, type OmniSyncApiError, OmniSyncClient, type OmniSyncClientOptions, OmniSyncError, type Order, type OrderAddress, type OrderCustomer, type OrderItem, type OrderQueryParams, type OrderStatus, type PaginatedResponse, type PlatformCouponCapabilities, type Product, type ProductAttributeInput, type ProductImage, type ProductQueryParams, type ProductSuggestion, type ProductVariant, type PublishProductResponse, type ReconcileInventoryResponse, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type SearchSuggestions, type SelectShippingMethodDto, type SendInvoiceDto, type SetBillingAddressDto, type SetCheckoutCustomerDto, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingLine, type ShippingRate, type StoreInfo, type SyncJob, type UpdateAddressDto, type UpdateCartItemDto, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateInventoryDto, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateVariantDto, type UpdateVariantInventoryDto, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WebhookEvent, type WebhookEventType, createWebhookHandler, isCouponApplicableToProduct, isWebhookEventType, parseWebhookEvent, verifyWebhook };
package/dist/index.d.ts CHANGED
@@ -505,6 +505,30 @@ interface EmailVerificationResponse {
505
505
  verified: boolean;
506
506
  message: string;
507
507
  }
508
+ type CustomerOAuthProvider = 'GOOGLE' | 'FACEBOOK' | 'GITHUB';
509
+ interface OAuthAuthorizeResponse {
510
+ authorizationUrl: string;
511
+ state: string;
512
+ provider: CustomerOAuthProvider;
513
+ }
514
+ interface OAuthCallbackResponse extends CustomerAuthResponse {
515
+ isNewCustomer: boolean;
516
+ linkedToExisting: boolean;
517
+ provider: CustomerOAuthProvider;
518
+ redirectUrl?: string;
519
+ }
520
+ interface OAuthConnection {
521
+ id: string;
522
+ provider: CustomerOAuthProvider;
523
+ email?: string;
524
+ createdAt: string;
525
+ }
526
+ interface OAuthProvidersResponse {
527
+ providers: CustomerOAuthProvider[];
528
+ }
529
+ interface OAuthConnectionsResponse {
530
+ connections: OAuthConnection[];
531
+ }
508
532
  interface RegisterCustomerDto {
509
533
  email: string;
510
534
  password: string;
@@ -1709,6 +1733,118 @@ declare class OmniSyncClient {
1709
1733
  resendVerificationEmail(token?: string): Promise<{
1710
1734
  message: string;
1711
1735
  }>;
1736
+ /**
1737
+ * Get available OAuth providers for this store
1738
+ * Works in vibe-coded and storefront modes
1739
+ *
1740
+ * @example
1741
+ * ```typescript
1742
+ * const { providers } = await omni.getAvailableOAuthProviders();
1743
+ * // providers: ['GOOGLE', 'FACEBOOK']
1744
+ * ```
1745
+ */
1746
+ getAvailableOAuthProviders(): Promise<OAuthProvidersResponse>;
1747
+ /**
1748
+ * Get OAuth authorization URL for a provider
1749
+ * Redirects user to provider's login page
1750
+ * Works in vibe-coded and storefront modes
1751
+ *
1752
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1753
+ * @param options - Optional configuration
1754
+ * @param options.redirectUrl - URL to redirect to after OAuth completes
1755
+ *
1756
+ * @example
1757
+ * ```typescript
1758
+ * // Get authorization URL
1759
+ * const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl('GOOGLE', {
1760
+ * redirectUrl: 'https://mysite.com/auth/callback'
1761
+ * });
1762
+ *
1763
+ * // Redirect user to authorizationUrl
1764
+ * window.location.href = authorizationUrl;
1765
+ * ```
1766
+ */
1767
+ getOAuthAuthorizeUrl(provider: CustomerOAuthProvider, options?: {
1768
+ redirectUrl?: string;
1769
+ }): Promise<OAuthAuthorizeResponse>;
1770
+ /**
1771
+ * Handle OAuth callback - exchange code for customer token
1772
+ * Call this after user is redirected back from OAuth provider
1773
+ * Works in vibe-coded and storefront modes
1774
+ *
1775
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1776
+ * @param code - Authorization code from OAuth provider
1777
+ * @param state - State parameter from OAuth callback
1778
+ *
1779
+ * @example
1780
+ * ```typescript
1781
+ * // After user is redirected back with code and state in URL
1782
+ * const urlParams = new URLSearchParams(window.location.search);
1783
+ * const code = urlParams.get('code');
1784
+ * const state = urlParams.get('state');
1785
+ *
1786
+ * const auth = await omni.handleOAuthCallback('GOOGLE', code, state);
1787
+ * omni.setCustomerToken(auth.token);
1788
+ *
1789
+ * if (auth.isNewCustomer) {
1790
+ * console.log('Welcome, new customer!');
1791
+ * }
1792
+ * ```
1793
+ */
1794
+ handleOAuthCallback(provider: CustomerOAuthProvider, code: string, state: string): Promise<OAuthCallbackResponse>;
1795
+ /**
1796
+ * Link OAuth provider to current logged-in customer
1797
+ * Returns authorization URL - redirect user there
1798
+ * Requires customer to be logged in (setCustomerToken called first)
1799
+ *
1800
+ * @param provider - OAuth provider to link ('GOOGLE', 'FACEBOOK', 'GITHUB')
1801
+ * @param options - Optional configuration
1802
+ * @param options.redirectUrl - URL to redirect to after linking
1803
+ *
1804
+ * @example
1805
+ * ```typescript
1806
+ * // Customer must be logged in first
1807
+ * omni.setCustomerToken(auth.token);
1808
+ *
1809
+ * // Get authorization URL for linking
1810
+ * const { authorizationUrl } = await omni.linkOAuthProvider('GITHUB', {
1811
+ * redirectUrl: '/settings'
1812
+ * });
1813
+ *
1814
+ * // Redirect user to link their GitHub account
1815
+ * window.location.href = authorizationUrl;
1816
+ * ```
1817
+ */
1818
+ linkOAuthProvider(provider: CustomerOAuthProvider, options?: {
1819
+ redirectUrl?: string;
1820
+ }): Promise<OAuthAuthorizeResponse>;
1821
+ /**
1822
+ * Unlink OAuth provider from current customer account
1823
+ * Requires customer to be logged in
1824
+ *
1825
+ * @param provider - OAuth provider to unlink ('GOOGLE', 'FACEBOOK', 'GITHUB')
1826
+ *
1827
+ * @example
1828
+ * ```typescript
1829
+ * omni.setCustomerToken(auth.token);
1830
+ * await omni.unlinkOAuthProvider('FACEBOOK');
1831
+ * ```
1832
+ */
1833
+ unlinkOAuthProvider(provider: CustomerOAuthProvider): Promise<{
1834
+ success: boolean;
1835
+ }>;
1836
+ /**
1837
+ * Get OAuth connections for current customer
1838
+ * Requires customer to be logged in
1839
+ *
1840
+ * @example
1841
+ * ```typescript
1842
+ * omni.setCustomerToken(auth.token);
1843
+ * const { connections } = await omni.getOAuthConnections();
1844
+ * // connections: [{ id: '...', provider: 'GOOGLE', email: 'user@gmail.com', createdAt: '...' }]
1845
+ * ```
1846
+ */
1847
+ getOAuthConnections(): Promise<OAuthConnectionsResponse>;
1712
1848
  /**
1713
1849
  * Get the current logged-in customer's profile
1714
1850
  * Requires a customer token to be set via setCustomerToken()
@@ -1870,6 +2006,20 @@ declare class OmniSyncClient {
1870
2006
  * ```
1871
2007
  */
1872
2008
  removeCoupon(cartId: string): Promise<Cart>;
2009
+ /**
2010
+ * Link a cart to the currently logged-in customer
2011
+ * Use this after customer logs in to associate their guest cart with their account
2012
+ * Requires customer token to be set via setCustomerToken()
2013
+ *
2014
+ * @example
2015
+ * ```typescript
2016
+ * // After customer logs in
2017
+ * omni.setCustomerToken(authResponse.token);
2018
+ * const cart = await omni.linkCart('cart_123');
2019
+ * // Cart is now linked to the customer
2020
+ * ```
2021
+ */
2022
+ linkCart(cartId: string): Promise<Cart>;
1873
2023
  /**
1874
2024
  * Merge a guest cart into a customer's cart (after login)
1875
2025
  * The guest cart items are moved to the customer's cart
@@ -2395,4 +2545,4 @@ declare function isWebhookEventType(event: WebhookEvent, type: WebhookEventType)
2395
2545
  */
2396
2546
  declare function createWebhookHandler(handlers: Partial<Record<WebhookEventType, (event: WebhookEvent) => Promise<void>>>): (payload: unknown) => Promise<void>;
2397
2547
 
2398
- export { type AddToCartDto, type AppliedDiscount, type ApplyCouponDto, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartItem, type CartStatus, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutLineItem, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConnectorPlatform, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateCheckoutDto, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateGuestOrderDto, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerProfile, type CustomerQueryParams, type DraftLineItem, type EditInventoryDto, type EmailVerificationResponse, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type InventoryInfo, type InventorySyncStatus, type LocalCart, type LocalCartItem, type MergeCartsDto, type OmniSyncApiError, OmniSyncClient, type OmniSyncClientOptions, OmniSyncError, type Order, type OrderAddress, type OrderCustomer, type OrderItem, type OrderQueryParams, type OrderStatus, type PaginatedResponse, type PlatformCouponCapabilities, type Product, type ProductAttributeInput, type ProductImage, type ProductQueryParams, type ProductSuggestion, type ProductVariant, type PublishProductResponse, type ReconcileInventoryResponse, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type SearchSuggestions, type SelectShippingMethodDto, type SendInvoiceDto, type SetBillingAddressDto, type SetCheckoutCustomerDto, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingLine, type ShippingRate, type StoreInfo, type SyncJob, type UpdateAddressDto, type UpdateCartItemDto, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateInventoryDto, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateVariantDto, type UpdateVariantInventoryDto, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WebhookEvent, type WebhookEventType, createWebhookHandler, isCouponApplicableToProduct, isWebhookEventType, parseWebhookEvent, verifyWebhook };
2548
+ export { type AddToCartDto, type AppliedDiscount, type ApplyCouponDto, type BulkInventoryResponse, type BulkSaveVariantsDto, type BulkSaveVariantsResponse, type BulkVariantInput, type Cart, type CartItem, type CartStatus, type CategorySuggestion, type Checkout, type CheckoutAddress, type CheckoutLineItem, type CheckoutStatus, type CompleteCheckoutResponse, type CompleteDraftDto, type ConnectorPlatform, type Coupon, type CouponCreateResponse, type CouponQueryParams, type CouponStatus, type CouponType, type CouponValidationWarning, type CreateAddressDto, type CreateCheckoutDto, type CreateCouponDto, type CreateCustomApiDto, type CreateCustomerDto, type CreateGuestOrderDto, type CreateOrderDto, type CreateProductDto, type CreateRefundDto, type CreateVariantDto, type CustomApiAuthType, type CustomApiConnectionStatus, type CustomApiCredentials, type CustomApiIntegration, type CustomApiSyncConfig, type CustomApiSyncDirection, type CustomApiTestResult, type Customer, type CustomerAddress, type CustomerAuthResponse, type CustomerOAuthProvider, type CustomerProfile, type CustomerQueryParams, type DraftLineItem, type EditInventoryDto, type EmailVerificationResponse, type FulfillOrderDto, type GuestCheckoutStartResponse, type GuestOrderResponse, type InventoryInfo, type InventorySyncStatus, type LocalCart, type LocalCartItem, type MergeCartsDto, type OAuthAuthorizeResponse, type OAuthCallbackResponse, type OAuthConnection, type OAuthConnectionsResponse, type OAuthProvidersResponse, type OmniSyncApiError, OmniSyncClient, type OmniSyncClientOptions, OmniSyncError, type Order, type OrderAddress, type OrderCustomer, type OrderItem, type OrderQueryParams, type OrderStatus, type PaginatedResponse, type PlatformCouponCapabilities, type Product, type ProductAttributeInput, type ProductImage, type ProductQueryParams, type ProductSuggestion, type ProductVariant, type PublishProductResponse, type ReconcileInventoryResponse, type Refund, type RefundLineItem, type RefundLineItemResponse, type RefundType, type RegisterCustomerDto, type SearchSuggestions, type SelectShippingMethodDto, type SendInvoiceDto, type SetBillingAddressDto, type SetCheckoutCustomerDto, type SetShippingAddressDto, type SetShippingAddressResponse, type ShippingLine, type ShippingRate, type StoreInfo, type SyncJob, type UpdateAddressDto, type UpdateCartItemDto, type UpdateCouponDto, type UpdateCustomApiDto, type UpdateCustomerDto, type UpdateDraftDto, type UpdateInventoryDto, type UpdateOrderDto, type UpdateOrderShippingDto, type UpdateProductDto, type UpdateVariantDto, type UpdateVariantInventoryDto, type VariantInventoryResponse, type VariantPlatformOverlay, type VariantStatus, type WebhookEvent, type WebhookEventType, createWebhookHandler, isCouponApplicableToProduct, isWebhookEventType, parseWebhookEvent, verifyWebhook };
package/dist/index.js CHANGED
@@ -1187,6 +1187,195 @@ var OmniSyncClient = class {
1187
1187
  }
1188
1188
  }
1189
1189
  }
1190
+ // ===================================================
1191
+ // Customer OAuth (Social Login)
1192
+ // ===================================================
1193
+ /**
1194
+ * Get available OAuth providers for this store
1195
+ * Works in vibe-coded and storefront modes
1196
+ *
1197
+ * @example
1198
+ * ```typescript
1199
+ * const { providers } = await omni.getAvailableOAuthProviders();
1200
+ * // providers: ['GOOGLE', 'FACEBOOK']
1201
+ * ```
1202
+ */
1203
+ async getAvailableOAuthProviders() {
1204
+ if (this.isVibeCodedMode()) {
1205
+ return this.vibeCodedRequest("GET", "/oauth/providers");
1206
+ }
1207
+ if (this.isStorefrontMode()) {
1208
+ return this.storefrontRequest("GET", "/oauth/providers");
1209
+ }
1210
+ throw new OmniSyncError(
1211
+ "getAvailableOAuthProviders requires vibe-coded or storefront mode",
1212
+ 400
1213
+ );
1214
+ }
1215
+ /**
1216
+ * Get OAuth authorization URL for a provider
1217
+ * Redirects user to provider's login page
1218
+ * Works in vibe-coded and storefront modes
1219
+ *
1220
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1221
+ * @param options - Optional configuration
1222
+ * @param options.redirectUrl - URL to redirect to after OAuth completes
1223
+ *
1224
+ * @example
1225
+ * ```typescript
1226
+ * // Get authorization URL
1227
+ * const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl('GOOGLE', {
1228
+ * redirectUrl: 'https://mysite.com/auth/callback'
1229
+ * });
1230
+ *
1231
+ * // Redirect user to authorizationUrl
1232
+ * window.location.href = authorizationUrl;
1233
+ * ```
1234
+ */
1235
+ async getOAuthAuthorizeUrl(provider, options) {
1236
+ const params = new URLSearchParams();
1237
+ if (options?.redirectUrl) {
1238
+ params.set("redirectUrl", options.redirectUrl);
1239
+ }
1240
+ const queryString = params.toString();
1241
+ const endpoint = `/oauth/${provider}/authorize${queryString ? `?${queryString}` : ""}`;
1242
+ if (this.isVibeCodedMode()) {
1243
+ return this.vibeCodedRequest("GET", endpoint);
1244
+ }
1245
+ if (this.isStorefrontMode()) {
1246
+ return this.storefrontRequest("GET", endpoint);
1247
+ }
1248
+ throw new OmniSyncError("getOAuthAuthorizeUrl requires vibe-coded or storefront mode", 400);
1249
+ }
1250
+ /**
1251
+ * Handle OAuth callback - exchange code for customer token
1252
+ * Call this after user is redirected back from OAuth provider
1253
+ * Works in vibe-coded and storefront modes
1254
+ *
1255
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1256
+ * @param code - Authorization code from OAuth provider
1257
+ * @param state - State parameter from OAuth callback
1258
+ *
1259
+ * @example
1260
+ * ```typescript
1261
+ * // After user is redirected back with code and state in URL
1262
+ * const urlParams = new URLSearchParams(window.location.search);
1263
+ * const code = urlParams.get('code');
1264
+ * const state = urlParams.get('state');
1265
+ *
1266
+ * const auth = await omni.handleOAuthCallback('GOOGLE', code, state);
1267
+ * omni.setCustomerToken(auth.token);
1268
+ *
1269
+ * if (auth.isNewCustomer) {
1270
+ * console.log('Welcome, new customer!');
1271
+ * }
1272
+ * ```
1273
+ */
1274
+ async handleOAuthCallback(provider, code, state) {
1275
+ const params = new URLSearchParams({ code, state });
1276
+ const endpoint = `/oauth/${provider}/callback?${params.toString()}`;
1277
+ if (this.isVibeCodedMode()) {
1278
+ return this.vibeCodedRequest("GET", endpoint);
1279
+ }
1280
+ if (this.isStorefrontMode()) {
1281
+ return this.storefrontRequest("GET", endpoint);
1282
+ }
1283
+ throw new OmniSyncError("handleOAuthCallback requires vibe-coded or storefront mode", 400);
1284
+ }
1285
+ /**
1286
+ * Link OAuth provider to current logged-in customer
1287
+ * Returns authorization URL - redirect user there
1288
+ * Requires customer to be logged in (setCustomerToken called first)
1289
+ *
1290
+ * @param provider - OAuth provider to link ('GOOGLE', 'FACEBOOK', 'GITHUB')
1291
+ * @param options - Optional configuration
1292
+ * @param options.redirectUrl - URL to redirect to after linking
1293
+ *
1294
+ * @example
1295
+ * ```typescript
1296
+ * // Customer must be logged in first
1297
+ * omni.setCustomerToken(auth.token);
1298
+ *
1299
+ * // Get authorization URL for linking
1300
+ * const { authorizationUrl } = await omni.linkOAuthProvider('GITHUB', {
1301
+ * redirectUrl: '/settings'
1302
+ * });
1303
+ *
1304
+ * // Redirect user to link their GitHub account
1305
+ * window.location.href = authorizationUrl;
1306
+ * ```
1307
+ */
1308
+ async linkOAuthProvider(provider, options) {
1309
+ if (!this.customerToken) {
1310
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1311
+ }
1312
+ const params = new URLSearchParams();
1313
+ if (options?.redirectUrl) {
1314
+ params.set("redirectUrl", options.redirectUrl);
1315
+ }
1316
+ const queryString = params.toString();
1317
+ const endpoint = `/oauth/${provider}/link${queryString ? `?${queryString}` : ""}`;
1318
+ if (this.isVibeCodedMode()) {
1319
+ return this.vibeCodedRequest("POST", endpoint);
1320
+ }
1321
+ if (this.isStorefrontMode()) {
1322
+ return this.storefrontRequest("POST", endpoint);
1323
+ }
1324
+ throw new OmniSyncError("linkOAuthProvider requires vibe-coded or storefront mode", 400);
1325
+ }
1326
+ /**
1327
+ * Unlink OAuth provider from current customer account
1328
+ * Requires customer to be logged in
1329
+ *
1330
+ * @param provider - OAuth provider to unlink ('GOOGLE', 'FACEBOOK', 'GITHUB')
1331
+ *
1332
+ * @example
1333
+ * ```typescript
1334
+ * omni.setCustomerToken(auth.token);
1335
+ * await omni.unlinkOAuthProvider('FACEBOOK');
1336
+ * ```
1337
+ */
1338
+ async unlinkOAuthProvider(provider) {
1339
+ if (!this.customerToken) {
1340
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1341
+ }
1342
+ if (this.isVibeCodedMode()) {
1343
+ return this.vibeCodedRequest("DELETE", `/oauth/${provider}/link`);
1344
+ }
1345
+ if (this.isStorefrontMode()) {
1346
+ return this.storefrontRequest("DELETE", `/oauth/${provider}/link`);
1347
+ }
1348
+ throw new OmniSyncError("unlinkOAuthProvider requires vibe-coded or storefront mode", 400);
1349
+ }
1350
+ /**
1351
+ * Get OAuth connections for current customer
1352
+ * Requires customer to be logged in
1353
+ *
1354
+ * @example
1355
+ * ```typescript
1356
+ * omni.setCustomerToken(auth.token);
1357
+ * const { connections } = await omni.getOAuthConnections();
1358
+ * // connections: [{ id: '...', provider: 'GOOGLE', email: 'user@gmail.com', createdAt: '...' }]
1359
+ * ```
1360
+ */
1361
+ async getOAuthConnections() {
1362
+ if (!this.customerToken) {
1363
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1364
+ }
1365
+ if (this.isVibeCodedMode()) {
1366
+ return this.vibeCodedRequest(
1367
+ "GET",
1368
+ "/customers/me/oauth-connections"
1369
+ );
1370
+ }
1371
+ if (this.isStorefrontMode()) {
1372
+ return this.storefrontRequest(
1373
+ "GET",
1374
+ "/customers/me/oauth-connections"
1375
+ );
1376
+ }
1377
+ throw new OmniSyncError("getOAuthConnections requires vibe-coded or storefront mode", 400);
1378
+ }
1190
1379
  /**
1191
1380
  * Get the current logged-in customer's profile
1192
1381
  * Requires a customer token to be set via setCustomerToken()
@@ -1452,6 +1641,34 @@ var OmniSyncClient = class {
1452
1641
  }
1453
1642
  return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/coupon`);
1454
1643
  }
1644
+ /**
1645
+ * Link a cart to the currently logged-in customer
1646
+ * Use this after customer logs in to associate their guest cart with their account
1647
+ * Requires customer token to be set via setCustomerToken()
1648
+ *
1649
+ * @example
1650
+ * ```typescript
1651
+ * // After customer logs in
1652
+ * omni.setCustomerToken(authResponse.token);
1653
+ * const cart = await omni.linkCart('cart_123');
1654
+ * // Cart is now linked to the customer
1655
+ * ```
1656
+ */
1657
+ async linkCart(cartId) {
1658
+ if (!this.customerToken) {
1659
+ throw new OmniSyncError(
1660
+ "Customer must be logged in to link cart. Call setCustomerToken() first.",
1661
+ 401
1662
+ );
1663
+ }
1664
+ if (this.isVibeCodedMode()) {
1665
+ return this.vibeCodedRequest("POST", `/cart/${cartId}/link`);
1666
+ }
1667
+ if (this.storeId && !this.apiKey) {
1668
+ return this.storefrontRequest("POST", `/cart/${cartId}/link`);
1669
+ }
1670
+ throw new OmniSyncError("linkCart is only available in vibe-coded or storefront mode", 400);
1671
+ }
1455
1672
  /**
1456
1673
  * Merge a guest cart into a customer's cart (after login)
1457
1674
  * The guest cart items are moved to the customer's cart
package/dist/index.mjs CHANGED
@@ -1162,6 +1162,195 @@ var OmniSyncClient = class {
1162
1162
  }
1163
1163
  }
1164
1164
  }
1165
+ // ===================================================
1166
+ // Customer OAuth (Social Login)
1167
+ // ===================================================
1168
+ /**
1169
+ * Get available OAuth providers for this store
1170
+ * Works in vibe-coded and storefront modes
1171
+ *
1172
+ * @example
1173
+ * ```typescript
1174
+ * const { providers } = await omni.getAvailableOAuthProviders();
1175
+ * // providers: ['GOOGLE', 'FACEBOOK']
1176
+ * ```
1177
+ */
1178
+ async getAvailableOAuthProviders() {
1179
+ if (this.isVibeCodedMode()) {
1180
+ return this.vibeCodedRequest("GET", "/oauth/providers");
1181
+ }
1182
+ if (this.isStorefrontMode()) {
1183
+ return this.storefrontRequest("GET", "/oauth/providers");
1184
+ }
1185
+ throw new OmniSyncError(
1186
+ "getAvailableOAuthProviders requires vibe-coded or storefront mode",
1187
+ 400
1188
+ );
1189
+ }
1190
+ /**
1191
+ * Get OAuth authorization URL for a provider
1192
+ * Redirects user to provider's login page
1193
+ * Works in vibe-coded and storefront modes
1194
+ *
1195
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1196
+ * @param options - Optional configuration
1197
+ * @param options.redirectUrl - URL to redirect to after OAuth completes
1198
+ *
1199
+ * @example
1200
+ * ```typescript
1201
+ * // Get authorization URL
1202
+ * const { authorizationUrl, state } = await omni.getOAuthAuthorizeUrl('GOOGLE', {
1203
+ * redirectUrl: 'https://mysite.com/auth/callback'
1204
+ * });
1205
+ *
1206
+ * // Redirect user to authorizationUrl
1207
+ * window.location.href = authorizationUrl;
1208
+ * ```
1209
+ */
1210
+ async getOAuthAuthorizeUrl(provider, options) {
1211
+ const params = new URLSearchParams();
1212
+ if (options?.redirectUrl) {
1213
+ params.set("redirectUrl", options.redirectUrl);
1214
+ }
1215
+ const queryString = params.toString();
1216
+ const endpoint = `/oauth/${provider}/authorize${queryString ? `?${queryString}` : ""}`;
1217
+ if (this.isVibeCodedMode()) {
1218
+ return this.vibeCodedRequest("GET", endpoint);
1219
+ }
1220
+ if (this.isStorefrontMode()) {
1221
+ return this.storefrontRequest("GET", endpoint);
1222
+ }
1223
+ throw new OmniSyncError("getOAuthAuthorizeUrl requires vibe-coded or storefront mode", 400);
1224
+ }
1225
+ /**
1226
+ * Handle OAuth callback - exchange code for customer token
1227
+ * Call this after user is redirected back from OAuth provider
1228
+ * Works in vibe-coded and storefront modes
1229
+ *
1230
+ * @param provider - OAuth provider ('GOOGLE', 'FACEBOOK', 'GITHUB')
1231
+ * @param code - Authorization code from OAuth provider
1232
+ * @param state - State parameter from OAuth callback
1233
+ *
1234
+ * @example
1235
+ * ```typescript
1236
+ * // After user is redirected back with code and state in URL
1237
+ * const urlParams = new URLSearchParams(window.location.search);
1238
+ * const code = urlParams.get('code');
1239
+ * const state = urlParams.get('state');
1240
+ *
1241
+ * const auth = await omni.handleOAuthCallback('GOOGLE', code, state);
1242
+ * omni.setCustomerToken(auth.token);
1243
+ *
1244
+ * if (auth.isNewCustomer) {
1245
+ * console.log('Welcome, new customer!');
1246
+ * }
1247
+ * ```
1248
+ */
1249
+ async handleOAuthCallback(provider, code, state) {
1250
+ const params = new URLSearchParams({ code, state });
1251
+ const endpoint = `/oauth/${provider}/callback?${params.toString()}`;
1252
+ if (this.isVibeCodedMode()) {
1253
+ return this.vibeCodedRequest("GET", endpoint);
1254
+ }
1255
+ if (this.isStorefrontMode()) {
1256
+ return this.storefrontRequest("GET", endpoint);
1257
+ }
1258
+ throw new OmniSyncError("handleOAuthCallback requires vibe-coded or storefront mode", 400);
1259
+ }
1260
+ /**
1261
+ * Link OAuth provider to current logged-in customer
1262
+ * Returns authorization URL - redirect user there
1263
+ * Requires customer to be logged in (setCustomerToken called first)
1264
+ *
1265
+ * @param provider - OAuth provider to link ('GOOGLE', 'FACEBOOK', 'GITHUB')
1266
+ * @param options - Optional configuration
1267
+ * @param options.redirectUrl - URL to redirect to after linking
1268
+ *
1269
+ * @example
1270
+ * ```typescript
1271
+ * // Customer must be logged in first
1272
+ * omni.setCustomerToken(auth.token);
1273
+ *
1274
+ * // Get authorization URL for linking
1275
+ * const { authorizationUrl } = await omni.linkOAuthProvider('GITHUB', {
1276
+ * redirectUrl: '/settings'
1277
+ * });
1278
+ *
1279
+ * // Redirect user to link their GitHub account
1280
+ * window.location.href = authorizationUrl;
1281
+ * ```
1282
+ */
1283
+ async linkOAuthProvider(provider, options) {
1284
+ if (!this.customerToken) {
1285
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1286
+ }
1287
+ const params = new URLSearchParams();
1288
+ if (options?.redirectUrl) {
1289
+ params.set("redirectUrl", options.redirectUrl);
1290
+ }
1291
+ const queryString = params.toString();
1292
+ const endpoint = `/oauth/${provider}/link${queryString ? `?${queryString}` : ""}`;
1293
+ if (this.isVibeCodedMode()) {
1294
+ return this.vibeCodedRequest("POST", endpoint);
1295
+ }
1296
+ if (this.isStorefrontMode()) {
1297
+ return this.storefrontRequest("POST", endpoint);
1298
+ }
1299
+ throw new OmniSyncError("linkOAuthProvider requires vibe-coded or storefront mode", 400);
1300
+ }
1301
+ /**
1302
+ * Unlink OAuth provider from current customer account
1303
+ * Requires customer to be logged in
1304
+ *
1305
+ * @param provider - OAuth provider to unlink ('GOOGLE', 'FACEBOOK', 'GITHUB')
1306
+ *
1307
+ * @example
1308
+ * ```typescript
1309
+ * omni.setCustomerToken(auth.token);
1310
+ * await omni.unlinkOAuthProvider('FACEBOOK');
1311
+ * ```
1312
+ */
1313
+ async unlinkOAuthProvider(provider) {
1314
+ if (!this.customerToken) {
1315
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1316
+ }
1317
+ if (this.isVibeCodedMode()) {
1318
+ return this.vibeCodedRequest("DELETE", `/oauth/${provider}/link`);
1319
+ }
1320
+ if (this.isStorefrontMode()) {
1321
+ return this.storefrontRequest("DELETE", `/oauth/${provider}/link`);
1322
+ }
1323
+ throw new OmniSyncError("unlinkOAuthProvider requires vibe-coded or storefront mode", 400);
1324
+ }
1325
+ /**
1326
+ * Get OAuth connections for current customer
1327
+ * Requires customer to be logged in
1328
+ *
1329
+ * @example
1330
+ * ```typescript
1331
+ * omni.setCustomerToken(auth.token);
1332
+ * const { connections } = await omni.getOAuthConnections();
1333
+ * // connections: [{ id: '...', provider: 'GOOGLE', email: 'user@gmail.com', createdAt: '...' }]
1334
+ * ```
1335
+ */
1336
+ async getOAuthConnections() {
1337
+ if (!this.customerToken) {
1338
+ throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1339
+ }
1340
+ if (this.isVibeCodedMode()) {
1341
+ return this.vibeCodedRequest(
1342
+ "GET",
1343
+ "/customers/me/oauth-connections"
1344
+ );
1345
+ }
1346
+ if (this.isStorefrontMode()) {
1347
+ return this.storefrontRequest(
1348
+ "GET",
1349
+ "/customers/me/oauth-connections"
1350
+ );
1351
+ }
1352
+ throw new OmniSyncError("getOAuthConnections requires vibe-coded or storefront mode", 400);
1353
+ }
1165
1354
  /**
1166
1355
  * Get the current logged-in customer's profile
1167
1356
  * Requires a customer token to be set via setCustomerToken()
@@ -1427,6 +1616,34 @@ var OmniSyncClient = class {
1427
1616
  }
1428
1617
  return this.adminRequest("DELETE", `/api/v1/cart/${cartId}/coupon`);
1429
1618
  }
1619
+ /**
1620
+ * Link a cart to the currently logged-in customer
1621
+ * Use this after customer logs in to associate their guest cart with their account
1622
+ * Requires customer token to be set via setCustomerToken()
1623
+ *
1624
+ * @example
1625
+ * ```typescript
1626
+ * // After customer logs in
1627
+ * omni.setCustomerToken(authResponse.token);
1628
+ * const cart = await omni.linkCart('cart_123');
1629
+ * // Cart is now linked to the customer
1630
+ * ```
1631
+ */
1632
+ async linkCart(cartId) {
1633
+ if (!this.customerToken) {
1634
+ throw new OmniSyncError(
1635
+ "Customer must be logged in to link cart. Call setCustomerToken() first.",
1636
+ 401
1637
+ );
1638
+ }
1639
+ if (this.isVibeCodedMode()) {
1640
+ return this.vibeCodedRequest("POST", `/cart/${cartId}/link`);
1641
+ }
1642
+ if (this.storeId && !this.apiKey) {
1643
+ return this.storefrontRequest("POST", `/cart/${cartId}/link`);
1644
+ }
1645
+ throw new OmniSyncError("linkCart is only available in vibe-coded or storefront mode", 400);
1646
+ }
1430
1647
  /**
1431
1648
  * Merge a guest cart into a customer's cart (after login)
1432
1649
  * The guest cart items are moved to the customer's cart
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omni-sync-sdk",
3
- "version": "0.7.10",
3
+ "version": "0.8.0",
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",