@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,198 +0,0 @@
1
- // Workflow Demo Plugin - Demonstrates step function orchestration
2
- import { createPlugin, workflow, type WorkflowContext, type CoreServices } from "@donkeylabs/server";
3
- import { z } from "zod";
4
-
5
- // Helper to simulate async work with delay
6
- const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
7
-
8
- // Input/output types for better type safety
9
- type OrderInput = {
10
- orderId: string;
11
- items: { name: string; qty: number }[];
12
- customerEmail: string;
13
- };
14
-
15
- type ValidateOutput = { valid: boolean; total: number; itemCount: number };
16
- type PaymentOutput = { paymentId: string; status: string };
17
-
18
- // Define an example order processing workflow with placeholder tasks
19
- export const orderWorkflow = workflow("process-order")
20
- .timeout(60000) // 1 minute max
21
- .defaultRetry({ maxAttempts: 2 })
22
-
23
- // Step 1: Validate Order
24
- .task("validate", {
25
- inputSchema: z.object({
26
- orderId: z.string(),
27
- items: z.array(z.object({ name: z.string(), qty: z.number() })),
28
- customerEmail: z.string().email(),
29
- }),
30
- outputSchema: z.object({
31
- valid: z.boolean(),
32
- total: z.number(),
33
- itemCount: z.number(),
34
- }),
35
- handler: async (input: OrderInput, ctx: { core: CoreServices }): Promise<ValidateOutput> => {
36
- ctx.core.logger.info("Validating order", { orderId: input.orderId });
37
- await sleep(1000); // Simulate validation work
38
- const total = input.items.reduce((sum: number, item: { qty: number }) => sum + item.qty * 10, 0);
39
- return { valid: true, total, itemCount: input.items.length };
40
- },
41
- })
42
-
43
- // Step 2: Process Payment
44
- .task("payment", {
45
- inputSchema: (prev: ValidateOutput, workflowInput: OrderInput) => ({
46
- orderId: workflowInput.orderId,
47
- amount: prev.total,
48
- email: workflowInput.customerEmail,
49
- }),
50
- outputSchema: z.object({
51
- paymentId: z.string(),
52
- status: z.string(),
53
- }),
54
- handler: async (input: { orderId: string; amount: number; email: string }, ctx: { core: CoreServices }): Promise<PaymentOutput> => {
55
- ctx.core.logger.info("Processing payment", {
56
- orderId: input.orderId,
57
- amount: input.amount,
58
- });
59
- await sleep(2000); // Simulate payment processing
60
- return {
61
- paymentId: `PAY-${Date.now().toString(36).toUpperCase()}`,
62
- status: "completed",
63
- };
64
- },
65
- })
66
-
67
- // Step 3: Parallel - Send Notification + Prepare Shipment
68
- .parallel("fulfill", {
69
- branches: [
70
- workflow
71
- .branch("notification")
72
- .task("send-email", {
73
- handler: async (_input: unknown, ctx: { core: CoreServices }) => {
74
- ctx.core.logger.info("Sending confirmation email");
75
- await sleep(800); // Simulate email send
76
- return { emailSent: true, sentAt: new Date().toISOString() };
77
- },
78
- })
79
- .build(),
80
-
81
- workflow
82
- .branch("shipping")
83
- .task("prepare-shipment", {
84
- handler: async (_input: unknown, ctx: { core: CoreServices }) => {
85
- ctx.core.logger.info("Preparing shipment");
86
- await sleep(1500); // Simulate shipment prep
87
- return {
88
- trackingId: `SHIP-${Date.now().toString(36).toUpperCase()}`,
89
- carrier: "FastShip",
90
- estimatedDelivery: new Date(
91
- Date.now() + 3 * 24 * 60 * 60 * 1000
92
- ).toISOString(),
93
- };
94
- },
95
- })
96
- .build(),
97
- ],
98
- next: "complete",
99
- })
100
-
101
- // Step 4: Complete
102
- .pass("complete", {
103
- transform: (ctx: WorkflowContext) => ({
104
- orderId: ctx.input.orderId,
105
- paymentId: ctx.steps["payment"].paymentId,
106
- // Parallel branch outputs are stored directly by branch name
107
- tracking: ctx.steps["fulfill"].shipping.trackingId,
108
- emailSent: ctx.steps["fulfill"].notification.emailSent,
109
- completedAt: new Date().toISOString(),
110
- }),
111
- end: true,
112
- })
113
- .build();
114
-
115
- // Plugin that registers the workflow and provides service methods
116
- export const workflowDemoPlugin = createPlugin.define({
117
- name: "workflowDemo",
118
- service: async (ctx) => ({
119
- // Start a new order processing workflow
120
- startOrder: async (input: {
121
- orderId: string;
122
- items: { name: string; qty: number }[];
123
- customerEmail: string;
124
- }) => {
125
- const instanceId = await ctx.core.workflows.start("process-order", input);
126
- return { instanceId };
127
- },
128
-
129
- // Get workflow instance status
130
- getStatus: async (instanceId: string) => {
131
- const instance = await ctx.core.workflows.getInstance(instanceId);
132
- if (!instance) return null;
133
-
134
- return {
135
- id: instance.id,
136
- status: instance.status,
137
- currentStep: instance.currentStep,
138
- input: instance.input,
139
- output: instance.output,
140
- error: instance.error,
141
- stepResults: instance.stepResults,
142
- createdAt: instance.createdAt.toISOString(),
143
- startedAt: instance.startedAt?.toISOString(),
144
- completedAt: instance.completedAt?.toISOString(),
145
- };
146
- },
147
-
148
- // List all workflow instances
149
- listInstances: async (status?: string) => {
150
- const instances = await ctx.core.workflows.getInstances(
151
- "process-order",
152
- status as any
153
- );
154
- return instances.map((i) => ({
155
- id: i.id,
156
- status: i.status,
157
- currentStep: i.currentStep,
158
- createdAt: i.createdAt.toISOString(),
159
- completedAt: i.completedAt?.toISOString(),
160
- }));
161
- },
162
-
163
- // Cancel a running workflow
164
- cancel: async (instanceId: string) => {
165
- const success = await ctx.core.workflows.cancel(instanceId);
166
- return { success };
167
- },
168
- }),
169
-
170
- init: async (ctx) => {
171
- // Register the workflow definition
172
- ctx.core.workflows.register(orderWorkflow);
173
-
174
- // Broadcast workflow events to SSE for real-time UI updates
175
- const workflowEvents = [
176
- "workflow.started",
177
- "workflow.progress",
178
- "workflow.completed",
179
- "workflow.failed",
180
- "workflow.cancelled",
181
- "workflow.step.started",
182
- "workflow.step.completed",
183
- "workflow.step.failed",
184
- ];
185
-
186
- for (const event of workflowEvents) {
187
- ctx.core.events.on(event, (data: any) => {
188
- // Broadcast to workflow-specific channel
189
- ctx.core.sse.broadcast(`workflow:${data.instanceId}`, event, data);
190
-
191
- // Also broadcast to general workflow-updates channel for the demo list
192
- ctx.core.sse.broadcast("workflow-updates", event, data);
193
- });
194
- }
195
-
196
- ctx.core.logger.info("Workflow demo plugin initialized with order workflow");
197
- },
198
- });
@@ -1,66 +0,0 @@
1
- import { z } from "zod";
2
-
3
- // =============================================================================
4
- // INPUT SCHEMAS
5
- // =============================================================================
6
-
7
- export const registerSchema = z.object({
8
- email: z.string().email("Invalid email address"),
9
- password: z.string().min(8, "Password must be at least 8 characters"),
10
- name: z.string().min(1).optional(),
11
- });
12
-
13
- export const loginSchema = z.object({
14
- email: z.string().email("Invalid email address"),
15
- password: z.string().min(1, "Password is required"),
16
- });
17
-
18
- export const refreshSchema = z.object({
19
- refreshToken: z.string(),
20
- });
21
-
22
- export const updateProfileSchema = z.object({
23
- name: z.string().min(1).optional(),
24
- email: z.string().email().optional(),
25
- });
26
-
27
- // =============================================================================
28
- // OUTPUT SCHEMAS
29
- // =============================================================================
30
-
31
- export const userSchema = z.object({
32
- id: z.string(),
33
- email: z.string(),
34
- name: z.string().nullable(),
35
- });
36
-
37
- export const tokensSchema = z.object({
38
- accessToken: z.string(),
39
- refreshToken: z.string().optional(),
40
- expiresIn: z.number(),
41
- });
42
-
43
- export const authResponseSchema = z.object({
44
- user: userSchema,
45
- tokens: tokensSchema,
46
- });
47
-
48
- export const refreshResponseSchema = tokensSchema;
49
-
50
- export const meResponseSchema = userSchema.nullable();
51
-
52
- export const logoutResponseSchema = z.object({
53
- success: z.boolean(),
54
- });
55
-
56
- // =============================================================================
57
- // DERIVED TYPES
58
- // =============================================================================
59
-
60
- export type RegisterInput = z.infer<typeof registerSchema>;
61
- export type LoginInput = z.infer<typeof loginSchema>;
62
- export type RefreshInput = z.infer<typeof refreshSchema>;
63
- export type UpdateProfileInput = z.infer<typeof updateProfileSchema>;
64
- export type User = z.infer<typeof userSchema>;
65
- export type Tokens = z.infer<typeof tokensSchema>;
66
- export type AuthResponse = z.infer<typeof authResponseSchema>;
@@ -1,18 +0,0 @@
1
- /**
2
- * Login Handler - Authenticate user and create session/token
3
- */
4
- export class LoginHandler {
5
- constructor(private ctx: any) {}
6
-
7
- async handle(input: { email: string; password: string }) {
8
- const result = await (this.ctx.plugins as any).auth.login({
9
- email: input.email,
10
- password: input.password,
11
- });
12
-
13
- return {
14
- user: result.user,
15
- tokens: result.tokens,
16
- };
17
- }
18
- }
@@ -1,16 +0,0 @@
1
- /**
2
- * Logout Handler - Invalidate current session/token
3
- */
4
- export class LogoutHandler {
5
- constructor(private ctx: any) {}
6
-
7
- async handle(_input: Record<string, never>) {
8
- const token = this.ctx.token;
9
-
10
- if (token) {
11
- await (this.ctx.plugins as any).auth.logout(token);
12
- }
13
-
14
- return { success: true };
15
- }
16
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * Me Handler - Get current authenticated user
3
- */
4
- export class MeHandler {
5
- constructor(private ctx: any) {}
6
-
7
- async handle(_input: Record<string, never>) {
8
- const user = this.ctx.user;
9
-
10
- if (!user) {
11
- return null;
12
- }
13
-
14
- return {
15
- id: user.id,
16
- email: user.email,
17
- name: user.name,
18
- };
19
- }
20
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * Refresh Handler - Get new access token using refresh token
3
- * Only available with refresh-token strategy
4
- */
5
- export class RefreshHandler {
6
- constructor(private ctx: any) {}
7
-
8
- async handle(input: { refreshToken: string }) {
9
- const tokens = await (this.ctx.plugins as any).auth.refresh(input.refreshToken);
10
-
11
- return {
12
- accessToken: tokens.accessToken,
13
- refreshToken: tokens.refreshToken,
14
- expiresIn: tokens.expiresIn,
15
- };
16
- }
17
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Register Handler - Create a new user account
3
- */
4
- export class RegisterHandler {
5
- constructor(private ctx: any) {}
6
-
7
- async handle(input: { email: string; password: string; name: string }) {
8
- const result = await (this.ctx.plugins as any).auth.register({
9
- email: input.email,
10
- password: input.password,
11
- name: input.name,
12
- });
13
-
14
- return {
15
- user: result.user,
16
- tokens: result.tokens,
17
- };
18
- }
19
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Update Profile Handler - Update current user's profile
3
- */
4
- export class UpdateProfileHandler {
5
- constructor(private ctx: any) {}
6
-
7
- async handle(input: { name?: string; email?: string }) {
8
- const user = this.ctx.user;
9
-
10
- if (!user) {
11
- throw this.ctx.errors.Unauthorized("Not authenticated");
12
- }
13
-
14
- const updated = await (this.ctx.plugins as any).auth.updateProfile(user.id, {
15
- name: input.name,
16
- email: input.email,
17
- });
18
-
19
- return updated;
20
- }
21
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * Auth Router - Authentication endpoints
3
- *
4
- * Provides:
5
- * - auth.register - Create new account
6
- * - auth.login - Login and get tokens
7
- * - auth.refresh - Refresh access token (refresh-token strategy only)
8
- * - auth.logout - Invalidate session/token
9
- * - auth.me - Get current user
10
- * - auth.updateProfile - Update profile
11
- */
12
-
13
- import { createRouter } from "@donkeylabs/server";
14
- import { z } from "zod";
15
- import {
16
- registerSchema,
17
- loginSchema,
18
- refreshSchema,
19
- updateProfileSchema,
20
- authResponseSchema,
21
- refreshResponseSchema,
22
- userSchema,
23
- logoutResponseSchema,
24
- } from "./auth.schemas";
25
- import { RegisterHandler } from "./handlers/register.handler";
26
- import { LoginHandler } from "./handlers/login.handler";
27
- import { RefreshHandler } from "./handlers/refresh.handler";
28
- import { LogoutHandler } from "./handlers/logout.handler";
29
- import { MeHandler } from "./handlers/me.handler";
30
- import { UpdateProfileHandler } from "./handlers/update-profile.handler";
31
-
32
- export const authRouter = createRouter("auth")
33
-
34
- // Public routes
35
- .route("register").typed({
36
- input: registerSchema,
37
- output: authResponseSchema,
38
- handle: RegisterHandler,
39
- })
40
-
41
- .route("login").typed({
42
- input: loginSchema,
43
- output: authResponseSchema,
44
- handle: LoginHandler,
45
- })
46
-
47
- // Refresh token (for refresh-token strategy)
48
- .route("refresh").typed({
49
- input: refreshSchema,
50
- output: refreshResponseSchema,
51
- handle: RefreshHandler,
52
- })
53
-
54
- // Get current user (returns null if not authenticated)
55
- .route("me").typed({
56
- input: z.object({}),
57
- output: userSchema.nullable(),
58
- handle: MeHandler,
59
- })
60
-
61
- // Logout (invalidate session/token)
62
- .route("logout").typed({
63
- input: z.object({}),
64
- output: logoutResponseSchema,
65
- handle: LogoutHandler,
66
- })
67
-
68
- // Update profile
69
- .route("updateProfile").typed({
70
- input: updateProfileSchema,
71
- output: userSchema,
72
- handle: UpdateProfileHandler,
73
- });