@insforge/nextjs 1.0.7 → 1.0.8-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/provider.d.ts +0 -1
- package/dist/components.client.d.ts +1 -4
- package/dist/components.server.d.ts +3 -9
- package/dist/esm/api/route-handlers.js +17 -0
- package/dist/esm/api/route-handlers.js.map +1 -1
- package/dist/esm/client/provider.js +7 -6
- package/dist/esm/client/provider.js.map +1 -1
- package/dist/esm/components.client.js +0 -10
- package/dist/esm/components.client.js.map +1 -1
- package/dist/esm/components.server.js +8 -2
- package/dist/esm/components.server.js.map +1 -1
- package/dist/esm/index.js +6 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/package.json +9 -9
- package/dist/esm/server/InsforgeProvider.js +10 -3
- package/dist/esm/server/InsforgeProvider.js.map +1 -1
- package/dist/esm/server/index.js +5 -1
- package/dist/esm/server/index.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/server/InsforgeProvider.d.ts +27 -14
- package/dist/server/index.d.ts +1 -3
- package/package.json +4 -4
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export { InsforgeAuth, auth } from './server/auth.js';
|
|
2
|
+
export { InsforgeProviderServerProps, InsforgeServerProvider, InsforgeServerProviderProps, getAuthFromCookies } from './server/InsforgeProvider.js';
|
|
3
|
+
import '@insforge/shared';
|
|
3
4
|
import 'react';
|
|
4
5
|
import '@insforge/react';
|
|
5
|
-
import '@insforge/sdk';
|
|
6
|
-
|
|
7
|
-
type ServerComponentsServerModuleTypes = {
|
|
8
|
-
InsforgeProvider: typeof InsforgeProvider;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export { InsforgeProvider, type ServerComponentsServerModuleTypes };
|
|
@@ -114,6 +114,23 @@ function createAuthRouteHandlers(config) {
|
|
|
114
114
|
console.error("[Auth Route] No token provided in header");
|
|
115
115
|
return NextResponse.json({ error: "Token is required" }, { status: 400 });
|
|
116
116
|
}
|
|
117
|
+
const { user: userFromBody } = body;
|
|
118
|
+
if (userFromBody?.id && userFromBody?.email) {
|
|
119
|
+
const nextResponse = NextResponse.json({
|
|
120
|
+
user: userFromBody,
|
|
121
|
+
session: {
|
|
122
|
+
userId: userFromBody.id,
|
|
123
|
+
expiresAt: "",
|
|
124
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
setAuthCookies(nextResponse, token, {
|
|
128
|
+
id: userFromBody.id,
|
|
129
|
+
email: userFromBody.email,
|
|
130
|
+
profile: userFromBody.profile || null
|
|
131
|
+
});
|
|
132
|
+
return nextResponse;
|
|
133
|
+
}
|
|
117
134
|
try {
|
|
118
135
|
const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {
|
|
119
136
|
headers: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\nimport {\n COOKIE_NAMES,\n COOKIE_DEFAULTS,\n getBaseCookieOptions,\n getClearCookieOptions,\n serializeUserCookie,\n} from '../lib/cookies';\nimport { InsforgeUser } from '@insforge/shared';\nimport { GetCurrentSessionResponse } from '@insforge/shared-schemas';\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}\n\ntype AuthRequestBody = SignInRequestBody | SignUpRequestBody | SyncTokenRequestBody;\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\ninterface AuthRouteHandlers {\n POST: (request: NextRequest) => Promise<NextResponse>;\n GET: (request: NextRequest) => Promise<NextResponse>;\n DELETE: (request: NextRequest) => Promise<NextResponse>;\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): AuthRouteHandlers {\n const { baseUrl, cookieMaxAge = COOKIE_DEFAULTS.MAX_AGE } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookies (session token + user identity)\n */\n function setAuthCookies(response: NextResponse, token: string, user: InsforgeUser) {\n const cookieOptions = getBaseCookieOptions({\n maxAge: cookieMaxAge,\n secure: config.secure,\n });\n\n // Set session cookie (access token)\n response.cookies.set({\n name: COOKIE_NAMES.SESSION,\n value: token,\n ...cookieOptions,\n });\n\n // Set user identity cookie (basic info for SSR)\n response.cookies.set({\n name: COOKIE_NAMES.USER,\n value: serializeUserCookie(user),\n ...cookieOptions,\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookies\n */\n function clearAuthCookies(response: NextResponse) {\n const clearOptions = getClearCookieOptions({ secure: config.secure });\n\n // Clear session cookie\n response.cookies.set({\n name: COOKIE_NAMES.SESSION,\n value: '',\n ...clearOptions,\n });\n\n // Clear user cookie\n response.cookies.set({\n name: COOKIE_NAMES.USER,\n value: '',\n ...clearOptions,\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 profile: result.data.user.profile || null,\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 profile: result.data.user.profile || null,\n });\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs access token to HTTP-only cookie for server-side usage\n // Token is passed via Authorization header (preferred)\n const authHeader = request.headers.get('Authorization');\n const tokenFromHeader = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\n const token = tokenFromHeader;\n\n if (!token) {\n console.error('[Auth Route] No token provided in header');\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 GetCurrentSessionResponse;\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 profile: session.user.profile || null,\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(COOKIE_NAMES.SESSION)?.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 GetCurrentSessionResponse;\n\n return NextResponse.json({\n user: session.user,\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(COOKIE_NAMES.SESSION)?.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":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\nimport {\n COOKIE_NAMES,\n COOKIE_DEFAULTS,\n getBaseCookieOptions,\n getClearCookieOptions,\n serializeUserCookie,\n} from '../lib/cookies';\nimport { InsforgeUser } from '@insforge/shared';\nimport { GetCurrentSessionResponse } from '@insforge/shared-schemas';\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}\n\ntype AuthRequestBody = SignInRequestBody | SignUpRequestBody | SyncTokenRequestBody;\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\ninterface AuthRouteHandlers {\n POST: (request: NextRequest) => Promise<NextResponse>;\n GET: (request: NextRequest) => Promise<NextResponse>;\n DELETE: (request: NextRequest) => Promise<NextResponse>;\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): AuthRouteHandlers {\n const { baseUrl, cookieMaxAge = COOKIE_DEFAULTS.MAX_AGE } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookies (session token + user identity)\n */\n function setAuthCookies(response: NextResponse, token: string, user: InsforgeUser) {\n const cookieOptions = getBaseCookieOptions({\n maxAge: cookieMaxAge,\n secure: config.secure,\n });\n\n // Set session cookie (access token)\n response.cookies.set({\n name: COOKIE_NAMES.SESSION,\n value: token,\n ...cookieOptions,\n });\n\n // Set user identity cookie (basic info for SSR)\n response.cookies.set({\n name: COOKIE_NAMES.USER,\n value: serializeUserCookie(user),\n ...cookieOptions,\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookies\n */\n function clearAuthCookies(response: NextResponse) {\n const clearOptions = getClearCookieOptions({ secure: config.secure });\n\n // Clear session cookie\n response.cookies.set({\n name: COOKIE_NAMES.SESSION,\n value: '',\n ...clearOptions,\n });\n\n // Clear user cookie\n response.cookies.set({\n name: COOKIE_NAMES.USER,\n value: '',\n ...clearOptions,\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 profile: result.data.user.profile || null,\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 profile: result.data.user.profile || null,\n });\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs access token to HTTP-only cookie for server-side usage\n // Token is passed via Authorization header (preferred)\n const authHeader = request.headers.get('Authorization');\n const tokenFromHeader = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\n const token = tokenFromHeader;\n\n if (!token) {\n console.error('[Auth Route] No token provided in header');\n return NextResponse.json({ error: 'Token is required' }, { status: 400 });\n }\n\n // User data can be passed from client (preferred) or fetched from backend\n const { user: userFromBody } = body as { user?: InsforgeUser };\n\n // If user data is provided by client, use it directly (faster)\n if (userFromBody?.id && userFromBody?.email) {\n const nextResponse = NextResponse.json({\n user: userFromBody,\n session: {\n userId: userFromBody.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookies(nextResponse, token, {\n id: userFromBody.id,\n email: userFromBody.email,\n profile: userFromBody.profile || null,\n });\n\n return nextResponse;\n }\n\n // Fallback: Verify the token and get user data from 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 GetCurrentSessionResponse;\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 profile: session.user.profile || null,\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(COOKIE_NAMES.SESSION)?.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 GetCurrentSessionResponse;\n\n return NextResponse.json({\n user: session.user,\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(COOKIE_NAMES.SESSION)?.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":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
StyleProvider
|
|
8
8
|
} from "@insforge/react";
|
|
9
9
|
import { NavigationAdapter } from "../navigation";
|
|
10
|
-
async function
|
|
10
|
+
async function syncToCookie(token, user) {
|
|
11
11
|
try {
|
|
12
12
|
const response = await fetch("/api/auth", {
|
|
13
13
|
method: "POST",
|
|
@@ -16,7 +16,8 @@ async function syncTokenToCookie(token) {
|
|
|
16
16
|
"Content-Type": "application/json"
|
|
17
17
|
},
|
|
18
18
|
body: JSON.stringify({
|
|
19
|
-
action: "sync-token"
|
|
19
|
+
action: "sync-token",
|
|
20
|
+
user
|
|
20
21
|
})
|
|
21
22
|
});
|
|
22
23
|
if (!response.ok) {
|
|
@@ -27,11 +28,11 @@ async function syncTokenToCookie(token) {
|
|
|
27
28
|
console.error("[InsforgeBrowserProvider] Failed to sync token to cookie:", err);
|
|
28
29
|
}
|
|
29
30
|
}
|
|
30
|
-
async function handleSignIn(token) {
|
|
31
|
-
await
|
|
31
|
+
async function handleSignIn(token, user) {
|
|
32
|
+
await syncToCookie(token, user);
|
|
32
33
|
}
|
|
33
|
-
async function handleRefresh(token) {
|
|
34
|
-
await
|
|
34
|
+
async function handleRefresh(token, user) {
|
|
35
|
+
await syncToCookie(token, user);
|
|
35
36
|
}
|
|
36
37
|
async function handleSignOut() {
|
|
37
38
|
try {
|
|
@@ -1 +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 StyleProvider,\n InsforgeUser,\n} from '@insforge/react';\nimport { NavigationAdapter } from '../navigation';\nimport type { InsForgeClient } from '@insforge/sdk';\n\n/**\n * Props for InsforgeBrowserProvider\n */\nexport interface InsforgeBrowserProviderProps extends InsforgeProviderProps {\n children: React.ReactNode;\n /**\n * The InsForge SDK client instance.\n *\n * **Important:** Use the same client instance that you use for database,\n * storage, and other SDK operations. This ensures authentication tokens\n * are shared correctly.\n */\n client: InsForgeClient;\n /**\n * URL to redirect to after successful sign in\n * @default '/'\n */\n afterSignInUrl?: string;\n /**\n * Callback when auth state changes\n */\n onAuthChange?: (user: InsforgeUser | null) => void;\n /**\n * Initial auth state from server (for SSR hydration).\n * Get this using `getAuthFromCookies()`.\n */\n initialState?: InitialAuthState;\n}\n\n// Sync
|
|
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 StyleProvider,\n InsforgeUser,\n} from '@insforge/react';\nimport { NavigationAdapter } from '../navigation';\nimport type { InsForgeClient } from '@insforge/sdk';\n\n/**\n * Props for InsforgeBrowserProvider\n */\nexport interface InsforgeBrowserProviderProps extends InsforgeProviderProps {\n children: React.ReactNode;\n /**\n * The InsForge SDK client instance.\n *\n * **Important:** Use the same client instance that you use for database,\n * storage, and other SDK operations. This ensures authentication tokens\n * are shared correctly.\n */\n client: InsForgeClient;\n /**\n * URL to redirect to after successful sign in\n * @default '/'\n */\n afterSignInUrl?: string;\n /**\n * Callback when auth state changes\n */\n onAuthChange?: (user: InsforgeUser | null) => void;\n /**\n * Initial auth state from server (for SSR hydration).\n * Get this using `getAuthFromCookies()`.\n */\n initialState?: InitialAuthState;\n}\n\n// Sync to server-side cookie using Authorization header\nasync function syncToCookie(token: string, user: InsforgeUser): Promise<void> {\n try {\n const response = await fetch('/api/auth', {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n action: 'sync-token',\n user: user,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[InsforgeBrowserProvider] sync-token failed:', errorText);\n }\n } catch (err) {\n console.error('[InsforgeBrowserProvider] Failed to sync token to cookie:', err);\n }\n}\n\n// Sync token to server-side cookie on sign in\nasync function handleSignIn(token: string, user: InsforgeUser): Promise<void> {\n await syncToCookie(token, user);\n}\n\n// Sync token to server-side cookie on refresh (page load/refresh)\nasync function handleRefresh(token: string, user: InsforgeUser): Promise<void> {\n await syncToCookie(token, user);\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 * Browser-side Insforge Provider for Next.js\n *\n * This provider manages authentication state on the client side and automatically\n * syncs tokens to HTTP-only cookies via `/api/auth` route for server-side access.\n *\n * **Key Features:**\n * - Uses YOUR SDK client instance (shared with database/storage operations)\n * - Automatic token sync to HTTP-only cookies\n * - SSR hydration support via `initialState`\n * - Works with Next.js App Router\n *\n * ---\n *\n * ## Setup Guide\n *\n * ### Step 1: Create your SDK client\n *\n * @example\n * ```tsx\n * // lib/insforge.ts\n * import { createClient } from '@insforge/sdk';\n *\n * export const insforge = createClient({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_URL!,\n * anonKey: process.env.NEXT_PUBLIC_INSFORGE_ANON_KEY!,\n * });\n * ```\n *\n * ### Step 2: Create your Providers component\n *\n * @example\n * ```tsx\n * // app/providers.tsx\n * 'use client';\n * import { InsforgeBrowserProvider, type InitialAuthState } from '@insforge/nextjs';\n * import { insforge } from '@/lib/insforge';\n *\n * export function Providers({\n * children,\n * }: {\n * children: React.ReactNode;\n * }) {\n * return (\n * <InsforgeBrowserProvider\n * client={insforge}\n * afterSignInUrl=\"/dashboard\"\n * >\n * {children}\n * </InsforgeBrowserProvider>\n * );\n * }\n * ```\n *\n * ### Step 3: Use in your root layout\n *\n * @example\n * ```tsx\n * // app/layout.tsx\n * import { getAuthFromCookies } from '@insforge/nextjs';\n * import { Providers } from './providers';\n *\n * export default async function RootLayout({\n * children,\n * }: {\n * children: React.ReactNode;\n * }) {\n * const initialState = await getAuthFromCookies();\n *\n * return (\n * <html>\n * <body>\n * <Providers initialState={initialState}>\n * {children}\n * </Providers>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * ### Step 4: Use auth components and hooks\n *\n * @example\n * ```tsx\n * // app/page.tsx\n * 'use client';\n * import { SignIn, UserButton, useInsforge } from '@insforge/nextjs';\n *\n * export default function Page() {\n * const { isSignedIn, user } = useInsforge();\n *\n * if (!isSignedIn) return <SignIn />;\n *\n * return (\n * <div>\n * <UserButton />\n * <p>Welcome {user?.email}</p>\n * </div>\n * );\n * }\n * ```\n *\n * ---\n *\n * ## Why pass your own client?\n *\n * Authentication tokens are stored in the SDK client instance's memory.\n * If auth components use a different client than your app, they won't share\n * tokens, causing authentication to fail for database/storage operations.\n *\n * By passing YOUR client to the provider, all operations use the same\n * authenticated session.\n */\nexport function InsforgeBrowserProvider({\n children,\n client,\n afterSignInUrl = '/',\n onAuthChange,\n initialState = { user: null, userId: null },\n}: InsforgeBrowserProviderProps) {\n const providerProps: InsforgeProviderProps = {\n children,\n client,\n afterSignInUrl,\n onAuthChange,\n onSignIn: handleSignIn,\n onSignOut: handleSignOut,\n onRefresh: handleRefresh,\n initialState,\n };\n\n return (\n <StyleProvider>\n <NavigationProvider adapter={NavigationAdapter}>\n <InsforgeProviderCore {...providerProps}>{children}</InsforgeProviderCore>\n </NavigationProvider>\n </StyleProvider>\n );\n}\n\n/**\n * @deprecated Use `InsforgeBrowserProvider` instead.\n *\n * This alias is kept for backward compatibility and will be removed in a future version.\n *\n * Migration:\n * ```tsx\n * // Before\n * import { ClientInsforgeProvider } from '@insforge/nextjs';\n *\n * // After\n * import { InsforgeBrowserProvider } from '@insforge/nextjs';\n * ```\n */\nexport const ClientInsforgeProvider = InsforgeBrowserProvider;\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\n// Re-export types\nexport type { InitialAuthState };\n"],"mappings":";AA6NQ;AA3NR;AAAA,EACE;AAAA,EAGA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,OAEK;AACP,SAAS,yBAAyB;AAiClC,eAAe,aAAa,OAAe,MAAmC;AAC5E,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,aAAa;AAAA,MACxC,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,eAAe,UAAU,KAAK;AAAA,QAC9B,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,gDAAgD,SAAS;AAAA,IACzE;AAAA,EACF,SAAS,KAAK;AACZ,YAAQ,MAAM,6DAA6D,GAAG;AAAA,EAChF;AACF;AAGA,eAAe,aAAa,OAAe,MAAmC;AAC5E,QAAM,aAAa,OAAO,IAAI;AAChC;AAGA,eAAe,cAAc,OAAe,MAAmC;AAC7E,QAAM,aAAa,OAAO,IAAI;AAChC;AAGA,eAAe,gBAA+B;AAC5C,MAAI;AACF,UAAM,MAAM,aAAa,EAAE,QAAQ,SAAS,CAAC;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAoHO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA,eAAe,EAAE,MAAM,MAAM,QAAQ,KAAK;AAC5C,GAAiC;AAC/B,QAAM,gBAAuC;AAAA,IAC3C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,IACX;AAAA,EACF;AAEA,SACE,oBAAC,iBACC,8BAAC,sBAAmB,SAAS,mBAC3B,8BAAC,wBAAsB,GAAG,eAAgB,UAAS,GACrD,GACF;AAEJ;AAgBO,MAAM,yBAAyB;AAuB/B,MAAM,cAAc;","names":[]}
|
|
@@ -1,12 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
InsforgeBrowserProvider,
|
|
4
|
-
InsforgeBrowserProvider as InsforgeBrowserProvider2,
|
|
5
|
-
ClientInsforgeProvider
|
|
6
|
-
} from "./client/provider";
|
|
7
|
-
export {
|
|
8
|
-
ClientInsforgeProvider,
|
|
9
|
-
InsforgeBrowserProvider,
|
|
10
|
-
InsforgeBrowserProvider2 as InsforgeProvider
|
|
11
|
-
};
|
|
12
2
|
//# sourceMappingURL=components.client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { auth } from "./server/auth";
|
|
2
|
+
import { getAuthFromCookies } from "./server/InsforgeProvider";
|
|
3
|
+
import {
|
|
4
|
+
InsforgeServerProvider
|
|
5
|
+
} from "./server/InsforgeProvider";
|
|
2
6
|
export {
|
|
3
|
-
|
|
7
|
+
InsforgeServerProvider,
|
|
8
|
+
auth,
|
|
9
|
+
getAuthFromCookies
|
|
4
10
|
};
|
|
5
11
|
//# sourceMappingURL=components.server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components.server.ts"],"sourcesContent":["// Server Component exports (
|
|
1
|
+
{"version":3,"sources":["../../src/components.server.ts"],"sourcesContent":["// Server Component exports (react-server environment)\r\n// This file is used when code runs in a Server Component\r\n\r\n// Server-only utilities that use next/headers\r\nexport { auth, type InsforgeAuth } from './server/auth';\r\nexport { getAuthFromCookies } from './server/InsforgeProvider';\r\n\r\n// Server Provider (deprecated but exported for backward compatibility)\r\nexport {\r\n InsforgeServerProvider,\r\n type InsforgeServerProviderProps,\r\n type InsforgeProviderServerProps,\r\n} from './server/InsforgeProvider';\r\n"],"mappings":"AAIA,SAAS,YAA+B;AACxC,SAAS,0BAA0B;AAGnC;AAAA,EACE;AAAA,OAGK;","names":[]}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { InsforgeProvider } from "#components";
|
|
2
1
|
import {
|
|
3
2
|
InsforgeBrowserProvider,
|
|
4
3
|
ClientInsforgeProvider
|
|
5
4
|
} from "./client/provider";
|
|
5
|
+
import {
|
|
6
|
+
auth,
|
|
7
|
+
getAuthFromCookies,
|
|
8
|
+
InsforgeServerProvider
|
|
9
|
+
} from "#components";
|
|
6
10
|
import { useInsforge } from "./client/provider";
|
|
7
11
|
import {
|
|
8
12
|
SignIn,
|
|
@@ -42,8 +46,6 @@ import {
|
|
|
42
46
|
AuthResetPasswordVerificationStep
|
|
43
47
|
} from "./client/components";
|
|
44
48
|
import { useAuth, useUser, usePublicAuthConfig } from "./client/hooks";
|
|
45
|
-
import { getAuthFromCookies } from "./server/InsforgeProvider";
|
|
46
|
-
import { auth } from "./server/auth";
|
|
47
49
|
export {
|
|
48
50
|
AuthBranding,
|
|
49
51
|
AuthContainer,
|
|
@@ -64,7 +66,7 @@ export {
|
|
|
64
66
|
ForgotPassword,
|
|
65
67
|
ForgotPasswordForm,
|
|
66
68
|
InsforgeBrowserProvider,
|
|
67
|
-
|
|
69
|
+
InsforgeServerProvider,
|
|
68
70
|
Protect,
|
|
69
71
|
ResetPassword,
|
|
70
72
|
ResetPasswordForm,
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["//
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// ============================================================================\n// Providers\n// ============================================================================\n\n// Browser Provider - The recommended way to use Insforge in Next.js\n// Use this directly in a client component for proper SDK client sharing\nexport {\n InsforgeBrowserProvider,\n ClientInsforgeProvider, // Deprecated alias\n type InsforgeBrowserProviderProps,\n type InitialAuthState,\n} from './client/provider';\n\n// Server-only exports (uses conditional exports via #components)\n// In Server Components: exports auth, getAuthFromCookies, InsforgeServerProvider\n// In Client Components: not available (will error if imported, which is correct)\nexport {\n auth,\n type InsforgeAuth,\n getAuthFromCookies,\n InsforgeServerProvider,\n type InsforgeServerProviderProps,\n type InsforgeProviderServerProps,\n} 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":"AAMA;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AAKP;AAAA,EACE;AAAA,EAEA;AAAA,EACA;AAAA,OAGK;AAGP,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":[]}
|
package/dist/esm/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"sideEffects": false,
|
|
3
|
-
"imports": {
|
|
4
|
-
"#components": {
|
|
5
|
-
"react-server": "./components.server.js",
|
|
6
|
-
"default": "./components.client.js"
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"sideEffects": false,
|
|
3
|
+
"imports": {
|
|
4
|
+
"#components": {
|
|
5
|
+
"react-server": "./components.server.js",
|
|
6
|
+
"default": "./components.client.js"
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -33,13 +33,20 @@ async function getAuthFromCookies() {
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
async function
|
|
37
|
-
const { children, dynamic = true,
|
|
36
|
+
async function InsforgeServerProvider(props) {
|
|
37
|
+
const { children, dynamic = true, baseUrl, anonKey, ...restProps } = props;
|
|
38
|
+
if (process.env.NODE_ENV === "development") {
|
|
39
|
+
console.warn(
|
|
40
|
+
'[Insforge] \u26A0\uFE0F InsforgeServerProvider is deprecated and will not work correctly.\nSDK client instances cannot be passed from Server to Client Components in Next.js.\n\nPlease migrate to InsforgeBrowserProvider:\n1. Create a client component (e.g., app/providers.tsx) with "use client"\n2. Use InsforgeBrowserProvider with your SDK client in that component\n3. Use getAuthFromCookies() in your layout to pass initialState\n\nSee: https://insforge.com/docs/nextjs/migration'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
38
43
|
const initialAuth = dynamic ? await getAuthFromCookies() : { user: null, userId: null };
|
|
39
|
-
return /* @__PURE__ */ jsx(InsforgeBrowserProvider, {
|
|
44
|
+
return /* @__PURE__ */ jsx(InsforgeBrowserProvider, { initialState: initialAuth, ...restProps, children });
|
|
40
45
|
}
|
|
46
|
+
const InsforgeProvider = InsforgeServerProvider;
|
|
41
47
|
export {
|
|
42
48
|
InsforgeProvider,
|
|
49
|
+
InsforgeServerProvider,
|
|
43
50
|
getAuthFromCookies
|
|
44
51
|
};
|
|
45
52
|
//# sourceMappingURL=InsforgeProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/InsforgeProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { InsforgeBrowserProvider } from '../client/provider';\nimport type { InsforgeProviderProps, InitialAuthState } from '@insforge/react';\nimport { cookies } from 'next/headers';\nimport { COOKIE_NAMES, parseUserCookie } from '../lib/cookies';\
|
|
1
|
+
{"version":3,"sources":["../../../src/server/InsforgeProvider.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { InsforgeBrowserProvider } from '../client/provider';\nimport type { InsforgeProviderProps, InitialAuthState } from '@insforge/react';\nimport { cookies } from 'next/headers';\nimport { COOKIE_NAMES, parseUserCookie } from '../lib/cookies';\n\nexport interface InsforgeServerProviderProps extends Omit<InsforgeProviderProps, 'initialState'> {\n children: ReactNode;\n /**\n * The base URL of your InsForge backend.\n *\n * @deprecated Use `InsforgeBrowserProvider` in a client component instead.\n * This prop is kept for backward compatibility only.\n */\n baseUrl?: string;\n /**\n * The anonymous key for your InsForge backend.\n *\n * @deprecated Use `InsforgeBrowserProvider` in a client component instead.\n * This prop is kept for backward compatibility only.\n */\n anonKey?: string;\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 * @default true\n */\n dynamic?: boolean;\n}\n\n/**\n * @deprecated Use `InsforgeServerProviderProps` instead.\n */\nexport type InsforgeProviderServerProps = InsforgeServerProviderProps;\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 to get the initial auth state and pass it\n * to `InsforgeBrowserProvider` via the `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 { getAuthFromCookies } from '@insforge/nextjs';\n * import { Providers } from './providers';\n *\n * export default async function RootLayout({ children }) {\n * const initialState = await getAuthFromCookies();\n *\n * return (\n * <html>\n * <body>\n * <Providers initialState={initialState}>\n * {children}\n * </Providers>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * @returns Initial auth state with user and userId, or null values 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 token = cookieStore.get(COOKIE_NAMES.SESSION)?.value || null;\n\n if (!token) {\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(COOKIE_NAMES.USER)?.value;\n\n try {\n const user = parseUserCookie(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 userId: user?.id || null,\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 * @deprecated **This component is deprecated.** Use `InsforgeBrowserProvider` instead.\n *\n * This Server Component wrapper doesn't work correctly because SDK client instances\n * (class objects) cannot be serialized and passed from Server to Client Components.\n *\n * ---\n *\n * ## Migration Guide\n *\n * ### Before (deprecated):\n * ```tsx\n * // app/layout.tsx\n * import { InsforgeServerProvider } from '@insforge/nextjs';\n * import { insforge } from '@/lib/insforge';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <InsforgeServerProvider client={insforge}> // ❌ This fails!\n * {children}\n * </InsforgeServerProvider>\n * );\n * }\n * ```\n *\n * ### After (recommended):\n *\n * **Step 1:** Create a client-side Providers component:\n * ```tsx\n * // app/providers.tsx\n * 'use client';\n * import { InsforgeBrowserProvider, type InitialAuthState } from '@insforge/nextjs';\n * import { insforge } from '@/lib/insforge';\n *\n * export function Providers({\n * children,\n * initialState,\n * }: {\n * children: React.ReactNode;\n * initialState?: InitialAuthState;\n * }) {\n * return (\n * <InsforgeBrowserProvider client={insforge} initialState={initialState}>\n * {children}\n * </InsforgeBrowserProvider>\n * );\n * }\n * ```\n *\n * **Step 2:** Use it in your layout:\n * ```tsx\n * // app/layout.tsx\n * import { getAuthFromCookies } from '@insforge/nextjs';\n * import { Providers } from './providers';\n *\n * export default async function RootLayout({ children }) {\n * const initialState = await getAuthFromCookies();\n *\n * return (\n * <html>\n * <body>\n * <Providers initialState={initialState}>\n * {children}\n * </Providers>\n * </body>\n * </html>\n * );\n * }\n * ```\n *\n * ---\n *\n * @see InsforgeBrowserProvider - The recommended client-side provider\n * @see getAuthFromCookies - Helper to get initial auth state for SSR\n */\nexport async function InsforgeServerProvider(\n props: InsforgeServerProviderProps\n): Promise<React.JSX.Element> {\n const { children, dynamic = true, baseUrl, anonKey, ...restProps } = props;\n\n // Show deprecation warning in development\n if (process.env.NODE_ENV === 'development') {\n console.warn(\n '[Insforge] ⚠️ InsforgeServerProvider is deprecated and will not work correctly.\\n' +\n 'SDK client instances cannot be passed from Server to Client Components in Next.js.\\n\\n' +\n 'Please migrate to InsforgeBrowserProvider:\\n' +\n '1. Create a client component (e.g., app/providers.tsx) with \"use client\"\\n' +\n '2. Use InsforgeBrowserProvider with your SDK client in that component\\n' +\n '3. Use getAuthFromCookies() in your layout to pass initialState\\n\\n' +\n 'See: https://insforge.com/docs/nextjs/migration'\n );\n }\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 ? await getAuthFromCookies() : { user: null, userId: null };\n\n // Note: This will fail at runtime because `client` is a class instance\n // We still attempt to render for backward compatibility, but it won't work\n return (\n <InsforgeBrowserProvider initialState={initialAuth} {...restProps}>\n {children}\n </InsforgeBrowserProvider>\n );\n}\n\n/**\n * @deprecated Use `InsforgeServerProvider` instead (which is also deprecated).\n * Migrate to `InsforgeBrowserProvider` for proper Next.js App Router support.\n */\nexport const InsforgeProvider = InsforgeServerProvider;\n"],"mappings":"AAuNI;AAtNJ,SAAS,+BAA+B;AAExC,SAAS,eAAe;AACxB,SAAS,cAAc,uBAAuB;AAkE9C,eAAsB,qBAAgD;AACpE,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAGlC,UAAM,QAAQ,YAAY,IAAI,aAAa,OAAO,GAAG,SAAS;AAE9D,QAAI,CAAC,OAAO;AAEV,aAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MACV;AAAA,IACF;AAGA,UAAM,aAAa,YAAY,IAAI,aAAa,IAAI,GAAG;AAEvD,QAAI;AACF,YAAM,OAAO,gBAAgB,UAAU;AAKvC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ,MAAM,MAAM;AAAA,MACtB;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;AA6EA,eAAsB,uBACpB,OAC4B;AAC5B,QAAM,EAAE,UAAU,UAAU,MAAM,SAAS,SAAS,GAAG,UAAU,IAAI;AAGrE,MAAI,QAAQ,IAAI,aAAa,eAAe;AAC1C,YAAQ;AAAA,MACN;AAAA,IAOF;AAAA,EACF;AAIA,QAAM,cAAc,UAAU,MAAM,mBAAmB,IAAI,EAAE,MAAM,MAAM,QAAQ,KAAK;AAItF,SACE,oBAAC,2BAAwB,cAAc,aAAc,GAAG,WACrD,UACH;AAEJ;AAMO,MAAM,mBAAmB;","names":[]}
|
package/dist/esm/server/index.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { getAuthFromCookies } from "./InsforgeProvider";
|
|
2
2
|
import { auth } from "./auth";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
InsforgeServerProvider,
|
|
5
|
+
InsforgeProvider
|
|
6
|
+
} from "./InsforgeProvider";
|
|
4
7
|
export {
|
|
5
8
|
InsforgeProvider,
|
|
9
|
+
InsforgeServerProvider,
|
|
6
10
|
auth,
|
|
7
11
|
getAuthFromCookies
|
|
8
12
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["// Server-side exports (Server Components, no 'use client')\n\n// Auth helpers\nexport { getAuthFromCookies } from './InsforgeProvider';\nexport { auth } from './auth';\nexport type { InsforgeAuth } from './auth';\n\n// Deprecated: Server Provider (doesn't work due to Next.js serialization constraints)\n// Use InsforgeBrowserProvider directly in a client component instead\nexport {
|
|
1
|
+
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["// Server-side exports (Server Components, no 'use client')\n\n// Auth helpers\nexport { getAuthFromCookies } from './InsforgeProvider';\nexport { auth } from './auth';\nexport type { InsforgeAuth } from './auth';\n\n// Deprecated: Server Provider (doesn't work due to Next.js serialization constraints)\n// Use InsforgeBrowserProvider directly in a client component instead\nexport {\n InsforgeServerProvider,\n InsforgeProvider, // Deprecated alias\n type InsforgeServerProviderProps,\n type InsforgeProviderServerProps, // Deprecated alias\n} from './InsforgeProvider';\n"],"mappings":"AAGA,SAAS,0BAA0B;AACnC,SAAS,YAAY;AAKrB;AAAA,EACE;AAAA,EACA;AAAA,OAGK;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export { InsforgeProvider, getAuthFromCookies } from './server/InsforgeProvider.js';
|
|
2
1
|
export { ClientInsforgeProvider, InsforgeBrowserProvider, InsforgeBrowserProviderProps, useInsforge } from './client/provider.js';
|
|
2
|
+
export { InsforgeAuth, auth } from './server/auth.js';
|
|
3
|
+
export { InsforgeProviderServerProps, InsforgeServerProvider, InsforgeServerProviderProps, getAuthFromCookies } from './server/InsforgeProvider.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
5
|
export { useAuth, usePublicAuthConfig, useUser } from './client/hooks.js';
|
|
5
|
-
export { InsforgeAuth, auth } from './server/auth.js';
|
|
6
6
|
export { InitialAuthState } from '@insforge/react';
|
|
7
7
|
import 'react/jsx-runtime';
|
|
8
|
-
import 'react';
|
|
9
8
|
import '@insforge/sdk';
|
|
10
|
-
import '@insforge/shared-schemas';
|
|
11
9
|
import '@insforge/shared';
|
|
10
|
+
import 'react';
|
|
11
|
+
import '@insforge/shared-schemas';
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import { InsForgeClient } from '@insforge/sdk';
|
|
2
|
+
import { InitialAuthState, InsforgeProviderProps } from '@insforge/react';
|
|
5
3
|
|
|
6
|
-
interface
|
|
4
|
+
interface InsforgeServerProviderProps extends Omit<InsforgeProviderProps, 'initialState'> {
|
|
7
5
|
children: ReactNode;
|
|
8
6
|
/**
|
|
9
|
-
* The
|
|
7
|
+
* The base URL of your InsForge backend.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* `InsforgeBrowserProvider` directly in a client component instead.
|
|
9
|
+
* @deprecated Use `InsforgeBrowserProvider` in a client component instead.
|
|
10
|
+
* This prop is kept for backward compatibility only.
|
|
14
11
|
*/
|
|
15
|
-
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The anonymous key for your InsForge backend.
|
|
15
|
+
*
|
|
16
|
+
* @deprecated Use `InsforgeBrowserProvider` in a client component instead.
|
|
17
|
+
* This prop is kept for backward compatibility only.
|
|
18
|
+
*/
|
|
19
|
+
anonKey?: string;
|
|
16
20
|
/**
|
|
17
21
|
* Opt into dynamic rendering to read auth state from cookies during SSR.
|
|
18
22
|
*
|
|
@@ -23,6 +27,10 @@ interface InsforgeProviderServerProps extends Omit<InsforgeProviderProps, 'initi
|
|
|
23
27
|
*/
|
|
24
28
|
dynamic?: boolean;
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* @deprecated Use `InsforgeServerProviderProps` instead.
|
|
32
|
+
*/
|
|
33
|
+
type InsforgeProviderServerProps = InsforgeServerProviderProps;
|
|
26
34
|
/**
|
|
27
35
|
* Get initial auth state from cookies (server-side)
|
|
28
36
|
*
|
|
@@ -69,14 +77,14 @@ declare function getAuthFromCookies(): Promise<InitialAuthState>;
|
|
|
69
77
|
* ### Before (deprecated):
|
|
70
78
|
* ```tsx
|
|
71
79
|
* // app/layout.tsx
|
|
72
|
-
* import {
|
|
80
|
+
* import { InsforgeServerProvider } from '@insforge/nextjs';
|
|
73
81
|
* import { insforge } from '@/lib/insforge';
|
|
74
82
|
*
|
|
75
83
|
* export default function RootLayout({ children }) {
|
|
76
84
|
* return (
|
|
77
|
-
* <
|
|
85
|
+
* <InsforgeServerProvider client={insforge}> // ❌ This fails!
|
|
78
86
|
* {children}
|
|
79
|
-
* </
|
|
87
|
+
* </InsforgeServerProvider>
|
|
80
88
|
* );
|
|
81
89
|
* }
|
|
82
90
|
* ```
|
|
@@ -131,6 +139,11 @@ declare function getAuthFromCookies(): Promise<InitialAuthState>;
|
|
|
131
139
|
* @see InsforgeBrowserProvider - The recommended client-side provider
|
|
132
140
|
* @see getAuthFromCookies - Helper to get initial auth state for SSR
|
|
133
141
|
*/
|
|
134
|
-
declare function
|
|
142
|
+
declare function InsforgeServerProvider(props: InsforgeServerProviderProps): Promise<React.JSX.Element>;
|
|
143
|
+
/**
|
|
144
|
+
* @deprecated Use `InsforgeServerProvider` instead (which is also deprecated).
|
|
145
|
+
* Migrate to `InsforgeBrowserProvider` for proper Next.js App Router support.
|
|
146
|
+
*/
|
|
147
|
+
declare const InsforgeProvider: typeof InsforgeServerProvider;
|
|
135
148
|
|
|
136
|
-
export { InsforgeProvider, type InsforgeProviderServerProps, getAuthFromCookies };
|
|
149
|
+
export { InsforgeProvider, type InsforgeProviderServerProps, InsforgeServerProvider, type InsforgeServerProviderProps, getAuthFromCookies };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
export { InsforgeProvider, getAuthFromCookies } from './InsforgeProvider.js';
|
|
1
|
+
export { InsforgeProvider, InsforgeProviderServerProps, InsforgeServerProvider, InsforgeServerProviderProps, getAuthFromCookies } from './InsforgeProvider.js';
|
|
2
2
|
export { InsforgeAuth, auth } from './auth.js';
|
|
3
|
-
import 'react/jsx-runtime';
|
|
4
3
|
import 'react';
|
|
5
4
|
import '@insforge/react';
|
|
6
|
-
import '@insforge/sdk';
|
|
7
5
|
import '@insforge/shared';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@insforge/nextjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8-dev.0",
|
|
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",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"author": "Insforge",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@insforge/react": "
|
|
49
|
-
"@insforge/sdk": "
|
|
50
|
-
"@insforge/shared": "
|
|
48
|
+
"@insforge/react": "dev",
|
|
49
|
+
"@insforge/sdk": "dev",
|
|
50
|
+
"@insforge/shared": "dev",
|
|
51
51
|
"@insforge/shared-schemas": "^1.1.35"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|