@insforge/nextjs 0.7.10 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  ✅ **Auto OAuth** - 11 providers configured from backend automatically
11
11
  ✅ **TypeScript First** - Complete type safety out of the box
12
12
 
13
- **Need custom UI?** Scroll to [Advanced Usage](#advanced-usage) for custom components and styling.
13
+ **Need custom UI?** Scroll to [Customization](#customization) for custom components and styling.
14
14
 
15
15
  ## Installation
16
16
 
@@ -43,10 +43,6 @@ export default function RootLayout({ children }: { children: React.ReactNode })
43
43
  }
44
44
  ```
45
45
 
46
- **Props:**
47
- - `baseUrl` (required): Your Insforge backend URL
48
- - `onAuthChange` (optional): Callback when auth state changes
49
-
50
46
  > **Auto-styled**: Component styles are automatically injected. No CSS imports needed!
51
47
 
52
48
  ### 2. Create API Route
@@ -74,12 +70,7 @@ export const DELETE = handlers.DELETE;
74
70
 
75
71
  ### 3. Create Callback Page
76
72
 
77
- Create a callback page to complete the authentication flow. Use the `<InsforgeCallback>` component that handles everything automatically:
78
-
79
- - Detects authentication errors from backend
80
- - Validates authentication tokens
81
- - Syncs tokens to HTTP-only cookies for SSR
82
- - Redirects to the destination page
73
+ Handle OAuth redirects with the `<InsforgeCallback>` component:
83
74
 
84
75
  ```tsx
85
76
  // app/auth/callback/page.tsx
@@ -92,39 +83,6 @@ export default function CallbackPage() {
92
83
  }
93
84
  ```
94
85
 
95
- **Optional: Custom loading UI**
96
-
97
- ```tsx
98
- export default function CallbackPage() {
99
- return (
100
- <InsforgeCallback
101
- loadingComponent={
102
- <div className="flex items-center justify-center min-h-screen">
103
- <div className="text-center">
104
- <h2 className="text-2xl font-semibold mb-4">Signing you in...</h2>
105
- <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
106
- </div>
107
- </div>
108
- }
109
- />
110
- );
111
- }
112
- ```
113
-
114
- **Optional: Custom redirect and callbacks**
115
-
116
- ```tsx
117
- export default function CallbackPage() {
118
- return (
119
- <InsforgeCallback
120
- redirectTo="/dashboard"
121
- onSuccess={() => console.log('Authentication successful!')}
122
- onError={(error) => console.error('Authentication failed:', error)}
123
- />
124
- );
125
- }
126
- ```
127
-
128
86
  ### 4. Setup Middleware
129
87
 
130
88
  Protect routes with middleware:
@@ -159,7 +117,6 @@ export default function Home() {
159
117
  return (
160
118
  <div>
161
119
  <SignedOut>
162
- {/* Clicking will redirect to backend auth page */}
163
120
  <a href="/sign-in">Sign In</a>
164
121
  </SignedOut>
165
122
 
@@ -172,12 +129,6 @@ export default function Home() {
172
129
  }
173
130
  ```
174
131
 
175
- **Available Components:**
176
- - `<SignedIn>` - Shows children only when authenticated
177
- - `<SignedOut>` - Shows children only when not authenticated
178
- - `<UserButton>` - User profile button with dropdown
179
- - `<Protect>` - Conditional rendering with custom logic
180
-
181
132
  **Available Hooks:**
182
133
 
183
134
  ```tsx
@@ -198,9 +149,9 @@ function Component() {
198
149
  ## How It Works
199
150
 
200
151
  ```
201
- 1. User clicks "Sign In" → Middleware redirects to backend
152
+ 1. User clicks "Sign In" → Middleware redirects to backend auth page
202
153
 
203
- 2. User signs in on backend-hosted page (https://backend.insforge.app/auth/signin)
154
+ 2. User signs in on backend (https://your-project.insforge.app/auth/sign-in)
204
155
 
205
156
  3. Backend redirects: yourapp.com/auth/callback?access_token=xxx&user_id=xxx...
206
157
 
@@ -219,25 +170,11 @@ function Component() {
219
170
 
220
171
  ---
221
172
 
222
- ## Local Development
223
-
224
- During local development, backend typically runs on a different port:
173
+ ## Customization
225
174
 
226
- ```bash
227
- # .env.local
228
- NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130 # Backend API URL
229
- INSFORGE_BASE_URL=http://localhost:7130 # Backend API URL (for server-side)
230
- ```
231
-
232
- Both variables should point to your Insforge backend URL.
175
+ ### Custom Auth Pages
233
176
 
234
- ---
235
-
236
- ## Advanced Usage
237
-
238
- ### Custom Auth Components
239
-
240
- Want custom branding or additional fields? Create custom auth pages:
177
+ Want custom branding? Create custom auth pages instead of using built-in pages:
241
178
 
242
179
  ```tsx
243
180
  // app/sign-in/page.tsx
@@ -257,72 +194,81 @@ export default function SignInPage() {
257
194
  console.log('Signed in:', user);
258
195
  router.push('/dashboard');
259
196
  }}
260
- onError={(error) => {
261
- console.error('Sign in error:', error);
262
- }}
263
197
  />
264
198
  </div>
265
199
  );
266
200
  }
267
201
  ```
268
202
 
269
- ```tsx
270
- // app/sign-up/page.tsx
271
- 'use client';
272
-
273
- import { SignUp } from '@insforge/nextjs';
203
+ ### Hierarchical Appearance System
274
204
 
275
- export default function SignUpPage() {
276
- return (
277
- <div className="min-h-screen flex items-center justify-center bg-gray-50">
278
- <SignUp afterSignUpUrl="/onboarding" />
279
- </div>
280
- );
281
- }
282
- ```
283
-
284
- **SignIn Props:**
285
- - `afterSignInUrl` - Redirect URL after successful sign in
286
- - `title` / `subtitle` - Custom heading text
287
- - `emailLabel` / `passwordLabel` - Custom field labels
288
- - `submitButtonText` / `loadingButtonText` - Custom button text
289
- - `appearance` - Tailwind CSS classes for styling
290
- - `onSuccess` / `onError` - Callback functions
291
-
292
- **SignUp Props:** Same as SignIn, plus:
293
- - `afterSignUpUrl` - Redirect URL after successful sign up
294
- - Additional text customization options
295
-
296
- ### Styling Components
297
-
298
- All components support an `appearance` prop for Tailwind CSS customization:
205
+ Style any nested component through a hierarchical structure:
299
206
 
300
207
  ```tsx
301
208
  <SignIn
302
209
  appearance={{
303
- containerClassName: "shadow-2xl",
304
- buttonClassName: "bg-blue-600 hover:bg-blue-700"
210
+ card: "bg-gradient-to-br from-blue-50 to-white shadow-2xl",
211
+ header: {
212
+ title: "text-3xl font-bold text-purple-900",
213
+ subtitle: "text-purple-600"
214
+ },
215
+ form: {
216
+ emailField: {
217
+ label: "text-gray-800 font-semibold",
218
+ input: "border-purple-300 focus:border-purple-500 rounded-lg"
219
+ },
220
+ passwordField: {
221
+ input: "border-purple-300 focus:border-purple-500 rounded-lg",
222
+ forgotPasswordLink: "text-purple-600 hover:text-purple-800"
223
+ }
224
+ },
225
+ button: "bg-purple-600 hover:bg-purple-700 rounded-lg h-12",
226
+ link: {
227
+ text: "text-gray-600",
228
+ link: "text-purple-600 hover:text-purple-800 font-semibold"
229
+ },
230
+ oauth: {
231
+ button: "border-2 hover:bg-gray-50 rounded-xl"
232
+ }
305
233
  }}
306
234
  />
235
+ ```
307
236
 
237
+ ### UserButton Styling
238
+
239
+ ```tsx
308
240
  <UserButton
309
- mode="detailed"
241
+ mode="detailed" // or "simple"
310
242
  appearance={{
311
- containerClassName: "ml-auto",
312
- buttonClassName: "hover:bg-gray-100",
313
- nameClassName: "text-white",
314
- emailClassName: "text-gray-300"
243
+ buttonClassName: "hover:bg-gray-100 rounded-full",
244
+ nameClassName: "text-gray-900 font-semibold",
245
+ emailClassName: "text-gray-500",
246
+ dropdownClassName: "shadow-xl"
315
247
  }}
316
248
  />
317
249
  ```
318
250
 
319
- **UserButton Modes:**
320
- - `detailed` (default): Shows avatar + name + email
321
- - `simple`: Shows avatar only
251
+ ### Text Customization
252
+
253
+ ```tsx
254
+ <SignIn
255
+ title="Welcome Back!"
256
+ subtitle="Sign in to continue"
257
+ emailLabel="Your Email Address"
258
+ passwordLabel="Your Password"
259
+ submitButtonText="Login Now"
260
+ signUpText="New to our platform?"
261
+ signUpLinkText="Create an account"
262
+ />
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Advanced Usage
322
268
 
323
269
  ### Building Custom Auth Forms
324
270
 
325
- Use primitive components for complete customization:
271
+ Use atomic components for complete customization:
326
272
 
327
273
  ```tsx
328
274
  import {
@@ -334,7 +280,6 @@ import {
334
280
  AuthDivider,
335
281
  AuthOAuthProviders,
336
282
  AuthLink,
337
- cn,
338
283
  } from '@insforge/nextjs';
339
284
 
340
285
  function CustomSignIn() {
@@ -342,7 +287,7 @@ function CustomSignIn() {
342
287
  <AuthContainer
343
288
  appearance={{
344
289
  containerClassName: "max-w-md",
345
- cardClassName: "bg-white"
290
+ cardClassName: "bg-white shadow-2xl"
346
291
  }}
347
292
  >
348
293
  <AuthHeader
@@ -387,9 +332,6 @@ function CustomSignIn() {
387
332
  providers={['google', 'github']}
388
333
  onClick={handleOAuth}
389
334
  loading={oauthLoading}
390
- appearance={{
391
- buttonClassName: "hover:bg-gray-50"
392
- }}
393
335
  />
394
336
 
395
337
  <AuthLink
@@ -402,7 +344,7 @@ function CustomSignIn() {
402
344
  }
403
345
  ```
404
346
 
405
- **Available Primitive Components:**
347
+ **Available Atomic Components:**
406
348
  - `AuthContainer` - Main form container
407
349
  - `AuthHeader` - Title and subtitle
408
350
  - `AuthFormField` - Standard input field
@@ -417,8 +359,6 @@ function CustomSignIn() {
417
359
  - `AuthLink` - Navigation link
418
360
  - `AuthBranding` - Insforge branding footer
419
361
 
420
- All components support `appearance` prop with specific `className` options for each element.
421
-
422
362
  ### Server-Side Usage
423
363
 
424
364
  Access auth data in Server Components:
@@ -465,6 +405,24 @@ import { Protect } from '@insforge/nextjs';
465
405
  </Protect>
466
406
  ```
467
407
 
408
+ ### InsforgeCallback Options
409
+
410
+ ```tsx
411
+ <InsforgeCallback
412
+ redirectTo="/dashboard"
413
+ onSuccess={() => console.log('Authentication successful!')}
414
+ onError={(error) => console.error('Authentication failed:', error)}
415
+ loadingComponent={
416
+ <div className="flex items-center justify-center min-h-screen">
417
+ <div className="text-center">
418
+ <h2 className="text-2xl font-semibold mb-4">Signing you in...</h2>
419
+ <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
420
+ </div>
421
+ </div>
422
+ }
423
+ />
424
+ ```
425
+
468
426
  ### Auth Change Callback
469
427
 
470
428
  Track authentication events:
@@ -474,10 +432,8 @@ Track authentication events:
474
432
  baseUrl={baseUrl}
475
433
  onAuthChange={(user) => {
476
434
  if (user) {
477
- // User signed in
478
435
  analytics.identify(user.id);
479
436
  } else {
480
- // User signed out
481
437
  analytics.reset();
482
438
  }
483
439
  }}
@@ -486,83 +442,14 @@ Track authentication events:
486
442
 
487
443
  ---
488
444
 
489
- ## API Reference
490
-
491
- ### InsforgeProvider Props
492
-
493
- ```tsx
494
- interface InsforgeProviderProps {
495
- baseUrl: string; // Insforge backend URL
496
- onAuthChange?: (user: InsforgeUser | null) => void; // Auth state change callback
497
- }
498
- ```
499
-
500
- ### InsforgeCallback Props
501
-
502
- ```tsx
503
- interface InsforgeCallbackProps {
504
- redirectTo?: string; // Custom redirect destination after auth
505
- onSuccess?: () => void; // Callback fired on successful authentication
506
- onError?: (error: string) => void; // Callback fired on authentication error
507
- loadingComponent?: ReactNode; // Custom loading UI during authentication
508
- }
509
- ```
510
-
511
- **Default behavior:**
512
- - Redirects to `sessionStorage['auth_destination']` or `sessionStorage['oauth_final_destination']` or `'/'`
513
- - Displays a built-in loading spinner during authentication
514
- - Handles errors by redirecting to `/?error=<error_message>`
515
-
516
- ### useAuth()
517
-
518
- ```tsx
519
- const {
520
- signIn, // (email: string, password: string) => Promise<void>
521
- signUp, // (email: string, password: string) => Promise<void>
522
- signOut, // () => Promise<void>
523
- isSignedIn, // boolean
524
- isLoaded, // boolean
525
- } = useAuth();
526
- ```
527
-
528
- ### useUser()
529
-
530
- ```tsx
531
- const {
532
- user, // InsforgeUser | null
533
- isLoaded, // boolean
534
- updateUser, // (data: Partial<InsforgeUser>) => Promise<void>
535
- } = useUser();
536
- ```
537
-
538
- **InsforgeUser Type:**
539
- ```tsx
540
- interface InsforgeUser {
541
- id: string;
542
- email: string;
543
- nickname?: string;
544
- avatarUrl?: string;
545
- role?: string;
546
- emailVerified?: boolean;
547
- }
548
- ```
549
-
550
- ### Middleware Helpers
551
-
552
- ```tsx
553
- import { getAuthUserId, getAuthToken } from '@insforge/nextjs/middleware';
554
-
555
- const userId = getAuthUserId(headers()); // string | null
556
- const token = getAuthToken(headers()); // string | null
557
- ```
558
-
559
- ### Utility Function
445
+ ## Local Development
560
446
 
561
- ```tsx
562
- import { cn } from '@insforge/nextjs';
447
+ During local development, backend typically runs on a different port:
563
448
 
564
- // Merge Tailwind classes (uses clsx + tailwind-merge)
565
- const className = cn("px-4 py-2", "bg-blue-500", conditionalClass);
449
+ ```bash
450
+ # .env.local
451
+ NEXT_PUBLIC_INSFORGE_BASE_URL=http://localhost:7130
452
+ INSFORGE_BASE_URL=http://localhost:7130
566
453
  ```
567
454
 
568
455
  ---
@@ -577,30 +464,16 @@ import type {
577
464
  InsforgeCallbackProps,
578
465
  SignInProps,
579
466
  SignUpProps,
467
+ SignInAppearance,
468
+ SignUpAppearance,
580
469
  UserButtonProps,
581
470
  ProtectProps,
582
- OAuthProviderConfig,
471
+ OAuthProvider,
583
472
  } from '@insforge/nextjs';
584
473
  ```
585
474
 
586
475
  ---
587
476
 
588
- ## Why @insforge/nextjs?
589
-
590
- **For Developers:**
591
- - ⚡️ 5-minute setup vs hours of custom auth code
592
- - 🔒 Production-ready security and session management
593
- - 🎨 Customizable components when needed
594
- - 🚀 Built-in SSR support for Next.js App Router
595
-
596
- **For AI Agents:**
597
- - 📝 Minimal code generation (5 files vs 20+ for custom auth)
598
- - 🎯 Consistent patterns across projects
599
- - 🤖 SDK-first approach reduces errors
600
- - 💰 Less tokens used per setup
601
-
602
- ---
603
-
604
477
  ## Support
605
478
 
606
479
  - **Documentation**: https://docs.insforge.dev
package/dist/api.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  "use strict";
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/index.ts","../src/api/route-handlers.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\r\nexport type { AuthRouteConfig } from './route-handlers';","import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieName = 'insforge_token',\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookie\n */\n function setAuthCookie(response: NextResponse, token: string) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n response.cookies.set({\n name: cookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookie\n */\n function clearAuthCookie(response: NextResponse) {\n response.cookies.set({\n name: cookieName,\n value: '',\n httpOnly: true,\n secure: config.secure ?? (process.env.NODE_ENV === 'production'),\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = await request.json();\n const { action, email, password } = body;\n\n if (!action) {\n return NextResponse.json(\n { error: 'Action is required' },\n { status: 400 }\n );\n }\n\n switch (action) {\n case 'sign-in': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 401 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Authentication failed' },\n { status: 401 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sign-up': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 400 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Sign up failed' },\n { status: 400 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n return NextResponse.json(\n { error: 'Token is required' },\n { status: 400 }\n );\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = await response.json();\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(nextResponse, token);\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json(\n { error: 'Invalid action' },\n { status: 400 }\n );\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookie(nextResponse);\n return nextResponse;\n }\n\n const session = await response.json();\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookie(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\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/index.ts","../src/api/route-handlers.ts"],"sourcesContent":["export { createAuthRouteHandlers } from './route-handlers';\r\nexport type { AuthRouteConfig } from './route-handlers';","import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieName = 'insforge_token',\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookie\n */\n function setAuthCookie(response: NextResponse, token: string) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n response.cookies.set({\n name: cookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookie\n */\n function clearAuthCookie(response: NextResponse) {\n response.cookies.set({\n name: cookieName,\n value: '',\n httpOnly: true,\n secure: config.secure ?? (process.env.NODE_ENV === 'production'),\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = await request.json();\n const { action, email, password } = body;\n\n if (!action) {\n return NextResponse.json(\n { error: 'Action is required' },\n { status: 400 }\n );\n }\n\n switch (action) {\n case 'sign-in': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 401 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Authentication failed' },\n { status: 401 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sign-up': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 400 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Sign up failed' },\n { status: 400 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n return NextResponse.json(\n { error: 'Token is required' },\n { status: 400 }\n );\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = await response.json();\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(nextResponse, token);\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json(\n { error: 'Invalid action' },\n { status: 400 }\n );\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookie(nextResponse);\n return nextResponse;\n }\n\n const session = await response.json();\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookie(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n return {\n POST,\n GET,\n DELETE,\n };\n}\n"],"mappings":"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","names":[]}
package/dist/api.mjs CHANGED
@@ -1,3 +1,5 @@
1
+ "use client";
2
+
1
3
  // src/api/route-handlers.ts
2
4
  import { NextResponse } from "next/server";
3
5
  import { createClient } from "@insforge/sdk";
package/dist/api.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieName = 'insforge_token',\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookie\n */\n function setAuthCookie(response: NextResponse, token: string) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n response.cookies.set({\n name: cookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookie\n */\n function clearAuthCookie(response: NextResponse) {\n response.cookies.set({\n name: cookieName,\n value: '',\n httpOnly: true,\n secure: config.secure ?? (process.env.NODE_ENV === 'production'),\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = await request.json();\n const { action, email, password } = body;\n\n if (!action) {\n return NextResponse.json(\n { error: 'Action is required' },\n { status: 400 }\n );\n }\n\n switch (action) {\n case 'sign-in': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 401 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Authentication failed' },\n { status: 401 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sign-up': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 400 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Sign up failed' },\n { status: 400 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n return NextResponse.json(\n { error: 'Token is required' },\n { status: 400 }\n );\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = await response.json();\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(nextResponse, token);\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json(\n { error: 'Invalid action' },\n { status: 400 }\n );\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookie(nextResponse);\n return nextResponse;\n }\n\n const session = await response.json();\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookie(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n return {\n POST,\n GET,\n DELETE,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/api/route-handlers.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { createClient } from '@insforge/sdk';\n\nexport interface AuthRouteConfig {\n /**\n * Base URL of your Insforge backend\n */\n baseUrl: string;\n\n /**\n * Cookie name for the auth token\n * @default 'insforge_token'\n */\n cookieName?: string;\n\n /**\n * Cookie max age in seconds (default: 7 days)\n * @default 604800\n */\n cookieMaxAge?: number;\n\n /**\n * Whether to use secure cookies (HTTPS only)\n * Auto-detected based on environment\n */\n secure?: boolean;\n}\n\n/**\n * Creates authentication route handlers for Next.js App Router\n * These handlers set HTTP-only cookies that can be read by middleware\n *\n * @example\n * ```ts\n * // app/api/auth/[...auth]/route.ts\n * import { createAuthRouteHandlers } from '@insforge/nextjs/api';\n *\n * const handlers = createAuthRouteHandlers({\n * baseUrl: process.env.NEXT_PUBLIC_INSFORGE_BASE_URL!,\n * });\n *\n * export const POST = handlers.POST;\n * export const GET = handlers.GET;\n * export const DELETE = handlers.DELETE;\n * ```\n */\nexport function createAuthRouteHandlers(config: AuthRouteConfig) {\n const {\n baseUrl,\n cookieName = 'insforge_token',\n cookieMaxAge = 7 * 24 * 60 * 60, // 7 days\n } = config;\n\n const insforge = createClient({ baseUrl });\n\n /**\n * Helper to set auth cookie\n */\n function setAuthCookie(response: NextResponse, token: string) {\n // NODE_ENV is automatically set by Next.js runtime ('development' | 'production' | 'test')\n // In production, cookies are sent over HTTPS only (secure flag)\n const isProduction = process.env.NODE_ENV === 'production';\n const secure = config.secure ?? isProduction;\n\n response.cookies.set({\n name: cookieName,\n value: token,\n httpOnly: true, // Cannot be accessed by JavaScript\n secure, // Only sent over HTTPS in production\n sameSite: 'lax',\n maxAge: cookieMaxAge,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * Helper to clear auth cookie\n */\n function clearAuthCookie(response: NextResponse) {\n response.cookies.set({\n name: cookieName,\n value: '',\n httpOnly: true,\n secure: config.secure ?? (process.env.NODE_ENV === 'production'),\n sameSite: 'lax',\n maxAge: 0,\n path: '/',\n });\n\n return response;\n }\n\n /**\n * POST handler for authentication actions\n * Supports: sign-in, sign-up\n */\n async function POST(request: NextRequest) {\n try {\n const body = await request.json();\n const { action, email, password } = body;\n\n if (!action) {\n return NextResponse.json(\n { error: 'Action is required' },\n { status: 400 }\n );\n }\n\n switch (action) {\n case 'sign-in': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signInWithPassword({\n email,\n password,\n });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 401 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Authentication failed' },\n { status: 401 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sign-up': {\n if (!email || !password) {\n return NextResponse.json(\n { error: 'Email and password are required' },\n { status: 400 }\n );\n }\n\n const result = await insforge.auth.signUp({ email, password });\n\n if (result.error) {\n return NextResponse.json(\n { error: result.error.message },\n { status: 400 }\n );\n }\n\n if (!result.data || !result.data.user) {\n return NextResponse.json(\n { error: 'Sign up failed' },\n { status: 400 }\n );\n }\n\n const response = NextResponse.json({\n user: result.data.user,\n session: {\n userId: result.data.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(response, result.data.accessToken || '');\n\n return response;\n }\n\n case 'sync-token': {\n // Syncs a token from localStorage to HTTP-only cookie\n const { token } = body;\n\n if (!token) {\n return NextResponse.json(\n { error: 'Token is required' },\n { status: 400 }\n );\n }\n\n // Verify the token is valid by checking with backend\n try {\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('[Auth API] Token validation failed:', errorText);\n return NextResponse.json(\n { error: 'Invalid token', details: errorText },\n { status: 401 }\n );\n }\n\n const session = await response.json();\n\n const nextResponse = NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n\n setAuthCookie(nextResponse, token);\n\n return nextResponse;\n } catch (error) {\n console.error('[Auth API] Token validation error:', error);\n return NextResponse.json(\n { error: 'Token validation failed', details: String(error) },\n { status: 401 }\n );\n }\n }\n\n default:\n return NextResponse.json(\n { error: 'Invalid action' },\n { status: 400 }\n );\n }\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n /**\n * GET handler to check current session\n */\n async function GET(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (!token) {\n return NextResponse.json({ user: null, session: null });\n }\n\n // Verify token with backend\n const response = await fetch(`${baseUrl}/api/auth/sessions/current`, {\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const nextResponse = NextResponse.json({ user: null, session: null });\n clearAuthCookie(nextResponse);\n return nextResponse;\n }\n\n const session = await response.json();\n\n return NextResponse.json({\n user: session.user,\n session: {\n userId: session.user.id,\n token,\n expiresAt: '',\n createdAt: new Date().toISOString(),\n },\n });\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json({ user: null, session: null });\n }\n }\n\n /**\n * DELETE handler for sign out\n */\n async function DELETE(request: NextRequest) {\n try {\n const token = request.cookies.get(cookieName)?.value;\n\n if (token) {\n // Call backend sign out\n try {\n await fetch(`${baseUrl}/auth/sessions/current`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n });\n } catch (error) {\n // Ignore backend errors during sign out\n console.error('[Auth API] Sign out error:', error);\n }\n }\n\n const response = NextResponse.json({ success: true });\n clearAuthCookie(response);\n\n return response;\n } catch (error) {\n console.error('[Auth API Error]:', error);\n return NextResponse.json(\n { error: 'Internal server error' },\n { status: 500 }\n );\n }\n }\n\n return {\n POST,\n GET,\n DELETE,\n };\n}\n"],"mappings":";;;AAAA,SAAsB,oBAAoB;AAC1C,SAAS,oBAAoB;AA6CtB,SAAS,wBAAwB,QAAyB;AAC/D,QAAM;AAAA,IACJ;AAAA,IACA,aAAa;AAAA,IACb,eAAe,IAAI,KAAK,KAAK;AAAA;AAAA,EAC/B,IAAI;AAEJ,QAAM,WAAW,aAAa,EAAE,QAAQ,CAAC;AAKzC,WAAS,cAAc,UAAwB,OAAe;AAG5D,UAAM,eAAe,QAAQ,IAAI,aAAa;AAC9C,UAAM,SAAS,OAAO,UAAU;AAEhC,aAAS,QAAQ,IAAI;AAAA,MACnB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA;AAAA,MACV;AAAA;AAAA,MACA,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AAED,WAAO;AAAA,EACT;AAKA,WAAS,gBAAgB,UAAwB;AAC/C,aAAS,QAAQ,IAAI;AAAA,MACnB,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,QAAQ,OAAO,UAAW,QAAQ,IAAI,aAAa;AAAA,MACnD,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,IACR,CAAC;AAED,WAAO;AAAA,EACT;AAMA,iBAAe,KAAK,SAAsB;AACxC,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,KAAK;AAChC,YAAM,EAAE,QAAQ,OAAO,SAAS,IAAI;AAEpC,UAAI,CAAC,QAAQ;AACX,eAAO,aAAa;AAAA,UAClB,EAAE,OAAO,qBAAqB;AAAA,UAC9B,EAAE,QAAQ,IAAI;AAAA,QAChB;AAAA,MACF;AAEA,cAAQ,QAAQ;AAAA,QACd,KAAK,WAAW;AACd,cAAI,CAAC,SAAS,CAAC,UAAU;AACvB,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,kCAAkC;AAAA,cAC3C,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEA,gBAAM,SAAS,MAAM,SAAS,KAAK,mBAAmB;AAAA,YACpD;AAAA,YACA;AAAA,UACF,CAAC;AAED,cAAI,OAAO,OAAO;AAChB,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,OAAO,MAAM,QAAQ;AAAA,cAC9B,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEF,cAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,KAAK,MAAM;AACrC,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,wBAAwB;AAAA,cACjC,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEA,gBAAM,WAAW,aAAa,KAAK;AAAA,YACjC,MAAM,OAAO,KAAK;AAAA,YAClB,SAAS;AAAA,cACP,QAAQ,OAAO,KAAK,KAAK;AAAA,cACzB,WAAW;AAAA,cACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC;AAAA,UACF,CAAC;AAEC,wBAAc,UAAU,OAAO,KAAK,eAAe,EAAE;AAErD,iBAAO;AAAA,QACT;AAAA,QAEA,KAAK,WAAW;AACd,cAAI,CAAC,SAAS,CAAC,UAAU;AACvB,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,kCAAkC;AAAA,cAC3C,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEA,gBAAM,SAAS,MAAM,SAAS,KAAK,OAAO,EAAE,OAAO,SAAS,CAAC;AAE7D,cAAI,OAAO,OAAO;AAChB,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,OAAO,MAAM,QAAQ;AAAA,cAC9B,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEF,cAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,KAAK,MAAM;AACrC,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,iBAAiB;AAAA,cAC1B,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAEA,gBAAM,WAAW,aAAa,KAAK;AAAA,YACjC,MAAM,OAAO,KAAK;AAAA,YAClB,SAAS;AAAA,cACP,QAAQ,OAAO,KAAK,KAAK;AAAA,cACzB,WAAW;AAAA,cACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,YACpC;AAAA,UACF,CAAC;AAEC,wBAAc,UAAU,OAAO,KAAK,eAAe,EAAE;AAErD,iBAAO;AAAA,QACT;AAAA,QAEA,KAAK,cAAc;AAEjB,gBAAM,EAAE,MAAM,IAAI;AAElB,cAAI,CAAC,OAAO;AACV,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,oBAAoB;AAAA,cAC7B,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAGA,cAAI;AACF,kBAAM,WAAW,MAAM,MAAM,GAAG,OAAO,8BAA8B;AAAA,cACnE,SAAS;AAAA,gBACP,eAAe,UAAU,KAAK;AAAA,gBAC9B,gBAAgB;AAAA,cAClB;AAAA,YACF,CAAC;AAED,gBAAI,CAAC,SAAS,IAAI;AAChB,oBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,sBAAQ,MAAM,uCAAuC,SAAS;AAC9D,qBAAO,aAAa;AAAA,gBAClB,EAAE,OAAO,iBAAiB,SAAS,UAAU;AAAA,gBAC7C,EAAE,QAAQ,IAAI;AAAA,cAChB;AAAA,YACF;AAEA,kBAAM,UAAU,MAAM,SAAS,KAAK;AAEpC,kBAAM,eAAe,aAAa,KAAK;AAAA,cACrC,MAAM,QAAQ;AAAA,cACd,SAAS;AAAA,gBACP,QAAQ,QAAQ,KAAK;AAAA,gBACrB,WAAW;AAAA,gBACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,cACpC;AAAA,YACF,CAAC;AAED,0BAAc,cAAc,KAAK;AAEjC,mBAAO;AAAA,UACT,SAAS,OAAO;AACd,oBAAQ,MAAM,sCAAsC,KAAK;AACzD,mBAAO,aAAa;AAAA,cAClB,EAAE,OAAO,2BAA2B,SAAS,OAAO,KAAK,EAAE;AAAA,cAC3D,EAAE,QAAQ,IAAI;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AAAA,QAEA;AACE,iBAAO,aAAa;AAAA,YAClB,EAAE,OAAO,iBAAiB;AAAA,YAC1B,EAAE,QAAQ,IAAI;AAAA,UAChB;AAAA,MACJ;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,KAAK;AACxC,aAAO,aAAa;AAAA,QAClB,EAAE,OAAO,wBAAwB;AAAA,QACjC,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAKA,iBAAe,IAAI,SAAsB;AACvC,QAAI;AACF,YAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,UAAI,CAAC,OAAO;AACV,eAAO,aAAa,KAAK,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC;AAAA,MACxD;AAGA,YAAM,WAAW,MAAM,MAAM,GAAG,OAAO,8BAA8B;AAAA,QACnE,SAAS;AAAA,UACP,eAAe,UAAU,KAAK;AAAA,UAC9B,gBAAgB;AAAA,QAClB;AAAA,MACF,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,eAAe,aAAa,KAAK,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC;AACpE,wBAAgB,YAAY;AAC5B,eAAO;AAAA,MACT;AAEA,YAAM,UAAU,MAAM,SAAS,KAAK;AAEpC,aAAO,aAAa,KAAK;AAAA,QACvB,MAAM,QAAQ;AAAA,QACd,SAAS;AAAA,UACP,QAAQ,QAAQ,KAAK;AAAA,UACrB;AAAA,UACA,WAAW;AAAA,UACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,KAAK;AACxC,aAAO,aAAa,KAAK,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC;AAAA,IACxD;AAAA,EACF;AAKA,iBAAe,OAAO,SAAsB;AAC1C,QAAI;AACF,YAAM,QAAQ,QAAQ,QAAQ,IAAI,UAAU,GAAG;AAE/C,UAAI,OAAO;AAET,YAAI;AACF,gBAAM,MAAM,GAAG,OAAO,0BAA0B;AAAA,YAC9C,QAAQ;AAAA,YACR,SAAS;AAAA,cACP,eAAe,UAAU,KAAK;AAAA,cAC9B,gBAAgB;AAAA,YAClB;AAAA,UACF,CAAC;AAAA,QACH,SAAS,OAAO;AAEd,kBAAQ,MAAM,8BAA8B,KAAK;AAAA,QACnD;AAAA,MACF;AAEA,YAAM,WAAW,aAAa,KAAK,EAAE,SAAS,KAAK,CAAC;AACpD,sBAAgB,QAAQ;AAExB,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,KAAK;AACxC,aAAO,aAAa;AAAA,QAClB,EAAE,OAAO,wBAAwB;AAAA,QACjC,EAAE,QAAQ,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}