@insforge/nextjs 0.10.9 → 0.10.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.
Files changed (37) hide show
  1. package/dist/api/route-handlers.d.ts +0 -5
  2. package/dist/client/provider.d.ts +48 -0
  3. package/dist/components.client.d.ts +3 -0
  4. package/dist/components.server.d.ts +10 -0
  5. package/dist/esm/api/index.js.map +1 -1
  6. package/dist/esm/api/route-handlers.js +51 -13
  7. package/dist/esm/api/route-handlers.js.map +1 -1
  8. package/dist/esm/client/components.js.map +1 -0
  9. package/dist/esm/client/hooks.js.map +1 -0
  10. package/dist/esm/{client-boundary → client}/provider.js +12 -6
  11. package/dist/esm/client/provider.js.map +1 -0
  12. package/dist/esm/components.client.js +6 -0
  13. package/dist/esm/components.client.js.map +1 -0
  14. package/dist/esm/components.server.js +5 -0
  15. package/dist/esm/components.server.js.map +1 -0
  16. package/dist/esm/index.js +6 -6
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/middleware/InsforgeMiddleware.js +23 -6
  19. package/dist/esm/middleware/InsforgeMiddleware.js.map +1 -1
  20. package/dist/esm/package.json +10 -0
  21. package/dist/esm/server/InsforgeProvider.js +102 -0
  22. package/dist/esm/server/InsforgeProvider.js.map +1 -0
  23. package/dist/esm/server/index.js +5 -0
  24. package/dist/esm/server/index.js.map +1 -0
  25. package/dist/index.d.ts +4 -2
  26. package/dist/middleware/InsforgeMiddleware.d.ts +1 -6
  27. package/dist/server/InsforgeProvider.d.ts +102 -0
  28. package/dist/server/index.d.ts +4 -0
  29. package/package.json +7 -3
  30. package/dist/client-boundary/provider.d.ts +0 -50
  31. package/dist/esm/client-boundary/components.js.map +0 -1
  32. package/dist/esm/client-boundary/hooks.js.map +0 -1
  33. package/dist/esm/client-boundary/provider.js.map +0 -1
  34. /package/dist/{client-boundary → client}/components.d.ts +0 -0
  35. /package/dist/{client-boundary → client}/hooks.d.ts +0 -0
  36. /package/dist/esm/{client-boundary → client}/components.js +0 -0
  37. /package/dist/esm/{client-boundary → client}/hooks.js +0 -0
@@ -5,11 +5,6 @@ interface AuthRouteConfig {
5
5
  * Base URL of your Insforge backend
6
6
  */
7
7
  baseUrl: string;
8
- /**
9
- * Cookie name for the auth token
10
- * @default 'insforge_token'
11
- */
12
- cookieName?: string;
13
8
  /**
14
9
  * Cookie max age in seconds (default: 7 days)
15
10
  * @default 604800
@@ -0,0 +1,48 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { InsforgeProviderProps, InitialAuthState, useInsforge as useInsforge$1 } from '@insforge/react';
3
+
4
+ interface ExtendedProviderProps extends InsforgeProviderProps {
5
+ afterSignInUrl?: string;
6
+ onSignIn?: (authToken: string) => Promise<void>;
7
+ onSignOut?: () => Promise<void>;
8
+ /**
9
+ * Initial auth state from server (for SSR hydration)
10
+ * @internal
11
+ */
12
+ initialState?: InitialAuthState;
13
+ }
14
+ /**
15
+ * Client Insforge Provider for Next.js
16
+ *
17
+ * This is a Client Component ('use client') that:
18
+ * 1. Receives initialState from Server Provider
19
+ * 2. Manages authentication state on the client
20
+ * 3. Syncs tokens to HTTP-only cookies via /api/auth
21
+ *
22
+ * @internal - Not intended for direct use. Use the Server Provider instead.
23
+ */
24
+ declare function ClientInsforgeProvider({ children, baseUrl, afterSignInUrl, onAuthChange, initialState, }: ExtendedProviderProps): react_jsx_runtime.JSX.Element;
25
+ /**
26
+ * Hook to access Insforge context
27
+ *
28
+ * Re-exports the hook from @insforge/react for convenience.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * function MyComponent() {
33
+ * const { user, isSignedIn, signOut } = useInsforge();
34
+ *
35
+ * if (!isSignedIn) return <SignIn />;
36
+ *
37
+ * return (
38
+ * <div>
39
+ * <p>Welcome {user.email}</p>
40
+ * <button onClick={signOut}>Sign Out</button>
41
+ * </div>
42
+ * );
43
+ * }
44
+ * ```
45
+ */
46
+ declare const useInsforge: typeof useInsforge$1;
47
+
48
+ export { ClientInsforgeProvider, useInsforge };
@@ -0,0 +1,3 @@
1
+ export { ClientInsforgeProvider as InsforgeProvider } from './client/provider.js';
2
+ import 'react/jsx-runtime';
3
+ import '@insforge/react';
@@ -0,0 +1,10 @@
1
+ import { InsforgeProvider } from './server/InsforgeProvider.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import '@insforge/react';
5
+
6
+ type ServerComponentsServerModuleTypes = {
7
+ InsforgeProvider: typeof InsforgeProvider;
8
+ };
9
+
10
+ export { InsforgeProvider, type ServerComponentsServerModuleTypes };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/api/index.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\nexport type { AuthRouteConfig } from './route-handlers';\n"],"mappings":"AAAA,SAAS,+BAA+B;","names":[]}
1
+ {"version":3,"sources":["../../../src/api/index.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\nexport type { AuthRouteConfig } from './route-handlers';"],"mappings":"AAAA,SAAS,+BAA+B;","names":[]}
@@ -3,16 +3,17 @@ import { createClient } from "@insforge/sdk";
3
3
  function createAuthRouteHandlers(config) {
4
4
  const {
5
5
  baseUrl,
6
- cookieName = "insforge_token",
7
6
  cookieMaxAge = 7 * 24 * 60 * 60
8
7
  // 7 days
9
8
  } = config;
9
+ const sessionCookieName = "insforge-session";
10
+ const userCookieName = "insforge-user";
10
11
  const insforge = createClient({ baseUrl });
11
- function setAuthCookie(response, token) {
12
+ function setAuthCookies(response, token, user) {
12
13
  const isProduction = process.env.NODE_ENV === "production";
13
14
  const secure = config.secure ?? isProduction;
14
15
  response.cookies.set({
15
- name: cookieName,
16
+ name: sessionCookieName,
16
17
  value: token,
17
18
  httpOnly: true,
18
19
  // Cannot be accessed by JavaScript
@@ -22,14 +23,38 @@ function createAuthRouteHandlers(config) {
22
23
  maxAge: cookieMaxAge,
23
24
  path: "/"
24
25
  });
26
+ const userInfo = JSON.stringify({
27
+ id: user.id,
28
+ email: user.email,
29
+ name: user.name || ""
30
+ });
31
+ response.cookies.set({
32
+ name: userCookieName,
33
+ value: userInfo,
34
+ httpOnly: true,
35
+ secure,
36
+ sameSite: "lax",
37
+ maxAge: cookieMaxAge,
38
+ path: "/"
39
+ });
25
40
  return response;
26
41
  }
27
- function clearAuthCookie(response) {
42
+ function clearAuthCookies(response) {
43
+ const secure = config.secure ?? process.env.NODE_ENV === "production";
44
+ response.cookies.set({
45
+ name: sessionCookieName,
46
+ value: "",
47
+ httpOnly: true,
48
+ secure,
49
+ sameSite: "lax",
50
+ maxAge: 0,
51
+ path: "/"
52
+ });
28
53
  response.cookies.set({
29
- name: cookieName,
54
+ name: userCookieName,
30
55
  value: "",
31
56
  httpOnly: true,
32
- secure: config.secure ?? process.env.NODE_ENV === "production",
57
+ secure,
33
58
  sameSite: "lax",
34
59
  maxAge: 0,
35
60
  path: "/"
@@ -67,7 +92,11 @@ function createAuthRouteHandlers(config) {
67
92
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
68
93
  }
69
94
  });
70
- setAuthCookie(response, result.data.accessToken || "");
95
+ setAuthCookies(response, result.data.accessToken || "", {
96
+ id: result.data.user.id,
97
+ email: result.data.user.email,
98
+ name: result.data.user.name
99
+ });
71
100
  return response;
72
101
  }
73
102
  case "sign-up": {
@@ -90,12 +119,17 @@ function createAuthRouteHandlers(config) {
90
119
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
91
120
  }
92
121
  });
93
- setAuthCookie(response, result.data.accessToken || "");
122
+ setAuthCookies(response, result.data.accessToken || "", {
123
+ id: result.data.user.id,
124
+ email: result.data.user.email,
125
+ name: result.data.user.name
126
+ });
94
127
  return response;
95
128
  }
96
129
  case "sync-token": {
97
130
  const { token } = body;
98
131
  if (!token) {
132
+ console.error("[Auth Route] No token provided");
99
133
  return NextResponse.json({ error: "Token is required" }, { status: 400 });
100
134
  }
101
135
  try {
@@ -122,7 +156,11 @@ function createAuthRouteHandlers(config) {
122
156
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
123
157
  }
124
158
  });
125
- setAuthCookie(nextResponse, token);
159
+ setAuthCookies(nextResponse, token, {
160
+ id: session.user.id,
161
+ email: session.user.email,
162
+ name: session.user.name
163
+ });
126
164
  return nextResponse;
127
165
  } catch (error) {
128
166
  console.error("[Auth API] Token validation error:", error);
@@ -142,7 +180,7 @@ function createAuthRouteHandlers(config) {
142
180
  }
143
181
  async function GET(request) {
144
182
  try {
145
- const token = request.cookies.get(cookieName)?.value;
183
+ const token = request.cookies.get(sessionCookieName)?.value;
146
184
  if (!token) {
147
185
  return NextResponse.json({ user: null, session: null });
148
186
  }
@@ -154,7 +192,7 @@ function createAuthRouteHandlers(config) {
154
192
  });
155
193
  if (!response.ok) {
156
194
  const nextResponse = NextResponse.json({ user: null, session: null });
157
- clearAuthCookie(nextResponse);
195
+ clearAuthCookies(nextResponse);
158
196
  return nextResponse;
159
197
  }
160
198
  const session = await response.json();
@@ -174,7 +212,7 @@ function createAuthRouteHandlers(config) {
174
212
  }
175
213
  async function DELETE(request) {
176
214
  try {
177
- const token = request.cookies.get(cookieName)?.value;
215
+ const token = request.cookies.get(sessionCookieName)?.value;
178
216
  if (token) {
179
217
  try {
180
218
  await fetch(`${baseUrl}/auth/sessions/current`, {
@@ -189,7 +227,7 @@ function createAuthRouteHandlers(config) {
189
227
  }
190
228
  }
191
229
  const response = NextResponse.json({ success: true });
192
- clearAuthCookie(response);
230
+ clearAuthCookies(response);
193
231
  return response;
194
232
  } catch (error) {
195
233
  console.error("[Auth API Error]:", error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\ninterface SignInRequestBody {\n action: 'sign-in';\n email: string;\n password: string;\n}\n\ninterface SignUpRequestBody {\n action: 'sign-up';\n email: string;\n password: string;\n}\n\ninterface SyncTokenRequestBody {\n action: 'sync-token';\n token: string;\n}\n\ntype AuthRequestBody = SignInRequestBody | SignUpRequestBody | SyncTokenRequestBody;\n\ninterface SessionResponse {\n user: {\n id: string;\n email: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieName = 'insforge_token',\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookie\n */\n function setAuthCookie(response: NextResponse, token: string) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n response.cookies.set({\n name: cookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookie\n */\n function clearAuthCookie(response: NextResponse) {\n response.cookies.set({\n name: cookieName,\n value: '',\n httpOnly: true,\n secure: config.secure ?? process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = (await request.json()) as AuthRequestBody;\n const { action } = body;\n\n if (!action) {\n return NextResponse.json({ error: 'Action is required' }, { status: 400 });\n }\n\n switch (action) {\n case 'sign-in': {\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json({ error: result.error.message }, { status: 401 });\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json({ error: 'Authentication failed' }, { status: 401 });\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sign-up': {\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json({ error: result.error.message }, { status: 400 });\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json({ error: 'Sign up failed' }, { status: 400 });\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n return NextResponse.json({ error: 'Token is required' }, { status: 400 });\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = (await response.json()) as SessionResponse;\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(nextResponse, token);\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json({ error: 'Invalid action' }, { status: 400 });\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookie(nextResponse);\n return nextResponse;\n }\n\n const session = (await response.json()) as SessionResponse;\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookie(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\n }\n }\n\n return {\n POST,\n GET,\n DELETE,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\ninterface SignInRequestBody {\n action: 'sign-in';\n email: string;\n password: string;\n}\n\ninterface SignUpRequestBody {\n action: 'sign-up';\n email: string;\n password: string;\n}\n\ninterface SyncTokenRequestBody {\n action: 'sync-token';\n token: string;\n}\n\ntype AuthRequestBody = SignInRequestBody | SignUpRequestBody | SyncTokenRequestBody;\n\ninterface SessionResponse {\n user: {\n id: string;\n email: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n // Fixed cookie names - not configurable\n const sessionCookieName = 'insforge-session';\n const userCookieName = 'insforge-user';\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookies (session token + user identity)\n */\n function setAuthCookies(\n response: NextResponse, \n token: string, \n user: { id: string; email: string; name?: string }\n ) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n // Set session cookie (access token)\n response.cookies.set({\n name: sessionCookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n // Set user identity cookie (basic info for SSR)\n const userInfo = JSON.stringify({\n id: user.id,\n email: user.email,\n name: user.name || '',\n });\n\n response.cookies.set({\n name: userCookieName,\n value: userInfo,\n httpOnly: true,\n secure,\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookies\n */\n function clearAuthCookies(response: NextResponse) {\n const secure = config.secure ?? process.env.NODE_ENV === 'production';\n\n // Clear session cookie\n response.cookies.set({\n name: sessionCookieName,\n value: '',\n httpOnly: true,\n secure,\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n // Clear user cookie\n response.cookies.set({\n name: userCookieName,\n value: '',\n httpOnly: true,\n secure,\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = (await request.json()) as AuthRequestBody;\n const { action } = body;\n\n if (!action) {\n return NextResponse.json({ error: 'Action is required' }, { status: 400 });\n }\n\n switch (action) {\n case 'sign-in': {\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json({ error: result.error.message }, { status: 401 });\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json({ error: 'Authentication failed' }, { status: 401 });\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookies(response, result.data.accessToken || '', {\n id: result.data.user.id,\n email: result.data.user.email,\n name: (result.data.user as any).name,\n });\n\n return response;\n }\n\n case 'sign-up': {\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json({ error: result.error.message }, { status: 400 });\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json({ error: 'Sign up failed' }, { status: 400 });\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookies(response, result.data.accessToken || '', {\n id: result.data.user.id,\n email: result.data.user.email,\n name: (result.data.user as any).name,\n });\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n console.error('[Auth Route] No token provided');\n return NextResponse.json({ error: 'Token is required' }, { status: 400 });\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = (await response.json()) as SessionResponse;\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookies(nextResponse, token, {\n id: session.user.id,\n email: session.user.email,\n name: (session.user as any).name,\n });\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json({ error: 'Invalid action' }, { status: 400 });\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(sessionCookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookies(nextResponse);\n return nextResponse;\n }\n\n const session = (await response.json()) as SessionResponse;\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(sessionCookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookies(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\n }\n }\n\n return {\n POST,\n GET,\n DELETE,\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/client/components.tsx"],"sourcesContent":["'use client';\n\n/**\n * Client-side UI components boundary for Next.js App Router\n * All components from @insforge/react are re-exported here with 'use client' directive\n */\n\n// Main components\nexport {\n SignIn,\n SignUp,\n ForgotPassword,\n ResetPassword,\n VerifyEmail,\n UserButton,\n Protect,\n SignedIn,\n SignedOut,\n SignInButton,\n SignUpButton,\n} from '@insforge/react/components';\n\n// Form components\nexport {\n SignInForm,\n SignUpForm,\n ForgotPasswordForm,\n ResetPasswordForm,\n VerifyEmailStatus,\n} from '@insforge/react/components';\n\n// Atom components\nexport {\n AuthBranding,\n AuthContainer,\n AuthHeader,\n AuthErrorBanner,\n AuthFormField,\n AuthPasswordField,\n AuthPasswordStrengthIndicator,\n AuthSubmitButton,\n AuthLink,\n AuthDivider,\n AuthOAuthButton,\n AuthOAuthProviders,\n AuthVerificationCodeInput,\n AuthEmailVerificationStep,\n AuthResetPasswordVerificationStep,\n} from '@insforge/react/components';\n\n// Re-export all component types\nexport type {\n SignInProps,\n SignUpProps,\n ForgotPasswordProps,\n ResetPasswordProps,\n VerifyEmailProps,\n UserButtonProps,\n ProtectProps,\n ConditionalProps,\n SignInFormProps,\n SignUpFormProps,\n ForgotPasswordFormProps,\n ResetPasswordFormProps,\n VerifyEmailStatusProps,\n AuthContainerProps,\n AuthHeaderProps,\n AuthErrorBannerProps,\n AuthFormFieldProps,\n AuthPasswordFieldProps,\n AuthPasswordStrengthIndicatorProps,\n AuthSubmitButtonProps,\n AuthLinkProps,\n AuthDividerProps,\n AuthOAuthButtonProps,\n AuthOAuthProvidersProps,\n AuthVerificationCodeInputProps,\n} from '@insforge/react/components';\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/client/hooks.ts"],"sourcesContent":["'use client';\n\nimport { useInsforge } from './provider';\n\n/**\n * Next.js specific hooks - implemented locally to avoid Context duplication\n */\n\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n\nexport function useUser() {\n const { user, isLoaded } = useInsforge();\n return { user, isLoaded };\n}\n\nexport function usePublicAuthConfig() {\n const { getPublicAuthConfig } = useInsforge();\n return { getPublicAuthConfig };\n}\n"],"mappings":";AAEA,SAAS,mBAAmB;AAMrB,SAAS,UAAU;AACxB,QAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW,IAAI,YAAY;AACtE,SAAO,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW;AACzD;AAEO,SAAS,UAAU;AACxB,QAAM,EAAE,MAAM,SAAS,IAAI,YAAY;AACvC,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEO,SAAS,sBAAsB;AACpC,QAAM,EAAE,oBAAoB,IAAI,YAAY;AAC5C,SAAO,EAAE,oBAAoB;AAC/B;","names":[]}
@@ -8,7 +8,7 @@ import {
8
8
  import { NavigationAdapter } from "../navigation";
9
9
  async function handleSignIn(token) {
10
10
  try {
11
- await fetch("/api/auth", {
11
+ const response = await fetch("/api/auth", {
12
12
  method: "POST",
13
13
  headers: {
14
14
  "Content-Type": "application/json"
@@ -18,8 +18,12 @@ async function handleSignIn(token) {
18
18
  token
19
19
  })
20
20
  });
21
+ if (!response.ok) {
22
+ const errorText = await response.text();
23
+ console.error("[Insforge Client Provider] sync-token failed:", errorText);
24
+ }
21
25
  } catch (err) {
22
- console.error("[InsforgeProvider] Failed to sync token to cookie:", err);
26
+ console.error("[Insforge Client Provider] Failed to sync token to cookie:", err);
23
27
  }
24
28
  }
25
29
  async function handleSignOut() {
@@ -28,11 +32,12 @@ async function handleSignOut() {
28
32
  } catch {
29
33
  }
30
34
  }
31
- function InsforgeProvider({
35
+ function ClientInsforgeProvider({
32
36
  children,
33
37
  baseUrl,
34
38
  afterSignInUrl = "/",
35
- onAuthChange
39
+ onAuthChange,
40
+ initialState
36
41
  }) {
37
42
  const providerProps = {
38
43
  children,
@@ -40,13 +45,14 @@ function InsforgeProvider({
40
45
  afterSignInUrl,
41
46
  onAuthChange,
42
47
  onSignIn: handleSignIn,
43
- onSignOut: handleSignOut
48
+ onSignOut: handleSignOut,
49
+ initialState
44
50
  };
45
51
  return /* @__PURE__ */ jsx(NavigationProvider, { adapter: NavigationAdapter, children: /* @__PURE__ */ jsx(InsforgeProviderCore, { ...providerProps, children }) });
46
52
  }
47
53
  const useInsforge = useReactInsforge;
48
54
  export {
49
- InsforgeProvider,
55
+ ClientInsforgeProvider,
50
56
  useInsforge
51
57
  };
52
58
  //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/client/provider.tsx"],"sourcesContent":["'use client';\n\nimport {\n InsforgeProviderCore,\n type InsforgeProviderProps,\n type InitialAuthState,\n useInsforge as useReactInsforge,\n NavigationProvider,\n} from '@insforge/react';\nimport { NavigationAdapter } from '../navigation';\n\n// Extended interface for Next.js provider\ninterface ExtendedProviderProps extends InsforgeProviderProps {\n afterSignInUrl?: string;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n /**\n * Initial auth state from server (for SSR hydration)\n * @internal\n */\n initialState?: InitialAuthState;\n}\n\n// Sync token to server-side cookie on sign in\nasync function handleSignIn(token: string): Promise<void> {\n try {\n const response = await fetch('/api/auth', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'sync-token',\n token,\n }),\n });\n \n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Insforge Client Provider] sync-token failed:', errorText);\n }\n } catch (err) {\n console.error('[Insforge Client Provider] Failed to sync token to cookie:', err);\n }\n}\n\n// Clear HTTP-only cookie on sign out\nasync function handleSignOut(): Promise<void> {\n try {\n await fetch('/api/auth', { method: 'DELETE' });\n } catch {\n // API route doesn't exist - ignore\n }\n}\n\n/**\n * Client Insforge Provider for Next.js\n * \n * This is a Client Component ('use client') that:\n * 1. Receives initialState from Server Provider\n * 2. Manages authentication state on the client\n * 3. Syncs tokens to HTTP-only cookies via /api/auth\n * \n * @internal - Not intended for direct use. Use the Server Provider instead.\n */\nexport function ClientInsforgeProvider({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n initialState,\n}: ExtendedProviderProps) {\n const providerProps: ExtendedProviderProps = {\n children,\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn: handleSignIn,\n onSignOut: handleSignOut,\n initialState,\n };\n\n return (\n <NavigationProvider adapter={NavigationAdapter}>\n <InsforgeProviderCore {...providerProps}>{children}</InsforgeProviderCore>\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Re-exports the hook from @insforge/react for convenience.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useInsforge = useReactInsforge;\n"],"mappings":";AAoFM;AAlFN;AAAA,EACE;AAAA,EAGA,eAAe;AAAA,EACf;AAAA,OACK;AACP,SAAS,yBAAyB;AAelC,eAAe,aAAa,OAA8B;AACxD,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,aAAa;AAAA,MACxC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,cAAQ,MAAM,iDAAiD,SAAS;AAAA,IAC1E;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,8DAA8D,GAAG;AAAA,EACjF;AACF;AAGA,eAAe,gBAA+B;AAC5C,MAAI;AACF,UAAM,MAAM,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAYO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAA0B;AACxB,QAAM,gBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,IACX;AAAA,EACF;AAEA,SACE,oBAAC,sBAAmB,SAAS,mBAC3B,8BAAC,wBAAsB,GAAG,eAAgB,UAAS,GACrD;AAEJ;AAuBO,MAAM,cAAc;","names":[]}
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { ClientInsforgeProvider } from "./client/provider";
3
+ export {
4
+ ClientInsforgeProvider as InsforgeProvider
5
+ };
6
+ //# sourceMappingURL=components.client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components.client.ts"],"sourcesContent":["'use client';\r\n\r\n// Client Component exports (from client folder)\r\n// This file is used when code runs in a Client Component (browser environment)\r\nexport { ClientInsforgeProvider as InsforgeProvider } from './client/provider';\r\n\r\n"],"mappings":";AAIA,SAAmC,8BAAwB;","names":[]}
@@ -0,0 +1,5 @@
1
+ import { InsforgeProvider as ServerInsforgeProvider } from "./server/InsforgeProvider";
2
+ export {
3
+ ServerInsforgeProvider as InsforgeProvider
4
+ };
5
+ //# sourceMappingURL=components.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components.server.ts"],"sourcesContent":["// Server Component exports (from server folder)\r\n// This file is used when code runs in a Server Component (react-server environment)\r\nimport { InsforgeProvider as ServerInsforgeProvider } from './server/InsforgeProvider';\r\n\r\nexport { ServerInsforgeProvider as InsforgeProvider };\r\n\r\nexport type ServerComponentsServerModuleTypes = {\r\n InsforgeProvider: typeof ServerInsforgeProvider;\r\n};\r\n\r\n"],"mappings":"AAEA,SAAS,oBAAoB,8BAA8B;","names":[]}
package/dist/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- "use client";
2
- import { InsforgeProvider, useInsforge } from "./client-boundary/provider";
1
+ import { InsforgeProvider } from "#components";
2
+ import { useInsforge } from "./client/provider";
3
3
  import {
4
4
  SignIn,
5
5
  SignUp,
@@ -12,14 +12,14 @@ import {
12
12
  SignedOut,
13
13
  SignInButton,
14
14
  SignUpButton
15
- } from "./client-boundary/components";
15
+ } from "./client/components";
16
16
  import {
17
17
  SignInForm,
18
18
  SignUpForm,
19
19
  ForgotPasswordForm,
20
20
  ResetPasswordForm,
21
21
  VerifyEmailStatus
22
- } from "./client-boundary/components";
22
+ } from "./client/components";
23
23
  import {
24
24
  AuthBranding,
25
25
  AuthContainer,
@@ -36,8 +36,8 @@ import {
36
36
  AuthVerificationCodeInput,
37
37
  AuthEmailVerificationStep,
38
38
  AuthResetPasswordVerificationStep
39
- } from "./client-boundary/components";
40
- import { useAuth, useUser, usePublicAuthConfig } from "./client-boundary/hooks";
39
+ } from "./client/components";
40
+ import { useAuth, useUser, usePublicAuthConfig } from "./client/hooks";
41
41
  export {
42
42
  AuthBranding,
43
43
  AuthContainer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["'use client';\n\n// Types (no 'use client' needed for types)\nexport type {\n OAuthProvider,\n AuthConfig,\n EmailVerificationMethod,\n InsforgeUser,\n OAuthProviderConfig,\n} from '@insforge/react/types';\n\n// Provider (from client-boundary)\nexport { InsforgeProvider, useInsforge } from './client-boundary/provider';\n\n/**\n * These need to be explicitly listed. Do not use an * here.\n * If you do, app router will break.\n *\n * Pattern learned from @clerk/nextjs\n */\n\n// Main UI Components\nexport {\n SignIn,\n SignUp,\n ForgotPassword,\n ResetPassword,\n VerifyEmail,\n UserButton,\n Protect,\n SignedIn,\n SignedOut,\n SignInButton,\n SignUpButton,\n} from './client-boundary/components';\n\n// Form Components\nexport {\n SignInForm,\n SignUpForm,\n ForgotPasswordForm,\n ResetPasswordForm,\n VerifyEmailStatus,\n} from './client-boundary/components';\n\n// Atom Components\nexport {\n AuthBranding,\n AuthContainer,\n AuthHeader,\n AuthErrorBanner,\n AuthFormField,\n AuthPasswordField,\n AuthPasswordStrengthIndicator,\n AuthSubmitButton,\n AuthLink,\n AuthDivider,\n AuthOAuthButton,\n AuthOAuthProviders,\n AuthVerificationCodeInput,\n AuthEmailVerificationStep,\n AuthResetPasswordVerificationStep,\n} from './client-boundary/components';\n\n// Component Types\nexport type {\n SignInProps,\n SignUpProps,\n ForgotPasswordProps,\n ResetPasswordProps,\n VerifyEmailProps,\n UserButtonProps,\n ProtectProps,\n ConditionalProps,\n SignInFormProps,\n SignUpFormProps,\n ForgotPasswordFormProps,\n ResetPasswordFormProps,\n VerifyEmailStatusProps,\n AuthContainerProps,\n AuthHeaderProps,\n AuthErrorBannerProps,\n AuthFormFieldProps,\n AuthPasswordFieldProps,\n AuthPasswordStrengthIndicatorProps,\n AuthSubmitButtonProps,\n AuthLinkProps,\n AuthDividerProps,\n AuthOAuthButtonProps,\n AuthOAuthProvidersProps,\n AuthVerificationCodeInputProps,\n} from './client-boundary/components';\n\n// Hooks\nexport { useAuth, useUser, usePublicAuthConfig } from './client-boundary/hooks';\n"],"mappings":";AAYA,SAAS,kBAAkB,mBAAmB;AAU9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgCP,SAAS,SAAS,SAAS,2BAA2B;","names":[]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// Types (no 'use client' needed for types)\nexport type {\n OAuthProvider,\n AuthConfig,\n EmailVerificationMethod,\n InsforgeUser,\n OAuthProviderConfig,\n} from '@insforge/react/types';\n\n// Provider - Uses conditional exports to provide correct version\n// In Server Components: exports from server/InsforgeProvider (async, uses next/headers)\n// In Client Components: exports from client/provider (use client)\nexport { InsforgeProvider } from '#components';\n\n// Hooks (from client)\nexport { useInsforge } from './client/provider';\n\n/**\n * These need to be explicitly listed. Do not use an * here.\n * If you do, app router will break.\n *\n * Pattern learned from @clerk/nextjs\n */\n\n// Main UI Components\nexport {\n SignIn,\n SignUp,\n ForgotPassword,\n ResetPassword,\n VerifyEmail,\n UserButton,\n Protect,\n SignedIn,\n SignedOut,\n SignInButton,\n SignUpButton,\n} from './client/components';\n\n// Form Components\nexport {\n SignInForm,\n SignUpForm,\n ForgotPasswordForm,\n ResetPasswordForm,\n VerifyEmailStatus,\n} from './client/components';\n\n// Atom Components\nexport {\n AuthBranding,\n AuthContainer,\n AuthHeader,\n AuthErrorBanner,\n AuthFormField,\n AuthPasswordField,\n AuthPasswordStrengthIndicator,\n AuthSubmitButton,\n AuthLink,\n AuthDivider,\n AuthOAuthButton,\n AuthOAuthProviders,\n AuthVerificationCodeInput,\n AuthEmailVerificationStep,\n AuthResetPasswordVerificationStep,\n} from './client/components';\n\n// Component Types\nexport type {\n SignInProps,\n SignUpProps,\n ForgotPasswordProps,\n ResetPasswordProps,\n VerifyEmailProps,\n UserButtonProps,\n ProtectProps,\n ConditionalProps,\n SignInFormProps,\n SignUpFormProps,\n ForgotPasswordFormProps,\n ResetPasswordFormProps,\n VerifyEmailStatusProps,\n AuthContainerProps,\n AuthHeaderProps,\n AuthErrorBannerProps,\n AuthFormFieldProps,\n AuthPasswordFieldProps,\n AuthPasswordStrengthIndicatorProps,\n AuthSubmitButtonProps,\n AuthLinkProps,\n AuthDividerProps,\n AuthOAuthButtonProps,\n AuthOAuthProvidersProps,\n AuthVerificationCodeInputProps,\n} from './client/components';\n\n// Hooks\nexport { useAuth, useUser, usePublicAuthConfig } from './client/hooks';\n"],"mappings":"AAYA,SAAS,wBAAwB;AAGjC,SAAS,mBAAmB;AAU5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAgCP,SAAS,SAAS,SAAS,2BAA2B;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- function InsforgeMiddleware(config) {
2
+ const InsforgeMiddleware = (config) => {
3
3
  const {
4
4
  baseUrl,
5
5
  publicRoutes = ["/"],
@@ -7,15 +7,32 @@ function InsforgeMiddleware(config) {
7
7
  signUpUrl = "/sign-up",
8
8
  forgotPasswordUrl = "/forgot-password",
9
9
  afterSignInUrl = "/",
10
- cookieName = "insforge_token",
11
10
  useBuiltInAuth = true
12
11
  } = config;
12
+ const sessionCookieName = "insforge-session";
13
+ const userCookieName = "insforge-user";
13
14
  return function middleware(request) {
14
15
  const { pathname, searchParams } = request.nextUrl;
15
16
  const accessToken = searchParams.get("access_token");
16
- if (accessToken) {
17
+ const userId = searchParams.get("user_id");
18
+ const email = searchParams.get("email");
19
+ const name = searchParams.get("name");
20
+ if (accessToken && userId && email) {
17
21
  const response = NextResponse.next();
18
- response.cookies.set(cookieName, accessToken, {
22
+ response.cookies.set(sessionCookieName, accessToken, {
23
+ httpOnly: true,
24
+ secure: process.env.NODE_ENV === "production",
25
+ sameSite: "lax",
26
+ path: "/",
27
+ maxAge: 60 * 60 * 24 * 7
28
+ // 7 days
29
+ });
30
+ const userInfo = JSON.stringify({
31
+ id: userId,
32
+ email,
33
+ name: name || ""
34
+ });
35
+ response.cookies.set(userCookieName, userInfo, {
19
36
  httpOnly: true,
20
37
  secure: process.env.NODE_ENV === "production",
21
38
  sameSite: "lax",
@@ -48,7 +65,7 @@ function InsforgeMiddleware(config) {
48
65
  if (isPublicRoute) {
49
66
  return NextResponse.next();
50
67
  }
51
- const token = request.cookies.get(cookieName)?.value;
68
+ const token = request.cookies.get(sessionCookieName)?.value;
52
69
  if (!token) {
53
70
  if (useBuiltInAuth) {
54
71
  const backendSignInUrl = new URL("/auth/sign-in", baseUrl);
@@ -62,7 +79,7 @@ function InsforgeMiddleware(config) {
62
79
  }
63
80
  return NextResponse.next();
64
81
  };
65
- }
82
+ };
66
83
  export {
67
84
  InsforgeMiddleware
68
85
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\n\nexport interface InsforgeMiddlewareConfig {\n /**\n * Base URL of your Insforge backend\n * @example 'https://your-backend.com' or 'http://localhost:3001'\n */\n baseUrl: string;\n\n /**\n * Routes that are public and don't require authentication\n * @default ['/']\n * @example ['/sign-in', '/sign-up', '/', '/about']\n */\n publicRoutes?: string[];\n\n /**\n * Local route path for sign-in (can be customized to any path like '/login')\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\n * @default '/sign-in'\n */\n signInUrl?: string;\n\n /**\n * Local route path for sign-up (can be customized to any path like '/register')\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\n * @default '/sign-up'\n */\n signUpUrl?: string;\n\n /**\n * Local route path for forgot password\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\n * @default '/forgot-password'\n */\n forgotPasswordUrl?: string;\n\n /**\n * URL to redirect to after successful authentication\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\n * @default '/'\n */\n afterSignInUrl?: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Whether to use built-in authentication pages hosted on the backend\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\n * @default true\n */\n useBuiltInAuth?: boolean;\n}\n\n/**\n * Creates Next.js middleware for protecting routes with Insforge authentication.\n *\n * This middleware provides lightweight route protection by:\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\n * - Checking for auth token presence in cookies\n * - Redirecting unauthenticated users to sign-in page\n * - Allowing public routes to be accessed without authentication\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\n *\n * **How Authentication Flow Works:**\n * 1. User visits protected route → Middleware checks for token\n * 2. No token → Redirects to sign-in (backend or local)\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\n *\n * **Important Notes:**\n * - This middleware only checks if a token exists, it doesn't validate it\n * - Tokens from URL are automatically extracted and stored in cookies\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\n *\n * @param config - Middleware configuration\n * @returns Next.js middleware function\n *\n * @example\n * ```ts\n * // middleware.ts - Using built-in auth\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/', '/about'],\n * afterSignInUrl: '/', // Redirect here after successful auth\n * useBuiltInAuth: true,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Custom local auth pages with custom paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/login', '/register', '/', '/about'],\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: false,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Built-in auth with custom auth route paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: 'https://your-backend.com',\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * forgotPasswordUrl: '/forgot',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: true,\n * });\n * ```\n */\nexport function InsforgeMiddleware(config: InsforgeMiddlewareConfig) {\n const {\n baseUrl,\n publicRoutes = ['/'],\n signInUrl = '/sign-in',\n signUpUrl = '/sign-up',\n forgotPasswordUrl = '/forgot-password',\n afterSignInUrl = '/',\n cookieName = 'insforge_token',\n useBuiltInAuth = true,\n } = config;\n\n return function middleware(request: NextRequest) {\n const { pathname, searchParams } = request.nextUrl;\n\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\n const accessToken = searchParams.get('access_token');\n\n if (accessToken) {\n // Token detected in URL - store it in HTTP-only cookie\n const response = NextResponse.next();\n\n // Set HTTP-only cookie with secure settings\n response.cookies.set(cookieName, accessToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: 60 * 60 * 24 * 7, // 7 days\n });\n\n return response;\n }\n\n // STEP 2: Handle built-in auth redirects for authentication pages\n // Map local auth routes to backend's fixed auth pages\n if (useBuiltInAuth) {\n const authRouteMapping: Record<string, string> = {\n [signInUrl]: '/auth/sign-in',\n [signUpUrl]: '/auth/sign-up',\n [forgotPasswordUrl]: '/auth/forgot-password',\n };\n\n const backendAuthPath = authRouteMapping[pathname];\n if (backendAuthPath) {\n // Redirect to afterSignInUrl after successful authentication\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\n return NextResponse.redirect(backendAuthUrl.toString());\n }\n }\n\n // STEP 3: Check if route is public\n const isPublicRoute = publicRoutes.some((route) => {\n if (route.endsWith('*')) {\n // Wildcard route: /admin/* matches /admin/anything\n return pathname.startsWith(route.slice(0, -1));\n }\n // Exact match or starts with route path\n return pathname === route || pathname.startsWith(route + '/');\n });\n\n if (isPublicRoute) {\n return NextResponse.next();\n }\n\n // STEP 4: Check for authentication token in cookies\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n // No token found, redirect to sign-in\n if (useBuiltInAuth) {\n // Built-in auth: redirect to backend's /auth/sign-in page\n // Backend will redirect back to current URL with token\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\n backendSignInUrl.searchParams.set('redirect', request.url);\n return NextResponse.redirect(backendSignInUrl);\n } else {\n // Custom auth: redirect to local sign-in page\n const localSignInUrl = new URL(signInUrl, request.url);\n localSignInUrl.searchParams.set('redirect', pathname);\n return NextResponse.redirect(localSignInUrl);\n }\n }\n\n // Token exists in cookie, allow request to continue\n return NextResponse.next();\n };\n}\n"],"mappings":"AAAA,SAAsB,oBAAoB;AA0InC,SAAS,mBAAmB,QAAkC;AACnE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,SAAS,WAAW,SAAsB;AAC/C,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AAEnD,QAAI,aAAa;AAEf,YAAM,WAAW,aAAa,KAAK;AAGnC,eAAS,QAAQ,IAAI,YAAY,aAAa;AAAA,QAC5C,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,IACT;AAIA,QAAI,gBAAgB;AAClB,YAAM,mBAA2C;AAAA,QAC/C,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,iBAAiB,GAAG;AAAA,MACvB;AAEA,YAAM,kBAAkB,iBAAiB,QAAQ;AACjD,UAAI,iBAAiB;AAEnB,cAAM,cAAc,IAAI,IAAI,gBAAgB,QAAQ,GAAG,EAAE,SAAS;AAClE,cAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,uBAAe,aAAa,IAAI,YAAY,WAAW;AACvD,eAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\n\nexport interface InsforgeMiddlewareConfig {\n /**\n * Base URL of your Insforge backend\n * @example 'https://your-backend.com' or 'http://localhost:3001'\n */\n baseUrl: string;\n\n /**\n * Routes that are public and don't require authentication\n * @default ['/']\n * @example ['/sign-in', '/sign-up', '/', '/about']\n */\n publicRoutes?: string[];\n\n /**\n * Local route path for sign-in (can be customized to any path like '/login')\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\n * @default '/sign-in'\n */\n signInUrl?: string;\n\n /**\n * Local route path for sign-up (can be customized to any path like '/register')\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\n * @default '/sign-up'\n */\n signUpUrl?: string;\n\n /**\n * Local route path for forgot password\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\n * @default '/forgot-password'\n */\n forgotPasswordUrl?: string;\n\n /**\n * URL to redirect to after successful authentication\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\n * @default '/'\n */\n afterSignInUrl?: string;\n\n /**\n * Whether to use built-in authentication pages hosted on the backend\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\n * @default true\n */\n useBuiltInAuth?: boolean;\n}\n\n/**\n * Creates Next.js middleware for protecting routes with Insforge authentication.\n *\n * This middleware provides lightweight route protection by:\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\n * - Checking for auth token presence in cookies\n * - Redirecting unauthenticated users to sign-in page\n * - Allowing public routes to be accessed without authentication\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\n *\n * **How Authentication Flow Works:**\n * 1. User visits protected route → Middleware checks for token\n * 2. No token → Redirects to sign-in (backend or local)\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\n *\n * **Important Notes:**\n * - This middleware only checks if a token exists, it doesn't validate it\n * - Tokens from URL are automatically extracted and stored in cookies\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\n *\n * @param config - Middleware configuration\n * @returns Next.js middleware function\n *\n * @example\n * ```ts\n * // middleware.ts - Using built-in auth\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/', '/about'],\n * afterSignInUrl: '/', // Redirect here after successful auth\n * useBuiltInAuth: true,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Custom local auth pages with custom paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/login', '/register', '/', '/about'],\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: false,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Built-in auth with custom auth route paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: 'https://your-backend.com',\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * forgotPasswordUrl: '/forgot',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: true,\n * });\n * ```\n */\nexport const InsforgeMiddleware = (config: InsforgeMiddlewareConfig) => {\n const {\n baseUrl,\n publicRoutes = ['/'],\n signInUrl = '/sign-in',\n signUpUrl = '/sign-up',\n forgotPasswordUrl = '/forgot-password',\n afterSignInUrl = '/',\n useBuiltInAuth = true,\n } = config;\n\n // Fixed cookie names - not configurable\n const sessionCookieName = 'insforge-session';\n const userCookieName = 'insforge-user';\n\n return function middleware(request: NextRequest) {\n const { pathname, searchParams } = request.nextUrl;\n\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\n const accessToken = searchParams.get('access_token');\n const userId = searchParams.get('user_id');\n const email = searchParams.get('email');\n const name = searchParams.get('name');\n\n if (accessToken && userId && email) {\n // Token detected in URL - store it in HTTP-only cookies\n const response = NextResponse.next();\n\n // Set session cookie (access token)\n response.cookies.set(sessionCookieName, accessToken, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: 60 * 60 * 24 * 7, // 7 days\n });\n\n // Set user identity cookie (basic user info for SSR)\n const userInfo = JSON.stringify({\n id: userId,\n email: email,\n name: name || '',\n });\n\n response.cookies.set(userCookieName, userInfo, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: 60 * 60 * 24 * 7, // 7 days\n });\n\n return response;\n }\n\n // STEP 2: Handle built-in auth redirects for authentication pages\n // Map local auth routes to backend's fixed auth pages\n if (useBuiltInAuth) {\n const authRouteMapping: Record<string, string> = {\n [signInUrl]: '/auth/sign-in',\n [signUpUrl]: '/auth/sign-up',\n [forgotPasswordUrl]: '/auth/forgot-password',\n };\n\n const backendAuthPath = authRouteMapping[pathname];\n if (backendAuthPath) {\n // Redirect to afterSignInUrl after successful authentication\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\n return NextResponse.redirect(backendAuthUrl.toString());\n }\n }\n\n // STEP 3: Check if route is public\n const isPublicRoute = publicRoutes.some((route) => {\n if (route.endsWith('*')) {\n // Wildcard route: /admin/* matches /admin/anything\n return pathname.startsWith(route.slice(0, -1));\n }\n // Exact match or starts with route path\n return pathname === route || pathname.startsWith(route + '/');\n });\n\n if (isPublicRoute) {\n return NextResponse.next();\n }\n\n // STEP 4: Check for authentication token in cookies\n const token = request.cookies.get(sessionCookieName)?.value;\n\n if (!token) {\n // No token found, redirect to sign-in\n if (useBuiltInAuth) {\n // Built-in auth: redirect to backend's /auth/sign-in page\n // Backend will redirect back to current URL with token\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\n backendSignInUrl.searchParams.set('redirect', request.url);\n return NextResponse.redirect(backendSignInUrl);\n } else {\n // Custom auth: redirect to local sign-in page\n const localSignInUrl = new URL(signInUrl, request.url);\n localSignInUrl.searchParams.set('redirect', pathname);\n return NextResponse.redirect(localSignInUrl);\n }\n }\n\n // Token exists in cookie, allow request to continue\n return NextResponse.next();\n };\n}\n"],"mappings":"AAAA,SAAsB,oBAAoB;AAoInC,MAAM,qBAAqB,CAAC,WAAqC;AACtE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB,IAAI;AAGJ,QAAM,oBAAoB;AAC1B,QAAM,iBAAiB;AAEvB,SAAO,SAAS,WAAW,SAAsB;AAC/C,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AACnD,UAAM,SAAS,aAAa,IAAI,SAAS;AACzC,UAAM,QAAQ,aAAa,IAAI,OAAO;AACtC,UAAM,OAAO,aAAa,IAAI,MAAM;AAEpC,QAAI,eAAe,UAAU,OAAO;AAElC,YAAM,WAAW,aAAa,KAAK;AAGnC,eAAS,QAAQ,IAAI,mBAAmB,aAAa;AAAA,QACnD,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,MACzB,CAAC;AAGD,YAAM,WAAW,KAAK,UAAU;AAAA,QAC9B,IAAI;AAAA,QACJ;AAAA,QACA,MAAM,QAAQ;AAAA,MAChB,CAAC;AAED,eAAS,QAAQ,IAAI,gBAAgB,UAAU;AAAA,QAC7C,UAAU;AAAA,QACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,QACjC,UAAU;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,KAAK,KAAK,KAAK;AAAA;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,IACT;AAIA,QAAI,gBAAgB;AAClB,YAAM,mBAA2C;AAAA,QAC/C,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,iBAAiB,GAAG;AAAA,MACvB;AAEA,YAAM,kBAAkB,iBAAiB,QAAQ;AACjD,UAAI,iBAAiB;AAEnB,cAAM,cAAc,IAAI,IAAI,gBAAgB,QAAQ,GAAG,EAAE,SAAS;AAClE,cAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,uBAAe,aAAa,IAAI,YAAY,WAAW;AACvD,eAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,iBAAiB,GAAG;AAEtD,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
@@ -0,0 +1,10 @@
1
+ {
2
+ "sideEffects": false,
3
+ "imports": {
4
+ "#components": {
5
+ "react-server": "./components.server.js",
6
+ "default": "./components.client.js"
7
+ }
8
+ }
9
+ }
10
+
@@ -0,0 +1,102 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { ClientInsforgeProvider } from "../client/provider";
3
+ import { cookies } from "next/headers";
4
+ async function getAuthFromCookies() {
5
+ try {
6
+ const cookieStore = await cookies();
7
+ const sessionToken = cookieStore.get("insforge-session")?.value;
8
+ if (!sessionToken) {
9
+ return {
10
+ user: null,
11
+ userId: null
12
+ };
13
+ }
14
+ const userCookie = cookieStore.get("insforge-user")?.value;
15
+ if (!userCookie) {
16
+ return {
17
+ user: null,
18
+ userId: null
19
+ };
20
+ }
21
+ try {
22
+ const user = JSON.parse(userCookie);
23
+ return {
24
+ user: {
25
+ id: user.id,
26
+ email: user.email,
27
+ name: user.name || ""
28
+ },
29
+ userId: user.id
30
+ };
31
+ } catch {
32
+ return {
33
+ user: null,
34
+ userId: null
35
+ };
36
+ }
37
+ } catch (error) {
38
+ console.error("[Insforge] Error reading cookies:", error);
39
+ return {
40
+ user: null,
41
+ userId: null
42
+ };
43
+ }
44
+ }
45
+ function getAuthFromRequest(request) {
46
+ try {
47
+ const cookieHeader = request.headers.get("cookie") || "";
48
+ const cookies2 = Object.fromEntries(
49
+ cookieHeader.split("; ").map((c) => {
50
+ const [key, ...v] = c.split("=");
51
+ return [key, v.join("=")];
52
+ })
53
+ );
54
+ const sessionToken = cookies2["insforge-session"];
55
+ if (!sessionToken) {
56
+ return {
57
+ user: null,
58
+ userId: null
59
+ };
60
+ }
61
+ const userCookie = cookies2["insforge-user"];
62
+ if (!userCookie) {
63
+ return {
64
+ user: null,
65
+ userId: null
66
+ };
67
+ }
68
+ try {
69
+ const user = JSON.parse(decodeURIComponent(userCookie));
70
+ return {
71
+ user: {
72
+ id: user.id,
73
+ email: user.email,
74
+ name: user.name || ""
75
+ },
76
+ userId: user.id
77
+ };
78
+ } catch {
79
+ return {
80
+ user: null,
81
+ userId: null
82
+ };
83
+ }
84
+ } catch (error) {
85
+ console.error("[Insforge] Error reading cookies from request:", error);
86
+ return {
87
+ user: null,
88
+ userId: null
89
+ };
90
+ }
91
+ }
92
+ async function InsforgeProvider(props) {
93
+ const { children, dynamic = true, ...restProps } = props;
94
+ const initialAuth = dynamic ? await getAuthFromCookies() : { user: null, userId: null };
95
+ return /* @__PURE__ */ jsx(ClientInsforgeProvider, { ...restProps, initialState: initialAuth, children });
96
+ }
97
+ export {
98
+ InsforgeProvider,
99
+ getAuthFromCookies,
100
+ getAuthFromRequest
101
+ };
102
+ //# sourceMappingURL=InsforgeProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/InsforgeProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { ClientInsforgeProvider } from '../client/provider';\nimport type { InsforgeProviderProps } from '@insforge/react';\nimport { cookies } from 'next/headers';\nimport type { InitialAuthState } from '@insforge/react';\n\nexport interface InsforgeProviderServerProps extends Omit<InsforgeProviderProps, 'initialState'> {\n children: ReactNode;\n /**\n * Opt into dynamic rendering to read auth state from cookies during SSR.\n * \n * - When true: Reads cookies on server, prevents content flashing, opts into dynamic rendering\n * - When false: Static rendering, may see brief content flash during hydration\n * \n * Following Clerk's pattern: dynamic prop controls server-side auth state access\n * \n * @default false\n * \n * @example\n * ```tsx\n * <InsforgeProvider baseUrl={...} dynamic>\n * {children}\n * </InsforgeProvider>\n * ```\n */\n dynamic?: boolean;\n}\n\n/**\n * Get initial auth state from cookies (server-side)\n * \n * This helper reads the authentication state from cookies set by the SDK.\n * Use this in Server Components or Server Actions to get the initial auth state\n * and pass it to the InsforgeProvider via initialState prop.\n * \n * This prevents hydration mismatches by ensuring SSR and client render have the same state.\n * \n * @example\n * ```tsx\n * // app/layout.tsx (Server Component)\n * import { InsforgeProvider } from '@insforge/nextjs';\n * import { getAuthFromCookies } from '@insforge/nextjs/api/auth-helpers';\n * \n * export default async function RootLayout({ children }) {\n * const initialAuth = await getAuthFromCookies();\n * \n * return (\n * <html>\n * <body>\n * <InsforgeProvider\n * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}\n * initialState={initialAuth}\n * >\n * {children}\n * </InsforgeProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n * \n * @returns Initial auth state with user and userId, or empty object if not authenticated\n */\nexport async function getAuthFromCookies(): Promise<InitialAuthState> {\n try {\n const cookieStore = await cookies();\n \n // Read session token from cookie (set by middleware or /api/auth route)\n const sessionToken = cookieStore.get('insforge-session')?.value;\n \n if (!sessionToken) {\n // Not authenticated - return null to indicate signed out\n return {\n user: null,\n userId: null,\n };\n }\n\n // Read user identity from cookie (set by middleware or /api/auth route)\n const userCookie = cookieStore.get('insforge-user')?.value;\n \n if (!userCookie) {\n // Have session token but no user info - this shouldn't happen\n // but return null to be safe\n return {\n user: null,\n userId: null,\n };\n }\n\n try {\n const user = JSON.parse(userCookie);\n \n // Return basic user info from cookie\n // This is lightweight data for SSR hydration only\n // Full profile will be loaded by SDK's getCurrentUser() after hydration\n return {\n user: {\n id: user.id,\n email: user.email,\n name: user.name || '',\n },\n userId: user.id,\n };\n } catch {\n // Invalid user data in cookie\n return {\n user: null,\n userId: null,\n };\n }\n } catch (error) {\n // Error reading cookies (might be in middleware or edge runtime)\n console.error('[Insforge] Error reading cookies:', error);\n return {\n user: null,\n userId: null,\n };\n }\n}\n\n/**\n * Synchronous version for use in middleware or edge runtime\n * \n * @param request - Next.js request object\n * @returns Initial auth state\n */\nexport function getAuthFromRequest(request: Request): InitialAuthState {\n try {\n // Parse cookies from request headers\n const cookieHeader = request.headers.get('cookie') || '';\n const cookies = Object.fromEntries(\n cookieHeader.split('; ').map(c => {\n const [key, ...v] = c.split('=');\n return [key, v.join('=')];\n })\n );\n\n const sessionToken = cookies['insforge-session'];\n \n if (!sessionToken) {\n // Not authenticated\n return {\n user: null,\n userId: null,\n };\n }\n\n const userCookie = cookies['insforge-user'];\n \n if (!userCookie) {\n // Have session but no user info\n return {\n user: null,\n userId: null,\n };\n }\n\n try {\n const user = JSON.parse(decodeURIComponent(userCookie));\n \n // Return basic user info from cookie\n // This is lightweight data for SSR hydration only\n return {\n user: {\n id: user.id,\n email: user.email,\n name: user.name || '',\n },\n userId: user.id,\n };\n } catch {\n return {\n user: null,\n userId: null,\n };\n }\n } catch (error) {\n console.error('[Insforge] Error reading cookies from request:', error);\n return {\n user: null,\n userId: null,\n };\n }\n}\n\n\n\n/**\n * Server Component Provider for Insforge\n * \n * This is a Server Component (no 'use client') that:\n * 1. Optionally reads auth state from cookies on the server (when dynamic=true)\n * 2. Passes initialState to the Client Provider\n * 3. Ensures SSR and client hydration match perfectly\n * \n * Following Clerk's pattern: packages/nextjs/src/app-router/server/ClerkProvider.tsx\n * \n * @example\n * ```tsx\n * // app/layout.tsx (Server Component)\n * import { InsforgeProvider } from '@insforge/nextjs';\n * \n * export default async function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <InsforgeProvider\n * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}\n * dynamic // 👈 Enable dynamic rendering for SSR auth\n * >\n * {children}\n * </InsforgeProvider>\n * </body>\n * </html>\n * );\n * }\n * ```\n */\nexport async function InsforgeProvider(props: InsforgeProviderServerProps) {\n const { children, dynamic = true, ...restProps } = props;\n\n // Only read cookies if dynamic=true (opts into dynamic rendering)\n // When dynamic=false, Next.js can statically generate the page\n const initialAuth = dynamic \n ? await getAuthFromCookies()\n : { user: null, userId: null };\n\n // Pass initialState to Client Provider\n return (\n <ClientInsforgeProvider {...restProps} initialState={initialAuth}>\n {children}\n </ClientInsforgeProvider>\n );\n}\n\n"],"mappings":"AAsOI;AArOJ,SAAS,8BAA8B;AAEvC,SAAS,eAAe;AA4DxB,eAAsB,qBAAgD;AACpE,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAGlC,UAAM,eAAe,YAAY,IAAI,kBAAkB,GAAG;AAE1D,QAAI,CAAC,cAAc;AAEjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,UAAM,aAAa,YAAY,IAAI,eAAe,GAAG;AAErD,QAAI,CAAC,YAAY;AAGf,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,UAAU;AAKlC,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,IAAI,KAAK;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK,QAAQ;AAAA,QACrB;AAAA,QACA,QAAQ,KAAK;AAAA,MACf;AAAA,IACF,QAAQ;AAEN,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,YAAQ,MAAM,qCAAqC,KAAK;AACxD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAQO,SAAS,mBAAmB,SAAoC;AACrE,MAAI;AAEF,UAAM,eAAe,QAAQ,QAAQ,IAAI,QAAQ,KAAK;AACtD,UAAMA,WAAU,OAAO;AAAA,MACrB,aAAa,MAAM,IAAI,EAAE,IAAI,OAAK;AAChC,cAAM,CAAC,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG;AAC/B,eAAO,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,UAAM,eAAeA,SAAQ,kBAAkB;AAE/C,QAAI,CAAC,cAAc;AAEjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,UAAM,aAAaA,SAAQ,eAAe;AAE1C,QAAI,CAAC,YAAY;AAEf,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,mBAAmB,UAAU,CAAC;AAItD,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,IAAI,KAAK;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK,QAAQ;AAAA,QACrB;AAAA,QACA,QAAQ,KAAK;AAAA,MACf;AAAA,IACF,QAAQ;AACN,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,kDAAkD,KAAK;AACrE,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAmCA,eAAsB,iBAAiB,OAAoC;AACzE,QAAM,EAAE,UAAU,UAAU,MAAM,GAAG,UAAU,IAAI;AAInD,QAAM,cAAc,UAChB,MAAM,mBAAmB,IACzB,EAAE,MAAM,MAAM,QAAQ,KAAK;AAG/B,SACE,oBAAC,0BAAwB,GAAG,WAAW,cAAc,aAClD,UACH;AAEJ;","names":["cookies"]}
@@ -0,0 +1,5 @@
1
+ import { InsforgeProvider } from "./InsforgeProvider";
2
+ export {
3
+ InsforgeProvider
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["// Server-side exports (Server Components, no 'use client')\r\nexport { InsforgeProvider } from './InsforgeProvider';\r\n\r\n"],"mappings":"AACA,SAAS,wBAAwB;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  export { AuthConfig, EmailVerificationMethod, InsforgeUser, OAuthProvider, OAuthProviderConfig } from '@insforge/react/types';
2
- export { InsforgeProvider, useInsforge } from './client-boundary/provider.js';
2
+ export { InsforgeProvider } from './server/InsforgeProvider.js';
3
+ export { useInsforge } from './client/provider.js';
3
4
  export { AuthBranding, AuthContainer, AuthContainerProps, AuthDivider, AuthDividerProps, AuthEmailVerificationStep, AuthErrorBanner, AuthErrorBannerProps, AuthFormField, AuthFormFieldProps, AuthHeader, AuthHeaderProps, AuthLink, AuthLinkProps, AuthOAuthButton, AuthOAuthButtonProps, AuthOAuthProviders, AuthOAuthProvidersProps, AuthPasswordField, AuthPasswordFieldProps, AuthPasswordStrengthIndicator, AuthPasswordStrengthIndicatorProps, AuthResetPasswordVerificationStep, AuthSubmitButton, AuthSubmitButtonProps, AuthVerificationCodeInput, AuthVerificationCodeInputProps, ConditionalProps, ForgotPassword, ForgotPasswordForm, ForgotPasswordFormProps, ForgotPasswordProps, Protect, ProtectProps, ResetPassword, ResetPasswordForm, ResetPasswordFormProps, ResetPasswordProps, SignIn, SignInButton, SignInForm, SignInFormProps, SignInProps, SignUp, SignUpButton, SignUpForm, SignUpFormProps, SignUpProps, SignedIn, SignedOut, UserButton, UserButtonProps, VerifyEmail, VerifyEmailProps, VerifyEmailStatus, VerifyEmailStatusProps } from '@insforge/react/components';
4
- export { useAuth, usePublicAuthConfig, useUser } from './client-boundary/hooks.js';
5
+ export { useAuth, usePublicAuthConfig, useUser } from './client/hooks.js';
5
6
  import 'react/jsx-runtime';
7
+ import 'react';
6
8
  import '@insforge/react';
7
9
  import '@insforge/shared';
8
10
  import '@insforge/shared-schemas';
@@ -36,11 +36,6 @@ interface InsforgeMiddlewareConfig {
36
36
  * @default '/'
37
37
  */
38
38
  afterSignInUrl?: string;
39
- /**
40
- * Cookie name for the auth token
41
- * @default 'insforge_token'
42
- */
43
- cookieName?: string;
44
39
  /**
45
40
  * Whether to use built-in authentication pages hosted on the backend
46
41
  * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages
@@ -128,6 +123,6 @@ interface InsforgeMiddlewareConfig {
128
123
  * });
129
124
  * ```
130
125
  */
131
- declare function InsforgeMiddleware(config: InsforgeMiddlewareConfig): (request: NextRequest) => NextResponse<unknown>;
126
+ declare const InsforgeMiddleware: (config: InsforgeMiddlewareConfig) => (request: NextRequest) => NextResponse<unknown>;
132
127
 
133
128
  export { InsforgeMiddleware, type InsforgeMiddlewareConfig };
@@ -0,0 +1,102 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { InsforgeProviderProps, InitialAuthState } from '@insforge/react';
4
+
5
+ interface InsforgeProviderServerProps extends Omit<InsforgeProviderProps, 'initialState'> {
6
+ children: ReactNode;
7
+ /**
8
+ * Opt into dynamic rendering to read auth state from cookies during SSR.
9
+ *
10
+ * - When true: Reads cookies on server, prevents content flashing, opts into dynamic rendering
11
+ * - When false: Static rendering, may see brief content flash during hydration
12
+ *
13
+ * Following Clerk's pattern: dynamic prop controls server-side auth state access
14
+ *
15
+ * @default false
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * <InsforgeProvider baseUrl={...} dynamic>
20
+ * {children}
21
+ * </InsforgeProvider>
22
+ * ```
23
+ */
24
+ dynamic?: boolean;
25
+ }
26
+ /**
27
+ * Get initial auth state from cookies (server-side)
28
+ *
29
+ * This helper reads the authentication state from cookies set by the SDK.
30
+ * Use this in Server Components or Server Actions to get the initial auth state
31
+ * and pass it to the InsforgeProvider via initialState prop.
32
+ *
33
+ * This prevents hydration mismatches by ensuring SSR and client render have the same state.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * // app/layout.tsx (Server Component)
38
+ * import { InsforgeProvider } from '@insforge/nextjs';
39
+ * import { getAuthFromCookies } from '@insforge/nextjs/api/auth-helpers';
40
+ *
41
+ * export default async function RootLayout({ children }) {
42
+ * const initialAuth = await getAuthFromCookies();
43
+ *
44
+ * return (
45
+ * <html>
46
+ * <body>
47
+ * <InsforgeProvider
48
+ * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}
49
+ * initialState={initialAuth}
50
+ * >
51
+ * {children}
52
+ * </InsforgeProvider>
53
+ * </body>
54
+ * </html>
55
+ * );
56
+ * }
57
+ * ```
58
+ *
59
+ * @returns Initial auth state with user and userId, or empty object if not authenticated
60
+ */
61
+ declare function getAuthFromCookies(): Promise<InitialAuthState>;
62
+ /**
63
+ * Synchronous version for use in middleware or edge runtime
64
+ *
65
+ * @param request - Next.js request object
66
+ * @returns Initial auth state
67
+ */
68
+ declare function getAuthFromRequest(request: Request): InitialAuthState;
69
+ /**
70
+ * Server Component Provider for Insforge
71
+ *
72
+ * This is a Server Component (no 'use client') that:
73
+ * 1. Optionally reads auth state from cookies on the server (when dynamic=true)
74
+ * 2. Passes initialState to the Client Provider
75
+ * 3. Ensures SSR and client hydration match perfectly
76
+ *
77
+ * Following Clerk's pattern: packages/nextjs/src/app-router/server/ClerkProvider.tsx
78
+ *
79
+ * @example
80
+ * ```tsx
81
+ * // app/layout.tsx (Server Component)
82
+ * import { InsforgeProvider } from '@insforge/nextjs';
83
+ *
84
+ * export default async function RootLayout({ children }) {
85
+ * return (
86
+ * <html>
87
+ * <body>
88
+ * <InsforgeProvider
89
+ * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}
90
+ * dynamic // 👈 Enable dynamic rendering for SSR auth
91
+ * >
92
+ * {children}
93
+ * </InsforgeProvider>
94
+ * </body>
95
+ * </html>
96
+ * );
97
+ * }
98
+ * ```
99
+ */
100
+ declare function InsforgeProvider(props: InsforgeProviderServerProps): Promise<react_jsx_runtime.JSX.Element>;
101
+
102
+ export { InsforgeProvider, type InsforgeProviderServerProps, getAuthFromCookies, getAuthFromRequest };
@@ -0,0 +1,4 @@
1
+ export { InsforgeProvider } from './InsforgeProvider.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import '@insforge/react';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@insforge/nextjs",
3
- "version": "0.10.9",
3
+ "version": "0.10.10",
4
4
  "description": "Pre-built authentication UI components for Next.js with Insforge backend - zero configuration required",
5
5
  "type": "module",
6
6
  "types": "./dist/index.d.ts",
@@ -9,6 +9,10 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "import": "./dist/esm/index.js"
11
11
  },
12
+ "./server": {
13
+ "types": "./dist/server/index.d.ts",
14
+ "import": "./dist/esm/server/index.js"
15
+ },
12
16
  "./middleware": {
13
17
  "types": "./dist/middleware/index.d.ts",
14
18
  "import": "./dist/esm/middleware/index.js"
@@ -41,9 +45,9 @@
41
45
  "author": "Insforge",
42
46
  "license": "MIT",
43
47
  "dependencies": {
44
- "@insforge/react": "^0.6.5",
48
+ "@insforge/react": "^0.6.6",
45
49
  "@insforge/sdk": "^0.0.58",
46
- "@insforge/shared": "^0.1.2",
50
+ "@insforge/shared": "^0.1.5",
47
51
  "@insforge/shared-schemas": "^1.1.19"
48
52
  },
49
53
  "devDependencies": {
@@ -1,50 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { InsforgeProviderProps, useInsforge as useInsforge$1 } from '@insforge/react';
3
-
4
- /**
5
- * Insforge Provider for Next.js - wraps @insforge/react provider with Next.js-specific cookie sync
6
- *
7
- * Manages user authentication state and provides all necessary context to child components.
8
- * Automatically syncs authentication tokens to HTTP-only cookies for server-side middleware support.
9
- *
10
- * @example
11
- * ```tsx
12
- * import { InsforgeProvider } from '@insforge/nextjs';
13
- *
14
- * export default function RootLayout({ children }) {
15
- * return (
16
- * <InsforgeProvider
17
- * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}
18
- * afterSignInUrl="/dashboard"
19
- * >
20
- * {children}
21
- * </InsforgeProvider>
22
- * );
23
- * }
24
- * ```
25
- */
26
- declare function InsforgeProvider({ children, baseUrl, afterSignInUrl, onAuthChange, }: InsforgeProviderProps): react_jsx_runtime.JSX.Element;
27
- /**
28
- * Hook to access Insforge context
29
- *
30
- * Re-exports the hook from @insforge/react for convenience.
31
- *
32
- * @example
33
- * ```tsx
34
- * function MyComponent() {
35
- * const { user, isSignedIn, signOut } = useInsforge();
36
- *
37
- * if (!isSignedIn) return <SignIn />;
38
- *
39
- * return (
40
- * <div>
41
- * <p>Welcome {user.email}</p>
42
- * <button onClick={signOut}>Sign Out</button>
43
- * </div>
44
- * );
45
- * }
46
- * ```
47
- */
48
- declare const useInsforge: typeof useInsforge$1;
49
-
50
- export { InsforgeProvider, useInsforge };
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/client-boundary/components.tsx"],"sourcesContent":["'use client';\n\n/**\n * Client-side UI components boundary for Next.js App Router\n * All components from @insforge/react are re-exported here with 'use client' directive\n */\n\n// Main components\nexport {\n SignIn,\n SignUp,\n ForgotPassword,\n ResetPassword,\n VerifyEmail,\n UserButton,\n Protect,\n SignedIn,\n SignedOut,\n SignInButton,\n SignUpButton,\n} from '@insforge/react/components';\n\n// Form components\nexport {\n SignInForm,\n SignUpForm,\n ForgotPasswordForm,\n ResetPasswordForm,\n VerifyEmailStatus,\n} from '@insforge/react/components';\n\n// Atom components\nexport {\n AuthBranding,\n AuthContainer,\n AuthHeader,\n AuthErrorBanner,\n AuthFormField,\n AuthPasswordField,\n AuthPasswordStrengthIndicator,\n AuthSubmitButton,\n AuthLink,\n AuthDivider,\n AuthOAuthButton,\n AuthOAuthProviders,\n AuthVerificationCodeInput,\n AuthEmailVerificationStep,\n AuthResetPasswordVerificationStep,\n} from '@insforge/react/components';\n\n// Re-export all component types\nexport type {\n SignInProps,\n SignUpProps,\n ForgotPasswordProps,\n ResetPasswordProps,\n VerifyEmailProps,\n UserButtonProps,\n ProtectProps,\n ConditionalProps,\n SignInFormProps,\n SignUpFormProps,\n ForgotPasswordFormProps,\n ResetPasswordFormProps,\n VerifyEmailStatusProps,\n AuthContainerProps,\n AuthHeaderProps,\n AuthErrorBannerProps,\n AuthFormFieldProps,\n AuthPasswordFieldProps,\n AuthPasswordStrengthIndicatorProps,\n AuthSubmitButtonProps,\n AuthLinkProps,\n AuthDividerProps,\n AuthOAuthButtonProps,\n AuthOAuthProvidersProps,\n AuthVerificationCodeInputProps,\n} from '@insforge/react/components';\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/client-boundary/hooks.ts"],"sourcesContent":["'use client';\n\nimport { useInsforge } from './provider';\n\n/**\n * Next.js specific hooks - implemented locally to avoid Context duplication\n */\n\nexport function useAuth() {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n\nexport function useUser() {\n const { user, isLoaded } = useInsforge();\n return { user, isLoaded };\n}\n\nexport function usePublicAuthConfig() {\n const { getPublicAuthConfig } = useInsforge();\n return { getPublicAuthConfig };\n}\n"],"mappings":";AAEA,SAAS,mBAAmB;AAMrB,SAAS,UAAU;AACxB,QAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW,IAAI,YAAY;AACtE,SAAO,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW;AACzD;AAEO,SAAS,UAAU;AACxB,QAAM,EAAE,MAAM,SAAS,IAAI,YAAY;AACvC,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEO,SAAS,sBAAsB;AACpC,QAAM,EAAE,oBAAoB,IAAI,YAAY;AAC5C,SAAO,EAAE,oBAAoB;AAC/B;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../src/client-boundary/provider.tsx"],"sourcesContent":["'use client';\n\nimport {\n InsforgeProviderCore,\n type InsforgeProviderProps,\n useInsforge as useReactInsforge,\n NavigationProvider,\n} from '@insforge/react';\nimport { NavigationAdapter } from '../navigation';\n\n// Extended interface for React provider that includes internal handlers\ninterface ExtendedProviderProps extends InsforgeProviderProps {\n afterSignInUrl?: string;\n onSignIn?: (authToken: string) => Promise<void>;\n onSignOut?: () => Promise<void>;\n}\n\n// Sync token to server-side cookie on sign in\nasync function handleSignIn(token: string): Promise<void> {\n try {\n await fetch('/api/auth', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'sync-token',\n token,\n }),\n });\n } catch (err) {\n console.error('[InsforgeProvider] Failed to sync token to cookie:', err);\n }\n}\n\n// Clear HTTP-only cookie on sign out\nasync function handleSignOut(): Promise<void> {\n try {\n await fetch('/api/auth', { method: 'DELETE' });\n } catch {\n // API route doesn't exist - ignore\n }\n}\n\n/**\n * Insforge Provider for Next.js - wraps @insforge/react provider with Next.js-specific cookie sync\n *\n * Manages user authentication state and provides all necessary context to child components.\n * Automatically syncs authentication tokens to HTTP-only cookies for server-side middleware support.\n *\n * @example\n * ```tsx\n * import { InsforgeProvider } from '@insforge/nextjs';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <InsforgeProvider\n * baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}\n * afterSignInUrl=\"/dashboard\"\n * >\n * {children}\n * </InsforgeProvider>\n * );\n * }\n * ```\n */\nexport function InsforgeProvider({\n children,\n baseUrl,\n afterSignInUrl = '/',\n onAuthChange,\n}: InsforgeProviderProps) {\n const providerProps: ExtendedProviderProps = {\n children,\n baseUrl,\n afterSignInUrl,\n onAuthChange,\n onSignIn: handleSignIn,\n onSignOut: handleSignOut,\n };\n\n return (\n <NavigationProvider adapter={NavigationAdapter}>\n <InsforgeProviderCore {...providerProps}>{children}</InsforgeProviderCore>\n </NavigationProvider>\n );\n}\n\n/**\n * Hook to access Insforge context\n *\n * Re-exports the hook from @insforge/react for convenience.\n *\n * @example\n * ```tsx\n * function MyComponent() {\n * const { user, isSignedIn, signOut } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <p>Welcome {user.email}</p>\n * <button onClick={signOut}>Sign Out</button>\n * </div>\n * );\n * }\n * ```\n */\nexport const useInsforge = useReactInsforge;\n"],"mappings":";AAmFM;AAjFN;AAAA,EACE;AAAA,EAEA,eAAe;AAAA,EACf;AAAA,OACK;AACP,SAAS,yBAAyB;AAUlC,eAAe,aAAa,OAA8B;AACxD,MAAI;AACF,UAAM,MAAM,aAAa;AAAA,MACvB,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB,QAAQ;AAAA,QACR;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,YAAQ,MAAM,sDAAsD,GAAG;AAAA,EACzE;AACF;AAGA,eAAe,gBAA+B;AAC5C,MAAI;AACF,UAAM,MAAM,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAwBO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AACF,GAA0B;AACxB,QAAM,gBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,EACb;AAEA,SACE,oBAAC,sBAAmB,SAAS,mBAC3B,8BAAC,wBAAsB,GAAG,eAAgB,UAAS,GACrD;AAEJ;AAuBO,MAAM,cAAc;","names":[]}
File without changes
File without changes