@donkeylabs/server 0.1.3 → 0.1.4

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 (55) hide show
  1. package/examples/starter/node_modules/@donkeylabs/server/README.md +15 -0
  2. package/examples/starter/node_modules/@donkeylabs/server/cli/commands/generate.ts +461 -0
  3. package/examples/starter/node_modules/@donkeylabs/server/cli/commands/init.ts +476 -0
  4. package/examples/starter/node_modules/@donkeylabs/server/cli/commands/interactive.ts +223 -0
  5. package/examples/starter/node_modules/@donkeylabs/server/cli/commands/plugin.ts +192 -0
  6. package/examples/starter/node_modules/@donkeylabs/server/cli/donkeylabs +106 -0
  7. package/examples/starter/node_modules/@donkeylabs/server/cli/index.ts +100 -0
  8. package/examples/starter/node_modules/@donkeylabs/server/context.d.ts +17 -0
  9. package/examples/starter/node_modules/@donkeylabs/server/docs/api-client.md +520 -0
  10. package/examples/starter/node_modules/@donkeylabs/server/docs/cache.md +437 -0
  11. package/examples/starter/node_modules/@donkeylabs/server/docs/cli.md +353 -0
  12. package/examples/starter/node_modules/@donkeylabs/server/docs/core-services.md +338 -0
  13. package/examples/starter/node_modules/@donkeylabs/server/docs/cron.md +465 -0
  14. package/examples/starter/node_modules/@donkeylabs/server/docs/errors.md +303 -0
  15. package/examples/starter/node_modules/@donkeylabs/server/docs/events.md +460 -0
  16. package/examples/starter/node_modules/@donkeylabs/server/docs/handlers.md +549 -0
  17. package/examples/starter/node_modules/@donkeylabs/server/docs/jobs.md +556 -0
  18. package/examples/starter/node_modules/@donkeylabs/server/docs/logger.md +316 -0
  19. package/examples/starter/node_modules/@donkeylabs/server/docs/middleware.md +682 -0
  20. package/examples/starter/node_modules/@donkeylabs/server/docs/plugins.md +524 -0
  21. package/examples/starter/node_modules/@donkeylabs/server/docs/project-structure.md +493 -0
  22. package/examples/starter/node_modules/@donkeylabs/server/docs/rate-limiter.md +525 -0
  23. package/examples/starter/node_modules/@donkeylabs/server/docs/router.md +566 -0
  24. package/examples/starter/node_modules/@donkeylabs/server/docs/sse.md +542 -0
  25. package/examples/starter/node_modules/@donkeylabs/server/docs/svelte-frontend.md +324 -0
  26. package/examples/starter/node_modules/@donkeylabs/server/mcp/donkeylabs-mcp +3238 -0
  27. package/examples/starter/node_modules/@donkeylabs/server/mcp/server.ts +3238 -0
  28. package/examples/starter/node_modules/@donkeylabs/server/package.json +77 -0
  29. package/examples/starter/node_modules/@donkeylabs/server/registry.d.ts +11 -0
  30. package/examples/starter/node_modules/@donkeylabs/server/src/client/base.ts +481 -0
  31. package/examples/starter/node_modules/@donkeylabs/server/src/client/index.ts +150 -0
  32. package/examples/starter/node_modules/@donkeylabs/server/src/core/cache.ts +183 -0
  33. package/examples/starter/node_modules/@donkeylabs/server/src/core/cron.ts +255 -0
  34. package/examples/starter/node_modules/@donkeylabs/server/src/core/errors.ts +320 -0
  35. package/examples/starter/node_modules/@donkeylabs/server/src/core/events.ts +163 -0
  36. package/examples/starter/node_modules/@donkeylabs/server/src/core/index.ts +94 -0
  37. package/examples/starter/node_modules/@donkeylabs/server/src/core/jobs.ts +334 -0
  38. package/examples/starter/node_modules/@donkeylabs/server/src/core/logger.ts +131 -0
  39. package/examples/starter/node_modules/@donkeylabs/server/src/core/rate-limiter.ts +193 -0
  40. package/examples/starter/node_modules/@donkeylabs/server/src/core/sse.ts +210 -0
  41. package/examples/starter/node_modules/@donkeylabs/server/src/core.ts +428 -0
  42. package/examples/starter/node_modules/@donkeylabs/server/src/handlers.ts +87 -0
  43. package/examples/starter/node_modules/@donkeylabs/server/src/harness.ts +70 -0
  44. package/examples/starter/node_modules/@donkeylabs/server/src/index.ts +38 -0
  45. package/examples/starter/node_modules/@donkeylabs/server/src/middleware.ts +34 -0
  46. package/examples/starter/node_modules/@donkeylabs/server/src/registry.ts +13 -0
  47. package/examples/starter/node_modules/@donkeylabs/server/src/router.ts +155 -0
  48. package/examples/starter/node_modules/@donkeylabs/server/src/server.ts +234 -0
  49. package/examples/starter/node_modules/@donkeylabs/server/templates/init/donkeylabs.config.ts.template +14 -0
  50. package/examples/starter/node_modules/@donkeylabs/server/templates/init/index.ts.template +41 -0
  51. package/examples/starter/node_modules/@donkeylabs/server/templates/plugin/index.ts.template +25 -0
  52. package/examples/starter/src/routes/health/ping/models/model.ts +11 -7
  53. package/package.json +3 -3
  54. package/examples/starter/node_modules/.svelte2tsx-language-server-files/svelte-native-jsx.d.ts +0 -32
  55. package/examples/starter/node_modules/.svelte2tsx-language-server-files/svelte-shims-v4.d.ts +0 -290
@@ -0,0 +1,192 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { existsSync } from "node:fs";
4
+ import pc from "picocolors";
5
+ import prompts from "prompts";
6
+
7
+ export async function pluginCommand(args: string[]): Promise<void> {
8
+ const subcommand = args[0];
9
+
10
+ switch (subcommand) {
11
+ case "create":
12
+ case "new":
13
+ await createPlugin(args[1]);
14
+ break;
15
+
16
+ case "list":
17
+ await listPlugins();
18
+ break;
19
+
20
+ default:
21
+ console.log(`
22
+ ${pc.bold("Plugin Management")}
23
+
24
+ ${pc.bold("Commands:")}
25
+ ${pc.cyan("create <name>")} Create a new plugin
26
+ ${pc.cyan("list")} List installed plugins
27
+
28
+ ${pc.bold("Examples:")}
29
+ donkeylabs plugin create auth
30
+ donkeylabs plugin list
31
+ `);
32
+ }
33
+ }
34
+
35
+ async function createPlugin(name?: string): Promise<void> {
36
+ if (!name) {
37
+ const response = await prompts({
38
+ type: "text",
39
+ name: "name",
40
+ message: "Plugin name:",
41
+ validate: (v) =>
42
+ /^[a-z][a-z0-9-]*$/.test(v) ||
43
+ "Name must be lowercase alphanumeric with dashes",
44
+ });
45
+ name = response.name;
46
+ }
47
+
48
+ if (!name) {
49
+ console.log(pc.yellow("Cancelled."));
50
+ return;
51
+ }
52
+
53
+ const { hasSchema, hasDependencies } = await prompts([
54
+ {
55
+ type: "confirm",
56
+ name: "hasSchema",
57
+ message: "Does this plugin need a database schema?",
58
+ initial: false,
59
+ },
60
+ {
61
+ type: "confirm",
62
+ name: "hasDependencies",
63
+ message: "Does this plugin depend on other plugins?",
64
+ initial: false,
65
+ },
66
+ ]);
67
+
68
+ let dependencies: string[] = [];
69
+ if (hasDependencies) {
70
+ const { deps } = await prompts({
71
+ type: "list",
72
+ name: "deps",
73
+ message: "Enter dependency names (comma-separated):",
74
+ separator: ",",
75
+ });
76
+ dependencies = deps?.filter(Boolean) || [];
77
+ }
78
+
79
+ const pluginDir = join(process.cwd(), "src/plugins", name);
80
+
81
+ if (existsSync(pluginDir)) {
82
+ console.log(pc.red(`Plugin directory already exists: ${pluginDir}`));
83
+ return;
84
+ }
85
+
86
+ await mkdir(pluginDir, { recursive: true });
87
+
88
+ const camelName = name.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
89
+ const pascalName = camelName.charAt(0).toUpperCase() + camelName.slice(1);
90
+
91
+ const schemaImport = hasSchema
92
+ ? `import type { DB as ${pascalName}Schema } from "./schema";\n`
93
+ : "";
94
+
95
+ const schemaType = hasSchema ? `<${pascalName}Schema>()` : "";
96
+
97
+ const depsLine =
98
+ dependencies.length > 0
99
+ ? ` dependencies: [${dependencies.map((d) => `"${d}"`).join(", ")}] as const,\n`
100
+ : "";
101
+
102
+ const pluginContent = `import { createPlugin } from "@donkeylabs/server";
103
+ ${schemaImport}
104
+ export interface ${pascalName}Service {
105
+ // Define your service interface here
106
+ getData(): Promise<string>;
107
+ }
108
+
109
+ export const ${camelName}Plugin = createPlugin${hasSchema ? `\n .withSchema${schemaType}` : ""}
110
+ .define({
111
+ name: "${name}",
112
+ version: "1.0.0",
113
+ ${depsLine}
114
+ service: async (ctx): Promise<${pascalName}Service> => {
115
+ console.log("[${pascalName}Plugin] Initializing...");
116
+ ${
117
+ dependencies.length > 0
118
+ ? dependencies.map((d) => ` // Access ${d} via: ctx.deps.${d}`).join("\n") + "\n"
119
+ : ""
120
+ }
121
+ return {
122
+ getData: async () => {
123
+ return "Hello from ${name} plugin!";
124
+ },
125
+ };
126
+ },
127
+ });
128
+ `;
129
+
130
+ await writeFile(join(pluginDir, "index.ts"), pluginContent);
131
+ console.log(pc.green(" Created:"), `src/plugins/${name}/index.ts`);
132
+
133
+ if (hasSchema) {
134
+ const schemaContent = `// Database schema types for ${name} plugin
135
+ // Run \`bun run gen:types\` to regenerate from database
136
+
137
+ export interface DB {
138
+ // Define your table interfaces here
139
+ // Example:
140
+ // ${name}: {
141
+ // id: Generated<number>;
142
+ // name: string;
143
+ // created_at: Generated<string>;
144
+ // };
145
+ }
146
+ `;
147
+ await writeFile(join(pluginDir, "schema.ts"), schemaContent);
148
+ console.log(pc.green(" Created:"), `src/plugins/${name}/schema.ts`);
149
+
150
+ await mkdir(join(pluginDir, "migrations"), { recursive: true });
151
+
152
+ const migrationContent = `import { Kysely } from "kysely";
153
+
154
+ export async function up(db: Kysely<any>) {
155
+ // Create your tables here
156
+ // await db.schema
157
+ // .createTable("${name}")
158
+ // .ifNotExists()
159
+ // .addColumn("id", "integer", (col) => col.primaryKey().autoIncrement())
160
+ // .addColumn("name", "text", (col) => col.notNull())
161
+ // .addColumn("created_at", "text", (col) => col.defaultTo(sql\`CURRENT_TIMESTAMP\`))
162
+ // .execute();
163
+ }
164
+
165
+ export async function down(db: Kysely<any>) {
166
+ // Drop your tables here
167
+ // await db.schema.dropTable("${name}").ifExists().execute();
168
+ }
169
+ `;
170
+ await writeFile(
171
+ join(pluginDir, "migrations", "001_initial.ts"),
172
+ migrationContent
173
+ );
174
+ console.log(
175
+ pc.green(" Created:"),
176
+ `src/plugins/${name}/migrations/001_initial.ts`
177
+ );
178
+ }
179
+
180
+ console.log(`
181
+ ${pc.bold(pc.green("Plugin created!"))}
182
+
183
+ ${pc.bold("Next steps:")}
184
+ 1. Edit your plugin at ${pc.cyan(`src/plugins/${name}/index.ts`)}
185
+ ${hasSchema ? ` 2. Define your schema in ${pc.cyan(`src/plugins/${name}/schema.ts`)}\n 3. Add migrations in ${pc.cyan(`src/plugins/${name}/migrations/`)}\n` : ""} ${hasSchema ? "4" : "2"}. Regenerate types: ${pc.cyan("donkeylabs generate")}
186
+ `);
187
+ }
188
+
189
+ async function listPlugins() {
190
+ console.log(pc.yellow("Plugin listing not yet implemented."));
191
+ console.log("Run 'donkeylabs generate' to see discovered plugins.");
192
+ }
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * @donkeylabs/server CLI
4
+ *
5
+ * Commands:
6
+ * init Initialize a new project
7
+ * generate Generate types (registry, context, client)
8
+ * plugin Plugin management (create, list)
9
+ */
10
+
11
+ import { parseArgs } from "node:util";
12
+ import pc from "picocolors";
13
+
14
+ const { positionals, values } = parseArgs({
15
+ args: process.argv.slice(2),
16
+ options: {
17
+ help: { type: "boolean", short: "h" },
18
+ version: { type: "boolean", short: "v" },
19
+ },
20
+ allowPositionals: true,
21
+ });
22
+
23
+ const command = positionals[0];
24
+
25
+ function printHelp() {
26
+ console.log(`
27
+ ${pc.bold("@donkeylabs/server")} - Type-safe plugin system for Bun
28
+
29
+ ${pc.bold("Usage:")}
30
+ donkeylabs Interactive menu
31
+ donkeylabs <command> [options]
32
+
33
+ ${pc.bold("Commands:")}
34
+ ${pc.cyan("init")} Initialize a new project
35
+ ${pc.cyan("generate")} Generate types (registry, context, client)
36
+ ${pc.cyan("plugin")} Plugin management
37
+ ${pc.cyan("mcp")} Start MCP server for AI assistants
38
+
39
+ ${pc.bold("Options:")}
40
+ -h, --help Show this help message
41
+ -v, --version Show version number
42
+
43
+ ${pc.bold("Examples:")}
44
+ donkeylabs # Interactive menu
45
+ donkeylabs init
46
+ donkeylabs generate
47
+ donkeylabs plugin create myPlugin
48
+ `);
49
+ }
50
+
51
+ function printVersion() {
52
+ // Read from package.json
53
+ console.log("0.1.0");
54
+ }
55
+
56
+ async function main() {
57
+ if (values.help) {
58
+ printHelp();
59
+ process.exit(0);
60
+ }
61
+
62
+ if (values.version) {
63
+ printVersion();
64
+ process.exit(0);
65
+ }
66
+
67
+ // No command provided - launch interactive mode
68
+ if (!command) {
69
+ const { interactiveCommand } = await import("./commands/interactive");
70
+ await interactiveCommand();
71
+ return;
72
+ }
73
+
74
+ switch (command) {
75
+ case "init":
76
+ const { initCommand } = await import("./commands/init");
77
+ await initCommand(positionals.slice(1));
78
+ break;
79
+
80
+ case "generate":
81
+ case "gen":
82
+ const { generateCommand } = await import("./commands/generate");
83
+ await generateCommand(positionals.slice(1));
84
+ break;
85
+
86
+ case "plugin":
87
+ const { pluginCommand } = await import("./commands/plugin");
88
+ await pluginCommand(positionals.slice(1));
89
+ break;
90
+
91
+ case "mcp":
92
+ // Run MCP server - import runs it automatically
93
+ await import("../mcp/donkeylabs-mcp");
94
+ break;
95
+
96
+ default:
97
+ console.error(pc.red(`Unknown command: ${command}`));
98
+ console.log(`Run ${pc.cyan("donkeylabs --help")} for available commands.`);
99
+ process.exit(1);
100
+ }
101
+ }
102
+
103
+ main().catch((error) => {
104
+ console.error(pc.red("Error:"), error.message);
105
+ process.exit(1);
106
+ });
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * @donkeylabs/server CLI
4
+ *
5
+ * Commands:
6
+ * init Initialize a new project
7
+ * generate Generate types (registry, context, client)
8
+ * plugin Plugin management (create, list)
9
+ */
10
+
11
+ import { parseArgs } from "node:util";
12
+ import pc from "picocolors";
13
+
14
+ const { positionals, values } = parseArgs({
15
+ args: process.argv.slice(2),
16
+ options: {
17
+ help: { type: "boolean", short: "h" },
18
+ version: { type: "boolean", short: "v" },
19
+ },
20
+ allowPositionals: true,
21
+ });
22
+
23
+ const command = positionals[0];
24
+
25
+ function printHelp() {
26
+ console.log(`
27
+ ${pc.bold("@donkeylabs/server")} - Type-safe plugin system for Bun
28
+
29
+ ${pc.bold("Usage:")}
30
+ donkeylabs Interactive menu
31
+ donkeylabs <command> [options]
32
+
33
+ ${pc.bold("Commands:")}
34
+ ${pc.cyan("init")} Initialize a new project
35
+ ${pc.cyan("generate")} Generate types (registry, context, client)
36
+ ${pc.cyan("plugin")} Plugin management
37
+
38
+ ${pc.bold("Options:")}
39
+ -h, --help Show this help message
40
+ -v, --version Show version number
41
+
42
+ ${pc.bold("Examples:")}
43
+ donkeylabs # Interactive menu
44
+ donkeylabs init
45
+ donkeylabs generate
46
+ donkeylabs plugin create myPlugin
47
+ `);
48
+ }
49
+
50
+ function printVersion() {
51
+ // Read from package.json
52
+ console.log("0.1.0");
53
+ }
54
+
55
+ async function main() {
56
+ if (values.help) {
57
+ printHelp();
58
+ process.exit(0);
59
+ }
60
+
61
+ if (values.version) {
62
+ printVersion();
63
+ process.exit(0);
64
+ }
65
+
66
+ // No command provided - launch interactive mode
67
+ if (!command) {
68
+ const { interactiveCommand } = await import("./commands/interactive");
69
+ await interactiveCommand();
70
+ return;
71
+ }
72
+
73
+ switch (command) {
74
+ case "init":
75
+ const { initCommand } = await import("./commands/init");
76
+ await initCommand(positionals.slice(1));
77
+ break;
78
+
79
+ case "generate":
80
+ case "gen":
81
+ const { generateCommand } = await import("./commands/generate");
82
+ await generateCommand(positionals.slice(1));
83
+ break;
84
+
85
+ case "plugin":
86
+ const { pluginCommand } = await import("./commands/plugin");
87
+ await pluginCommand(positionals.slice(1));
88
+ break;
89
+
90
+ default:
91
+ console.error(pc.red(`Unknown command: ${command}`));
92
+ console.log(`Run ${pc.cyan("donkeylabs --help")} for available commands.`);
93
+ process.exit(1);
94
+ }
95
+ }
96
+
97
+ main().catch((error) => {
98
+ console.error(pc.red("Error:"), error.message);
99
+ process.exit(1);
100
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Global server context type.
3
+ * This is a stub - run `donkeylabs generate` to create project-specific types.
4
+ */
5
+ import type { Kysely } from "kysely";
6
+ import type { CoreServices } from "./src/core";
7
+
8
+ export interface GlobalContext {
9
+ db: Kysely<any>;
10
+ plugins: Record<string, any>;
11
+ core: Omit<CoreServices, "db" | "config" | "errors">;
12
+ errors: CoreServices["errors"];
13
+ config: Record<string, any>;
14
+ ip: string;
15
+ requestId: string;
16
+ user?: any;
17
+ }