@donkeylabs/cli 2.0.14 → 2.0.16

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.
Files changed (85) hide show
  1. package/package.json +1 -1
  2. package/src/commands/config.ts +610 -0
  3. package/src/commands/deploy-enhanced.ts +354 -0
  4. package/src/commands/deploy.ts +204 -0
  5. package/src/commands/generate.ts +11 -13
  6. package/src/commands/init-enhanced.ts +1994 -0
  7. package/src/deployment/manager.ts +356 -0
  8. package/src/index.ts +47 -19
  9. package/templates/starter/.env.example +0 -44
  10. package/templates/starter/.gitignore.template +0 -4
  11. package/templates/starter/donkeylabs.config.ts +0 -6
  12. package/templates/starter/package.json +0 -21
  13. package/templates/starter/src/index.ts +0 -54
  14. package/templates/starter/src/plugins/stats/index.ts +0 -105
  15. package/templates/starter/src/routes/health/handlers/ping.ts +0 -22
  16. package/templates/starter/src/routes/health/index.ts +0 -19
  17. package/templates/starter/tsconfig.json +0 -27
  18. package/templates/sveltekit-app/.env.example +0 -59
  19. package/templates/sveltekit-app/README.md +0 -103
  20. package/templates/sveltekit-app/bun.lock +0 -683
  21. package/templates/sveltekit-app/donkeylabs.config.ts +0 -12
  22. package/templates/sveltekit-app/package.json +0 -38
  23. package/templates/sveltekit-app/src/app.css +0 -40
  24. package/templates/sveltekit-app/src/app.html +0 -12
  25. package/templates/sveltekit-app/src/hooks.server.ts +0 -4
  26. package/templates/sveltekit-app/src/lib/components/ui/badge/badge.svelte +0 -30
  27. package/templates/sveltekit-app/src/lib/components/ui/badge/index.ts +0 -3
  28. package/templates/sveltekit-app/src/lib/components/ui/button/button.svelte +0 -48
  29. package/templates/sveltekit-app/src/lib/components/ui/button/index.ts +0 -9
  30. package/templates/sveltekit-app/src/lib/components/ui/card/card-content.svelte +0 -18
  31. package/templates/sveltekit-app/src/lib/components/ui/card/card-description.svelte +0 -18
  32. package/templates/sveltekit-app/src/lib/components/ui/card/card-footer.svelte +0 -18
  33. package/templates/sveltekit-app/src/lib/components/ui/card/card-header.svelte +0 -18
  34. package/templates/sveltekit-app/src/lib/components/ui/card/card-title.svelte +0 -18
  35. package/templates/sveltekit-app/src/lib/components/ui/card/card.svelte +0 -21
  36. package/templates/sveltekit-app/src/lib/components/ui/card/index.ts +0 -21
  37. package/templates/sveltekit-app/src/lib/components/ui/index.ts +0 -4
  38. package/templates/sveltekit-app/src/lib/components/ui/input/index.ts +0 -2
  39. package/templates/sveltekit-app/src/lib/components/ui/input/input.svelte +0 -20
  40. package/templates/sveltekit-app/src/lib/permissions.ts +0 -213
  41. package/templates/sveltekit-app/src/lib/utils/index.ts +0 -6
  42. package/templates/sveltekit-app/src/routes/+layout.svelte +0 -8
  43. package/templates/sveltekit-app/src/routes/+page.server.ts +0 -25
  44. package/templates/sveltekit-app/src/routes/+page.svelte +0 -680
  45. package/templates/sveltekit-app/src/routes/workflows/+page.server.ts +0 -23
  46. package/templates/sveltekit-app/src/routes/workflows/+page.svelte +0 -522
  47. package/templates/sveltekit-app/src/server/events.ts +0 -28
  48. package/templates/sveltekit-app/src/server/index.ts +0 -124
  49. package/templates/sveltekit-app/src/server/plugins/auth/auth.test.ts +0 -377
  50. package/templates/sveltekit-app/src/server/plugins/auth/index.ts +0 -815
  51. package/templates/sveltekit-app/src/server/plugins/auth/migrations/001_create_users.ts +0 -25
  52. package/templates/sveltekit-app/src/server/plugins/auth/migrations/002_create_sessions.ts +0 -32
  53. package/templates/sveltekit-app/src/server/plugins/auth/migrations/003_create_refresh_tokens.ts +0 -33
  54. package/templates/sveltekit-app/src/server/plugins/auth/migrations/004_create_passkeys.ts +0 -60
  55. package/templates/sveltekit-app/src/server/plugins/auth/schema.ts +0 -65
  56. package/templates/sveltekit-app/src/server/plugins/demo/index.ts +0 -262
  57. package/templates/sveltekit-app/src/server/plugins/email/email.test.ts +0 -369
  58. package/templates/sveltekit-app/src/server/plugins/email/index.ts +0 -411
  59. package/templates/sveltekit-app/src/server/plugins/email/migrations/001_create_email_tokens.ts +0 -33
  60. package/templates/sveltekit-app/src/server/plugins/email/schema.ts +0 -24
  61. package/templates/sveltekit-app/src/server/plugins/permissions/index.ts +0 -1048
  62. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/001_create_tenants.ts +0 -63
  63. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/002_create_roles.ts +0 -90
  64. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/003_create_resource_grants.ts +0 -50
  65. package/templates/sveltekit-app/src/server/plugins/permissions/permissions.test.ts +0 -566
  66. package/templates/sveltekit-app/src/server/plugins/permissions/schema.ts +0 -67
  67. package/templates/sveltekit-app/src/server/plugins/workflow-demo/index.ts +0 -198
  68. package/templates/sveltekit-app/src/server/routes/auth/auth.schemas.ts +0 -66
  69. package/templates/sveltekit-app/src/server/routes/auth/handlers/login.handler.ts +0 -18
  70. package/templates/sveltekit-app/src/server/routes/auth/handlers/logout.handler.ts +0 -16
  71. package/templates/sveltekit-app/src/server/routes/auth/handlers/me.handler.ts +0 -20
  72. package/templates/sveltekit-app/src/server/routes/auth/handlers/refresh.handler.ts +0 -17
  73. package/templates/sveltekit-app/src/server/routes/auth/handlers/register.handler.ts +0 -19
  74. package/templates/sveltekit-app/src/server/routes/auth/handlers/update-profile.handler.ts +0 -21
  75. package/templates/sveltekit-app/src/server/routes/auth/index.ts +0 -73
  76. package/templates/sveltekit-app/src/server/routes/demo.ts +0 -464
  77. package/templates/sveltekit-app/src/server/routes/example/example.schemas.ts +0 -22
  78. package/templates/sveltekit-app/src/server/routes/example/handlers/greet.handler.ts +0 -21
  79. package/templates/sveltekit-app/src/server/routes/example/index.ts +0 -28
  80. package/templates/sveltekit-app/src/server/routes/permissions/index.ts +0 -248
  81. package/templates/sveltekit-app/src/server/routes/tenants/index.ts +0 -339
  82. package/templates/sveltekit-app/static/robots.txt +0 -3
  83. package/templates/sveltekit-app/svelte.config.ts +0 -17
  84. package/templates/sveltekit-app/tsconfig.json +0 -20
  85. package/templates/sveltekit-app/vite.config.ts +0 -12
@@ -1,464 +0,0 @@
1
- /**
2
- * Demo Router - Showcases @donkeylabs/server core features
3
- *
4
- * Routes delegate to the demo plugin service which handles
5
- * the core service integrations with proper types.
6
- */
7
-
8
- import { createRouter, defineRoute } from "@donkeylabs/server";
9
- import { z } from "zod";
10
-
11
- const demo = createRouter("api");
12
-
13
- // =============================================================================
14
- // COUNTER - Uses plugin service for state
15
- // =============================================================================
16
-
17
- demo.route("counter.get").typed(
18
- defineRoute({
19
- output: z.object({ count: z.number() }),
20
- handle: async (_, ctx) => {
21
- return { count: ctx.plugins.demo.getCounter() };
22
- },
23
- })
24
- );
25
-
26
- demo.route("counter.increment").typed(
27
- defineRoute({
28
- output: z.object({ count: z.number() }),
29
- handle: async (_, ctx) => {
30
- return { count: ctx.plugins.demo.increment() };
31
- },
32
- })
33
- );
34
-
35
- demo.route("counter.decrement").typed(
36
- defineRoute({
37
- output: z.object({ count: z.number() }),
38
- handle: async (_, ctx) => {
39
- return { count: ctx.plugins.demo.decrement() };
40
- },
41
- })
42
- );
43
-
44
- demo.route("counter.reset").typed(
45
- defineRoute({
46
- output: z.object({ count: z.number() }),
47
- handle: async (_, ctx) => {
48
- return { count: ctx.plugins.demo.reset() };
49
- },
50
- })
51
- );
52
-
53
- // =============================================================================
54
- // CACHE - In-memory caching (via plugin service)
55
- // =============================================================================
56
-
57
- demo.route("cache.set").typed(
58
- defineRoute({
59
- input: z.object({
60
- key: z.string(),
61
- value: z.any(),
62
- ttl: z.number().optional(),
63
- }),
64
- output: z.object({ success: z.boolean() }),
65
- handle: async (input, ctx) => {
66
- return ctx.plugins.demo.cacheSet(input.key, input.value, input.ttl);
67
- },
68
- })
69
- );
70
-
71
- demo.route("cache.get").typed(
72
- defineRoute({
73
- input: z.object({ key: z.string() }),
74
- output: z.object({ value: z.any().optional(), exists: z.boolean() }),
75
- handle: async (input, ctx) => {
76
- return ctx.plugins.demo.cacheGet(input.key);
77
- },
78
- })
79
- );
80
-
81
- demo.route("cache.delete").typed(
82
- defineRoute({
83
- input: z.object({ key: z.string() }),
84
- output: z.object({ success: z.boolean() }),
85
- handle: async (input, ctx) => {
86
- return ctx.plugins.demo.cacheDelete(input.key);
87
- },
88
- })
89
- );
90
-
91
- demo.route("cache.keys").typed(
92
- defineRoute({
93
- output: z.object({ keys: z.array(z.string()), size: z.number() }),
94
- handle: async (_, ctx) => {
95
- return ctx.plugins.demo.cacheKeys();
96
- },
97
- })
98
- );
99
-
100
- // =============================================================================
101
- // SSE - Server-Sent Events (via plugin service)
102
- // =============================================================================
103
-
104
- demo.route("sse.broadcast").typed(
105
- defineRoute({
106
- input: z.object({
107
- channel: z.string().default("events"),
108
- event: z.string().default("manual"),
109
- data: z.any(),
110
- }),
111
- output: z.object({ success: z.boolean() }),
112
- handle: async (input, ctx) => {
113
- const channel = input.channel ?? "events";
114
- const event = input.event ?? "manual";
115
- return ctx.plugins.demo.broadcast(channel, event, input.data);
116
- },
117
- })
118
- );
119
-
120
- demo.route("sse.clients").typed(
121
- defineRoute({
122
- output: z.object({ total: z.number(), byChannel: z.number() }),
123
- handle: async (_, ctx) => {
124
- return ctx.plugins.demo.getSSEClients();
125
- },
126
- })
127
- );
128
-
129
- // =============================================================================
130
- // JOBS - Background job queue (via plugin service)
131
- // =============================================================================
132
-
133
- demo.route("jobs.enqueue").typed(
134
- defineRoute({
135
- input: z.object({
136
- name: z.string().default("demo-job"),
137
- data: z.record(z.any()).optional(),
138
- delay: z.number().optional(),
139
- }),
140
- output: z.object({ jobId: z.string() }),
141
- handle: async (input, ctx) => {
142
- const name = input.name ?? "demo-job";
143
- return ctx.plugins.demo.enqueueJob(name, input.data || {}, input.delay);
144
- },
145
- })
146
- );
147
-
148
- demo.route("jobs.stats").typed(
149
- defineRoute({
150
- output: z.object({
151
- pending: z.number(),
152
- running: z.number(),
153
- completed: z.number(),
154
- }),
155
- handle: async (_, ctx) => {
156
- return ctx.plugins.demo.getJobStats();
157
- },
158
- })
159
- );
160
-
161
- // =============================================================================
162
- // EVENTS - Pub/sub system (via plugin service)
163
- // =============================================================================
164
-
165
- demo.route("events.emit").typed(
166
- defineRoute({
167
- input: z.object({
168
- event: z.string(),
169
- data: z.record(z.any()).optional(),
170
- }),
171
- output: z.object({ success: z.boolean() }),
172
- handle: async (input, ctx) => {
173
- return ctx.plugins.demo.emitEvent(input.event, input.data || {});
174
- },
175
- })
176
- );
177
-
178
- // =============================================================================
179
- // RATE LIMITING (via plugin service)
180
- // =============================================================================
181
-
182
- demo.route("ratelimit.check").typed(
183
- defineRoute({
184
- input: z.object({
185
- key: z.string(),
186
- limit: z.number().default(10),
187
- window: z.number().default(60),
188
- }),
189
- output: z.object({
190
- allowed: z.boolean(),
191
- remaining: z.number(),
192
- limit: z.number(),
193
- resetAt: z.date(),
194
- }),
195
- handle: async (input, ctx) => {
196
- const limit = input.limit ?? 10;
197
- const window = input.window ?? 60;
198
- return ctx.plugins.demo.checkRateLimit(input.key, limit, window * 1000);
199
- },
200
- })
201
- );
202
-
203
- demo.route("ratelimit.reset").typed(
204
- defineRoute({
205
- input: z.object({ key: z.string() }),
206
- output: z.object({ success: z.boolean() }),
207
- handle: async (input, ctx) => {
208
- return ctx.plugins.demo.resetRateLimit(input.key);
209
- },
210
- })
211
- );
212
-
213
- // =============================================================================
214
- // CRON - Scheduled tasks info (via plugin service)
215
- // =============================================================================
216
-
217
- demo.route("cron.list").typed(
218
- defineRoute({
219
- output: z.object({
220
- tasks: z.array(
221
- z.object({
222
- id: z.string(),
223
- name: z.string(),
224
- expression: z.string(),
225
- enabled: z.boolean(),
226
- lastRun: z.string().optional(),
227
- nextRun: z.string().optional(),
228
- })
229
- ),
230
- }),
231
- handle: async (_, ctx) => {
232
- return { tasks: ctx.plugins.demo.getCronTasks() };
233
- },
234
- })
235
- );
236
-
237
- // =============================================================================
238
- // WORKFLOWS - Step function orchestration (via workflowDemo plugin)
239
- // =============================================================================
240
-
241
- demo.route("workflow.start").typed(
242
- defineRoute({
243
- input: z.object({
244
- orderId: z.string().default(() => `ORD-${Date.now().toString(36).toUpperCase()}`),
245
- items: z
246
- .array(z.object({ name: z.string(), qty: z.number() }))
247
- .default([
248
- { name: "Widget A", qty: 2 },
249
- { name: "Gadget B", qty: 1 },
250
- ]),
251
- customerEmail: z.string().email().default("demo@example.com"),
252
- }),
253
- output: z.object({ instanceId: z.string() }),
254
- handle: async (input, ctx) => {
255
- return ctx.plugins.workflowDemo.startOrder({
256
- orderId: input.orderId ?? `ORD-${Date.now().toString(36).toUpperCase()}`,
257
- items: input.items ?? [
258
- { name: "Widget A", qty: 2 },
259
- { name: "Gadget B", qty: 1 },
260
- ],
261
- customerEmail: input.customerEmail ?? "demo@example.com",
262
- });
263
- },
264
- })
265
- );
266
-
267
- demo.route("workflow.status").typed(
268
- defineRoute({
269
- input: z.object({ instanceId: z.string() }),
270
- output: z.object({
271
- id: z.string(),
272
- status: z.string(),
273
- currentStep: z.string().optional(),
274
- input: z.any(),
275
- output: z.any().optional(),
276
- error: z.string().optional(),
277
- stepResults: z.record(z.any()),
278
- createdAt: z.string(),
279
- startedAt: z.string().optional(),
280
- completedAt: z.string().optional(),
281
- }).nullable(),
282
- handle: async (input, ctx) => {
283
- return ctx.plugins.workflowDemo.getStatus(input.instanceId);
284
- },
285
- })
286
- );
287
-
288
- demo.route("workflow.list").typed(
289
- defineRoute({
290
- input: z.object({ status: z.string().optional() }),
291
- output: z.object({
292
- instances: z.array(
293
- z.object({
294
- id: z.string(),
295
- status: z.string(),
296
- currentStep: z.string().optional(),
297
- createdAt: z.string(),
298
- completedAt: z.string().optional(),
299
- })
300
- ),
301
- }),
302
- handle: async (input, ctx) => {
303
- const instances = await ctx.plugins.workflowDemo.listInstances(input.status);
304
- return { instances };
305
- },
306
- })
307
- );
308
-
309
- demo.route("workflow.cancel").typed(
310
- defineRoute({
311
- input: z.object({ instanceId: z.string() }),
312
- output: z.object({ success: z.boolean() }),
313
- handle: async (input, ctx) => {
314
- return ctx.plugins.workflowDemo.cancel(input.instanceId);
315
- },
316
- })
317
- );
318
-
319
- // =============================================================================
320
- // AUDIT - Compliance and tracking (via plugin service)
321
- // =============================================================================
322
-
323
- demo.route("audit.log").typed(
324
- defineRoute({
325
- input: z.object({
326
- action: z.string(),
327
- resource: z.string(),
328
- resourceId: z.string().optional(),
329
- metadata: z.record(z.any()).optional(),
330
- }),
331
- output: z.object({ id: z.string() }),
332
- handle: async (input, ctx) => {
333
- return ctx.plugins.demo.auditLog(
334
- input.action,
335
- input.resource,
336
- input.resourceId,
337
- input.metadata
338
- );
339
- },
340
- })
341
- );
342
-
343
- demo.route("audit.query").typed(
344
- defineRoute({
345
- input: z.object({
346
- action: z.string().optional(),
347
- resource: z.string().optional(),
348
- limit: z.number().optional().default(10),
349
- }),
350
- output: z.object({
351
- entries: z.array(
352
- z.object({
353
- id: z.string(),
354
- timestamp: z.string(),
355
- action: z.string(),
356
- actor: z.string(),
357
- resource: z.string(),
358
- resourceId: z.string().optional(),
359
- metadata: z.record(z.any()).optional(),
360
- })
361
- ),
362
- }),
363
- handle: async (input, ctx) => {
364
- return ctx.plugins.demo.auditQuery({
365
- action: input.action,
366
- resource: input.resource,
367
- limit: input.limit ?? 10,
368
- });
369
- },
370
- })
371
- );
372
-
373
- demo.route("audit.byResource").typed(
374
- defineRoute({
375
- input: z.object({
376
- resource: z.string(),
377
- resourceId: z.string(),
378
- }),
379
- output: z.object({
380
- entries: z.array(
381
- z.object({
382
- id: z.string(),
383
- timestamp: z.string(),
384
- action: z.string(),
385
- actor: z.string(),
386
- metadata: z.record(z.any()).optional(),
387
- })
388
- ),
389
- }),
390
- handle: async (input, ctx) => {
391
- return ctx.plugins.demo.auditGetByResource(input.resource, input.resourceId);
392
- },
393
- })
394
- );
395
-
396
- // =============================================================================
397
- // WEBSOCKET - Bidirectional real-time communication (via plugin service)
398
- // =============================================================================
399
-
400
- demo.route("websocket.broadcast").typed(
401
- defineRoute({
402
- input: z.object({
403
- channel: z.string(),
404
- event: z.string().default("message"),
405
- data: z.any(),
406
- }),
407
- output: z.object({ success: z.boolean() }),
408
- handle: async (input, ctx) => {
409
- return ctx.plugins.demo.wsBroadcast(
410
- input.channel,
411
- input.event ?? "message",
412
- input.data
413
- );
414
- },
415
- })
416
- );
417
-
418
- demo.route("websocket.broadcastAll").typed(
419
- defineRoute({
420
- input: z.object({
421
- event: z.string().default("message"),
422
- data: z.any(),
423
- }),
424
- output: z.object({ success: z.boolean() }),
425
- handle: async (input, ctx) => {
426
- return ctx.plugins.demo.wsBroadcastAll(input.event ?? "message", input.data);
427
- },
428
- })
429
- );
430
-
431
- demo.route("websocket.clients").typed(
432
- defineRoute({
433
- input: z.object({
434
- channel: z.string().optional(),
435
- }),
436
- output: z.object({
437
- count: z.number(),
438
- clients: z.array(
439
- z.object({
440
- id: z.string(),
441
- connectedAt: z.date(),
442
- channels: z.array(z.string()),
443
- })
444
- ),
445
- }),
446
- handle: async (input, ctx) => {
447
- return ctx.plugins.demo.wsGetClients(input.channel);
448
- },
449
- })
450
- );
451
-
452
- demo.route("websocket.clientCount").typed(
453
- defineRoute({
454
- input: z.object({
455
- channel: z.string().optional(),
456
- }),
457
- output: z.object({ count: z.number() }),
458
- handle: async (input, ctx) => {
459
- return ctx.plugins.demo.wsGetClientCount(input.channel);
460
- },
461
- })
462
- );
463
-
464
- export default demo;
@@ -1,22 +0,0 @@
1
- import { z } from "zod";
2
-
3
- // =============================================================================
4
- // GREETING SCHEMAS
5
- // =============================================================================
6
-
7
- export const greetInputSchema = z.object({
8
- name: z.string().min(1, "Name is required"),
9
- formal: z.boolean().optional().default(false),
10
- });
11
-
12
- export const greetOutputSchema = z.object({
13
- message: z.string(),
14
- timestamp: z.string(),
15
- });
16
-
17
- // =============================================================================
18
- // DERIVED TYPES
19
- // =============================================================================
20
-
21
- export type GreetInput = z.infer<typeof greetInputSchema>;
22
- export type GreetOutput = z.infer<typeof greetOutputSchema>;
@@ -1,21 +0,0 @@
1
- /**
2
- * Greet Handler
3
- *
4
- * Example handler demonstrating the feature module pattern.
5
- * Business logic lives directly in the handler - no separate model layer needed.
6
- */
7
- export class GreetHandler {
8
- constructor(private ctx: any) {}
9
-
10
- handle(input: { name: string; formal?: boolean }) {
11
- // Business logic directly in handler
12
- const greeting = input.formal
13
- ? `Good day, ${input.name}. How may I assist you?`
14
- : `Hey ${input.name}!`;
15
-
16
- return {
17
- message: greeting,
18
- timestamp: new Date().toISOString(),
19
- };
20
- }
21
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Example Router - Demonstrates the feature module pattern
3
- *
4
- * Feature modules organize app-specific routes with:
5
- * - Thin router (just wiring)
6
- * - Handler classes with business logic
7
- * - Schemas in separate file
8
- *
9
- * Structure:
10
- * routes/example/
11
- * ├── index.ts <- Router (this file)
12
- * ├── example.schemas.ts <- Zod schemas + types
13
- * └── handlers/
14
- * └── greet.handler.ts <- Handler with business logic
15
- */
16
-
17
- import { createRouter } from "@donkeylabs/server";
18
- import { greetInputSchema, greetOutputSchema } from "./example.schemas";
19
- import { GreetHandler } from "./handlers/greet.handler";
20
-
21
- export const exampleRouter = createRouter("example")
22
-
23
- // Simple greeting route
24
- .route("greet").typed({
25
- input: greetInputSchema,
26
- output: greetOutputSchema,
27
- handle: GreetHandler,
28
- });