@donkeylabs/server 2.0.19 → 2.0.21
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/docs/caching-strategies.md +677 -0
- package/docs/dev-experience.md +656 -0
- package/docs/hot-reload-limitations.md +166 -0
- package/docs/load-testing.md +974 -0
- package/docs/plugin-registry-design.md +1064 -0
- package/docs/production.md +1229 -0
- package/docs/workflows.md +90 -3
- package/package.json +1 -1
- package/src/admin/routes.ts +153 -0
- package/src/core/cron.ts +90 -9
- package/src/core/index.ts +31 -0
- package/src/core/job-adapter-kysely.ts +176 -73
- package/src/core/job-adapter-sqlite.ts +10 -0
- package/src/core/jobs.ts +112 -17
- package/src/core/migrations/workflows/002_add_metadata_column.ts +28 -0
- package/src/core/process-adapter-kysely.ts +62 -21
- package/src/core/storage-adapter-local.test.ts +199 -0
- package/src/core/storage.test.ts +197 -0
- package/src/core/workflow-adapter-kysely.ts +66 -19
- package/src/core/workflow-executor.ts +239 -0
- package/src/core/workflow-proxy.ts +238 -0
- package/src/core/workflow-socket.ts +449 -0
- package/src/core/workflow-state-machine.ts +593 -0
- package/src/core/workflows.test.ts +758 -0
- package/src/core/workflows.ts +705 -595
- package/src/core.ts +17 -6
- package/src/index.ts +14 -0
- package/src/testing/database.test.ts +263 -0
- package/src/testing/database.ts +173 -0
- package/src/testing/e2e.test.ts +189 -0
- package/src/testing/e2e.ts +272 -0
- package/src/testing/index.ts +18 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
# Development Experience Guide
|
|
2
|
+
|
|
3
|
+
This guide covers the development workflow, hot reload system, and tooling for DonkeyLabs framework.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Hot Reload System](#hot-reload-system)
|
|
8
|
+
- [Dev Server Modes](#dev-server-modes)
|
|
9
|
+
- [File Watching](#file-watching)
|
|
10
|
+
- [Type Generation](#type-generation)
|
|
11
|
+
- [Debugging Utilities](#debugging-utilities)
|
|
12
|
+
- [Performance Optimization](#performance-optimization)
|
|
13
|
+
- [VS Code Integration](#vs-code-integration)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Hot Reload System
|
|
18
|
+
|
|
19
|
+
The framework provides sophisticated hot reload capabilities that dramatically speed up development.
|
|
20
|
+
|
|
21
|
+
### What Gets Hot Reloaded
|
|
22
|
+
|
|
23
|
+
| Component | Hot Reload Support | Trigger | Notes |
|
|
24
|
+
|-----------|-------------------|---------|-------|
|
|
25
|
+
| Route handlers | ✅ Yes | File save in routes/ | Instant, no server restart |
|
|
26
|
+
| Route schemas | ✅ Yes | File save | Requires type regeneration |
|
|
27
|
+
| Plugin service methods | ⚠️ Partial | File save | Type regen needed for full typing |
|
|
28
|
+
| Plugin structure changes | ❌ No | N/A | Requires full restart |
|
|
29
|
+
| Middleware | ✅ Yes | File save | Instant |
|
|
30
|
+
| Database migrations | ⚠️ Partial | Migration added | Auto-runs migration + type gen |
|
|
31
|
+
| Generated types | ✅ Auto | Source changes | Triggered by file watcher |
|
|
32
|
+
|
|
33
|
+
### How Hot Reload Works
|
|
34
|
+
|
|
35
|
+
**In-Process Mode** (`bun --bun run dev`):
|
|
36
|
+
|
|
37
|
+
1. Vite's file watcher detects changes in `src/server/`
|
|
38
|
+
2. Route files are identified by glob pattern `**/routes/**/*.ts`
|
|
39
|
+
3. Changed module is invalidated in Vite's cache
|
|
40
|
+
4. Module is re-imported with cache-busting query param
|
|
41
|
+
5. `appServer.reloadRouter(prefix, newRouter)` updates the route map
|
|
42
|
+
6. Changes are immediately available without restart
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// From packages/adapter-sveltekit/src/vite.ts
|
|
46
|
+
async function hotReloadRoute(filepath: string) {
|
|
47
|
+
// 1. Invalidate Vite module cache
|
|
48
|
+
const mod = viteServer.moduleGraph.getModuleById(filepath);
|
|
49
|
+
if (mod) viteServer.moduleGraph.invalidateModule(mod);
|
|
50
|
+
|
|
51
|
+
// 2. Re-import with timestamp
|
|
52
|
+
const freshModule = await viteServer.ssrLoadModule(`${filepath}?t=${Date.now()}`);
|
|
53
|
+
|
|
54
|
+
// 3. Extract router from exports
|
|
55
|
+
let newRouter = freshModule.router || freshModule.default;
|
|
56
|
+
|
|
57
|
+
// 4. Hot swap in app server
|
|
58
|
+
if (newRouter && prefix) {
|
|
59
|
+
appServer.reloadRouter(prefix, newRouter);
|
|
60
|
+
console.log("[donkeylabs-dev] Route hot reload complete:", prefix);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Hot Reload Limitations
|
|
66
|
+
|
|
67
|
+
**Plugin structure changes** (adding new methods, changing signatures):
|
|
68
|
+
- Changes require full type regeneration
|
|
69
|
+
- May need server restart if plugin initialization changed
|
|
70
|
+
- Run `bun run gen:types` after structure changes
|
|
71
|
+
|
|
72
|
+
**Database schema changes**:
|
|
73
|
+
- Migrations are detected and auto-run
|
|
74
|
+
- Schema types are regenerated
|
|
75
|
+
- But plugin may need restart to see new table types
|
|
76
|
+
|
|
77
|
+
**Configuration changes**:
|
|
78
|
+
- `donkeylabs.config.ts` changes require restart
|
|
79
|
+
- Environment variable changes require restart
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Dev Server Modes
|
|
84
|
+
|
|
85
|
+
The framework supports two development server modes:
|
|
86
|
+
|
|
87
|
+
### In-Process Mode (Recommended)
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
bun --bun run dev
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Architecture:**
|
|
94
|
+
```
|
|
95
|
+
┌─────────────────────────────────────────────┐
|
|
96
|
+
│ Vite Dev Server │
|
|
97
|
+
│ ┌──────────────────────────────────────┐ │
|
|
98
|
+
│ │ @donkeylabs/server (in-process) │ │
|
|
99
|
+
│ │ - Runs in same Bun process │ │
|
|
100
|
+
│ │ - Shares event loop with Vite │ │
|
|
101
|
+
│ │ - Direct middleware integration │ │
|
|
102
|
+
│ └──────────────────────────────────────┘ │
|
|
103
|
+
│ ┌──────────────────────────────────────┐ │
|
|
104
|
+
│ │ SvelteKit (Vite plugin) │ │
|
|
105
|
+
│ └──────────────────────────────────────┘ │
|
|
106
|
+
└─────────────────────────────────────────────┘
|
|
107
|
+
↓ Single port (e.g., 5173)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Advantages:**
|
|
111
|
+
- 🚀 **Fastest performance**: No inter-process communication
|
|
112
|
+
- 🔄 **Full hot reload**: All features work
|
|
113
|
+
- 📦 **Single port**: No CORS, no proxy issues
|
|
114
|
+
- 🧠 **Shared memory**: SSR can directly call server methods
|
|
115
|
+
- ⚡ **Instant startup**: No process spawning
|
|
116
|
+
|
|
117
|
+
**How it works:**
|
|
118
|
+
1. Vite loads the `@donkeylabs/adapter-sveltekit` plugin
|
|
119
|
+
2. Plugin detects Bun runtime (`typeof globalThis.Bun !== "undefined"`)
|
|
120
|
+
3. Server entry file is imported directly (not spawned)
|
|
121
|
+
4. Server initializes but doesn't start HTTP server
|
|
122
|
+
5. Vite middleware stack gets custom handler for API routes
|
|
123
|
+
6. API requests are handled in-process via middleware
|
|
124
|
+
|
|
125
|
+
### Subprocess Mode (Fallback)
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
bun run dev
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**Architecture:**
|
|
132
|
+
```
|
|
133
|
+
┌─────────────────────────────────────────────┐
|
|
134
|
+
│ Vite Dev Server │
|
|
135
|
+
│ ┌──────────────────────────────────────┐ │
|
|
136
|
+
│ │ SvelteKit (Vite plugin) │ │
|
|
137
|
+
│ └──────────────────────────────────────┘ │
|
|
138
|
+
│ ┌──────────────────────────────────────┐ │
|
|
139
|
+
│ │ Proxy Middleware (port 5173) │ │
|
|
140
|
+
│ │ - Intercepts /api/* requests │ │
|
|
141
|
+
│ │ - Forwards to backend process │ │
|
|
142
|
+
│ └──────────────────────────────────────┘ │
|
|
143
|
+
└─────────────────────────────────────────────┘
|
|
144
|
+
↓ HTTP Proxy
|
|
145
|
+
┌─────────────────────────────────────────────┐
|
|
146
|
+
│ Backend Server (port 3001) │
|
|
147
|
+
│ ┌──────────────────────────────────────┐ │
|
|
148
|
+
│ │ @donkeylabs/server (subprocess) │ │
|
|
149
|
+
│ │ - Spawned via Bun child_process │ │
|
|
150
|
+
│ │ - Runs full HTTP server │ │
|
|
151
|
+
│ └──────────────────────────────────────┘ │
|
|
152
|
+
└─────────────────────────────────────────────┘
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Use when:**
|
|
156
|
+
- Not using Bun runtime
|
|
157
|
+
- Debugging backend separately
|
|
158
|
+
- Need isolated backend process
|
|
159
|
+
|
|
160
|
+
**Limitations:**
|
|
161
|
+
- Requires two ports
|
|
162
|
+
- Proxy overhead
|
|
163
|
+
- Hot reload works but is slower
|
|
164
|
+
- SSR calls require HTTP instead of direct
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## File Watching
|
|
169
|
+
|
|
170
|
+
The framework has multiple file watchers for different purposes:
|
|
171
|
+
|
|
172
|
+
### 1. Route/Type Watcher (Vite Plugin)
|
|
173
|
+
|
|
174
|
+
**Location:** `packages/adapter-sveltekit/src/vite.ts`
|
|
175
|
+
|
|
176
|
+
**Watches:** `src/server/**/*.ts` (configurable)
|
|
177
|
+
|
|
178
|
+
**Triggers:**
|
|
179
|
+
- Route file changes → Hot reload
|
|
180
|
+
- Any `.ts` file → Type regeneration
|
|
181
|
+
|
|
182
|
+
**Config:**
|
|
183
|
+
```typescript
|
|
184
|
+
// vite.config.ts
|
|
185
|
+
donkeylabsDev({
|
|
186
|
+
watchDir: "./src/server", // Watch this directory
|
|
187
|
+
watchTypes: true, // Auto-generate types
|
|
188
|
+
hotReloadRoutes: true, // Enable hot reload
|
|
189
|
+
routePatterns: ["**/routes/**/*.ts"], // Route file glob
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 2. Plugin Watcher (CLI Script)
|
|
194
|
+
|
|
195
|
+
**Location:** `packages/cli/scripts/watcher.ts`
|
|
196
|
+
|
|
197
|
+
**Usage:**
|
|
198
|
+
```bash
|
|
199
|
+
# Watch a specific plugin for changes
|
|
200
|
+
bun scripts/watcher.ts users
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**Watches:** Individual plugin directory
|
|
204
|
+
|
|
205
|
+
**Triggers:**
|
|
206
|
+
- `migrations/*.ts` changes → Generate schema types
|
|
207
|
+
- `index.ts` changes → Regenerate registry
|
|
208
|
+
|
|
209
|
+
**Why use it:**
|
|
210
|
+
- Focused watching for plugin development
|
|
211
|
+
- Prevents unnecessary type regeneration
|
|
212
|
+
- Better performance than full watcher
|
|
213
|
+
|
|
214
|
+
### 3. Migration Watcher
|
|
215
|
+
|
|
216
|
+
**Triggers:**
|
|
217
|
+
- New migration file created
|
|
218
|
+
- Migration modified
|
|
219
|
+
|
|
220
|
+
**Actions:**
|
|
221
|
+
1. Runs `bun scripts/generate-types.ts <plugin>`
|
|
222
|
+
2. Generates `schema.ts` with Kysely types
|
|
223
|
+
3. Updates plugin `index.ts` to import schema
|
|
224
|
+
4. Regenerates registry
|
|
225
|
+
|
|
226
|
+
**Debouncing:**
|
|
227
|
+
- 500ms debounce to batch rapid changes
|
|
228
|
+
- 2s cooldown after generation to prevent loops
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Type Generation
|
|
233
|
+
|
|
234
|
+
Type generation is automatic but can be triggered manually:
|
|
235
|
+
|
|
236
|
+
### Auto-Generation (Dev Mode)
|
|
237
|
+
|
|
238
|
+
**Triggers:**
|
|
239
|
+
- File changes in watched directories
|
|
240
|
+
- Migration file added
|
|
241
|
+
- Plugin structure modified
|
|
242
|
+
|
|
243
|
+
**Generated files:**
|
|
244
|
+
- `registry.d.ts` - Plugin registry types
|
|
245
|
+
- `context.d.ts` - App context with merged schemas
|
|
246
|
+
- `routes.ts` - Route input/output types
|
|
247
|
+
- `client.ts` or `api.ts` - API client
|
|
248
|
+
|
|
249
|
+
### Manual Generation
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Generate all types
|
|
253
|
+
bun run gen:types
|
|
254
|
+
|
|
255
|
+
# Or via CLI
|
|
256
|
+
bunx donkeylabs generate
|
|
257
|
+
|
|
258
|
+
# Generate for specific plugin
|
|
259
|
+
bun scripts/generate-types.ts users
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Generation Pipeline
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
1. Parse all plugin index.ts files
|
|
266
|
+
↓
|
|
267
|
+
2. Extract schema types (if withSchema used)
|
|
268
|
+
↓
|
|
269
|
+
3. Merge schemas from all plugins
|
|
270
|
+
↓
|
|
271
|
+
4. Generate registry.d.ts (PluginRegistry augmentation)
|
|
272
|
+
↓
|
|
273
|
+
5. Generate context.d.ts (GlobalContext with merged DB)
|
|
274
|
+
↓
|
|
275
|
+
6. Extract route definitions from route files
|
|
276
|
+
↓
|
|
277
|
+
7. Generate route types (input/output validation)
|
|
278
|
+
↓
|
|
279
|
+
8. Generate API client with full typing
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Time:** ~1-3 seconds for typical project
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Debugging Utilities
|
|
287
|
+
|
|
288
|
+
### Debug Logging
|
|
289
|
+
|
|
290
|
+
Enable detailed logging:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// src/server/index.ts
|
|
294
|
+
const server = new AppServer({
|
|
295
|
+
logger: { level: "debug" },
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Log prefixes:**
|
|
300
|
+
- `[donkeylabs-dev]` - Dev server activity
|
|
301
|
+
- `[donkeylabs-hot-reload]` - Hot reload events
|
|
302
|
+
- `[plugin-name]` - Plugin-specific logs
|
|
303
|
+
|
|
304
|
+
### Dev Server Logs
|
|
305
|
+
|
|
306
|
+
When running `bun --bun run dev`:
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
[donkeylabs-dev] Starting in-process mode (Bun runtime detected)
|
|
310
|
+
[donkeylabs-dev] Watching src/server for type generation, hot reload...
|
|
311
|
+
[donkeylabs-dev] Server initialized (in-process mode)
|
|
312
|
+
[donkeylabs-dev] Ready at http://localhost:5173
|
|
313
|
+
|
|
314
|
+
[donkeylabs-dev] Hot reloading route: /src/server/routes/users/index.ts
|
|
315
|
+
[donkeylabs-dev] Route hot reload complete: users
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Inspecting Hot Reload
|
|
319
|
+
|
|
320
|
+
To debug hot reload issues:
|
|
321
|
+
|
|
322
|
+
1. **Check mode:**
|
|
323
|
+
```bash
|
|
324
|
+
bun --bun run dev # Should show "in-process mode"
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
2. **Verify file pattern:**
|
|
328
|
+
Your route files should match the pattern:
|
|
329
|
+
```typescript
|
|
330
|
+
// Default: **/routes/**/*.ts
|
|
331
|
+
src/server/routes/users/index.ts ✅
|
|
332
|
+
src/server/plugins/users/index.ts ❌ (not a route)
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
3. **Check console:**
|
|
336
|
+
Look for `[donkeylabs-dev]` messages
|
|
337
|
+
|
|
338
|
+
4. **Manual test:**
|
|
339
|
+
```typescript
|
|
340
|
+
// Add to route file
|
|
341
|
+
console.log("Route loaded:", Date.now());
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Performance Optimization
|
|
347
|
+
|
|
348
|
+
### Dev Server Performance
|
|
349
|
+
|
|
350
|
+
**Fastest setup:**
|
|
351
|
+
```bash
|
|
352
|
+
# Use Bun runtime
|
|
353
|
+
bun --bun run dev
|
|
354
|
+
|
|
355
|
+
# Disable type watching if not needed (rare)
|
|
356
|
+
donkeylabsDev({ watchTypes: false })
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Slowdown causes:**
|
|
360
|
+
1. Subprocess mode (proxy overhead)
|
|
361
|
+
2. Type regeneration on every save (debounced but still frequent)
|
|
362
|
+
3. Too many plugins (increases init time)
|
|
363
|
+
4. Complex middleware chains
|
|
364
|
+
|
|
365
|
+
### Type Generation Performance
|
|
366
|
+
|
|
367
|
+
**Fast:**
|
|
368
|
+
- Few plugins (< 10)
|
|
369
|
+
- Simple schemas
|
|
370
|
+
- SSD storage
|
|
371
|
+
|
|
372
|
+
**Slow:**
|
|
373
|
+
- Many plugins (> 20)
|
|
374
|
+
- Complex type definitions
|
|
375
|
+
- Network drives
|
|
376
|
+
|
|
377
|
+
**Optimization:**
|
|
378
|
+
- Use plugin watcher for focused work
|
|
379
|
+
- Commit generated types to avoid regeneration
|
|
380
|
+
- Skip validation in dev: `skipLibCheck: true`
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## VS Code Integration
|
|
385
|
+
|
|
386
|
+
### Recommended Extensions
|
|
387
|
+
|
|
388
|
+
1. **Svelte for VS Code** - Svelte/SvelteKit support
|
|
389
|
+
2. **TypeScript Importer** - Auto-import types
|
|
390
|
+
3. **Error Lens** - Inline error display
|
|
391
|
+
4. **TODO Highlight** - Mark todos in code
|
|
392
|
+
|
|
393
|
+
### VS Code Extension Opportunities
|
|
394
|
+
|
|
395
|
+
A custom DonkeyLabs VS Code extension could provide:
|
|
396
|
+
|
|
397
|
+
#### 1. Code Snippets
|
|
398
|
+
|
|
399
|
+
**Plugin snippet:**
|
|
400
|
+
```json
|
|
401
|
+
{
|
|
402
|
+
"DonkeyLabs Plugin": {
|
|
403
|
+
"prefix": "plugin",
|
|
404
|
+
"body": [
|
|
405
|
+
"export const ${1:name}Plugin = createPlugin",
|
|
406
|
+
" .withSchema<${2:Schema}>()",
|
|
407
|
+
" .define({",
|
|
408
|
+
" name: '${1:name}',",
|
|
409
|
+
" service: async (ctx) => ({",
|
|
410
|
+
" $3",
|
|
411
|
+
" }),",
|
|
412
|
+
" });"
|
|
413
|
+
]
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
**Route snippet:**
|
|
419
|
+
```json
|
|
420
|
+
{
|
|
421
|
+
"DonkeyLabs Route": {
|
|
422
|
+
"prefix": "route",
|
|
423
|
+
"body": [
|
|
424
|
+
"router.route('${1:name}').typed(defineRoute({",
|
|
425
|
+
" input: ${2:inputSchema},",
|
|
426
|
+
" output: ${3:outputSchema},",
|
|
427
|
+
" handle: async (input, ctx) => {",
|
|
428
|
+
" $4",
|
|
429
|
+
" },",
|
|
430
|
+
"}));"
|
|
431
|
+
]
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
#### 2. Go to Definition
|
|
437
|
+
|
|
438
|
+
**Route → Plugin:**
|
|
439
|
+
- Click on `ctx.plugins.users.getById`
|
|
440
|
+
- Jump to plugin service method definition
|
|
441
|
+
|
|
442
|
+
**Implementation:**
|
|
443
|
+
```typescript
|
|
444
|
+
// VS Code extension
|
|
445
|
+
vscode.languages.registerDefinitionProvider('typescript', {
|
|
446
|
+
provideDefinition(document, position) {
|
|
447
|
+
// Detect ctx.plugins.* pattern
|
|
448
|
+
// Resolve plugin path from registry
|
|
449
|
+
// Return Location to plugin method
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### 3. Auto-Import
|
|
455
|
+
|
|
456
|
+
**Context-aware suggestions:**
|
|
457
|
+
- Type `ctx.plugins.` → Suggest all available plugins
|
|
458
|
+
- Type `ctx.core.` → Suggest core services
|
|
459
|
+
- Type `router.` → Suggest middleware methods
|
|
460
|
+
|
|
461
|
+
#### 4. Type Hints
|
|
462
|
+
|
|
463
|
+
**Show generated types inline:**
|
|
464
|
+
```typescript
|
|
465
|
+
// Hover shows:
|
|
466
|
+
// (property) users: {
|
|
467
|
+
// getById: (id: string) => Promise<User | undefined>
|
|
468
|
+
// create: (data: CreateUserInput) => Promise<User>
|
|
469
|
+
// }
|
|
470
|
+
ctx.plugins.users
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### 5. Status Bar
|
|
474
|
+
|
|
475
|
+
**Display:**
|
|
476
|
+
- ⏳ Type generation in progress
|
|
477
|
+
- ✅ Types up to date
|
|
478
|
+
- 🔄 Hot reload active
|
|
479
|
+
- 🌡️ Backend status (in-process/subprocess)
|
|
480
|
+
|
|
481
|
+
**Click actions:**
|
|
482
|
+
- Regenerate types
|
|
483
|
+
- Restart dev server
|
|
484
|
+
- Toggle hot reload
|
|
485
|
+
|
|
486
|
+
#### 6. Commands
|
|
487
|
+
|
|
488
|
+
**Command palette:**
|
|
489
|
+
- `DonkeyLabs: Generate Types`
|
|
490
|
+
- `DonkeyLabs: Create Plugin`
|
|
491
|
+
- `DonkeyLabs: Add Migration`
|
|
492
|
+
- `DonkeyLabs: Restart Dev Server`
|
|
493
|
+
|
|
494
|
+
#### 7. File Explorer Integration
|
|
495
|
+
|
|
496
|
+
**Context menus:**
|
|
497
|
+
- Right-click on `plugins/` folder → "Create Plugin"
|
|
498
|
+
- Right-click on plugin folder → "Add Migration"
|
|
499
|
+
- Right-click on route file → "Add Route Handler"
|
|
500
|
+
|
|
501
|
+
#### 8. Error Diagnostics
|
|
502
|
+
|
|
503
|
+
**Custom linting:**
|
|
504
|
+
- Warn about raw SQL in migrations
|
|
505
|
+
- Detect missing type regeneration
|
|
506
|
+
- Flag business logic in routes
|
|
507
|
+
- Check plugin dependency cycles
|
|
508
|
+
|
|
509
|
+
### Implementation Approach
|
|
510
|
+
|
|
511
|
+
**Option 1: Language Server Protocol (LSP)**
|
|
512
|
+
- Full IDE integration
|
|
513
|
+
- Real-time type checking
|
|
514
|
+
- Complex to implement
|
|
515
|
+
|
|
516
|
+
**Option 2: VS Code Extension API**
|
|
517
|
+
- Simpler implementation
|
|
518
|
+
- Good enough for most features
|
|
519
|
+
- Can use existing TypeScript compiler API
|
|
520
|
+
|
|
521
|
+
**Priority features:**
|
|
522
|
+
1. Code snippets (easy win)
|
|
523
|
+
2. Status bar indicator
|
|
524
|
+
3. Commands palette integration
|
|
525
|
+
4. Go to definition (high value)
|
|
526
|
+
5. Auto-import (high value)
|
|
527
|
+
6. Diagnostics (nice to have)
|
|
528
|
+
|
|
529
|
+
### Example Extension Structure
|
|
530
|
+
|
|
531
|
+
```
|
|
532
|
+
donkeylabs-vscode/
|
|
533
|
+
├── package.json
|
|
534
|
+
├── src/
|
|
535
|
+
│ ├── extension.ts # Main entry
|
|
536
|
+
│ ├── providers/
|
|
537
|
+
│ │ ├── definition.ts # Go to definition
|
|
538
|
+
│ │ ├── completion.ts # Auto-complete
|
|
539
|
+
│ │ └── diagnostics.ts # Linting
|
|
540
|
+
│ ├── commands/
|
|
541
|
+
│ │ ├── generateTypes.ts
|
|
542
|
+
│ │ ├── createPlugin.ts
|
|
543
|
+
│ │ └── addMigration.ts
|
|
544
|
+
│ └── status/
|
|
545
|
+
│ └── bar.ts # Status bar
|
|
546
|
+
└── snippets/
|
|
547
|
+
├── plugin.json
|
|
548
|
+
├── route.json
|
|
549
|
+
└── migration.json
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Troubleshooting
|
|
555
|
+
|
|
556
|
+
### Hot Reload Not Working
|
|
557
|
+
|
|
558
|
+
**Symptoms:** Changes don't appear after save
|
|
559
|
+
|
|
560
|
+
**Checklist:**
|
|
561
|
+
1. ✅ Using `bun --bun run dev`
|
|
562
|
+
2. ✅ File is in `src/server/routes/`
|
|
563
|
+
3. ✅ File matches pattern `**/routes/**/*.ts`
|
|
564
|
+
4. ✅ No TypeScript errors in file
|
|
565
|
+
5. ✅ Console shows `[donkeylabs-dev]` messages
|
|
566
|
+
|
|
567
|
+
**Fixes:**
|
|
568
|
+
```bash
|
|
569
|
+
# Restart dev server
|
|
570
|
+
Ctrl+C && bun --bun run dev
|
|
571
|
+
|
|
572
|
+
# Manual type regeneration
|
|
573
|
+
bun run gen:types
|
|
574
|
+
|
|
575
|
+
# Check file pattern
|
|
576
|
+
grep "routePatterns" vite.config.ts
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Types Not Updating
|
|
580
|
+
|
|
581
|
+
**Symptoms:** `api.ts` shows old types
|
|
582
|
+
|
|
583
|
+
**Causes:**
|
|
584
|
+
1. Type generation skipped due to cooldown
|
|
585
|
+
2. Plugin has TypeScript errors
|
|
586
|
+
3. Migration doesn't compile
|
|
587
|
+
|
|
588
|
+
**Fix:**
|
|
589
|
+
```bash
|
|
590
|
+
# Force regeneration
|
|
591
|
+
bun run gen:types
|
|
592
|
+
|
|
593
|
+
# Check for errors
|
|
594
|
+
bun --bun tsc --noEmit
|
|
595
|
+
|
|
596
|
+
# Regenerate specific plugin
|
|
597
|
+
bun scripts/generate-types.ts <plugin-name>
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Slow Dev Server
|
|
601
|
+
|
|
602
|
+
**Symptoms:** Long startup, slow requests
|
|
603
|
+
|
|
604
|
+
**Causes:**
|
|
605
|
+
1. Using subprocess mode
|
|
606
|
+
2. Too many plugins initializing
|
|
607
|
+
3. Slow database connection
|
|
608
|
+
4. Heavy middleware chains
|
|
609
|
+
|
|
610
|
+
**Fix:**
|
|
611
|
+
```bash
|
|
612
|
+
# Switch to in-process
|
|
613
|
+
bun --bun run dev
|
|
614
|
+
|
|
615
|
+
# Check plugin count
|
|
616
|
+
ls -1 src/server/plugins/ | wc -l
|
|
617
|
+
|
|
618
|
+
# Profile startup
|
|
619
|
+
DEBUG=* bun --bun run dev
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### "Cannot find module" Errors
|
|
623
|
+
|
|
624
|
+
**Causes:**
|
|
625
|
+
1. Types not generated
|
|
626
|
+
2. Import path wrong
|
|
627
|
+
3. Plugin not registered
|
|
628
|
+
|
|
629
|
+
**Fix:**
|
|
630
|
+
```bash
|
|
631
|
+
# Generate types
|
|
632
|
+
bun run gen:types
|
|
633
|
+
|
|
634
|
+
# Verify import path
|
|
635
|
+
# Check plugin is registered in server/index.ts
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Summary
|
|
641
|
+
|
|
642
|
+
The DonkeyLabs dev experience includes:
|
|
643
|
+
|
|
644
|
+
1. **Sophisticated hot reload** - Route changes without restart
|
|
645
|
+
2. **Two dev modes** - In-process (fast) and subprocess (compatible)
|
|
646
|
+
3. **Automatic type generation** - Triggered by file changes
|
|
647
|
+
4. **File watchers** - Route watcher + plugin watcher
|
|
648
|
+
5. **Debugging tools** - Console logging, status indicators
|
|
649
|
+
6. **VS Code opportunities** - Snippets, go-to-def, auto-import
|
|
650
|
+
|
|
651
|
+
**Best practices:**
|
|
652
|
+
- Always use `bun --bun run dev`
|
|
653
|
+
- Run `gen:types` after structural changes
|
|
654
|
+
- Use plugin watcher for focused plugin dev
|
|
655
|
+
- Commit generated types for faster CI
|
|
656
|
+
- Check console for `[donkeylabs-dev]` messages
|