omni-sync-sdk 0.7.8 → 0.7.10

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
@@ -903,6 +903,153 @@ interface CustomerAuthResponse {
903
903
  };
904
904
  token: string;
905
905
  expiresAt: string;
906
+ requiresVerification?: boolean; // true if email verification is required
907
+ }
908
+ ```
909
+
910
+ ---
911
+
912
+ ### Email Verification
913
+
914
+ If the store has **email verification enabled**, customers must verify their email after registration before they can fully use their account.
915
+
916
+ #### Registration with Email Verification
917
+
918
+ When `requiresVerification` is true in the registration response, the customer needs to verify their email:
919
+
920
+ ```typescript
921
+ const auth = await omni.registerCustomer({
922
+ email: 'customer@example.com',
923
+ password: 'securepassword123',
924
+ firstName: 'John',
925
+ });
926
+
927
+ if (auth.requiresVerification) {
928
+ // Save token for verification step
929
+ localStorage.setItem('verificationToken', auth.token);
930
+ // Redirect to verification page
931
+ window.location.href = '/verify-email';
932
+ } else {
933
+ // No verification needed - proceed normally
934
+ setCustomerToken(auth.token);
935
+ window.location.href = '/account';
936
+ }
937
+ ```
938
+
939
+ #### Verify Email with Code
940
+
941
+ After the customer receives the 6-digit code via email:
942
+
943
+ ```typescript
944
+ // Get the token saved from registration
945
+ const token = localStorage.getItem('verificationToken');
946
+
947
+ // Verify email - pass the token directly (no need to call setCustomerToken first!)
948
+ const result = await omni.verifyEmail(code, token);
949
+
950
+ if (result.verified) {
951
+ // Email verified! Now set the token for normal use
952
+ setCustomerToken(token);
953
+ localStorage.removeItem('verificationToken');
954
+ window.location.href = '/account';
955
+ }
956
+ ```
957
+
958
+ #### Resend Verification Email
959
+
960
+ If the customer didn't receive the email or the code expired:
961
+
962
+ ```typescript
963
+ const token = localStorage.getItem('verificationToken');
964
+ await omni.resendVerificationEmail(token);
965
+ // Show success message - new code sent
966
+ ```
967
+
968
+ > **Note:** Resend is rate-limited to 3 requests per hour.
969
+
970
+ #### Complete Email Verification Page Example
971
+
972
+ ```typescript
973
+ 'use client';
974
+ import { useState } from 'react';
975
+ import { omni, setCustomerToken } from '@/lib/omni-sync';
976
+ import { toast } from 'sonner';
977
+
978
+ export default function VerifyEmailPage() {
979
+ const [code, setCode] = useState('');
980
+ const [loading, setLoading] = useState(false);
981
+
982
+ const handleVerify = async (e: React.FormEvent) => {
983
+ e.preventDefault();
984
+ setLoading(true);
985
+
986
+ try {
987
+ const token = localStorage.getItem('verificationToken');
988
+ if (!token) {
989
+ toast.error('No verification token found. Please register again.');
990
+ return;
991
+ }
992
+
993
+ const result = await omni.verifyEmail(code, token);
994
+
995
+ if (result.verified) {
996
+ toast.success('Email verified!');
997
+ setCustomerToken(token);
998
+ localStorage.removeItem('verificationToken');
999
+ window.location.href = '/account';
1000
+ }
1001
+ } catch (error) {
1002
+ toast.error(error instanceof Error ? error.message : 'Verification failed');
1003
+ } finally {
1004
+ setLoading(false);
1005
+ }
1006
+ };
1007
+
1008
+ const handleResend = async () => {
1009
+ try {
1010
+ const token = localStorage.getItem('verificationToken');
1011
+ if (!token) {
1012
+ toast.error('No verification token found');
1013
+ return;
1014
+ }
1015
+ await omni.resendVerificationEmail(token);
1016
+ toast.success('Verification code sent!');
1017
+ } catch (error) {
1018
+ toast.error(error instanceof Error ? error.message : 'Failed to resend');
1019
+ }
1020
+ };
1021
+
1022
+ return (
1023
+ <div className="max-w-md mx-auto mt-12">
1024
+ <h1 className="text-2xl font-bold mb-4">Verify Your Email</h1>
1025
+ <p className="text-gray-600 mb-6">
1026
+ We sent a 6-digit code to your email. Enter it below to verify your account.
1027
+ </p>
1028
+
1029
+ <form onSubmit={handleVerify} className="space-y-4">
1030
+ <input
1031
+ type="text"
1032
+ placeholder="Enter 6-digit code"
1033
+ value={code}
1034
+ onChange={(e) => setCode(e.target.value)}
1035
+ maxLength={6}
1036
+ className="w-full border p-3 rounded text-center text-2xl tracking-widest"
1037
+ required
1038
+ />
1039
+ <button
1040
+ type="submit"
1041
+ disabled={loading || code.length !== 6}
1042
+ className="w-full bg-black text-white py-3 rounded disabled:opacity-50"
1043
+ >
1044
+ {loading ? 'Verifying...' : 'Verify Email'}
1045
+ </button>
1046
+ </form>
1047
+
1048
+ <button onClick={handleResend} className="mt-4 text-blue-600 text-sm">
1049
+ Didn't receive the code? Resend
1050
+ </button>
1051
+ </div>
1052
+ );
906
1053
  }
907
1054
  ```
908
1055
 
@@ -1684,8 +1831,17 @@ export default function RegisterPage() {
1684
1831
  setError('');
1685
1832
  try {
1686
1833
  const auth = await omni.registerCustomer({ email, password, firstName, lastName });
1687
- setCustomerToken(auth.token);
1688
- window.location.href = '/account';
1834
+
1835
+ // Check if email verification is required
1836
+ if (auth.requiresVerification) {
1837
+ // Save token for verification step
1838
+ localStorage.setItem('verificationToken', auth.token);
1839
+ window.location.href = '/verify-email';
1840
+ } else {
1841
+ // No verification needed - proceed normally
1842
+ setCustomerToken(auth.token);
1843
+ window.location.href = '/account';
1844
+ }
1689
1845
  } catch (err) {
1690
1846
  setError('Registration failed. Email may already be in use.');
1691
1847
  } finally {
@@ -1989,6 +2145,7 @@ When building a store, implement these pages:
1989
2145
  - [ ] **Checkout** (`/checkout`) - Multi-step checkout flow
1990
2146
  - [ ] **Login** (`/login`) - Customer login
1991
2147
  - [ ] **Register** (`/register`) - Customer registration
2148
+ - [ ] **Verify Email** (`/verify-email`) - Email verification with 6-digit code (if store requires it)
1992
2149
  - [ ] **Account** (`/account`) - Profile and order history
1993
2150
 
1994
2151
  ---
package/dist/index.d.mts CHANGED
@@ -1670,31 +1670,43 @@ declare class OmniSyncClient {
1670
1670
  }>;
1671
1671
  /**
1672
1672
  * Verify customer email with a verification code
1673
- * Requires a customer token to be set via setCustomerToken()
1674
1673
  * Only available in vibe-coded mode
1675
1674
  *
1675
+ * @param code - The 6-digit verification code from the email
1676
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1677
+ *
1676
1678
  * @example
1677
1679
  * ```typescript
1678
- * // After registration with requiresVerification: true
1680
+ * // Option 1: Pass token directly (recommended for verification flow)
1681
+ * const auth = await omni.registerCustomer({...});
1682
+ * if (auth.requiresVerification) {
1683
+ * const result = await omni.verifyEmail('123456', auth.token);
1684
+ * }
1685
+ *
1686
+ * // Option 2: Use setCustomerToken first
1679
1687
  * omni.setCustomerToken(auth.token);
1680
1688
  * const result = await omni.verifyEmail('123456');
1681
- * console.log(result.verified); // true
1682
1689
  * ```
1683
1690
  */
1684
- verifyEmail(code: string): Promise<EmailVerificationResponse>;
1691
+ verifyEmail(code: string, token?: string): Promise<EmailVerificationResponse>;
1685
1692
  /**
1686
1693
  * Resend verification email
1687
- * Requires a customer token to be set via setCustomerToken()
1688
1694
  * Only available in vibe-coded mode
1689
1695
  * Rate limited to 3 requests per hour
1690
1696
  *
1697
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1698
+ *
1691
1699
  * @example
1692
1700
  * ```typescript
1701
+ * // Option 1: Pass token directly
1702
+ * await omni.resendVerificationEmail(auth.token);
1703
+ *
1704
+ * // Option 2: Use setCustomerToken first
1693
1705
  * omni.setCustomerToken(auth.token);
1694
1706
  * await omni.resendVerificationEmail();
1695
1707
  * ```
1696
1708
  */
1697
- resendVerificationEmail(): Promise<{
1709
+ resendVerificationEmail(token?: string): Promise<{
1698
1710
  message: string;
1699
1711
  }>;
1700
1712
  /**
package/dist/index.d.ts CHANGED
@@ -1670,31 +1670,43 @@ declare class OmniSyncClient {
1670
1670
  }>;
1671
1671
  /**
1672
1672
  * Verify customer email with a verification code
1673
- * Requires a customer token to be set via setCustomerToken()
1674
1673
  * Only available in vibe-coded mode
1675
1674
  *
1675
+ * @param code - The 6-digit verification code from the email
1676
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1677
+ *
1676
1678
  * @example
1677
1679
  * ```typescript
1678
- * // After registration with requiresVerification: true
1680
+ * // Option 1: Pass token directly (recommended for verification flow)
1681
+ * const auth = await omni.registerCustomer({...});
1682
+ * if (auth.requiresVerification) {
1683
+ * const result = await omni.verifyEmail('123456', auth.token);
1684
+ * }
1685
+ *
1686
+ * // Option 2: Use setCustomerToken first
1679
1687
  * omni.setCustomerToken(auth.token);
1680
1688
  * const result = await omni.verifyEmail('123456');
1681
- * console.log(result.verified); // true
1682
1689
  * ```
1683
1690
  */
1684
- verifyEmail(code: string): Promise<EmailVerificationResponse>;
1691
+ verifyEmail(code: string, token?: string): Promise<EmailVerificationResponse>;
1685
1692
  /**
1686
1693
  * Resend verification email
1687
- * Requires a customer token to be set via setCustomerToken()
1688
1694
  * Only available in vibe-coded mode
1689
1695
  * Rate limited to 3 requests per hour
1690
1696
  *
1697
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1698
+ *
1691
1699
  * @example
1692
1700
  * ```typescript
1701
+ * // Option 1: Pass token directly
1702
+ * await omni.resendVerificationEmail(auth.token);
1703
+ *
1704
+ * // Option 2: Use setCustomerToken first
1693
1705
  * omni.setCustomerToken(auth.token);
1694
1706
  * await omni.resendVerificationEmail();
1695
1707
  * ```
1696
1708
  */
1697
- resendVerificationEmail(): Promise<{
1709
+ resendVerificationEmail(token?: string): Promise<{
1698
1710
  message: string;
1699
1711
  }>;
1700
1712
  /**
package/dist/index.js CHANGED
@@ -1097,48 +1097,95 @@ var OmniSyncClient = class {
1097
1097
  }
1098
1098
  /**
1099
1099
  * Verify customer email with a verification code
1100
- * Requires a customer token to be set via setCustomerToken()
1101
1100
  * Only available in vibe-coded mode
1102
1101
  *
1102
+ * @param code - The 6-digit verification code from the email
1103
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1104
+ *
1103
1105
  * @example
1104
1106
  * ```typescript
1105
- * // After registration with requiresVerification: true
1107
+ * // Option 1: Pass token directly (recommended for verification flow)
1108
+ * const auth = await omni.registerCustomer({...});
1109
+ * if (auth.requiresVerification) {
1110
+ * const result = await omni.verifyEmail('123456', auth.token);
1111
+ * }
1112
+ *
1113
+ * // Option 2: Use setCustomerToken first
1106
1114
  * omni.setCustomerToken(auth.token);
1107
1115
  * const result = await omni.verifyEmail('123456');
1108
- * console.log(result.verified); // true
1109
1116
  * ```
1110
1117
  */
1111
- async verifyEmail(code) {
1112
- if (!this.customerToken) {
1113
- throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1118
+ async verifyEmail(code, token) {
1119
+ const effectiveToken = token || this.customerToken;
1120
+ if (!effectiveToken) {
1121
+ throw new OmniSyncError(
1122
+ "Customer token is required. Pass token parameter or call setCustomerToken() first.",
1123
+ 401
1124
+ );
1114
1125
  }
1115
- if (this.isVibeCodedMode()) {
1116
- return this.vibeCodedRequest("POST", "/customers/verify-email", {
1117
- code
1118
- });
1126
+ const originalToken = this.customerToken;
1127
+ if (token) {
1128
+ this.customerToken = token;
1129
+ }
1130
+ try {
1131
+ if (this.isVibeCodedMode()) {
1132
+ return await this.vibeCodedRequest(
1133
+ "POST",
1134
+ "/customers/verify-email",
1135
+ {
1136
+ code
1137
+ }
1138
+ );
1139
+ }
1140
+ throw new OmniSyncError("verifyEmail is only available in vibe-coded mode", 400);
1141
+ } finally {
1142
+ if (token) {
1143
+ this.customerToken = originalToken;
1144
+ }
1119
1145
  }
1120
- throw new OmniSyncError("verifyEmail is only available in vibe-coded mode", 400);
1121
1146
  }
1122
1147
  /**
1123
1148
  * Resend verification email
1124
- * Requires a customer token to be set via setCustomerToken()
1125
1149
  * Only available in vibe-coded mode
1126
1150
  * Rate limited to 3 requests per hour
1127
1151
  *
1152
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1153
+ *
1128
1154
  * @example
1129
1155
  * ```typescript
1156
+ * // Option 1: Pass token directly
1157
+ * await omni.resendVerificationEmail(auth.token);
1158
+ *
1159
+ * // Option 2: Use setCustomerToken first
1130
1160
  * omni.setCustomerToken(auth.token);
1131
1161
  * await omni.resendVerificationEmail();
1132
1162
  * ```
1133
1163
  */
1134
- async resendVerificationEmail() {
1135
- if (!this.customerToken) {
1136
- throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1164
+ async resendVerificationEmail(token) {
1165
+ const effectiveToken = token || this.customerToken;
1166
+ if (!effectiveToken) {
1167
+ throw new OmniSyncError(
1168
+ "Customer token is required. Pass token parameter or call setCustomerToken() first.",
1169
+ 401
1170
+ );
1137
1171
  }
1138
- if (this.isVibeCodedMode()) {
1139
- return this.vibeCodedRequest("POST", "/customers/resend-verification");
1172
+ const originalToken = this.customerToken;
1173
+ if (token) {
1174
+ this.customerToken = token;
1175
+ }
1176
+ try {
1177
+ if (this.isVibeCodedMode()) {
1178
+ return await this.vibeCodedRequest(
1179
+ "POST",
1180
+ "/customers/resend-verification"
1181
+ );
1182
+ }
1183
+ throw new OmniSyncError("resendVerificationEmail is only available in vibe-coded mode", 400);
1184
+ } finally {
1185
+ if (token) {
1186
+ this.customerToken = originalToken;
1187
+ }
1140
1188
  }
1141
- throw new OmniSyncError("resendVerificationEmail is only available in vibe-coded mode", 400);
1142
1189
  }
1143
1190
  /**
1144
1191
  * Get the current logged-in customer's profile
package/dist/index.mjs CHANGED
@@ -1072,48 +1072,95 @@ var OmniSyncClient = class {
1072
1072
  }
1073
1073
  /**
1074
1074
  * Verify customer email with a verification code
1075
- * Requires a customer token to be set via setCustomerToken()
1076
1075
  * Only available in vibe-coded mode
1077
1076
  *
1077
+ * @param code - The 6-digit verification code from the email
1078
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1079
+ *
1078
1080
  * @example
1079
1081
  * ```typescript
1080
- * // After registration with requiresVerification: true
1082
+ * // Option 1: Pass token directly (recommended for verification flow)
1083
+ * const auth = await omni.registerCustomer({...});
1084
+ * if (auth.requiresVerification) {
1085
+ * const result = await omni.verifyEmail('123456', auth.token);
1086
+ * }
1087
+ *
1088
+ * // Option 2: Use setCustomerToken first
1081
1089
  * omni.setCustomerToken(auth.token);
1082
1090
  * const result = await omni.verifyEmail('123456');
1083
- * console.log(result.verified); // true
1084
1091
  * ```
1085
1092
  */
1086
- async verifyEmail(code) {
1087
- if (!this.customerToken) {
1088
- throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1093
+ async verifyEmail(code, token) {
1094
+ const effectiveToken = token || this.customerToken;
1095
+ if (!effectiveToken) {
1096
+ throw new OmniSyncError(
1097
+ "Customer token is required. Pass token parameter or call setCustomerToken() first.",
1098
+ 401
1099
+ );
1089
1100
  }
1090
- if (this.isVibeCodedMode()) {
1091
- return this.vibeCodedRequest("POST", "/customers/verify-email", {
1092
- code
1093
- });
1101
+ const originalToken = this.customerToken;
1102
+ if (token) {
1103
+ this.customerToken = token;
1104
+ }
1105
+ try {
1106
+ if (this.isVibeCodedMode()) {
1107
+ return await this.vibeCodedRequest(
1108
+ "POST",
1109
+ "/customers/verify-email",
1110
+ {
1111
+ code
1112
+ }
1113
+ );
1114
+ }
1115
+ throw new OmniSyncError("verifyEmail is only available in vibe-coded mode", 400);
1116
+ } finally {
1117
+ if (token) {
1118
+ this.customerToken = originalToken;
1119
+ }
1094
1120
  }
1095
- throw new OmniSyncError("verifyEmail is only available in vibe-coded mode", 400);
1096
1121
  }
1097
1122
  /**
1098
1123
  * Resend verification email
1099
- * Requires a customer token to be set via setCustomerToken()
1100
1124
  * Only available in vibe-coded mode
1101
1125
  * Rate limited to 3 requests per hour
1102
1126
  *
1127
+ * @param token - Optional customer token. If not provided, uses the token set via setCustomerToken()
1128
+ *
1103
1129
  * @example
1104
1130
  * ```typescript
1131
+ * // Option 1: Pass token directly
1132
+ * await omni.resendVerificationEmail(auth.token);
1133
+ *
1134
+ * // Option 2: Use setCustomerToken first
1105
1135
  * omni.setCustomerToken(auth.token);
1106
1136
  * await omni.resendVerificationEmail();
1107
1137
  * ```
1108
1138
  */
1109
- async resendVerificationEmail() {
1110
- if (!this.customerToken) {
1111
- throw new OmniSyncError("Customer token is required. Call setCustomerToken() first.", 401);
1139
+ async resendVerificationEmail(token) {
1140
+ const effectiveToken = token || this.customerToken;
1141
+ if (!effectiveToken) {
1142
+ throw new OmniSyncError(
1143
+ "Customer token is required. Pass token parameter or call setCustomerToken() first.",
1144
+ 401
1145
+ );
1112
1146
  }
1113
- if (this.isVibeCodedMode()) {
1114
- return this.vibeCodedRequest("POST", "/customers/resend-verification");
1147
+ const originalToken = this.customerToken;
1148
+ if (token) {
1149
+ this.customerToken = token;
1150
+ }
1151
+ try {
1152
+ if (this.isVibeCodedMode()) {
1153
+ return await this.vibeCodedRequest(
1154
+ "POST",
1155
+ "/customers/resend-verification"
1156
+ );
1157
+ }
1158
+ throw new OmniSyncError("resendVerificationEmail is only available in vibe-coded mode", 400);
1159
+ } finally {
1160
+ if (token) {
1161
+ this.customerToken = originalToken;
1162
+ }
1115
1163
  }
1116
- throw new OmniSyncError("resendVerificationEmail is only available in vibe-coded mode", 400);
1117
1164
  }
1118
1165
  /**
1119
1166
  * Get the current logged-in customer's profile
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omni-sync-sdk",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
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",
@@ -16,6 +16,14 @@
16
16
  "dist",
17
17
  "README.md"
18
18
  ],
19
+ "scripts": {
20
+ "build": "tsup src/index.ts --format cjs,esm --dts",
21
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
22
+ "lint": "eslint \"src/**/*.ts\"",
23
+ "test": "vitest run",
24
+ "test:watch": "vitest",
25
+ "prepublishOnly": "pnpm build"
26
+ },
19
27
  "keywords": [
20
28
  "omni-sync",
21
29
  "e-commerce",
@@ -64,12 +72,5 @@
64
72
  "typescript": {
65
73
  "optional": true
66
74
  }
67
- },
68
- "scripts": {
69
- "build": "tsup src/index.ts --format cjs,esm --dts",
70
- "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
71
- "lint": "eslint \"src/**/*.ts\"",
72
- "test": "vitest run",
73
- "test:watch": "vitest"
74
75
  }
75
- }
76
+ }
package/LICENSE DELETED
File without changes