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 +388 -13
- package/dist/index.d.mts +151 -1
- package/dist/index.d.ts +151 -1
- package/dist/index.js +217 -0
- package/dist/index.mjs +217 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -853,8 +853,15 @@ const auth = await omni.registerCustomer({
|
|
|
853
853
|
lastName: 'Doe',
|
|
854
854
|
});
|
|
855
855
|
|
|
856
|
-
|
|
857
|
-
|
|
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 -
|
|
948
|
+
// No verification needed - redirect back to store
|
|
934
949
|
setCustomerToken(auth.token);
|
|
935
|
-
window.location.href = '/
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 -
|
|
2213
|
+
// No verification needed - redirect back to store (like Amazon/Shopify)
|
|
1842
2214
|
setCustomerToken(auth.token);
|
|
1843
|
-
|
|
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.
|
|
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",
|