@logickernel/bridge 0.8.1 → 0.8.3
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 +188 -262
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,83 +1,171 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @logickernel/bridge
|
|
2
2
|
|
|
3
|
-
Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens.
|
|
3
|
+
Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens with built-in Next.js components.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @logickernel/bridge
|
|
9
|
-
# or
|
|
10
|
-
pnpm add @logickernel/bridge
|
|
11
|
-
# or
|
|
12
|
-
yarn add @logickernel/bridge
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
- **Framework-agnostic core** - JWT decoding and validation works anywhere
|
|
18
|
-
- **Next.js adapter** - First-class support for Next.js App Router
|
|
19
|
-
- **Role-based access control** - Check user roles against organization permissions
|
|
20
|
-
- **TypeScript-first** - Full type safety with detailed type exports
|
|
21
|
-
- **Dual ESM/CJS** - Works in any JavaScript environment
|
|
11
|
+
## Quick Start (Next.js)
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
### 1. Environment Variables
|
|
24
14
|
|
|
25
|
-
|
|
15
|
+
Add these to the `.env` file of your application:
|
|
26
16
|
|
|
27
17
|
```bash
|
|
28
18
|
AUTH_SECRET=your-nextauth-secret # Required: Same secret used by your kernel/auth server
|
|
29
|
-
AUTH_URL=http://localhost:3000 # Required:
|
|
30
|
-
BASE_URL=http://localhost:7001 # Optional:
|
|
31
|
-
AUTH_COOKIE=authjs.session-token # Optional: Cookie name for session token (defaults to authjs.session-token)
|
|
19
|
+
AUTH_URL=http://localhost:3000 # Required: Base URL of your kernel/auth server
|
|
20
|
+
BASE_URL=http://localhost:7001 # Optional: Your facade URL for user-facing redirects
|
|
32
21
|
```
|
|
33
22
|
|
|
34
|
-
###
|
|
23
|
+
### 2. Configure Next.js
|
|
24
|
+
|
|
25
|
+
In your `next.config.ts`, add the bridge package to `transpilePackages`:
|
|
35
26
|
|
|
36
27
|
```typescript
|
|
37
|
-
import {
|
|
38
|
-
decodeSessionToken,
|
|
39
|
-
extractSessionCookie,
|
|
40
|
-
fetchUserRoles,
|
|
41
|
-
hasAnyRole,
|
|
42
|
-
} from "@logickernel/bridge"
|
|
28
|
+
import type { NextConfig } from "next"
|
|
43
29
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
console.log(result.session.user.email)
|
|
48
|
-
console.log(result.session.user.id)
|
|
49
|
-
} else {
|
|
50
|
-
console.error(result.error) // "missing_token" | "missing_secret" | "decode_error" | "expired"
|
|
30
|
+
const nextConfig: NextConfig = {
|
|
31
|
+
transpilePackages: ["@logickernel/bridge"],
|
|
32
|
+
// ... other config
|
|
51
33
|
}
|
|
52
34
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
35
|
+
export default nextConfig
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Why `transpilePackages`?** This tells Next.js to transpile the bridge library's TypeScript/ES modules during the build process. This is necessary because the library uses modern JavaScript features and needs to be processed by Next.js's bundler (Turbopack or webpack) to work correctly with your application.
|
|
39
|
+
|
|
40
|
+
### 3. Use the Layout Component
|
|
41
|
+
|
|
42
|
+
The library provides a ready-to-use layout component with sidebar navigation. You need a thin wrapper component in your app to establish the client/server boundary.
|
|
43
|
+
|
|
44
|
+
**Step 1: Create a wrapper component**
|
|
45
|
+
|
|
46
|
+
Create `src/components/app-layout-wrapper.tsx`:
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
```typescript
|
|
49
|
+
"use client"
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Client boundary wrapper for AppLayout.
|
|
53
|
+
*
|
|
54
|
+
* This wrapper is required because "use client" directives are not preserved
|
|
55
|
+
* in bundled library code. Next.js needs this directive in your source code
|
|
56
|
+
* to properly handle the client/server boundary.
|
|
57
|
+
*/
|
|
58
|
+
import { AppLayout } from "@logickernel/bridge/next-components"
|
|
59
|
+
|
|
60
|
+
export function AppLayoutWrapper({
|
|
61
|
+
children,
|
|
62
|
+
organizationId,
|
|
63
|
+
apiBaseUrl,
|
|
64
|
+
}: {
|
|
65
|
+
children: React.ReactNode
|
|
66
|
+
organizationId?: string
|
|
67
|
+
apiBaseUrl?: string
|
|
68
|
+
}) {
|
|
69
|
+
return (
|
|
70
|
+
<AppLayout
|
|
71
|
+
organizationId={organizationId}
|
|
72
|
+
apiBaseUrl={apiBaseUrl}
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</AppLayout>
|
|
76
|
+
)
|
|
62
77
|
}
|
|
63
78
|
```
|
|
64
79
|
|
|
65
|
-
|
|
80
|
+
**Step 2: Use in your layout**
|
|
81
|
+
|
|
82
|
+
In your `app/app/layout.tsx` (or wherever your app layout is):
|
|
66
83
|
|
|
67
84
|
```typescript
|
|
68
|
-
import {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
85
|
+
import { redirect } from "next/navigation"
|
|
86
|
+
import { auth } from "@/lib/next-auth" // or your auth setup
|
|
87
|
+
import { AppLayoutWrapper } from "@/components/app-layout-wrapper"
|
|
88
|
+
|
|
89
|
+
export default async function Layout({
|
|
90
|
+
children,
|
|
91
|
+
}: {
|
|
92
|
+
children: React.ReactNode
|
|
93
|
+
}) {
|
|
94
|
+
const session = await auth()
|
|
95
|
+
|
|
96
|
+
if (!session?.user) {
|
|
97
|
+
redirect("/auth/signin?callbackUrl=/app")
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<AppLayoutWrapper>
|
|
102
|
+
{children}
|
|
103
|
+
</AppLayoutWrapper>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The `user` prop is **not needed** - the layout automatically fetches user information from the navigation API endpoint.
|
|
109
|
+
|
|
110
|
+
### 4. Navigation API Endpoint
|
|
111
|
+
|
|
112
|
+
The layout component automatically loads navigation items from your API. The **Kernel Core application** provides this endpoint at `/api/navigation/[organization_id]`.
|
|
113
|
+
|
|
114
|
+
**Required Endpoint:** `GET /api/navigation/[organization_id]`
|
|
115
|
+
|
|
116
|
+
**Response Payload:**
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
{
|
|
120
|
+
items: NavigationItem[]
|
|
121
|
+
organizationId: string
|
|
122
|
+
organizations: NavigationOrganization[]
|
|
123
|
+
user: {
|
|
124
|
+
id: string
|
|
125
|
+
name: string | null
|
|
126
|
+
email: string
|
|
127
|
+
image: string | null
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
interface NavigationItem {
|
|
132
|
+
title: string
|
|
133
|
+
url?: string // If missing, item is treated as a section label
|
|
134
|
+
icon?: string // Lucide icon name (e.g., "LayoutDashboard", "Users")
|
|
135
|
+
isActive?: boolean // Whether the item should be highlighted
|
|
136
|
+
items?: { // Sub-items for collapsible navigation
|
|
137
|
+
title: string
|
|
138
|
+
url: string
|
|
139
|
+
}[]
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
interface NavigationOrganization {
|
|
143
|
+
id: string
|
|
144
|
+
name: string
|
|
145
|
+
logo?: string // Lucide icon name for the organization logo
|
|
146
|
+
plan?: string // Optional plan/badge text
|
|
147
|
+
}
|
|
75
148
|
```
|
|
76
149
|
|
|
77
|
-
|
|
150
|
+
**Note:** The endpoint should be protected and only return data the authenticated user has access to. The `{organizationId}` placeholder in item URLs will be automatically replaced with the current organization ID.
|
|
151
|
+
|
|
152
|
+
## Features
|
|
153
|
+
|
|
154
|
+
The `AppLayout` component provides:
|
|
155
|
+
|
|
156
|
+
- ✅ **Built-in sidebar navigation** with collapsible sections
|
|
157
|
+
- ✅ **Organization switcher** - Switch between organizations the user belongs to
|
|
158
|
+
- ✅ **User menu** with profile information and sign-out
|
|
159
|
+
- ✅ **Responsive design** - Works on mobile and desktop
|
|
160
|
+
- ✅ **Automatic navigation loading** - Fetches from your API endpoint
|
|
161
|
+
- ✅ **Consistent UI** - Same look and feel across all microfrontends using the library
|
|
162
|
+
- ✅ **No extra components required** - All UI components are included in the library
|
|
163
|
+
|
|
164
|
+
## Next.js Utilities
|
|
165
|
+
|
|
166
|
+
### Server Components / Pages
|
|
78
167
|
|
|
79
168
|
```typescript
|
|
80
|
-
// app/dashboard/page.tsx
|
|
81
169
|
import { getSession } from "@logickernel/bridge/next"
|
|
82
170
|
import { redirect } from "next/navigation"
|
|
83
171
|
|
|
@@ -92,42 +180,39 @@ export default async function DashboardPage() {
|
|
|
92
180
|
}
|
|
93
181
|
```
|
|
94
182
|
|
|
95
|
-
|
|
183
|
+
### Role-Based Page Protection
|
|
96
184
|
|
|
97
185
|
```typescript
|
|
98
|
-
// app/[org_id]/admin/page.tsx
|
|
99
186
|
import { checkPageAuth } from "@logickernel/bridge/next"
|
|
100
187
|
import { redirect, notFound } from "next/navigation"
|
|
101
188
|
|
|
102
189
|
export default async function AdminPage({
|
|
103
190
|
params,
|
|
104
191
|
}: {
|
|
105
|
-
params: Promise<{
|
|
192
|
+
params: Promise<{ organization_id: string }>
|
|
106
193
|
}) {
|
|
107
|
-
const {
|
|
194
|
+
const { organization_id } = await params
|
|
108
195
|
|
|
109
196
|
const auth = await checkPageAuth({
|
|
110
197
|
requiredRoles: ["organization.owner", "organization.editor"],
|
|
111
|
-
organizationId:
|
|
198
|
+
organizationId: organization_id,
|
|
112
199
|
})
|
|
113
200
|
|
|
114
201
|
if (!auth.authenticated) {
|
|
115
202
|
redirect(auth.redirectUrl)
|
|
116
203
|
}
|
|
117
204
|
|
|
118
|
-
|
|
119
|
-
if (!auth.roles.some(r => ["organization.owner", "organization.editor"].includes(r))) {
|
|
205
|
+
if (!auth.hasRequiredRole) {
|
|
120
206
|
notFound()
|
|
121
207
|
}
|
|
122
208
|
|
|
123
|
-
return <div>Admin Panel for {session.user.email}</div>
|
|
209
|
+
return <div>Admin Panel for {auth.session.user.email}</div>
|
|
124
210
|
}
|
|
125
211
|
```
|
|
126
212
|
|
|
127
|
-
|
|
213
|
+
### API Routes
|
|
128
214
|
|
|
129
215
|
```typescript
|
|
130
|
-
// app/api/data/route.ts
|
|
131
216
|
import { withAuth } from "@logickernel/bridge/next"
|
|
132
217
|
import { NextResponse } from "next/server"
|
|
133
218
|
|
|
@@ -152,10 +237,10 @@ export const DELETE = withAuth(
|
|
|
152
237
|
)
|
|
153
238
|
```
|
|
154
239
|
|
|
155
|
-
|
|
240
|
+
### Middleware / Proxy
|
|
156
241
|
|
|
157
242
|
```typescript
|
|
158
|
-
//
|
|
243
|
+
// middleware.ts or proxy.ts
|
|
159
244
|
import { createProxyHandler, type ProxyOptions } from "@logickernel/bridge/next"
|
|
160
245
|
|
|
161
246
|
const config: ProxyOptions = {
|
|
@@ -166,7 +251,7 @@ const config: ProxyOptions = {
|
|
|
166
251
|
},
|
|
167
252
|
dynamicRoutes: [
|
|
168
253
|
{
|
|
169
|
-
pattern: "/[organization_id]/admin",
|
|
254
|
+
pattern: "/app/[organization_id]/admin",
|
|
170
255
|
requiredRoles: ["organization.owner"],
|
|
171
256
|
},
|
|
172
257
|
],
|
|
@@ -174,174 +259,27 @@ const config: ProxyOptions = {
|
|
|
174
259
|
|
|
175
260
|
export const proxy = createProxyHandler(config)
|
|
176
261
|
|
|
177
|
-
// Static config for Next.js
|
|
178
|
-
export const
|
|
262
|
+
// Static config for Next.js middleware
|
|
263
|
+
export const config = {
|
|
179
264
|
matcher: ["/((?!_next/static|_next/image|favicon.ico|public).*)"],
|
|
180
265
|
}
|
|
181
266
|
```
|
|
182
267
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
The bridge library provides ready-to-use layout components with built-in navigation connected to the Core of the Kernel.
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
// app/app/layout.tsx (or your app layout)
|
|
189
|
-
"use client"
|
|
190
|
-
|
|
191
|
-
import { AppLayout, type User } from "@logickernel/bridge/next/components"
|
|
192
|
-
import { useSession } from "next-auth/react"
|
|
193
|
-
|
|
194
|
-
export default function Layout({ children }: { children: React.ReactNode }) {
|
|
195
|
-
const { data: session } = useSession()
|
|
196
|
-
|
|
197
|
-
if (!session?.user) {
|
|
198
|
-
return <>{children}</>
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
const user: User = {
|
|
202
|
-
name: session.user.name || null,
|
|
203
|
-
email: session.user.email || "",
|
|
204
|
-
image: session.user.image || null,
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return (
|
|
208
|
-
<AppLayout
|
|
209
|
-
user={user}
|
|
210
|
-
organizationId={organizationId} // Optional: Current organization ID
|
|
211
|
-
apiBaseUrl={apiBaseUrl} // Optional: API base URL for navigation
|
|
212
|
-
>
|
|
213
|
-
{children}
|
|
214
|
-
</AppLayout>
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
**For Server Components:**
|
|
268
|
+
## Import Paths
|
|
220
269
|
|
|
221
|
-
|
|
222
|
-
// app/app/layout.tsx
|
|
223
|
-
import { AppLayout, type User } from "@logickernel/bridge/next/components"
|
|
224
|
-
import { redirect } from "next/navigation"
|
|
225
|
-
import { auth } from "@/lib/next-auth" // or your NextAuth setup
|
|
270
|
+
The library uses top-level exports (no subpath exports) for better bundler compatibility:
|
|
226
271
|
|
|
227
|
-
export default async function Layout({
|
|
228
|
-
children,
|
|
229
|
-
params,
|
|
230
|
-
}: {
|
|
231
|
-
children: React.ReactNode
|
|
232
|
-
params: Promise<{ organization_id?: string }>
|
|
233
|
-
}) {
|
|
234
|
-
const session = await auth()
|
|
235
|
-
|
|
236
|
-
if (!session?.user) {
|
|
237
|
-
redirect("/auth/signin")
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const { organization_id } = await params
|
|
241
|
-
|
|
242
|
-
const user: User = {
|
|
243
|
-
name: session.user.name || null,
|
|
244
|
-
email: session.user.email || "",
|
|
245
|
-
image: session.user.image || null,
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
return (
|
|
249
|
-
<AppLayout
|
|
250
|
-
user={user}
|
|
251
|
-
organizationId={organization_id}
|
|
252
|
-
apiBaseUrl={process.env.AUTH_URL}
|
|
253
|
-
>
|
|
254
|
-
{children}
|
|
255
|
-
</AppLayout>
|
|
256
|
-
)
|
|
257
|
-
}
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
**Note:** You can also use `getSession()` from `@logickernel/bridge/next` instead of NextAuth's `auth()` function. Both will work, but NextAuth's `auth()` is recommended if you're using NextAuth v5.
|
|
261
|
-
|
|
262
|
-
**Features:**
|
|
263
|
-
- ✅ Built-in sidebar navigation with organization switcher
|
|
264
|
-
- ✅ User menu with sign-out
|
|
265
|
-
- ✅ Responsive design (mobile/desktop)
|
|
266
|
-
- ✅ Automatic navigation loading from your API
|
|
267
|
-
- ✅ No component passing required - UI components are included in the library
|
|
268
|
-
- ✅ Consistent UI across all microfrontends using the bridge
|
|
269
|
-
|
|
270
|
-
The `AppLayout` component automatically:
|
|
271
|
-
- Loads navigation items from `/api/navigation/[organization_id]` endpoint
|
|
272
|
-
- Displays organizations the user belongs to
|
|
273
|
-
- Handles organization switching
|
|
274
|
-
- Provides user profile menu with sign-out
|
|
275
|
-
|
|
276
|
-
**Required API Endpoint:**
|
|
277
|
-
|
|
278
|
-
The navigation requires an endpoint at `/api/navigation/[organization_id]` that returns:
|
|
279
|
-
```typescript
|
|
280
|
-
{
|
|
281
|
-
items: NavigationItem[],
|
|
282
|
-
organizations: NavigationOrganization[]
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
**Type Definitions:**
|
|
287
272
|
```typescript
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
url?: string // If missing, item is treated as a section label
|
|
291
|
-
icon?: string // Icon name (mapped using getIconComponent)
|
|
292
|
-
isActive?: boolean // Whether the item should be highlighted
|
|
293
|
-
items?: { // Sub-items for collapsible navigation
|
|
294
|
-
title: string
|
|
295
|
-
url: string
|
|
296
|
-
}[]
|
|
297
|
-
}
|
|
273
|
+
// Core utilities (framework-agnostic)
|
|
274
|
+
import { decodeSessionToken, fetchUserRoles } from "@logickernel/bridge"
|
|
298
275
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
name: string
|
|
302
|
-
logo?: string // Icon name for the organization logo
|
|
303
|
-
plan?: string // Optional plan/badge text
|
|
304
|
-
}
|
|
305
|
-
```
|
|
276
|
+
// Next.js utilities (server components, API routes, middleware)
|
|
277
|
+
import { getSession, withAuth, checkPageAuth } from "@logickernel/bridge/next"
|
|
306
278
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
{
|
|
310
|
-
"items": [
|
|
311
|
-
{
|
|
312
|
-
"title": "Dashboard",
|
|
313
|
-
"url": "/app/{organizationId}/home",
|
|
314
|
-
"icon": "LayoutDashboard"
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
"title": "Team",
|
|
318
|
-
"icon": "Users" // Section label (no URL)
|
|
319
|
-
},
|
|
320
|
-
{
|
|
321
|
-
"title": "Members",
|
|
322
|
-
"url": "/app/{organizationId}/members",
|
|
323
|
-
"icon": "User",
|
|
324
|
-
"items": [
|
|
325
|
-
{
|
|
326
|
-
"title": "All Members",
|
|
327
|
-
"url": "/app/{organizationId}/members"
|
|
328
|
-
}
|
|
329
|
-
]
|
|
330
|
-
}
|
|
331
|
-
],
|
|
332
|
-
"organizations": [
|
|
333
|
-
{
|
|
334
|
-
"id": "org-123",
|
|
335
|
-
"name": "Acme Corp",
|
|
336
|
-
"logo": "Building",
|
|
337
|
-
"plan": "Pro"
|
|
338
|
-
}
|
|
339
|
-
]
|
|
340
|
-
}
|
|
279
|
+
// Layout components (client components)
|
|
280
|
+
import { AppLayout, type User } from "@logickernel/bridge/next-components"
|
|
341
281
|
```
|
|
342
282
|
|
|
343
|
-
**Note:** The `{organizationId}` placeholder in URLs will be automatically replaced with the current organization ID. The endpoint should be protected and only return data the current user has access to.
|
|
344
|
-
|
|
345
283
|
## API Reference
|
|
346
284
|
|
|
347
285
|
### Core Exports (`@logickernel/bridge`)
|
|
@@ -350,13 +288,10 @@ interface NavigationOrganization {
|
|
|
350
288
|
|--------|-------------|
|
|
351
289
|
| `decodeSessionToken(token, secret, isSecure)` | Decode and validate a JWT session token |
|
|
352
290
|
| `extractSessionCookie(cookies)` | Extract session cookie from a cookies object |
|
|
353
|
-
| `fetchUserRoles(options)` | Fetch user roles from the kernel API
|
|
291
|
+
| `fetchUserRoles(options)` | Fetch user roles from the kernel API |
|
|
354
292
|
| `hasAnyRole(userRoles, requiredRoles)` | Check if user has at least one required role |
|
|
355
293
|
| `hasAllRoles(userRoles, requiredRoles)` | Check if user has all required roles |
|
|
356
294
|
| `hasRole(userRoles, role)` | Check if user has a specific role |
|
|
357
|
-
| `matchRoute(pathname, config)` | Match a pathname against route configuration |
|
|
358
|
-
| `buildSignInUrl(callbackUrl?)` | Build a sign-in redirect URL (uses AUTH_URL internally) |
|
|
359
|
-
| `buildSignOutUrl(callbackUrl?)` | Build a sign-out redirect URL (uses AUTH_URL internally) |
|
|
360
295
|
|
|
361
296
|
### Next.js Exports (`@logickernel/bridge/next`)
|
|
362
297
|
|
|
@@ -364,63 +299,57 @@ interface NavigationOrganization {
|
|
|
364
299
|
|--------|-------------|
|
|
365
300
|
| `getSession()` | Get the current session from cookies |
|
|
366
301
|
| `getSessionToken()` | Get the raw session token value |
|
|
367
|
-
| `getUserRoles(orgId)` | Get user roles in an organization
|
|
302
|
+
| `getUserRoles(orgId)` | Get user roles in an organization |
|
|
368
303
|
| `withAuth(handler, options?)` | Wrap an API route with authentication |
|
|
369
|
-
| `getSessionFromRequest(request)` | Get session from a NextRequest |
|
|
370
304
|
| `checkPageAuth(options?)` | Check authentication for a page |
|
|
371
305
|
| `requireAuth()` | Require authentication (throws if not authenticated) |
|
|
372
|
-
| `hasRequiredRole(orgId, roles)` | Check if user has required roles
|
|
306
|
+
| `hasRequiredRole(orgId, roles)` | Check if user has required roles |
|
|
373
307
|
| `createProxyHandler(options)` | Create a middleware/proxy handler |
|
|
374
308
|
|
|
375
|
-
### Layout Components (`@logickernel/bridge/next
|
|
309
|
+
### Layout Components (`@logickernel/bridge/next-components`)
|
|
376
310
|
|
|
377
311
|
| Export | Description |
|
|
378
312
|
|--------|-------------|
|
|
379
|
-
| `AppLayout` | Main layout component with sidebar navigation |
|
|
380
|
-
| `AppSidebar` | Sidebar component (used internally by AppLayout) |
|
|
381
|
-
| `NavMain` | Main navigation component (used internally) |
|
|
382
|
-
| `NavUser` | User menu component (used internally) |
|
|
383
|
-
| `TeamSwitcher` | Organization switcher component (used internally) |
|
|
313
|
+
| `AppLayout` | Main layout component with sidebar navigation (wrap in a local component with `"use client"` for server components) |
|
|
384
314
|
| `useNavigation` | Hook to fetch navigation items from API |
|
|
385
315
|
| `getIconComponent` | Utility to get icon component from icon name |
|
|
386
316
|
|
|
387
317
|
**AppLayout Props:**
|
|
318
|
+
|
|
388
319
|
```typescript
|
|
389
320
|
interface AppLayoutProps {
|
|
390
|
-
user
|
|
391
|
-
organizationId?: string
|
|
392
|
-
apiBaseUrl?: string
|
|
393
|
-
children: React.ReactNode
|
|
321
|
+
user?: User // Optional: User information (auto-fetched if not provided)
|
|
322
|
+
organizationId?: string // Optional: Current organization ID
|
|
323
|
+
apiBaseUrl?: string // Optional: API base URL (defaults to "/api")
|
|
324
|
+
children: React.ReactNode // Page content
|
|
394
325
|
}
|
|
395
326
|
```
|
|
396
327
|
|
|
397
|
-
|
|
328
|
+
## TypeScript Types
|
|
398
329
|
|
|
399
330
|
```typescript
|
|
331
|
+
// Core types
|
|
400
332
|
import type {
|
|
401
333
|
Session,
|
|
402
334
|
SessionUser,
|
|
403
335
|
DecodeResult,
|
|
404
|
-
RouteConfig,
|
|
405
|
-
RouteMatch,
|
|
406
|
-
MicroFrontendConfig,
|
|
407
336
|
} from "@logickernel/bridge"
|
|
408
337
|
|
|
338
|
+
// Next.js types
|
|
409
339
|
import type {
|
|
410
340
|
ProxyOptions,
|
|
411
|
-
DynamicRoutePattern,
|
|
412
341
|
AuthContext,
|
|
413
342
|
AuthenticatedHandler,
|
|
414
|
-
WithAuthOptions,
|
|
415
343
|
PageAuthOptions,
|
|
416
344
|
PageAuthResult,
|
|
417
345
|
} from "@logickernel/bridge/next"
|
|
418
346
|
|
|
347
|
+
// Component types
|
|
419
348
|
import type {
|
|
420
349
|
User,
|
|
421
350
|
NavigationItem,
|
|
422
351
|
NavigationOrganization,
|
|
423
|
-
} from "@logickernel/bridge/next
|
|
352
|
+
} from "@logickernel/bridge/next-components"
|
|
424
353
|
```
|
|
425
354
|
|
|
426
355
|
## Architecture
|
|
@@ -428,26 +357,23 @@ import type {
|
|
|
428
357
|
```
|
|
429
358
|
bridge/
|
|
430
359
|
├── src/
|
|
431
|
-
│ ├── index.ts
|
|
432
|
-
│ ├──
|
|
433
|
-
│ ├──
|
|
434
|
-
│ ├── roles.ts # Role checking utilities
|
|
435
|
-
│ ├── routes.ts # Route matching utilities
|
|
360
|
+
│ ├── index.ts # Core exports (framework-agnostic)
|
|
361
|
+
│ ├── jwt.ts # JWT decoding utilities
|
|
362
|
+
│ ├── roles.ts # Role checking utilities
|
|
436
363
|
│ └── next/
|
|
437
|
-
│ ├── index.ts
|
|
438
|
-
│ ├──
|
|
439
|
-
│ ├──
|
|
440
|
-
│ ├──
|
|
441
|
-
│ ├──
|
|
442
|
-
│ ├── proxy.ts # Middleware/proxy utilities
|
|
364
|
+
│ ├── index.ts # Next.js adapter exports
|
|
365
|
+
│ ├── session.ts # Session utilities
|
|
366
|
+
│ ├── api.ts # API route utilities
|
|
367
|
+
│ ├── page.ts # Page utilities
|
|
368
|
+
│ ├── proxy.ts # Middleware/proxy utilities
|
|
443
369
|
│ └── components/
|
|
444
|
-
│ ├── app-layout.tsx
|
|
445
|
-
│ ├── app-sidebar.tsx
|
|
446
|
-
│ ├── nav-main.tsx
|
|
447
|
-
│ ├── nav-user.tsx
|
|
448
|
-
│ ├── team-switcher.tsx
|
|
449
|
-
│ ├── use-navigation.ts
|
|
450
|
-
│ └── ui/
|
|
370
|
+
│ ├── app-layout.tsx # Main layout component
|
|
371
|
+
│ ├── app-sidebar.tsx # Sidebar component
|
|
372
|
+
│ ├── nav-main.tsx # Navigation component
|
|
373
|
+
│ ├── nav-user.tsx # User menu component
|
|
374
|
+
│ ├── team-switcher.tsx # Organization switcher
|
|
375
|
+
│ ├── use-navigation.ts # Navigation hook
|
|
376
|
+
│ └── ui/ # Internal UI components (shadcn)
|
|
451
377
|
```
|
|
452
378
|
|
|
453
379
|
## Development
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@logickernel/bridge",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "Framework-agnostic micro-frontend authentication library for AuthJS/NextAuth JWT tokens",
|
|
5
5
|
"author": "Victor",
|
|
6
6
|
"license": "MIT",
|
|
@@ -101,4 +101,3 @@
|
|
|
101
101
|
"node": ">=18"
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
|