@donkeylabs/cli 2.0.15 → 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 (84) 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/init-enhanced.ts +1994 -0
  6. package/src/deployment/manager.ts +356 -0
  7. package/src/index.ts +47 -19
  8. package/templates/starter/.env.example +0 -44
  9. package/templates/starter/.gitignore.template +0 -4
  10. package/templates/starter/donkeylabs.config.ts +0 -6
  11. package/templates/starter/package.json +0 -21
  12. package/templates/starter/src/index.ts +0 -54
  13. package/templates/starter/src/plugins/stats/index.ts +0 -105
  14. package/templates/starter/src/routes/health/handlers/ping.ts +0 -22
  15. package/templates/starter/src/routes/health/index.ts +0 -19
  16. package/templates/starter/tsconfig.json +0 -27
  17. package/templates/sveltekit-app/.env.example +0 -59
  18. package/templates/sveltekit-app/README.md +0 -103
  19. package/templates/sveltekit-app/bun.lock +0 -683
  20. package/templates/sveltekit-app/donkeylabs.config.ts +0 -12
  21. package/templates/sveltekit-app/package.json +0 -38
  22. package/templates/sveltekit-app/src/app.css +0 -40
  23. package/templates/sveltekit-app/src/app.html +0 -12
  24. package/templates/sveltekit-app/src/hooks.server.ts +0 -4
  25. package/templates/sveltekit-app/src/lib/components/ui/badge/badge.svelte +0 -30
  26. package/templates/sveltekit-app/src/lib/components/ui/badge/index.ts +0 -3
  27. package/templates/sveltekit-app/src/lib/components/ui/button/button.svelte +0 -48
  28. package/templates/sveltekit-app/src/lib/components/ui/button/index.ts +0 -9
  29. package/templates/sveltekit-app/src/lib/components/ui/card/card-content.svelte +0 -18
  30. package/templates/sveltekit-app/src/lib/components/ui/card/card-description.svelte +0 -18
  31. package/templates/sveltekit-app/src/lib/components/ui/card/card-footer.svelte +0 -18
  32. package/templates/sveltekit-app/src/lib/components/ui/card/card-header.svelte +0 -18
  33. package/templates/sveltekit-app/src/lib/components/ui/card/card-title.svelte +0 -18
  34. package/templates/sveltekit-app/src/lib/components/ui/card/card.svelte +0 -21
  35. package/templates/sveltekit-app/src/lib/components/ui/card/index.ts +0 -21
  36. package/templates/sveltekit-app/src/lib/components/ui/index.ts +0 -4
  37. package/templates/sveltekit-app/src/lib/components/ui/input/index.ts +0 -2
  38. package/templates/sveltekit-app/src/lib/components/ui/input/input.svelte +0 -20
  39. package/templates/sveltekit-app/src/lib/permissions.ts +0 -213
  40. package/templates/sveltekit-app/src/lib/utils/index.ts +0 -6
  41. package/templates/sveltekit-app/src/routes/+layout.svelte +0 -8
  42. package/templates/sveltekit-app/src/routes/+page.server.ts +0 -25
  43. package/templates/sveltekit-app/src/routes/+page.svelte +0 -680
  44. package/templates/sveltekit-app/src/routes/workflows/+page.server.ts +0 -23
  45. package/templates/sveltekit-app/src/routes/workflows/+page.svelte +0 -522
  46. package/templates/sveltekit-app/src/server/events.ts +0 -28
  47. package/templates/sveltekit-app/src/server/index.ts +0 -124
  48. package/templates/sveltekit-app/src/server/plugins/auth/auth.test.ts +0 -377
  49. package/templates/sveltekit-app/src/server/plugins/auth/index.ts +0 -815
  50. package/templates/sveltekit-app/src/server/plugins/auth/migrations/001_create_users.ts +0 -25
  51. package/templates/sveltekit-app/src/server/plugins/auth/migrations/002_create_sessions.ts +0 -32
  52. package/templates/sveltekit-app/src/server/plugins/auth/migrations/003_create_refresh_tokens.ts +0 -33
  53. package/templates/sveltekit-app/src/server/plugins/auth/migrations/004_create_passkeys.ts +0 -60
  54. package/templates/sveltekit-app/src/server/plugins/auth/schema.ts +0 -65
  55. package/templates/sveltekit-app/src/server/plugins/demo/index.ts +0 -262
  56. package/templates/sveltekit-app/src/server/plugins/email/email.test.ts +0 -369
  57. package/templates/sveltekit-app/src/server/plugins/email/index.ts +0 -411
  58. package/templates/sveltekit-app/src/server/plugins/email/migrations/001_create_email_tokens.ts +0 -33
  59. package/templates/sveltekit-app/src/server/plugins/email/schema.ts +0 -24
  60. package/templates/sveltekit-app/src/server/plugins/permissions/index.ts +0 -1048
  61. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/001_create_tenants.ts +0 -63
  62. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/002_create_roles.ts +0 -90
  63. package/templates/sveltekit-app/src/server/plugins/permissions/migrations/003_create_resource_grants.ts +0 -50
  64. package/templates/sveltekit-app/src/server/plugins/permissions/permissions.test.ts +0 -566
  65. package/templates/sveltekit-app/src/server/plugins/permissions/schema.ts +0 -67
  66. package/templates/sveltekit-app/src/server/plugins/workflow-demo/index.ts +0 -198
  67. package/templates/sveltekit-app/src/server/routes/auth/auth.schemas.ts +0 -66
  68. package/templates/sveltekit-app/src/server/routes/auth/handlers/login.handler.ts +0 -18
  69. package/templates/sveltekit-app/src/server/routes/auth/handlers/logout.handler.ts +0 -16
  70. package/templates/sveltekit-app/src/server/routes/auth/handlers/me.handler.ts +0 -20
  71. package/templates/sveltekit-app/src/server/routes/auth/handlers/refresh.handler.ts +0 -17
  72. package/templates/sveltekit-app/src/server/routes/auth/handlers/register.handler.ts +0 -19
  73. package/templates/sveltekit-app/src/server/routes/auth/handlers/update-profile.handler.ts +0 -21
  74. package/templates/sveltekit-app/src/server/routes/auth/index.ts +0 -73
  75. package/templates/sveltekit-app/src/server/routes/demo.ts +0 -464
  76. package/templates/sveltekit-app/src/server/routes/example/example.schemas.ts +0 -22
  77. package/templates/sveltekit-app/src/server/routes/example/handlers/greet.handler.ts +0 -21
  78. package/templates/sveltekit-app/src/server/routes/example/index.ts +0 -28
  79. package/templates/sveltekit-app/src/server/routes/permissions/index.ts +0 -248
  80. package/templates/sveltekit-app/src/server/routes/tenants/index.ts +0 -339
  81. package/templates/sveltekit-app/static/robots.txt +0 -3
  82. package/templates/sveltekit-app/svelte.config.ts +0 -17
  83. package/templates/sveltekit-app/tsconfig.json +0 -20
  84. 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
- });