monorepotime 1.1.7 → 1.1.8

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 (3) hide show
  1. package/README.md +1 -5
  2. package/dist/index.js +380 -178
  3. package/package.json +4 -3
package/README.md CHANGED
@@ -5,13 +5,9 @@
5
5
 
6
6
  To use it instantly without installing:
7
7
 
8
- ```bash
9
- npx monorepotime
10
- ```
11
- or
12
8
  ```bash
13
9
  npm install -D monorepotime
14
- npx monorepotime
10
+ monorepotime
15
11
  ```
16
12
 
17
13
  This will:
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ __export(index_exports, {
39
39
  module.exports = __toCommonJS(index_exports);
40
40
  var import_express24 = __toESM(require("express"));
41
41
  var import_cors = __toESM(require("cors"));
42
- var import_path16 = __toESM(require("path"));
42
+ var import_path18 = __toESM(require("path"));
43
43
 
44
44
  // ../../packages/api/index.ts
45
45
  var apiRoute = {
@@ -394,10 +394,8 @@ async function handleOnRun(socket, data) {
394
394
  return socket.emit("log", "Attached to already running process...");
395
395
  const commandToRun = runas === "dev" ? workspace.devCommand : workspace.startCommand;
396
396
  if (!commandToRun) throw new Error("No command to run");
397
- const baseCMD = commandToRun.split(" ")[0];
398
- const args = commandToRun.split(" ").slice(1);
399
397
  socket.emit("log", import_chalk.default.green(`${data.workspace.path}: ${commandToRun}`));
400
- const child = (0, import_child_process.spawn)(baseCMD, args, {
398
+ const child = (0, import_child_process.spawn)(commandToRun, [], {
401
399
  cwd: workspace.path,
402
400
  env: {
403
401
  ...process.env,
@@ -670,7 +668,7 @@ function interactiveTerminalSocket(io2) {
670
668
  io2.on("connection", (socket) => {
671
669
  socket.on("terminal:start", (data) => {
672
670
  var _a, _b;
673
- const { path: path17, command, workspaceName } = data;
671
+ const { path: path19, command, workspaceName } = data;
674
672
  stopTerminalProcess(socket.id);
675
673
  try {
676
674
  const env = { ...process.env };
@@ -684,7 +682,7 @@ function interactiveTerminalSocket(io2) {
684
682
  const baseCMD = command.split(" ")[0];
685
683
  const args = command.split(" ").slice(1);
686
684
  child = (0, import_child_process3.spawn)(baseCMD, args, {
687
- cwd: path17,
685
+ cwd: path19,
688
686
  env,
689
687
  shell: true,
690
688
  stdio: ["pipe", "pipe", "pipe"]
@@ -712,7 +710,7 @@ except Exception as e:
712
710
  sys.exit(1)
713
711
  `;
714
712
  child = (0, import_child_process3.spawn)("python3", ["-u", "-c", pythonScript], {
715
- cwd: path17,
713
+ cwd: path19,
716
714
  env,
717
715
  stdio: ["pipe", "pipe", "pipe"]
718
716
  });
@@ -1324,6 +1322,7 @@ async function runGit(command) {
1324
1322
  return stdout.trim();
1325
1323
  }
1326
1324
  router14.get("/history", async (req, res) => {
1325
+ var _a;
1327
1326
  try {
1328
1327
  const output = await runGit('git log -n 10 --pretty=format:"%h|%s|%ar"');
1329
1328
  const history = output.split("\n").filter(Boolean).map((line) => {
@@ -1336,16 +1335,21 @@ router14.get("/history", async (req, res) => {
1336
1335
  });
1337
1336
  res.json({ history });
1338
1337
  } catch (error) {
1339
- console.error("Git History Error:", error);
1338
+ if (!((_a = error.message) == null ? void 0 : _a.includes("not a git repository"))) {
1339
+ console.error("Git History Error:", error);
1340
+ }
1340
1341
  res.status(500).json({ error: error.message });
1341
1342
  }
1342
1343
  });
1343
1344
  router14.get("/branch", async (req, res) => {
1345
+ var _a;
1344
1346
  try {
1345
1347
  const branch = await runGit("git branch --show-current");
1346
1348
  res.json({ branch });
1347
1349
  } catch (error) {
1348
- console.error("Git Branch Error:", error);
1350
+ if (!((_a = error.message) == null ? void 0 : _a.includes("not a git repository"))) {
1351
+ console.error("Git Branch Error:", error);
1352
+ }
1349
1353
  res.status(500).json({ error: error.message });
1350
1354
  }
1351
1355
  });
@@ -1750,7 +1754,8 @@ var MySQL = {
1750
1754
  templating: [
1751
1755
  {
1752
1756
  action: "command",
1753
- command: "npm install open"
1757
+ cmd: "npm",
1758
+ args: ["install", "open"]
1754
1759
  },
1755
1760
  {
1756
1761
  action: "file",
@@ -1773,15 +1778,18 @@ const EDITOR_URL = 'http://localhost/phpmyadmin'; // Change this to your preferr
1773
1778
  },
1774
1779
  {
1775
1780
  action: "command",
1776
- command: 'npm pkg set scripts.start="node server.js"'
1781
+ cmd: "npm",
1782
+ args: ["pkg", "set", "scripts.start=node server.js"]
1777
1783
  },
1778
1784
  {
1779
1785
  action: "command",
1780
- command: `npm pkg set scripts.stop="echo 'Note: MySQL is running as a system service. Please stop it manually.'"`
1786
+ cmd: "npm",
1787
+ args: ["pkg", "set", "scripts.stop=echo 'Note: MySQL is running as a system service. Please stop it manually.'"]
1781
1788
  },
1782
1789
  {
1783
1790
  action: "command",
1784
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-database"'
1791
+ cmd: "npm",
1792
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-database"]
1785
1793
  }
1786
1794
  ]
1787
1795
  };
@@ -1939,7 +1947,9 @@ const cleanup = () => {
1939
1947
  if (runtime.containerIds) {
1940
1948
  console.log(\`Stopping \${runtime.containerIds.length} containers...\`);
1941
1949
  runtime.containerIds.forEach(id => {
1942
- exec(\`docker stop \${id}\`);
1950
+ exec(\`docker stop \${id}\`, () => {
1951
+ exec(\`docker rm -f \${id}\`);
1952
+ });
1943
1953
  });
1944
1954
  }
1945
1955
  } catch(e) {}
@@ -1955,19 +1965,23 @@ process.on('SIGTERM', cleanup);`
1955
1965
  },
1956
1966
  {
1957
1967
  action: "command",
1958
- command: "npm install"
1968
+ cmd: "npm",
1969
+ args: ["install"]
1959
1970
  },
1960
1971
  {
1961
1972
  action: "command",
1962
- command: 'npm pkg set scripts.start="node index.js"'
1973
+ cmd: "npm",
1974
+ args: ["pkg", "set", "scripts.start=node index.js"]
1963
1975
  },
1964
1976
  {
1965
1977
  action: "command",
1966
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
1978
+ cmd: "npm",
1979
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
1967
1980
  },
1968
1981
  {
1969
1982
  action: "command",
1970
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-database"'
1983
+ cmd: "npm",
1984
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-database"]
1971
1985
  }
1972
1986
  ]
1973
1987
  };
@@ -1980,23 +1994,28 @@ var Supabase = {
1980
1994
  templating: [
1981
1995
  {
1982
1996
  action: "command",
1983
- command: "npm install supabase --save-dev"
1997
+ cmd: "npm",
1998
+ args: ["install", "supabase", "--save-dev"]
1984
1999
  },
1985
2000
  {
1986
2001
  action: "command",
1987
- command: "npx supabase init"
2002
+ cmd: "npx",
2003
+ args: ["supabase", "init"]
1988
2004
  },
1989
2005
  {
1990
2006
  action: "command",
1991
- command: 'npm pkg set scripts.start="npx supabase start"'
2007
+ cmd: "npm",
2008
+ args: ["pkg", "set", "scripts.start=npx supabase start"]
1992
2009
  },
1993
2010
  {
1994
2011
  action: "command",
1995
- command: 'npm pkg set scripts.stop="npx supabase stop"'
2012
+ cmd: "npm",
2013
+ args: ["pkg", "set", "scripts.stop=npx supabase stop"]
1996
2014
  },
1997
2015
  {
1998
2016
  action: "command",
1999
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-database"'
2017
+ cmd: "npm",
2018
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-database"]
2000
2019
  }
2001
2020
  ]
2002
2021
  };
@@ -2117,7 +2136,9 @@ const cleanup = () => {
2117
2136
  if (runtime.containerIds) {
2118
2137
  console.log(\`Stopping \${runtime.containerIds.length} containers...\`);
2119
2138
  runtime.containerIds.forEach(id => {
2120
- exec(\`docker stop \${id}\`);
2139
+ exec(\`docker stop \${id}\`, () => {
2140
+ exec(\`docker rm -f \${id}\`);
2141
+ });
2121
2142
  });
2122
2143
  }
2123
2144
  } catch(e) {}
@@ -2133,19 +2154,23 @@ process.on('SIGTERM', cleanup);`
2133
2154
  },
2134
2155
  {
2135
2156
  action: "command",
2136
- command: "npm install"
2157
+ cmd: "npm",
2158
+ args: ["install"]
2137
2159
  },
2138
2160
  {
2139
2161
  action: "command",
2140
- command: 'npm pkg set scripts.start="node index.js"'
2162
+ cmd: "npm",
2163
+ args: ["pkg", "set", "scripts.start=node index.js"]
2141
2164
  },
2142
2165
  {
2143
2166
  action: "command",
2144
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
2167
+ cmd: "npm",
2168
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
2145
2169
  },
2146
2170
  {
2147
2171
  action: "command",
2148
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-database"'
2172
+ cmd: "npm",
2173
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-database"]
2149
2174
  }
2150
2175
  ]
2151
2176
  };
@@ -2269,7 +2294,9 @@ const cleanup = () => {
2269
2294
  if (runtime.containerIds) {
2270
2295
  console.log(\`Stopping \${runtime.containerIds.length} containers...\`);
2271
2296
  runtime.containerIds.forEach(id => {
2272
- exec(\`docker stop \${id}\`);
2297
+ exec(\`docker stop \${id}\`, () => {
2298
+ exec(\`docker rm -f \${id}\`);
2299
+ });
2273
2300
  });
2274
2301
  }
2275
2302
  } catch(e) {}
@@ -2285,19 +2312,23 @@ process.on('SIGTERM', cleanup);`
2285
2312
  },
2286
2313
  {
2287
2314
  action: "command",
2288
- command: "npm install"
2315
+ cmd: "npm",
2316
+ args: ["install"]
2289
2317
  },
2290
2318
  {
2291
2319
  action: "command",
2292
- command: 'npm pkg set scripts.start="node index.js"'
2320
+ cmd: "npm",
2321
+ args: ["pkg", "set", "scripts.start=node index.js"]
2293
2322
  },
2294
2323
  {
2295
2324
  action: "command",
2296
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
2325
+ cmd: "npm",
2326
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
2297
2327
  },
2298
2328
  {
2299
2329
  action: "command",
2300
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-database"'
2330
+ cmd: "npm",
2331
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-database"]
2301
2332
  }
2302
2333
  ]
2303
2334
  };
@@ -2415,7 +2446,9 @@ const cleanup = () => {
2415
2446
  if (runtime.containerIds) {
2416
2447
  console.log(\`Stopping \${runtime.containerIds.length} containers...\`);
2417
2448
  runtime.containerIds.forEach(id => {
2418
- exec(\`docker stop \${id}\`);
2449
+ exec(\`docker stop \${id}\`, () => {
2450
+ exec(\`docker rm -f \${id}\`);
2451
+ });
2419
2452
  });
2420
2453
  }
2421
2454
  } catch(e) {}
@@ -2431,23 +2464,28 @@ process.on('SIGTERM', cleanup);`
2431
2464
  },
2432
2465
  {
2433
2466
  action: "command",
2434
- command: "npm install"
2467
+ cmd: "npm",
2468
+ args: ["install"]
2435
2469
  },
2436
2470
  {
2437
2471
  action: "command",
2438
- command: 'npm pkg set scripts.start="node index.js"'
2472
+ cmd: "npm",
2473
+ args: ["pkg", "set", "scripts.start=node index.js"]
2439
2474
  },
2440
2475
  {
2441
2476
  action: "command",
2442
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
2477
+ cmd: "npm",
2478
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
2443
2479
  },
2444
2480
  {
2445
2481
  action: "command",
2446
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-magnifying-glass"'
2482
+ cmd: "npm",
2483
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-magnifying-glass"]
2447
2484
  },
2448
2485
  {
2449
2486
  action: "command",
2450
- command: 'npm pkg set name="$(basename $PWD)"'
2487
+ cmd: "npm",
2488
+ args: ["pkg", "set", "name=$(basename $PWD)"]
2451
2489
  }
2452
2490
  ]
2453
2491
  };
@@ -2583,7 +2621,9 @@ const cleanup = () => {
2583
2621
  if (runtime.containerIds) {
2584
2622
  console.log(\`Stopping \${runtime.containerIds.length} containers...\`);
2585
2623
  runtime.containerIds.forEach(id => {
2586
- exec(\`docker stop \${id}\`);
2624
+ exec(\`docker stop \${id}\`, () => {
2625
+ exec(\`docker rm -f \${id}\`);
2626
+ });
2587
2627
  });
2588
2628
  }
2589
2629
  } catch(e) {}
@@ -2599,23 +2639,28 @@ process.on('SIGTERM', cleanup);`
2599
2639
  },
2600
2640
  {
2601
2641
  action: "command",
2602
- command: "npm install"
2642
+ cmd: "npm",
2643
+ args: ["install"]
2603
2644
  },
2604
2645
  {
2605
2646
  action: "command",
2606
- command: 'npm pkg set scripts.start="node index.js"'
2647
+ cmd: "npm",
2648
+ args: ["pkg", "set", "scripts.start=node index.js"]
2607
2649
  },
2608
2650
  {
2609
2651
  action: "command",
2610
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
2652
+ cmd: "npm",
2653
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
2611
2654
  },
2612
2655
  {
2613
2656
  action: "command",
2614
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-bucket"'
2657
+ cmd: "npm",
2658
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-bucket"]
2615
2659
  },
2616
2660
  {
2617
2661
  action: "command",
2618
- command: 'npm pkg set name="$(basename $PWD)"'
2662
+ cmd: "npm",
2663
+ args: ["pkg", "set", "name=$(basename $PWD)"]
2619
2664
  }
2620
2665
  ]
2621
2666
  };
@@ -4064,11 +4109,18 @@ var AIChat = {
4064
4109
  // Install dependencies
4065
4110
  {
4066
4111
  action: "command",
4067
- command: "npm install express"
4112
+ cmd: "npm",
4113
+ args: ["init", "-y"]
4068
4114
  },
4069
4115
  {
4070
4116
  action: "command",
4071
- command: "npm install -D nodemon typescript ts-node @types/node @types/express tsup"
4117
+ cmd: "npm",
4118
+ args: ["install", "express"]
4119
+ },
4120
+ {
4121
+ action: "command",
4122
+ cmd: "npm",
4123
+ args: ["install", "-D", "nodemon", "typescript", "ts-node", "@types/node", "@types/express", "tsup"]
4072
4124
  },
4073
4125
  // Public files
4074
4126
  {
@@ -4131,27 +4183,33 @@ var AIChat = {
4131
4183
  // NPM scripts
4132
4184
  {
4133
4185
  action: "command",
4134
- command: `npm pkg set scripts.dev="nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"`
4186
+ cmd: "npm",
4187
+ args: ["pkg", "set", "scripts.dev=nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"]
4135
4188
  },
4136
4189
  {
4137
4190
  action: "command",
4138
- command: 'npm pkg set scripts.build="tsup"'
4191
+ cmd: "npm",
4192
+ args: ["pkg", "set", "scripts.build=tsup"]
4139
4193
  },
4140
4194
  {
4141
4195
  action: "command",
4142
- command: 'npm pkg set scripts.start="node dist/index.js"'
4196
+ cmd: "npm",
4197
+ args: ["pkg", "set", "scripts.start=node dist/index.js"]
4143
4198
  },
4144
4199
  {
4145
4200
  action: "command",
4146
- command: 'npm pkg set scripts.stop="npx -y kill-port 3500"'
4201
+ cmd: "npm",
4202
+ args: ["pkg", "set", "scripts.stop=npx -y kill-port 3500"]
4147
4203
  },
4148
4204
  {
4149
4205
  action: "command",
4150
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-comments"'
4206
+ cmd: "npm",
4207
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-comments"]
4151
4208
  },
4152
4209
  {
4153
4210
  action: "command",
4154
- command: 'npm pkg set name="$(basename $PWD)"'
4211
+ cmd: "npm",
4212
+ args: ["pkg", "set", "name=$(basename $PWD)"]
4155
4213
  }
4156
4214
  ]
4157
4215
  };
@@ -4170,15 +4228,23 @@ var ViteReact = {
4170
4228
  templating: [
4171
4229
  {
4172
4230
  action: "command",
4173
- command: "npx -y create-vite@latest --template react-ts --no-interactive ."
4231
+ cmd: "rm -rf ./* ./.[!.]*",
4232
+ args: []
4174
4233
  },
4175
4234
  {
4176
4235
  action: "command",
4177
- command: "npm install"
4236
+ cmd: "npm",
4237
+ args: ["create", "vite@latest", ".", "--", "--template", "react-ts"]
4178
4238
  },
4179
4239
  {
4180
4240
  action: "command",
4181
- command: "npm install -D tailwindcss @tailwindcss/postcss autoprefixer"
4241
+ cmd: "npm",
4242
+ args: ["install"]
4243
+ },
4244
+ {
4245
+ action: "command",
4246
+ cmd: "npm",
4247
+ args: ["install", "-D", "tailwindcss", "@tailwindcss/postcss", "autoprefixer"]
4182
4248
  },
4183
4249
  {
4184
4250
  action: "file",
@@ -4192,15 +4258,18 @@ var ViteReact = {
4192
4258
  },
4193
4259
  {
4194
4260
  action: "command",
4195
- command: 'npm pkg set name="$(basename $PWD)"'
4261
+ cmd: "npm",
4262
+ args: ["pkg", "set", "name=$(basename $PWD)"]
4196
4263
  },
4197
4264
  {
4198
4265
  action: "command",
4199
- command: 'npm pkg set scripts.stop="npx -y kill-port 5173"'
4266
+ cmd: "npm",
4267
+ args: ["pkg", "set", "scripts.stop=npx -y kill-port 5173"]
4200
4268
  },
4201
4269
  {
4202
4270
  action: "command",
4203
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-globe"'
4271
+ cmd: "npm",
4272
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-globe"]
4204
4273
  }
4205
4274
  ]
4206
4275
  };
@@ -4213,23 +4282,28 @@ var NextJS = {
4213
4282
  templating: [
4214
4283
  {
4215
4284
  action: "command",
4216
- command: "rm -rf ./* ./.[!.]* 2>/dev/null || true"
4285
+ cmd: "rm -rf ./* ./.[!.]*",
4286
+ args: []
4217
4287
  },
4218
4288
  {
4219
4289
  action: "command",
4220
- command: "npx -y create-next-app@latest . --typescript --tailwind --eslint --app --yes --use-npm"
4290
+ cmd: "npx",
4291
+ args: ["-y", "create-next-app@latest", ".", "--typescript", "--tailwind", "--eslint", "--app", "--yes", "--use-npm"]
4221
4292
  },
4222
4293
  {
4223
4294
  action: "command",
4224
- command: "npm install"
4295
+ cmd: "npm",
4296
+ args: ["install"]
4225
4297
  },
4226
4298
  {
4227
4299
  action: "command",
4228
- command: 'npm pkg set name="$(basename $PWD)"'
4300
+ cmd: "npm",
4301
+ args: ["pkg", "set", "name=$(basename $PWD)"]
4229
4302
  },
4230
4303
  {
4231
4304
  action: "command",
4232
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-globe"'
4305
+ cmd: "npm",
4306
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-globe"]
4233
4307
  }
4234
4308
  ]
4235
4309
  };
@@ -4296,15 +4370,23 @@ var ExpressTS = {
4296
4370
  templating: [
4297
4371
  {
4298
4372
  action: "command",
4299
- command: "npm install express"
4373
+ cmd: "npm",
4374
+ args: ["init", "-y"]
4375
+ },
4376
+ {
4377
+ action: "command",
4378
+ cmd: "npm",
4379
+ args: ["install", "express"]
4300
4380
  },
4301
4381
  {
4302
4382
  action: "command",
4303
- command: "npm install -D nodemon typescript ts-node @types/node @types/express"
4383
+ cmd: "npm",
4384
+ args: ["install", "-D", "nodemon", "typescript", "ts-node", "@types/node", "@types/express"]
4304
4385
  },
4305
4386
  {
4306
4387
  action: "command",
4307
- command: "npm install -D tsup"
4388
+ cmd: "npm",
4389
+ args: ["install", "-D", "tsup"]
4308
4390
  },
4309
4391
  {
4310
4392
  action: "file",
@@ -4333,23 +4415,28 @@ var ExpressTS = {
4333
4415
  },
4334
4416
  {
4335
4417
  action: "command",
4336
- command: `npm pkg set scripts.dev="nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"`
4418
+ cmd: "npm",
4419
+ args: ["pkg", "set", "scripts.dev=nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"]
4337
4420
  },
4338
4421
  {
4339
4422
  action: "command",
4340
- command: 'npm pkg set scripts.build="tsup"'
4423
+ cmd: "npm",
4424
+ args: ["pkg", "set", "scripts.build=tsup"]
4341
4425
  },
4342
4426
  {
4343
4427
  action: "command",
4344
- command: 'npm pkg set scripts.start="node dist/index.js"'
4428
+ cmd: "npm",
4429
+ args: ["pkg", "set", "scripts.start=node dist/index.js"]
4345
4430
  },
4346
4431
  {
4347
4432
  action: "command",
4348
- command: 'npm pkg set scripts.stop="npx -y kill-port 3500"'
4433
+ cmd: "npm",
4434
+ args: ["pkg", "set", "scripts.stop=npx -y kill-port 3500"]
4349
4435
  },
4350
4436
  {
4351
4437
  action: "command",
4352
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-server"'
4438
+ cmd: "npm",
4439
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-server"]
4353
4440
  }
4354
4441
  ]
4355
4442
  };
@@ -4367,19 +4454,23 @@ var PHP = {
4367
4454
  },
4368
4455
  {
4369
4456
  action: "command",
4370
- command: 'npm pkg set scripts.dev="php -S localhost:3000"'
4457
+ cmd: "npm",
4458
+ args: ["pkg", "set", "scripts.dev=php -S localhost:3000"]
4371
4459
  },
4372
4460
  {
4373
4461
  action: "command",
4374
- command: 'npm pkg set scripts.start="php -S localhost:3000"'
4462
+ cmd: "npm",
4463
+ args: ["pkg", "set", "scripts.start=php -S localhost:3000"]
4375
4464
  },
4376
4465
  {
4377
4466
  action: "command",
4378
- command: 'npm pkg set scripts.stop="npx kill-port 3000"'
4467
+ cmd: "npm",
4468
+ args: ["pkg", "set", "scripts.stop=npx kill-port 3000"]
4379
4469
  },
4380
4470
  {
4381
4471
  action: "command",
4382
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-server"'
4472
+ cmd: "npm",
4473
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-server"]
4383
4474
  }
4384
4475
  ]
4385
4476
  };
@@ -4392,31 +4483,38 @@ var Laravel = {
4392
4483
  templating: [
4393
4484
  {
4394
4485
  action: "command",
4395
- command: "rm -rf ./* ./.[!.]* 2>/dev/null || true"
4486
+ cmd: "rm -rf ./* ./.[!.]*",
4487
+ args: []
4396
4488
  },
4397
4489
  {
4398
4490
  action: "command",
4399
- command: "composer create-project laravel/laravel . --no-interaction --no-progress"
4491
+ cmd: "composer",
4492
+ args: ["create-project", "laravel/laravel", ".", "--no-interaction", "--no-progress"]
4400
4493
  },
4401
4494
  {
4402
4495
  action: "command",
4403
- command: 'npm pkg set name="$(basename $PWD)"'
4496
+ cmd: "npm",
4497
+ args: ["pkg", "set", "name=$(basename $PWD)"]
4404
4498
  },
4405
4499
  {
4406
4500
  action: "command",
4407
- command: 'npm pkg set scripts.dev="php artisan serve"'
4501
+ cmd: "npm",
4502
+ args: ["pkg", "set", "scripts.dev=php artisan serve"]
4408
4503
  },
4409
4504
  {
4410
4505
  action: "command",
4411
- command: 'npm pkg set scripts.start="php artisan serve"'
4506
+ cmd: "npm",
4507
+ args: ["pkg", "set", "scripts.start=php artisan serve"]
4412
4508
  },
4413
4509
  {
4414
4510
  action: "command",
4415
- command: 'npm pkg set scripts.stop="npx -y kill-port 8000"'
4511
+ cmd: "npm",
4512
+ args: ["pkg", "set", "scripts.stop=npx -y kill-port 8000"]
4416
4513
  },
4417
4514
  {
4418
4515
  action: "command",
4419
- command: 'npm pkg set fontawesomeIcon="fa-brands fa-laravel"'
4516
+ cmd: "npm",
4517
+ args: ["pkg", "set", "fontawesomeIcon=fa-brands fa-laravel"]
4420
4518
  }
4421
4519
  ]
4422
4520
  };
@@ -4438,15 +4536,18 @@ var PythonConsole = {
4438
4536
  },
4439
4537
  {
4440
4538
  action: "command",
4441
- command: 'npm pkg set scripts.dev="python3 main.py"'
4539
+ cmd: "npm",
4540
+ args: ["pkg", "set", "scripts.dev=python3 main.py"]
4442
4541
  },
4443
4542
  {
4444
4543
  action: "command",
4445
- command: 'npm pkg set scripts.start="python3 main.py"'
4544
+ cmd: "npm",
4545
+ args: ["pkg", "set", "scripts.start=python3 main.py"]
4446
4546
  },
4447
4547
  {
4448
4548
  action: "command",
4449
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-terminal"'
4549
+ cmd: "npm",
4550
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-terminal"]
4450
4551
  }
4451
4552
  ]
4452
4553
  };
@@ -4465,7 +4566,8 @@ var DotNetConsole = {
4465
4566
  templating: [
4466
4567
  {
4467
4568
  action: "command",
4468
- command: "dotnet new console"
4569
+ cmd: "dotnet",
4570
+ args: ["new", "console"]
4469
4571
  },
4470
4572
  {
4471
4573
  action: "file",
@@ -4474,15 +4576,18 @@ var DotNetConsole = {
4474
4576
  },
4475
4577
  {
4476
4578
  action: "command",
4477
- command: 'npm pkg set scripts.dev="dotnet run"'
4579
+ cmd: "npm",
4580
+ args: ["pkg", "set", "scripts.dev=dotnet run"]
4478
4581
  },
4479
4582
  {
4480
4583
  action: "command",
4481
- command: 'npm pkg set scripts.start="dotnet run"'
4584
+ cmd: "npm",
4585
+ args: ["pkg", "set", "scripts.start=dotnet run"]
4482
4586
  },
4483
4587
  {
4484
4588
  action: "command",
4485
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-terminal"'
4589
+ cmd: "npm",
4590
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-terminal"]
4486
4591
  }
4487
4592
  ]
4488
4593
  };
@@ -4507,27 +4612,33 @@ var N8NLocal = {
4507
4612
  templating: [
4508
4613
  {
4509
4614
  action: "command",
4510
- command: "npm install n8n"
4615
+ cmd: "npm",
4616
+ args: ["install", "n8n"]
4511
4617
  },
4512
4618
  {
4513
4619
  action: "command",
4514
- command: 'npm pkg set scripts.dev="npx n8n"'
4620
+ cmd: "npm",
4621
+ args: ["pkg", "set", "scripts.dev=npx n8n"]
4515
4622
  },
4516
4623
  {
4517
4624
  action: "command",
4518
- command: 'npm pkg set scripts.start="npx n8n"'
4625
+ cmd: "npm",
4626
+ args: ["pkg", "set", "scripts.start=npx n8n"]
4519
4627
  },
4520
4628
  {
4521
4629
  action: "command",
4522
- command: 'npm pkg set scripts.stop="npx kill-port 5678"'
4630
+ cmd: "npm",
4631
+ args: ["pkg", "set", "scripts.stop=npx kill-port 5678"]
4523
4632
  },
4524
4633
  {
4525
4634
  action: "command",
4526
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-robot"'
4635
+ cmd: "npm",
4636
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-robot"]
4527
4637
  },
4528
4638
  {
4529
4639
  action: "command",
4530
- command: 'npm pkg set name="$(basename $PWD)"'
4640
+ cmd: "npm",
4641
+ args: ["pkg", "set", "name=$(basename $PWD)"]
4531
4642
  }
4532
4643
  ]
4533
4644
  };
@@ -5132,7 +5243,8 @@ var AWSTemplate = {
5132
5243
  },
5133
5244
  {
5134
5245
  action: "command",
5135
- command: "mkdir -p examples/frontend examples/nodeserver"
5246
+ cmd: "mkdir",
5247
+ args: ["-p", "examples/frontend", "examples/nodeserver"]
5136
5248
  },
5137
5249
  {
5138
5250
  action: "file",
@@ -5146,19 +5258,23 @@ var AWSTemplate = {
5146
5258
  },
5147
5259
  {
5148
5260
  action: "command",
5149
- command: 'npm pkg set scripts.dev="node server.js"'
5261
+ cmd: "npm",
5262
+ args: ["pkg", "set", "scripts.dev=node server.js"]
5150
5263
  },
5151
5264
  {
5152
5265
  action: "command",
5153
- command: 'npm pkg set scripts.stop="node stop.js"'
5266
+ cmd: "npm",
5267
+ args: ["pkg", "set", "scripts.stop=node stop.js"]
5154
5268
  },
5155
5269
  {
5156
5270
  action: "command",
5157
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-cloud"'
5271
+ cmd: "npm",
5272
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-cloud"]
5158
5273
  },
5159
5274
  {
5160
5275
  action: "command",
5161
- command: 'npm pkg set name="$(basename $PWD)"'
5276
+ cmd: "npm",
5277
+ args: ["pkg", "set", "name=$(basename $PWD)"]
5162
5278
  }
5163
5279
  ]
5164
5280
  };
@@ -5355,31 +5471,38 @@ var StripeTemplate = {
5355
5471
  },
5356
5472
  {
5357
5473
  action: "command",
5358
- command: "npm install stripe"
5474
+ cmd: "npm",
5475
+ args: ["install", "stripe"]
5359
5476
  },
5360
5477
  {
5361
5478
  action: "command",
5362
- command: 'npm pkg set scripts.dev="node server.js"'
5479
+ cmd: "npm",
5480
+ args: ["pkg", "set", "scripts.dev=node server.js"]
5363
5481
  },
5364
5482
  {
5365
5483
  action: "command",
5366
- command: 'npm pkg set scripts.start="node server.js"'
5484
+ cmd: "npm",
5485
+ args: ["pkg", "set", "scripts.start=node server.js"]
5367
5486
  },
5368
5487
  {
5369
5488
  action: "command",
5370
- command: 'npm pkg set scripts.test="node test.js"'
5489
+ cmd: "npm",
5490
+ args: ["pkg", "set", "scripts.test=node test.js"]
5371
5491
  },
5372
5492
  {
5373
5493
  action: "command",
5374
- command: `npm pkg set scripts.stop="node -e 'const fs=require(\\"fs\\"); try{const p=JSON.parse(fs.readFileSync(\\".runtime.json\\")).port; fetch(\\"http://localhost:\\"+p+\\"/stop\\").catch(e=>{})}catch(e){}'"`
5494
+ cmd: "npm",
5495
+ args: ["pkg", "set", `scripts.stop=node -e 'const fs=require("fs"); try{const p=JSON.parse(fs.readFileSync(".runtime.json")).port; fetch("http://localhost:"+p+"/stop").catch(e=>{})}catch(e){}'`]
5375
5496
  },
5376
5497
  {
5377
5498
  action: "command",
5378
- command: 'npm pkg set fontawesomeIcon="fa-solid fa-credit-card"'
5499
+ cmd: "npm",
5500
+ args: ["pkg", "set", "fontawesomeIcon=fa-solid fa-credit-card"]
5379
5501
  },
5380
5502
  {
5381
5503
  action: "command",
5382
- command: 'npm pkg set name="$(basename $PWD)"'
5504
+ cmd: "npm",
5505
+ args: ["pkg", "set", "name=$(basename $PWD)"]
5383
5506
  }
5384
5507
  ]
5385
5508
  };
@@ -5422,12 +5545,15 @@ router18.get("/", (req, res) => {
5422
5545
  });
5423
5546
  var availabletemplates_default = router18;
5424
5547
 
5425
- // src/routes/setworkspacetemplate.ts
5548
+ // src/routes/setworkspace/index.ts
5426
5549
  var import_express22 = __toESM(require("express"));
5550
+
5551
+ // src/routes/setworkspace/template.ts
5552
+ var import_path16 = __toESM(require("path"));
5553
+
5554
+ // src/routes/setworkspace/utils.ts
5427
5555
  var import_fs3 = require("fs");
5428
5556
  var import_path14 = __toESM(require("path"));
5429
- var import_execa = require("execa");
5430
- var router19 = import_express22.default.Router();
5431
5557
  async function ensureDirectory(dirPath) {
5432
5558
  try {
5433
5559
  await import_fs3.promises.mkdir(dirPath, { recursive: true });
@@ -5443,10 +5569,14 @@ async function writeFile(filePath, content) {
5443
5569
  await import_fs3.promises.writeFile(filePath, content, { encoding: "utf8" });
5444
5570
  }
5445
5571
  var isWindows = process.platform === "win32";
5572
+
5573
+ // src/routes/setworkspace/command.ts
5574
+ var import_path15 = __toESM(require("path"));
5575
+ var import_execa = require("execa");
5446
5576
  function preprocessCommand(command, cwd) {
5447
5577
  let processedCommand = command;
5448
5578
  if (processedCommand.includes("$(basename $PWD)")) {
5449
- const dirName = import_path14.default.basename(cwd);
5579
+ const dirName = import_path15.default.basename(cwd);
5450
5580
  processedCommand = processedCommand.replace(/\$\(basename \$PWD\)/g, dirName);
5451
5581
  }
5452
5582
  if (processedCommand.match(/rm\s+-rf\s+\.\/\*\s+\.\/\.\[!\.\]\*.*$/)) {
@@ -5461,13 +5591,17 @@ function preprocessCommand(command, cwd) {
5461
5591
  }
5462
5592
  return processedCommand;
5463
5593
  }
5464
- async function runCommand2(command, cwd) {
5594
+ async function runCommand2(command, args, cwd, useShell = false) {
5465
5595
  try {
5466
- const result = await (0, import_execa.execa)(command, {
5596
+ let cmd = command;
5597
+ if (!useShell && process.platform === "win32" && (command === "npm" || command === "npx")) {
5598
+ cmd = `${command}.cmd`;
5599
+ }
5600
+ const result = await (0, import_execa.execa)(cmd, args, {
5467
5601
  cwd,
5468
- shell: true,
5469
5602
  // Detach from parent's stdio to avoid IDE terminal conflicts
5470
5603
  stdin: "ignore",
5604
+ shell: useShell,
5471
5605
  // Set non-interactive environment
5472
5606
  env: {
5473
5607
  ...process.env,
@@ -5483,17 +5617,23 @@ async function runCommand2(command, cwd) {
5483
5617
  // Timeout after 5 minutes (for npm install which can be slow)
5484
5618
  timeout: 3e5
5485
5619
  });
5486
- return { stdout: result.stdout || "", stderr: result.stderr || "" };
5620
+ return {
5621
+ stdout: result.stdout ?? "",
5622
+ stderr: result.stderr ?? ""
5623
+ };
5487
5624
  } catch (error) {
5488
5625
  const execaError = error;
5489
5626
  throw new Error(
5490
- `Command failed: ${command}
5627
+ `Command failed: ${command} ${args.join(" ")}
5628
+ Error code: ${execaError.code || "N/A"}
5491
5629
  Exit code: ${execaError.exitCode}
5492
5630
  stderr: ${execaError.stderr || "N/A"}
5493
5631
  stdout: ${execaError.stdout || "N/A"}`
5494
5632
  );
5495
5633
  }
5496
5634
  }
5635
+
5636
+ // src/routes/setworkspace/template.ts
5497
5637
  function findTemplate(templatename) {
5498
5638
  const categories = ["project", "database", "services", "demo"];
5499
5639
  for (const cat of categories) {
@@ -5511,29 +5651,47 @@ async function executeTemplate(template, workspacePath, onProgress) {
5511
5651
  if (!template) {
5512
5652
  throw new Error("Template not found");
5513
5653
  }
5654
+ await ensureDirectory(workspacePath);
5514
5655
  const progress = onProgress || ((msg) => console.log(`[Template] ${msg}`));
5515
5656
  for (const step of template.templating) {
5516
- if (step.action === "command" && step.command) {
5517
- const processedCommand = preprocessCommand(step.command, workspacePath);
5518
- progress(`Running: ${processedCommand}`);
5657
+ if (step.action === "command" && step.cmd) {
5658
+ const cmd = step.cmd;
5659
+ let args = step.args || [];
5660
+ const rawFullCmd = args.length > 0 ? `${cmd} ${args.join(" ")}` : cmd;
5661
+ const processedCmd = preprocessCommand(rawFullCmd, workspacePath);
5662
+ let finalCmd = cmd;
5663
+ let finalArgs = args;
5664
+ let useShell = false;
5665
+ if (processedCmd !== rawFullCmd || cmd.includes(" ") && args.length === 0) {
5666
+ finalCmd = processedCmd;
5667
+ finalArgs = [];
5668
+ useShell = true;
5669
+ } else {
5670
+ const dirName = import_path16.default.basename(workspacePath);
5671
+ finalArgs = finalArgs.map((arg) => arg.replace(/\$\(basename \$PWD\)/g, dirName));
5672
+ }
5673
+ progress(`Running: ${finalCmd} ${finalArgs.join(" ")}`);
5519
5674
  try {
5520
- const result = await runCommand2(processedCommand, workspacePath);
5675
+ const result = await runCommand2(finalCmd, finalArgs, workspacePath, useShell);
5521
5676
  if (result.stdout.trim()) {
5522
5677
  const truncated = result.stdout.trim().slice(0, 200);
5523
5678
  progress(`Output: ${truncated}${result.stdout.length > 200 ? "..." : ""}`);
5524
5679
  }
5525
5680
  } catch (cmdErr) {
5526
- console.error(`Command failed: ${step.command}`, cmdErr);
5527
- throw new Error(`Command failed: ${step.command}
5681
+ console.error(`Command failed: ${finalCmd}`, cmdErr);
5682
+ throw new Error(`Command failed: ${finalCmd}
5528
5683
  ${cmdErr.message}`);
5529
5684
  }
5530
5685
  } else if (step.action === "file" && step.file && step.filecontent !== void 0) {
5531
5686
  progress(`Creating file: ${step.file}`);
5532
- const filePath = import_path14.default.join(workspacePath, step.file);
5687
+ const filePath = import_path16.default.join(workspacePath, step.file);
5533
5688
  await writeFile(filePath, step.filecontent);
5534
5689
  }
5535
5690
  }
5536
5691
  }
5692
+
5693
+ // src/routes/setworkspace/index.ts
5694
+ var router19 = import_express22.default.Router();
5537
5695
  router19.post("/", async (req, res) => {
5538
5696
  try {
5539
5697
  const { workspace, templatename } = req.body;
@@ -5555,7 +5713,7 @@ router19.post("/", async (req, res) => {
5555
5713
  res.status(500).json({ error: "Failed to apply template: " + error.message });
5556
5714
  }
5557
5715
  });
5558
- var setworkspacetemplate_default = router19;
5716
+ var setworkspace_default = router19;
5559
5717
  function setWorkspaceTemplateSocket(io2) {
5560
5718
  io2.on("connection", (socket) => {
5561
5719
  socket.on("template:start", async (data) => {
@@ -5590,18 +5748,75 @@ function setWorkspaceTemplateSocket(io2) {
5590
5748
  // src/routes/stopTerminalWorkspace.ts
5591
5749
  var import_express23 = require("express");
5592
5750
  var import_fs_extra12 = __toESM(require("fs-extra"));
5593
- var import_path15 = __toESM(require("path"));
5594
- var import_child_process8 = require("child_process");
5595
- var import_util2 = __toESM(require("util"));
5596
- var execAsync2 = import_util2.default.promisify(import_child_process8.exec);
5751
+ var import_path17 = __toESM(require("path"));
5752
+ var import_execa2 = require("execa");
5753
+ var import_tree_kill = __toESM(require("tree-kill"));
5597
5754
  var router20 = (0, import_express23.Router)();
5755
+ async function killProcessTree(pid, signal = "SIGKILL") {
5756
+ return new Promise((resolve, reject) => {
5757
+ (0, import_tree_kill.default)(pid, signal, (err) => {
5758
+ if (err) {
5759
+ console.error(`[StopTerminal] Error killing process tree for PID ${pid}:`, err.message);
5760
+ reject(err);
5761
+ } else {
5762
+ console.log(`[StopTerminal] Successfully killed process tree for PID ${pid}`);
5763
+ resolve();
5764
+ }
5765
+ });
5766
+ });
5767
+ }
5768
+ async function stopDockerContainers(containerIds) {
5769
+ for (const cid of containerIds) {
5770
+ try {
5771
+ console.log(`[StopTerminal] Stopping container ${cid}`);
5772
+ await (0, import_execa2.execa)("docker", ["stop", cid]);
5773
+ console.log(`[StopTerminal] Stopped container ${cid}`);
5774
+ try {
5775
+ await (0, import_execa2.execa)("docker", ["rm", cid]);
5776
+ console.log(`[StopTerminal] Removed container ${cid}`);
5777
+ } catch (rmError) {
5778
+ console.log(`[StopTerminal] Container ${cid} already removed or doesn't exist`);
5779
+ }
5780
+ } catch (e) {
5781
+ console.error(`[StopTerminal] Error stopping container ${cid}:`, e.message);
5782
+ }
5783
+ }
5784
+ }
5785
+ function stopTerminalProcessInternal(socketId) {
5786
+ var _a, _b;
5787
+ const session = activeTerminals.get(socketId);
5788
+ if (session) {
5789
+ const { child, socket } = session;
5790
+ if (socket.connected) {
5791
+ socket.emit("terminal:log", "\r\n\x1B[33m[System] Stopping interactive terminal process...\x1B[0m\r\n");
5792
+ }
5793
+ child.removeAllListeners();
5794
+ (_a = child.stdout) == null ? void 0 : _a.removeAllListeners();
5795
+ (_b = child.stderr) == null ? void 0 : _b.removeAllListeners();
5796
+ if (child.pid) {
5797
+ killProcessTree(child.pid).catch((err) => {
5798
+ console.error("[StopTerminal] Error in killProcessTree:", err);
5799
+ try {
5800
+ child.kill("SIGKILL");
5801
+ } catch (e) {
5802
+ console.error("[StopTerminal] Fallback kill also failed:", e);
5803
+ }
5804
+ });
5805
+ } else {
5806
+ child.kill();
5807
+ }
5808
+ activeTerminals.delete(socketId);
5809
+ return true;
5810
+ }
5811
+ return false;
5812
+ }
5598
5813
  router20.post("/", async (req, res) => {
5599
5814
  try {
5600
5815
  const { socketId, workspace } = req.body;
5601
5816
  if (workspace && workspace.name) {
5602
5817
  const workspacePath = workspace.path;
5603
5818
  if (!workspacePath) {
5604
- console.error(`[StopTerminal] ERROR: No workspace path provided for ${workspace.name}. Docker cleanup may fail.`);
5819
+ console.error(`[StopTerminal] ERROR: No workspace path provided for ${workspace.name}. Cleanup may fail.`);
5605
5820
  }
5606
5821
  let socket = null;
5607
5822
  let activeSession = null;
@@ -5615,6 +5830,7 @@ router20.post("/", async (req, res) => {
5615
5830
  }
5616
5831
  }
5617
5832
  const log = (msg) => {
5833
+ console.log(`[StopTerminal] ${msg}`);
5618
5834
  if (activeSession && activeSession.socket && activeSession.socket.connected) {
5619
5835
  activeSession.socket.emit("terminal:log", `\r
5620
5836
  \x1B[33m[System] ${msg}\x1B[0m\r
@@ -5624,80 +5840,66 @@ router20.post("/", async (req, res) => {
5624
5840
  if (activeSession) {
5625
5841
  log("Stopping workspace resources...");
5626
5842
  }
5627
- if (workspacePath && await import_fs_extra12.default.pathExists(import_path15.default.join(workspacePath, ".runtime.json"))) {
5843
+ if (workspacePath && await import_fs_extra12.default.pathExists(import_path17.default.join(workspacePath, ".runtime.json"))) {
5628
5844
  try {
5629
- if (activeSession) log("Checking/Stopping Docker container...");
5630
- const runtimeConfig = await import_fs_extra12.default.readJSON(import_path15.default.join(workspacePath, ".runtime.json"));
5845
+ log("Checking/Stopping Docker containers...");
5846
+ const runtimeConfig = await import_fs_extra12.default.readJSON(import_path17.default.join(workspacePath, ".runtime.json"));
5631
5847
  if (runtimeConfig && runtimeConfig.containerIds && Array.isArray(runtimeConfig.containerIds)) {
5632
- console.log(`[StopTerminal] Stopping ${runtimeConfig.containerIds.length} containers...`);
5633
- activeSession && log(`Stopping ${runtimeConfig.containerIds.length} Docker containers...`);
5634
- for (const cid of runtimeConfig.containerIds) {
5635
- try {
5636
- console.log(`[StopTerminal] Stopping container ${cid}`);
5637
- await execAsync2(`docker stop ${cid}`);
5638
- console.log(`[StopTerminal] Container ${cid} stopped.`);
5639
- } catch (e) {
5640
- console.error(`[StopTerminal] Error stopping container ${cid}:`, e);
5641
- activeSession && log(`Error stopping container ${cid}: ${e.message}`);
5642
- }
5643
- }
5644
- activeSession && log("All Docker containers stopped.");
5848
+ log(`Stopping ${runtimeConfig.containerIds.length} Docker containers...`);
5849
+ await stopDockerContainers(runtimeConfig.containerIds);
5850
+ log("All Docker containers stopped and removed.");
5645
5851
  } else if (runtimeConfig && runtimeConfig.containerId) {
5646
- console.log(`[StopTerminal] Stopping container ${runtimeConfig.containerId}`);
5647
- await execAsync2(`docker stop ${runtimeConfig.containerId}`);
5648
- console.log(`[StopTerminal] Container stopped.`);
5649
- if (activeSession) log("Docker container stopped.");
5852
+ await stopDockerContainers([runtimeConfig.containerId]);
5853
+ log("Docker container stopped and removed.");
5650
5854
  } else {
5651
- if (activeSession) log("No active container ID found in config.");
5855
+ log("No active container ID found in config.");
5652
5856
  }
5653
5857
  } catch (e) {
5654
5858
  console.error("[StopTerminal] Error stopping docker:", e);
5655
- if (activeSession) log(`Error stopping Docker: ${e.message}`);
5859
+ log(`Error stopping Docker: ${e.message}`);
5656
5860
  }
5657
- } else {
5658
5861
  }
5659
5862
  if (workspacePath) {
5660
5863
  try {
5661
- if (activeSession) log("Running npm run stop...");
5662
- await execAsync2("npm run stop", { cwd: workspacePath });
5663
- if (activeSession) log("npm run stop executed.");
5864
+ log("Running npm run stop...");
5865
+ await (0, import_execa2.execa)("npm", ["run", "stop"], {
5866
+ cwd: workspacePath,
5867
+ shell: true,
5868
+ reject: false
5869
+ // Don't throw on non-zero exit
5870
+ });
5871
+ log("npm run stop executed.");
5664
5872
  } catch (e) {
5665
- if (activeSession) log(`Error running npm run stop (might not exist): ${e.message}`);
5873
+ log(`npm run stop not available or failed (this is okay): ${e.message}`);
5666
5874
  }
5667
5875
  }
5668
5876
  let stopped = false;
5669
5877
  if (activeSession && activeSessionId) {
5670
- log("Closing terminal in 1 second...");
5671
- await new Promise((resolve) => setTimeout(resolve, 1e3));
5672
5878
  const currentProcess = activeSession.child;
5673
5879
  if (currentProcess && currentProcess.pid) {
5674
- if (process.platform === "win32") {
5675
- (0, import_child_process8.exec)(`taskkill /pid ${currentProcess.pid} /T /F`, (err) => {
5676
- });
5677
- } else {
5678
- try {
5679
- process.kill(-currentProcess.pid, "SIGKILL");
5680
- } catch (e) {
5681
- try {
5682
- currentProcess.kill("SIGKILL");
5683
- } catch (e2) {
5684
- }
5685
- }
5880
+ log(`Killing process tree for PID ${currentProcess.pid}...`);
5881
+ try {
5882
+ await killProcessTree(currentProcess.pid, "SIGKILL");
5883
+ log("Process tree killed successfully.");
5884
+ } catch (e) {
5885
+ console.error("[StopTerminal] Error killing process tree:", e);
5886
+ log(`Error killing process tree: ${e.message}`);
5686
5887
  }
5687
5888
  }
5688
- stopTerminalProcess(activeSessionId);
5889
+ stopTerminalProcessInternal(activeSessionId);
5689
5890
  stopped = true;
5891
+ log("Terminal session cleaned up.");
5690
5892
  }
5893
+ await new Promise((resolve) => setTimeout(resolve, 500));
5691
5894
  if (stopped) {
5692
- res.json({ success: true, message: `Terminated process for workspace ${workspace.name}` });
5895
+ res.json({ success: true, message: `Terminated process and freed resources for workspace ${workspace.name}` });
5693
5896
  } else {
5694
- await new Promise((resolve) => setTimeout(resolve, 500));
5695
5897
  res.json({ success: true, message: `Cleanup performed for workspace ${workspace.name} (no active terminal found)` });
5696
5898
  }
5697
5899
  return;
5698
5900
  }
5699
5901
  if (socketId) {
5700
- const stopped = stopTerminalProcess(socketId);
5902
+ const stopped = stopTerminalProcessInternal(socketId);
5701
5903
  if (stopped) {
5702
5904
  res.json({ success: true, message: `Terminated process for socket ${socketId}` });
5703
5905
  } else {
@@ -5743,11 +5945,11 @@ app.use("/" + api_default.initMonorepoTime, initmonorepotime_default);
5743
5945
  app.use("/" + api_default.processTree, processUsage_default);
5744
5946
  app.use("/" + api_default.docker, apidocker_default);
5745
5947
  app.use("/" + api_default.availabletemplates, availabletemplates_default);
5746
- app.use("/" + api_default.setWorkspaceTemplate, setworkspacetemplate_default);
5747
- var frontendPath = import_path16.default.join(__dirname, "../public");
5948
+ app.use("/" + api_default.setWorkspaceTemplate, setworkspace_default);
5949
+ var frontendPath = import_path18.default.join(__dirname, "../public");
5748
5950
  app.use(import_express24.default.static(frontendPath));
5749
5951
  app.get("*", (req, res) => {
5750
- res.sendFile(import_path16.default.join(frontendPath, "index.html"));
5952
+ res.sendFile(import_path18.default.join(frontendPath, "index.html"));
5751
5953
  });
5752
5954
  var httpServer = (0, import_http.createServer)(app);
5753
5955
  var io = new import_socket.Server(httpServer, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monorepotime",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "monorepo / turborepo gui tools built with nodejs and reactjs",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -21,7 +21,8 @@
21
21
  "fs-extra": "^11.3.3",
22
22
  "open": "^11.0.0",
23
23
  "pidusage": "^4.0.1",
24
- "socket.io": "^4.8.3"
24
+ "socket.io": "^4.8.3",
25
+ "tree-kill": "^1.2.2"
25
26
  },
26
27
  "keywords": [
27
28
  "monorepotime",
@@ -52,7 +53,7 @@
52
53
  "typescript": "^5.9.3"
53
54
  },
54
55
  "bin": {
55
- "monorepotime": "./dist/index.js"
56
+ "monorepotime": "dist/index.js"
56
57
  },
57
58
  "files": [
58
59
  "dist",