@bagelink/workspace 1.7.12 → 1.7.14

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/bin/bgl.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process'
3
3
  import { isWorkspace } from '../src/detect.js'
4
+ import { runDev } from '../src/dev.js'
4
5
  import { generateWorkspaceConfig } from '../src/init.js'
5
6
  import { setupLint } from '../src/lint.js'
6
7
  import { generateSDK, generateSDKForWorkspace } from '../src/sdk.js'
@@ -97,6 +98,12 @@ SDK Commands:
97
98
  process.exit(1)
98
99
  }
99
100
  }
101
+ else if (command === 'dev') {
102
+ // Get optional filter argument
103
+ const filter = subcommand || './[!shared]*'
104
+ const exitCode = await runDev(filter)
105
+ process.exit(exitCode)
106
+ }
100
107
  else {
101
108
  console.log(`
102
109
  Bagel Workspace CLI
@@ -106,6 +113,7 @@ Usage:
106
113
  bgl init --workspace Create a new workspace with multiple projects
107
114
  bgl add <name> Add a new project to workspace
108
115
  bgl list List all projects in workspace
116
+ bgl dev [filter] Run dev servers with clean output (default: './[!shared]*')
109
117
  bgl lint init Set up linting (auto-detects workspace)
110
118
  bgl sdk generate Generate SDK (auto-detects workspace)
111
119
 
package/dist/bin/bgl.cjs CHANGED
@@ -2,10 +2,11 @@
2
2
  'use strict';
3
3
 
4
4
  const process = require('node:process');
5
- const detect = require('../shared/workspace.BMTTo3s8.cjs');
5
+ const workspace = require('../shared/workspace.BHE_cGVH.cjs');
6
6
  require('node:fs');
7
7
  require('node:path');
8
8
  require('prompts');
9
+ require('node:child_process');
9
10
 
10
11
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
12
 
@@ -16,9 +17,9 @@ async function main() {
16
17
  if (command === "init") {
17
18
  const createWorkspace = subcommand === "--workspace" || subcommand === "-w" || args.includes("--workspace") || args.includes("-w");
18
19
  if (createWorkspace) {
19
- await detect.initWorkspace();
20
+ await workspace.initWorkspace();
20
21
  } else {
21
- await detect.generateWorkspaceConfig();
22
+ await workspace.generateWorkspaceConfig();
22
23
  }
23
24
  } else if (command === "add") {
24
25
  const projectName = subcommand;
@@ -27,9 +28,9 @@ async function main() {
27
28
  console.log("Usage: bgl add <project-name>");
28
29
  process__default.exit(1);
29
30
  }
30
- await detect.addProject(projectName);
31
+ await workspace.addProject(projectName);
31
32
  } else if (command === "list") {
32
- const projects = detect.listProjects();
33
+ const projects = workspace.listProjects();
33
34
  if (projects.length === 0) {
34
35
  console.log("No projects found");
35
36
  } else {
@@ -43,13 +44,13 @@ async function main() {
43
44
  if (subcommand === "init") {
44
45
  const forceWorkspace = args.includes("--workspace") || args.includes("-w");
45
46
  const forceProject = args.includes("--project") || args.includes("-p");
46
- let workspaceMode = detect.isWorkspace(process__default.cwd());
47
+ let workspaceMode = workspace.isWorkspace(process__default.cwd());
47
48
  if (forceWorkspace) workspaceMode = true;
48
49
  if (forceProject) workspaceMode = false;
49
50
  if (workspaceMode) {
50
51
  console.log("\u2713 Detected workspace mode");
51
52
  }
52
- await detect.setupLint(process__default.cwd(), workspaceMode);
53
+ await workspace.setupLint(process__default.cwd(), workspaceMode);
53
54
  } else {
54
55
  console.log(`
55
56
  Lint Commands:
@@ -63,14 +64,14 @@ Lint Commands:
63
64
  if (subcommand === "generate") {
64
65
  const forceWorkspace = args.includes("--workspace") || args.includes("-w");
65
66
  const forceProject = args.includes("--project") || args.includes("-p");
66
- let workspaceMode = detect.isWorkspace(process__default.cwd());
67
+ let workspaceMode = workspace.isWorkspace(process__default.cwd());
67
68
  if (forceWorkspace) workspaceMode = true;
68
69
  if (forceProject) workspaceMode = false;
69
70
  if (workspaceMode) {
70
71
  console.log("\u2713 Detected workspace mode - will generate for multiple projects");
71
- await detect.generateSDKForWorkspace();
72
+ await workspace.generateSDKForWorkspace();
72
73
  } else {
73
- await detect.generateSDK(process__default.cwd());
74
+ await workspace.generateSDK(process__default.cwd());
74
75
  }
75
76
  } else {
76
77
  console.log(`
@@ -81,6 +82,10 @@ SDK Commands:
81
82
  `);
82
83
  process__default.exit(1);
83
84
  }
85
+ } else if (command === "dev") {
86
+ const filter = subcommand || "./[!shared]*";
87
+ const exitCode = await workspace.runDev(filter);
88
+ process__default.exit(exitCode);
84
89
  } else {
85
90
  console.log(`
86
91
  Bagel Workspace CLI
@@ -90,6 +95,7 @@ Usage:
90
95
  bgl init --workspace Create a new workspace with multiple projects
91
96
  bgl add <name> Add a new project to workspace
92
97
  bgl list List all projects in workspace
98
+ bgl dev [filter] Run dev servers with clean output (default: './[!shared]*')
93
99
  bgl lint init Set up linting (auto-detects workspace)
94
100
  bgl sdk generate Generate SDK (auto-detects workspace)
95
101
 
package/dist/bin/bgl.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import process from 'node:process';
3
- import { i as initWorkspace, g as generateWorkspaceConfig, h as addProject, l as listProjects, k as isWorkspace, d as setupLint, f as generateSDKForWorkspace, e as generateSDK } from '../shared/workspace.COhZ__uF.mjs';
3
+ import { k as initWorkspace, g as generateWorkspaceConfig, j as addProject, l as listProjects, i as isWorkspace, e as setupLint, h as generateSDKForWorkspace, f as generateSDK, r as runDev } from '../shared/workspace.Ce21E5iO.mjs';
4
4
  import 'node:fs';
5
5
  import 'node:path';
6
6
  import 'prompts';
7
+ import 'node:child_process';
7
8
 
8
9
  const [, , command, subcommand, ...args] = process.argv;
9
10
  async function main() {
@@ -75,6 +76,10 @@ SDK Commands:
75
76
  `);
76
77
  process.exit(1);
77
78
  }
79
+ } else if (command === "dev") {
80
+ const filter = subcommand || "./[!shared]*";
81
+ const exitCode = await runDev(filter);
82
+ process.exit(exitCode);
78
83
  } else {
79
84
  console.log(`
80
85
  Bagel Workspace CLI
@@ -84,6 +89,7 @@ Usage:
84
89
  bgl init --workspace Create a new workspace with multiple projects
85
90
  bgl add <name> Add a new project to workspace
86
91
  bgl list List all projects in workspace
92
+ bgl dev [filter] Run dev servers with clean output (default: './[!shared]*')
87
93
  bgl lint init Set up linting (auto-detects workspace)
88
94
  bgl sdk generate Generate SDK (auto-detects workspace)
89
95
 
package/dist/index.cjs CHANGED
@@ -3,8 +3,9 @@
3
3
  const node_fs = require('node:fs');
4
4
  const node_path = require('node:path');
5
5
  const process = require('node:process');
6
- const detect = require('./shared/workspace.BMTTo3s8.cjs');
6
+ const workspace = require('./shared/workspace.BHE_cGVH.cjs');
7
7
  require('prompts');
8
+ require('node:child_process');
8
9
 
9
10
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
10
11
 
@@ -32,7 +33,7 @@ async function resolveConfig(mode = "development", options = {}) {
32
33
  currentDir = parentDir;
33
34
  }
34
35
  if (options.interactive !== false) {
35
- await detect.generateWorkspaceConfig(root, configFile);
36
+ await workspace.generateWorkspaceConfig(root, configFile);
36
37
  const newConfig = await loadConfig(localConfigPath, mode);
37
38
  if (newConfig) {
38
39
  return newConfig;
@@ -131,13 +132,13 @@ function createWorkspace(options = {}) {
131
132
  * Generate Netlify configuration file
132
133
  */
133
134
  generateNetlify(config, outPath = "./netlify.toml", additionalConfig) {
134
- detect.writeNetlifyConfig(config, outPath, additionalConfig);
135
+ workspace.writeNetlifyConfig(config, outPath, additionalConfig);
135
136
  },
136
137
  /**
137
138
  * Set build environment variables
138
139
  */
139
140
  setBuildEnv(config) {
140
- detect.setBuildEnvVars(config);
141
+ workspace.setBuildEnvVars(config);
141
142
  },
142
143
  /**
143
144
  * Clear cached configuration
@@ -148,20 +149,21 @@ function createWorkspace(options = {}) {
148
149
  };
149
150
  }
150
151
 
151
- exports.addProject = detect.addProject;
152
- exports.generateNetlifyConfig = detect.generateNetlifyConfig;
153
- exports.generateNetlifyRedirect = detect.generateNetlifyRedirect;
154
- exports.generateSDK = detect.generateSDK;
155
- exports.generateSDKForWorkspace = detect.generateSDKForWorkspace;
156
- exports.generateWorkspaceConfig = detect.generateWorkspaceConfig;
157
- exports.generateWorkspaceConfigSync = detect.generateWorkspaceConfigSync;
158
- exports.getWorkspaceInfo = detect.getWorkspaceInfo;
159
- exports.initWorkspace = detect.initWorkspace;
160
- exports.isWorkspace = detect.isWorkspace;
161
- exports.listProjects = detect.listProjects;
162
- exports.setBuildEnvVars = detect.setBuildEnvVars;
163
- exports.setupLint = detect.setupLint;
164
- exports.writeNetlifyConfig = detect.writeNetlifyConfig;
152
+ exports.addProject = workspace.addProject;
153
+ exports.generateNetlifyConfig = workspace.generateNetlifyConfig;
154
+ exports.generateNetlifyRedirect = workspace.generateNetlifyRedirect;
155
+ exports.generateSDK = workspace.generateSDK;
156
+ exports.generateSDKForWorkspace = workspace.generateSDKForWorkspace;
157
+ exports.generateWorkspaceConfig = workspace.generateWorkspaceConfig;
158
+ exports.generateWorkspaceConfigSync = workspace.generateWorkspaceConfigSync;
159
+ exports.getWorkspaceInfo = workspace.getWorkspaceInfo;
160
+ exports.initWorkspace = workspace.initWorkspace;
161
+ exports.isWorkspace = workspace.isWorkspace;
162
+ exports.listProjects = workspace.listProjects;
163
+ exports.runDev = workspace.runDev;
164
+ exports.setBuildEnvVars = workspace.setBuildEnvVars;
165
+ exports.setupLint = workspace.setupLint;
166
+ exports.writeNetlifyConfig = workspace.writeNetlifyConfig;
165
167
  exports.createCustomProxy = createCustomProxy;
166
168
  exports.createViteProxy = createViteProxy;
167
169
  exports.createWorkspace = createWorkspace;
package/dist/index.d.cts CHANGED
@@ -91,6 +91,21 @@ declare function createCustomProxy(paths: string[], target: string, options?: {
91
91
  secure?: boolean;
92
92
  }): ProxyConfig;
93
93
 
94
+ /**
95
+ * Detect if current directory is a workspace root
96
+ */
97
+ declare function isWorkspace(root?: string): boolean;
98
+ /**
99
+ * Get workspace info
100
+ */
101
+ declare function getWorkspaceInfo(root?: string): {
102
+ isWorkspace: boolean;
103
+ projects: string[];
104
+ hasShared: boolean;
105
+ };
106
+
107
+ declare function runDev(filter?: string): Promise<number>;
108
+
94
109
  /**
95
110
  * Set up linting in a project
96
111
  */
@@ -118,19 +133,6 @@ declare function addProject(name: string, root?: string): Promise<void>;
118
133
  */
119
134
  declare function listProjects(root?: string): string[];
120
135
 
121
- /**
122
- * Detect if current directory is a workspace root
123
- */
124
- declare function isWorkspace(root?: string): boolean;
125
- /**
126
- * Get workspace info
127
- */
128
- declare function getWorkspaceInfo(root?: string): {
129
- isWorkspace: boolean;
130
- projects: string[];
131
- hasShared: boolean;
132
- };
133
-
134
136
  /**
135
137
  * Define workspace configuration
136
138
  * Simple helper to get config from a config map
@@ -163,5 +165,5 @@ declare function createWorkspace(options?: WorkspaceOptions): {
163
165
  clearCache(): void;
164
166
  };
165
167
 
166
- export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, setBuildEnvVars, setupLint, writeNetlifyConfig };
168
+ export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, runDev, setBuildEnvVars, setupLint, writeNetlifyConfig };
167
169
  export type { ProxyConfig, WorkspaceConfig, WorkspaceEnvironment, WorkspaceOptions };
package/dist/index.d.mts CHANGED
@@ -91,6 +91,21 @@ declare function createCustomProxy(paths: string[], target: string, options?: {
91
91
  secure?: boolean;
92
92
  }): ProxyConfig;
93
93
 
94
+ /**
95
+ * Detect if current directory is a workspace root
96
+ */
97
+ declare function isWorkspace(root?: string): boolean;
98
+ /**
99
+ * Get workspace info
100
+ */
101
+ declare function getWorkspaceInfo(root?: string): {
102
+ isWorkspace: boolean;
103
+ projects: string[];
104
+ hasShared: boolean;
105
+ };
106
+
107
+ declare function runDev(filter?: string): Promise<number>;
108
+
94
109
  /**
95
110
  * Set up linting in a project
96
111
  */
@@ -118,19 +133,6 @@ declare function addProject(name: string, root?: string): Promise<void>;
118
133
  */
119
134
  declare function listProjects(root?: string): string[];
120
135
 
121
- /**
122
- * Detect if current directory is a workspace root
123
- */
124
- declare function isWorkspace(root?: string): boolean;
125
- /**
126
- * Get workspace info
127
- */
128
- declare function getWorkspaceInfo(root?: string): {
129
- isWorkspace: boolean;
130
- projects: string[];
131
- hasShared: boolean;
132
- };
133
-
134
136
  /**
135
137
  * Define workspace configuration
136
138
  * Simple helper to get config from a config map
@@ -163,5 +165,5 @@ declare function createWorkspace(options?: WorkspaceOptions): {
163
165
  clearCache(): void;
164
166
  };
165
167
 
166
- export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, setBuildEnvVars, setupLint, writeNetlifyConfig };
168
+ export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, runDev, setBuildEnvVars, setupLint, writeNetlifyConfig };
167
169
  export type { ProxyConfig, WorkspaceConfig, WorkspaceEnvironment, WorkspaceOptions };
package/dist/index.d.ts CHANGED
@@ -91,6 +91,21 @@ declare function createCustomProxy(paths: string[], target: string, options?: {
91
91
  secure?: boolean;
92
92
  }): ProxyConfig;
93
93
 
94
+ /**
95
+ * Detect if current directory is a workspace root
96
+ */
97
+ declare function isWorkspace(root?: string): boolean;
98
+ /**
99
+ * Get workspace info
100
+ */
101
+ declare function getWorkspaceInfo(root?: string): {
102
+ isWorkspace: boolean;
103
+ projects: string[];
104
+ hasShared: boolean;
105
+ };
106
+
107
+ declare function runDev(filter?: string): Promise<number>;
108
+
94
109
  /**
95
110
  * Set up linting in a project
96
111
  */
@@ -118,19 +133,6 @@ declare function addProject(name: string, root?: string): Promise<void>;
118
133
  */
119
134
  declare function listProjects(root?: string): string[];
120
135
 
121
- /**
122
- * Detect if current directory is a workspace root
123
- */
124
- declare function isWorkspace(root?: string): boolean;
125
- /**
126
- * Get workspace info
127
- */
128
- declare function getWorkspaceInfo(root?: string): {
129
- isWorkspace: boolean;
130
- projects: string[];
131
- hasShared: boolean;
132
- };
133
-
134
136
  /**
135
137
  * Define workspace configuration
136
138
  * Simple helper to get config from a config map
@@ -163,5 +165,5 @@ declare function createWorkspace(options?: WorkspaceOptions): {
163
165
  clearCache(): void;
164
166
  };
165
167
 
166
- export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, setBuildEnvVars, setupLint, writeNetlifyConfig };
168
+ export { addProject, createCustomProxy, createViteProxy, createWorkspace, defineWorkspace, generateNetlifyConfig, generateNetlifyRedirect, generateSDK, generateSDKForWorkspace, generateWorkspaceConfig, generateWorkspaceConfigSync, getWorkspaceInfo, initWorkspace, isWorkspace, listProjects, mergeConfigs, resolveConfig, runDev, setBuildEnvVars, setupLint, writeNetlifyConfig };
167
169
  export type { ProxyConfig, WorkspaceConfig, WorkspaceEnvironment, WorkspaceOptions };
package/dist/index.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { resolve, join } from 'node:path';
3
3
  import process from 'node:process';
4
- import { g as generateWorkspaceConfig, s as setBuildEnvVars, w as writeNetlifyConfig } from './shared/workspace.COhZ__uF.mjs';
5
- export { h as addProject, a as generateNetlifyConfig, b as generateNetlifyRedirect, e as generateSDK, f as generateSDKForWorkspace, c as generateWorkspaceConfigSync, j as getWorkspaceInfo, i as initWorkspace, k as isWorkspace, l as listProjects, d as setupLint } from './shared/workspace.COhZ__uF.mjs';
4
+ import { g as generateWorkspaceConfig, s as setBuildEnvVars, w as writeNetlifyConfig } from './shared/workspace.Ce21E5iO.mjs';
5
+ export { j as addProject, a as generateNetlifyConfig, b as generateNetlifyRedirect, f as generateSDK, h as generateSDKForWorkspace, c as generateWorkspaceConfigSync, d as getWorkspaceInfo, k as initWorkspace, i as isWorkspace, l as listProjects, r as runDev, e as setupLint } from './shared/workspace.Ce21E5iO.mjs';
6
6
  import 'prompts';
7
+ import 'node:child_process';
7
8
 
8
9
  async function resolveConfig(mode = "development", options = {}) {
9
10
  const root = options.root ?? process.cwd();
@@ -4,6 +4,7 @@ const node_fs = require('node:fs');
4
4
  const node_path = require('node:path');
5
5
  const process = require('node:process');
6
6
  const prompts = require('prompts');
7
+ const node_child_process = require('node:child_process');
7
8
 
8
9
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
9
10
 
@@ -238,6 +239,136 @@ export default defineConfig(({ mode }) => {
238
239
  console.log("\u2705 Created vite.config.ts");
239
240
  }
240
241
 
242
+ function isWorkspace(root = process__default.cwd()) {
243
+ const packageJsonPath = node_path.resolve(root, "package.json");
244
+ if (node_fs.existsSync(packageJsonPath)) {
245
+ try {
246
+ const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
247
+ if (packageJson.workspaces !== void 0) {
248
+ return true;
249
+ }
250
+ } catch {
251
+ }
252
+ }
253
+ try {
254
+ const items = node_fs.readdirSync(root, { withFileTypes: true });
255
+ const projectDirs = items.filter(
256
+ (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
257
+ );
258
+ return projectDirs.length >= 2;
259
+ } catch {
260
+ return false;
261
+ }
262
+ }
263
+ function getWorkspaceInfo(root = process__default.cwd()) {
264
+ const workspace = isWorkspace(root);
265
+ if (!workspace) {
266
+ return {
267
+ isWorkspace: false,
268
+ projects: [],
269
+ hasShared: false
270
+ };
271
+ }
272
+ try {
273
+ const items = node_fs.readdirSync(root, { withFileTypes: true });
274
+ const projects = items.filter(
275
+ (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
276
+ ).map((item) => item.name);
277
+ const hasShared = node_fs.existsSync(node_path.resolve(root, "shared"));
278
+ return {
279
+ isWorkspace: true,
280
+ projects,
281
+ hasShared
282
+ };
283
+ } catch {
284
+ return {
285
+ isWorkspace: false,
286
+ projects: [],
287
+ hasShared: false
288
+ };
289
+ }
290
+ }
291
+
292
+ const servers = /* @__PURE__ */ new Map();
293
+ const seenLines = /* @__PURE__ */ new Set();
294
+ const colors = {
295
+ reset: "\x1B[0m",
296
+ cyan: "\x1B[36m",
297
+ green: "\x1B[32m",
298
+ yellow: "\x1B[33m",
299
+ dim: "\x1B[2m"
300
+ };
301
+ function clearAndPrintServers() {
302
+ if (servers.size > 0) {
303
+ process__default.stdout.write("\x1B[2J\x1B[H");
304
+ }
305
+ console.log(`${colors.cyan}\u{1F680} Development Servers${colors.reset}
306
+ `);
307
+ for (const [name, info] of servers.entries()) {
308
+ if (info.status === "ready" && info.port) {
309
+ const url = `http://localhost:${info.port}`;
310
+ console.log(`${colors.green}\u25CF${colors.reset} ${colors.cyan}${name}${colors.reset} ${colors.dim}\u2192${colors.reset} ${url}`);
311
+ } else {
312
+ console.log(`${colors.yellow}\u25CB${colors.reset} ${colors.dim}${name} (starting...)${colors.reset}`);
313
+ }
314
+ }
315
+ console.log("");
316
+ }
317
+ async function runDev(filter = "./[!shared]*") {
318
+ const proc = node_child_process.spawn("bun", ["run", "--filter", filter, "dev"], {
319
+ cwd: process__default.cwd(),
320
+ stdio: ["inherit", "pipe", "pipe"]
321
+ });
322
+ let buffer = "";
323
+ function processLine(line) {
324
+ if (!line.trim()) return;
325
+ if (seenLines.has(line)) return;
326
+ seenLines.add(line);
327
+ const projectMatch = line.match(/^(\w+)\s+dev\s+\$/);
328
+ if (projectMatch) {
329
+ const name = projectMatch[1];
330
+ if (!servers.has(name)) {
331
+ servers.set(name, { name, status: "starting" });
332
+ clearAndPrintServers();
333
+ }
334
+ }
335
+ const portMatch = line.match(/Local:\s+http:\/\/localhost:(\d+)/);
336
+ if (portMatch) {
337
+ const port = Number.parseInt(portMatch[1], 10);
338
+ for (const [name, info] of servers.entries()) {
339
+ if (info.status === "starting" && !info.port) {
340
+ info.port = port;
341
+ info.status = "ready";
342
+ clearAndPrintServers();
343
+ break;
344
+ }
345
+ }
346
+ }
347
+ }
348
+ proc.stdout?.on("data", (data) => {
349
+ buffer += data.toString();
350
+ const lines = buffer.split("\n");
351
+ buffer = lines.pop() || "";
352
+ for (const line of lines) {
353
+ processLine(line);
354
+ }
355
+ });
356
+ proc.stderr?.on("data", (data) => {
357
+ buffer += data.toString();
358
+ const lines = buffer.split("\n");
359
+ buffer = lines.pop() || "";
360
+ for (const line of lines) {
361
+ processLine(line);
362
+ }
363
+ });
364
+ return new Promise((resolve, reject) => {
365
+ proc.on("exit", (code) => {
366
+ resolve(code || 0);
367
+ });
368
+ proc.on("error", reject);
369
+ });
370
+ }
371
+
241
372
  async function setupLint(root = process__default.cwd(), isWorkspace = false) {
242
373
  console.log("\n\u{1F50D} Setting up linting...\n");
243
374
  const response = await prompts__default([
@@ -927,56 +1058,6 @@ function listProjects(root = process__default.cwd()) {
927
1058
  }
928
1059
  }
929
1060
 
930
- function isWorkspace(root = process__default.cwd()) {
931
- const packageJsonPath = node_path.resolve(root, "package.json");
932
- if (node_fs.existsSync(packageJsonPath)) {
933
- try {
934
- const packageJson = JSON.parse(node_fs.readFileSync(packageJsonPath, "utf-8"));
935
- if (packageJson.workspaces !== void 0) {
936
- return true;
937
- }
938
- } catch {
939
- }
940
- }
941
- try {
942
- const items = node_fs.readdirSync(root, { withFileTypes: true });
943
- const projectDirs = items.filter(
944
- (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
945
- );
946
- return projectDirs.length >= 2;
947
- } catch {
948
- return false;
949
- }
950
- }
951
- function getWorkspaceInfo(root = process__default.cwd()) {
952
- const workspace = isWorkspace(root);
953
- if (!workspace) {
954
- return {
955
- isWorkspace: false,
956
- projects: [],
957
- hasShared: false
958
- };
959
- }
960
- try {
961
- const items = node_fs.readdirSync(root, { withFileTypes: true });
962
- const projects = items.filter(
963
- (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && node_fs.existsSync(node_path.resolve(root, item.name, "package.json"))
964
- ).map((item) => item.name);
965
- const hasShared = node_fs.existsSync(node_path.resolve(root, "shared"));
966
- return {
967
- isWorkspace: true,
968
- projects,
969
- hasShared
970
- };
971
- } catch {
972
- return {
973
- isWorkspace: false,
974
- projects: [],
975
- hasShared: false
976
- };
977
- }
978
- }
979
-
980
1061
  exports.addProject = addProject;
981
1062
  exports.generateNetlifyConfig = generateNetlifyConfig;
982
1063
  exports.generateNetlifyRedirect = generateNetlifyRedirect;
@@ -988,6 +1069,7 @@ exports.getWorkspaceInfo = getWorkspaceInfo;
988
1069
  exports.initWorkspace = initWorkspace;
989
1070
  exports.isWorkspace = isWorkspace;
990
1071
  exports.listProjects = listProjects;
1072
+ exports.runDev = runDev;
991
1073
  exports.setBuildEnvVars = setBuildEnvVars;
992
1074
  exports.setupLint = setupLint;
993
1075
  exports.writeNetlifyConfig = writeNetlifyConfig;
@@ -1,7 +1,8 @@
1
- import { writeFileSync, existsSync, readFileSync, mkdirSync, readdirSync } from 'node:fs';
1
+ import { writeFileSync, existsSync, readFileSync, readdirSync, mkdirSync } from 'node:fs';
2
2
  import { resolve } from 'node:path';
3
3
  import process from 'node:process';
4
4
  import prompts from 'prompts';
5
+ import { spawn } from 'node:child_process';
5
6
 
6
7
  function generateNetlifyRedirect(config) {
7
8
  const redirect = `[[redirects]]
@@ -231,6 +232,136 @@ export default defineConfig(({ mode }) => {
231
232
  console.log("\u2705 Created vite.config.ts");
232
233
  }
233
234
 
235
+ function isWorkspace(root = process.cwd()) {
236
+ const packageJsonPath = resolve(root, "package.json");
237
+ if (existsSync(packageJsonPath)) {
238
+ try {
239
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
240
+ if (packageJson.workspaces !== void 0) {
241
+ return true;
242
+ }
243
+ } catch {
244
+ }
245
+ }
246
+ try {
247
+ const items = readdirSync(root, { withFileTypes: true });
248
+ const projectDirs = items.filter(
249
+ (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && existsSync(resolve(root, item.name, "package.json"))
250
+ );
251
+ return projectDirs.length >= 2;
252
+ } catch {
253
+ return false;
254
+ }
255
+ }
256
+ function getWorkspaceInfo(root = process.cwd()) {
257
+ const workspace = isWorkspace(root);
258
+ if (!workspace) {
259
+ return {
260
+ isWorkspace: false,
261
+ projects: [],
262
+ hasShared: false
263
+ };
264
+ }
265
+ try {
266
+ const items = readdirSync(root, { withFileTypes: true });
267
+ const projects = items.filter(
268
+ (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && existsSync(resolve(root, item.name, "package.json"))
269
+ ).map((item) => item.name);
270
+ const hasShared = existsSync(resolve(root, "shared"));
271
+ return {
272
+ isWorkspace: true,
273
+ projects,
274
+ hasShared
275
+ };
276
+ } catch {
277
+ return {
278
+ isWorkspace: false,
279
+ projects: [],
280
+ hasShared: false
281
+ };
282
+ }
283
+ }
284
+
285
+ const servers = /* @__PURE__ */ new Map();
286
+ const seenLines = /* @__PURE__ */ new Set();
287
+ const colors = {
288
+ reset: "\x1B[0m",
289
+ cyan: "\x1B[36m",
290
+ green: "\x1B[32m",
291
+ yellow: "\x1B[33m",
292
+ dim: "\x1B[2m"
293
+ };
294
+ function clearAndPrintServers() {
295
+ if (servers.size > 0) {
296
+ process.stdout.write("\x1B[2J\x1B[H");
297
+ }
298
+ console.log(`${colors.cyan}\u{1F680} Development Servers${colors.reset}
299
+ `);
300
+ for (const [name, info] of servers.entries()) {
301
+ if (info.status === "ready" && info.port) {
302
+ const url = `http://localhost:${info.port}`;
303
+ console.log(`${colors.green}\u25CF${colors.reset} ${colors.cyan}${name}${colors.reset} ${colors.dim}\u2192${colors.reset} ${url}`);
304
+ } else {
305
+ console.log(`${colors.yellow}\u25CB${colors.reset} ${colors.dim}${name} (starting...)${colors.reset}`);
306
+ }
307
+ }
308
+ console.log("");
309
+ }
310
+ async function runDev(filter = "./[!shared]*") {
311
+ const proc = spawn("bun", ["run", "--filter", filter, "dev"], {
312
+ cwd: process.cwd(),
313
+ stdio: ["inherit", "pipe", "pipe"]
314
+ });
315
+ let buffer = "";
316
+ function processLine(line) {
317
+ if (!line.trim()) return;
318
+ if (seenLines.has(line)) return;
319
+ seenLines.add(line);
320
+ const projectMatch = line.match(/^(\w+)\s+dev\s+\$/);
321
+ if (projectMatch) {
322
+ const name = projectMatch[1];
323
+ if (!servers.has(name)) {
324
+ servers.set(name, { name, status: "starting" });
325
+ clearAndPrintServers();
326
+ }
327
+ }
328
+ const portMatch = line.match(/Local:\s+http:\/\/localhost:(\d+)/);
329
+ if (portMatch) {
330
+ const port = Number.parseInt(portMatch[1], 10);
331
+ for (const [name, info] of servers.entries()) {
332
+ if (info.status === "starting" && !info.port) {
333
+ info.port = port;
334
+ info.status = "ready";
335
+ clearAndPrintServers();
336
+ break;
337
+ }
338
+ }
339
+ }
340
+ }
341
+ proc.stdout?.on("data", (data) => {
342
+ buffer += data.toString();
343
+ const lines = buffer.split("\n");
344
+ buffer = lines.pop() || "";
345
+ for (const line of lines) {
346
+ processLine(line);
347
+ }
348
+ });
349
+ proc.stderr?.on("data", (data) => {
350
+ buffer += data.toString();
351
+ const lines = buffer.split("\n");
352
+ buffer = lines.pop() || "";
353
+ for (const line of lines) {
354
+ processLine(line);
355
+ }
356
+ });
357
+ return new Promise((resolve, reject) => {
358
+ proc.on("exit", (code) => {
359
+ resolve(code || 0);
360
+ });
361
+ proc.on("error", reject);
362
+ });
363
+ }
364
+
234
365
  async function setupLint(root = process.cwd(), isWorkspace = false) {
235
366
  console.log("\n\u{1F50D} Setting up linting...\n");
236
367
  const response = await prompts([
@@ -920,54 +1051,4 @@ function listProjects(root = process.cwd()) {
920
1051
  }
921
1052
  }
922
1053
 
923
- function isWorkspace(root = process.cwd()) {
924
- const packageJsonPath = resolve(root, "package.json");
925
- if (existsSync(packageJsonPath)) {
926
- try {
927
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
928
- if (packageJson.workspaces !== void 0) {
929
- return true;
930
- }
931
- } catch {
932
- }
933
- }
934
- try {
935
- const items = readdirSync(root, { withFileTypes: true });
936
- const projectDirs = items.filter(
937
- (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && existsSync(resolve(root, item.name, "package.json"))
938
- );
939
- return projectDirs.length >= 2;
940
- } catch {
941
- return false;
942
- }
943
- }
944
- function getWorkspaceInfo(root = process.cwd()) {
945
- const workspace = isWorkspace(root);
946
- if (!workspace) {
947
- return {
948
- isWorkspace: false,
949
- projects: [],
950
- hasShared: false
951
- };
952
- }
953
- try {
954
- const items = readdirSync(root, { withFileTypes: true });
955
- const projects = items.filter(
956
- (item) => item.isDirectory() && item.name !== "node_modules" && item.name !== "shared" && item.name !== ".git" && !item.name.startsWith(".") && existsSync(resolve(root, item.name, "package.json"))
957
- ).map((item) => item.name);
958
- const hasShared = existsSync(resolve(root, "shared"));
959
- return {
960
- isWorkspace: true,
961
- projects,
962
- hasShared
963
- };
964
- } catch {
965
- return {
966
- isWorkspace: false,
967
- projects: [],
968
- hasShared: false
969
- };
970
- }
971
- }
972
-
973
- export { generateNetlifyConfig as a, generateNetlifyRedirect as b, generateWorkspaceConfigSync as c, setupLint as d, generateSDK as e, generateSDKForWorkspace as f, generateWorkspaceConfig as g, addProject as h, initWorkspace as i, getWorkspaceInfo as j, isWorkspace as k, listProjects as l, setBuildEnvVars as s, writeNetlifyConfig as w };
1054
+ export { generateNetlifyConfig as a, generateNetlifyRedirect as b, generateWorkspaceConfigSync as c, getWorkspaceInfo as d, setupLint as e, generateSDK as f, generateWorkspaceConfig as g, generateSDKForWorkspace as h, isWorkspace as i, addProject as j, initWorkspace as k, listProjects as l, runDev as r, setBuildEnvVars as s, writeNetlifyConfig as w };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bagelink/workspace",
3
3
  "type": "module",
4
- "version": "1.7.12",
4
+ "version": "1.7.14",
5
5
  "description": "Monorepo workspace tooling for Bagel projects with proxy and config management",
6
6
  "author": {
7
7
  "name": "Bagel Studio",
package/src/dev.ts ADDED
@@ -0,0 +1,112 @@
1
+ import type { Buffer } from 'node:buffer'
2
+ import { spawn } from 'node:child_process'
3
+ import process from 'node:process'
4
+
5
+ interface ServerInfo {
6
+ name: string
7
+ port?: number
8
+ status: 'starting' | 'ready'
9
+ }
10
+
11
+ const servers = new Map<string, ServerInfo>()
12
+ const seenLines = new Set<string>()
13
+
14
+ // ANSI colors
15
+ const colors = {
16
+ reset: '\x1B[0m',
17
+ cyan: '\x1B[36m',
18
+ green: '\x1B[32m',
19
+ yellow: '\x1B[33m',
20
+ dim: '\x1B[2m',
21
+ }
22
+
23
+ function clearAndPrintServers() {
24
+ // Clear previous output
25
+ if (servers.size > 0) {
26
+ process.stdout.write('\x1B[2J\x1B[H') // Clear screen and move to top
27
+ }
28
+
29
+ console.log(`${colors.cyan}🚀 Development Servers${colors.reset}\n`)
30
+
31
+ for (const [name, info] of servers.entries()) {
32
+ if (info.status === 'ready' && info.port) {
33
+ const url = `http://localhost:${info.port}`
34
+ console.log(`${colors.green}●${colors.reset} ${colors.cyan}${name}${colors.reset} ${colors.dim}→${colors.reset} ${url}`)
35
+ }
36
+ else {
37
+ console.log(`${colors.yellow}○${colors.reset} ${colors.dim}${name} (starting...)${colors.reset}`)
38
+ }
39
+ }
40
+
41
+ console.log('')
42
+ }
43
+
44
+ export async function runDev(filter = './[!shared]*') {
45
+ const proc = spawn('bun', ['run', '--filter', filter, 'dev'], {
46
+ cwd: process.cwd(),
47
+ stdio: ['inherit', 'pipe', 'pipe'],
48
+ })
49
+
50
+ let buffer = ''
51
+
52
+ function processLine(line: string) {
53
+ if (!line.trim()) return
54
+
55
+ // Skip duplicate lines
56
+ if (seenLines.has(line)) return
57
+ seenLines.add(line)
58
+
59
+ // Extract project name from "project dev $ vite"
60
+ const projectMatch = line.match(/^(\w+)\s+dev\s+\$/)
61
+ if (projectMatch) {
62
+ const name = projectMatch[1]
63
+ if (!servers.has(name)) {
64
+ servers.set(name, { name, status: 'starting' })
65
+ clearAndPrintServers()
66
+ }
67
+ }
68
+
69
+ // Extract port from "Local: http://localhost:5173/"
70
+ const portMatch = line.match(/Local:\s+http:\/\/localhost:(\d+)/)
71
+ if (portMatch) {
72
+ const port = Number.parseInt(portMatch[1], 10)
73
+
74
+ // Find which server just started (last one that's still starting)
75
+ for (const [name, info] of servers.entries()) {
76
+ if (info.status === 'starting' && !info.port) {
77
+ info.port = port
78
+ info.status = 'ready'
79
+ clearAndPrintServers()
80
+ break
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ proc.stdout?.on('data', (data: Buffer) => {
87
+ buffer += data.toString()
88
+ const lines = buffer.split('\n')
89
+ buffer = lines.pop() || ''
90
+
91
+ for (const line of lines) {
92
+ processLine(line)
93
+ }
94
+ })
95
+
96
+ proc.stderr?.on('data', (data: Buffer) => {
97
+ buffer += data.toString()
98
+ const lines = buffer.split('\n')
99
+ buffer = lines.pop() || ''
100
+
101
+ for (const line of lines) {
102
+ processLine(line)
103
+ }
104
+ })
105
+
106
+ return new Promise<number>((resolve, reject) => {
107
+ proc.on('exit', (code) => {
108
+ resolve(code || 0)
109
+ })
110
+ proc.on('error', reject)
111
+ })
112
+ }
package/src/index.ts CHANGED
@@ -34,10 +34,11 @@ export {
34
34
  writeNetlifyConfig,
35
35
  }
36
36
 
37
+ export { getWorkspaceInfo, isWorkspace } from './detect'
38
+ export { runDev } from './dev'
37
39
  export { setupLint } from './lint'
38
40
  export { generateSDK, generateSDKForWorkspace } from './sdk'
39
41
  export { addProject, initWorkspace, listProjects } from './workspace'
40
- export { getWorkspaceInfo, isWorkspace } from './detect'
41
42
 
42
43
  /**
43
44
  * Define workspace configuration