@donkeylabs/cli 0.1.1 → 0.4.1

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 (47) hide show
  1. package/package.json +2 -2
  2. package/src/client/base.ts +481 -0
  3. package/src/commands/generate.ts +242 -41
  4. package/templates/starter/src/index.ts +19 -30
  5. package/templates/starter/src/routes/health/handlers/ping.ts +22 -0
  6. package/templates/starter/src/routes/health/index.ts +16 -2
  7. package/templates/sveltekit-app/bun.lock +6 -6
  8. package/templates/sveltekit-app/donkeylabs.config.ts +1 -0
  9. package/templates/sveltekit-app/package.json +5 -5
  10. package/templates/sveltekit-app/src/lib/api.ts +229 -41
  11. package/templates/sveltekit-app/src/routes/+page.server.ts +2 -2
  12. package/templates/sveltekit-app/src/routes/+page.svelte +235 -96
  13. package/templates/sveltekit-app/src/server/index.ts +25 -117
  14. package/templates/sveltekit-app/src/server/routes/cache/handlers/delete.ts +15 -0
  15. package/templates/sveltekit-app/src/server/routes/cache/handlers/get.ts +15 -0
  16. package/templates/sveltekit-app/src/server/routes/cache/handlers/keys.ts +15 -0
  17. package/templates/sveltekit-app/src/server/routes/cache/handlers/set.ts +15 -0
  18. package/templates/sveltekit-app/src/server/routes/cache/index.ts +46 -0
  19. package/templates/sveltekit-app/src/server/routes/counter/handlers/decrement.ts +17 -0
  20. package/templates/sveltekit-app/src/server/routes/counter/handlers/get.ts +17 -0
  21. package/templates/sveltekit-app/src/server/routes/counter/handlers/increment.ts +17 -0
  22. package/templates/sveltekit-app/src/server/routes/counter/handlers/reset.ts +17 -0
  23. package/templates/sveltekit-app/src/server/routes/counter/index.ts +39 -0
  24. package/templates/sveltekit-app/src/server/routes/cron/handlers/list.ts +17 -0
  25. package/templates/sveltekit-app/src/server/routes/cron/index.ts +24 -0
  26. package/templates/sveltekit-app/src/server/routes/events/handlers/emit.ts +15 -0
  27. package/templates/sveltekit-app/src/server/routes/events/index.ts +19 -0
  28. package/templates/sveltekit-app/src/server/routes/index.ts +8 -0
  29. package/templates/sveltekit-app/src/server/routes/jobs/handlers/enqueue.ts +15 -0
  30. package/templates/sveltekit-app/src/server/routes/jobs/handlers/stats.ts +15 -0
  31. package/templates/sveltekit-app/src/server/routes/jobs/index.ts +28 -0
  32. package/templates/sveltekit-app/src/server/routes/ratelimit/handlers/check.ts +15 -0
  33. package/templates/sveltekit-app/src/server/routes/ratelimit/handlers/reset.ts +15 -0
  34. package/templates/sveltekit-app/src/server/routes/ratelimit/index.ts +29 -0
  35. package/templates/sveltekit-app/src/server/routes/sse/handlers/broadcast.ts +15 -0
  36. package/templates/sveltekit-app/src/server/routes/sse/handlers/clients.ts +15 -0
  37. package/templates/sveltekit-app/src/server/routes/sse/index.ts +28 -0
  38. package/templates/sveltekit-app/{svelte.config.js → svelte.config.ts} +3 -2
  39. package/templates/starter/CLAUDE.md +0 -144
  40. package/templates/starter/src/client.test.ts +0 -7
  41. package/templates/starter/src/db.ts +0 -9
  42. package/templates/starter/src/routes/health/ping/index.ts +0 -13
  43. package/templates/starter/src/routes/health/ping/models/model.ts +0 -23
  44. package/templates/starter/src/routes/health/ping/schema.ts +0 -14
  45. package/templates/starter/src/routes/health/ping/tests/integ.test.ts +0 -20
  46. package/templates/starter/src/routes/health/ping/tests/unit.test.ts +0 -21
  47. package/templates/starter/src/test-ctx.ts +0 -24
@@ -84,55 +84,164 @@ interface ExtractedRoute {
84
84
  handler: string;
85
85
  }
86
86
 
87
- async function extractRoutesFromServer(entryPath: string): Promise<ExtractedRoute[]> {
88
- const fullPath = join(process.cwd(), entryPath);
87
+ interface RouteInfo {
88
+ name: string;
89
+ prefix: string;
90
+ routeName: string;
91
+ handler: "typed" | "raw" | string;
92
+ inputSource?: string;
93
+ outputSource?: string;
94
+ }
95
+
96
+ /**
97
+ * Extract a balanced block from source code starting at a given position
98
+ */
99
+ function extractBalancedBlock(source: string, startPos: number, open = "{", close = "}"): string {
100
+ let depth = 0;
101
+ let start = -1;
102
+ let end = -1;
103
+
104
+ for (let i = startPos; i < source.length; i++) {
105
+ if (source[i] === open) {
106
+ if (depth === 0) start = i;
107
+ depth++;
108
+ } else if (source[i] === close) {
109
+ depth--;
110
+ if (depth === 0) {
111
+ end = i;
112
+ break;
113
+ }
114
+ }
115
+ }
116
+
117
+ if (start !== -1 && end !== -1) {
118
+ return source.slice(start, end + 1);
119
+ }
120
+ return "";
121
+ }
122
+
123
+ /**
124
+ * Extract Zod schema from input/output definition
125
+ */
126
+ function extractZodSchema(configBlock: string, key: "input" | "output"): string | undefined {
127
+ // Find where the key starts
128
+ const keyPattern = new RegExp(`${key}\\s*:\\s*`);
129
+ const match = configBlock.match(keyPattern);
130
+ if (!match || match.index === undefined) return undefined;
131
+
132
+ const startPos = match.index + match[0].length;
133
+
134
+ // Check if it starts with z.
135
+ const afterKey = configBlock.slice(startPos);
136
+ if (!afterKey.startsWith("z.")) return undefined;
137
+
138
+ // Find the end of the Zod expression by tracking parentheses
139
+ let depth = 0;
140
+ let endPos = 0;
141
+ let inParen = false;
142
+
143
+ for (let i = 0; i < afterKey.length; i++) {
144
+ const char = afterKey[i];
145
+
146
+ if (char === "(") {
147
+ depth++;
148
+ inParen = true;
149
+ } else if (char === ")") {
150
+ depth--;
151
+ if (depth === 0 && inParen) {
152
+ endPos = i + 1;
153
+ // Check for chained methods like .optional()
154
+ const rest = afterKey.slice(endPos);
155
+ const chainMatch = rest.match(/^\s*\.\w+\(\)/);
156
+ if (chainMatch) {
157
+ endPos += chainMatch[0].length;
158
+ }
159
+ break;
160
+ }
161
+ } else if (depth === 0 && inParen) {
162
+ break;
163
+ }
164
+ }
165
+
166
+ if (endPos > 0) {
167
+ return afterKey.slice(0, endPos).trim();
168
+ }
169
+ return undefined;
170
+ }
171
+
172
+ /**
173
+ * Extract routes from a server/router source file by parsing the code
174
+ */
175
+ async function extractRoutesFromSource(filePath: string): Promise<RouteInfo[]> {
176
+ const fullPath = join(process.cwd(), filePath);
89
177
 
90
178
  if (!existsSync(fullPath)) {
91
- console.warn(pc.yellow(`Entry file not found: ${entryPath}, skipping route extraction`));
179
+ console.warn(pc.yellow(`Entry file not found: ${filePath}, skipping route extraction`));
92
180
  return [];
93
181
  }
94
182
 
95
- return new Promise((resolve) => {
96
- const child = spawn("bun", [fullPath], {
97
- env: { ...process.env, DONKEYLABS_GENERATE: "1" },
98
- stdio: ["inherit", "pipe", "pipe"],
99
- cwd: process.cwd(),
100
- });
183
+ const content = await readFile(fullPath, "utf-8");
184
+ const routes: RouteInfo[] = [];
101
185
 
102
- let stdout = "";
103
- let stderr = "";
186
+ // Find all createRouter calls with their positions
187
+ const routerPattern = /createRouter\s*\(\s*["']([^"']+)["']\s*\)/g;
188
+ const routerPositions: { prefix: string; pos: number }[] = [];
104
189
 
105
- child.stdout?.on("data", (data) => {
106
- stdout += data.toString();
190
+ let routerMatch;
191
+ while ((routerMatch = routerPattern.exec(content)) !== null) {
192
+ routerPositions.push({
193
+ prefix: routerMatch[1] || "",
194
+ pos: routerMatch.index,
107
195
  });
196
+ }
108
197
 
109
- child.stderr?.on("data", (data) => {
110
- stderr += data.toString();
111
- });
198
+ // Sort by position
199
+ routerPositions.sort((a, b) => a.pos - b.pos);
112
200
 
113
- child.on("close", (code) => {
114
- if (code !== 0) {
115
- console.warn(pc.yellow(`Failed to extract routes from server (exit code ${code})`));
116
- if (stderr) console.warn(pc.dim(stderr));
117
- resolve([]);
118
- return;
119
- }
201
+ // Find all route definitions with their positions
202
+ const routePattern = /\.route\s*\(\s*["']([^"']+)["']\s*\)\s*\.(typed|raw|[\w]+)\s*\(/g;
120
203
 
121
- try {
122
- // Parse the JSON output from server
123
- const result = JSON.parse(stdout.trim());
124
- resolve(result.routes || []);
125
- } catch (e) {
126
- console.warn(pc.yellow("Failed to parse route data from server"));
127
- resolve([]);
204
+ let routeMatch;
205
+ while ((routeMatch = routePattern.exec(content)) !== null) {
206
+ const routeName = routeMatch[1] || "";
207
+ const handler = routeMatch[2] || "typed";
208
+ const routePos = routeMatch.index;
209
+
210
+ // Find which router this route belongs to (most recent one before this position)
211
+ let currentPrefix = "";
212
+ for (const router of routerPositions) {
213
+ if (router.pos < routePos) {
214
+ currentPrefix = router.prefix;
215
+ } else {
216
+ break;
128
217
  }
129
- });
218
+ }
130
219
 
131
- child.on("error", (err) => {
132
- console.warn(pc.yellow(`Failed to run entry file: ${err.message}`));
133
- resolve([]);
220
+ // Extract the config block
221
+ const configStartPos = routeMatch.index + routeMatch[0].length - 1; // Position of the (
222
+ const configBlock = extractBalancedBlock(content, configStartPos, "(", ")");
223
+
224
+ // Remove outer parens and the inner braces wrapper
225
+ let innerConfig = configBlock.slice(1, -1).trim(); // Remove ( and )
226
+ if (innerConfig.startsWith("{") && innerConfig.endsWith("}")) {
227
+ innerConfig = innerConfig.slice(1, -1); // Remove { and }
228
+ }
229
+
230
+ // Extract input and output schemas
231
+ const inputSource = extractZodSchema(innerConfig, "input");
232
+ const outputSource = extractZodSchema(innerConfig, "output");
233
+
234
+ routes.push({
235
+ name: currentPrefix ? `${currentPrefix}.${routeName}` : routeName,
236
+ prefix: currentPrefix,
237
+ routeName,
238
+ handler,
239
+ inputSource,
240
+ outputSource,
134
241
  });
135
- });
242
+ }
243
+
244
+ return routes;
136
245
  }
137
246
 
138
247
 
@@ -179,6 +288,98 @@ async function findPlugins(
179
288
  return plugins;
180
289
  }
181
290
 
291
+ async function findRouteFiles(pattern: string): Promise<string[]> {
292
+ const files: string[] = [];
293
+ const baseDir = pattern.includes("**")
294
+ ? pattern.split("**")[0] || "."
295
+ : dirname(pattern);
296
+ const fileName = basename(pattern.replace("**/", ""));
297
+
298
+ const targetDir = join(process.cwd(), baseDir);
299
+ if (!existsSync(targetDir)) return files;
300
+
301
+ async function scanDir(dir: string): Promise<void> {
302
+ const entries = await readdir(dir, { withFileTypes: true });
303
+ for (const entry of entries) {
304
+ const fullPath = join(dir, entry.name);
305
+ if (entry.isDirectory()) {
306
+ await scanDir(fullPath);
307
+ } else if (entry.name === fileName) {
308
+ files.push(relative(process.cwd(), fullPath));
309
+ }
310
+ }
311
+ }
312
+
313
+ await scanDir(targetDir);
314
+ return files;
315
+ }
316
+
317
+ /**
318
+ * Run the server entry file with DONKEYLABS_GENERATE=1 to get typed route metadata
319
+ */
320
+ async function extractRoutesFromServer(entryPath: string): Promise<RouteInfo[]> {
321
+ const fullPath = join(process.cwd(), entryPath);
322
+
323
+ if (!existsSync(fullPath)) {
324
+ console.warn(pc.yellow(`Entry file not found: ${entryPath}`));
325
+ return [];
326
+ }
327
+
328
+ return new Promise((resolve) => {
329
+ const child = spawn("bun", [fullPath], {
330
+ env: { ...process.env, DONKEYLABS_GENERATE: "1" },
331
+ stdio: ["inherit", "pipe", "pipe"],
332
+ cwd: process.cwd(),
333
+ });
334
+
335
+ let stdout = "";
336
+ let stderr = "";
337
+
338
+ child.stdout?.on("data", (data) => {
339
+ stdout += data.toString();
340
+ });
341
+
342
+ child.stderr?.on("data", (data) => {
343
+ stderr += data.toString();
344
+ });
345
+
346
+ child.on("close", (code) => {
347
+ if (code !== 0) {
348
+ console.warn(pc.yellow(`Failed to extract routes from server (exit code ${code})`));
349
+ if (stderr) console.warn(pc.dim(stderr));
350
+ resolve([]);
351
+ return;
352
+ }
353
+
354
+ try {
355
+ const result = JSON.parse(stdout.trim());
356
+ // Convert server output to RouteInfo format
357
+ const routes: RouteInfo[] = (result.routes || []).map((r: any) => {
358
+ const parts = r.name.split(".");
359
+ return {
360
+ name: r.name,
361
+ prefix: parts.slice(0, -1).join("."),
362
+ routeName: parts[parts.length - 1] || r.name,
363
+ handler: r.handler || "typed",
364
+ // Server outputs TypeScript strings directly now
365
+ inputSource: r.inputType,
366
+ outputSource: r.outputType,
367
+ };
368
+ });
369
+ resolve(routes);
370
+ } catch (e) {
371
+ console.warn(pc.yellow("Failed to parse route data from server"));
372
+ resolve([]);
373
+ }
374
+ });
375
+
376
+ child.on("error", (err) => {
377
+ console.warn(pc.yellow(`Failed to run entry file: ${err.message}`));
378
+ resolve([]);
379
+ });
380
+ });
381
+ }
382
+
182
383
  export async function generateCommand(_args: string[]): Promise<void> {
183
384
  const config = await loadConfig();
184
385
  const outDir = config.outDir || ".@donkeylabs/server";
@@ -189,7 +390,7 @@ export async function generateCommand(_args: string[]): Promise<void> {
189
390
  const plugins = await findPlugins(config.plugins);
190
391
  const fileRoutes = await findRoutes(config.routes || "./src/routes/**/schema.ts");
191
392
 
192
- // Extract routes from server entry file
393
+ // Extract routes by running the server with DONKEYLABS_GENERATE=1
193
394
  const entryPath = config.entry || "./src/index.ts";
194
395
  const serverRoutes = await extractRoutesFromServer(entryPath);
195
396
 
@@ -391,14 +592,14 @@ export type GlobalContext = AppContext;
391
592
  }
392
593
 
393
594
  // Route file structure: /src/routes/<namespace>/<route-name>/schema.ts
394
- interface RouteInfo {
595
+ interface SchemaRouteInfo {
395
596
  namespace: string;
396
597
  name: string;
397
598
  schemaPath: string;
398
599
  }
399
600
 
400
- async function findRoutes(_pattern: string): Promise<RouteInfo[]> {
401
- const routes: RouteInfo[] = [];
601
+ async function findRoutes(_pattern: string): Promise<SchemaRouteInfo[]> {
602
+ const routes: SchemaRouteInfo[] = [];
402
603
  const routesDir = join(process.cwd(), "src/routes");
403
604
 
404
605
  if (!existsSync(routesDir)) {
@@ -438,9 +639,9 @@ function toPascalCase(str: string): string {
438
639
  .replace(/^./, (c) => c.toUpperCase());
439
640
  }
440
641
 
441
- async function generateRouteTypes(routes: RouteInfo[], outPath: string): Promise<void> {
642
+ async function generateRouteTypes(routes: SchemaRouteInfo[], outPath: string): Promise<void> {
442
643
  // Group routes by namespace
443
- const byNamespace = new Map<string, RouteInfo[]>();
644
+ const byNamespace = new Map<string, SchemaRouteInfo[]>();
444
645
  for (const route of routes) {
445
646
  if (!byNamespace.has(route.namespace)) {
446
647
  byNamespace.set(route.namespace, []);
@@ -1,48 +1,37 @@
1
1
  import { db } from "./db";
2
- import { AppServer } from "@donkeylabs/server";
2
+ import { AppServer, createRouter } from "@donkeylabs/server";
3
3
  import { healthRouter } from "./routes/health";
4
4
  import { statsPlugin } from "./plugins/stats";
5
- import { z } from "zod";
6
5
 
7
6
  const server = new AppServer({
8
7
  port: Number(process.env.PORT) || 3000,
9
8
  db,
10
9
  config: { env: process.env.NODE_ENV || "development" },
10
+ generateTypes: {
11
+ output: "./.@donkeylabs/server/api.ts",
12
+ baseImport: 'import { ApiClientBase, type ApiClientOptions } from "@donkeylabs/server/client";',
13
+ baseClass: "ApiClientBase",
14
+ constructorSignature: "baseUrl: string, options?: ApiClientOptions",
15
+ constructorBody: "super(baseUrl, options);",
16
+ factoryFunction: `/**
17
+ * Create an API client instance
18
+ * @param baseUrl - The base URL of the API server
19
+ */
20
+ export function createApi(baseUrl: string, options?: ApiClientOptions) {
21
+ return new ApiClient(baseUrl, options);
22
+ }`,
23
+ },
11
24
  });
12
25
 
13
26
  // Register plugins
14
27
  server.registerPlugin(statsPlugin);
15
28
 
16
- // Register routes with middleware applied at router level
29
+ const api = createRouter("api")
30
+ // Register routes
31
+ api.router(healthRouter);
17
32
 
18
- const api = server.router("api")
19
- .middleware
20
- .timing()
21
33
 
22
- const hello = api.router("hello")
23
- hello.route("test").typed({
24
- input: z.string(),
25
- output: z.string(),
26
- handle: (input, ctx) => {
27
- // ctx.plugins.stats should now be typed correctly
28
- const stats = ctx.plugins.stats;
29
- return input;
30
- }
31
- }).route("ping").typed({
32
- input: z.string(),
33
- output: z.string(),
34
- handle: (input, ctx) => {
35
- return input;
36
- }
37
- })
38
- .route("pong").typed({
39
- input: z.string(),
40
- output: z.string(),
41
- handle: (input, ctx) => {
42
- return input;
43
- }
44
- })
45
34
 
46
- api.router(healthRouter)
47
35
 
36
+ server.use(api);
48
37
  await server.start();
@@ -0,0 +1,22 @@
1
+
2
+ // Types from generated api.ts (run server once to generate)
3
+ import type { Handler, Routes, AppContext } from "$server/api";
4
+
5
+ /**
6
+ * Ping Handler
7
+ */
8
+ export class PingHandler implements Handler<Routes.Api.Health.Ping> {
9
+ ctx: AppContext;
10
+
11
+ constructor(ctx: AppContext) {
12
+ this.ctx = ctx;
13
+ }
14
+
15
+ handle(input: Routes.Api.Health.Ping.Input): Routes.Api.Health.Ping.Output {
16
+ return {
17
+ status: "ok",
18
+ timestamp: new Date().toISOString(),
19
+ echo: input.echo,
20
+ };
21
+ }
22
+ }
@@ -1,5 +1,19 @@
1
+
1
2
  import { createRouter } from "@donkeylabs/server";
2
- import { pingRoute } from "./ping";
3
+ import { z } from "zod";
4
+ import { PingHandler } from "./handlers/ping";
3
5
 
4
6
  export const healthRouter = createRouter("health")
5
- .route("ping").typed(pingRoute);
7
+ .route("ping").typed({
8
+ input: z.object({
9
+ name: z.string(),
10
+ cool: z.number(),
11
+ echo: z.string().optional(),
12
+ }),
13
+ output: z.object({
14
+ status: z.literal("ok"),
15
+ timestamp: z.string(),
16
+ echo: z.string().optional(),
17
+ }),
18
+ handle: PingHandler,
19
+ });
@@ -4,9 +4,9 @@
4
4
  "": {
5
5
  "name": "my-sveltekit-app",
6
6
  "dependencies": {
7
- "@donkeylabs/adapter-sveltekit": "0.1.1",
8
- "@donkeylabs/cli": "0.1.0",
9
- "@donkeylabs/server": "0.3.1",
7
+ "@donkeylabs/adapter-sveltekit": "^0.4.0",
8
+ "@donkeylabs/cli": "^0.4.0",
9
+ "@donkeylabs/server": "^0.4.0",
10
10
  "bits-ui": "^2.15.4",
11
11
  "clsx": "^2.1.1",
12
12
  "kysely": "^0.27.6",
@@ -28,11 +28,11 @@
28
28
  },
29
29
  },
30
30
  "packages": {
31
- "@donkeylabs/adapter-sveltekit": ["@donkeylabs/adapter-sveltekit@0.1.1", "", { "peerDependencies": { "@donkeylabs/server": "*", "@sveltejs/kit": "^2.0.0" } }, "sha512-CokdEH6+vBoNvM1HYXp1/kd8WYEokEY/MrAToGE+QlcQ+gd5x74X+Yu792WX+C+ntM4oVFqMQToHxr6m46/n1w=="],
31
+ "@donkeylabs/adapter-sveltekit": ["@donkeylabs/adapter-sveltekit@0.4.0", "", { "peerDependencies": { "@donkeylabs/server": "^0.4.0", "@sveltejs/kit": "^2.0.0" } }, "sha512-J1kcwhp8X0egAhjC/HyxEizR3aEP7ea08rfAh0++C31UldM3ahAjO3Ux0QYp+fAV76lh8mKrDNAWIsKTyPmqNg=="],
32
32
 
33
- "@donkeylabs/cli": ["@donkeylabs/cli@0.1.0", "", { "dependencies": { "picocolors": "^1.1.1", "prompts": "^2.4.2" }, "peerDependencies": { "@donkeylabs/server": "*" }, "bin": { "donkeylabs": "src/index.ts" } }, "sha512-aIvXr/wLGET/+JvLny7m4Jid1NYQWX9Js2z3KmQRGq6T4JPddpzZ3lmz9SalqqWMowkVODZNWew4y5QSBbe9CA=="],
33
+ "@donkeylabs/cli": ["@donkeylabs/cli@0.4.0", "", { "dependencies": { "picocolors": "^1.1.1", "prompts": "^2.4.2" }, "peerDependencies": { "@donkeylabs/server": "^0.4.0" }, "bin": { "donkeylabs": "src/index.ts" } }, "sha512-5Y5oXOzFrhdPMAprij5d/D1r9tcjDRuZo1Ud3zSkGTvVxfejMQjbzrB8KmxFM4+7TBJdjuduvhNewL5V6XnUlA=="],
34
34
 
35
- "@donkeylabs/server": ["@donkeylabs/server@0.3.1", "", { "dependencies": { "@modelcontextprotocol/sdk": "^1.25.2", "picocolors": "^1.1.1", "prompts": "^2.4.2" }, "peerDependencies": { "kysely": "^0.27.0 || ^0.28.0", "typescript": "^5", "zod": "^3.20.0" }, "bin": { "donkeylabs-mcp": "mcp/server.ts" } }, "sha512-rpYKD7dKNwpcw51aO/pL1Zh1r6FlAqp0UIUJ+9nV1Cm/4hKq6WQHM/AtmPhM25ZRvnSbriB4X8o28UVJR8dN2w=="],
35
+ "@donkeylabs/server": ["@donkeylabs/server@0.4.0", "", { "dependencies": { "@modelcontextprotocol/sdk": "^1.25.2", "picocolors": "^1.1.1", "prompts": "^2.4.2" }, "peerDependencies": { "kysely": "^0.27.0 || ^0.28.0", "typescript": "^5", "zod": "^3.20.0" } }, "sha512-Nr7kgKtyqM5EDFTmUL2kyEqCW/NeJiQgYQL4Y3DnphM9rgHz07Qi2mgPs8McYFvrWGUVFRMvzXa6CZILY896bw=="],
36
36
 
37
37
  "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw=="],
38
38
 
@@ -4,6 +4,7 @@ export default defineConfig({
4
4
  plugins: ["./src/server/plugins/**/index.ts"],
5
5
  outDir: ".@donkeylabs/server",
6
6
  entry: "./src/server/index.ts",
7
+ routes: "./src/server/routes/**/{route,index}.ts",
7
8
  adapter: "@donkeylabs/adapter-sveltekit",
8
9
  client: {
9
10
  output: "./src/lib/api.ts",
@@ -8,8 +8,8 @@
8
8
  "dev:watch": "bun --watch --no-clear-screen scripts/watch-server.ts",
9
9
  "build": "bun run gen:types && vite build",
10
10
  "preview": "bun build/server/entry.js",
11
- "prepare": "svelte-kit sync || echo ''",
12
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
11
+ "prepare": "bun --bun svelte-kit sync || echo ''",
12
+ "check": "bun --bun svelte-kit sync && bun --bun svelte-check --tsconfig ./tsconfig.json",
13
13
  "gen:types": "donkeylabs generate",
14
14
  "cli": "donkeylabs"
15
15
  },
@@ -24,9 +24,9 @@
24
24
  "vite": "^7.2.6"
25
25
  },
26
26
  "dependencies": {
27
- "@donkeylabs/cli": "0.1.1",
28
- "@donkeylabs/adapter-sveltekit": "0.1.2",
29
- "@donkeylabs/server": "0.3.1",
27
+ "@donkeylabs/cli": "^0.4.0",
28
+ "@donkeylabs/adapter-sveltekit": "^0.4.0",
29
+ "@donkeylabs/server": "^0.4.0",
30
30
  "bits-ui": "^2.15.4",
31
31
  "clsx": "^2.1.1",
32
32
  "kysely": "^0.27.6",