- Add fresh app structure (auth, tenant, mail, insight, docs, panel) - Include CMS content, API routes, scripts, and config - Migrate UI components, themes, and extensions to fresh runtime
304 lines
7.5 KiB
Markdown
304 lines
7.5 KiB
Markdown
# API Migration Guide - Next.js to Fresh + Deno
|
|
|
|
This document tracks the migration of Next.js API routes to Fresh handlers with Deno runtime.
|
|
|
|
## Migration Status
|
|
|
|
### ✅ Completed
|
|
|
|
#### Core Infrastructure
|
|
- [x] `middleware.ts` - Fresh middleware for authentication and session management
|
|
- [x] `lib/authGateway.deno.ts` - Cookie management with Web APIs
|
|
- [x] `server/serviceConfig.deno.ts` - Service URL configuration
|
|
|
|
#### API Routes Migrated
|
|
- [x] `/api/ping` → `routes/api/ping.ts`
|
|
- [x] `/api/auth/login` → `routes/api/auth/login.ts`
|
|
- [x] `/api/auth/session` → `routes/api/auth/session.ts`
|
|
- [x] `/api/render-markdown` → `routes/api/render-markdown.ts`
|
|
- [x] `/api/content-meta` → `routes/api/content-meta.ts`
|
|
|
|
### 🚧 In Progress
|
|
- [ ] Authentication routes (register, verify-email, MFA)
|
|
- [ ] Protected API routes (users, admin, mail, etc.)
|
|
- [ ] Dynamic routes ([...segments])
|
|
|
|
### 📋 Pending
|
|
The following Next.js API routes need to be migrated:
|
|
|
|
#### Auth Routes
|
|
- `app/api/auth/register/route.ts`
|
|
- `app/api/auth/register/verify/route.ts`
|
|
- `app/api/auth/register/send/route.ts`
|
|
- `app/api/auth/verify-email/route.ts`
|
|
- `app/api/auth/verify-email/send/route.ts`
|
|
- `app/api/auth/mfa/setup/route.ts`
|
|
- `app/api/auth/mfa/verify/route.ts`
|
|
- `app/api/auth/mfa/status/route.ts`
|
|
- `app/api/auth/mfa/disable/route.ts`
|
|
|
|
#### Protected API Routes
|
|
- `app/api/users/route.ts`
|
|
- `app/api/admin/settings/route.ts`
|
|
- `app/api/admin/users/metrics/route.ts`
|
|
- `app/api/admin/users/[userId]/role/route.ts`
|
|
|
|
#### Mail API Routes
|
|
- `app/api/mail/inbox/route.ts`
|
|
- `app/api/mail/send/route.ts`
|
|
- `app/api/mail/namespace/route.ts`
|
|
- `app/api/mail/message/[id]/route.ts`
|
|
- `app/api/mail/ai/summarize/route.ts`
|
|
- `app/api/mail/ai/reply-suggest/route.ts`
|
|
- `app/api/mail/ai/classify/route.ts`
|
|
|
|
#### AI & Task Routes
|
|
- `app/api/askai/route.ts`
|
|
- `app/api/rag/query/route.ts`
|
|
- `app/api/task/[...segments]/route.ts`
|
|
- `app/api/agent/[...segments]/route.ts`
|
|
|
|
## Migration Patterns
|
|
|
|
### 1. Basic API Handler
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
import { NextRequest, NextResponse } from 'next/server'
|
|
|
|
export async function GET(request: NextRequest) {
|
|
return NextResponse.json({ data: 'value' })
|
|
}
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
import { Handlers } from '$fresh/server.ts'
|
|
|
|
export const handler: Handlers = {
|
|
GET(_req, _ctx) {
|
|
return new Response(JSON.stringify({ data: 'value' }), {
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
},
|
|
}
|
|
```
|
|
|
|
### 2. Cookie Management
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
import { cookies } from 'next/headers'
|
|
|
|
const token = cookies().get('session')?.value
|
|
const res = NextResponse.json({ ... })
|
|
res.cookies.set('session', token, { httpOnly: true })
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
import { getSessionToken, applySessionCookie } from '@/lib/authGateway.deno.ts'
|
|
|
|
const token = getSessionToken(req)
|
|
const headers = new Headers({ 'Content-Type': 'application/json' })
|
|
applySessionCookie(headers, token)
|
|
return new Response(JSON.stringify({ ... }), { headers })
|
|
```
|
|
|
|
### 3. Query Parameters
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
const path = request.nextUrl.searchParams.get('path')
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
const url = new URL(req.url)
|
|
const path = url.searchParams.get('path')
|
|
```
|
|
|
|
### 4. Request Body
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
const body = await request.json()
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
const body = await req.json()
|
|
```
|
|
|
|
### 5. Dynamic Routes
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
// app/api/mail/message/[id]/route.ts
|
|
export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
|
|
const { id } = params
|
|
}
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
// routes/api/mail/message/[id].ts
|
|
import { Handlers } from '$fresh/server.ts'
|
|
|
|
export const handler: Handlers = {
|
|
GET(_req, ctx) {
|
|
const { id } = ctx.params
|
|
},
|
|
}
|
|
```
|
|
|
|
### 6. Catch-all Routes
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
// app/api/task/[...segments]/route.ts
|
|
export async function POST(request: NextRequest, { params }: { params: { segments: string[] } }) {
|
|
const { segments } = params
|
|
}
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
// routes/api/task/[...segments].ts
|
|
import { Handlers } from '$fresh/server.ts'
|
|
|
|
export const handler: Handlers = {
|
|
POST(_req, ctx) {
|
|
const segments = ctx.params.segments.split('/')
|
|
},
|
|
}
|
|
```
|
|
|
|
### 7. Middleware State Access
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
import { Handlers } from '$fresh/server.ts'
|
|
import { FreshState } from '@/middleware.ts'
|
|
|
|
export const handler: Handlers<unknown, FreshState> = {
|
|
GET(_req, ctx) {
|
|
const user = ctx.state.user
|
|
const isAuthenticated = ctx.state.isAuthenticated
|
|
// ...
|
|
},
|
|
}
|
|
```
|
|
|
|
### 8. Environment Variables
|
|
|
|
**Next.js Pattern:**
|
|
```typescript
|
|
const apiUrl = process.env.API_BASE_URL
|
|
```
|
|
|
|
**Fresh Pattern:**
|
|
```typescript
|
|
const apiUrl = Deno.env.get('API_BASE_URL')
|
|
```
|
|
|
|
## Key Differences
|
|
|
|
### Response Construction
|
|
|
|
**Next.js:** Uses `NextResponse` helper
|
|
```typescript
|
|
NextResponse.json(data, { status: 200 })
|
|
```
|
|
|
|
**Fresh:** Uses standard `Response` API
|
|
```typescript
|
|
new Response(JSON.stringify(data), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
})
|
|
```
|
|
|
|
### Cookie Handling
|
|
|
|
**Next.js:** Built-in cookie API with `cookies()` from `next/headers`
|
|
|
|
**Fresh:** Manual cookie parsing and `Set-Cookie` header management
|
|
- Use `getCookies(req)` to parse request cookies
|
|
- Use helper functions to set cookies in response headers
|
|
- See `lib/authGateway.deno.ts` for implementation
|
|
|
|
### File System Access
|
|
|
|
**Next.js:** Uses Node.js `fs` module
|
|
```typescript
|
|
import { readFile } from 'fs/promises'
|
|
const content = await readFile(path, 'utf-8')
|
|
```
|
|
|
|
**Fresh/Deno:** Uses Deno APIs
|
|
```typescript
|
|
const content = await Deno.readTextFile(path)
|
|
const stats = await Deno.stat(path)
|
|
```
|
|
|
|
### Subprocess Execution
|
|
|
|
**Next.js:** Uses Node.js `child_process`
|
|
```typescript
|
|
import { execFile } from 'child_process'
|
|
execFile('git', ['log'], callback)
|
|
```
|
|
|
|
**Fresh/Deno:** Uses `Deno.Command`
|
|
```typescript
|
|
const command = new Deno.Command('git', {
|
|
args: ['log'],
|
|
stdout: 'piped',
|
|
})
|
|
const { stdout } = await command.output()
|
|
```
|
|
|
|
## Authentication Flow
|
|
|
|
### Middleware (`middleware.ts`)
|
|
1. Parses session and MFA cookies from request
|
|
2. For protected routes: validates session token against Account Service
|
|
3. Injects user context into `ctx.state`
|
|
4. Returns 401 for unauthenticated API requests
|
|
5. Redirects to login for unauthenticated page requests
|
|
|
|
### Login Flow (`routes/api/auth/login.ts`)
|
|
1. Validates credentials with Account Service
|
|
2. On success: sets session cookie with token
|
|
3. On MFA required: sets MFA challenge cookie
|
|
4. Clears cookies on failure
|
|
|
|
### Session Flow (`routes/api/auth/session.ts`)
|
|
1. Gets session token from cookie
|
|
2. Validates with Account Service
|
|
3. Returns normalized user data
|
|
4. DELETE method clears session (logout)
|
|
|
|
## Testing Checklist
|
|
|
|
When migrating an API route, verify:
|
|
- [ ] Request parsing works (query params, body, headers)
|
|
- [ ] Response format matches original (status, headers, body)
|
|
- [ ] Error handling preserves status codes
|
|
- [ ] Cookie handling works correctly
|
|
- [ ] Authentication/authorization is enforced
|
|
- [ ] Deno permissions are sufficient (--allow-net, --allow-read, etc.)
|
|
- [ ] Environment variables are read correctly
|
|
- [ ] External service calls have timeouts
|
|
- [ ] Type safety is maintained
|
|
|
|
## Next Steps
|
|
|
|
1. Migrate authentication routes (register, verify-email, MFA)
|
|
2. Migrate protected API routes with user context
|
|
3. Migrate dynamic and catch-all routes
|
|
4. Create integration tests for migrated routes
|
|
5. Update frontend to use new API endpoints
|
|
6. Remove Next.js route handlers from app/ directory
|