bun-workspaces 1.4.1 → 1.5.0

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 (56) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/src/ai/mcp/bwMcpServer.d.ts +4 -0
  4. package/src/ai/mcp/bwMcpServer.mjs +46 -0
  5. package/src/ai/mcp/core/index.d.ts +3 -0
  6. package/src/ai/mcp/core/index.mjs +3 -0
  7. package/src/ai/mcp/core/server.d.ts +14 -0
  8. package/src/ai/mcp/core/server.mjs +169 -0
  9. package/src/ai/mcp/core/transport.d.ts +12 -0
  10. package/src/ai/mcp/core/transport.mjs +45 -0
  11. package/src/ai/mcp/core/types.d.ts +104 -0
  12. package/src/ai/mcp/core/types.mjs +11 -0
  13. package/src/ai/mcp/index.d.ts +2 -0
  14. package/src/ai/mcp/index.mjs +2 -0
  15. package/src/ai/mcp/resources.d.ts +6 -0
  16. package/src/ai/mcp/resources.mjs +98 -0
  17. package/src/ai/mcp/tools.d.ts +6 -0
  18. package/src/ai/mcp/tools.mjs +210 -0
  19. package/src/cli/commands/commandHandlerUtils.mjs +1 -0
  20. package/src/cli/commands/commands.mjs +3 -0
  21. package/src/cli/commands/commandsConfig.d.ts +14 -0
  22. package/src/cli/commands/commandsConfig.mjs +8 -0
  23. package/src/cli/commands/handleSimpleCommands.mjs +4 -0
  24. package/src/cli/commands/index.d.ts +1 -0
  25. package/src/cli/commands/index.mjs +1 -0
  26. package/src/cli/commands/mcp.d.ts +3 -0
  27. package/src/cli/commands/mcp.mjs +13 -0
  28. package/src/cli/commands/runScript/handleRunScript.mjs +8 -0
  29. package/src/cli/commands/runScript/output/renderGroupedOutput.mjs +4 -2
  30. package/src/cli/createCli.mjs +1 -0
  31. package/src/config/public.d.ts +3 -0
  32. package/src/config/workspaceConfig/workspaceConfig.d.ts +13 -0
  33. package/src/config/workspaceConfig/workspaceConfig.mjs +11 -1
  34. package/src/config/workspaceConfig/workspaceConfigSchema.d.ts +24 -0
  35. package/src/config/workspaceConfig/workspaceConfigSchema.mjs +24 -0
  36. package/src/internal/docs/apiQuickstart.d.ts +3 -0
  37. package/src/internal/docs/apiQuickstart.mjs +132 -0
  38. package/src/internal/docs/cliQuickstart.d.ts +2 -0
  39. package/src/internal/docs/cliQuickstart.mjs +86 -0
  40. package/src/internal/docs/index.d.ts +2 -0
  41. package/src/internal/docs/index.mjs +2 -0
  42. package/src/internal/generated/aiDocs/.gitkeep.mjs +0 -0
  43. package/src/internal/generated/aiDocs/docs.d.ts +10 -0
  44. package/src/internal/generated/aiDocs/docs.mjs +285 -0
  45. package/src/internal/generated/ajv/validateWorkspaceConfig.mjs +1 -1
  46. package/src/runScript/subprocesses.mjs +1 -0
  47. package/src/workspaces/dependencyGraph/index.d.ts +1 -0
  48. package/src/workspaces/dependencyGraph/index.mjs +2 -1
  49. package/src/workspaces/dependencyGraph/validateDependencyRules.d.ts +7 -0
  50. package/src/workspaces/dependencyGraph/validateDependencyRules.mjs +66 -0
  51. package/src/workspaces/errors.d.ts +1 -0
  52. package/src/workspaces/errors.mjs +1 -0
  53. package/src/workspaces/findWorkspaces.d.ts +1 -1
  54. package/src/workspaces/findWorkspaces.mjs +8 -2
  55. package/src/workspaces/workspacePattern.d.ts +1 -0
  56. package/src/workspaces/workspacePattern.mjs +8 -4
package/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
  - Version 1 is here after the initial alpha! 🍔🍔👁️🍔🍔
12
12
  - You can demo the CLI [directly in the browser](https://bunworkspaces.com/web-cli)
13
13
  - There's now [an official blog](https://bunworkspaces.com/blog/bun-workspaces-v1) to cover noteworthy releases and more!
14
+ - There's now a provided [MCP server](https://bunworkspaces.com/ai/mcp) for your AI tooling to understand how to use `bun-workspaces`!
14
15
  <hr/>
15
16
 
16
17
  This is a CLI and TypeScript API to enhance your monorepo development with Bun's [native workspaces](https://bun.sh/docs/install/workspaces) feature for nested JavaScript/TypeScript packages.
@@ -81,6 +82,7 @@ bw run lint --dep-order --ignore-dep-failure
81
82
 
82
83
  bw run lint "my-workspace-*" # Run for matching workspace names
83
84
  bw run lint "alias:my-alias-*" "path:my-glob/**/*" "tag:my-tag" # Use matching specifiers
85
+ bw run lint "*" "not:path:my-path/*" # Run for all workspaces not in my-path/
84
86
 
85
87
  bw run lint --args="--my-appended-args" # Add args to each script call
86
88
  bw run lint --args="--my-arg=<workspaceName>" # Use the workspace name in args
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bun-workspaces",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
4
4
  "description": "A monorepo management tool for Bun, with a CLI and API to enhance Bun's native workspaces.",
5
5
  "license": "MIT",
6
6
  "exports": {
@@ -0,0 +1,4 @@
1
+ import type { FileSystemProject } from "../../project/implementations/fileSystemProject";
2
+ export declare const startBwMcpServer: (
3
+ project: FileSystemProject,
4
+ ) => Promise<void>;
@@ -0,0 +1,46 @@
1
+ import package_0 from "../../../package.json";
2
+ import { API_QUICKSTART } from "../../internal/docs/apiQuickstart.mjs";
3
+ import { CLI_QUICKSTART } from "../../internal/docs/cliQuickstart.mjs";
4
+ import { createMcpServer } from "./core/index.mjs";
5
+ import { registerBwResources } from "./resources.mjs";
6
+ import { registerBwTools } from "./tools.mjs"; // CONCATENATED MODULE: external "../../../package.json"
7
+ // CONCATENATED MODULE: external "../../internal/docs/apiQuickstart.mjs"
8
+ // CONCATENATED MODULE: external "../../internal/docs/cliQuickstart.mjs"
9
+ // CONCATENATED MODULE: external "./core/index.mjs"
10
+ // CONCATENATED MODULE: external "./resources.mjs"
11
+ // CONCATENATED MODULE: external "./tools.mjs"
12
+ // CONCATENATED MODULE: ./src/ai/mcp/bwMcpServer.ts
13
+
14
+ const SERVER_INSTRUCTIONS = `
15
+ bun-workspaces MCP server: tools to query Bun monorepo workspace metadata and documentation resources for the bun-workspaces CLI and TypeScript API.
16
+
17
+ bun-workspaces is an npm package that works on top of Bun's native workspaces. If this server is running, the project likely has bun-workspaces installed, or the user invokes it via bunx — often using the recommended alias "bw" for \`bunx bun-workspaces\`.
18
+
19
+ Use the tools to understand the project's workspaces and scripts. Running scripts across workspaces is a core bw feature not exposed as a tool — use the CLI directly. See the bw://docs/cli resource for the full CLI reference.
20
+
21
+ There are optional configuration files for the bun-workspaces CLI and TypeScript API. See the bw://docs/config resource for the full configuration reference.
22
+
23
+ ## CLI quickstart
24
+
25
+ \`\`\`bash
26
+ ${CLI_QUICKSTART}
27
+ \`\`\`
28
+
29
+ ## API quickstart
30
+
31
+ \`\`\`typescript
32
+ ${API_QUICKSTART}
33
+ \`\`\`
34
+ `.trim();
35
+ const startBwMcpServer = async (project) => {
36
+ const server = createMcpServer({
37
+ name: "bun-workspaces",
38
+ version: package_0.version,
39
+ instructions: SERVER_INSTRUCTIONS,
40
+ });
41
+ registerBwTools(server, project);
42
+ registerBwResources(server, project);
43
+ await server.start();
44
+ };
45
+
46
+ export { startBwMcpServer };
@@ -0,0 +1,3 @@
1
+ export * from "./types";
2
+ export * from "./transport";
3
+ export * from "./server";
@@ -0,0 +1,3 @@
1
+ export * from "./types.mjs";
2
+ export * from "./transport.mjs";
3
+ export * from "./server.mjs"; // CONCATENATED MODULE: ./src/ai/mcp/core/index.ts
@@ -0,0 +1,14 @@
1
+ import { type McpTransport } from "./transport";
2
+ import {
3
+ type McpServerInfo,
4
+ type Resource,
5
+ type ResourceHandler,
6
+ type Tool,
7
+ type ToolHandler,
8
+ } from "./types";
9
+ export type McpServer = {
10
+ registerTool: (tool: Tool, handler: ToolHandler) => void;
11
+ registerResource: (resource: Resource, handler: ResourceHandler) => void;
12
+ start: (transport?: McpTransport) => Promise<void>;
13
+ };
14
+ export declare const createMcpServer: (info: McpServerInfo) => McpServer;
@@ -0,0 +1,169 @@
1
+ import { createStdioTransport } from "./transport.mjs";
2
+ import { JSON_RPC_ERROR_CODES, MCP_PROTOCOL_VERSION } from "./types.mjs"; // CONCATENATED MODULE: external "./transport.mjs"
3
+ // CONCATENATED MODULE: external "./types.mjs"
4
+ // CONCATENATED MODULE: ./src/ai/mcp/core/server.ts
5
+
6
+ const createMcpServer = (info) => {
7
+ const tools = new Map();
8
+ const resources = new Map();
9
+ const registerTool = (tool, handler) => {
10
+ tools.set(tool.name, {
11
+ tool,
12
+ handler,
13
+ });
14
+ };
15
+ const registerResource = (resource, handler) => {
16
+ resources.set(resource.uri, {
17
+ resource,
18
+ handler,
19
+ });
20
+ };
21
+ const start = async (transport) => {
22
+ const activeTransport = transport ?? createStdioTransport();
23
+ const send = (id, result) => {
24
+ activeTransport.send({
25
+ jsonrpc: "2.0",
26
+ id,
27
+ result,
28
+ });
29
+ };
30
+ const sendError = (id, code, message) => {
31
+ activeTransport.send({
32
+ jsonrpc: "2.0",
33
+ id,
34
+ error: {
35
+ code,
36
+ message,
37
+ },
38
+ });
39
+ };
40
+ const handleInitialize = (id) => {
41
+ const result = {
42
+ protocolVersion: MCP_PROTOCOL_VERSION,
43
+ capabilities: {
44
+ ...(tools.size > 0
45
+ ? {
46
+ tools: {},
47
+ }
48
+ : {}),
49
+ ...(resources.size > 0
50
+ ? {
51
+ resources: {},
52
+ }
53
+ : {}),
54
+ },
55
+ serverInfo: {
56
+ name: info.name,
57
+ version: info.version,
58
+ },
59
+ ...(info.instructions !== undefined
60
+ ? {
61
+ instructions: info.instructions,
62
+ }
63
+ : {}),
64
+ };
65
+ send(id, result);
66
+ };
67
+ const handleListTools = (id) => {
68
+ send(id, {
69
+ tools: [...tools.values()].map(({ tool }) => tool),
70
+ });
71
+ };
72
+ const handleCallTool = async (id, params) => {
73
+ const name = params["name"];
74
+ const args = params["arguments"] ?? {};
75
+ const registered = tools.get(name);
76
+ if (!registered) {
77
+ sendError(
78
+ id,
79
+ JSON_RPC_ERROR_CODES.methodNotFound,
80
+ `Tool not found: ${name}`,
81
+ );
82
+ return;
83
+ }
84
+ try {
85
+ const result = await registered.handler(args);
86
+ send(id, result);
87
+ } catch (error) {
88
+ send(id, {
89
+ content: [
90
+ {
91
+ type: "text",
92
+ text: error instanceof Error ? error.message : String(error),
93
+ },
94
+ ],
95
+ isError: true,
96
+ });
97
+ }
98
+ };
99
+ const handleListResources = (id) => {
100
+ send(id, {
101
+ resources: [...resources.values()].map(({ resource }) => resource),
102
+ });
103
+ };
104
+ const handleReadResource = async (id, params) => {
105
+ const uri = params["uri"];
106
+ const registered = resources.get(uri);
107
+ if (!registered) {
108
+ sendError(
109
+ id,
110
+ JSON_RPC_ERROR_CODES.invalidParams,
111
+ `Resource not found: ${uri}`,
112
+ );
113
+ return;
114
+ }
115
+ try {
116
+ const result = await registered.handler(uri);
117
+ send(id, result);
118
+ } catch (error) {
119
+ sendError(
120
+ id,
121
+ JSON_RPC_ERROR_CODES.internalError,
122
+ error instanceof Error ? error.message : String(error),
123
+ );
124
+ }
125
+ };
126
+ for await (const raw of activeTransport.receive()) {
127
+ const method = raw["method"];
128
+ if (typeof method !== "string") continue;
129
+ const id = raw["id"];
130
+ // Notifications have no id — no response needed
131
+ if (id === undefined || id === null) continue;
132
+ const requestId = id;
133
+ const params = raw["params"] ?? {};
134
+ switch (method) {
135
+ case "initialize":
136
+ handleInitialize(requestId);
137
+ break;
138
+ case "ping":
139
+ send(requestId, {});
140
+ break;
141
+ case "tools/list":
142
+ handleListTools(requestId);
143
+ break;
144
+ case "tools/call":
145
+ await handleCallTool(requestId, params);
146
+ break;
147
+ case "resources/list":
148
+ handleListResources(requestId);
149
+ break;
150
+ case "resources/read":
151
+ await handleReadResource(requestId, params);
152
+ break;
153
+ default:
154
+ sendError(
155
+ requestId,
156
+ JSON_RPC_ERROR_CODES.methodNotFound,
157
+ `Method not found: ${method}`,
158
+ );
159
+ }
160
+ }
161
+ };
162
+ return {
163
+ registerTool,
164
+ registerResource,
165
+ start,
166
+ };
167
+ };
168
+
169
+ export { createMcpServer };
@@ -0,0 +1,12 @@
1
+ export type RawMessage = Record<string, unknown>;
2
+ export type McpTransport = {
3
+ receive: () => AsyncGenerator<RawMessage>;
4
+ send: (message: RawMessage) => void;
5
+ };
6
+ export type MemoryTransport = McpTransport & {
7
+ sent: RawMessage[];
8
+ };
9
+ export declare const createMemoryTransport: (
10
+ messages: RawMessage[],
11
+ ) => MemoryTransport;
12
+ export declare const createStdioTransport: () => McpTransport;
@@ -0,0 +1,45 @@
1
+ import readline from "readline"; // CONCATENATED MODULE: external "readline"
2
+ // CONCATENATED MODULE: ./src/ai/mcp/core/transport.ts
3
+
4
+ const createMemoryTransport = (messages) => {
5
+ const sent = [];
6
+ const send = (message) => {
7
+ sent.push(message);
8
+ };
9
+ const receive = async function* () {
10
+ for (const message of messages) {
11
+ yield message;
12
+ }
13
+ };
14
+ return {
15
+ send,
16
+ receive,
17
+ sent,
18
+ };
19
+ };
20
+ const createStdioTransport = () => {
21
+ const send = (message) => {
22
+ process.stdout.write(JSON.stringify(message) + "\n");
23
+ };
24
+ const receive = async function* () {
25
+ const rl = readline.createInterface({
26
+ input: process.stdin,
27
+ terminal: false,
28
+ });
29
+ for await (const line of rl) {
30
+ const trimmed = line.trim();
31
+ if (!trimmed) continue;
32
+ try {
33
+ yield JSON.parse(trimmed);
34
+ } catch {
35
+ // Ignore malformed lines — the client sent invalid JSON
36
+ }
37
+ }
38
+ };
39
+ return {
40
+ send,
41
+ receive,
42
+ };
43
+ };
44
+
45
+ export { createMemoryTransport, createStdioTransport };
@@ -0,0 +1,104 @@
1
+ export type JsonRpcId = string | number;
2
+ export type JsonRpcSuccessResponse = {
3
+ jsonrpc: "2.0";
4
+ id: JsonRpcId;
5
+ result: unknown;
6
+ };
7
+ export type JsonRpcErrorResponse = {
8
+ jsonrpc: "2.0";
9
+ id: JsonRpcId;
10
+ error: {
11
+ code: number;
12
+ message: string;
13
+ data?: unknown;
14
+ };
15
+ };
16
+ export declare const JSON_RPC_ERROR_CODES: {
17
+ readonly parseError: -32700;
18
+ readonly invalidRequest: -32600;
19
+ readonly methodNotFound: -32601;
20
+ readonly invalidParams: -32602;
21
+ readonly internalError: -32603;
22
+ };
23
+ export declare const MCP_PROTOCOL_VERSION = "2024-11-05";
24
+ export type ServerCapabilities = {
25
+ tools?: Record<string, never>;
26
+ resources?: Record<string, never>;
27
+ };
28
+ export type McpServerInfo = {
29
+ name: string;
30
+ version: string;
31
+ instructions?: string;
32
+ };
33
+ export type InitializeResult = {
34
+ protocolVersion: string;
35
+ capabilities: ServerCapabilities;
36
+ serverInfo: {
37
+ name: string;
38
+ version: string;
39
+ };
40
+ instructions?: string;
41
+ };
42
+ export type JsonSchemaProperty =
43
+ | {
44
+ type: "string";
45
+ description?: string;
46
+ enum?: string[];
47
+ }
48
+ | {
49
+ type: "number";
50
+ description?: string;
51
+ }
52
+ | {
53
+ type: "boolean";
54
+ description?: string;
55
+ }
56
+ | {
57
+ type: "array";
58
+ items: JsonSchemaProperty;
59
+ description?: string;
60
+ }
61
+ | {
62
+ type: "object";
63
+ properties?: Record<string, JsonSchemaProperty>;
64
+ required?: string[];
65
+ description?: string;
66
+ };
67
+ export type ToolInputSchema = {
68
+ type: "object";
69
+ properties?: Record<string, JsonSchemaProperty>;
70
+ required?: string[];
71
+ };
72
+ export type Tool = {
73
+ name: string;
74
+ description: string;
75
+ inputSchema: ToolInputSchema;
76
+ };
77
+ export type TextContent = {
78
+ type: "text";
79
+ text: string;
80
+ };
81
+ export type CallToolResult = {
82
+ content: TextContent[];
83
+ isError?: boolean;
84
+ };
85
+ export type Resource = {
86
+ uri: string;
87
+ name: string;
88
+ description?: string;
89
+ mimeType?: string;
90
+ };
91
+ export type ResourceContent = {
92
+ uri: string;
93
+ mimeType: string;
94
+ text: string;
95
+ };
96
+ export type ReadResourceResult = {
97
+ contents: ResourceContent[];
98
+ };
99
+ export type ToolHandler = (
100
+ args: Record<string, unknown>,
101
+ ) => Promise<CallToolResult> | CallToolResult;
102
+ export type ResourceHandler = (
103
+ uri: string,
104
+ ) => Promise<ReadResourceResult> | ReadResourceResult;
@@ -0,0 +1,11 @@
1
+ // CONCATENATED MODULE: ./src/ai/mcp/core/types.ts
2
+ const JSON_RPC_ERROR_CODES = {
3
+ parseError: -32700,
4
+ invalidRequest: -32600,
5
+ methodNotFound: -32601,
6
+ invalidParams: -32602,
7
+ internalError: -32603,
8
+ };
9
+ const MCP_PROTOCOL_VERSION = "2024-11-05";
10
+
11
+ export { JSON_RPC_ERROR_CODES, MCP_PROTOCOL_VERSION };
@@ -0,0 +1,2 @@
1
+ export * from "./core";
2
+ export * from "./bwMcpServer";
@@ -0,0 +1,2 @@
1
+ export * from "./core/index.mjs";
2
+ export * from "./bwMcpServer.mjs"; // CONCATENATED MODULE: ./src/ai/mcp/index.ts
@@ -0,0 +1,6 @@
1
+ import type { FileSystemProject } from "../../project/implementations/fileSystemProject";
2
+ import type { McpServer } from "./core";
3
+ export declare const registerBwResources: (
4
+ server: McpServer,
5
+ project: FileSystemProject,
6
+ ) => void;
@@ -0,0 +1,98 @@
1
+ import {
2
+ DOC_API,
3
+ DOC_CLI,
4
+ DOC_CONCEPTS,
5
+ DOC_CONFIG,
6
+ DOC_OVERVIEW,
7
+ } from "../../internal/generated/aiDocs/docs.mjs"; // CONCATENATED MODULE: external "../../internal/generated/aiDocs/docs.mjs"
8
+ // CONCATENATED MODULE: ./src/ai/mcp/resources.ts
9
+
10
+ const textResource = (uri, text) => ({
11
+ contents: [
12
+ {
13
+ uri,
14
+ mimeType: "text/markdown",
15
+ text,
16
+ },
17
+ ],
18
+ });
19
+ const registerBwResources = (server, project) => {
20
+ server.registerResource(
21
+ {
22
+ uri: "bw://project",
23
+ name: "Project overview",
24
+ description:
25
+ "Overview of this bun-workspaces project: name, root directory, and all workspace metadata.",
26
+ mimeType: "application/json",
27
+ },
28
+ (uri) => ({
29
+ contents: [
30
+ {
31
+ uri,
32
+ mimeType: "application/json",
33
+ text: JSON.stringify(
34
+ {
35
+ name: project.name,
36
+ rootDirectory: project.rootDirectory,
37
+ workspaces: project.workspaces,
38
+ },
39
+ null,
40
+ 2,
41
+ ),
42
+ },
43
+ ],
44
+ }),
45
+ );
46
+ server.registerResource(
47
+ {
48
+ uri: "bw://docs/overview",
49
+ name: "bun-workspaces overview",
50
+ description:
51
+ "What bun-workspaces is, its domain model, and core concepts.",
52
+ mimeType: "text/markdown",
53
+ },
54
+ (uri) => textResource(uri, DOC_OVERVIEW),
55
+ );
56
+ server.registerResource(
57
+ {
58
+ uri: "bw://docs/concepts",
59
+ name: "bun-workspaces concepts",
60
+ description:
61
+ "Workspace patterns, script runtime metadata, and how to run scripts via the CLI.",
62
+ mimeType: "text/markdown",
63
+ },
64
+ (uri) => textResource(uri, DOC_CONCEPTS),
65
+ );
66
+ server.registerResource(
67
+ {
68
+ uri: "bw://docs/cli",
69
+ name: "bun-workspaces CLI reference",
70
+ description:
71
+ "Full CLI command reference with examples, including run-script and all global options.",
72
+ mimeType: "text/markdown",
73
+ },
74
+ (uri) => textResource(uri, DOC_CLI),
75
+ );
76
+ server.registerResource(
77
+ {
78
+ uri: "bw://docs/api",
79
+ name: "bun-workspaces TypeScript API reference",
80
+ description:
81
+ "TypeScript API examples for createFileSystemProject and the Project/Workspace interfaces.",
82
+ mimeType: "text/markdown",
83
+ },
84
+ (uri) => textResource(uri, DOC_API),
85
+ );
86
+ server.registerResource(
87
+ {
88
+ uri: "bw://docs/config",
89
+ name: "bun-workspaces config reference",
90
+ description:
91
+ "Root config (bw.root.jsonc) and workspace config (bw.workspace.jsonc) schema and options.",
92
+ mimeType: "text/markdown",
93
+ },
94
+ (uri) => textResource(uri, DOC_CONFIG),
95
+ );
96
+ };
97
+
98
+ export { registerBwResources };
@@ -0,0 +1,6 @@
1
+ import type { FileSystemProject } from "../../project/implementations/fileSystemProject";
2
+ import type { McpServer } from "./core";
3
+ export declare const registerBwTools: (
4
+ server: McpServer,
5
+ project: FileSystemProject,
6
+ ) => void;