@insforge/nextjs 0.4.0 → 0.6.5

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.
@@ -20,37 +20,67 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/middleware/index.ts
21
21
  var middleware_exports = {};
22
22
  __export(middleware_exports, {
23
+ InsforgeMiddleware: () => InsforgeMiddleware,
23
24
  getAuthToken: () => getAuthToken,
24
25
  getAuthUser: () => getAuthUser,
25
- withAuth: () => withAuth
26
+ getAuthUserId: () => getAuthUserId,
27
+ withAuth: () => withAuth,
28
+ withInsforgeAuth: () => withInsforgeAuth
26
29
  });
27
30
  module.exports = __toCommonJS(middleware_exports);
28
31
 
29
- // src/middleware/withAuth.ts
32
+ // src/middleware/InsforgeMiddleware.ts
30
33
  var import_server = require("next/server");
31
- function withAuth(config) {
34
+ function InsforgeMiddleware(config) {
32
35
  const {
33
36
  baseUrl,
34
37
  publicRoutes = [],
35
38
  signInUrl = "/sign-in",
36
- cookieName = "insforge_token"
39
+ signUpUrl = "/sign-up",
40
+ cookieName = "insforge_token",
41
+ useBuiltInAuth = true,
42
+ frontendUrl
37
43
  } = config;
38
44
  return async function middleware(request) {
39
45
  const { pathname } = request.nextUrl;
46
+ if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
47
+ const callbackUrl = new URL("/auth/callback", request.url);
48
+ const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);
49
+ ossAuthUrl.searchParams.set("redirect", callbackUrl.toString());
50
+ setTimeout(() => {
51
+ return import_server.NextResponse.redirect(ossAuthUrl.toString());
52
+ }, 100);
53
+ }
40
54
  const isPublicRoute = publicRoutes.some((route) => {
41
55
  if (route.endsWith("*")) {
42
56
  return pathname.startsWith(route.slice(0, -1));
43
57
  }
44
58
  return pathname === route || pathname.startsWith(route + "/");
45
59
  });
60
+ console.log("[Insforge Middleware]", {
61
+ pathname,
62
+ isPublicRoute,
63
+ publicRoutes,
64
+ hasToken: !!request.cookies.get(cookieName)?.value
65
+ });
46
66
  if (isPublicRoute) {
47
67
  return import_server.NextResponse.next();
48
68
  }
49
69
  const token = request.cookies.get(cookieName)?.value;
70
+ console.log("[Insforge Middleware] Token:", token);
50
71
  if (!token) {
51
- const signInUrlObj = new URL(signInUrl, request.url);
52
- signInUrlObj.searchParams.set("redirect", pathname);
53
- return import_server.NextResponse.redirect(signInUrlObj);
72
+ if (useBuiltInAuth) {
73
+ const callbackUrl = new URL("/auth/callback", request.url);
74
+ const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
75
+ backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
76
+ console.log("[Insforge Middleware] Redirecting to built-in auth:", backendSignInUrl.toString());
77
+ return import_server.NextResponse.redirect(backendSignInUrl);
78
+ } else {
79
+ const localSignInUrl = new URL(signInUrl, request.url);
80
+ localSignInUrl.searchParams.set("redirect", pathname);
81
+ console.log("[Insforge Middleware] Redirecting to local auth:", localSignInUrl.toString());
82
+ return import_server.NextResponse.redirect(localSignInUrl);
83
+ }
54
84
  }
55
85
  try {
56
86
  const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {
@@ -76,24 +106,37 @@ function withAuth(config) {
76
106
  return nextResponse;
77
107
  } catch (error) {
78
108
  console.error("[Insforge Middleware] Token validation error:", error);
79
- const signInUrlObj = new URL(signInUrl, request.url);
80
- signInUrlObj.searchParams.set("redirect", pathname);
81
- const response = import_server.NextResponse.redirect(signInUrlObj);
109
+ const response = useBuiltInAuth ? (() => {
110
+ const callbackUrl = new URL("/auth/callback", request.url);
111
+ const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
112
+ backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
113
+ return import_server.NextResponse.redirect(backendSignInUrl);
114
+ })() : (() => {
115
+ const localSignInUrl = new URL(signInUrl, request.url);
116
+ localSignInUrl.searchParams.set("redirect", pathname);
117
+ return import_server.NextResponse.redirect(localSignInUrl);
118
+ })();
82
119
  response.cookies.delete(cookieName);
83
120
  return response;
84
121
  }
85
122
  };
86
123
  }
87
- function getAuthUser(headers) {
124
+ var withAuth = InsforgeMiddleware;
125
+ var withInsforgeAuth = InsforgeMiddleware;
126
+ function getAuthUserId(headers) {
88
127
  return headers.get("x-user-id");
89
128
  }
129
+ var getAuthUser = getAuthUserId;
90
130
  function getAuthToken(headers) {
91
131
  return headers.get("x-user-token");
92
132
  }
93
133
  // Annotate the CommonJS export names for ESM import in node:
94
134
  0 && (module.exports = {
135
+ InsforgeMiddleware,
95
136
  getAuthToken,
96
137
  getAuthUser,
97
- withAuth
138
+ getAuthUserId,
139
+ withAuth,
140
+ withInsforgeAuth
98
141
  });
99
142
  //# sourceMappingURL=middleware.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/middleware/index.ts","../src/middleware/withAuth.ts"],"sourcesContent":["export { withAuth, getAuthUser, getAuthToken } from './withAuth';\r\nexport type { AuthMiddlewareConfig } from './withAuth';\r\n","import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface AuthMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication\r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts\r\n * import { withAuth } from '@insforge/nextjs/middleware';\r\n *\r\n * export default withAuth({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n */\r\nexport function withAuth(config: AuthMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [],\r\n signInUrl = '/sign-in',\r\n cookieName = 'insforge_token',\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n // Redirect to sign in with redirect parameter\r\n const signInUrlObj = new URL(signInUrl, request.url);\r\n signInUrlObj.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(signInUrlObj);\r\n }\r\n\r\n try {\r\n // Verify token with Insforge backend\r\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error('[Insforge Middleware] Backend validation failed:', {\r\n status: response.status,\r\n statusText: response.statusText,\r\n error: errorText,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = await response.json();\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Invalid token, redirect to sign in\r\n const signInUrlObj = new URL(signInUrl, request.url);\r\n signInUrlObj.searchParams.set('redirect', pathname);\r\n\r\n const response = NextResponse.redirect(signInUrlObj);\r\n // Clear invalid token\r\n response.cookies.delete(cookieName);\r\n\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Utility to get authenticated user from request headers in server components\r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUser } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function Page() {\r\n * const userId = getAuthUser(headers());\r\n * // ...\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUser(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components\r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAA0C;AAqDnC,SAAS,SAAS,QAA8B;AACrD,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC;AAAA,IAChB,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAG7B,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AACA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,2BAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,QAAI,CAAC,OAAO;AAEV,YAAM,eAAe,IAAI,IAAI,WAAW,QAAQ,GAAG;AACnD,mBAAa,aAAa,IAAI,YAAY,QAAQ;AAClD,aAAO,2BAAa,SAAS,YAAY;AAAA,IAC3C;AAEA,QAAI;AAEF,YAAM,WAAW,MAAM,MAAM,GAAG,OAAO,8BAA8B;AAAA,QACnE,SAAS;AAAA,UACP,eAAe,UAAU,KAAK;AAAA,UAC9B,gBAAgB;AAAA,QAClB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,gBAAQ,MAAM,oDAAoD;AAAA,UAChE,QAAQ,SAAS;AAAA,UACjB,YAAY,SAAS;AAAA,UACrB,OAAO;AAAA,QACT,CAAC;AACD,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACnC;AAEA,YAAM,UAAU,MAAM,SAAS,KAAK;AAGpC,YAAM,eAAe,2BAAa,KAAK;AACvC,mBAAa,QAAQ,IAAI,aAAa,QAAQ,KAAK,EAAE;AACrD,mBAAa,QAAQ,IAAI,gBAAgB,QAAQ,KAAK,KAAK;AAC3D,mBAAa,QAAQ,IAAI,gBAAgB,KAAK;AAE9C,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,iDAAiD,KAAK;AAGpE,YAAM,eAAe,IAAI,IAAI,WAAW,QAAQ,GAAG;AACnD,mBAAa,aAAa,IAAI,YAAY,QAAQ;AAElD,YAAM,WAAW,2BAAa,SAAS,YAAY;AAEnD,eAAS,QAAQ,OAAO,UAAU;AAElC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAkBO,SAAS,YAAY,SAAiC;AAC3D,SAAO,QAAQ,IAAI,WAAW;AAChC;AAOO,SAAS,aAAa,SAAiC;AAC5D,SAAO,QAAQ,IAAI,cAAc;AACnC;","names":[]}
1
+ {"version":3,"sources":["../src/middleware/index.ts","../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["// Middleware exports - NO 'use client' directive here!\r\n// Middleware runs in Edge Runtime, not in client browser\r\n\r\nexport { \r\n InsforgeMiddleware, \r\n withAuth,\r\n withInsforgeAuth,\r\n getAuthUserId, \r\n getAuthUser,\r\n getAuthToken \r\n} from './InsforgeMiddleware';\r\n\r\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\r\n\r\n","import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend (for API calls)\r\n * @example 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Base URL of your frontend application (for redirects)\r\n * If not provided, will use baseUrl for redirects\r\n * @example 'http://localhost:3000'\r\n */\r\n frontendUrl?: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is signing up\r\n * @default '/sign-up'\r\n */\r\n signUpUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n\r\n /**\r\n * Whether to use built-in authentication pages hosted on the backend\r\n * When true, middleware won't redirect to local sign-in pages\r\n * @default true\r\n */\r\n useBuiltInAuth?: boolean;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * This function generates a Next.js middleware that:\r\n * - Validates user authentication on each request\r\n * - Redirects unauthenticated users to sign-in page\r\n * - Allows public routes to be accessed without authentication\r\n * - Injects user information into request headers for server components\r\n * \r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts - Local development with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend API (e.g., http://localhost:3001)\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend app (e.g., http://localhost:3000)\r\n * publicRoutes: ['/auth/callback', '/'],\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Using custom SignIn/SignUp components\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL, // Optional: for redirects\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * signInUrl: '/sign-in',\r\n * useBuiltInAuth: false,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n */\r\nexport function InsforgeMiddleware(config: InsforgeMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [],\r\n signInUrl = '/sign-in',\r\n signUpUrl = '/sign-up',\r\n cookieName = 'insforge_token',\r\n useBuiltInAuth = true,\r\n frontendUrl,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Special handling for built-in auth: redirect /sign-in, /sign-up to OSS frontend\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n setTimeout(() => {\r\n return NextResponse.redirect(ossAuthUrl.toString());\r\n }, 100);\r\n }\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n console.log('[Insforge Middleware]', {\r\n pathname,\r\n isPublicRoute,\r\n publicRoutes,\r\n hasToken: !!request.cookies.get(cookieName)?.value,\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n console.log('[Insforge Middleware] Token:', token);\r\n\r\n if (!token) {\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n console.log('[Insforge Middleware] Redirecting to built-in auth:', backendSignInUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n } else {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n console.log('[Insforge Middleware] Redirecting to local auth:', localSignInUrl.toString());\r\n return NextResponse.redirect(localSignInUrl);\r\n }\r\n }\r\n\r\n try {\r\n // Verify token with Insforge backend\r\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error('[Insforge Middleware] Backend validation failed:', {\r\n status: response.status,\r\n statusText: response.statusText,\r\n error: errorText,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = await response.json();\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Clear invalid token first\r\n const response = useBuiltInAuth\r\n ? (() => {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n })()\r\n : (() => {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(localSignInUrl);\r\n })();\r\n\r\n response.cookies.delete(cookieName);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * @deprecated Use `InsforgeMiddleware` instead. This alias is kept for backward compatibility.\r\n * \r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Alternative name for `InsforgeMiddleware` with Insforge branding.\r\n * Useful when you want to be explicit about using Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withInsforgeAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Utility to get authenticated user ID from request headers in server components.\r\n * \r\n * The middleware automatically injects user information into request headers,\r\n * which can be accessed in server components using Next.js `headers()`.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUserId } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function DashboardPage() {\r\n * const userId = getAuthUserId(headers());\r\n * \r\n * if (!userId) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * return <div>User ID: {userId}</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUserId(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * @deprecated Use `getAuthUserId` instead. This alias is kept for backward compatibility.\r\n * @see getAuthUserId\r\n */\r\nexport const getAuthUser = getAuthUserId;\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components.\r\n * \r\n * The middleware automatically injects the authentication token into request headers,\r\n * which can be used to make authenticated API calls from server components.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthToken } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function ProfilePage() {\r\n * const token = getAuthToken(headers());\r\n * \r\n * if (!token) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * // Use token for API calls\r\n * const response = await fetch('https://api.example.com/profile', {\r\n * headers: { Authorization: `Bearer ${token}` }\r\n * });\r\n * \r\n * return <div>Profile data</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,28 +1,55 @@
1
- // src/middleware/withAuth.ts
1
+ // src/middleware/InsforgeMiddleware.ts
2
2
  import { NextResponse } from "next/server";
3
- function withAuth(config) {
3
+ function InsforgeMiddleware(config) {
4
4
  const {
5
5
  baseUrl,
6
6
  publicRoutes = [],
7
7
  signInUrl = "/sign-in",
8
- cookieName = "insforge_token"
8
+ signUpUrl = "/sign-up",
9
+ cookieName = "insforge_token",
10
+ useBuiltInAuth = true,
11
+ frontendUrl
9
12
  } = config;
10
13
  return async function middleware(request) {
11
14
  const { pathname } = request.nextUrl;
15
+ if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {
16
+ const callbackUrl = new URL("/auth/callback", request.url);
17
+ const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);
18
+ ossAuthUrl.searchParams.set("redirect", callbackUrl.toString());
19
+ setTimeout(() => {
20
+ return NextResponse.redirect(ossAuthUrl.toString());
21
+ }, 100);
22
+ }
12
23
  const isPublicRoute = publicRoutes.some((route) => {
13
24
  if (route.endsWith("*")) {
14
25
  return pathname.startsWith(route.slice(0, -1));
15
26
  }
16
27
  return pathname === route || pathname.startsWith(route + "/");
17
28
  });
29
+ console.log("[Insforge Middleware]", {
30
+ pathname,
31
+ isPublicRoute,
32
+ publicRoutes,
33
+ hasToken: !!request.cookies.get(cookieName)?.value
34
+ });
18
35
  if (isPublicRoute) {
19
36
  return NextResponse.next();
20
37
  }
21
38
  const token = request.cookies.get(cookieName)?.value;
39
+ console.log("[Insforge Middleware] Token:", token);
22
40
  if (!token) {
23
- const signInUrlObj = new URL(signInUrl, request.url);
24
- signInUrlObj.searchParams.set("redirect", pathname);
25
- return NextResponse.redirect(signInUrlObj);
41
+ if (useBuiltInAuth) {
42
+ const callbackUrl = new URL("/auth/callback", request.url);
43
+ const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
44
+ backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
45
+ console.log("[Insforge Middleware] Redirecting to built-in auth:", backendSignInUrl.toString());
46
+ return NextResponse.redirect(backendSignInUrl);
47
+ } else {
48
+ const localSignInUrl = new URL(signInUrl, request.url);
49
+ localSignInUrl.searchParams.set("redirect", pathname);
50
+ console.log("[Insforge Middleware] Redirecting to local auth:", localSignInUrl.toString());
51
+ return NextResponse.redirect(localSignInUrl);
52
+ }
26
53
  }
27
54
  try {
28
55
  const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {
@@ -48,23 +75,36 @@ function withAuth(config) {
48
75
  return nextResponse;
49
76
  } catch (error) {
50
77
  console.error("[Insforge Middleware] Token validation error:", error);
51
- const signInUrlObj = new URL(signInUrl, request.url);
52
- signInUrlObj.searchParams.set("redirect", pathname);
53
- const response = NextResponse.redirect(signInUrlObj);
78
+ const response = useBuiltInAuth ? (() => {
79
+ const callbackUrl = new URL("/auth/callback", request.url);
80
+ const backendSignInUrl = new URL("/auth/signin", frontendUrl || baseUrl);
81
+ backendSignInUrl.searchParams.set("redirect", callbackUrl.toString());
82
+ return NextResponse.redirect(backendSignInUrl);
83
+ })() : (() => {
84
+ const localSignInUrl = new URL(signInUrl, request.url);
85
+ localSignInUrl.searchParams.set("redirect", pathname);
86
+ return NextResponse.redirect(localSignInUrl);
87
+ })();
54
88
  response.cookies.delete(cookieName);
55
89
  return response;
56
90
  }
57
91
  };
58
92
  }
59
- function getAuthUser(headers) {
93
+ var withAuth = InsforgeMiddleware;
94
+ var withInsforgeAuth = InsforgeMiddleware;
95
+ function getAuthUserId(headers) {
60
96
  return headers.get("x-user-id");
61
97
  }
98
+ var getAuthUser = getAuthUserId;
62
99
  function getAuthToken(headers) {
63
100
  return headers.get("x-user-token");
64
101
  }
65
102
  export {
103
+ InsforgeMiddleware,
66
104
  getAuthToken,
67
105
  getAuthUser,
68
- withAuth
106
+ getAuthUserId,
107
+ withAuth,
108
+ withInsforgeAuth
69
109
  };
70
110
  //# sourceMappingURL=middleware.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/middleware/withAuth.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface AuthMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication\r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts\r\n * import { withAuth } from '@insforge/nextjs/middleware';\r\n *\r\n * export default withAuth({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n */\r\nexport function withAuth(config: AuthMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [],\r\n signInUrl = '/sign-in',\r\n cookieName = 'insforge_token',\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n if (!token) {\r\n // Redirect to sign in with redirect parameter\r\n const signInUrlObj = new URL(signInUrl, request.url);\r\n signInUrlObj.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(signInUrlObj);\r\n }\r\n\r\n try {\r\n // Verify token with Insforge backend\r\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error('[Insforge Middleware] Backend validation failed:', {\r\n status: response.status,\r\n statusText: response.statusText,\r\n error: errorText,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = await response.json();\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Invalid token, redirect to sign in\r\n const signInUrlObj = new URL(signInUrl, request.url);\r\n signInUrlObj.searchParams.set('redirect', pathname);\r\n\r\n const response = NextResponse.redirect(signInUrlObj);\r\n // Clear invalid token\r\n response.cookies.delete(cookieName);\r\n\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Utility to get authenticated user from request headers in server components\r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUser } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function Page() {\r\n * const userId = getAuthUser(headers());\r\n * // ...\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUser(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components\r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":";AAAA,SAAsB,oBAAoB;AAqDnC,SAAS,SAAS,QAA8B;AACrD,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC;AAAA,IAChB,YAAY;AAAA,IACZ,aAAa;AAAA,EACf,IAAI;AAEJ,SAAO,eAAe,WAAW,SAAsB;AACrD,UAAM,EAAE,SAAS,IAAI,QAAQ;AAG7B,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AACvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AACA,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,YAAM,eAAe,IAAI,IAAI,WAAW,QAAQ,GAAG;AACnD,mBAAa,aAAa,IAAI,YAAY,QAAQ;AAClD,aAAO,aAAa,SAAS,YAAY;AAAA,IAC3C;AAEA,QAAI;AAEF,YAAM,WAAW,MAAM,MAAM,GAAG,OAAO,8BAA8B;AAAA,QACnE,SAAS;AAAA,UACP,eAAe,UAAU,KAAK;AAAA,UAC9B,gBAAgB;AAAA,QAClB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,YAAY,MAAM,SAAS,KAAK;AACtC,gBAAQ,MAAM,oDAAoD;AAAA,UAChE,QAAQ,SAAS;AAAA,UACjB,YAAY,SAAS;AAAA,UACrB,OAAO;AAAA,QACT,CAAC;AACD,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACnC;AAEA,YAAM,UAAU,MAAM,SAAS,KAAK;AAGpC,YAAM,eAAe,aAAa,KAAK;AACvC,mBAAa,QAAQ,IAAI,aAAa,QAAQ,KAAK,EAAE;AACrD,mBAAa,QAAQ,IAAI,gBAAgB,QAAQ,KAAK,KAAK;AAC3D,mBAAa,QAAQ,IAAI,gBAAgB,KAAK;AAE9C,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,iDAAiD,KAAK;AAGpE,YAAM,eAAe,IAAI,IAAI,WAAW,QAAQ,GAAG;AACnD,mBAAa,aAAa,IAAI,YAAY,QAAQ;AAElD,YAAM,WAAW,aAAa,SAAS,YAAY;AAEnD,eAAS,QAAQ,OAAO,UAAU;AAElC,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAkBO,SAAS,YAAY,SAAiC;AAC3D,SAAO,QAAQ,IAAI,WAAW;AAChC;AAOO,SAAS,aAAa,SAAiC;AAC5D,SAAO,QAAQ,IAAI,cAAc;AACnC;","names":[]}
1
+ {"version":3,"sources":["../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend (for API calls)\r\n * @example 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Base URL of your frontend application (for redirects)\r\n * If not provided, will use baseUrl for redirects\r\n * @example 'http://localhost:3000'\r\n */\r\n frontendUrl?: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @example ['/sign-in', '/sign-up', '/']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * URL to redirect to after sign in\r\n * @default '/dashboard'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is not authenticated\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * URL to redirect to when user is signing up\r\n * @default '/sign-up'\r\n */\r\n signUpUrl?: string;\r\n\r\n /**\r\n * Cookie name for the auth token\r\n * @default 'insforge_token'\r\n */\r\n cookieName?: string;\r\n\r\n /**\r\n * Whether to use built-in authentication pages hosted on the backend\r\n * When true, middleware won't redirect to local sign-in pages\r\n * @default true\r\n */\r\n useBuiltInAuth?: boolean;\r\n}\r\n\r\n/**\r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * This function generates a Next.js middleware that:\r\n * - Validates user authentication on each request\r\n * - Redirects unauthenticated users to sign-in page\r\n * - Allows public routes to be accessed without authentication\r\n * - Injects user information into request headers for server components\r\n * \r\n * @param config - Middleware configuration\r\n * @returns Next.js middleware function\r\n *\r\n * @example\r\n * ```ts\r\n * // middleware.ts - Local development with separate frontend/backend URLs\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!, // Backend API (e.g., http://localhost:3001)\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL!, // Frontend app (e.g., http://localhost:3000)\r\n * publicRoutes: ['/auth/callback', '/'],\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n * \r\n * @example\r\n * ```ts\r\n * // middleware.ts - Using custom SignIn/SignUp components\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * frontendUrl: process.env.INSFORGE_FRONTEND_URL, // Optional: for redirects\r\n * publicRoutes: ['/sign-in', '/sign-up', '/'],\r\n * signInUrl: '/sign-in',\r\n * useBuiltInAuth: false,\r\n * });\r\n *\r\n * export const config = {\r\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\r\n * };\r\n * ```\r\n */\r\nexport function InsforgeMiddleware(config: InsforgeMiddlewareConfig) {\r\n const {\r\n baseUrl,\r\n publicRoutes = [],\r\n signInUrl = '/sign-in',\r\n signUpUrl = '/sign-up',\r\n cookieName = 'insforge_token',\r\n useBuiltInAuth = true,\r\n frontendUrl,\r\n } = config;\r\n\r\n return async function middleware(request: NextRequest) {\r\n const { pathname } = request.nextUrl;\r\n\r\n // Special handling for built-in auth: redirect /sign-in, /sign-up to OSS frontend\r\n if (useBuiltInAuth && (pathname === signInUrl || pathname === signUpUrl)) {\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const ossAuthUrl = new URL(`/auth${pathname}`, frontendUrl || baseUrl);\r\n ossAuthUrl.searchParams.set('redirect', callbackUrl.toString());\r\n setTimeout(() => {\r\n return NextResponse.redirect(ossAuthUrl.toString());\r\n }, 100);\r\n }\r\n\r\n // Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n return pathname === route || pathname.startsWith(route + '/');\r\n });\r\n\r\n console.log('[Insforge Middleware]', {\r\n pathname,\r\n isPublicRoute,\r\n publicRoutes,\r\n hasToken: !!request.cookies.get(cookieName)?.value,\r\n });\r\n\r\n if (isPublicRoute) {\r\n return NextResponse.next();\r\n }\r\n\r\n // Get token from cookie\r\n const token = request.cookies.get(cookieName)?.value;\r\n\r\n console.log('[Insforge Middleware] Token:', token);\r\n\r\n if (!token) {\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n console.log('[Insforge Middleware] Redirecting to built-in auth:', backendSignInUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n } else {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n console.log('[Insforge Middleware] Redirecting to local auth:', localSignInUrl.toString());\r\n return NextResponse.redirect(localSignInUrl);\r\n }\r\n }\r\n\r\n try {\r\n // Verify token with Insforge backend\r\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n console.error('[Insforge Middleware] Backend validation failed:', {\r\n status: response.status,\r\n statusText: response.statusText,\r\n error: errorText,\r\n });\r\n throw new Error('Invalid session');\r\n }\r\n\r\n const session = await response.json();\r\n\r\n // Add user info to headers for server components\r\n const nextResponse = NextResponse.next();\r\n nextResponse.headers.set('x-user-id', session.user.id);\r\n nextResponse.headers.set('x-user-email', session.user.email);\r\n nextResponse.headers.set('x-user-token', token);\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Insforge Middleware] Token validation error:', error);\r\n\r\n // Clear invalid token first\r\n const response = useBuiltInAuth\r\n ? (() => {\r\n // Built-in auth: redirect to backend's auth page\r\n const callbackUrl = new URL('/auth/callback', request.url);\r\n const backendSignInUrl = new URL('/auth/signin', frontendUrl || baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', callbackUrl.toString());\r\n return NextResponse.redirect(backendSignInUrl);\r\n })()\r\n : (() => {\r\n // Custom auth: redirect to local sign-in page\r\n const localSignInUrl = new URL(signInUrl, request.url);\r\n localSignInUrl.searchParams.set('redirect', pathname);\r\n return NextResponse.redirect(localSignInUrl);\r\n })();\r\n\r\n response.cookies.delete(cookieName);\r\n return response;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * @deprecated Use `InsforgeMiddleware` instead. This alias is kept for backward compatibility.\r\n * \r\n * Creates Next.js middleware for protecting routes with Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Alternative name for `InsforgeMiddleware` with Insforge branding.\r\n * Useful when you want to be explicit about using Insforge authentication.\r\n * \r\n * @see InsforgeMiddleware\r\n */\r\nexport const withInsforgeAuth = InsforgeMiddleware;\r\n\r\n/**\r\n * Utility to get authenticated user ID from request headers in server components.\r\n * \r\n * The middleware automatically injects user information into request headers,\r\n * which can be accessed in server components using Next.js `headers()`.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns User ID if authenticated, null otherwise\r\n *\r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthUserId } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function DashboardPage() {\r\n * const userId = getAuthUserId(headers());\r\n * \r\n * if (!userId) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * return <div>User ID: {userId}</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthUserId(headers: Headers): string | null {\r\n return headers.get('x-user-id');\r\n}\r\n\r\n/**\r\n * @deprecated Use `getAuthUserId` instead. This alias is kept for backward compatibility.\r\n * @see getAuthUserId\r\n */\r\nexport const getAuthUser = getAuthUserId;\r\n\r\n/**\r\n * Utility to get auth token from request headers in server components.\r\n * \r\n * The middleware automatically injects the authentication token into request headers,\r\n * which can be used to make authenticated API calls from server components.\r\n * \r\n * @param headers - Request headers from Next.js\r\n * @returns Auth token if authenticated, null otherwise\r\n * \r\n * @example\r\n * ```ts\r\n * import { headers } from 'next/headers';\r\n * import { getAuthToken } from '@insforge/nextjs/middleware';\r\n *\r\n * export default async function ProfilePage() {\r\n * const token = getAuthToken(headers());\r\n * \r\n * if (!token) {\r\n * return <div>Not authenticated</div>;\r\n * }\r\n * \r\n * // Use token for API calls\r\n * const response = await fetch('https://api.example.com/profile', {\r\n * headers: { Authorization: `Bearer ${token}` }\r\n * });\r\n * \r\n * return <div>Profile data</div>;\r\n * }\r\n * ```\r\n */\r\nexport function getAuthToken(headers: Headers): string | null {\r\n return headers.get('x-user-token');\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@insforge/nextjs",
3
- "version": "0.4.0",
3
+ "version": "0.6.5",
4
4
  "description": "Pre-built authentication UI components for Next.js with Insforge backend - zero configuration required",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -46,10 +46,9 @@
46
46
  "author": "Insforge",
47
47
  "license": "MIT",
48
48
  "peerDependencies": {
49
- "lucide-react": "^0.462.0",
50
- "next": "^14.0.0 || ^15.0.0",
51
- "react": "^18.0.0 || ^19.0.0",
52
- "react-dom": "^18.0.0 || ^19.0.0"
49
+ "next": "^15.0.0",
50
+ "react": "^19.0.0",
51
+ "react-dom": "^19.0.0"
53
52
  },
54
53
  "dependencies": {
55
54
  "@insforge/sdk": "^0.0.56",