@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.js CHANGED
@@ -123,9 +123,8 @@ function InsforgeProvider({
123
123
  const userData = {
124
124
  id: cachedData.user.id,
125
125
  email: cachedData.user.email,
126
- createdAt: cachedData.user.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
127
- updatedAt: cachedData.user.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
128
- ...cachedData.profile
126
+ name: cachedData.profile?.nickname || "",
127
+ avatarUrl: cachedData.profile?.avatar_url || ""
129
128
  };
130
129
  setUser(userData);
131
130
  setSession({
@@ -152,9 +151,8 @@ function InsforgeProvider({
152
151
  const userData = {
153
152
  id: userResult.data.user.id,
154
153
  email: userResult.data.user.email,
155
- createdAt: userResult.data.user.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
156
- updatedAt: userResult.data.user.updatedAt || (/* @__PURE__ */ new Date()).toISOString(),
157
- ...userResult.data.profile
154
+ name: userResult.data.profile?.nickname || "",
155
+ avatarUrl: userResult.data.profile?.avatar_url || ""
158
156
  };
159
157
  setUser(userData);
160
158
  setSession({
@@ -205,120 +203,90 @@ function InsforgeProvider({
205
203
  }
206
204
  };
207
205
  }, []);
206
+ const handleAuthSuccess = (0, import_react.useCallback)(
207
+ async (authToken, fallbackUser) => {
208
+ const userResult = await insforge.auth.getCurrentUser();
209
+ if (userResult.data) {
210
+ const userData = {
211
+ id: userResult.data.user.id,
212
+ email: userResult.data.user.email,
213
+ name: userResult.data.profile?.nickname || "",
214
+ avatarUrl: userResult.data.profile?.avatar_url || ""
215
+ };
216
+ const sessionData = {
217
+ userId: userResult.data.user.id,
218
+ token: authToken,
219
+ expiresAt: "",
220
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
221
+ };
222
+ setUser(userData);
223
+ setSession(sessionData);
224
+ localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
225
+ if (onAuthChange) {
226
+ onAuthChange(userData);
227
+ }
228
+ try {
229
+ await syncTokenToCookie(authToken);
230
+ } catch (error) {
231
+ }
232
+ } else if (fallbackUser) {
233
+ const userData = {
234
+ id: fallbackUser.id || "",
235
+ email: fallbackUser.email || "",
236
+ name: fallbackUser.name || "",
237
+ avatarUrl: ""
238
+ };
239
+ setUser(userData);
240
+ setSession({
241
+ userId: fallbackUser.id || "",
242
+ token: authToken,
243
+ expiresAt: "",
244
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
245
+ });
246
+ if (onAuthChange) {
247
+ onAuthChange(userData);
248
+ }
249
+ }
250
+ },
251
+ [insforge, onAuthChange]
252
+ );
208
253
  const signIn = (0, import_react.useCallback)(
209
254
  async (email, password) => {
210
255
  const sdkResult = await insforge.auth.signInWithPassword({ email, password });
211
256
  if (sdkResult.data) {
212
- const userResult = await insforge.auth.getCurrentUser();
213
- if (userResult.data) {
214
- const userData = {
215
- id: userResult.data.user.id,
216
- email: userResult.data.user.email,
217
- name: userResult.data.user.name || void 0,
218
- createdAt: userResult.data.user.createdAt,
219
- updatedAt: userResult.data.user.updatedAt,
220
- ...userResult.data.profile
221
- // Include profile fields (nickname, avatar_url, etc.)
222
- };
223
- const sessionData = {
224
- userId: userResult.data.user.id,
225
- token: sdkResult.data.accessToken || "",
226
- expiresAt: "",
227
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
228
- };
229
- setUser(userData);
230
- setSession(sessionData);
231
- localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
232
- if (onAuthChange) {
233
- onAuthChange(userData);
234
- }
235
- try {
236
- await syncTokenToCookie(sdkResult.data.accessToken || "");
237
- } catch (error) {
238
- console.error("Please add /api/auth route to your server to sync token to cookie:", error);
239
- }
240
- } else {
241
- const userData = {
257
+ await handleAuthSuccess(
258
+ sdkResult.data.accessToken || "",
259
+ sdkResult.data.user ? {
242
260
  id: sdkResult.data.user.id,
243
261
  email: sdkResult.data.user.email,
244
- name: sdkResult.data.user.name || void 0,
245
- createdAt: sdkResult.data.user.createdAt,
246
- updatedAt: sdkResult.data.user.updatedAt
247
- };
248
- setUser(userData);
249
- setSession({
250
- userId: sdkResult.data.user.id,
251
- token: sdkResult.data.accessToken || "",
252
- expiresAt: "",
253
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
254
- });
255
- if (onAuthChange) {
256
- onAuthChange(userData);
257
- }
258
- }
262
+ name: sdkResult.data.user.name
263
+ } : void 0
264
+ );
259
265
  } else {
260
266
  const errorMessage = sdkResult.error?.message || "Invalid email or password";
261
267
  throw new Error(errorMessage);
262
268
  }
263
269
  },
264
- [insforge, onAuthChange]
270
+ [insforge, handleAuthSuccess]
265
271
  );
266
272
  const signUp = (0, import_react.useCallback)(
267
273
  async (email, password) => {
268
274
  const sdkResult = await insforge.auth.signUp({ email, password });
269
275
  if (sdkResult.data) {
270
- const userResult = await insforge.auth.getCurrentUser();
271
- if (userResult.data) {
272
- const userData = {
273
- id: userResult.data.user.id,
274
- email: userResult.data.user.email,
275
- name: userResult.data.user.name || void 0,
276
- createdAt: userResult.data.user.createdAt,
277
- updatedAt: userResult.data.user.updatedAt,
278
- ...userResult.data.profile
279
- // Include profile fields (nickname, avatar_url, etc.)
280
- };
281
- const sessionData = {
282
- userId: userResult.data.user.id,
283
- token: sdkResult.data.accessToken || "",
284
- expiresAt: "",
285
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
286
- };
287
- setUser(userData);
288
- setSession(sessionData);
289
- localStorage.setItem("insforge-user-profile", JSON.stringify(userResult.data));
290
- if (onAuthChange) {
291
- onAuthChange(userData);
292
- }
293
- try {
294
- await syncTokenToCookie(sdkResult.data.accessToken || "");
295
- } catch (error) {
296
- }
297
- } else {
298
- const userData = {
276
+ await handleAuthSuccess(
277
+ sdkResult.data.accessToken || "",
278
+ sdkResult.data.user ? {
299
279
  id: sdkResult.data.user.id,
300
280
  email: sdkResult.data.user.email,
301
- name: sdkResult.data.user.name || void 0,
302
- createdAt: sdkResult.data.user.createdAt,
303
- updatedAt: sdkResult.data.user.updatedAt
304
- };
305
- setUser(userData);
306
- setSession({
307
- userId: sdkResult.data.user.id,
308
- token: sdkResult.data.accessToken || "",
309
- expiresAt: "",
310
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
311
- });
312
- if (onAuthChange) {
313
- onAuthChange(userData);
314
- }
315
- }
281
+ name: sdkResult.data.user.name
282
+ } : void 0
283
+ );
316
284
  } else {
317
285
  const errorMessage = sdkResult.error?.message || "Sign up failed";
318
286
  throw new Error(errorMessage);
319
287
  }
320
288
  },
321
- [insforge, onAuthChange]
289
+ [insforge, handleAuthSuccess]
322
290
  );
323
291
  const signOut = (0, import_react.useCallback)(async () => {
324
292
  await insforge.auth.signOut();
@@ -337,7 +305,10 @@ function InsforgeProvider({
337
305
  const updateUser = (0, import_react.useCallback)(
338
306
  async (data) => {
339
307
  if (!user) throw new Error("No user signed in");
340
- const result = await insforge.auth.setProfile(data);
308
+ const result = await insforge.auth.setProfile({
309
+ nickname: data.name || "",
310
+ avatar_url: data.avatarUrl || ""
311
+ });
341
312
  if (result.data) {
342
313
  const updatedUser = { ...user, ...result.data };
343
314
  setUser(updatedUser);
@@ -400,8 +371,8 @@ function useSession() {
400
371
  }
401
372
 
402
373
  // src/components/SignIn.tsx
403
- var import_react5 = require("react");
404
- var import_sdk3 = require("@insforge/sdk");
374
+ var import_react6 = require("react");
375
+ var import_sdk4 = require("@insforge/sdk");
405
376
 
406
377
  // src/hooks/useOAuthProviders.ts
407
378
  var import_react2 = require("react");
@@ -421,8 +392,8 @@ function useOAuthProviders() {
421
392
  console.warn("[useOAuthProviders] Failed to fetch OAuth providers:", error);
422
393
  setProviders([]);
423
394
  } else if (data) {
424
- const configuredProviders = data.filter((p) => p.isConfigured).map((p) => p.provider);
425
- setProviders(configuredProviders);
395
+ const providerNames = data.map((p) => p.provider);
396
+ setProviders(providerNames);
426
397
  } else {
427
398
  setProviders([]);
428
399
  }
@@ -443,6 +414,43 @@ function useOAuthProviders() {
443
414
  return { providers, isLoaded };
444
415
  }
445
416
 
417
+ // src/hooks/useEmailAuthConfig.ts
418
+ var import_react3 = require("react");
419
+ var import_sdk3 = require("@insforge/sdk");
420
+ function useEmailAuthConfig() {
421
+ const { baseUrl } = useInsforge();
422
+ const [config, setConfig] = (0, import_react3.useState)(null);
423
+ const [isLoaded, setIsLoaded] = (0, import_react3.useState)(false);
424
+ (0, import_react3.useEffect)(() => {
425
+ let mounted = true;
426
+ async function fetchConfig() {
427
+ try {
428
+ const insforge = (0, import_sdk3.createClient)({ baseUrl });
429
+ const { data, error } = await insforge.auth.getEmailAuthConfig();
430
+ if (!mounted) return;
431
+ if (error) {
432
+ console.warn("[useEmailAuthConfig] Failed to fetch email auth config:", error);
433
+ setConfig(null);
434
+ } else {
435
+ setConfig(data);
436
+ }
437
+ setIsLoaded(true);
438
+ } catch (error) {
439
+ console.warn("[useEmailAuthConfig] Unexpected error:", error);
440
+ if (mounted) {
441
+ setConfig(null);
442
+ setIsLoaded(true);
443
+ }
444
+ }
445
+ }
446
+ fetchConfig();
447
+ return () => {
448
+ mounted = false;
449
+ };
450
+ }, [baseUrl]);
451
+ return { config, isLoaded };
452
+ }
453
+
446
454
  // src/components/auth/AuthBranding.tsx
447
455
  var import_link = __toESM(require("next/link"));
448
456
  var import_jsx_runtime2 = require("react/jsx-runtime");
@@ -553,35 +561,59 @@ function AuthFormField({ label, id, className = "", ...props }) {
553
561
  }
554
562
 
555
563
  // src/components/auth/AuthPasswordField.tsx
556
- var import_react3 = require("react");
564
+ var import_react4 = require("react");
557
565
  var import_lucide_react3 = require("lucide-react");
558
566
 
559
567
  // src/components/auth/AuthPasswordStrengthIndicator.tsx
560
568
  var import_lucide_react2 = require("lucide-react");
561
569
  var import_jsx_runtime7 = require("react/jsx-runtime");
562
- var requirements = [
563
- {
564
- label: "At least 1 Uppercase letter",
565
- test: (pwd) => /[A-Z]/.test(pwd)
566
- },
567
- {
568
- label: "At least 1 Number",
569
- test: (pwd) => /\d/.test(pwd)
570
- },
571
- {
572
- label: "Special character (e.g. !?<>@#$%)",
573
- test: (pwd) => /[!@#$%^&*()_+\-=[\]{};\\|,.<>/?]/.test(pwd)
574
- },
575
- {
576
- label: "8 characters or more",
577
- test: (pwd) => pwd.length >= 8
570
+ function createRequirements(config) {
571
+ const requirements = [];
572
+ const minLength = config.passwordMinLength;
573
+ const requireUppercase = config.requireUppercase;
574
+ const requireLowercase = config.requireLowercase;
575
+ const requireNumber = config.requireNumber;
576
+ const requireSpecialChar = config.requireSpecialChar;
577
+ if (requireUppercase) {
578
+ requirements.push({
579
+ label: "At least 1 Uppercase letter",
580
+ test: (pwd) => /[A-Z]/.test(pwd)
581
+ });
578
582
  }
579
- ];
580
- function validatePasswordStrength(password) {
583
+ if (requireLowercase) {
584
+ requirements.push({
585
+ label: "At least 1 Lowercase letter",
586
+ test: (pwd) => /[a-z]/.test(pwd)
587
+ });
588
+ }
589
+ if (requireNumber) {
590
+ requirements.push({
591
+ label: "At least 1 Number",
592
+ test: (pwd) => /\d/.test(pwd)
593
+ });
594
+ }
595
+ if (requireSpecialChar) {
596
+ requirements.push({
597
+ label: "Special character (e.g. !?<>@#$%)",
598
+ test: (pwd) => /[!@#$%^&*()_+\-=[\]{};\\|,.<>/?]/.test(pwd)
599
+ });
600
+ }
601
+ requirements.push({
602
+ label: `${minLength} characters or more`,
603
+ test: (pwd) => pwd.length >= minLength
604
+ });
605
+ return requirements;
606
+ }
607
+ function validatePasswordStrength(password, config) {
581
608
  if (!password) return false;
609
+ const requirements = createRequirements(config);
582
610
  return requirements.every((req) => req.test(password));
583
611
  }
584
- function AuthPasswordStrengthIndicator({ password }) {
612
+ function AuthPasswordStrengthIndicator({
613
+ password,
614
+ config
615
+ }) {
616
+ const requirements = createRequirements(config);
585
617
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "insforge-password-strength", children: requirements.map((requirement, index) => {
586
618
  const isValid = requirement.test(password);
587
619
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "insforge-password-requirement", children: [
@@ -603,14 +635,15 @@ function AuthPasswordField({
603
635
  label,
604
636
  id,
605
637
  showStrengthIndicator = false,
638
+ emailAuthConfig,
606
639
  forgotPasswordLink,
607
640
  value,
608
641
  className = "",
609
642
  onFocus,
610
643
  ...props
611
644
  }) {
612
- const [showPassword, setShowPassword] = (0, import_react3.useState)(false);
613
- const [showStrength, setShowStrength] = (0, import_react3.useState)(false);
645
+ const [showPassword, setShowPassword] = (0, import_react4.useState)(false);
646
+ const [showStrength, setShowStrength] = (0, import_react4.useState)(false);
614
647
  const handleFocus = (e) => {
615
648
  if (showStrengthIndicator) {
616
649
  setShowStrength(true);
@@ -645,7 +678,13 @@ function AuthPasswordField({
645
678
  }
646
679
  )
647
680
  ] }),
648
- showStrengthIndicator && showStrength && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AuthPasswordStrengthIndicator, { password: String(value || "") })
681
+ showStrengthIndicator && showStrength && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
682
+ AuthPasswordStrengthIndicator,
683
+ {
684
+ password: String(value || ""),
685
+ config: emailAuthConfig
686
+ }
687
+ )
649
688
  ] });
650
689
  }
651
690
 
@@ -937,7 +976,7 @@ function AuthOAuthProviders({
937
976
  }
938
977
 
939
978
  // src/components/auth/AuthVerificationCodeInput.tsx
940
- var import_react4 = require("react");
979
+ var import_react5 = require("react");
941
980
  var import_jsx_runtime15 = require("react/jsx-runtime");
942
981
  function AuthVerificationCodeInput({
943
982
  length = 6,
@@ -946,7 +985,7 @@ function AuthVerificationCodeInput({
946
985
  onChange,
947
986
  disabled = false
948
987
  }) {
949
- const inputRefs = (0, import_react4.useRef)([]);
988
+ const inputRefs = (0, import_react5.useRef)([]);
950
989
  const handleChange = (index, digit) => {
951
990
  if (digit.length > 1) return;
952
991
  if (digit && !/^\d$/.test(digit)) return;
@@ -1030,12 +1069,13 @@ function SignIn({
1030
1069
  }) {
1031
1070
  const { signIn, baseUrl } = useInsforge();
1032
1071
  const { providers: oauthProviders } = useOAuthProviders();
1033
- const [email, setEmail] = (0, import_react5.useState)("");
1034
- const [password, setPassword] = (0, import_react5.useState)("");
1035
- const [error, setError] = (0, import_react5.useState)("");
1036
- const [loading, setLoading] = (0, import_react5.useState)(false);
1037
- const [oauthLoading, setOauthLoading] = (0, import_react5.useState)(null);
1038
- const insforge = (0, import_react5.useState)(() => (0, import_sdk3.createClient)({ baseUrl }))[0];
1072
+ const { config: emailAuthConfig } = useEmailAuthConfig();
1073
+ const [email, setEmail] = (0, import_react6.useState)("");
1074
+ const [password, setPassword] = (0, import_react6.useState)("");
1075
+ const [error, setError] = (0, import_react6.useState)("");
1076
+ const [loading, setLoading] = (0, import_react6.useState)(false);
1077
+ const [oauthLoading, setOauthLoading] = (0, import_react6.useState)(null);
1078
+ const insforge = (0, import_react6.useState)(() => (0, import_sdk4.createClient)({ baseUrl }))[0];
1039
1079
  async function handleSubmit(e) {
1040
1080
  e.preventDefault();
1041
1081
  setLoading(true);
@@ -1097,7 +1137,15 @@ function SignIn({
1097
1137
  value: password,
1098
1138
  onChange: (e) => setPassword(e.target.value),
1099
1139
  required: true,
1100
- autoComplete: "current-password"
1140
+ autoComplete: "current-password",
1141
+ emailAuthConfig: emailAuthConfig || {
1142
+ requireEmailVerification: false,
1143
+ passwordMinLength: 6,
1144
+ requireNumber: false,
1145
+ requireLowercase: false,
1146
+ requireUppercase: false,
1147
+ requireSpecialChar: false
1148
+ }
1101
1149
  }
1102
1150
  ),
1103
1151
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
@@ -1127,8 +1175,8 @@ function SignIn({
1127
1175
  }
1128
1176
 
1129
1177
  // src/components/SignUp.tsx
1130
- var import_react6 = require("react");
1131
- var import_sdk4 = require("@insforge/sdk");
1178
+ var import_react7 = require("react");
1179
+ var import_sdk5 = require("@insforge/sdk");
1132
1180
  var import_jsx_runtime17 = require("react/jsx-runtime");
1133
1181
  function SignUp({
1134
1182
  afterSignUpUrl = "/",
@@ -1153,17 +1201,18 @@ function SignUp({
1153
1201
  }) {
1154
1202
  const { signUp, baseUrl } = useInsforge();
1155
1203
  const { providers: oauthProviders } = useOAuthProviders();
1156
- const [email, setEmail] = (0, import_react6.useState)("");
1157
- const [password, setPassword] = (0, import_react6.useState)("");
1158
- const [error, setError] = (0, import_react6.useState)("");
1159
- const [loading, setLoading] = (0, import_react6.useState)(false);
1160
- const [oauthLoading, setOauthLoading] = (0, import_react6.useState)(null);
1161
- const insforge = (0, import_react6.useState)(() => (0, import_sdk4.createClient)({ baseUrl }))[0];
1204
+ const { config: emailAuthConfig } = useEmailAuthConfig();
1205
+ const [email, setEmail] = (0, import_react7.useState)("");
1206
+ const [password, setPassword] = (0, import_react7.useState)("");
1207
+ const [error, setError] = (0, import_react7.useState)("");
1208
+ const [loading, setLoading] = (0, import_react7.useState)(false);
1209
+ const [oauthLoading, setOauthLoading] = (0, import_react7.useState)(null);
1210
+ const insforge = (0, import_react7.useState)(() => (0, import_sdk5.createClient)({ baseUrl }))[0];
1162
1211
  async function handleCredentialsSubmit(e) {
1163
1212
  e.preventDefault();
1164
1213
  setLoading(true);
1165
1214
  setError("");
1166
- if (!validatePasswordStrength(password)) {
1215
+ if (emailAuthConfig && !validatePasswordStrength(password, emailAuthConfig)) {
1167
1216
  setError("Password does not meet all requirements");
1168
1217
  setLoading(false);
1169
1218
  return;
@@ -1228,9 +1277,17 @@ function SignUp({
1228
1277
  value: password,
1229
1278
  onChange: (e) => setPassword(e.target.value),
1230
1279
  required: true,
1231
- minLength: 8,
1280
+ minLength: emailAuthConfig?.passwordMinLength ?? 8,
1232
1281
  autoComplete: "new-password",
1233
- showStrengthIndicator: true
1282
+ showStrengthIndicator: true,
1283
+ emailAuthConfig: emailAuthConfig || {
1284
+ requireEmailVerification: false,
1285
+ passwordMinLength: 6,
1286
+ requireNumber: false,
1287
+ requireLowercase: false,
1288
+ requireUppercase: false,
1289
+ requireSpecialChar: false
1290
+ }
1234
1291
  }
1235
1292
  ),
1236
1293
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -1267,7 +1324,7 @@ function SignUp({
1267
1324
  }
1268
1325
 
1269
1326
  // src/components/UserButton.tsx
1270
- var import_react7 = require("react");
1327
+ var import_react8 = require("react");
1271
1328
  var import_lucide_react6 = require("lucide-react");
1272
1329
  var import_jsx_runtime18 = require("react/jsx-runtime");
1273
1330
  function UserButton({
@@ -1276,9 +1333,9 @@ function UserButton({
1276
1333
  appearance = {}
1277
1334
  }) {
1278
1335
  const { user, signOut } = useInsforge();
1279
- const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
1280
- const dropdownRef = (0, import_react7.useRef)(null);
1281
- (0, import_react7.useEffect)(() => {
1336
+ const [isOpen, setIsOpen] = (0, import_react8.useState)(false);
1337
+ const dropdownRef = (0, import_react8.useRef)(null);
1338
+ (0, import_react8.useEffect)(() => {
1282
1339
  function handleClickOutside(event) {
1283
1340
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
1284
1341
  setIsOpen(false);
@@ -1343,7 +1400,7 @@ function SignedOut({ children }) {
1343
1400
  }
1344
1401
 
1345
1402
  // src/components/Protect.tsx
1346
- var import_react8 = require("react");
1403
+ var import_react9 = require("react");
1347
1404
  var import_navigation = require("next/navigation");
1348
1405
  var import_jsx_runtime21 = require("react/jsx-runtime");
1349
1406
  function Protect({
@@ -1354,7 +1411,7 @@ function Protect({
1354
1411
  }) {
1355
1412
  const { isSignedIn, isLoaded, user } = useInsforge();
1356
1413
  const router = (0, import_navigation.useRouter)();
1357
- (0, import_react8.useEffect)(() => {
1414
+ (0, import_react9.useEffect)(() => {
1358
1415
  if (isLoaded && !isSignedIn) {
1359
1416
  router.push(redirectTo);
1360
1417
  } else if (isLoaded && isSignedIn && condition && user) {