@insforge/nextjs 1.1.6-dev.1 → 1.1.7

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/README.md CHANGED
@@ -1,380 +1,380 @@
1
- # @insforge/nextjs
2
-
3
- **Zero-configuration authentication for Next.js** using Insforge backend. Get production-ready auth in 5 minutes.
4
-
5
- ## Why @insforge/nextjs?
6
-
7
- ✅ **Built-in Auth Pages** - Backend-hosted UI, no React code needed
8
- ✅ **5-Minute Setup** - Provider + API route + callback + middleware = done
9
- ✅ **Full SSR Support** - Works with Next.js App Router and Server Components
10
- ✅ **Auto OAuth** - 11 providers configured from backend automatically
11
- ✅ **TypeScript First** - Complete type safety out of the box
12
-
13
- **Need custom UI?** Scroll to [Customization](#customization) for custom components and styling.
14
-
15
- ## Installation
16
-
17
- ```bash
18
- npm install @insforge/nextjs
19
- ```
20
-
21
- ---
22
-
23
- ## Quick Start
24
-
25
- ### 1. Setup Provider
26
-
27
- Wrap your app with `InsforgeProvider` in the root layout:
28
-
29
- ```tsx
30
- // app/layout.tsx
31
- import { InsforgeProvider } from '@insforge/nextjs';
32
-
33
- export default function RootLayout({ children }: { children: React.ReactNode }) {
34
- return (
35
- <html lang="en">
36
- <body>
37
- <InsforgeProvider
38
- baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}
39
- afterSignInUrl="/dashboard"
40
- >
41
- {children}
42
- </InsforgeProvider>
43
- </body>
44
- </html>
45
- );
46
- }
47
- ```
48
-
49
- > **Zero Configuration**: Styles are automatically injected via Emotion CSS-in-JS. No CSS imports needed!
50
-
51
- ### 2. Create API Route
52
-
53
- Create an API route to sync tokens to HTTP-only cookies (enables SSR):
54
-
55
- ```tsx
56
- // app/api/auth/route.ts
57
- import { createAuthRouteHandlers } from '@insforge/nextjs/api';
58
-
59
- const handlers = createAuthRouteHandlers({
60
- baseUrl: process.env.INSFORGE_BASE_URL || process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,
61
- cookieName: 'insforge_token',
62
- });
63
-
64
- export const POST = handlers.POST;
65
- export const GET = handlers.GET;
66
- export const DELETE = handlers.DELETE;
67
- ```
68
-
69
- **What it does:**
70
-
71
- - `POST /api/auth` - Syncs localStorage token to HTTP-only cookie
72
- - `GET /api/auth` - Retrieves user data server-side
73
- - `DELETE /api/auth` - Clears auth cookie on sign out
74
-
75
- ### 3. Setup Middleware
76
-
77
- Protect routes with middleware:
78
-
79
- ```ts
80
- // middleware.ts
81
- import { InsforgeMiddleware } from '@insforge/nextjs/middleware';
82
-
83
- export default InsforgeMiddleware({
84
- baseUrl: process.env.INSFORGE_BASE_URL!,
85
- publicRoutes: ['/auth/callback', '/'],
86
- cookieName: 'insforge_token',
87
- });
88
-
89
- export const config = {
90
- matcher: [
91
- '/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
92
- ],
93
- };
94
- ```
95
-
96
- **What it does:**
97
-
98
- - Redirects unauthenticated users to backend auth pages
99
- - Verifies tokens server-side
100
- - Allows public routes without auth
101
-
102
- ### 4. Use Hooks & Components
103
-
104
- ```tsx
105
- // app/page.tsx
106
- import { SignedIn, SignedOut, UserButton } from '@insforge/nextjs';
107
-
108
- export default function Home() {
109
- return (
110
- <div>
111
- <SignedOut>
112
- <a href="/sign-in">Sign In</a>
113
- </SignedOut>
114
-
115
- <SignedIn>
116
- <UserButton afterSignOutUrl="/" />
117
- <h1>Welcome back!</h1>
118
- </SignedIn>
119
- </div>
120
- );
121
- }
122
- ```
123
-
124
- **Available Hooks:**
125
-
126
- ```tsx
127
- import { useAuth, useUser } from '@insforge/nextjs';
128
-
129
- function Component() {
130
- const { signIn, signUp, signOut, isSignedIn, isLoaded } = useAuth();
131
- const { user, updateUser } = useUser();
132
-
133
- return <div>Email: {user?.email}</div>;
134
- }
135
- ```
136
-
137
- **That's it!** 🎉 Your app now has production-ready authentication.
138
-
139
- ---
140
-
141
- ## How It Works
142
-
143
- ```
144
- 1. User clicks "Sign In" → Middleware redirects to backend auth page
145
-
146
- 2. User signs in on backend (https://your-project.insforge.app/auth/sign-in)
147
-
148
- 3. Backend redirects: yourapp.com?access_token=xxx&user_id=xxx...
149
-
150
- 4. SDK auto-detects URL parameters:
151
- - Stores token in localStorage
152
- - Provider automatically reloads auth state
153
- - Token syncs to HTTP-only cookie (via API route)
154
-
155
- 5. User sees dashboard with authenticated state
156
- ```
157
-
158
- **Two-Storage Architecture:**
159
-
160
- - **localStorage**: Client-side token access (hooks, components, SDK)
161
- - **HTTP-only cookie**: Server-side token access (middleware, SSR)
162
-
163
- ---
164
-
165
- ## Customization
166
-
167
- ### Custom Auth Pages
168
-
169
- Want custom branding? Create custom auth pages instead of using built-in pages:
170
-
171
- ```tsx
172
- // app/sign-in/page.tsx
173
- 'use client';
174
-
175
- import { SignIn } from '@insforge/nextjs';
176
- import { useRouter } from 'next/navigation';
177
-
178
- export default function SignInPage() {
179
- const router = useRouter();
180
-
181
- return (
182
- <div className="min-h-screen flex items-center justify-center bg-gray-50">
183
- <SignIn
184
- afterSignInUrl="/dashboard"
185
- onSuccess={(user) => {
186
- console.log('Signed in:', user);
187
- router.push('/dashboard');
188
- }}
189
- />
190
- </div>
191
- );
192
- }
193
- ```
194
-
195
- **Additional Auth Components:**
196
-
197
- ```tsx
198
- // Password reset flow
199
- import { ForgotPassword, ResetPassword, VerifyEmail } from '@insforge/nextjs';
200
-
201
- // app/forgot-password/page.tsx
202
- <ForgotPassword backToSignInUrl="/sign-in" />
203
-
204
- // app/reset-password/page.tsx (with token from URL)
205
- <ResetPassword token={token} backToSignInUrl="/sign-in" />
206
-
207
- // app/verify-email/page.tsx (with token from URL)
208
- <VerifyEmail token={token} />
209
- ```
210
-
211
- **Available Atomic Components:**
212
-
213
- - `AuthContainer` - Main form container
214
- - `AuthHeader` - Title and subtitle
215
- - `AuthFormField` - Standard input field
216
- - `AuthPasswordField` - Password field with visibility toggle
217
- - `AuthPasswordStrengthIndicator` - Password requirement checklist
218
- - `AuthSubmitButton` - Submit button with loading states
219
- - `AuthErrorBanner` - Error message display
220
- - `AuthDivider` - Visual separator
221
- - `AuthOAuthProviders` - OAuth provider buttons grid
222
- - `AuthOAuthButton` - Individual OAuth button
223
- - `AuthVerificationCodeInput` - OTP/2FA code input
224
- - `AuthLink` - Navigation link
225
- - `AuthBranding` - Insforge branding footer
226
-
227
- ### Server-Side Usage
228
-
229
- Access auth data in Server Components, API Routes, and Server Actions using the `auth()` helper:
230
-
231
- #### Using in Server Components
232
-
233
- ```tsx
234
- // app/dashboard/page.tsx (Server Component)
235
- import { auth } from '@insforge/nextjs/server';
236
-
237
- export default async function Dashboard() {
238
- const { userId, user } = await auth();
239
-
240
- if (!userId) {
241
- return <div>Not authenticated</div>;
242
- }
243
-
244
- return <div>Welcome, {user?.email}!</div>;
245
- }
246
- ```
247
-
248
- #### Using in API Routes
249
-
250
- ```tsx
251
- // app/api/posts/route.ts
252
- import { auth, createServerClient } from '@insforge/nextjs/server';
253
- import { NextResponse } from 'next/server';
254
-
255
- export async function GET() {
256
- const { userId, token } = await auth();
257
-
258
- if (!userId || !token) {
259
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
260
- }
261
-
262
- // Option 1: Use auth info directly
263
- return NextResponse.json({ userId, message: 'Authenticated!' });
264
-
265
- // Option 2: Use createServerClient for database operations
266
- const insforge = await createServerClient({
267
- baseUrl: process.env.INSFORGE_BASE_URL!,
268
- });
269
-
270
- if (!insforge) {
271
- return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
272
- }
273
-
274
- const result = await insforge.database.from('posts').select();
275
- return NextResponse.json(result.data);
276
- }
277
- ```
278
-
279
- #### Using in Server Actions
280
-
281
- ```tsx
282
- 'use server';
283
-
284
- import { auth } from '@insforge/nextjs/server';
285
- import { revalidatePath } from 'next/cache';
286
-
287
- export async function createPost(formData: FormData) {
288
- const { userId } = await auth();
289
-
290
- if (!userId) {
291
- throw new Error('Not authenticated');
292
- }
293
-
294
- // Create post with userId
295
- const title = formData.get('title');
296
- // ... insert into database
297
-
298
- revalidatePath('/posts');
299
- }
300
- ```
301
-
302
- ### Conditional Rendering
303
-
304
- ```tsx
305
- import { Protect } from '@insforge/nextjs';
306
-
307
- // Role-based access
308
- <Protect condition={(user) => user.role === 'admin'}>
309
- <AdminPanel />
310
- </Protect>
311
-
312
- // Custom logic
313
- <Protect condition={(user) => user.emailVerified}>
314
- <VerifiedUserFeature />
315
- </Protect>
316
- ```
317
-
318
- ### Auth Change Callback
319
-
320
- Track authentication events:
321
-
322
- ```tsx
323
- <InsforgeProvider
324
- baseUrl={baseUrl}
325
- onAuthChange={(user) => {
326
- if (user) {
327
- analytics.identify(user.id);
328
- } else {
329
- analytics.reset();
330
- }
331
- }}
332
- />
333
- ```
334
-
335
- ---
336
-
337
- ## Local Development
338
-
339
- During local development, backend typically runs on a different port:
340
-
341
- ```bash
342
- # .env.local
343
- NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130
344
- INSFORGE_BASE_URL=http://localhost:7130
345
- ```
346
-
347
- ---
348
-
349
- ## TypeScript
350
-
351
- Full TypeScript support with exported types:
352
-
353
- ```tsx
354
- import type {
355
- InsforgeUser,
356
- InsforgeCallbackProps,
357
- SignInProps,
358
- SignUpProps,
359
- ForgotPasswordProps,
360
- ResetPasswordProps,
361
- VerifyEmailProps,
362
- SignInAppearance,
363
- SignUpAppearance,
364
- UserButtonProps,
365
- ProtectProps,
366
- OAuthProvider,
367
- } from '@insforge/nextjs';
368
- ```
369
-
370
- ---
371
-
372
- ## Support
373
-
374
- - **Documentation**: https://docs.insforge.dev
375
- - **GitHub Issues**: https://github.com/InsForge/InsForge/issues
376
- - **Discord Community**: https://discord.com/invite/DvBtaEc9Jz
377
-
378
- ## License
379
-
380
- MIT
1
+ # @insforge/nextjs
2
+
3
+ **Zero-configuration authentication for Next.js** using Insforge backend. Get production-ready auth in 5 minutes.
4
+
5
+ ## Why @insforge/nextjs?
6
+
7
+ ✅ **Built-in Auth Pages** - Backend-hosted UI, no React code needed
8
+ ✅ **5-Minute Setup** - Provider + API route + callback + middleware = done
9
+ ✅ **Full SSR Support** - Works with Next.js App Router and Server Components
10
+ ✅ **Auto OAuth** - 11 providers configured from backend automatically
11
+ ✅ **TypeScript First** - Complete type safety out of the box
12
+
13
+ **Need custom UI?** Scroll to [Customization](#customization) for custom components and styling.
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @insforge/nextjs
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Quick Start
24
+
25
+ ### 1. Setup Provider
26
+
27
+ Wrap your app with `InsforgeProvider` in the root layout:
28
+
29
+ ```tsx
30
+ // app/layout.tsx
31
+ import { InsforgeProvider } from '@insforge/nextjs';
32
+
33
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
34
+ return (
35
+ <html lang="en">
36
+ <body>
37
+ <InsforgeProvider
38
+ baseUrl={process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!}
39
+ afterSignInUrl="/dashboard"
40
+ >
41
+ {children}
42
+ </InsforgeProvider>
43
+ </body>
44
+ </html>
45
+ );
46
+ }
47
+ ```
48
+
49
+ > **Zero Configuration**: Styles are automatically injected via Emotion CSS-in-JS. No CSS imports needed!
50
+
51
+ ### 2. Create API Route
52
+
53
+ Create an API route to sync tokens to HTTP-only cookies (enables SSR):
54
+
55
+ ```tsx
56
+ // app/api/auth/route.ts
57
+ import { createAuthRouteHandlers } from '@insforge/nextjs/api';
58
+
59
+ const handlers = createAuthRouteHandlers({
60
+ baseUrl: process.env.INSFORGE_BASE_URL || process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,
61
+ cookieName: 'insforge_token',
62
+ });
63
+
64
+ export const POST = handlers.POST;
65
+ export const GET = handlers.GET;
66
+ export const DELETE = handlers.DELETE;
67
+ ```
68
+
69
+ **What it does:**
70
+
71
+ - `POST /api/auth` - Syncs localStorage token to HTTP-only cookie
72
+ - `GET /api/auth` - Retrieves user data server-side
73
+ - `DELETE /api/auth` - Clears auth cookie on sign out
74
+
75
+ ### 3. Setup Middleware
76
+
77
+ Protect routes with middleware:
78
+
79
+ ```ts
80
+ // middleware.ts
81
+ import { InsforgeMiddleware } from '@insforge/nextjs/middleware';
82
+
83
+ export default InsforgeMiddleware({
84
+ baseUrl: process.env.INSFORGE_BASE_URL!,
85
+ publicRoutes: ['/auth/callback', '/'],
86
+ cookieName: 'insforge_token',
87
+ });
88
+
89
+ export const config = {
90
+ matcher: [
91
+ '/((?!api|_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
92
+ ],
93
+ };
94
+ ```
95
+
96
+ **What it does:**
97
+
98
+ - Redirects unauthenticated users to backend auth pages
99
+ - Verifies tokens server-side
100
+ - Allows public routes without auth
101
+
102
+ ### 4. Use Hooks & Components
103
+
104
+ ```tsx
105
+ // app/page.tsx
106
+ import { SignedIn, SignedOut, UserButton } from '@insforge/nextjs';
107
+
108
+ export default function Home() {
109
+ return (
110
+ <div>
111
+ <SignedOut>
112
+ <a href="/sign-in">Sign In</a>
113
+ </SignedOut>
114
+
115
+ <SignedIn>
116
+ <UserButton afterSignOutUrl="/" />
117
+ <h1>Welcome back!</h1>
118
+ </SignedIn>
119
+ </div>
120
+ );
121
+ }
122
+ ```
123
+
124
+ **Available Hooks:**
125
+
126
+ ```tsx
127
+ import { useAuth, useUser } from '@insforge/nextjs';
128
+
129
+ function Component() {
130
+ const { signIn, signUp, signOut, isSignedIn, isLoaded } = useAuth();
131
+ const { user, updateUser } = useUser();
132
+
133
+ return <div>Email: {user?.email}</div>;
134
+ }
135
+ ```
136
+
137
+ **That's it!** 🎉 Your app now has production-ready authentication.
138
+
139
+ ---
140
+
141
+ ## How It Works
142
+
143
+ ```
144
+ 1. User clicks "Sign In" → Middleware redirects to backend auth page
145
+
146
+ 2. User signs in on backend (https://your-project.insforge.app/auth/sign-in)
147
+
148
+ 3. Backend redirects: yourapp.com?access_token=xxx&user_id=xxx...
149
+
150
+ 4. SDK auto-detects URL parameters:
151
+ - Stores token in localStorage
152
+ - Provider automatically reloads auth state
153
+ - Token syncs to HTTP-only cookie (via API route)
154
+
155
+ 5. User sees dashboard with authenticated state
156
+ ```
157
+
158
+ **Two-Storage Architecture:**
159
+
160
+ - **localStorage**: Client-side token access (hooks, components, SDK)
161
+ - **HTTP-only cookie**: Server-side token access (middleware, SSR)
162
+
163
+ ---
164
+
165
+ ## Customization
166
+
167
+ ### Custom Auth Pages
168
+
169
+ Want custom branding? Create custom auth pages instead of using built-in pages:
170
+
171
+ ```tsx
172
+ // app/sign-in/page.tsx
173
+ 'use client';
174
+
175
+ import { SignIn } from '@insforge/nextjs';
176
+ import { useRouter } from 'next/navigation';
177
+
178
+ export default function SignInPage() {
179
+ const router = useRouter();
180
+
181
+ return (
182
+ <div className="min-h-screen flex items-center justify-center bg-gray-50">
183
+ <SignIn
184
+ afterSignInUrl="/dashboard"
185
+ onSuccess={(user) => {
186
+ console.log('Signed in:', user);
187
+ router.push('/dashboard');
188
+ }}
189
+ />
190
+ </div>
191
+ );
192
+ }
193
+ ```
194
+
195
+ **Additional Auth Components:**
196
+
197
+ ```tsx
198
+ // Password reset flow
199
+ import { ForgotPassword, ResetPassword, VerifyEmail } from '@insforge/nextjs';
200
+
201
+ // app/forgot-password/page.tsx
202
+ <ForgotPassword backToSignInUrl="/sign-in" />
203
+
204
+ // app/reset-password/page.tsx (with token from URL)
205
+ <ResetPassword token={token} backToSignInUrl="/sign-in" />
206
+
207
+ // app/verify-email/page.tsx (with token from URL)
208
+ <VerifyEmail token={token} />
209
+ ```
210
+
211
+ **Available Atomic Components:**
212
+
213
+ - `AuthContainer` - Main form container
214
+ - `AuthHeader` - Title and subtitle
215
+ - `AuthFormField` - Standard input field
216
+ - `AuthPasswordField` - Password field with visibility toggle
217
+ - `AuthPasswordStrengthIndicator` - Password requirement checklist
218
+ - `AuthSubmitButton` - Submit button with loading states
219
+ - `AuthErrorBanner` - Error message display
220
+ - `AuthDivider` - Visual separator
221
+ - `AuthOAuthProviders` - OAuth provider buttons grid
222
+ - `AuthOAuthButton` - Individual OAuth button
223
+ - `AuthVerificationCodeInput` - OTP/2FA code input
224
+ - `AuthLink` - Navigation link
225
+ - `AuthBranding` - Insforge branding footer
226
+
227
+ ### Server-Side Usage
228
+
229
+ Access auth data in Server Components, API Routes, and Server Actions using the `auth()` helper:
230
+
231
+ #### Using in Server Components
232
+
233
+ ```tsx
234
+ // app/dashboard/page.tsx (Server Component)
235
+ import { auth } from '@insforge/nextjs/server';
236
+
237
+ export default async function Dashboard() {
238
+ const { userId, user } = await auth();
239
+
240
+ if (!userId) {
241
+ return <div>Not authenticated</div>;
242
+ }
243
+
244
+ return <div>Welcome, {user?.email}!</div>;
245
+ }
246
+ ```
247
+
248
+ #### Using in API Routes
249
+
250
+ ```tsx
251
+ // app/api/posts/route.ts
252
+ import { auth, createServerClient } from '@insforge/nextjs/server';
253
+ import { NextResponse } from 'next/server';
254
+
255
+ export async function GET() {
256
+ const { userId, token } = await auth();
257
+
258
+ if (!userId || !token) {
259
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
260
+ }
261
+
262
+ // Option 1: Use auth info directly
263
+ return NextResponse.json({ userId, message: 'Authenticated!' });
264
+
265
+ // Option 2: Use createServerClient for database operations
266
+ const insforge = await createServerClient({
267
+ baseUrl: process.env.INSFORGE_BASE_URL!,
268
+ });
269
+
270
+ if (!insforge) {
271
+ return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
272
+ }
273
+
274
+ const result = await insforge.database.from('posts').select();
275
+ return NextResponse.json(result.data);
276
+ }
277
+ ```
278
+
279
+ #### Using in Server Actions
280
+
281
+ ```tsx
282
+ 'use server';
283
+
284
+ import { auth } from '@insforge/nextjs/server';
285
+ import { revalidatePath } from 'next/cache';
286
+
287
+ export async function createPost(formData: FormData) {
288
+ const { userId } = await auth();
289
+
290
+ if (!userId) {
291
+ throw new Error('Not authenticated');
292
+ }
293
+
294
+ // Create post with userId
295
+ const title = formData.get('title');
296
+ // ... insert into database
297
+
298
+ revalidatePath('/posts');
299
+ }
300
+ ```
301
+
302
+ ### Conditional Rendering
303
+
304
+ ```tsx
305
+ import { Protect } from '@insforge/nextjs';
306
+
307
+ // Role-based access
308
+ <Protect condition={(user) => user.role === 'admin'}>
309
+ <AdminPanel />
310
+ </Protect>
311
+
312
+ // Custom logic
313
+ <Protect condition={(user) => user.emailVerified}>
314
+ <VerifiedUserFeature />
315
+ </Protect>
316
+ ```
317
+
318
+ ### Auth Change Callback
319
+
320
+ Track authentication events:
321
+
322
+ ```tsx
323
+ <InsforgeProvider
324
+ baseUrl={baseUrl}
325
+ onAuthChange={(user) => {
326
+ if (user) {
327
+ analytics.identify(user.id);
328
+ } else {
329
+ analytics.reset();
330
+ }
331
+ }}
332
+ />
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Local Development
338
+
339
+ During local development, backend typically runs on a different port:
340
+
341
+ ```bash
342
+ # .env.local
343
+ NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130
344
+ INSFORGE_BASE_URL=http://localhost:7130
345
+ ```
346
+
347
+ ---
348
+
349
+ ## TypeScript
350
+
351
+ Full TypeScript support with exported types:
352
+
353
+ ```tsx
354
+ import type {
355
+ InsforgeUser,
356
+ InsforgeCallbackProps,
357
+ SignInProps,
358
+ SignUpProps,
359
+ ForgotPasswordProps,
360
+ ResetPasswordProps,
361
+ VerifyEmailProps,
362
+ SignInAppearance,
363
+ SignUpAppearance,
364
+ UserButtonProps,
365
+ ProtectProps,
366
+ OAuthProvider,
367
+ } from '@insforge/nextjs';
368
+ ```
369
+
370
+ ---
371
+
372
+ ## Support
373
+
374
+ - **Documentation**: https://docs.insforge.dev
375
+ - **GitHub Issues**: https://github.com/InsForge/InsForge/issues
376
+ - **Discord Community**: https://discord.com/invite/DvBtaEc9Jz
377
+
378
+ ## License
379
+
380
+ MIT
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/api/index.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\nexport type { AuthRouteConfig } from './route-handlers';\n"],"mappings":"AAAA,SAAS,+BAA+B;","names":[]}
1
+ {"version":3,"sources":["../../../src/api/index.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\r\nexport type { AuthRouteConfig } from './route-handlers';\r\n"],"mappings":"AAAA,SAAS,+BAA+B;","names":[]}
@@ -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 // 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":[]}
1
+ {"version":3,"sources":["../../../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\nimport { createClient } from '@insforge/sdk';\r\nimport {\r\n COOKIE_NAMES,\r\n COOKIE_DEFAULTS,\r\n getBaseCookieOptions,\r\n getClearCookieOptions,\r\n serializeUserCookie,\r\n} from '../lib/cookies';\r\nimport { InsforgeUser } from '@insforge/shared';\r\nimport { GetCurrentSessionResponse } from '@insforge/shared-schemas';\r\n\r\ninterface SignInRequestBody {\r\n action: 'sign-in';\r\n email: string;\r\n password: string;\r\n}\r\n\r\ninterface SignUpRequestBody {\r\n action: 'sign-up';\r\n email: string;\r\n password: string;\r\n}\r\n\r\ninterface SyncTokenRequestBody {\r\n action: 'sync-token';\r\n}\r\n\r\ntype AuthRequestBody = SignInRequestBody | SignUpRequestBody | SyncTokenRequestBody;\r\n\r\nexport interface AuthRouteConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Cookie max age in seconds (default: 7 days)\r\n * @default 604800\r\n */\r\n cookieMaxAge?: number;\r\n\r\n /**\r\n * Whether to use secure cookies (HTTPS only)\r\n * Auto-detected based on environment\r\n */\r\n secure?: boolean;\r\n}\r\n\r\ninterface AuthRouteHandlers {\r\n POST: (request: NextRequest) => Promise<NextResponse>;\r\n GET: (request: NextRequest) => Promise<NextResponse>;\r\n DELETE: (request: NextRequest) => Promise<NextResponse>;\r\n}\r\n\r\n/**\r\n * Creates authentication route handlers for Next.js App Router\r\n * These handlers set HTTP-only cookies that can be read by middleware\r\n *\r\n * @example\r\n * ```ts\r\n * // app/api/auth/[...auth]/route.ts\r\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\r\n *\r\n * const handlers = createAuthRouteHandlers({\r\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\r\n * });\r\n *\r\n * export const POST = handlers.POST;\r\n * export const GET = handlers.GET;\r\n * export const DELETE = handlers.DELETE;\r\n * ```\r\n */\r\nexport function createAuthRouteHandlers(config: AuthRouteConfig): AuthRouteHandlers {\r\n const { baseUrl, cookieMaxAge = COOKIE_DEFAULTS.MAX_AGE } = config;\r\n\r\n const insforge = createClient({ baseUrl });\r\n\r\n /**\r\n * Helper to set auth cookies (session token + user identity)\r\n */\r\n function setAuthCookies(response: NextResponse, token: string, user: InsforgeUser) {\r\n const cookieOptions = getBaseCookieOptions({\r\n maxAge: cookieMaxAge,\r\n secure: config.secure,\r\n });\r\n\r\n // Set session cookie (access token)\r\n response.cookies.set({\r\n name: COOKIE_NAMES.SESSION,\r\n value: token,\r\n ...cookieOptions,\r\n });\r\n\r\n // Set user identity cookie (basic info for SSR)\r\n response.cookies.set({\r\n name: COOKIE_NAMES.USER,\r\n value: serializeUserCookie(user),\r\n ...cookieOptions,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * Helper to clear auth cookies\r\n */\r\n function clearAuthCookies(response: NextResponse) {\r\n const clearOptions = getClearCookieOptions({ secure: config.secure });\r\n\r\n // Clear session cookie\r\n response.cookies.set({\r\n name: COOKIE_NAMES.SESSION,\r\n value: '',\r\n ...clearOptions,\r\n });\r\n\r\n // Clear user cookie\r\n response.cookies.set({\r\n name: COOKIE_NAMES.USER,\r\n value: '',\r\n ...clearOptions,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n /**\r\n * POST handler for authentication actions\r\n * Supports: sign-in, sign-up\r\n */\r\n async function POST(request: NextRequest) {\r\n try {\r\n const body = (await request.json()) as AuthRequestBody;\r\n const { action } = body;\r\n\r\n if (!action) {\r\n return NextResponse.json({ error: 'Action is required' }, { status: 400 });\r\n }\r\n\r\n switch (action) {\r\n case 'sign-in': {\r\n const { email, password } = body;\r\n if (!email || !password) {\r\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\r\n }\r\n\r\n const result = await insforge.auth.signInWithPassword({\r\n email,\r\n password,\r\n });\r\n\r\n if (result.error) {\r\n return NextResponse.json({ error: result.error.message }, { status: 401 });\r\n }\r\n\r\n if (!result.data || !result.data.user) {\r\n return NextResponse.json({ error: 'Authentication failed' }, { status: 401 });\r\n }\r\n\r\n const response = NextResponse.json({\r\n user: result.data.user,\r\n session: {\r\n userId: result.data.user.id,\r\n expiresAt: '',\r\n createdAt: new Date().toISOString(),\r\n },\r\n });\r\n\r\n setAuthCookies(response, result.data.accessToken || '', {\r\n id: result.data.user.id,\r\n email: result.data.user.email,\r\n profile: result.data.user.profile || null,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n case 'sign-up': {\r\n const { email, password } = body;\r\n if (!email || !password) {\r\n return NextResponse.json({ error: 'Email and password are required' }, { status: 400 });\r\n }\r\n\r\n const result = await insforge.auth.signUp({ email, password });\r\n\r\n if (result.error) {\r\n return NextResponse.json({ error: result.error.message }, { status: 400 });\r\n }\r\n\r\n if (!result.data || !result.data.user) {\r\n return NextResponse.json({ error: 'Sign up failed' }, { status: 400 });\r\n }\r\n\r\n const response = NextResponse.json({\r\n user: result.data.user,\r\n session: {\r\n userId: result.data.user.id,\r\n expiresAt: '',\r\n createdAt: new Date().toISOString(),\r\n },\r\n });\r\n\r\n setAuthCookies(response, result.data.accessToken || '', {\r\n id: result.data.user.id,\r\n email: result.data.user.email,\r\n profile: result.data.user.profile || null,\r\n });\r\n\r\n return response;\r\n }\r\n\r\n case 'sync-token': {\r\n // Syncs access token to HTTP-only cookie for server-side usage\r\n // Token is passed via Authorization header (preferred)\r\n const authHeader = request.headers.get('Authorization');\r\n const tokenFromHeader = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null;\r\n const token = tokenFromHeader;\r\n\r\n if (!token) {\r\n console.error('[Auth Route] No token provided in header');\r\n return NextResponse.json({ error: 'Token is required' }, { status: 400 });\r\n }\r\n\r\n // User data can be passed from client (preferred) or fetched from backend\r\n const { user: userFromBody } = body as { user?: InsforgeUser };\r\n\r\n // If user data is provided by client, use it directly (faster)\r\n if (userFromBody?.id && userFromBody?.email) {\r\n const nextResponse = NextResponse.json({\r\n user: userFromBody,\r\n session: {\r\n userId: userFromBody.id,\r\n expiresAt: '',\r\n createdAt: new Date().toISOString(),\r\n },\r\n });\r\n\r\n setAuthCookies(nextResponse, token, {\r\n id: userFromBody.id,\r\n email: userFromBody.email,\r\n profile: userFromBody.profile || null,\r\n });\r\n\r\n return nextResponse;\r\n }\r\n\r\n // Fallback: Verify the token and get user data from backend\r\n try {\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('[Auth API] Token validation failed:', errorText);\r\n return NextResponse.json(\r\n { error: 'Invalid token', details: errorText },\r\n { status: 401 }\r\n );\r\n }\r\n\r\n const session = (await response.json()) as GetCurrentSessionResponse;\r\n\r\n const nextResponse = NextResponse.json({\r\n user: session.user,\r\n session: {\r\n userId: session.user.id,\r\n expiresAt: '',\r\n createdAt: new Date().toISOString(),\r\n },\r\n });\r\n\r\n setAuthCookies(nextResponse, token, {\r\n id: session.user.id,\r\n email: session.user.email,\r\n profile: session.user.profile || null,\r\n });\r\n\r\n return nextResponse;\r\n } catch (error) {\r\n console.error('[Auth API] Token validation error:', error);\r\n return NextResponse.json(\r\n { error: 'Token validation failed', details: String(error) },\r\n { status: 401 }\r\n );\r\n }\r\n }\r\n\r\n default:\r\n return NextResponse.json({ error: 'Invalid action' }, { status: 400 });\r\n }\r\n } catch (error) {\r\n console.error('[Auth API Error]:', error);\r\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\r\n }\r\n }\r\n\r\n /**\r\n * GET handler to check current session\r\n */\r\n async function GET(request: NextRequest) {\r\n try {\r\n const token = request.cookies.get(COOKIE_NAMES.SESSION)?.value;\r\n\r\n if (!token) {\r\n return NextResponse.json({ user: null, session: null });\r\n }\r\n\r\n // Verify token with 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 nextResponse = NextResponse.json({ user: null, session: null });\r\n clearAuthCookies(nextResponse);\r\n return nextResponse;\r\n }\r\n\r\n const session = (await response.json()) as GetCurrentSessionResponse;\r\n\r\n return NextResponse.json({\r\n user: session.user,\r\n });\r\n } catch (error) {\r\n console.error('[Auth API Error]:', error);\r\n return NextResponse.json({ user: null, session: null });\r\n }\r\n }\r\n\r\n /**\r\n * DELETE handler for sign out\r\n */\r\n async function DELETE(request: NextRequest) {\r\n try {\r\n const token = request.cookies.get(COOKIE_NAMES.SESSION)?.value;\r\n\r\n if (token) {\r\n // Call backend sign out\r\n try {\r\n await fetch(`${baseUrl}/auth/sessions/current`, {\r\n method: 'DELETE',\r\n headers: {\r\n Authorization: `Bearer ${token}`,\r\n 'Content-Type': 'application/json',\r\n },\r\n });\r\n } catch (error) {\r\n // Ignore backend errors during sign out\r\n console.error('[Auth API] Sign out error:', error);\r\n }\r\n }\r\n\r\n const response = NextResponse.json({ success: true });\r\n clearAuthCookies(response);\r\n\r\n return response;\r\n } catch (error) {\r\n console.error('[Auth API Error]:', error);\r\n return NextResponse.json({ error: 'Internal server error' }, { status: 500 });\r\n }\r\n }\r\n\r\n return {\r\n POST,\r\n GET,\r\n DELETE,\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/components.tsx"],"sourcesContent":["'use client';\n\n/**\n * Client-side UI components boundary for Next.js App Router\n * All components from @insforge/react are re-exported here with 'use client' directive\n */\n\n// Main components\nexport {\n SignIn,\n SignUp,\n ForgotPassword,\n ResetPassword,\n VerifyEmail,\n UserButton,\n Protect,\n SignedIn,\n SignedOut,\n SignInButton,\n SignUpButton,\n} from '@insforge/react/components';\n\n// Form components\nexport {\n SignInForm,\n SignUpForm,\n ForgotPasswordForm,\n ResetPasswordForm,\n VerifyEmailStatus,\n} from '@insforge/react/components';\n\n// Atom components\nexport {\n AuthBranding,\n AuthContainer,\n AuthHeader,\n AuthErrorBanner,\n AuthFormField,\n AuthPasswordField,\n AuthPasswordStrengthIndicator,\n AuthSubmitButton,\n AuthLink,\n AuthDivider,\n AuthOAuthButton,\n AuthOAuthProviders,\n AuthVerificationCodeInput,\n AuthEmailVerificationStep,\n AuthResetPasswordVerificationStep,\n} from '@insforge/react/components';\n\n// Re-export all component types\nexport type {\n SignInProps,\n SignUpProps,\n ForgotPasswordProps,\n ResetPasswordProps,\n VerifyEmailProps,\n UserButtonProps,\n ProtectProps,\n ConditionalProps,\n SignInFormProps,\n SignUpFormProps,\n ForgotPasswordFormProps,\n ResetPasswordFormProps,\n VerifyEmailStatusProps,\n AuthContainerProps,\n AuthHeaderProps,\n AuthErrorBannerProps,\n AuthFormFieldProps,\n AuthPasswordFieldProps,\n AuthPasswordStrengthIndicatorProps,\n AuthSubmitButtonProps,\n AuthLinkProps,\n AuthDividerProps,\n AuthOAuthButtonProps,\n AuthOAuthProvidersProps,\n AuthVerificationCodeInputProps,\n} from '@insforge/react/components';\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/components.tsx"],"sourcesContent":["'use client';\r\n\r\n/**\r\n * Client-side UI components boundary for Next.js App Router\r\n * All components from @insforge/react are re-exported here with 'use client' directive\r\n */\r\n\r\n// Main components\r\nexport {\r\n SignIn,\r\n SignUp,\r\n ForgotPassword,\r\n ResetPassword,\r\n VerifyEmail,\r\n UserButton,\r\n Protect,\r\n SignedIn,\r\n SignedOut,\r\n SignInButton,\r\n SignUpButton,\r\n} from '@insforge/react/components';\r\n\r\n// Form components\r\nexport {\r\n SignInForm,\r\n SignUpForm,\r\n ForgotPasswordForm,\r\n ResetPasswordForm,\r\n VerifyEmailStatus,\r\n} from '@insforge/react/components';\r\n\r\n// Atom components\r\nexport {\r\n AuthBranding,\r\n AuthContainer,\r\n AuthHeader,\r\n AuthErrorBanner,\r\n AuthFormField,\r\n AuthPasswordField,\r\n AuthPasswordStrengthIndicator,\r\n AuthSubmitButton,\r\n AuthLink,\r\n AuthDivider,\r\n AuthOAuthButton,\r\n AuthOAuthProviders,\r\n AuthVerificationCodeInput,\r\n AuthEmailVerificationStep,\r\n AuthResetPasswordVerificationStep,\r\n} from '@insforge/react/components';\r\n\r\n// Re-export all component types\r\nexport type {\r\n SignInProps,\r\n SignUpProps,\r\n ForgotPasswordProps,\r\n ResetPasswordProps,\r\n VerifyEmailProps,\r\n UserButtonProps,\r\n ProtectProps,\r\n ConditionalProps,\r\n SignInFormProps,\r\n SignUpFormProps,\r\n ForgotPasswordFormProps,\r\n ResetPasswordFormProps,\r\n VerifyEmailStatusProps,\r\n AuthContainerProps,\r\n AuthHeaderProps,\r\n AuthErrorBannerProps,\r\n AuthFormFieldProps,\r\n AuthPasswordFieldProps,\r\n AuthPasswordStrengthIndicatorProps,\r\n AuthSubmitButtonProps,\r\n AuthLinkProps,\r\n AuthDividerProps,\r\n AuthOAuthButtonProps,\r\n AuthOAuthProvidersProps,\r\n AuthVerificationCodeInputProps,\r\n} from '@insforge/react/components';\r\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/client/hooks.ts"],"sourcesContent":["'use client';\n\nimport { useInsforge } from './provider';\nimport { CreateSessionResponse, CreateUserResponse } from '@insforge/shared-schemas';\nimport type { InsforgeUser } from '@insforge/shared';\n\n/**\n * Next.js specific hooks - implemented locally to avoid Context duplication\n */\n\nexport function useAuth(): {\n signIn: (email: string, password: string) => Promise<CreateSessionResponse | { error?: string }>;\n signUp: (email: string, password: string) => Promise<CreateUserResponse | { error?: string }>;\n signOut: () => Promise<void>;\n isLoaded: boolean;\n isSignedIn: boolean | undefined;\n} {\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\n}\n\nexport function useUser(): {\n user: InsforgeUser | null | undefined;\n isLoaded: boolean;\n} {\n const { user, isLoaded } = useInsforge();\n return { user, isLoaded };\n}\n\nexport function usePublicAuthConfig() {\n const { getPublicAuthConfig } = useInsforge();\n return { getPublicAuthConfig };\n}\n"],"mappings":";AAEA,SAAS,mBAAmB;AAQrB,SAAS,UAMd;AACA,QAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW,IAAI,YAAY;AACtE,SAAO,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW;AACzD;AAEO,SAAS,UAGd;AACA,QAAM,EAAE,MAAM,SAAS,IAAI,YAAY;AACvC,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEO,SAAS,sBAAsB;AACpC,QAAM,EAAE,oBAAoB,IAAI,YAAY;AAC5C,SAAO,EAAE,oBAAoB;AAC/B;","names":[]}
1
+ {"version":3,"sources":["../../../src/client/hooks.ts"],"sourcesContent":["'use client';\r\n\r\nimport { useInsforge } from './provider';\r\nimport { CreateSessionResponse, CreateUserResponse } from '@insforge/shared-schemas';\r\nimport type { InsforgeUser } from '@insforge/shared';\r\n\r\n/**\r\n * Next.js specific hooks - implemented locally to avoid Context duplication\r\n */\r\n\r\nexport function useAuth(): {\r\n signIn: (email: string, password: string) => Promise<CreateSessionResponse | { error?: string }>;\r\n signUp: (email: string, password: string) => Promise<CreateUserResponse | { error?: string }>;\r\n signOut: () => Promise<void>;\r\n isLoaded: boolean;\r\n isSignedIn: boolean | undefined;\r\n} {\r\n const { signIn, signUp, signOut, isLoaded, isSignedIn } = useInsforge();\r\n return { signIn, signUp, signOut, isLoaded, isSignedIn };\r\n}\r\n\r\nexport function useUser(): {\r\n user: InsforgeUser | null | undefined;\r\n isLoaded: boolean;\r\n} {\r\n const { user, isLoaded } = useInsforge();\r\n return { user, isLoaded };\r\n}\r\n\r\nexport function usePublicAuthConfig() {\r\n const { getPublicAuthConfig } = useInsforge();\r\n return { getPublicAuthConfig };\r\n}\r\n"],"mappings":";AAEA,SAAS,mBAAmB;AAQrB,SAAS,UAMd;AACA,QAAM,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW,IAAI,YAAY;AACtE,SAAO,EAAE,QAAQ,QAAQ,SAAS,UAAU,WAAW;AACzD;AAEO,SAAS,UAGd;AACA,QAAM,EAAE,MAAM,SAAS,IAAI,YAAY;AACvC,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEO,SAAS,sBAAsB;AACpC,QAAM,EAAE,oBAAoB,IAAI,YAAY;AAC5C,SAAO,EAAE,oBAAoB;AAC/B;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components.server.ts"],"sourcesContent":["// Server Component exports (react-server environment)\n// This file is used when code runs in a Server Component\n\n// Server-only utilities that use next/headers\nexport { auth, type InsforgeAuth } from './server/auth';\nexport { getAuthFromCookies } from './server/InsforgeProvider';\n\n// Server Provider (deprecated but exported for backward compatibility)\nexport {\n InsforgeServerProvider,\n type InsforgeServerProviderProps,\n type InsforgeProviderServerProps,\n} from './server/InsforgeProvider';\n"],"mappings":"AAIA,SAAS,YAA+B;AACxC,SAAS,0BAA0B;AAGnC;AAAA,EACE;AAAA,OAGK;","names":[]}
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":[]}
@@ -1 +1 @@
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":[]}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// ============================================================================\r\n// Providers\r\n// ============================================================================\r\n\r\n// Browser Provider - The recommended way to use Insforge in Next.js\r\n// Use this directly in a client component for proper SDK client sharing\r\nexport {\r\n InsforgeBrowserProvider,\r\n ClientInsforgeProvider, // Deprecated alias\r\n type InsforgeBrowserProviderProps,\r\n type InitialAuthState,\r\n} from './client/provider';\r\n\r\n// Server-only exports (uses conditional exports via #components)\r\n// In Server Components: exports auth, getAuthFromCookies, InsforgeServerProvider\r\n// In Client Components: not available (will error if imported, which is correct)\r\nexport {\r\n auth,\r\n type InsforgeAuth,\r\n getAuthFromCookies,\r\n InsforgeServerProvider,\r\n type InsforgeServerProviderProps,\r\n type InsforgeProviderServerProps,\r\n} from '#components';\r\n\r\n// Hooks (from client)\r\nexport { useInsforge } from './client/provider';\r\n\r\n/**\r\n * These need to be explicitly listed. Do not use an * here.\r\n * If you do, app router will break.\r\n *\r\n * Pattern learned from @clerk/nextjs\r\n */\r\n\r\n// Main UI Components\r\nexport {\r\n SignIn,\r\n SignUp,\r\n ForgotPassword,\r\n ResetPassword,\r\n VerifyEmail,\r\n UserButton,\r\n Protect,\r\n SignedIn,\r\n SignedOut,\r\n SignInButton,\r\n SignUpButton,\r\n} from './client/components';\r\n\r\n// Form Components\r\nexport {\r\n SignInForm,\r\n SignUpForm,\r\n ForgotPasswordForm,\r\n ResetPasswordForm,\r\n VerifyEmailStatus,\r\n} from './client/components';\r\n\r\n// Atom Components\r\nexport {\r\n AuthBranding,\r\n AuthContainer,\r\n AuthHeader,\r\n AuthErrorBanner,\r\n AuthFormField,\r\n AuthPasswordField,\r\n AuthPasswordStrengthIndicator,\r\n AuthSubmitButton,\r\n AuthLink,\r\n AuthDivider,\r\n AuthOAuthButton,\r\n AuthOAuthProviders,\r\n AuthVerificationCodeInput,\r\n AuthEmailVerificationStep,\r\n AuthResetPasswordVerificationStep,\r\n} from './client/components';\r\n\r\n// Component Types\r\nexport type {\r\n SignInProps,\r\n SignUpProps,\r\n ForgotPasswordProps,\r\n ResetPasswordProps,\r\n VerifyEmailProps,\r\n UserButtonProps,\r\n ProtectProps,\r\n ConditionalProps,\r\n SignInFormProps,\r\n SignUpFormProps,\r\n ForgotPasswordFormProps,\r\n ResetPasswordFormProps,\r\n VerifyEmailStatusProps,\r\n AuthContainerProps,\r\n AuthHeaderProps,\r\n AuthErrorBannerProps,\r\n AuthFormFieldProps,\r\n AuthPasswordFieldProps,\r\n AuthPasswordStrengthIndicatorProps,\r\n AuthSubmitButtonProps,\r\n AuthLinkProps,\r\n AuthDividerProps,\r\n AuthOAuthButtonProps,\r\n AuthOAuthProvidersProps,\r\n AuthVerificationCodeInputProps,\r\n} from './client/components';\r\n\r\n// Hooks\r\nexport { useAuth, useUser, usePublicAuthConfig } from './client/hooks';\r\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":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/cookies.ts"],"sourcesContent":["import type { ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies';\nimport { InsforgeUser } from '@insforge/shared';\n\n/**\n * Cookie names used by Insforge authentication\n * These are fixed and should not be changed to ensure consistency\n */\nexport const COOKIE_NAMES = {\n /** Session cookie storing the access token */\n SESSION: 'insforge-session',\n /** User info cookie storing basic user data for SSR */\n USER: 'insforge-user',\n} as const;\n\n/**\n * Default cookie configuration values\n */\nexport const COOKIE_DEFAULTS = {\n /** Default max age: 7 days in seconds */\n MAX_AGE: 7 * 24 * 60 * 60,\n /** Cookie path */\n PATH: '/',\n /** SameSite policy */\n SAME_SITE: 'lax' as const,\n} as const;\n\n/**\n * Options for cookie operations\n */\nexport interface CookieOptions {\n /** Max age in seconds (default: 7 days) */\n maxAge?: number;\n /** Whether to use secure cookies (HTTPS only). Auto-detected if not provided */\n secure?: boolean;\n}\n\n/**\n * Determines if secure cookies should be used based on environment\n * @param explicitSecure - Explicit secure value if provided\n * @returns Whether to use secure cookies\n */\nexport function isSecureCookie(explicitSecure?: boolean): boolean {\n if (explicitSecure !== undefined) {\n return explicitSecure;\n }\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n return process.env.NODE_ENV === 'production';\n}\n\n/**\n * Get base cookie options for auth cookies\n * @param options - Optional cookie configuration\n * @returns Cookie options object compatible with Next.js cookies API\n */\nexport function getBaseCookieOptions(\n options?: CookieOptions\n): Omit<ResponseCookie, 'name' | 'value'> {\n const secure = isSecureCookie(options?.secure);\n const maxAge = options?.maxAge ?? COOKIE_DEFAULTS.MAX_AGE;\n\n return {\n httpOnly: true,\n secure,\n sameSite: COOKIE_DEFAULTS.SAME_SITE,\n maxAge,\n path: COOKIE_DEFAULTS.PATH,\n };\n}\n\n/**\n * Get cookie options for clearing/deleting a cookie\n * @param options - Optional cookie configuration\n * @returns Cookie options for deletion (maxAge: 0)\n */\nexport function getClearCookieOptions(\n options?: Pick<CookieOptions, 'secure'>\n): Omit<ResponseCookie, 'name' | 'value'> {\n const secure = isSecureCookie(options?.secure);\n\n return {\n httpOnly: true,\n secure,\n sameSite: COOKIE_DEFAULTS.SAME_SITE,\n maxAge: 0,\n path: COOKIE_DEFAULTS.PATH,\n };\n}\n\n/**\n * Serialize user info for storage in cookie\n * @param user - User information to serialize\n * @returns JSON string of user info\n */\nexport function serializeUserCookie(user: InsforgeUser): string {\n return JSON.stringify({\n id: user.id,\n email: user.email,\n profile: user.profile || null,\n });\n}\n\n/**\n * Parse user info from cookie value\n * @param cookieValue - Raw cookie value\n * @returns Parsed user info or null if invalid\n */\nexport function parseUserCookie(cookieValue: string | undefined): InsforgeUser | null {\n if (!cookieValue) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(cookieValue) as unknown;\n\n // Type guard to validate the parsed data\n if (\n parsed &&\n typeof parsed === 'object' &&\n 'id' in parsed &&\n 'email' in parsed &&\n 'profile' in parsed &&\n typeof parsed.id === 'string' &&\n typeof parsed.email === 'string' &&\n typeof parsed.profile === 'object'\n ) {\n return parsed as InsforgeUser;\n }\n\n return null;\n } catch {\n return null;\n }\n}\n"],"mappings":"AAOO,MAAM,eAAe;AAAA;AAAA,EAE1B,SAAS;AAAA;AAAA,EAET,MAAM;AACR;AAKO,MAAM,kBAAkB;AAAA;AAAA,EAE7B,SAAS,IAAI,KAAK,KAAK;AAAA;AAAA,EAEvB,MAAM;AAAA;AAAA,EAEN,WAAW;AACb;AAiBO,SAAS,eAAe,gBAAmC;AAChE,MAAI,mBAAmB,QAAW;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI,aAAa;AAClC;AAOO,SAAS,qBACd,SACwC;AACxC,QAAM,SAAS,eAAe,SAAS,MAAM;AAC7C,QAAM,SAAS,SAAS,UAAU,gBAAgB;AAElD,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,UAAU,gBAAgB;AAAA,IAC1B;AAAA,IACA,MAAM,gBAAgB;AAAA,EACxB;AACF;AAOO,SAAS,sBACd,SACwC;AACxC,QAAM,SAAS,eAAe,SAAS,MAAM;AAE7C,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,UAAU,gBAAgB;AAAA,IAC1B,QAAQ;AAAA,IACR,MAAM,gBAAgB;AAAA,EACxB;AACF;AAOO,SAAS,oBAAoB,MAA4B;AAC9D,SAAO,KAAK,UAAU;AAAA,IACpB,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK,WAAW;AAAA,EAC3B,CAAC;AACH;AAOO,SAAS,gBAAgB,aAAsD;AACpF,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,WAAW;AAGrC,QACE,UACA,OAAO,WAAW,YAClB,QAAQ,UACR,WAAW,UACX,aAAa,UACb,OAAO,OAAO,OAAO,YACrB,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,YAAY,UAC1B;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/lib/cookies.ts"],"sourcesContent":["import type { ResponseCookie } from 'next/dist/compiled/@edge-runtime/cookies';\r\nimport { InsforgeUser } from '@insforge/shared';\r\n\r\n/**\r\n * Cookie names used by Insforge authentication\r\n * These are fixed and should not be changed to ensure consistency\r\n */\r\nexport const COOKIE_NAMES = {\r\n /** Session cookie storing the access token */\r\n SESSION: 'insforge-session',\r\n /** User info cookie storing basic user data for SSR */\r\n USER: 'insforge-user',\r\n} as const;\r\n\r\n/**\r\n * Default cookie configuration values\r\n */\r\nexport const COOKIE_DEFAULTS = {\r\n /** Default max age: 7 days in seconds */\r\n MAX_AGE: 7 * 24 * 60 * 60,\r\n /** Cookie path */\r\n PATH: '/',\r\n /** SameSite policy */\r\n SAME_SITE: 'lax' as const,\r\n} as const;\r\n\r\n/**\r\n * Options for cookie operations\r\n */\r\nexport interface CookieOptions {\r\n /** Max age in seconds (default: 7 days) */\r\n maxAge?: number;\r\n /** Whether to use secure cookies (HTTPS only). Auto-detected if not provided */\r\n secure?: boolean;\r\n}\r\n\r\n/**\r\n * Determines if secure cookies should be used based on environment\r\n * @param explicitSecure - Explicit secure value if provided\r\n * @returns Whether to use secure cookies\r\n */\r\nexport function isSecureCookie(explicitSecure?: boolean): boolean {\r\n if (explicitSecure !== undefined) {\r\n return explicitSecure;\r\n }\r\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\r\n return process.env.NODE_ENV === 'production';\r\n}\r\n\r\n/**\r\n * Get base cookie options for auth cookies\r\n * @param options - Optional cookie configuration\r\n * @returns Cookie options object compatible with Next.js cookies API\r\n */\r\nexport function getBaseCookieOptions(\r\n options?: CookieOptions\r\n): Omit<ResponseCookie, 'name' | 'value'> {\r\n const secure = isSecureCookie(options?.secure);\r\n const maxAge = options?.maxAge ?? COOKIE_DEFAULTS.MAX_AGE;\r\n\r\n return {\r\n httpOnly: true,\r\n secure,\r\n sameSite: COOKIE_DEFAULTS.SAME_SITE,\r\n maxAge,\r\n path: COOKIE_DEFAULTS.PATH,\r\n };\r\n}\r\n\r\n/**\r\n * Get cookie options for clearing/deleting a cookie\r\n * @param options - Optional cookie configuration\r\n * @returns Cookie options for deletion (maxAge: 0)\r\n */\r\nexport function getClearCookieOptions(\r\n options?: Pick<CookieOptions, 'secure'>\r\n): Omit<ResponseCookie, 'name' | 'value'> {\r\n const secure = isSecureCookie(options?.secure);\r\n\r\n return {\r\n httpOnly: true,\r\n secure,\r\n sameSite: COOKIE_DEFAULTS.SAME_SITE,\r\n maxAge: 0,\r\n path: COOKIE_DEFAULTS.PATH,\r\n };\r\n}\r\n\r\n/**\r\n * Serialize user info for storage in cookie\r\n * @param user - User information to serialize\r\n * @returns JSON string of user info\r\n */\r\nexport function serializeUserCookie(user: InsforgeUser): string {\r\n return JSON.stringify({\r\n id: user.id,\r\n email: user.email,\r\n profile: user.profile || null,\r\n });\r\n}\r\n\r\n/**\r\n * Parse user info from cookie value\r\n * @param cookieValue - Raw cookie value\r\n * @returns Parsed user info or null if invalid\r\n */\r\nexport function parseUserCookie(cookieValue: string | undefined): InsforgeUser | null {\r\n if (!cookieValue) {\r\n return null;\r\n }\r\n\r\n try {\r\n const parsed = JSON.parse(cookieValue) as unknown;\r\n\r\n // Type guard to validate the parsed data\r\n if (\r\n parsed &&\r\n typeof parsed === 'object' &&\r\n 'id' in parsed &&\r\n 'email' in parsed &&\r\n 'profile' in parsed &&\r\n typeof parsed.id === 'string' &&\r\n typeof parsed.email === 'string' &&\r\n typeof parsed.profile === 'object'\r\n ) {\r\n return parsed as InsforgeUser;\r\n }\r\n\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n"],"mappings":"AAOO,MAAM,eAAe;AAAA;AAAA,EAE1B,SAAS;AAAA;AAAA,EAET,MAAM;AACR;AAKO,MAAM,kBAAkB;AAAA;AAAA,EAE7B,SAAS,IAAI,KAAK,KAAK;AAAA;AAAA,EAEvB,MAAM;AAAA;AAAA,EAEN,WAAW;AACb;AAiBO,SAAS,eAAe,gBAAmC;AAChE,MAAI,mBAAmB,QAAW;AAChC,WAAO;AAAA,EACT;AAEA,SAAO,QAAQ,IAAI,aAAa;AAClC;AAOO,SAAS,qBACd,SACwC;AACxC,QAAM,SAAS,eAAe,SAAS,MAAM;AAC7C,QAAM,SAAS,SAAS,UAAU,gBAAgB;AAElD,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,UAAU,gBAAgB;AAAA,IAC1B;AAAA,IACA,MAAM,gBAAgB;AAAA,EACxB;AACF;AAOO,SAAS,sBACd,SACwC;AACxC,QAAM,SAAS,eAAe,SAAS,MAAM;AAE7C,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,UAAU,gBAAgB;AAAA,IAC1B,QAAQ;AAAA,IACR,MAAM,gBAAgB;AAAA,EACxB;AACF;AAOO,SAAS,oBAAoB,MAA4B;AAC9D,SAAO,KAAK,UAAU;AAAA,IACpB,IAAI,KAAK;AAAA,IACT,OAAO,KAAK;AAAA,IACZ,SAAS,KAAK,WAAW;AAAA,EAC3B,CAAC;AACH;AAOO,SAAS,gBAAgB,aAAsD;AACpF,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,WAAW;AAGrC,QACE,UACA,OAAO,WAAW,YAClB,QAAQ,UACR,WAAW,UACX,aAAa,UACb,OAAO,OAAO,OAAO,YACrB,OAAO,OAAO,UAAU,YACxB,OAAO,OAAO,YAAY,UAC1B;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { COOKIE_NAMES, getBaseCookieOptions, serializeUserCookie } from '../lib/cookies';\n\nexport interface InsforgeMiddlewareConfig {\n /**\n * Base URL of your Insforge backend\n * @example 'https://your-backend.com' or 'http://localhost:3001'\n */\n baseUrl: string;\n\n /**\n * Routes that are public and don't require authentication\n * @default ['/']\n * @example ['/sign-in', '/sign-up', '/', '/about']\n */\n publicRoutes?: string[];\n\n /**\n * Local route path for sign-in (can be customized to any path like '/login')\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\n * @default '/sign-in'\n */\n signInUrl?: string;\n\n /**\n * Local route path for sign-up (can be customized to any path like '/register')\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\n * @default '/sign-up'\n */\n signUpUrl?: string;\n\n /**\n * Local route path for forgot password\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\n * @default '/forgot-password'\n */\n forgotPasswordUrl?: string;\n\n /**\n * URL to redirect to after successful authentication\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\n * @default '/'\n */\n afterSignInUrl?: string;\n\n /**\n * Whether to use built-in authentication pages hosted on the backend\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\n * @default true\n */\n useBuiltInAuth?: boolean;\n}\n\n/**\n * Creates Next.js middleware for protecting routes with Insforge authentication.\n *\n * This middleware provides lightweight route protection by:\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\n * - Checking for auth token presence in cookies\n * - Redirecting unauthenticated users to sign-in page\n * - Allowing public routes to be accessed without authentication\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\n *\n * **How Authentication Flow Works:**\n * 1. User visits protected route → Middleware checks for token\n * 2. No token → Redirects to sign-in (backend or local)\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\n *\n * **Important Notes:**\n * - This middleware only checks if a token exists, it doesn't validate it\n * - Tokens from URL are automatically extracted and stored in cookies\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\n *\n * @param config - Middleware configuration\n * @returns Next.js middleware function\n *\n * @example\n * ```ts\n * // middleware.ts - Using built-in auth\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/', '/about'],\n * afterSignInUrl: '/', // Redirect here after successful auth\n * useBuiltInAuth: true,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Custom local auth pages with custom paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * publicRoutes: ['/login', '/register', '/', '/about'],\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: false,\n * });\n *\n * export const config = {\n * matcher: ['/((?!_next|api|.*\\\\..*).*)'],\n * };\n * ```\n *\n * @example\n * ```ts\n * // middleware.ts - Built-in auth with custom auth route paths\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\n *\n * export default InsforgeMiddleware({\n * baseUrl: 'https://your-backend.com',\n * signInUrl: '/login',\n * signUpUrl: '/register',\n * forgotPasswordUrl: '/forgot',\n * afterSignInUrl: '/dashboard',\n * useBuiltInAuth: true,\n * });\n * ```\n */\nexport const InsforgeMiddleware = (config: InsforgeMiddlewareConfig) => {\n const {\n baseUrl,\n publicRoutes = ['/'],\n signInUrl = '/sign-in',\n signUpUrl = '/sign-up',\n forgotPasswordUrl = '/forgot-password',\n afterSignInUrl = '/',\n useBuiltInAuth = true,\n } = config;\n\n return function middleware(request: NextRequest) {\n const { pathname, searchParams } = request.nextUrl;\n\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\n const accessToken = searchParams.get('access_token');\n const userId = searchParams.get('user_id');\n const email = searchParams.get('email');\n const name = searchParams.get('name');\n\n if (accessToken && userId && email) {\n // Token detected in URL - store it in HTTP-only cookies\n const response = NextResponse.next();\n const cookieOptions = getBaseCookieOptions();\n\n // Set session cookie (access token)\n response.cookies.set(COOKIE_NAMES.SESSION, accessToken, cookieOptions);\n\n // Set user identity cookie (basic user info for SSR)\n response.cookies.set(\n COOKIE_NAMES.USER,\n serializeUserCookie({ id: userId, email, profile: { name: name || undefined } }),\n cookieOptions\n );\n\n return response;\n }\n\n // STEP 2: Handle built-in auth redirects for authentication pages\n // Map local auth routes to backend's fixed auth pages\n if (useBuiltInAuth) {\n const authRouteMapping: Record<string, string> = {\n [signInUrl]: '/auth/sign-in',\n [signUpUrl]: '/auth/sign-up',\n [forgotPasswordUrl]: '/auth/forgot-password',\n };\n\n const backendAuthPath = authRouteMapping[pathname];\n if (backendAuthPath) {\n // Redirect to afterSignInUrl after successful authentication\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\n return NextResponse.redirect(backendAuthUrl.toString());\n }\n }\n\n // STEP 3: Check if route is public\n const isPublicRoute = publicRoutes.some((route) => {\n if (route.endsWith('*')) {\n // Wildcard route: /admin/* matches /admin/anything\n return pathname.startsWith(route.slice(0, -1));\n }\n // Exact match or starts with route path\n return pathname === route || pathname.startsWith(route + '/');\n });\n\n if (isPublicRoute) {\n return NextResponse.next();\n }\n\n // STEP 4: Check for authentication token in cookies\n const token = request.cookies.get(COOKIE_NAMES.SESSION)?.value;\n\n if (!token) {\n // No token found, redirect to sign-in\n if (useBuiltInAuth) {\n // Built-in auth: redirect to backend's /auth/sign-in page\n // Backend will redirect back to current URL with token\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\n backendSignInUrl.searchParams.set('redirect', request.url);\n return NextResponse.redirect(backendSignInUrl);\n } else {\n // Custom auth: redirect to local sign-in page\n const localSignInUrl = new URL(signInUrl, request.url);\n localSignInUrl.searchParams.set('redirect', pathname);\n return NextResponse.redirect(localSignInUrl);\n }\n }\n\n // Token exists in cookie, allow request to continue\n return NextResponse.next();\n };\n};\n"],"mappings":"AAAA,SAAsB,oBAAoB;AAC1C,SAAS,cAAc,sBAAsB,2BAA2B;AAoIjE,MAAM,qBAAqB,CAAC,WAAqC;AACtE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,SAAS,WAAW,SAAsB;AAC/C,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AACnD,UAAM,SAAS,aAAa,IAAI,SAAS;AACzC,UAAM,QAAQ,aAAa,IAAI,OAAO;AACtC,UAAM,OAAO,aAAa,IAAI,MAAM;AAEpC,QAAI,eAAe,UAAU,OAAO;AAElC,YAAM,WAAW,aAAa,KAAK;AACnC,YAAM,gBAAgB,qBAAqB;AAG3C,eAAS,QAAQ,IAAI,aAAa,SAAS,aAAa,aAAa;AAGrE,eAAS,QAAQ;AAAA,QACf,aAAa;AAAA,QACb,oBAAoB,EAAE,IAAI,QAAQ,OAAO,SAAS,EAAE,MAAM,QAAQ,OAAU,EAAE,CAAC;AAAA,QAC/E;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAIA,QAAI,gBAAgB;AAClB,YAAM,mBAA2C;AAAA,QAC/C,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,iBAAiB,GAAG;AAAA,MACvB;AAEA,YAAM,kBAAkB,iBAAiB,QAAQ;AACjD,UAAI,iBAAiB;AAEnB,cAAM,cAAc,IAAI,IAAI,gBAAgB,QAAQ,GAAG,EAAE,SAAS;AAClE,cAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,uBAAe,aAAa,IAAI,YAAY,WAAW;AACvD,eAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,aAAa,OAAO,GAAG;AAEzD,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/middleware/InsforgeMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\r\nimport { COOKIE_NAMES, getBaseCookieOptions, serializeUserCookie } from '../lib/cookies';\r\n\r\nexport interface InsforgeMiddlewareConfig {\r\n /**\r\n * Base URL of your Insforge backend\r\n * @example 'https://your-backend.com' or 'http://localhost:3001'\r\n */\r\n baseUrl: string;\r\n\r\n /**\r\n * Routes that are public and don't require authentication\r\n * @default ['/']\r\n * @example ['/sign-in', '/sign-up', '/', '/about']\r\n */\r\n publicRoutes?: string[];\r\n\r\n /**\r\n * Local route path for sign-in (can be customized to any path like '/login')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-in`\r\n * @default '/sign-in'\r\n */\r\n signInUrl?: string;\r\n\r\n /**\r\n * Local route path for sign-up (can be customized to any path like '/register')\r\n * When using built-in auth, this will redirect to backend's `/auth/sign-up`\r\n * @default '/sign-up'\r\n */\r\n signUpUrl?: string;\r\n\r\n /**\r\n * Local route path for forgot password\r\n * When using built-in auth, this will redirect to backend's `/auth/forgot-password`\r\n * @default '/forgot-password'\r\n */\r\n forgotPasswordUrl?: string;\r\n\r\n /**\r\n * URL to redirect to after successful authentication\r\n * When user completes sign-in/sign-up, they will be redirected to this URL with token in URL\r\n * @default '/'\r\n */\r\n afterSignInUrl?: string;\r\n\r\n /**\r\n * Whether to use built-in authentication pages hosted on the backend\r\n * - When true: redirects to backend's `/auth/sign-in` and `/auth/sign-up` pages\r\n * - When false: redirects to local sign-in/sign-up pages (you provide your own components)\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 middleware provides lightweight route protection by:\r\n * - Detecting and storing auth tokens from URL parameters (after backend redirect)\r\n * - Checking for auth token presence in cookies\r\n * - Redirecting unauthenticated users to sign-in page\r\n * - Allowing public routes to be accessed without authentication\r\n * - Mapping local auth routes to backend's fixed paths when using built-in auth\r\n *\r\n * **How Authentication Flow Works:**\r\n * 1. User visits protected route → Middleware checks for token\r\n * 2. No token → Redirects to sign-in (backend or local)\r\n * 3. User accesses auth page (e.g., /sign-in) → Redirects to backend with afterSignInUrl as redirect target\r\n * 4. After sign-in → Backend redirects to `yourapp.com/afterSignInUrl?access_token=xxx&user_id=xxx...`\r\n * 5. Middleware detects `access_token` in URL → Stores in HTTP-only cookie → Cleans URL → Allows access\r\n * 6. SDK also detects token from URL → Stores in localStorage → Updates auth state\r\n *\r\n * **Important Notes:**\r\n * - This middleware only checks if a token exists, it doesn't validate it\r\n * - Tokens from URL are automatically extracted and stored in cookies\r\n * - When `useBuiltInAuth: true`, local routes map to backend's fixed auth paths\r\n * - You can customize local route paths (e.g., `/login`) while backend paths remain fixed\r\n * - After successful auth, users are redirected to `afterSignInUrl` (default: `/`), not back to the auth page\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 - Using built-in auth\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 * publicRoutes: ['/', '/about'],\r\n * afterSignInUrl: '/', // Redirect here after successful auth\r\n * useBuiltInAuth: true,\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 - Custom local auth pages with custom paths\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 * publicRoutes: ['/login', '/register', '/', '/about'],\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * afterSignInUrl: '/dashboard',\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\n * @example\r\n * ```ts\r\n * // middleware.ts - Built-in auth with custom auth route paths\r\n * import { InsforgeMiddleware } from '@insforge/nextjs/middleware';\r\n *\r\n * export default InsforgeMiddleware({\r\n * baseUrl: 'https://your-backend.com',\r\n * signInUrl: '/login',\r\n * signUpUrl: '/register',\r\n * forgotPasswordUrl: '/forgot',\r\n * afterSignInUrl: '/dashboard',\r\n * useBuiltInAuth: true,\r\n * });\r\n * ```\r\n */\r\nexport const InsforgeMiddleware = (config: InsforgeMiddlewareConfig) => {\r\n const {\r\n baseUrl,\r\n publicRoutes = ['/'],\r\n signInUrl = '/sign-in',\r\n signUpUrl = '/sign-up',\r\n forgotPasswordUrl = '/forgot-password',\r\n afterSignInUrl = '/',\r\n useBuiltInAuth = true,\r\n } = config;\r\n\r\n return function middleware(request: NextRequest) {\r\n const { pathname, searchParams } = request.nextUrl;\r\n\r\n // STEP 1: Check if URL contains access_token (from backend redirect after auth)\r\n const accessToken = searchParams.get('access_token');\r\n const userId = searchParams.get('user_id');\r\n const email = searchParams.get('email');\r\n const name = searchParams.get('name');\r\n\r\n if (accessToken && userId && email) {\r\n // Token detected in URL - store it in HTTP-only cookies\r\n const response = NextResponse.next();\r\n const cookieOptions = getBaseCookieOptions();\r\n\r\n // Set session cookie (access token)\r\n response.cookies.set(COOKIE_NAMES.SESSION, accessToken, cookieOptions);\r\n\r\n // Set user identity cookie (basic user info for SSR)\r\n response.cookies.set(\r\n COOKIE_NAMES.USER,\r\n serializeUserCookie({ id: userId, email, profile: { name: name || undefined } }),\r\n cookieOptions\r\n );\r\n\r\n return response;\r\n }\r\n\r\n // STEP 2: Handle built-in auth redirects for authentication pages\r\n // Map local auth routes to backend's fixed auth pages\r\n if (useBuiltInAuth) {\r\n const authRouteMapping: Record<string, string> = {\r\n [signInUrl]: '/auth/sign-in',\r\n [signUpUrl]: '/auth/sign-up',\r\n [forgotPasswordUrl]: '/auth/forgot-password',\r\n };\r\n\r\n const backendAuthPath = authRouteMapping[pathname];\r\n if (backendAuthPath) {\r\n // Redirect to afterSignInUrl after successful authentication\r\n const redirectUrl = new URL(afterSignInUrl, request.url).toString();\r\n const backendAuthUrl = new URL(backendAuthPath, baseUrl);\r\n backendAuthUrl.searchParams.set('redirect', redirectUrl);\r\n return NextResponse.redirect(backendAuthUrl.toString());\r\n }\r\n }\r\n\r\n // STEP 3: Check if route is public\r\n const isPublicRoute = publicRoutes.some((route) => {\r\n if (route.endsWith('*')) {\r\n // Wildcard route: /admin/* matches /admin/anything\r\n return pathname.startsWith(route.slice(0, -1));\r\n }\r\n // Exact match or starts with route path\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 // STEP 4: Check for authentication token in cookies\r\n const token = request.cookies.get(COOKIE_NAMES.SESSION)?.value;\r\n\r\n if (!token) {\r\n // No token found, redirect to sign-in\r\n if (useBuiltInAuth) {\r\n // Built-in auth: redirect to backend's /auth/sign-in page\r\n // Backend will redirect back to current URL with token\r\n const backendSignInUrl = new URL('/auth/sign-in', baseUrl);\r\n backendSignInUrl.searchParams.set('redirect', request.url);\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 return NextResponse.redirect(localSignInUrl);\r\n }\r\n }\r\n\r\n // Token exists in cookie, allow request to continue\r\n return NextResponse.next();\r\n };\r\n};\r\n"],"mappings":"AAAA,SAAsB,oBAAoB;AAC1C,SAAS,cAAc,sBAAsB,2BAA2B;AAoIjE,MAAM,qBAAqB,CAAC,WAAqC;AACtE,QAAM;AAAA,IACJ;AAAA,IACA,eAAe,CAAC,GAAG;AAAA,IACnB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB,IAAI;AAEJ,SAAO,SAAS,WAAW,SAAsB;AAC/C,UAAM,EAAE,UAAU,aAAa,IAAI,QAAQ;AAG3C,UAAM,cAAc,aAAa,IAAI,cAAc;AACnD,UAAM,SAAS,aAAa,IAAI,SAAS;AACzC,UAAM,QAAQ,aAAa,IAAI,OAAO;AACtC,UAAM,OAAO,aAAa,IAAI,MAAM;AAEpC,QAAI,eAAe,UAAU,OAAO;AAElC,YAAM,WAAW,aAAa,KAAK;AACnC,YAAM,gBAAgB,qBAAqB;AAG3C,eAAS,QAAQ,IAAI,aAAa,SAAS,aAAa,aAAa;AAGrE,eAAS,QAAQ;AAAA,QACf,aAAa;AAAA,QACb,oBAAoB,EAAE,IAAI,QAAQ,OAAO,SAAS,EAAE,MAAM,QAAQ,OAAU,EAAE,CAAC;AAAA,QAC/E;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAIA,QAAI,gBAAgB;AAClB,YAAM,mBAA2C;AAAA,QAC/C,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,SAAS,GAAG;AAAA,QACb,CAAC,iBAAiB,GAAG;AAAA,MACvB;AAEA,YAAM,kBAAkB,iBAAiB,QAAQ;AACjD,UAAI,iBAAiB;AAEnB,cAAM,cAAc,IAAI,IAAI,gBAAgB,QAAQ,GAAG,EAAE,SAAS;AAClE,cAAM,iBAAiB,IAAI,IAAI,iBAAiB,OAAO;AACvD,uBAAe,aAAa,IAAI,YAAY,WAAW;AACvD,eAAO,aAAa,SAAS,eAAe,SAAS,CAAC;AAAA,MACxD;AAAA,IACF;AAGA,UAAM,gBAAgB,aAAa,KAAK,CAAC,UAAU;AACjD,UAAI,MAAM,SAAS,GAAG,GAAG;AAEvB,eAAO,SAAS,WAAW,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAC/C;AAEA,aAAO,aAAa,SAAS,SAAS,WAAW,QAAQ,GAAG;AAAA,IAC9D,CAAC;AAED,QAAI,eAAe;AACjB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,QAAQ,QAAQ,QAAQ,IAAI,aAAa,OAAO,GAAG;AAEzD,QAAI,CAAC,OAAO;AAEV,UAAI,gBAAgB;AAGlB,cAAM,mBAAmB,IAAI,IAAI,iBAAiB,OAAO;AACzD,yBAAiB,aAAa,IAAI,YAAY,QAAQ,GAAG;AACzD,eAAO,aAAa,SAAS,gBAAgB;AAAA,MAC/C,OAAO;AAEL,cAAM,iBAAiB,IAAI,IAAI,WAAW,QAAQ,GAAG;AACrD,uBAAe,aAAa,IAAI,YAAY,QAAQ;AACpD,eAAO,aAAa,SAAS,cAAc;AAAA,MAC7C;AAAA,IACF;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/middleware/index.ts"],"sourcesContent":["// Middleware exports - NO 'use client' directive here!\n// Middleware runs in Edge Runtime, not in client browser\n\nexport { InsforgeMiddleware } from './InsforgeMiddleware';\n\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\n"],"mappings":"AAGA,SAAS,0BAA0B;","names":[]}
1
+ {"version":3,"sources":["../../../src/middleware/index.ts"],"sourcesContent":["// Middleware exports - NO 'use client' directive here!\r\n// Middleware runs in Edge Runtime, not in client browser\r\n\r\nexport { InsforgeMiddleware } from './InsforgeMiddleware';\r\n\r\nexport type { InsforgeMiddlewareConfig } from './InsforgeMiddleware';\r\n"],"mappings":"AAGA,SAAS,0BAA0B;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/navigation/NextNavigationAdapter.tsx"],"sourcesContent":["'use client';\nimport type { ReactNode } from 'react';\nimport { useSearchParams as useNextSearchParams } from 'next/navigation';\nimport Link from 'next/link';\nimport type { NavigationAdapter } from '@insforge/react/navigation';\n\n/**\n * Next.js navigation adapter\n * Uses Next.js's useSearchParams hook and Link component\n * Provides optimized navigation with prefetching and client-side routing\n */\nexport const NextNavigationAdapter: NavigationAdapter = {\n /**\n * Returns URLSearchParams from Next.js's useSearchParams\n * Reactive - updates when URL changes\n */\n useSearchParams() {\n const nextSearchParams = useNextSearchParams();\n // Convert Next.js's ReadonlyURLSearchParams to URLSearchParams\n return new URLSearchParams(nextSearchParams?.toString() || '');\n },\n\n /**\n * Next.js's Link component for optimized client-side navigation\n * Supports prefetching, scroll restoration, and shallow routing\n */\n Link({ href, className, children }: { href: string; className?: string; children: ReactNode }) {\n return (\n <Link href={href} className={className}>\n {children}\n </Link>\n );\n },\n};\n"],"mappings":";AA4BM;AA1BN,SAAS,mBAAmB,2BAA2B;AACvD,OAAO,UAAU;AAQV,MAAM,wBAA2C;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtD,kBAAkB;AAChB,UAAM,mBAAmB,oBAAoB;AAE7C,WAAO,IAAI,gBAAgB,kBAAkB,SAAS,KAAK,EAAE;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,EAAE,MAAM,WAAW,SAAS,GAA8D;AAC7F,WACE,oBAAC,QAAK,MAAY,WACf,UACH;AAAA,EAEJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/navigation/NextNavigationAdapter.tsx"],"sourcesContent":["'use client';\r\nimport type { ReactNode } from 'react';\r\nimport { useSearchParams as useNextSearchParams } from 'next/navigation';\r\nimport Link from 'next/link';\r\nimport type { NavigationAdapter } from '@insforge/react/navigation';\r\n\r\n/**\r\n * Next.js navigation adapter\r\n * Uses Next.js's useSearchParams hook and Link component\r\n * Provides optimized navigation with prefetching and client-side routing\r\n */\r\nexport const NextNavigationAdapter: NavigationAdapter = {\r\n /**\r\n * Returns URLSearchParams from Next.js's useSearchParams\r\n * Reactive - updates when URL changes\r\n */\r\n useSearchParams() {\r\n const nextSearchParams = useNextSearchParams();\r\n // Convert Next.js's ReadonlyURLSearchParams to URLSearchParams\r\n return new URLSearchParams(nextSearchParams?.toString() || '');\r\n },\r\n\r\n /**\r\n * Next.js's Link component for optimized client-side navigation\r\n * Supports prefetching, scroll restoration, and shallow routing\r\n */\r\n Link({ href, className, children }: { href: string; className?: string; children: ReactNode }) {\r\n return (\r\n <Link href={href} className={className}>\r\n {children}\r\n </Link>\r\n );\r\n },\r\n};\r\n"],"mappings":";AA4BM;AA1BN,SAAS,mBAAmB,2BAA2B;AACvD,OAAO,UAAU;AAQV,MAAM,wBAA2C;AAAA;AAAA;AAAA;AAAA;AAAA,EAKtD,kBAAkB;AAChB,UAAM,mBAAmB,oBAAoB;AAE7C,WAAO,IAAI,gBAAgB,kBAAkB,SAAS,KAAK,EAAE;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,EAAE,MAAM,WAAW,SAAS,GAA8D;AAC7F,WACE,oBAAC,QAAK,MAAY,WACf,UACH;AAAA,EAEJ;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/navigation/index.ts"],"sourcesContent":["'use client';\nexport { NextNavigationAdapter as NavigationAdapter } from './NextNavigationAdapter';\n"],"mappings":";AACA,SAAkC,6BAAyB;","names":[]}
1
+ {"version":3,"sources":["../../../src/navigation/index.ts"],"sourcesContent":["'use client';\r\nexport { NextNavigationAdapter as NavigationAdapter } from './NextNavigationAdapter';\r\n"],"mappings":";AACA,SAAkC,6BAAyB;","names":[]}
@@ -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
+ }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/auth.ts"],"sourcesContent":["import { cookies } from 'next/headers';\nimport type { InsforgeUser } from '@insforge/shared';\nimport { COOKIE_NAMES, parseUserCookie } from '../lib/cookies';\n\n/**\n * Session information extracted from cookies\n */\nexport interface InsforgeAuth {\n /**\n * The current user's ID, or null if not authenticated\n */\n userId: string | null;\n\n /**\n * The current session token, or null if not authenticated\n */\n token: string | null;\n\n /**\n * User information (email, name) if available\n */\n user: InsforgeUser | null;\n}\n\n/**\n * Get authentication information from cookies in Server Components,\n * Route Handlers, and Server Actions.\n *\n * This function reads the HTTP-only cookies set by the middleware\n * and returns user authentication data.\n *\n * @example\n * ```ts\n * // In a Server Component\n * import { auth } from '@insforge/nextjs/server';\n *\n * export default async function Page() {\n * const { userId, token } = await auth();\n *\n * if (!userId) {\n * return <div>Not authenticated</div>;\n * }\n *\n * return <div>User ID: {userId}</div>;\n * }\n * ```\n *\n * @example\n * ```ts\n * // In an API Route Handler\n * import { auth } from '@insforge/nextjs/server';\n * import { createClient } from '@insforge/sdk';\n *\n * export async function GET() {\n * const { userId, token } = await auth();\n *\n * if (!userId || !token) {\n * return Response.json({ error: 'Unauthorized' }, { status: 401 });\n * }\n *\n * // Use token with SDK\n * const insforge = createClient({\n * baseUrl: process.env.INSFORGE_BASE_URL!,\n * edgeFunctionToken: token,\n * });\n *\n * const result = await insforge.database.from('posts').select();\n * return Response.json(result.data);\n * }\n * ```\n *\n * @example\n * ```ts\n * // In a Server Action\n * 'use server';\n *\n * import { auth } from '@insforge/nextjs/server';\n *\n * export async function createPost(formData: FormData) {\n * const { userId } = await auth();\n *\n * if (!userId) {\n * throw new Error('Not authenticated');\n * }\n *\n * // Create post with userId\n * }\n * ```\n */\nexport async function auth(): Promise<InsforgeAuth> {\n const cookieStore = await cookies();\n\n // Get session token\n const token = cookieStore.get(COOKIE_NAMES.SESSION)?.value || null;\n\n // Get user info using centralized parsing\n const userCookie = cookieStore.get(COOKIE_NAMES.USER)?.value;\n const user = parseUserCookie(userCookie);\n const userId = user?.id || null;\n\n return {\n userId,\n token,\n user,\n };\n}\n"],"mappings":"AAAA,SAAS,eAAe;AAExB,SAAS,cAAc,uBAAuB;AAuF9C,eAAsB,OAA8B;AAClD,QAAM,cAAc,MAAM,QAAQ;AAGlC,QAAM,QAAQ,YAAY,IAAI,aAAa,OAAO,GAAG,SAAS;AAG9D,QAAM,aAAa,YAAY,IAAI,aAAa,IAAI,GAAG;AACvD,QAAM,OAAO,gBAAgB,UAAU;AACvC,QAAM,SAAS,MAAM,MAAM;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/auth.ts"],"sourcesContent":["import { cookies } from 'next/headers';\r\nimport type { InsforgeUser } from '@insforge/shared';\r\nimport { COOKIE_NAMES, parseUserCookie } from '../lib/cookies';\r\n\r\n/**\r\n * Session information extracted from cookies\r\n */\r\nexport interface InsforgeAuth {\r\n /**\r\n * The current user's ID, or null if not authenticated\r\n */\r\n userId: string | null;\r\n\r\n /**\r\n * The current session token, or null if not authenticated\r\n */\r\n token: string | null;\r\n\r\n /**\r\n * User information (email, name) if available\r\n */\r\n user: InsforgeUser | null;\r\n}\r\n\r\n/**\r\n * Get authentication information from cookies in Server Components,\r\n * Route Handlers, and Server Actions.\r\n *\r\n * This function reads the HTTP-only cookies set by the middleware\r\n * and returns user authentication data.\r\n *\r\n * @example\r\n * ```ts\r\n * // In a Server Component\r\n * import { auth } from '@insforge/nextjs/server';\r\n *\r\n * export default async function Page() {\r\n * const { userId, token } = await auth();\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\n * @example\r\n * ```ts\r\n * // In an API Route Handler\r\n * import { auth } from '@insforge/nextjs/server';\r\n * import { createClient } from '@insforge/sdk';\r\n *\r\n * export async function GET() {\r\n * const { userId, token } = await auth();\r\n *\r\n * if (!userId || !token) {\r\n * return Response.json({ error: 'Unauthorized' }, { status: 401 });\r\n * }\r\n *\r\n * // Use token with SDK\r\n * const insforge = createClient({\r\n * baseUrl: process.env.INSFORGE_BASE_URL!,\r\n * edgeFunctionToken: token,\r\n * });\r\n *\r\n * const result = await insforge.database.from('posts').select();\r\n * return Response.json(result.data);\r\n * }\r\n * ```\r\n *\r\n * @example\r\n * ```ts\r\n * // In a Server Action\r\n * 'use server';\r\n *\r\n * import { auth } from '@insforge/nextjs/server';\r\n *\r\n * export async function createPost(formData: FormData) {\r\n * const { userId } = await auth();\r\n *\r\n * if (!userId) {\r\n * throw new Error('Not authenticated');\r\n * }\r\n *\r\n * // Create post with userId\r\n * }\r\n * ```\r\n */\r\nexport async function auth(): Promise<InsforgeAuth> {\r\n const cookieStore = await cookies();\r\n\r\n // Get session token\r\n const token = cookieStore.get(COOKIE_NAMES.SESSION)?.value || null;\r\n\r\n // Get user info using centralized parsing\r\n const userCookie = cookieStore.get(COOKIE_NAMES.USER)?.value;\r\n const user = parseUserCookie(userCookie);\r\n const userId = user?.id || null;\r\n\r\n return {\r\n userId,\r\n token,\r\n user,\r\n };\r\n}\r\n"],"mappings":"AAAA,SAAS,eAAe;AAExB,SAAS,cAAc,uBAAuB;AAuF9C,eAAsB,OAA8B;AAClD,QAAM,cAAc,MAAM,QAAQ;AAGlC,QAAM,QAAQ,YAAY,IAAI,aAAa,OAAO,GAAG,SAAS;AAG9D,QAAM,aAAa,YAAY,IAAI,aAAa,IAAI,GAAG;AACvD,QAAM,OAAO,gBAAgB,UAAU;AACvC,QAAM,SAAS,MAAM,MAAM;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
@@ -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 {\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":[]}
1
+ {"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["// Server-side exports (Server Components, no 'use client')\r\n\r\n// Auth helpers\r\nexport { getAuthFromCookies } from './InsforgeProvider';\r\nexport { auth } from './auth';\r\nexport type { InsforgeAuth } from './auth';\r\n\r\n// Deprecated: Server Provider (doesn't work due to Next.js serialization constraints)\r\n// Use InsforgeBrowserProvider directly in a client component instead\r\nexport {\r\n InsforgeServerProvider,\r\n InsforgeProvider, // Deprecated alias\r\n type InsforgeServerProviderProps,\r\n type InsforgeProviderServerProps, // Deprecated alias\r\n} from './InsforgeProvider';\r\n"],"mappings":"AAGA,SAAS,0BAA0B;AACnC,SAAS,YAAY;AAKrB;AAAA,EACE;AAAA,EACA;AAAA,OAGK;","names":[]}
package/package.json CHANGED
@@ -1,75 +1,75 @@
1
- {
2
- "name": "@insforge/nextjs",
3
- "version": "1.1.6-dev.1",
4
- "description": "Pre-built authentication UI components for Next.js with Insforge backend - zero configuration required",
5
- "type": "module",
6
- "types": "./dist/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "import": "./dist/esm/index.js"
11
- },
12
- "./server": {
13
- "types": "./dist/server/index.d.ts",
14
- "import": "./dist/esm/server/index.js"
15
- },
16
- "./middleware": {
17
- "types": "./dist/middleware/index.d.ts",
18
- "import": "./dist/esm/middleware/index.js"
19
- },
20
- "./api": {
21
- "types": "./dist/api/index.d.ts",
22
- "import": "./dist/esm/api/index.js"
23
- },
24
- "./styles.css": "./src/styles.css"
25
- },
26
- "files": [
27
- "dist",
28
- "src/styles.css",
29
- "README.md"
30
- ],
31
- "scripts": {
32
- "build": "tsup",
33
- "dev": "tsup --watch",
34
- "type-check": "tsc --noEmit"
35
- },
36
- "keywords": [
37
- "insforge",
38
- "nextjs",
39
- "authentication",
40
- "auth",
41
- "ui",
42
- "components",
43
- "react"
44
- ],
45
- "author": "Insforge",
46
- "license": "MIT",
47
- "dependencies": {
48
- "@insforge/react": "1.1.7-dev.0",
49
- "@insforge/sdk": "^1.1.3",
50
- "@insforge/shared": "^1.1.5",
51
- "@insforge/shared-schemas": "^1.1.43"
52
- },
53
- "devDependencies": {
54
- "@eslint/js": "^9.21.0",
55
- "@types/node": "^24.9.2",
56
- "@types/react": "^19.2.2",
57
- "@types/react-dom": "^19.2.2",
58
- "eslint": "^9.21.0",
59
- "eslint-config-prettier": "^10.0.2",
60
- "eslint-plugin-prettier": "^5.2.1",
61
- "eslint-plugin-react": "^7.37.5",
62
- "eslint-plugin-react-hooks": "^5.1.2",
63
- "globals": "^15.12.0",
64
- "prettier": "^3.4.2",
65
- "rimraf": "^6.1.0",
66
- "tsup": "^8.5.0",
67
- "typescript": "^5.9.3",
68
- "typescript-eslint": "^8.23.0"
69
- },
70
- "peerDependencies": {
71
- "next": ">=14.0.0 <17.0.0",
72
- "react": ">=18.0.0 <20.0.0",
73
- "react-dom": ">=18.0.0 <20.0.0"
74
- }
75
- }
1
+ {
2
+ "name": "@insforge/nextjs",
3
+ "version": "1.1.7",
4
+ "description": "Pre-built authentication UI components for Next.js with Insforge backend - zero configuration required",
5
+ "type": "module",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/esm/index.js"
11
+ },
12
+ "./server": {
13
+ "types": "./dist/server/index.d.ts",
14
+ "import": "./dist/esm/server/index.js"
15
+ },
16
+ "./middleware": {
17
+ "types": "./dist/middleware/index.d.ts",
18
+ "import": "./dist/esm/middleware/index.js"
19
+ },
20
+ "./api": {
21
+ "types": "./dist/api/index.d.ts",
22
+ "import": "./dist/esm/api/index.js"
23
+ },
24
+ "./styles.css": "./src/styles.css"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "src/styles.css",
29
+ "README.md"
30
+ ],
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "type-check": "tsc --noEmit"
35
+ },
36
+ "keywords": [
37
+ "insforge",
38
+ "nextjs",
39
+ "authentication",
40
+ "auth",
41
+ "ui",
42
+ "components",
43
+ "react"
44
+ ],
45
+ "author": "Insforge",
46
+ "license": "MIT",
47
+ "dependencies": {
48
+ "@insforge/react": "^1.1.8",
49
+ "@insforge/sdk": "^1.1.4",
50
+ "@insforge/shared": "^1.1.5",
51
+ "@insforge/shared-schemas": "^1.1.43"
52
+ },
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.21.0",
55
+ "@types/node": "^24.9.2",
56
+ "@types/react": "^19.2.2",
57
+ "@types/react-dom": "^19.2.2",
58
+ "eslint": "^9.21.0",
59
+ "eslint-config-prettier": "^10.0.2",
60
+ "eslint-plugin-prettier": "^5.2.1",
61
+ "eslint-plugin-react": "^7.37.5",
62
+ "eslint-plugin-react-hooks": "^5.1.2",
63
+ "globals": "^15.12.0",
64
+ "prettier": "^3.4.2",
65
+ "rimraf": "^6.1.0",
66
+ "tsup": "^8.5.0",
67
+ "typescript": "^5.9.3",
68
+ "typescript-eslint": "^8.23.0"
69
+ },
70
+ "peerDependencies": {
71
+ "next": ">=14.0.0 <17.0.0",
72
+ "react": ">=18.0.0 <20.0.0",
73
+ "react-dom": ">=18.0.0 <20.0.0"
74
+ }
75
+ }
package/src/styles.css CHANGED
@@ -1,9 +1,9 @@
1
- /**
2
- * InsForge Next.js Component Library Styles
3
- * Powered by Tailwind CSS 4.1
4
- *
5
- * This file imports the base @insforge/react styles and adds Next.js-specific customizations.
6
- */
7
-
8
- /* Import base React package styles - contains all component styles */
9
- @import '@insforge/react/styles.css';
1
+ /**
2
+ * InsForge Next.js Component Library Styles
3
+ * Powered by Tailwind CSS 4.1
4
+ *
5
+ * This file imports the base @insforge/react styles and adds Next.js-specific customizations.
6
+ */
7
+
8
+ /* Import base React package styles - contains all component styles */
9
+ @import '@insforge/react/styles.css';