@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.
- package/package.json +1 -1
- package/src/commands/config.ts +610 -0
- package/src/commands/deploy-enhanced.ts +354 -0
- package/src/commands/deploy.ts +204 -0
- package/src/commands/generate.ts +11 -13
- package/src/commands/init-enhanced.ts +1994 -0
- package/src/deployment/manager.ts +356 -0
- package/src/index.ts +47 -19
- package/templates/starter/.env.example +0 -44
- package/templates/starter/.gitignore.template +0 -4
- package/templates/starter/donkeylabs.config.ts +0 -6
- package/templates/starter/package.json +0 -21
- package/templates/starter/src/index.ts +0 -54
- package/templates/starter/src/plugins/stats/index.ts +0 -105
- package/templates/starter/src/routes/health/handlers/ping.ts +0 -22
- package/templates/starter/src/routes/health/index.ts +0 -19
- package/templates/starter/tsconfig.json +0 -27
- package/templates/sveltekit-app/.env.example +0 -59
- package/templates/sveltekit-app/README.md +0 -103
- package/templates/sveltekit-app/bun.lock +0 -683
- package/templates/sveltekit-app/donkeylabs.config.ts +0 -12
- package/templates/sveltekit-app/package.json +0 -38
- package/templates/sveltekit-app/src/app.css +0 -40
- package/templates/sveltekit-app/src/app.html +0 -12
- package/templates/sveltekit-app/src/hooks.server.ts +0 -4
- package/templates/sveltekit-app/src/lib/components/ui/badge/badge.svelte +0 -30
- package/templates/sveltekit-app/src/lib/components/ui/badge/index.ts +0 -3
- package/templates/sveltekit-app/src/lib/components/ui/button/button.svelte +0 -48
- package/templates/sveltekit-app/src/lib/components/ui/button/index.ts +0 -9
- package/templates/sveltekit-app/src/lib/components/ui/card/card-content.svelte +0 -18
- package/templates/sveltekit-app/src/lib/components/ui/card/card-description.svelte +0 -18
- package/templates/sveltekit-app/src/lib/components/ui/card/card-footer.svelte +0 -18
- package/templates/sveltekit-app/src/lib/components/ui/card/card-header.svelte +0 -18
- package/templates/sveltekit-app/src/lib/components/ui/card/card-title.svelte +0 -18
- package/templates/sveltekit-app/src/lib/components/ui/card/card.svelte +0 -21
- package/templates/sveltekit-app/src/lib/components/ui/card/index.ts +0 -21
- package/templates/sveltekit-app/src/lib/components/ui/index.ts +0 -4
- package/templates/sveltekit-app/src/lib/components/ui/input/index.ts +0 -2
- package/templates/sveltekit-app/src/lib/components/ui/input/input.svelte +0 -20
- package/templates/sveltekit-app/src/lib/permissions.ts +0 -213
- package/templates/sveltekit-app/src/lib/utils/index.ts +0 -6
- package/templates/sveltekit-app/src/routes/+layout.svelte +0 -8
- package/templates/sveltekit-app/src/routes/+page.server.ts +0 -25
- package/templates/sveltekit-app/src/routes/+page.svelte +0 -680
- package/templates/sveltekit-app/src/routes/workflows/+page.server.ts +0 -23
- package/templates/sveltekit-app/src/routes/workflows/+page.svelte +0 -522
- package/templates/sveltekit-app/src/server/events.ts +0 -28
- package/templates/sveltekit-app/src/server/index.ts +0 -124
- package/templates/sveltekit-app/src/server/plugins/auth/auth.test.ts +0 -377
- package/templates/sveltekit-app/src/server/plugins/auth/index.ts +0 -815
- package/templates/sveltekit-app/src/server/plugins/auth/migrations/001_create_users.ts +0 -25
- package/templates/sveltekit-app/src/server/plugins/auth/migrations/002_create_sessions.ts +0 -32
- package/templates/sveltekit-app/src/server/plugins/auth/migrations/003_create_refresh_tokens.ts +0 -33
- package/templates/sveltekit-app/src/server/plugins/auth/migrations/004_create_passkeys.ts +0 -60
- package/templates/sveltekit-app/src/server/plugins/auth/schema.ts +0 -65
- package/templates/sveltekit-app/src/server/plugins/demo/index.ts +0 -262
- package/templates/sveltekit-app/src/server/plugins/email/email.test.ts +0 -369
- package/templates/sveltekit-app/src/server/plugins/email/index.ts +0 -411
- package/templates/sveltekit-app/src/server/plugins/email/migrations/001_create_email_tokens.ts +0 -33
- package/templates/sveltekit-app/src/server/plugins/email/schema.ts +0 -24
- package/templates/sveltekit-app/src/server/plugins/permissions/index.ts +0 -1048
- package/templates/sveltekit-app/src/server/plugins/permissions/migrations/001_create_tenants.ts +0 -63
- package/templates/sveltekit-app/src/server/plugins/permissions/migrations/002_create_roles.ts +0 -90
- package/templates/sveltekit-app/src/server/plugins/permissions/migrations/003_create_resource_grants.ts +0 -50
- package/templates/sveltekit-app/src/server/plugins/permissions/permissions.test.ts +0 -566
- package/templates/sveltekit-app/src/server/plugins/permissions/schema.ts +0 -67
- package/templates/sveltekit-app/src/server/plugins/workflow-demo/index.ts +0 -198
- package/templates/sveltekit-app/src/server/routes/auth/auth.schemas.ts +0 -66
- package/templates/sveltekit-app/src/server/routes/auth/handlers/login.handler.ts +0 -18
- package/templates/sveltekit-app/src/server/routes/auth/handlers/logout.handler.ts +0 -16
- package/templates/sveltekit-app/src/server/routes/auth/handlers/me.handler.ts +0 -20
- package/templates/sveltekit-app/src/server/routes/auth/handlers/refresh.handler.ts +0 -17
- package/templates/sveltekit-app/src/server/routes/auth/handlers/register.handler.ts +0 -19
- package/templates/sveltekit-app/src/server/routes/auth/handlers/update-profile.handler.ts +0 -21
- package/templates/sveltekit-app/src/server/routes/auth/index.ts +0 -73
- package/templates/sveltekit-app/src/server/routes/demo.ts +0 -464
- package/templates/sveltekit-app/src/server/routes/example/example.schemas.ts +0 -22
- package/templates/sveltekit-app/src/server/routes/example/handlers/greet.handler.ts +0 -21
- package/templates/sveltekit-app/src/server/routes/example/index.ts +0 -28
- package/templates/sveltekit-app/src/server/routes/permissions/index.ts +0 -248
- package/templates/sveltekit-app/src/server/routes/tenants/index.ts +0 -339
- package/templates/sveltekit-app/static/robots.txt +0 -3
- package/templates/sveltekit-app/svelte.config.ts +0 -17
- package/templates/sveltekit-app/tsconfig.json +0 -20
- 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
|
-
});
|