@insforge/nextjs 0.7.0 → 0.7.1

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/dist/index.mjs CHANGED
@@ -59,9 +59,8 @@ function InsforgeProvider({
59
59
  const userData = {
60
60
  id: cachedData.user.id,
61
61
  email: cachedData.user.email,
62
- createdAt: cachedData.user.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
63
- updatedAt: cachedData.user.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
64
- ...cachedData.profile
62
+ name: cachedData.profile?.nickname || "",
63
+ avatarUrl: cachedData.profile?.avatar_url || ""
65
64
  };
66
65
  setUser(userData);
67
66
  setSession({
@@ -88,9 +87,8 @@ function InsforgeProvider({
88
87
  const userData = {
89
88
  id: userResult.data.user.id,
90
89
  email: userResult.data.user.email,
91
- createdAt: userResult.data.user.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
92
- updatedAt: userResult.data.user.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
93
- ...userResult.data.profile
90
+ name: userResult.data.profile?.nickname || "",
91
+ avatarUrl: userResult.data.profile?.avatar_url || ""
94
92
  };
95
93
  setUser(userData);
96
94
  setSession({
@@ -141,120 +139,90 @@ function InsforgeProvider({
141
139
  }
142
140
  };
143
141
  }, []);
142
+ const handleAuthSuccess = useCallback(
143
+ async (authToken, fallbackUser) => {
144
+ const userResult = await insforge.auth.getCurrentUser();
145
+ if (userResult.data) {
146
+ const userData = {
147
+ id: userResult.data.user.id,
148
+ email: userResult.data.user.email,
149
+ name: userResult.data.profile?.nickname || "",
150
+ avatarUrl: userResult.data.profile?.avatar_url || ""
151
+ };
152
+ const sessionData = {
153
+ userId: userResult.data.user.id,
154
+ token: authToken,
155
+ expiresAt: "",
156
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
157
+ };
158
+ setUser(userData);
159
+ setSession(sessionData);
160
+ localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
161
+ if (onAuthChange) {
162
+ onAuthChange(userData);
163
+ }
164
+ try {
165
+ await syncTokenToCookie(authToken);
166
+ } catch (error) {
167
+ }
168
+ } else if (fallbackUser) {
169
+ const userData = {
170
+ id: fallbackUser.id || "",
171
+ email: fallbackUser.email || "",
172
+ name: fallbackUser.name || "",
173
+ avatarUrl: ""
174
+ };
175
+ setUser(userData);
176
+ setSession({
177
+ userId: fallbackUser.id || "",
178
+ token: authToken,
179
+ expiresAt: "",
180
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
181
+ });
182
+ if (onAuthChange) {
183
+ onAuthChange(userData);
184
+ }
185
+ }
186
+ },
187
+ [insforge, onAuthChange]
188
+ );
144
189
  const signIn = useCallback(
145
190
  async (email, password) => {
146
191
  const sdkResult = await insforge.auth.signInWithPassword({ email, password });
147
192
  if (sdkResult.data) {
148
- const userResult = await insforge.auth.getCurrentUser();
149
- if (userResult.data) {
150
- const userData = {
151
- id: userResult.data.user.id,
152
- email: userResult.data.user.email,
153
- name: userResult.data.user.name || void 0,
154
- createdAt: userResult.data.user.createdAt,
155
- updatedAt: userResult.data.user.updatedAt,
156
- ...userResult.data.profile
157
- // Include profile fields (nickname, avatar_url, etc.)
158
- };
159
- const sessionData = {
160
- userId: userResult.data.user.id,
161
- token: sdkResult.data.accessToken || "",
162
- expiresAt: "",
163
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
164
- };
165
- setUser(userData);
166
- setSession(sessionData);
167
- localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
168
- if (onAuthChange) {
169
- onAuthChange(userData);
170
- }
171
- try {
172
- await syncTokenToCookie(sdkResult.data.accessToken || "");
173
- } catch (error) {
174
- console.error("Please add /api/auth route to your server to sync token to cookie:", error);
175
- }
176
- } else {
177
- const userData = {
193
+ await handleAuthSuccess(
194
+ sdkResult.data.accessToken || "",
195
+ sdkResult.data.user ? {
178
196
  id: sdkResult.data.user.id,
179
197
  email: sdkResult.data.user.email,
180
- name: sdkResult.data.user.name || void 0,
181
- createdAt: sdkResult.data.user.createdAt,
182
- updatedAt: sdkResult.data.user.updatedAt
183
- };
184
- setUser(userData);
185
- setSession({
186
- userId: sdkResult.data.user.id,
187
- token: sdkResult.data.accessToken || "",
188
- expiresAt: "",
189
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
190
- });
191
- if (onAuthChange) {
192
- onAuthChange(userData);
193
- }
194
- }
198
+ name: sdkResult.data.user.name
199
+ } : void 0
200
+ );
195
201
  } else {
196
202
  const errorMessage = sdkResult.error?.message || "Invalid email or password";
197
203
  throw new Error(errorMessage);
198
204
  }
199
205
  },
200
- [insforge, onAuthChange]
206
+ [insforge, handleAuthSuccess]
201
207
  );
202
208
  const signUp = useCallback(
203
209
  async (email, password) => {
204
210
  const sdkResult = await insforge.auth.signUp({ email, password });
205
211
  if (sdkResult.data) {
206
- const userResult = await insforge.auth.getCurrentUser();
207
- if (userResult.data) {
208
- const userData = {
209
- id: userResult.data.user.id,
210
- email: userResult.data.user.email,
211
- name: userResult.data.user.name || void 0,
212
- createdAt: userResult.data.user.createdAt,
213
- updatedAt: userResult.data.user.updatedAt,
214
- ...userResult.data.profile
215
- // Include profile fields (nickname, avatar_url, etc.)
216
- };
217
- const sessionData = {
218
- userId: userResult.data.user.id,
219
- token: sdkResult.data.accessToken || "",
220
- expiresAt: "",
221
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
222
- };
223
- setUser(userData);
224
- setSession(sessionData);
225
- localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
226
- if (onAuthChange) {
227
- onAuthChange(userData);
228
- }
229
- try {
230
- await syncTokenToCookie(sdkResult.data.accessToken || "");
231
- } catch (error) {
232
- }
233
- } else {
234
- const userData = {
212
+ await handleAuthSuccess(
213
+ sdkResult.data.accessToken || "",
214
+ sdkResult.data.user ? {
235
215
  id: sdkResult.data.user.id,
236
216
  email: sdkResult.data.user.email,
237
- name: sdkResult.data.user.name || void 0,
238
- createdAt: sdkResult.data.user.createdAt,
239
- updatedAt: sdkResult.data.user.updatedAt
240
- };
241
- setUser(userData);
242
- setSession({
243
- userId: sdkResult.data.user.id,
244
- token: sdkResult.data.accessToken || "",
245
- expiresAt: "",
246
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
247
- });
248
- if (onAuthChange) {
249
- onAuthChange(userData);
250
- }
251
- }
217
+ name: sdkResult.data.user.name
218
+ } : void 0
219
+ );
252
220
  } else {
253
221
  const errorMessage = sdkResult.error?.message || "Sign up failed";
254
222
  throw new Error(errorMessage);
255
223
  }
256
224
  },
257
- [insforge, onAuthChange]
225
+ [insforge, handleAuthSuccess]
258
226
  );
259
227
  const signOut = useCallback(async () => {
260
228
  await insforge.auth.signOut();
@@ -273,7 +241,10 @@ function InsforgeProvider({
273
241
  const updateUser = useCallback(
274
242
  async (data) => {
275
243
  if (!user) throw new Error("No user signed in");
276
- const result = await insforge.auth.setProfile(data);
244
+ const result = await insforge.auth.setProfile({
245
+ nickname: data.name || "",
246
+ avatar_url: data.avatarUrl || ""
247
+ });
277
248
  if (result.data) {
278
249
  const updatedUser = { ...user, ...result.data };
279
250
  setUser(updatedUser);
@@ -336,8 +307,8 @@ function useSession() {
336
307
  }
337
308
 
338
309
  // src/components/SignIn.tsx
339
- import { useState as useState4 } from "react";
340
- import { createClient as createClient3 } from "@insforge/sdk";
310
+ import { useState as useState5 } from "react";
311
+ import { createClient as createClient4 } from "@insforge/sdk";
341
312
 
342
313
  // src/hooks/useOAuthProviders.ts
343
314
  import { useState as useState2, useEffect as useEffect2 } from "react";
@@ -357,8 +328,8 @@ function useOAuthProviders() {
357
328
  console.warn("[useOAuthProviders] Failed to fetch OAuth providers:", error);
358
329
  setProviders([]);
359
330
  } else if (data) {
360
- const configuredProviders = data.filter((p) => p.isConfigured).map((p) => p.provider);
361
- setProviders(configuredProviders);
331
+ const providerNames = data.map((p) => p.provider);
332
+ setProviders(providerNames);
362
333
  } else {
363
334
  setProviders([]);
364
335
  }
@@ -379,6 +350,43 @@ function useOAuthProviders() {
379
350
  return { providers, isLoaded };
380
351
  }
381
352
 
353
+ // src/hooks/useEmailAuthConfig.ts
354
+ import { useState as useState3, useEffect as useEffect3 } from "react";
355
+ import { createClient as createClient3 } from "@insforge/sdk";
356
+ function useEmailAuthConfig() {
357
+ const { baseUrl } = useInsforge();
358
+ const [config, setConfig] = useState3(null);
359
+ const [isLoaded, setIsLoaded] = useState3(false);
360
+ useEffect3(() => {
361
+ let mounted = true;
362
+ async function fetchConfig() {
363
+ try {
364
+ const insforge = createClient3({ baseUrl });
365
+ const { data, error } = await insforge.auth.getEmailAuthConfig();
366
+ if (!mounted) return;
367
+ if (error) {
368
+ console.warn("[useEmailAuthConfig] Failed to fetch email auth config:", error);
369
+ setConfig(null);
370
+ } else {
371
+ setConfig(data);
372
+ }
373
+ setIsLoaded(true);
374
+ } catch (error) {
375
+ console.warn("[useEmailAuthConfig] Unexpected error:", error);
376
+ if (mounted) {
377
+ setConfig(null);
378
+ setIsLoaded(true);
379
+ }
380
+ }
381
+ }
382
+ fetchConfig();
383
+ return () => {
384
+ mounted = false;
385
+ };
386
+ }, [baseUrl]);
387
+ return { config, isLoaded };
388
+ }
389
+
382
390
  // src/components/auth/AuthBranding.tsx
383
391
  import Link from "next/link";
384
392
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -489,35 +497,59 @@ function AuthFormField({ label, id, className = "", ...props }) {
489
497
  }
490
498
 
491
499
  // src/components/auth/AuthPasswordField.tsx
492
- import { useState as useState3 } from "react";
500
+ import { useState as useState4 } from "react";
493
501
  import { Eye, EyeOff } from "lucide-react";
494
502
 
495
503
  // src/components/auth/AuthPasswordStrengthIndicator.tsx
496
504
  import { Check } from "lucide-react";
497
505
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
498
- var requirements = [
499
- {
500
- label: "At least 1 Uppercase letter",
501
- test: (pwd) => /[A-Z]/.test(pwd)
502
- },
503
- {
504
- label: "At least 1 Number",
505
- test: (pwd) => /\d/.test(pwd)
506
- },
507
- {
508
- label: "Special character (e.g. !?<>@#$%)",
509
- test: (pwd) => /[!@#$%^&*()_+\-=[\]{};\\|,.<>/?]/.test(pwd)
510
- },
511
- {
512
- label: "8 characters or more",
513
- test: (pwd) => pwd.length >= 8
506
+ function createRequirements(config) {
507
+ const requirements = [];
508
+ const minLength = config.passwordMinLength;
509
+ const requireUppercase = config.requireUppercase;
510
+ const requireLowercase = config.requireLowercase;
511
+ const requireNumber = config.requireNumber;
512
+ const requireSpecialChar = config.requireSpecialChar;
513
+ if (requireUppercase) {
514
+ requirements.push({
515
+ label: "At least 1 Uppercase letter",
516
+ test: (pwd) => /[A-Z]/.test(pwd)
517
+ });
518
+ }
519
+ if (requireLowercase) {
520
+ requirements.push({
521
+ label: "At least 1 Lowercase letter",
522
+ test: (pwd) => /[a-z]/.test(pwd)
523
+ });
524
+ }
525
+ if (requireNumber) {
526
+ requirements.push({
527
+ label: "At least 1 Number",
528
+ test: (pwd) => /\d/.test(pwd)
529
+ });
530
+ }
531
+ if (requireSpecialChar) {
532
+ requirements.push({
533
+ label: "Special character (e.g. !?<>@#$%)",
534
+ test: (pwd) => /[!@#$%^&*()_+\-=[\]{};\\|,.<>/?]/.test(pwd)
535
+ });
514
536
  }
515
- ];
516
- function validatePasswordStrength(password) {
537
+ requirements.push({
538
+ label: `${minLength} characters or more`,
539
+ test: (pwd) => pwd.length >= minLength
540
+ });
541
+ return requirements;
542
+ }
543
+ function validatePasswordStrength(password, config) {
517
544
  if (!password) return false;
545
+ const requirements = createRequirements(config);
518
546
  return requirements.every((req) => req.test(password));
519
547
  }
520
- function AuthPasswordStrengthIndicator({ password }) {
548
+ function AuthPasswordStrengthIndicator({
549
+ password,
550
+ config
551
+ }) {
552
+ const requirements = createRequirements(config);
521
553
  return /* @__PURE__ */ jsx7("div", { className: "insforge-password-strength", children: requirements.map((requirement, index) => {
522
554
  const isValid = requirement.test(password);
523
555
  return /* @__PURE__ */ jsxs6("div", { className: "insforge-password-requirement", children: [
@@ -539,14 +571,15 @@ function AuthPasswordField({
539
571
  label,
540
572
  id,
541
573
  showStrengthIndicator = false,
574
+ emailAuthConfig,
542
575
  forgotPasswordLink,
543
576
  value,
544
577
  className = "",
545
578
  onFocus,
546
579
  ...props
547
580
  }) {
548
- const [showPassword, setShowPassword] = useState3(false);
549
- const [showStrength, setShowStrength] = useState3(false);
581
+ const [showPassword, setShowPassword] = useState4(false);
582
+ const [showStrength, setShowStrength] = useState4(false);
550
583
  const handleFocus = (e) => {
551
584
  if (showStrengthIndicator) {
552
585
  setShowStrength(true);
@@ -581,7 +614,13 @@ function AuthPasswordField({
581
614
  }
582
615
  )
583
616
  ] }),
584
- showStrengthIndicator && showStrength && /* @__PURE__ */ jsx8(AuthPasswordStrengthIndicator, { password: String(value || "") })
617
+ showStrengthIndicator && showStrength && /* @__PURE__ */ jsx8(
618
+ AuthPasswordStrengthIndicator,
619
+ {
620
+ password: String(value || ""),
621
+ config: emailAuthConfig
622
+ }
623
+ )
585
624
  ] });
586
625
  }
587
626
 
@@ -968,12 +1007,13 @@ function SignIn({
968
1007
  }) {
969
1008
  const { signIn, baseUrl } = useInsforge();
970
1009
  const { providers: oauthProviders } = useOAuthProviders();
971
- const [email, setEmail] = useState4("");
972
- const [password, setPassword] = useState4("");
973
- const [error, setError] = useState4("");
974
- const [loading, setLoading] = useState4(false);
975
- const [oauthLoading, setOauthLoading] = useState4(null);
976
- const insforge = useState4(() => createClient3({ baseUrl }))[0];
1010
+ const { config: emailAuthConfig } = useEmailAuthConfig();
1011
+ const [email, setEmail] = useState5("");
1012
+ const [password, setPassword] = useState5("");
1013
+ const [error, setError] = useState5("");
1014
+ const [loading, setLoading] = useState5(false);
1015
+ const [oauthLoading, setOauthLoading] = useState5(null);
1016
+ const insforge = useState5(() => createClient4({ baseUrl }))[0];
977
1017
  async function handleSubmit(e) {
978
1018
  e.preventDefault();
979
1019
  setLoading(true);
@@ -1035,7 +1075,15 @@ function SignIn({
1035
1075
  value: password,
1036
1076
  onChange: (e) => setPassword(e.target.value),
1037
1077
  required: true,
1038
- autoComplete: "current-password"
1078
+ autoComplete: "current-password",
1079
+ emailAuthConfig: emailAuthConfig || {
1080
+ requireEmailVerification: false,
1081
+ passwordMinLength: 6,
1082
+ requireNumber: false,
1083
+ requireLowercase: false,
1084
+ requireUppercase: false,
1085
+ requireSpecialChar: false
1086
+ }
1039
1087
  }
1040
1088
  ),
1041
1089
  /* @__PURE__ */ jsx16(
@@ -1065,8 +1113,8 @@ function SignIn({
1065
1113
  }
1066
1114
 
1067
1115
  // src/components/SignUp.tsx
1068
- import { useState as useState5 } from "react";
1069
- import { createClient as createClient4 } from "@insforge/sdk";
1116
+ import { useState as useState6 } from "react";
1117
+ import { createClient as createClient5 } from "@insforge/sdk";
1070
1118
  import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
1071
1119
  function SignUp({
1072
1120
  afterSignUpUrl = "/",
@@ -1091,17 +1139,18 @@ function SignUp({
1091
1139
  }) {
1092
1140
  const { signUp, baseUrl } = useInsforge();
1093
1141
  const { providers: oauthProviders } = useOAuthProviders();
1094
- const [email, setEmail] = useState5("");
1095
- const [password, setPassword] = useState5("");
1096
- const [error, setError] = useState5("");
1097
- const [loading, setLoading] = useState5(false);
1098
- const [oauthLoading, setOauthLoading] = useState5(null);
1099
- const insforge = useState5(() => createClient4({ baseUrl }))[0];
1142
+ const { config: emailAuthConfig } = useEmailAuthConfig();
1143
+ const [email, setEmail] = useState6("");
1144
+ const [password, setPassword] = useState6("");
1145
+ const [error, setError] = useState6("");
1146
+ const [loading, setLoading] = useState6(false);
1147
+ const [oauthLoading, setOauthLoading] = useState6(null);
1148
+ const insforge = useState6(() => createClient5({ baseUrl }))[0];
1100
1149
  async function handleCredentialsSubmit(e) {
1101
1150
  e.preventDefault();
1102
1151
  setLoading(true);
1103
1152
  setError("");
1104
- if (!validatePasswordStrength(password)) {
1153
+ if (emailAuthConfig && !validatePasswordStrength(password, emailAuthConfig)) {
1105
1154
  setError("Password does not meet all requirements");
1106
1155
  setLoading(false);
1107
1156
  return;
@@ -1166,9 +1215,17 @@ function SignUp({
1166
1215
  value: password,
1167
1216
  onChange: (e) => setPassword(e.target.value),
1168
1217
  required: true,
1169
- minLength: 8,
1218
+ minLength: emailAuthConfig?.passwordMinLength ?? 8,
1170
1219
  autoComplete: "new-password",
1171
- showStrengthIndicator: true
1220
+ showStrengthIndicator: true,
1221
+ emailAuthConfig: emailAuthConfig || {
1222
+ requireEmailVerification: false,
1223
+ passwordMinLength: 6,
1224
+ requireNumber: false,
1225
+ requireLowercase: false,
1226
+ requireUppercase: false,
1227
+ requireSpecialChar: false
1228
+ }
1172
1229
  }
1173
1230
  ),
1174
1231
  /* @__PURE__ */ jsx17(
@@ -1205,7 +1262,7 @@ function SignUp({
1205
1262
  }
1206
1263
 
1207
1264
  // src/components/UserButton.tsx
1208
- import { useState as useState6, useRef as useRef3, useEffect as useEffect3 } from "react";
1265
+ import { useState as useState7, useRef as useRef3, useEffect as useEffect4 } from "react";
1209
1266
  import { LogOut } from "lucide-react";
1210
1267
  import { jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
1211
1268
  function UserButton({
@@ -1214,9 +1271,9 @@ function UserButton({
1214
1271
  appearance = {}
1215
1272
  }) {
1216
1273
  const { user, signOut } = useInsforge();
1217
- const [isOpen, setIsOpen] = useState6(false);
1274
+ const [isOpen, setIsOpen] = useState7(false);
1218
1275
  const dropdownRef = useRef3(null);
1219
- useEffect3(() => {
1276
+ useEffect4(() => {
1220
1277
  function handleClickOutside(event) {
1221
1278
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1222
1279
  setIsOpen(false);
@@ -1281,7 +1338,7 @@ function SignedOut({ children }) {
1281
1338
  }
1282
1339
 
1283
1340
  // src/components/Protect.tsx
1284
- import { useEffect as useEffect4 } from "react";
1341
+ import { useEffect as useEffect5 } from "react";
1285
1342
  import { useRouter } from "next/navigation";
1286
1343
  import { Fragment as Fragment5, jsx as jsx21 } from "react/jsx-runtime";
1287
1344
  function Protect({
@@ -1292,7 +1349,7 @@ function Protect({
1292
1349
  }) {
1293
1350
  const { isSignedIn, isLoaded, user } = useInsforge();
1294
1351
  const router = useRouter();
1295
- useEffect4(() => {
1352
+ useEffect5(() => {
1296
1353
  if (isLoaded && !isSignedIn) {
1297
1354
  router.push(redirectTo);
1298
1355
  } else if (isLoaded && isSignedIn && condition && user) {