mulink 1.0.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/LICENSE +70 -0
- package/README.md +1031 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/lib/chunk-F6QVO6NR.cjs +9541 -0
- package/dist/lib/chunk-F6QVO6NR.cjs.map +1 -0
- package/dist/lib/chunk-SMOCRKWL.js +9521 -0
- package/dist/lib/chunk-SMOCRKWL.js.map +1 -0
- package/dist/lib/cli.cjs +340 -0
- package/dist/lib/cli.cjs.map +1 -0
- package/dist/lib/cli.d.cts +1 -0
- package/dist/lib/cli.d.ts +1 -0
- package/dist/lib/cli.js +338 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/client.cjs +70 -0
- package/dist/lib/client.cjs.map +1 -0
- package/dist/lib/client.d.cts +9 -0
- package/dist/lib/client.d.ts +9 -0
- package/dist/lib/client.js +16 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/index.cjs +64 -0
- package/dist/lib/index.cjs.map +1 -0
- package/dist/lib/index.d.cts +15 -0
- package/dist/lib/index.d.ts +15 -0
- package/dist/lib/index.js +3 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/version-checker-BWdifiXN.d.cts +576 -0
- package/dist/lib/version-checker-BWdifiXN.d.ts +576 -0
- package/package.json +126 -0
package/README.md
ADDED
|
@@ -0,0 +1,1031 @@
|
|
|
1
|
+
# 🌉 Mulink - The Ultimate Intelligent API Client Generator
|
|
2
|
+
|
|
3
|
+
**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.
|
|
4
|
+
|
|
5
|
+
> **✨ Intelligent & Self-Adapting** - mulink automatically detects and validates endpoints, features, and configurations from your OpenAPI schema. No manual configuration needed!
|
|
6
|
+
|
|
7
|
+
> **🚀 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!
|
|
8
|
+
|
|
9
|
+
[](https://www.typescriptlang.org/)
|
|
10
|
+
[](https://nextjs.org/)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## ✨ Key Features
|
|
16
|
+
|
|
17
|
+
### 🧠 Intelligent Schema Analysis
|
|
18
|
+
- ✅ **Auto-Detection** - Automatically detects endpoints, OAuth providers, MFA, Passkeys, and more from OpenAPI schema
|
|
19
|
+
- ✅ **Smart Validation** - Validates configuration against actual schema endpoints before generating code
|
|
20
|
+
- ✅ **Intelligent Warnings** - Warns you when configured features don't exist in your backend
|
|
21
|
+
- ✅ **Adaptive Generation** - Only generates code for features that actually exist in your API
|
|
22
|
+
- ✅ **Account Status Detection** - Automatically detects account status patterns (active, inactive, suspended, locked)
|
|
23
|
+
- ✅ **Error Code Extraction** - Intelligently extracts error codes and patterns from schema
|
|
24
|
+
|
|
25
|
+
### 🚀 Core Features
|
|
26
|
+
- ✅ **Type-Safe API Clients** - Full TypeScript support with Zod validation
|
|
27
|
+
- ✅ **React Hooks** - Auto-generated React Query hooks for all endpoints
|
|
28
|
+
- ✅ **Server Actions** - Next.js 16 Server Actions with type safety
|
|
29
|
+
- ✅ **Error Handling** - Comprehensive error handling with auth error support
|
|
30
|
+
- ✅ **Middleware System** - Flexible request/response middleware
|
|
31
|
+
- ✅ **Caching** - Smart caching with Next.js cache tags
|
|
32
|
+
- ✅ **Request Deduplication** - Automatic request deduplication
|
|
33
|
+
- ✅ **Retry Logic** - Configurable retry with exponential backoff
|
|
34
|
+
|
|
35
|
+
### 📡 Streaming Support
|
|
36
|
+
- ✅ **Server-Sent Events (SSE)** - Full SSE support with auto-reconnect
|
|
37
|
+
- ✅ **Auto-Detection** - Automatically detects SSE endpoints from schema
|
|
38
|
+
- ✅ **Intelligent Hooks** - Auto-generated hooks with connection state management
|
|
39
|
+
- ✅ **WebSocket** - WebSocket streaming support (coming soon)
|
|
40
|
+
- ✅ **HTTP Streaming** - ReadableStream support
|
|
41
|
+
|
|
42
|
+
### 📤 File Uploads
|
|
43
|
+
- ✅ **Presigned URLs** - Direct upload to S3/MinIO with presigned URLs
|
|
44
|
+
- ✅ **Auto-Detection** - Automatically detects presigned upload endpoints
|
|
45
|
+
- ✅ **Progress Tracking** - Real-time upload progress with XMLHttpRequest
|
|
46
|
+
- ✅ **File Validation** - Automatic file size and type validation (extracted from schema)
|
|
47
|
+
- ✅ **Compression** - Image compression (WebP) support
|
|
48
|
+
- ✅ **Fallback Support** - Automatic fallback to backend upload
|
|
49
|
+
- ✅ **Smart Validation** - Validates presigned endpoint existence before enabling
|
|
50
|
+
|
|
51
|
+
### 🔐 Authentication (NextAuth 5.0)
|
|
52
|
+
- ✅ **NextAuth 5.0** - Full NextAuth 5.0 support with intelligent configuration
|
|
53
|
+
- ✅ **OAuth Providers** - Auto-detected OAuth providers (Google, GitHub, etc.)
|
|
54
|
+
- ✅ **MFA Support** - TOTP and backup codes (auto-detected from schema)
|
|
55
|
+
- ✅ **Passkeys** - WebAuthn/Passkeys support (auto-detected from schema)
|
|
56
|
+
- ✅ **Token Management** - Automatic token injection and refresh
|
|
57
|
+
- ✅ **Account Status Checking** - Auto-detected account status validation
|
|
58
|
+
- ✅ **Auth Error Handling** - Automatic redirect on auth errors
|
|
59
|
+
- ✅ **Session Management** - Server-side session handling with JWT/Database strategies
|
|
60
|
+
|
|
61
|
+
### 🎯 Advanced Features
|
|
62
|
+
- ✅ **Custom Middleware** - Add your own middleware
|
|
63
|
+
- ✅ **Custom Error Handlers** - Configure custom error handling
|
|
64
|
+
- ✅ **Plugin System** - Extensible plugin architecture
|
|
65
|
+
- ✅ **Type Mappings** - Custom type mappings
|
|
66
|
+
- ✅ **Development Tools** - Hot reload, validation, mocking
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 📦 Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install mulink
|
|
74
|
+
# or
|
|
75
|
+
yarn add mulink
|
|
76
|
+
# or
|
|
77
|
+
pnpm add mulink
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## 🚀 Quick Start
|
|
83
|
+
|
|
84
|
+
### 1. Create Configuration File
|
|
85
|
+
|
|
86
|
+
Create `link.config.json` in your project root:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"schema": "https://api.example.com/openapi.json",
|
|
91
|
+
"outputDir": "src/generated",
|
|
92
|
+
"framework": {
|
|
93
|
+
"type": "nextjs",
|
|
94
|
+
"version": "16.0.1",
|
|
95
|
+
"router": "app",
|
|
96
|
+
"features": {
|
|
97
|
+
"serverActions": true,
|
|
98
|
+
"middleware": true,
|
|
99
|
+
"streaming": true,
|
|
100
|
+
"revalidation": true
|
|
101
|
+
},
|
|
102
|
+
"streaming": {
|
|
103
|
+
"enabled": true,
|
|
104
|
+
"sse": {
|
|
105
|
+
"enabled": true,
|
|
106
|
+
"autoReconnect": true,
|
|
107
|
+
"reconnectDelay": 3000,
|
|
108
|
+
"maxReconnectAttempts": 5
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"api": {
|
|
113
|
+
"baseUrl": "https://api.example.com",
|
|
114
|
+
"timeout": 30000,
|
|
115
|
+
"retries": 3,
|
|
116
|
+
"errorHandling": {
|
|
117
|
+
"enableAuthErrorHandling": true,
|
|
118
|
+
"authErrorHandlerPath": "@/lib/auth-error-handler",
|
|
119
|
+
"generateAuthErrorHandler": true
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
"auth": {
|
|
123
|
+
"enabled": true,
|
|
124
|
+
"provider": "next-auth",
|
|
125
|
+
"authPath": "@/lib/auth",
|
|
126
|
+
"tokenGetter": "auth",
|
|
127
|
+
"oauth": {
|
|
128
|
+
"enabled": true,
|
|
129
|
+
"providers": ["google", "github"]
|
|
130
|
+
},
|
|
131
|
+
"mfa": {
|
|
132
|
+
"enabled": true
|
|
133
|
+
},
|
|
134
|
+
"passkeys": {
|
|
135
|
+
"enabled": true
|
|
136
|
+
},
|
|
137
|
+
"session": {
|
|
138
|
+
"strategy": "jwt",
|
|
139
|
+
"maxAge": 30 * 24 * 60 * 60
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"uploads": {
|
|
143
|
+
"enabled": true,
|
|
144
|
+
"strategy": "presigned",
|
|
145
|
+
"provider": "s3",
|
|
146
|
+
"presignedUploads": {
|
|
147
|
+
"enabled": true,
|
|
148
|
+
"presignEndpoint": "/api/v1/files/presign-upload",
|
|
149
|
+
"fallbackToBackend": true
|
|
150
|
+
},
|
|
151
|
+
"progressTracking": {
|
|
152
|
+
"enabled": true,
|
|
153
|
+
"useXHR": true
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 2. Generate Code
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
npx mulink generate
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**mulink will:**
|
|
166
|
+
- ✅ Analyze your OpenAPI schema intelligently
|
|
167
|
+
- ✅ Detect all available endpoints and features
|
|
168
|
+
- ✅ Validate your configuration against actual schema
|
|
169
|
+
- ✅ Warn you about missing endpoints
|
|
170
|
+
- ✅ Generate only code for features that exist
|
|
171
|
+
- ✅ Create type-safe clients, hooks, and actions
|
|
172
|
+
|
|
173
|
+
### 3. Use Generated Code
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
// In your component
|
|
177
|
+
import { useGetUsers } from '@/generated/hooks/users'
|
|
178
|
+
import { apiClient } from '@/generated/client'
|
|
179
|
+
|
|
180
|
+
// Use React Query hook
|
|
181
|
+
function UsersList() {
|
|
182
|
+
const { data, isLoading } = useGetUsers()
|
|
183
|
+
|
|
184
|
+
if (isLoading) return <div>Loading...</div>
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<ul>
|
|
188
|
+
{data?.data.map(user => (
|
|
189
|
+
<li key={user.id}>{user.name}</li>
|
|
190
|
+
))}
|
|
191
|
+
</ul>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Or use client directly
|
|
196
|
+
async function fetchUsers() {
|
|
197
|
+
const response = await apiClient.users.getUsers()
|
|
198
|
+
return response.data
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 🧠 Intelligent Features
|
|
205
|
+
|
|
206
|
+
### Auto-Detection & Validation
|
|
207
|
+
|
|
208
|
+
mulink intelligently analyzes your OpenAPI schema and validates your configuration:
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"auth": {
|
|
213
|
+
"oauth": {
|
|
214
|
+
"providers": ["google", "github", "discord"] // discord not in schema
|
|
215
|
+
},
|
|
216
|
+
"mfa": {
|
|
217
|
+
"enabled": true // MFA endpoints not in schema
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**mulink Output:**
|
|
224
|
+
```
|
|
225
|
+
⚠️ mulink Configuration Warnings:
|
|
226
|
+
⚠️ OAuth provider "discord" is configured but OAuth endpoints are not found in OpenAPI schema.
|
|
227
|
+
⚠️ MFA is enabled but MFA endpoints are not found in OpenAPI schema.
|
|
228
|
+
These features will be disabled in generated code.
|
|
229
|
+
|
|
230
|
+
✅ Generated:
|
|
231
|
+
- Google OAuth (exists in schema)
|
|
232
|
+
- GitHub OAuth (exists in schema)
|
|
233
|
+
❌ Discord OAuth (not found - automatically excluded)
|
|
234
|
+
❌ MFA (not found - automatically disabled)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### What mulink Auto-Detects
|
|
238
|
+
|
|
239
|
+
1. **Authentication Endpoints**
|
|
240
|
+
- Login endpoints (`/auth/login`, `/auth/login/credentials`)
|
|
241
|
+
- Refresh token endpoints
|
|
242
|
+
- Logout endpoints
|
|
243
|
+
- User info endpoints (`/auth/me`, `/auth/session`)
|
|
244
|
+
|
|
245
|
+
2. **OAuth Providers**
|
|
246
|
+
- OAuth authorize endpoints
|
|
247
|
+
- OAuth callback endpoints
|
|
248
|
+
- Provider names from paths
|
|
249
|
+
|
|
250
|
+
3. **MFA Support**
|
|
251
|
+
- TOTP setup endpoints (`/auth/mfa/totp/setup`)
|
|
252
|
+
- TOTP verify endpoints (`/auth/mfa/totp/verify`)
|
|
253
|
+
|
|
254
|
+
4. **Passkeys Support**
|
|
255
|
+
- Passkey challenge endpoints (`/auth/passkey/challenge`)
|
|
256
|
+
- Passkey authenticate endpoints (`/auth/passkey/authenticate`)
|
|
257
|
+
|
|
258
|
+
5. **Account Status Patterns**
|
|
259
|
+
- Active statuses (active, enabled, verified)
|
|
260
|
+
- Inactive statuses (inactive, disabled, unverified)
|
|
261
|
+
- Suspended statuses (suspended, banned)
|
|
262
|
+
- Locked statuses (locked, frozen)
|
|
263
|
+
|
|
264
|
+
6. **Error Codes**
|
|
265
|
+
- Common error codes from API responses
|
|
266
|
+
- Error patterns from schema definitions
|
|
267
|
+
|
|
268
|
+
7. **File Upload Configuration**
|
|
269
|
+
- Presigned upload endpoints
|
|
270
|
+
- File size constraints
|
|
271
|
+
- Allowed file types
|
|
272
|
+
|
|
273
|
+
8. **Streaming Endpoints**
|
|
274
|
+
- SSE endpoints (text/event-stream)
|
|
275
|
+
- WebSocket endpoints (coming soon)
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## 📚 Configuration Options
|
|
280
|
+
|
|
281
|
+
### Framework Configuration
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
{
|
|
285
|
+
framework: {
|
|
286
|
+
type: 'nextjs',
|
|
287
|
+
version: '16.0.1',
|
|
288
|
+
router: 'app', // 'app' | 'pages'
|
|
289
|
+
features: {
|
|
290
|
+
serverActions: true,
|
|
291
|
+
middleware: true,
|
|
292
|
+
streaming: true,
|
|
293
|
+
revalidation: true
|
|
294
|
+
},
|
|
295
|
+
streaming: {
|
|
296
|
+
enabled: true, // Auto-detected if SSE endpoints exist
|
|
297
|
+
sse: {
|
|
298
|
+
enabled: true,
|
|
299
|
+
autoReconnect: true,
|
|
300
|
+
reconnectDelay: 3000,
|
|
301
|
+
maxReconnectAttempts: 5
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### API Configuration
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
{
|
|
312
|
+
api: {
|
|
313
|
+
baseUrl: 'https://api.example.com',
|
|
314
|
+
timeout: 30000,
|
|
315
|
+
retries: 3,
|
|
316
|
+
headers: {
|
|
317
|
+
'User-Agent': 'Mulink-Client/3.4.5',
|
|
318
|
+
'Accept': 'application/json'
|
|
319
|
+
},
|
|
320
|
+
errorHandling: {
|
|
321
|
+
enableAuthErrorHandling: true,
|
|
322
|
+
authErrorHandlerPath: '@/lib/auth-error-handler',
|
|
323
|
+
generateAuthErrorHandler: true // Auto-generated with intelligent error detection
|
|
324
|
+
},
|
|
325
|
+
customMiddleware: [
|
|
326
|
+
{
|
|
327
|
+
name: 'analytics',
|
|
328
|
+
importPath: '@/lib/analytics-middleware',
|
|
329
|
+
includeInDefault: true,
|
|
330
|
+
priority: 5
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Authentication Configuration (NextAuth 5.0)
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
{
|
|
341
|
+
auth: {
|
|
342
|
+
enabled: true,
|
|
343
|
+
provider: 'next-auth', // 'next-auth' | 'clerk' | 'custom'
|
|
344
|
+
authPath: '@/lib/auth',
|
|
345
|
+
tokenGetter: 'auth',
|
|
346
|
+
oauth: {
|
|
347
|
+
enabled: true,
|
|
348
|
+
providers: ['google', 'github'] // Auto-validated against schema
|
|
349
|
+
},
|
|
350
|
+
mfa: {
|
|
351
|
+
enabled: true // Auto-validated - only enabled if endpoints exist
|
|
352
|
+
},
|
|
353
|
+
passkeys: {
|
|
354
|
+
enabled: true // Auto-validated - only enabled if endpoints exist
|
|
355
|
+
},
|
|
356
|
+
session: {
|
|
357
|
+
strategy: 'jwt', // 'jwt' | 'database'
|
|
358
|
+
maxAge: 30 * 24 * 60 * 60 // 30 days
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Note:** mulink automatically validates OAuth providers, MFA, and Passkeys against your schema. Features not found in the schema will be automatically disabled with warnings.
|
|
365
|
+
|
|
366
|
+
### Upload Configuration
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
{
|
|
370
|
+
uploads: {
|
|
371
|
+
enabled: true,
|
|
372
|
+
strategy: 'presigned', // 'standard' | 'external' | 'presigned'
|
|
373
|
+
provider: 's3', // 'uploadthing' | 'vercel-blob' | 's3' | 'minio'
|
|
374
|
+
compression: {
|
|
375
|
+
enabled: true,
|
|
376
|
+
formats: ['webp', 'gzip']
|
|
377
|
+
},
|
|
378
|
+
security: {
|
|
379
|
+
maxSize: '100MB', // Auto-extracted from schema if available
|
|
380
|
+
allowedTypes: ['image/*', 'video/*'], // Auto-extracted from schema if available
|
|
381
|
+
scan: 'none'
|
|
382
|
+
},
|
|
383
|
+
presignedUploads: {
|
|
384
|
+
enabled: true, // Auto-validated - only enabled if endpoint exists
|
|
385
|
+
presignEndpoint: '/api/v1/files/presign-upload', // Auto-detected if not specified
|
|
386
|
+
fallbackToBackend: true
|
|
387
|
+
},
|
|
388
|
+
progressTracking: {
|
|
389
|
+
enabled: true,
|
|
390
|
+
useXHR: true
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 🎯 Usage Examples
|
|
399
|
+
|
|
400
|
+
### Basic Query Hook
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { useGetUser } from '@/generated/hooks/users'
|
|
404
|
+
|
|
405
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
406
|
+
const { data, isLoading, error } = useGetUser(userId, {
|
|
407
|
+
enabled: !!userId,
|
|
408
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
if (isLoading) return <div>Loading...</div>
|
|
412
|
+
if (error) return <div>Error: {error.message}</div>
|
|
413
|
+
|
|
414
|
+
return <div>{data?.data.name}</div>
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### Mutation Hook
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
import { useCreateUser } from '@/generated/hooks/users'
|
|
422
|
+
|
|
423
|
+
function CreateUserForm() {
|
|
424
|
+
const { mutate, isPending } = useCreateUser({
|
|
425
|
+
onSuccess: (data) => {
|
|
426
|
+
toast.success('User created!')
|
|
427
|
+
router.push(`/users/${data.data.id}`)
|
|
428
|
+
},
|
|
429
|
+
onError: (error) => {
|
|
430
|
+
toast.error(error.message)
|
|
431
|
+
}
|
|
432
|
+
})
|
|
433
|
+
|
|
434
|
+
const handleSubmit = (formData: FormData) => {
|
|
435
|
+
mutate({
|
|
436
|
+
name: formData.get('name'),
|
|
437
|
+
email: formData.get('email')
|
|
438
|
+
})
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return (
|
|
442
|
+
<form action={handleSubmit}>
|
|
443
|
+
{/* form fields */}
|
|
444
|
+
<button type="submit" disabled={isPending}>
|
|
445
|
+
{isPending ? 'Creating...' : 'Create User'}
|
|
446
|
+
</button>
|
|
447
|
+
</form>
|
|
448
|
+
)
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Server-Sent Events (SSE) - Auto-Detected
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
import { useStreamAnalysisUpdates } from '@/generated/hooks/analysis'
|
|
456
|
+
|
|
457
|
+
function AnalysisStatus({ resultId }: { resultId: string }) {
|
|
458
|
+
// Hook auto-generated if SSE endpoint exists in schema
|
|
459
|
+
const { isConnected, sseError, reconnect } = useStreamAnalysisUpdates(
|
|
460
|
+
resultId,
|
|
461
|
+
{
|
|
462
|
+
enabled: true,
|
|
463
|
+
onMessage: (data) => {
|
|
464
|
+
console.log('Update:', data)
|
|
465
|
+
// Handle real-time updates
|
|
466
|
+
},
|
|
467
|
+
onError: (error) => {
|
|
468
|
+
console.error('SSE Error:', error)
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
return (
|
|
474
|
+
<div>
|
|
475
|
+
<div>Status: {isConnected ? 'Connected' : 'Disconnected'}</div>
|
|
476
|
+
{sseError && (
|
|
477
|
+
<button onClick={reconnect}>Reconnect</button>
|
|
478
|
+
)}
|
|
479
|
+
</div>
|
|
480
|
+
)
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
**Features:**
|
|
485
|
+
- ✅ **Auto-detection** - mulink automatically detects SSE endpoints from OpenAPI schema
|
|
486
|
+
- ✅ **Auto-reconnect** - Automatic reconnection on connection loss
|
|
487
|
+
- ✅ **State Management** - Full connection state (isConnected, sseError, reconnect)
|
|
488
|
+
- ✅ **Event Handlers** - Support for onMessage, onError, onOpen
|
|
489
|
+
- ✅ **No Manual Setup** - Everything is auto-generated!
|
|
490
|
+
|
|
491
|
+
### File Upload with Presigned URLs - Auto-Validated
|
|
492
|
+
|
|
493
|
+
```typescript
|
|
494
|
+
import { usePredictDeepfakeUpload } from '@/generated/services/uploadPredictDeepfake'
|
|
495
|
+
|
|
496
|
+
function FileUploadForm() {
|
|
497
|
+
const [progress, setProgress] = useState(0)
|
|
498
|
+
|
|
499
|
+
// Hook auto-generated if upload endpoint exists
|
|
500
|
+
// Presigned uploads auto-enabled if presigned endpoint exists
|
|
501
|
+
const { mutate, isPending } = usePredictDeepfakeUpload({
|
|
502
|
+
onProgress: ({ percentage }) => {
|
|
503
|
+
setProgress(percentage)
|
|
504
|
+
},
|
|
505
|
+
onSuccess: (data) => {
|
|
506
|
+
toast.success('File uploaded successfully!')
|
|
507
|
+
console.log('Result:', data)
|
|
508
|
+
},
|
|
509
|
+
onError: (error) => {
|
|
510
|
+
toast.error(error.message)
|
|
511
|
+
},
|
|
512
|
+
uploadConfig: {
|
|
513
|
+
maxSize: '100MB', // Auto-extracted from schema
|
|
514
|
+
allowedTypes: ['video/*', 'image/*'], // Auto-extracted from schema
|
|
515
|
+
compression: {
|
|
516
|
+
enabled: true,
|
|
517
|
+
formats: ['webp']
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
})
|
|
521
|
+
|
|
522
|
+
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
523
|
+
const file = e.target.files?.[0]
|
|
524
|
+
if (file) {
|
|
525
|
+
mutate({ file })
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
return (
|
|
530
|
+
<div>
|
|
531
|
+
<input type="file" onChange={handleFileChange} />
|
|
532
|
+
{isPending && (
|
|
533
|
+
<div>
|
|
534
|
+
<progress value={progress} max={100} />
|
|
535
|
+
<span>{progress}%</span>
|
|
536
|
+
</div>
|
|
537
|
+
)}
|
|
538
|
+
</div>
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Features:**
|
|
544
|
+
- ✅ **Auto-detection** - Automatically detects presigned upload endpoints
|
|
545
|
+
- ✅ **Auto-validation** - Validates endpoint existence before enabling
|
|
546
|
+
- ✅ **Auto-fallback** - Falls back to backend upload if presigned fails
|
|
547
|
+
- ✅ **Progress Tracking** - Real-time upload progress
|
|
548
|
+
- ✅ **File Constraints** - Auto-extracted from schema
|
|
549
|
+
|
|
550
|
+
### NextAuth 5.0 with OAuth, MFA, and Passkeys
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
// lib/auth.ts (auto-generated by mulink)
|
|
554
|
+
import NextAuth from 'next-auth'
|
|
555
|
+
import { authOptions } from './auth-options' // Auto-generated
|
|
556
|
+
|
|
557
|
+
export const { handlers, auth, signIn, signOut } = NextAuth(authOptions)
|
|
558
|
+
|
|
559
|
+
// Usage in components
|
|
560
|
+
import { signIn, signOut } from '@/lib/auth'
|
|
561
|
+
|
|
562
|
+
// OAuth sign-in (auto-detected providers)
|
|
563
|
+
await signIn('google') // ✅ Only if Google OAuth exists in schema
|
|
564
|
+
await signIn('github') // ✅ Only if GitHub OAuth exists in schema
|
|
565
|
+
|
|
566
|
+
// MFA setup (auto-detected)
|
|
567
|
+
import { setupMFA } from '@/lib/auth/utils'
|
|
568
|
+
await setupMFA() // ✅ Only if MFA endpoints exist
|
|
569
|
+
|
|
570
|
+
// Passkeys (auto-detected)
|
|
571
|
+
import { registerPasskey, authenticateWithPasskey } from '@/lib/auth/passkeys'
|
|
572
|
+
await registerPasskey() // ✅ Only if Passkey endpoints exist
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
**Features:**
|
|
576
|
+
- ✅ **Auto-detected OAuth** - Only generates code for providers that exist
|
|
577
|
+
- ✅ **Auto-detected MFA** - Only enabled if MFA endpoints exist
|
|
578
|
+
- ✅ **Auto-detected Passkeys** - Only enabled if Passkey endpoints exist
|
|
579
|
+
- ✅ **Account Status Checking** - Auto-detected account status patterns
|
|
580
|
+
- ✅ **Error Handling** - Auto-detected error codes and patterns
|
|
581
|
+
|
|
582
|
+
### Direct API Client Usage
|
|
583
|
+
|
|
584
|
+
```typescript
|
|
585
|
+
import { apiClient } from '@/generated/client'
|
|
586
|
+
|
|
587
|
+
// In Server Component or Server Action
|
|
588
|
+
async function getUsers() {
|
|
589
|
+
const response = await apiClient.users.getUsers({
|
|
590
|
+
config: {
|
|
591
|
+
cacheTags: ['users'],
|
|
592
|
+
revalidate: 300
|
|
593
|
+
}
|
|
594
|
+
})
|
|
595
|
+
return response.data
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// With custom middleware
|
|
599
|
+
const response = await apiClient.users.getUsers({
|
|
600
|
+
config: {
|
|
601
|
+
middleware: [
|
|
602
|
+
{
|
|
603
|
+
name: 'custom-logging',
|
|
604
|
+
onRequest: async (config) => {
|
|
605
|
+
console.log('Request:', config)
|
|
606
|
+
return config
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
]
|
|
610
|
+
}
|
|
611
|
+
})
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
### Server Actions
|
|
615
|
+
|
|
616
|
+
```typescript
|
|
617
|
+
import { createUser } from '@/generated/actions/users'
|
|
618
|
+
|
|
619
|
+
// In Server Component
|
|
620
|
+
async function CreateUserButton() {
|
|
621
|
+
async function handleCreate(formData: FormData) {
|
|
622
|
+
'use server'
|
|
623
|
+
|
|
624
|
+
const result = await createUser({
|
|
625
|
+
name: formData.get('name'),
|
|
626
|
+
email: formData.get('email')
|
|
627
|
+
})
|
|
628
|
+
|
|
629
|
+
if (result?.serverError) {
|
|
630
|
+
return { error: result.serverError }
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
redirect(`/users/${result.data.id}`)
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return (
|
|
637
|
+
<form action={handleCreate}>
|
|
638
|
+
{/* form fields */}
|
|
639
|
+
</form>
|
|
640
|
+
)
|
|
641
|
+
}
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## 🔧 Advanced Configuration
|
|
647
|
+
|
|
648
|
+
### Custom Middleware
|
|
649
|
+
|
|
650
|
+
```typescript
|
|
651
|
+
// In link.config.json
|
|
652
|
+
{
|
|
653
|
+
"api": {
|
|
654
|
+
"customMiddleware": [
|
|
655
|
+
{
|
|
656
|
+
"name": "analytics",
|
|
657
|
+
"importPath": "@/lib/analytics-middleware",
|
|
658
|
+
"includeInDefault": true,
|
|
659
|
+
"priority": 1
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
"name": "custom-logging",
|
|
663
|
+
"importPath": "@/lib/custom-logging",
|
|
664
|
+
"includeInDefault": false,
|
|
665
|
+
"priority": 10
|
|
666
|
+
}
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### Custom Error Handlers
|
|
673
|
+
|
|
674
|
+
```typescript
|
|
675
|
+
// In link.config.json
|
|
676
|
+
{
|
|
677
|
+
"api": {
|
|
678
|
+
"errorHandling": {
|
|
679
|
+
"enableAuthErrorHandling": true,
|
|
680
|
+
"authErrorHandlerPath": "@/lib/custom-auth-error-handler",
|
|
681
|
+
"generateAuthErrorHandler": false, // Use your own handler
|
|
682
|
+
"customHandlers": {
|
|
683
|
+
"rateLimit": "@/lib/rate-limit-handler",
|
|
684
|
+
"validation": "@/lib/validation-handler"
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
**Note:** mulink auto-generates error handlers with intelligent error code and account status detection. You can override with custom handlers if needed.
|
|
692
|
+
|
|
693
|
+
### Type Mappings
|
|
694
|
+
|
|
695
|
+
```typescript
|
|
696
|
+
// In link.config.json
|
|
697
|
+
{
|
|
698
|
+
"typeMappings": {
|
|
699
|
+
"DateTime": "Date",
|
|
700
|
+
"UUID": "string",
|
|
701
|
+
"Money": "number",
|
|
702
|
+
"Email": "string"
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
---
|
|
708
|
+
|
|
709
|
+
## 🎨 Best Practices
|
|
710
|
+
|
|
711
|
+
### 1. Use React Query Hooks for Client Components
|
|
712
|
+
|
|
713
|
+
```typescript
|
|
714
|
+
// ✅ Good - Uses generated hook
|
|
715
|
+
'use client'
|
|
716
|
+
import { useGetUsers } from '@/generated/hooks/users'
|
|
717
|
+
|
|
718
|
+
function UsersList() {
|
|
719
|
+
const { data } = useGetUsers()
|
|
720
|
+
return <div>{/* render */}</div>
|
|
721
|
+
}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
### 2. Use Server Actions for Server Components
|
|
725
|
+
|
|
726
|
+
```typescript
|
|
727
|
+
// ✅ Good - Uses server action
|
|
728
|
+
import { getUsers } from '@/generated/actions/users'
|
|
729
|
+
|
|
730
|
+
async function UsersList() {
|
|
731
|
+
const users = await getUsers()
|
|
732
|
+
return <div>{/* render */}</div>
|
|
733
|
+
}
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### 3. Use Direct Client for Complex Scenarios
|
|
737
|
+
|
|
738
|
+
```typescript
|
|
739
|
+
// ✅ Good - Direct client for complex logic
|
|
740
|
+
import { apiClient } from '@/generated/client'
|
|
741
|
+
|
|
742
|
+
async function complexOperation() {
|
|
743
|
+
const users = await apiClient.users.getUsers()
|
|
744
|
+
const posts = await apiClient.posts.getPosts()
|
|
745
|
+
// Complex logic here
|
|
746
|
+
}
|
|
747
|
+
```
|
|
748
|
+
|
|
749
|
+
### 4. Configure Caching Properly
|
|
750
|
+
|
|
751
|
+
```typescript
|
|
752
|
+
// ✅ Good - Configure cache tags
|
|
753
|
+
const response = await apiClient.users.getUsers({
|
|
754
|
+
config: {
|
|
755
|
+
cacheTags: ['users', 'user-list'],
|
|
756
|
+
revalidate: 300
|
|
757
|
+
}
|
|
758
|
+
})
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
### 5. Handle Errors Gracefully
|
|
762
|
+
|
|
763
|
+
```typescript
|
|
764
|
+
// ✅ Good - Proper error handling
|
|
765
|
+
const { data, error } = useGetUsers({
|
|
766
|
+
onError: (error) => {
|
|
767
|
+
if (error.status === 401) {
|
|
768
|
+
router.push('/auth/signin')
|
|
769
|
+
} else {
|
|
770
|
+
toast.error(error.message)
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
})
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### 6. Trust mulink's Intelligence
|
|
777
|
+
|
|
778
|
+
```typescript
|
|
779
|
+
// ✅ Good - Let mulink auto-detect and validate
|
|
780
|
+
// mulink will:
|
|
781
|
+
// - Only generate code for features that exist
|
|
782
|
+
// - Warn you about missing endpoints
|
|
783
|
+
// - Auto-disable features not in schema
|
|
784
|
+
// - Extract constraints from schema
|
|
785
|
+
|
|
786
|
+
// Just configure what you want, mulink handles the rest!
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
---
|
|
790
|
+
|
|
791
|
+
## 🐛 Troubleshooting
|
|
792
|
+
|
|
793
|
+
### Common Issues
|
|
794
|
+
|
|
795
|
+
#### 1. Import Errors
|
|
796
|
+
|
|
797
|
+
**Problem**: `Cannot find module '@/generated/...'`
|
|
798
|
+
|
|
799
|
+
**Solution**: Make sure your `tsconfig.json` has the correct path mapping:
|
|
800
|
+
|
|
801
|
+
```json
|
|
802
|
+
{
|
|
803
|
+
"compilerOptions": {
|
|
804
|
+
"paths": {
|
|
805
|
+
"@/*": ["./src/*"],
|
|
806
|
+
"@/generated/*": ["./src/generated/*"]
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
#### 2. Auth Errors
|
|
813
|
+
|
|
814
|
+
**Problem**: Auth errors not being handled
|
|
815
|
+
|
|
816
|
+
**Solution**: Enable auth error handling in config:
|
|
817
|
+
|
|
818
|
+
```json
|
|
819
|
+
{
|
|
820
|
+
"api": {
|
|
821
|
+
"errorHandling": {
|
|
822
|
+
"enableAuthErrorHandling": true,
|
|
823
|
+
"generateAuthErrorHandler": true
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
#### 3. SSE Not Working
|
|
830
|
+
|
|
831
|
+
**Problem**: SSE connection fails
|
|
832
|
+
|
|
833
|
+
**Solution**: Check streaming configuration. mulink will warn you if SSE endpoints don't exist:
|
|
834
|
+
|
|
835
|
+
```json
|
|
836
|
+
{
|
|
837
|
+
"framework": {
|
|
838
|
+
"streaming": {
|
|
839
|
+
"enabled": true,
|
|
840
|
+
"sse": {
|
|
841
|
+
"enabled": true,
|
|
842
|
+
"autoReconnect": true
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
**Note:** mulink will automatically detect if SSE endpoints exist and warn you if they don't.
|
|
850
|
+
|
|
851
|
+
#### 4. Upload Progress Not Working
|
|
852
|
+
|
|
853
|
+
**Problem**: Upload progress not updating
|
|
854
|
+
|
|
855
|
+
**Solution**: Enable progress tracking:
|
|
856
|
+
|
|
857
|
+
```json
|
|
858
|
+
{
|
|
859
|
+
"uploads": {
|
|
860
|
+
"progressTracking": {
|
|
861
|
+
"enabled": true,
|
|
862
|
+
"useXHR": true
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
#### 5. Features Not Generated
|
|
869
|
+
|
|
870
|
+
**Problem**: OAuth/MFA/Passkeys not working
|
|
871
|
+
|
|
872
|
+
**Solution**: Check mulink warnings. mulink will warn you if endpoints don't exist:
|
|
873
|
+
|
|
874
|
+
```
|
|
875
|
+
⚠️ OAuth provider "discord" is configured but OAuth endpoints are not found in OpenAPI schema.
|
|
876
|
+
⚠️ MFA is enabled but MFA endpoints are not found in OpenAPI schema.
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
**Solution**: Make sure your OpenAPI schema includes the required endpoints, or remove the configuration for features that don't exist.
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
## 📖 API Reference
|
|
884
|
+
|
|
885
|
+
### Generated Client
|
|
886
|
+
|
|
887
|
+
```typescript
|
|
888
|
+
import { apiClient } from '@/generated/client'
|
|
889
|
+
|
|
890
|
+
// Get endpoint client
|
|
891
|
+
const usersClient = apiClient.users
|
|
892
|
+
|
|
893
|
+
// Make request
|
|
894
|
+
const response = await usersClient.getUser({ params: { id: '123' } })
|
|
895
|
+
|
|
896
|
+
// With options
|
|
897
|
+
const response = await usersClient.getUsers({
|
|
898
|
+
config: {
|
|
899
|
+
timeout: 5000,
|
|
900
|
+
retries: 2,
|
|
901
|
+
cacheTags: ['users']
|
|
902
|
+
}
|
|
903
|
+
})
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
### Generated Hooks
|
|
907
|
+
|
|
908
|
+
```typescript
|
|
909
|
+
import { useGetUser, useCreateUser } from '@/generated/hooks/users'
|
|
910
|
+
|
|
911
|
+
// Query hook
|
|
912
|
+
const { data, isLoading, error, refetch } = useGetUser('123', {
|
|
913
|
+
enabled: true,
|
|
914
|
+
staleTime: 5 * 60 * 1000
|
|
915
|
+
})
|
|
916
|
+
|
|
917
|
+
// Mutation hook
|
|
918
|
+
const { mutate, isPending } = useCreateUser({
|
|
919
|
+
onSuccess: (data) => console.log(data),
|
|
920
|
+
onError: (error) => console.error(error)
|
|
921
|
+
})
|
|
922
|
+
```
|
|
923
|
+
|
|
924
|
+
### Generated Actions
|
|
925
|
+
|
|
926
|
+
```typescript
|
|
927
|
+
import { getUser, createUser } from '@/generated/actions/users'
|
|
928
|
+
|
|
929
|
+
// In server component or server action
|
|
930
|
+
const user = await getUser({ params: { id: '123' } })
|
|
931
|
+
const newUser = await createUser({ name: 'John', email: 'john@example.com' })
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### Generated Auth (NextAuth 5.0)
|
|
935
|
+
|
|
936
|
+
```typescript
|
|
937
|
+
import { signIn, signOut, auth } from '@/lib/auth'
|
|
938
|
+
import { setupMFA, verifyMFA } from '@/lib/auth/utils'
|
|
939
|
+
import { registerPasskey, authenticateWithPasskey } from '@/lib/auth/passkeys'
|
|
940
|
+
|
|
941
|
+
// OAuth sign-in (auto-detected providers)
|
|
942
|
+
await signIn('google')
|
|
943
|
+
await signIn('github')
|
|
944
|
+
|
|
945
|
+
// MFA (auto-detected)
|
|
946
|
+
await setupMFA()
|
|
947
|
+
await verifyMFA({ code: '123456' })
|
|
948
|
+
|
|
949
|
+
// Passkeys (auto-detected)
|
|
950
|
+
await registerPasskey()
|
|
951
|
+
await authenticateWithPasskey()
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
## 🧠 How Intelligence Works
|
|
957
|
+
|
|
958
|
+
### Schema Analysis Process
|
|
959
|
+
|
|
960
|
+
1. **Endpoint Detection**
|
|
961
|
+
- Scans all endpoints in OpenAPI schema
|
|
962
|
+
- Matches patterns (path, operationId, content-type)
|
|
963
|
+
- Extracts authentication, OAuth, MFA, Passkey endpoints
|
|
964
|
+
|
|
965
|
+
2. **Configuration Validation**
|
|
966
|
+
- Compares your configuration with detected endpoints
|
|
967
|
+
- Warns about missing endpoints
|
|
968
|
+
- Auto-disables features not in schema
|
|
969
|
+
|
|
970
|
+
3. **Pattern Extraction**
|
|
971
|
+
- Extracts account status patterns from schema definitions
|
|
972
|
+
- Extracts error codes from API responses
|
|
973
|
+
- Extracts file constraints from upload endpoints
|
|
974
|
+
|
|
975
|
+
4. **Code Generation**
|
|
976
|
+
- Only generates code for validated features
|
|
977
|
+
- Includes intelligent error handling
|
|
978
|
+
- Adds account status checking where detected
|
|
979
|
+
|
|
980
|
+
### Example: OAuth Auto-Detection
|
|
981
|
+
|
|
982
|
+
```typescript
|
|
983
|
+
// Your OpenAPI schema has:
|
|
984
|
+
// GET /auth/oauth/authorize/{provider}
|
|
985
|
+
// POST /auth/oauth/callback
|
|
986
|
+
|
|
987
|
+
// mulink detects:
|
|
988
|
+
const detectedProviders = ['google', 'github'] // From paths
|
|
989
|
+
|
|
990
|
+
// Your config:
|
|
991
|
+
{
|
|
992
|
+
"oauth": {
|
|
993
|
+
"providers": ["google", "github", "discord"]
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// mulink validates:
|
|
998
|
+
✅ google - exists in schema
|
|
999
|
+
✅ github - exists in schema
|
|
1000
|
+
❌ discord - not found, warns and excludes
|
|
1001
|
+
|
|
1002
|
+
// Generated code only includes google and github
|
|
1003
|
+
```
|
|
1004
|
+
|
|
1005
|
+
---
|
|
1006
|
+
|
|
1007
|
+
## 🤝 Contributing
|
|
1008
|
+
|
|
1009
|
+
Contributions are welcome! Please read our contributing guidelines first.
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
## 📄 License
|
|
1014
|
+
|
|
1015
|
+
MIT License - see LICENSE file for details.
|
|
1016
|
+
|
|
1017
|
+
---
|
|
1018
|
+
|
|
1019
|
+
## 🙏 Acknowledgments
|
|
1020
|
+
|
|
1021
|
+
- Built for Next.js 16+
|
|
1022
|
+
- Uses React Query for data fetching
|
|
1023
|
+
- Uses Zod for validation
|
|
1024
|
+
- Uses TypeScript for type safety
|
|
1025
|
+
- Uses NextAuth 5.0 for authentication
|
|
1026
|
+
|
|
1027
|
+
---
|
|
1028
|
+
|
|
1029
|
+
**Made with ❤️ by the Mulverse team**
|
|
1030
|
+
|
|
1031
|
+
**Version 3.4.7** - Intelligent API Client Generator
|