mulink
v1.2.3
Published
Universal type-safe API integration library for modern web applications
Maintainers
Readme
🌉 Mulink - The Ultimate Intelligent API Client Generator
mulink is the world's most comprehensive, intelligent, and flexible API client generator for Next.js. It automatically generates type-safe API clients, hooks, actions, and utilities from your OpenAPI schema, following Next.js 16+ best practices.
✨ Intelligent & Self-Adapting - mulink automatically detects and validates endpoints, features, and configurations from your OpenAPI schema. No manual configuration needed!
🚀 No Local APIs Required - mulink generates everything you need. No need to create local API routes or manual integrations. Everything is auto-generated and type-safe!
✨ Key Features
🧠 Intelligent Schema Analysis
- ✅ Auto-Detection - Automatically detects endpoints, OAuth providers, MFA, Passkeys, and more from OpenAPI schema
- ✅ Smart Validation - Validates configuration against actual schema endpoints before generating code
- ✅ Intelligent Warnings - Warns you when configured features don't exist in your backend
- ✅ Adaptive Generation - Only generates code for features that actually exist in your API
- ✅ Account Status Detection - Automatically detects account status patterns (active, inactive, suspended, locked)
- ✅ Error Code Extraction - Intelligently extracts error codes and patterns from schema
🚀 Core Features
- ✅ Type-Safe API Clients - Full TypeScript support with Zod validation
- ✅ React Hooks - Auto-generated React Query hooks for all endpoints
- ✅ Server Actions - Next.js 16 Server Actions with type safety
- ✅ Error Handling - Comprehensive error handling with auth error support
- ✅ Middleware System - Flexible request/response middleware
- ✅ Caching - Smart caching with Next.js cache tags
- ✅ Request Deduplication - Automatic request deduplication
- ✅ Retry Logic - Configurable retry with exponential backoff
📡 Streaming Support
- ✅ Server-Sent Events (SSE) - Full SSE support with auto-reconnect
- ✅ Auto-Detection - Automatically detects SSE endpoints from schema
- ✅ Intelligent Hooks - Auto-generated hooks with connection state management
- ✅ WebSocket - WebSocket streaming support (coming soon)
- ✅ HTTP Streaming - ReadableStream support
📤 File Uploads
- ✅ Presigned URLs - Direct upload to S3/MinIO with presigned URLs
- ✅ Auto-Detection - Automatically detects presigned upload endpoints
- ✅ Progress Tracking - Real-time upload progress with XMLHttpRequest
- ✅ File Validation - Automatic file size and type validation (extracted from schema)
- ✅ Compression - Image compression (WebP) support
- ✅ Fallback Support - Automatic fallback to backend upload
- ✅ Smart Validation - Validates presigned endpoint existence before enabling
🔐 Authentication (NextAuth 5.0)
- ✅ NextAuth 5.0 - Full NextAuth 5.0 support with intelligent configuration
- ✅ OAuth Providers - Auto-detected OAuth providers (Google, GitHub, etc.)
- ✅ MFA Support - TOTP and backup codes (auto-detected from schema)
- ✅ Passkeys - WebAuthn/Passkeys support (auto-detected from schema)
- ✅ Token Management - Automatic token injection and refresh
- ✅ Account Status Checking - Auto-detected account status validation
- ✅ Auth Error Handling - Automatic redirect on auth errors
- ✅ Session Management - Server-side session handling with JWT/Database strategies
🎯 Advanced Features
- ✅ Custom Middleware - Add your own middleware
- ✅ Custom Error Handlers - Configure custom error handling
- ✅ Plugin System - Extensible plugin architecture
- ✅ Type Mappings - Custom type mappings
- ✅ Development Tools - Hot reload, validation, mocking
📦 Installation
npm install mulink
# or
yarn add mulink
# or
pnpm add mulink🚀 Quick Start
1. Create Configuration File
Create link.config.json in your project root:
{
"schema": "https://api.example.com/openapi.json",
"outputDir": "src/generated",
"framework": {
"type": "nextjs",
"version": "16.0.7",
"router": "app",
"features": {
"serverActions": true,
"middleware": true,
"streaming": true,
"revalidation": true
},
"streaming": {
"enabled": true,
"sse": {
"enabled": true,
"autoReconnect": true,
"reconnectDelay": 3000,
"maxReconnectAttempts": 5
}
}
},
"api": {
"baseUrl": "https://api.example.com",
"timeout": 30000,
"retries": 3,
"errorHandling": {
"enableAuthErrorHandling": true,
"authErrorHandlerPath": "@/lib/auth-error-handler",
"generateAuthErrorHandler": true
}
},
"auth": {
"enabled": true,
"provider": "next-auth",
"authPath": "@/lib/auth",
"tokenGetter": "auth",
"oauth": {
"enabled": true,
"providers": ["google", "github"]
},
"mfa": {
"enabled": true
},
"passkeys": {
"enabled": true
},
"session": {
"strategy": "jwt",
"maxAge": 30 * 24 * 60 * 60
}
},
"uploads": {
"enabled": true,
"strategy": "presigned",
"provider": "s3",
"presignedUploads": {
"enabled": true,
"presignEndpoint": "/api/v1/files/presign-upload",
"fallbackToBackend": true
},
"progressTracking": {
"enabled": true,
"useXHR": true
}
}
}2. Generate Code
npx mulink generatemulink will:
- ✅ Analyze your OpenAPI schema intelligently
- ✅ Detect all available endpoints and features
- ✅ Validate your configuration against actual schema
- ✅ Warn you about missing endpoints
- ✅ Generate only code for features that exist
- ✅ Create type-safe clients, hooks, and actions
3. Use Generated Code
// In your component
import { useGetUsers } from '@/generated/hooks/users'
import { apiClient } from '@/generated/client'
// Use React Query hook
function UsersList() {
const { data, isLoading } = useGetUsers()
if (isLoading) return <div>Loading...</div>
return (
<ul>
{data?.data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}
// Or use client directly
async function fetchUsers() {
const response = await apiClient.users.getUsers()
return response.data
}🧠 Intelligent Features
Auto-Detection & Validation
mulink intelligently analyzes your OpenAPI schema and validates your configuration:
{
"auth": {
"oauth": {
"providers": ["google", "github", "discord"] // discord not in schema
},
"mfa": {
"enabled": true // MFA endpoints not in schema
}
}
}mulink Output:
⚠️ mulink Configuration Warnings:
⚠️ OAuth provider "discord" is configured but OAuth endpoints are not found in OpenAPI schema.
⚠️ MFA is enabled but MFA endpoints are not found in OpenAPI schema.
These features will be disabled in generated code.
✅ Generated:
- Google OAuth (exists in schema)
- GitHub OAuth (exists in schema)
❌ Discord OAuth (not found - automatically excluded)
❌ MFA (not found - automatically disabled)What mulink Auto-Detects
Authentication Endpoints
- Login endpoints (
/auth/login,/auth/login/credentials) - Refresh token endpoints
- Logout endpoints
- User info endpoints (
/auth/me,/auth/session)
- Login endpoints (
OAuth Providers
- OAuth authorize endpoints
- OAuth callback endpoints
- Provider names from paths
MFA Support
- TOTP setup endpoints (
/auth/mfa/totp/setup) - TOTP verify endpoints (
/auth/mfa/totp/verify)
- TOTP setup endpoints (
Passkeys Support
- Passkey challenge endpoints (
/auth/passkey/challenge) - Passkey authenticate endpoints (
/auth/passkey/authenticate)
- Passkey challenge endpoints (
Account Status Patterns
- Active statuses (active, enabled, verified)
- Inactive statuses (inactive, disabled, unverified)
- Suspended statuses (suspended, banned)
- Locked statuses (locked, frozen)
Error Codes
- Common error codes from API responses
- Error patterns from schema definitions
File Upload Configuration
- Presigned upload endpoints
- File size constraints
- Allowed file types
Streaming Endpoints
- SSE endpoints (text/event-stream)
- WebSocket endpoints (coming soon)
📚 Configuration Options
Framework Configuration
{
framework: {
type: 'nextjs',
version: '16.0.7',
router: 'app', // 'app' | 'pages'
features: {
serverActions: true,
middleware: true,
streaming: true,
revalidation: true
},
streaming: {
enabled: true, // Auto-detected if SSE endpoints exist
sse: {
enabled: true,
autoReconnect: true,
reconnectDelay: 3000,
maxReconnectAttempts: 5
}
}
}
}API Configuration
{
api: {
baseUrl: 'https://api.example.com',
timeout: 30000,
retries: 3,
headers: {
'User-Agent': 'Mulink-Client/3.4.5',
'Accept': 'application/json'
},
errorHandling: {
enableAuthErrorHandling: true,
authErrorHandlerPath: '@/lib/auth-error-handler',
generateAuthErrorHandler: true // Auto-generated with intelligent error detection
},
customMiddleware: [
{
name: 'analytics',
importPath: '@/lib/analytics-middleware',
includeInDefault: true,
priority: 5
}
]
}
}Authentication Configuration (NextAuth 5.0)
{
auth: {
enabled: true,
provider: 'next-auth', // 'next-auth' | 'clerk' | 'custom'
authPath: '@/lib/auth',
tokenGetter: 'auth',
oauth: {
enabled: true,
providers: ['google', 'github'] // Auto-validated against schema
},
mfa: {
enabled: true // Auto-validated - only enabled if endpoints exist
},
passkeys: {
enabled: true // Auto-validated - only enabled if endpoints exist
},
session: {
strategy: 'jwt', // 'jwt' | 'database'
maxAge: 30 * 24 * 60 * 60 // 30 days
}
}
}Note: mulink automatically validates OAuth providers, MFA, and Passkeys against your schema. Features not found in the schema will be automatically disabled with warnings.
Upload Configuration
{
uploads: {
enabled: true,
strategy: 'presigned', // 'standard' | 'external' | 'presigned'
provider: 's3', // 'uploadthing' | 'vercel-blob' | 's3' | 'minio'
compression: {
enabled: true,
formats: ['webp', 'gzip']
},
security: {
maxSize: '100MB', // Auto-extracted from schema if available
allowedTypes: ['image/*', 'video/*'], // Auto-extracted from schema if available
scan: 'none'
},
presignedUploads: {
enabled: true, // Auto-validated - only enabled if endpoint exists
presignEndpoint: '/api/v1/files/presign-upload', // Auto-detected if not specified
fallbackToBackend: true
},
progressTracking: {
enabled: true,
useXHR: true
}
}
}🎯 Usage Examples
Basic Query Hook
import { useGetUser } from '@/generated/hooks/users'
function UserProfile({ userId }: { userId: string }) {
const { data, isLoading, error } = useGetUser(userId, {
enabled: !!userId,
staleTime: 5 * 60 * 1000, // 5 minutes
})
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return <div>{data?.data.name}</div>
}Mutation Hook
import { useCreateUser } from '@/generated/hooks/users'
function CreateUserForm() {
const { mutate, isPending } = useCreateUser({
onSuccess: (data) => {
toast.success('User created!')
router.push(`/users/${data.data.id}`)
},
onError: (error) => {
toast.error(error.message)
}
})
const handleSubmit = (formData: FormData) => {
mutate({
name: formData.get('name'),
email: formData.get('email')
})
}
return (
<form action={handleSubmit}>
{/* form fields */}
<button type="submit" disabled={isPending}>
{isPending ? 'Creating...' : 'Create User'}
</button>
</form>
)
}Server-Sent Events (SSE) - Auto-Detected
import { useStreamAnalysisUpdates } from '@/generated/hooks/analysis'
function AnalysisStatus({ resultId }: { resultId: string }) {
// Hook auto-generated if SSE endpoint exists in schema
const { isConnected, sseError, reconnect } = useStreamAnalysisUpdates(
resultId,
{
enabled: true,
onMessage: (data) => {
console.log('Update:', data)
// Handle real-time updates
},
onError: (error) => {
console.error('SSE Error:', error)
}
}
)
return (
<div>
<div>Status: {isConnected ? 'Connected' : 'Disconnected'}</div>
{sseError && (
<button onClick={reconnect}>Reconnect</button>
)}
</div>
)
}Features:
- ✅ Auto-detection - mulink automatically detects SSE endpoints from OpenAPI schema
- ✅ Auto-reconnect - Automatic reconnection on connection loss
- ✅ State Management - Full connection state (isConnected, sseError, reconnect)
- ✅ Event Handlers - Support for onMessage, onError, onOpen
- ✅ No Manual Setup - Everything is auto-generated!
File Upload with Presigned URLs - Auto-Validated
import { usePredictDeepfakeUpload } from '@/generated/services/uploadPredictDeepfake'
function FileUploadForm() {
const [progress, setProgress] = useState(0)
// Hook auto-generated if upload endpoint exists
// Presigned uploads auto-enabled if presigned endpoint exists
const { mutate, isPending } = usePredictDeepfakeUpload({
onProgress: ({ percentage }) => {
setProgress(percentage)
},
onSuccess: (data) => {
toast.success('File uploaded successfully!')
console.log('Result:', data)
},
onError: (error) => {
toast.error(error.message)
},
uploadConfig: {
maxSize: '100MB', // Auto-extracted from schema
allowedTypes: ['video/*', 'image/*'], // Auto-extracted from schema
compression: {
enabled: true,
formats: ['webp']
}
}
})
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0]
if (file) {
mutate({ file })
}
}
return (
<div>
<input type="file" onChange={handleFileChange} />
{isPending && (
<div>
<progress value={progress} max={100} />
<span>{progress}%</span>
</div>
)}
</div>
)
}Features:
- ✅ Auto-detection - Automatically detects presigned upload endpoints
- ✅ Auto-validation - Validates endpoint existence before enabling
- ✅ Auto-fallback - Falls back to backend upload if presigned fails
- ✅ Progress Tracking - Real-time upload progress
- ✅ File Constraints - Auto-extracted from schema
NextAuth 5.0 with OAuth, MFA, and Passkeys
// lib/auth.ts (auto-generated by mulink)
import NextAuth from 'next-auth'
import { authOptions } from './auth-options' // Auto-generated
export const { handlers, auth, signIn, signOut } = NextAuth(authOptions)
// Usage in components
import { signIn, signOut } from '@/lib/auth'
// OAuth sign-in (auto-detected providers)
await signIn('google') // ✅ Only if Google OAuth exists in schema
await signIn('github') // ✅ Only if GitHub OAuth exists in schema
// MFA setup (auto-detected)
import { setupMFA } from '@/lib/auth/utils'
await setupMFA() // ✅ Only if MFA endpoints exist
// Passkeys (auto-detected)
import { registerPasskey, authenticateWithPasskey } from '@/lib/auth/passkeys'
await registerPasskey() // ✅ Only if Passkey endpoints existFeatures:
- ✅ Auto-detected OAuth - Only generates code for providers that exist
- ✅ Auto-detected MFA - Only enabled if MFA endpoints exist
- ✅ Auto-detected Passkeys - Only enabled if Passkey endpoints exist
- ✅ Account Status Checking - Auto-detected account status patterns
- ✅ Error Handling - Auto-detected error codes and patterns
Direct API Client Usage
import { apiClient } from '@/generated/client'
// In Server Component or Server Action
async function getUsers() {
const response = await apiClient.users.getUsers({
config: {
cacheTags: ['users'],
revalidate: 300
}
})
return response.data
}
// With custom middleware
const response = await apiClient.users.getUsers({
config: {
middleware: [
{
name: 'custom-logging',
onRequest: async (config) => {
console.log('Request:', config)
return config
}
}
]
}
})Server Actions
import { createUser } from '@/generated/actions/users'
// In Server Component
async function CreateUserButton() {
async function handleCreate(formData: FormData) {
'use server'
const result = await createUser({
name: formData.get('name'),
email: formData.get('email')
})
if (result?.serverError) {
return { error: result.serverError }
}
redirect(`/users/${result.data.id}`)
}
return (
<form action={handleCreate}>
{/* form fields */}
</form>
)
}🔧 Advanced Configuration
Custom Middleware
// In link.config.json
{
"api": {
"customMiddleware": [
{
"name": "analytics",
"importPath": "@/lib/analytics-middleware",
"includeInDefault": true,
"priority": 1
},
{
"name": "custom-logging",
"importPath": "@/lib/custom-logging",
"includeInDefault": false,
"priority": 10
}
]
}
}Custom Error Handlers
// In link.config.json
{
"api": {
"errorHandling": {
"enableAuthErrorHandling": true,
"authErrorHandlerPath": "@/lib/custom-auth-error-handler",
"generateAuthErrorHandler": false, // Use your own handler
"customHandlers": {
"rateLimit": "@/lib/rate-limit-handler",
"validation": "@/lib/validation-handler"
}
}
}
}Note: mulink auto-generates error handlers with intelligent error code and account status detection. You can override with custom handlers if needed.
Type Mappings
// In link.config.json
{
"typeMappings": {
"DateTime": "Date",
"UUID": "string",
"Money": "number",
"Email": "string"
}
}🎨 Best Practices
1. Use React Query Hooks for Client Components
// ✅ Good - Uses generated hook
'use client'
import { useGetUsers } from '@/generated/hooks/users'
function UsersList() {
const { data } = useGetUsers()
return <div>{/* render */}</div>
}2. Use Server Actions for Server Components
// ✅ Good - Uses server action
import { getUsers } from '@/generated/actions/users'
async function UsersList() {
const users = await getUsers()
return <div>{/* render */}</div>
}3. Use Direct Client for Complex Scenarios
// ✅ Good - Direct client for complex logic
import { apiClient } from '@/generated/client'
async function complexOperation() {
const users = await apiClient.users.getUsers()
const posts = await apiClient.posts.getPosts()
// Complex logic here
}4. Configure Caching Properly
// ✅ Good - Configure cache tags
const response = await apiClient.users.getUsers({
config: {
cacheTags: ['users', 'user-list'],
revalidate: 300
}
})5. Handle Errors Gracefully
// ✅ Good - Proper error handling
const { data, error } = useGetUsers({
onError: (error) => {
if (error.status === 401) {
router.push('/auth/signin')
} else {
toast.error(error.message)
}
}
})6. Trust mulink's Intelligence
// ✅ Good - Let mulink auto-detect and validate
// mulink will:
// - Only generate code for features that exist
// - Warn you about missing endpoints
// - Auto-disable features not in schema
// - Extract constraints from schema
// Just configure what you want, mulink handles the rest!🐛 Troubleshooting
Common Issues
1. Import Errors
Problem: Cannot find module '@/generated/...'
Solution: Make sure your tsconfig.json has the correct path mapping:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@/generated/*": ["./src/generated/*"]
}
}
}2. Auth Errors
Problem: Auth errors not being handled
Solution: Enable auth error handling in config:
{
"api": {
"errorHandling": {
"enableAuthErrorHandling": true,
"generateAuthErrorHandler": true
}
}
}3. SSE Not Working
Problem: SSE connection fails
Solution: Check streaming configuration. mulink will warn you if SSE endpoints don't exist:
{
"framework": {
"streaming": {
"enabled": true,
"sse": {
"enabled": true,
"autoReconnect": true
}
}
}
}Note: mulink will automatically detect if SSE endpoints exist and warn you if they don't.
4. Upload Progress Not Working
Problem: Upload progress not updating
Solution: Enable progress tracking:
{
"uploads": {
"progressTracking": {
"enabled": true,
"useXHR": true
}
}
}5. Features Not Generated
Problem: OAuth/MFA/Passkeys not working
Solution: Check mulink warnings. mulink will warn you if endpoints don't exist:
⚠️ OAuth provider "discord" is configured but OAuth endpoints are not found in OpenAPI schema.
⚠️ MFA is enabled but MFA endpoints are not found in OpenAPI schema.Solution: Make sure your OpenAPI schema includes the required endpoints, or remove the configuration for features that don't exist.
📖 API Reference
Generated Client
import { apiClient } from '@/generated/client'
// Get endpoint client
const usersClient = apiClient.users
// Make request
const response = await usersClient.getUser({ params: { id: '123' } })
// With options
const response = await usersClient.getUsers({
config: {
timeout: 5000,
retries: 2,
cacheTags: ['users']
}
})Generated Hooks
import { useGetUser, useCreateUser } from '@/generated/hooks/users'
// Query hook
const { data, isLoading, error, refetch } = useGetUser('123', {
enabled: true,
staleTime: 5 * 60 * 1000
})
// Mutation hook
const { mutate, isPending } = useCreateUser({
onSuccess: (data) => console.log(data),
onError: (error) => console.error(error)
})Generated Actions
import { getUser, createUser } from '@/generated/actions/users'
// In server component or server action
const user = await getUser({ params: { id: '123' } })
const newUser = await createUser({ name: 'John', email: '[email protected]' })Generated Auth (NextAuth 5.0)
import { signIn, signOut, auth } from '@/lib/auth'
import { setupMFA, verifyMFA } from '@/lib/auth/utils'
import { registerPasskey, authenticateWithPasskey } from '@/lib/auth/passkeys'
// OAuth sign-in (auto-detected providers)
await signIn('google')
await signIn('github')
// MFA (auto-detected)
await setupMFA()
await verifyMFA({ code: '123456' })
// Passkeys (auto-detected)
await registerPasskey()
await authenticateWithPasskey()🧠 How Intelligence Works
Schema Analysis Process
Endpoint Detection
- Scans all endpoints in OpenAPI schema
- Matches patterns (path, operationId, content-type)
- Extracts authentication, OAuth, MFA, Passkey endpoints
Configuration Validation
- Compares your configuration with detected endpoints
- Warns about missing endpoints
- Auto-disables features not in schema
Pattern Extraction
- Extracts account status patterns from schema definitions
- Extracts error codes from API responses
- Extracts file constraints from upload endpoints
Code Generation
- Only generates code for validated features
- Includes intelligent error handling
- Adds account status checking where detected
Example: OAuth Auto-Detection
// Your OpenAPI schema has:
// GET /auth/oauth/authorize/{provider}
// POST /auth/oauth/callback
// mulink detects:
const detectedProviders = ['google', 'github'] // From paths
// Your config:
{
"oauth": {
"providers": ["google", "github", "discord"]
}
}
// mulink validates:
✅ google - exists in schema
✅ github - exists in schema
❌ discord - not found, warns and excludes
// Generated code only includes google and github🤝 Contributing
Contributions are welcome! Please read our contributing guidelines first.
📄 License
MUV License - see LICENSE file for details.
🙏 Acknowledgments
- Built for Next.js 16+
- Uses React Query for data fetching
- Uses Zod for validation
- Uses TypeScript for type safety
- Uses NextAuth 5.0 for authentication
Made with ❤️ by the Mulverse team
Version 1.0.2 - Intelligent API Client Generator
