monorepotime 1.0.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.
- package/dist/index.js +106 -0
- package/dist/routes/_temp.js +9 -0
- package/dist/routes/interactiveTerminal.js +145 -0
- package/dist/routes/listworkspacedirs.js +107 -0
- package/dist/routes/newworkspace.js +43 -0
- package/dist/routes/rootPath.js +36 -0
- package/dist/routes/runcmddev.js +61 -0
- package/dist/routes/scafoldrepo.js +156 -0
- package/dist/routes/scanworkspace.js +167 -0
- package/dist/routes/stopcmd.js +203 -0
- package/dist/routes/turborepoexist.js +31 -0
- package/dist/routes/updateworkspace.js +50 -0
- package/dist/routes/vscodeHideShow.js +129 -0
- package/package.json +47 -0
- package/public/assets/index-DjKHu3u0.css +1 -0
- package/public/assets/index-L0znsqFE.js +100 -0
- package/public/index.html +30 -0
- package/public/og-image.png +0 -0
- package/public/vite.svg +1 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.httpServer = exports.io = exports.app = void 0;
|
|
41
|
+
const express_1 = __importDefault(require("express"));
|
|
42
|
+
const cors_1 = __importDefault(require("cors"));
|
|
43
|
+
const path_1 = __importDefault(require("path"));
|
|
44
|
+
const apiroute_1 = __importDefault(require("apiroute"));
|
|
45
|
+
const config_1 = __importDefault(require("config"));
|
|
46
|
+
const open_1 = __importDefault(require("open"));
|
|
47
|
+
const http_1 = require("http");
|
|
48
|
+
const socket_io_1 = require("socket.io");
|
|
49
|
+
//routers
|
|
50
|
+
const scanworkspace_1 = __importDefault(require("./routes/scanworkspace"));
|
|
51
|
+
const runcmddev_1 = __importDefault(require("./routes/runcmddev"));
|
|
52
|
+
const stopcmd_1 = __importDefault(require("./routes/stopcmd"));
|
|
53
|
+
const listworkspacedirs_1 = __importDefault(require("./routes/listworkspacedirs"));
|
|
54
|
+
const newworkspace_1 = __importDefault(require("./routes/newworkspace"));
|
|
55
|
+
const interactiveTerminal_1 = __importStar(require("./routes/interactiveTerminal"));
|
|
56
|
+
const updateworkspace_1 = __importDefault(require("./routes/updateworkspace"));
|
|
57
|
+
const vscodeHideShow_1 = __importDefault(require("./routes/vscodeHideShow"));
|
|
58
|
+
const rootPath_1 = __importDefault(require("./routes/rootPath"));
|
|
59
|
+
const scafoldrepo_1 = __importDefault(require("./routes/scafoldrepo"));
|
|
60
|
+
const turborepoexist_1 = __importDefault(require("./routes/turborepoexist"));
|
|
61
|
+
const app = (0, express_1.default)();
|
|
62
|
+
exports.app = app;
|
|
63
|
+
const port = config_1.default.apiPort;
|
|
64
|
+
app.use((0, cors_1.default)({
|
|
65
|
+
origin: true,
|
|
66
|
+
credentials: true,
|
|
67
|
+
}));
|
|
68
|
+
app.use(express_1.default.static('public'));
|
|
69
|
+
app.use(express_1.default.json());
|
|
70
|
+
// Serve frontend static files
|
|
71
|
+
//routes=======================================================================
|
|
72
|
+
app.use("/" + apiroute_1.default.scanWorkspace, scanworkspace_1.default);
|
|
73
|
+
app.use("/" + apiroute_1.default.stopProcess, stopcmd_1.default);
|
|
74
|
+
app.use("/" + apiroute_1.default.listWorkspacesDir, listworkspacedirs_1.default);
|
|
75
|
+
app.use("/" + apiroute_1.default.newWorkspace, newworkspace_1.default);
|
|
76
|
+
app.use("/" + apiroute_1.default.interactvTerminal, interactiveTerminal_1.default);
|
|
77
|
+
app.use("/" + apiroute_1.default.updateWorkspace, updateworkspace_1.default);
|
|
78
|
+
app.use("/" + apiroute_1.default.hideShowFileFolder, vscodeHideShow_1.default);
|
|
79
|
+
app.use("/" + apiroute_1.default.getRootPath, rootPath_1.default);
|
|
80
|
+
app.use("/" + apiroute_1.default.scaffoldRepo, scafoldrepo_1.default);
|
|
81
|
+
app.use("/" + apiroute_1.default.turborepoExist, turborepoexist_1.default);
|
|
82
|
+
// Serve frontend static files==================================================
|
|
83
|
+
const frontendPath = path_1.default.join(__dirname, '../public');
|
|
84
|
+
app.use(express_1.default.static(frontendPath));
|
|
85
|
+
app.get('*', (req, res) => {
|
|
86
|
+
res.sendFile(path_1.default.join(frontendPath, 'index.html'));
|
|
87
|
+
});
|
|
88
|
+
// Socket.IO Setup ============================================================
|
|
89
|
+
const httpServer = (0, http_1.createServer)(app);
|
|
90
|
+
exports.httpServer = httpServer;
|
|
91
|
+
const io = new socket_io_1.Server(httpServer, {
|
|
92
|
+
cors: {
|
|
93
|
+
origin: "*",
|
|
94
|
+
methods: ["GET", "POST"],
|
|
95
|
+
},
|
|
96
|
+
transports: ['websocket', 'polling']
|
|
97
|
+
});
|
|
98
|
+
exports.io = io;
|
|
99
|
+
(0, runcmddev_1.default)(io);
|
|
100
|
+
(0, interactiveTerminal_1.interactiveTerminalSocket)(io);
|
|
101
|
+
//=============================================================================
|
|
102
|
+
httpServer.listen(port, () => {
|
|
103
|
+
console.log(`Server running at http://localhost:${port}`);
|
|
104
|
+
(0, open_1.default)(`http://localhost:${port}`);
|
|
105
|
+
});
|
|
106
|
+
exports.default = app;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const express_1 = require("express");
|
|
4
|
+
const router = (0, express_1.Router)();
|
|
5
|
+
router.get("/", async (req, res) => {
|
|
6
|
+
console.log('called');
|
|
7
|
+
res.send("Hello World!");
|
|
8
|
+
});
|
|
9
|
+
exports.default = router;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.interactiveTerminalSocket = interactiveTerminalSocket;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const router = (0, express_1.Router)();
|
|
7
|
+
// Keep the router for potential future HTTP endpoints, though we primarily use sockets now
|
|
8
|
+
router.get("/", async (req, res) => {
|
|
9
|
+
res.send("Interactive Terminal Route");
|
|
10
|
+
});
|
|
11
|
+
exports.default = router;
|
|
12
|
+
// Map to store active terminal processes for each socket
|
|
13
|
+
const activeTerminals = new Map();
|
|
14
|
+
function interactiveTerminalSocket(io) {
|
|
15
|
+
io.on('connection', (socket) => {
|
|
16
|
+
socket.on('terminal:start', (data) => {
|
|
17
|
+
const { path, command } = data;
|
|
18
|
+
if (activeTerminals.has(socket.id)) {
|
|
19
|
+
const oldChild = activeTerminals.get(socket.id);
|
|
20
|
+
if (oldChild) {
|
|
21
|
+
// Remove all listeners to prevent 'exit' or 'data' events from the old process
|
|
22
|
+
// interfering with the new one or sending confusing logs.
|
|
23
|
+
oldChild.removeAllListeners();
|
|
24
|
+
oldChild.stdout?.removeAllListeners();
|
|
25
|
+
oldChild.stderr?.removeAllListeners();
|
|
26
|
+
oldChild.kill();
|
|
27
|
+
activeTerminals.delete(socket.id);
|
|
28
|
+
socket.emit('terminal:log', '\r\n\x1b[33m[System] Previous command terminated.\x1b[0m\r\n');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
const env = { ...process.env };
|
|
33
|
+
delete env.CI;
|
|
34
|
+
env.TERM = 'xterm-256color';
|
|
35
|
+
env.FORCE_COLOR = '1';
|
|
36
|
+
// Use PROMPT_COMMAND to force the PS1 prompt.
|
|
37
|
+
// This overrides any PS1 set by .bashrc which is sourced by the interactive shell.
|
|
38
|
+
// Format: [PATH] /current/path (newline) $
|
|
39
|
+
// \033[34m = Blue, \033[32m = Green, \033[0m = Reset
|
|
40
|
+
// We use \033 (octal) which is standard for bash PS1.
|
|
41
|
+
env.PROMPT_COMMAND = 'export PS1="\\[\\033[34m\\][PATH] \\[\\033[32m\\]\\w\\[\\033[0m\\]\\n$ ";';
|
|
42
|
+
let child;
|
|
43
|
+
if (process.platform === 'win32') {
|
|
44
|
+
// Windows does not support the python pty module.
|
|
45
|
+
// We fall back to standard spawn with shell: true.
|
|
46
|
+
// Interactivity might be limited (arrow keys might not work in some apps),
|
|
47
|
+
// but standard input/output should function.
|
|
48
|
+
socket.emit('terminal:log', '\x1b[33m[System] Windows detected. Running in compatible mode (limited interactivity).\x1b[0m\r\n');
|
|
49
|
+
const baseCMD = command.split(" ")[0];
|
|
50
|
+
const args = command.split(" ").slice(1);
|
|
51
|
+
child = (0, child_process_1.spawn)(baseCMD, args, {
|
|
52
|
+
cwd: path,
|
|
53
|
+
env: env,
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Linux/Mac: Use Python PTY bridge for full interactivity
|
|
60
|
+
env.CMD = command;
|
|
61
|
+
const pythonScript = `
|
|
62
|
+
import pty, sys, os
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
cmd = os.environ.get('CMD')
|
|
66
|
+
if not cmd:
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
69
|
+
# pty.spawn(argv) executes argv and connects stdin/stdout to pty
|
|
70
|
+
status = pty.spawn(['/bin/bash', '-c', 'stty cols 80 rows 24; ' + cmd])
|
|
71
|
+
|
|
72
|
+
if os.WIFEXITED(status):
|
|
73
|
+
sys.exit(os.WEXITSTATUS(status))
|
|
74
|
+
else:
|
|
75
|
+
sys.exit(1)
|
|
76
|
+
except ImportError:
|
|
77
|
+
sys.exit(127) # Return special code if pty module missing (unlikely on unix)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
`;
|
|
81
|
+
child = (0, child_process_1.spawn)('python3', ['-u', '-c', pythonScript], {
|
|
82
|
+
cwd: path,
|
|
83
|
+
env: env,
|
|
84
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
activeTerminals.set(socket.id, child);
|
|
88
|
+
child.stdout?.on('data', (chunk) => {
|
|
89
|
+
socket.emit('terminal:log', chunk.toString());
|
|
90
|
+
});
|
|
91
|
+
child.stderr?.on('data', (chunk) => {
|
|
92
|
+
socket.emit('terminal:log', chunk.toString());
|
|
93
|
+
});
|
|
94
|
+
child.on('error', (err) => {
|
|
95
|
+
if (err.code === 'ENOENT' && process.platform !== 'win32') {
|
|
96
|
+
socket.emit('terminal:error', '\r\n\x1b[31mError: Python3 is required for interactive mode on Linux/Mac but was not found.\x1b[0m');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
socket.emit('terminal:error', `Failed to start command: ${err.message}`);
|
|
100
|
+
}
|
|
101
|
+
cleanup(socket.id);
|
|
102
|
+
});
|
|
103
|
+
child.on('exit', (code) => {
|
|
104
|
+
// Check for our custom "Python missing pty" code or general failure logic
|
|
105
|
+
if (code === 127 && process.platform !== 'win32') {
|
|
106
|
+
socket.emit('terminal:error', '\r\n\x1b[31mError: Python PTY module issue.\x1b[0m');
|
|
107
|
+
}
|
|
108
|
+
else if (code !== 0) {
|
|
109
|
+
socket.emit('terminal:error', `\r\nProcess exited with code ${code}`);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
//socket.emit('terminal:log', `\r\nProcess finished successfully.`);
|
|
113
|
+
}
|
|
114
|
+
socket.emit('terminal:exit', code);
|
|
115
|
+
cleanup(socket.id);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
socket.emit('terminal:error', `Error handling command: ${error.message}`);
|
|
120
|
+
cleanup(socket.id);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
socket.on('terminal:input', (input) => {
|
|
124
|
+
const child = activeTerminals.get(socket.id);
|
|
125
|
+
if (child && child.stdin) {
|
|
126
|
+
// With PTY bridge, we send raw input. PTY handles newlines/signals.
|
|
127
|
+
child.stdin.write(input);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
socket.on('disconnect', () => {
|
|
131
|
+
const child = activeTerminals.get(socket.id);
|
|
132
|
+
if (child) {
|
|
133
|
+
// Remove listeners so we don't try to emit 'exit' or 'error' to a disconnected socket
|
|
134
|
+
child.removeAllListeners();
|
|
135
|
+
child.stdout?.removeAllListeners();
|
|
136
|
+
child.stderr?.removeAllListeners();
|
|
137
|
+
child.kill(); // Kill the process if client disconnects
|
|
138
|
+
activeTerminals.delete(socket.id);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
function cleanup(socketId) {
|
|
142
|
+
activeTerminals.delete(socketId);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = require("express");
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const router = (0, express_1.Router)();
|
|
10
|
+
const START_DIR = process.cwd();
|
|
11
|
+
// Find the monorepo root (where package.json with "workspaces" is defined)
|
|
12
|
+
// If not found, default to START_DIR
|
|
13
|
+
const findRoot = async (dir) => {
|
|
14
|
+
const pkgPath = path_1.default.join(dir, 'package.json');
|
|
15
|
+
if (await fs_extra_1.default.pathExists(pkgPath)) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = await fs_extra_1.default.readJSON(pkgPath);
|
|
18
|
+
// If "workspaces" is defined, we assume this is the root
|
|
19
|
+
if (pkg.workspaces) {
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// ignore
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const parent = path_1.default.dirname(dir);
|
|
28
|
+
if (parent === dir)
|
|
29
|
+
return START_DIR;
|
|
30
|
+
return findRoot(parent);
|
|
31
|
+
};
|
|
32
|
+
router.get("/", async (req, res) => {
|
|
33
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
34
|
+
try {
|
|
35
|
+
const rootPath = await findRoot(START_DIR);
|
|
36
|
+
const pkgPath = path_1.default.join(rootPath, 'package.json');
|
|
37
|
+
let workspaceDirs = [];
|
|
38
|
+
let foundWorkspaces = false;
|
|
39
|
+
// 1. Try to read "workspaces" from package.json
|
|
40
|
+
if (await fs_extra_1.default.pathExists(pkgPath)) {
|
|
41
|
+
const pkg = await fs_extra_1.default.readJSON(pkgPath);
|
|
42
|
+
let globs = [];
|
|
43
|
+
if (pkg.workspaces) {
|
|
44
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
45
|
+
globs = pkg.workspaces;
|
|
46
|
+
}
|
|
47
|
+
else if (pkg.workspaces.packages && Array.isArray(pkg.workspaces.packages)) {
|
|
48
|
+
globs = pkg.workspaces.packages;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (globs.length > 0) {
|
|
52
|
+
foundWorkspaces = true;
|
|
53
|
+
const uniqueDirs = new Set();
|
|
54
|
+
for (const pattern of globs) {
|
|
55
|
+
// Pattern examples: "apps/*", "packages/*", "libs/my-lib"
|
|
56
|
+
// We want the top-level folder, e.g. "apps", "packages", "libs"
|
|
57
|
+
const parts = pattern.split('/');
|
|
58
|
+
if (parts.length > 0) {
|
|
59
|
+
const topLevel = parts[0];
|
|
60
|
+
// filter out if the pattern was just "*" (unlikely but possible) or empty
|
|
61
|
+
if (topLevel && topLevel !== '*') {
|
|
62
|
+
uniqueDirs.add(topLevel);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const dirName of uniqueDirs) {
|
|
67
|
+
const fullPath = path_1.default.join(rootPath, dirName);
|
|
68
|
+
if (await fs_extra_1.default.pathExists(fullPath)) {
|
|
69
|
+
workspaceDirs.push({
|
|
70
|
+
label: dirName,
|
|
71
|
+
path: fullPath
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// 2. If no workspaces defined, fallback to scanning root
|
|
78
|
+
if (!foundWorkspaces) {
|
|
79
|
+
const items = await fs_extra_1.default.readdir(rootPath, { withFileTypes: true });
|
|
80
|
+
workspaceDirs = items
|
|
81
|
+
.filter(item => item.isDirectory())
|
|
82
|
+
.filter(item => {
|
|
83
|
+
const name = item.name;
|
|
84
|
+
// Exclude node_modules
|
|
85
|
+
if (name === 'node_modules')
|
|
86
|
+
return false;
|
|
87
|
+
// Exclude hidden fs (start with .)
|
|
88
|
+
if (name.startsWith('.'))
|
|
89
|
+
return false;
|
|
90
|
+
// Exclude folders starting with _
|
|
91
|
+
if (name.startsWith('_'))
|
|
92
|
+
return false;
|
|
93
|
+
return true;
|
|
94
|
+
})
|
|
95
|
+
.map(item => ({
|
|
96
|
+
label: item.name,
|
|
97
|
+
path: path_1.default.join(rootPath, item.name)
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
return res.json(workspaceDirs);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.error("Error listing workspaces:", e);
|
|
104
|
+
res.status(500).json({ error: e.message });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
exports.default = router;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = require("express");
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const router = (0, express_1.Router)();
|
|
10
|
+
router.post("/", async (req, res) => {
|
|
11
|
+
res.header("Access-Control-Allow-Origin", "*");
|
|
12
|
+
try {
|
|
13
|
+
const reqBody = req.body;
|
|
14
|
+
const targetPath = reqBody.path;
|
|
15
|
+
if (!targetPath) {
|
|
16
|
+
return res.status(400).json({ error: "Path is required" });
|
|
17
|
+
}
|
|
18
|
+
await fs_extra_1.default.ensureDir(targetPath);
|
|
19
|
+
const packageJson = {
|
|
20
|
+
name: reqBody.name || path_1.default.basename(targetPath),
|
|
21
|
+
version: "1.0.0",
|
|
22
|
+
description: reqBody.description || "",
|
|
23
|
+
fontawesomeIcon: reqBody.fontawesomeIcon || "",
|
|
24
|
+
scripts: {
|
|
25
|
+
dev: reqBody.devCommand || "",
|
|
26
|
+
start: reqBody.startCommand || undefined,
|
|
27
|
+
stop: reqBody.stopCommand || undefined,
|
|
28
|
+
build: reqBody.buildCommand || undefined,
|
|
29
|
+
clean: reqBody.cleanCommand || undefined,
|
|
30
|
+
lint: reqBody.lintCommand || undefined,
|
|
31
|
+
test: reqBody.testCommand || undefined
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
Object.keys(packageJson.scripts).forEach(key => packageJson.scripts[key] === undefined && delete packageJson.scripts[key]);
|
|
35
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(targetPath, "package.json"), packageJson, { spaces: 2 });
|
|
36
|
+
res.json({ message: "Workspace created successfully", path: targetPath });
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
console.error("Error creating workspace:", e);
|
|
40
|
+
res.status(500).json({ error: e.message });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
exports.default = router;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ROOT = void 0;
|
|
7
|
+
exports.findMonorepoRoot = findMonorepoRoot;
|
|
8
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const express_1 = require("express");
|
|
11
|
+
const START_DIR = process.cwd();
|
|
12
|
+
function findMonorepoRoot(startDir) {
|
|
13
|
+
let dir = startDir;
|
|
14
|
+
while (dir !== path_1.default.dirname(dir)) {
|
|
15
|
+
const pkgPath = path_1.default.join(dir, "package.json");
|
|
16
|
+
if (fs_extra_1.default.existsSync(pkgPath)) {
|
|
17
|
+
try {
|
|
18
|
+
const pkg = fs_extra_1.default.readJsonSync(pkgPath);
|
|
19
|
+
if (pkg.workspaces) {
|
|
20
|
+
return dir;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
// Ignore errors
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
dir = path_1.default.dirname(dir);
|
|
28
|
+
}
|
|
29
|
+
return startDir;
|
|
30
|
+
}
|
|
31
|
+
exports.ROOT = findMonorepoRoot(START_DIR);
|
|
32
|
+
const route = (0, express_1.Router)();
|
|
33
|
+
route.get("/", async (req, res) => {
|
|
34
|
+
res.json({ path: exports.ROOT });
|
|
35
|
+
});
|
|
36
|
+
exports.default = route;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.sockets = exports.activeProcesses = void 0;
|
|
7
|
+
exports.default = runCmdDevSocket;
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
exports.activeProcesses = new Map();
|
|
11
|
+
exports.sockets = new Map();
|
|
12
|
+
function runCmdDevSocket(io) {
|
|
13
|
+
io.on('connection', (socket) => {
|
|
14
|
+
socket.on('run', (data) => {
|
|
15
|
+
exports.sockets.set(data.workspace.name, socket);
|
|
16
|
+
try {
|
|
17
|
+
handleOnRun(socket, data);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
socket.emit('error', {
|
|
21
|
+
message: error
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async function handleOnRun(socket, data) {
|
|
28
|
+
const { workspace, runas } = data;
|
|
29
|
+
if (exports.activeProcesses.has(workspace.name))
|
|
30
|
+
return socket.emit("log", "Attached to already running process...");
|
|
31
|
+
const commandToRun = runas === "dev" ? workspace.devCommand : workspace.startCommand;
|
|
32
|
+
if (!commandToRun)
|
|
33
|
+
throw new Error("No command to run");
|
|
34
|
+
const baseCMD = commandToRun.split(" ")[0];
|
|
35
|
+
const args = commandToRun.split(" ").slice(1);
|
|
36
|
+
socket.emit('log', chalk_1.default.green(`${data.workspace.path}: ${commandToRun}`));
|
|
37
|
+
const child = (0, child_process_1.spawn)(baseCMD, args, {
|
|
38
|
+
cwd: workspace.path,
|
|
39
|
+
env: {
|
|
40
|
+
...process.env,
|
|
41
|
+
TERM: 'dumb',
|
|
42
|
+
FORCE_COLOR: '1',
|
|
43
|
+
},
|
|
44
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
45
|
+
shell: true,
|
|
46
|
+
detached: process.platform !== 'win32'
|
|
47
|
+
});
|
|
48
|
+
exports.activeProcesses.set(workspace.name, child);
|
|
49
|
+
child.on('error', (error) => {
|
|
50
|
+
socket.emit('error', error.message);
|
|
51
|
+
});
|
|
52
|
+
child.stdout.on('data', (data) => {
|
|
53
|
+
socket.emit('log', data.toString());
|
|
54
|
+
});
|
|
55
|
+
child.stderr.on('data', (data) => {
|
|
56
|
+
socket.emit('error', data.toString());
|
|
57
|
+
});
|
|
58
|
+
child.on('exit', (code) => {
|
|
59
|
+
socket.emit('exit', `Process exited with code ${code}`);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const express_1 = require("express");
|
|
7
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const rootPath_1 = require("./rootPath");
|
|
11
|
+
const router = (0, express_1.Router)();
|
|
12
|
+
router.get("/", async (req, res) => {
|
|
13
|
+
try {
|
|
14
|
+
const packageJsonPath = path_1.default.join(rootPath_1.ROOT, "package.json");
|
|
15
|
+
const turboJsonPath = path_1.default.join(rootPath_1.ROOT, "turbo.json");
|
|
16
|
+
// 1. Read package.json
|
|
17
|
+
if (!fs_extra_1.default.existsSync(packageJsonPath)) {
|
|
18
|
+
res.status(400).json({ error: "package.json not found in root" });
|
|
19
|
+
return; // Stop execution
|
|
20
|
+
}
|
|
21
|
+
const pkg = fs_extra_1.default.readJsonSync(packageJsonPath);
|
|
22
|
+
let pkgChanged = false;
|
|
23
|
+
// 2. Check Workspaces
|
|
24
|
+
if (!pkg.workspaces) {
|
|
25
|
+
pkg.workspaces = ["apps/*", "packages/*"];
|
|
26
|
+
pkgChanged = true;
|
|
27
|
+
}
|
|
28
|
+
// 3. Save package.json if workspaces changed (before install)
|
|
29
|
+
if (pkgChanged) {
|
|
30
|
+
fs_extra_1.default.writeJsonSync(packageJsonPath, pkg, { spaces: 2 });
|
|
31
|
+
}
|
|
32
|
+
// 4. Create directories
|
|
33
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(rootPath_1.ROOT, 'apps'));
|
|
34
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(rootPath_1.ROOT, 'packages'));
|
|
35
|
+
// 4.1 Create monorepotime.json if not exists
|
|
36
|
+
const monorepoTimePath = path_1.default.join(rootPath_1.ROOT, "monorepotime.json");
|
|
37
|
+
if (!fs_extra_1.default.existsSync(monorepoTimePath)) {
|
|
38
|
+
const defaultMonorepoTime = [
|
|
39
|
+
{
|
|
40
|
+
"category": "Internal CRUD Test",
|
|
41
|
+
"devurl": "http://localhost:3200",
|
|
42
|
+
"produrl": "http://superhost:3200",
|
|
43
|
+
"items": [
|
|
44
|
+
{
|
|
45
|
+
"label": "Ping the Tool Server",
|
|
46
|
+
"route": "/pingme",
|
|
47
|
+
"methods": "GET",
|
|
48
|
+
"description": "Ping the tool server to check if it is running.",
|
|
49
|
+
"sampleInput": "{}",
|
|
50
|
+
"suggested": [],
|
|
51
|
+
"expectedOutcome": "# You should see the word \"pong\" as a message \n\n{\n \"message\": \"pong\"\n}",
|
|
52
|
+
"availableFor": "public"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"label": "Check Post",
|
|
56
|
+
"route": "/pingpost",
|
|
57
|
+
"methods": "POST",
|
|
58
|
+
"description": "Send a POST request to check if it sending correctly",
|
|
59
|
+
"sampleInput": "{\n \"data\": \"test\",\n \"message\": \"test\"\n}",
|
|
60
|
+
"suggested": [
|
|
61
|
+
{
|
|
62
|
+
"name": "Customer Data",
|
|
63
|
+
"urlparams": "",
|
|
64
|
+
"content": "{\n \"name\": \"Demo Customer\",\n \"email\": \"CusRaRa@customer.com\",\n \"phone1\": \"123456789\",\n \"phone2\": \"987654321\",\n \"city\": \"randomw1\",\n \"state\": \"ultra state\",\n \"zip\": \"12345\",\n \"country\": \"mega country\",\n \"icon\": \"test icon\",\n \"gender\": \"female\",\n \"delivery_notes\": \"Make sure that it is packed correctly\"\n}"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"expectedOutcome": "# Note \nYou should see the mirror of your inputs",
|
|
68
|
+
"availableFor": "public"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"label": "Check Stream",
|
|
72
|
+
"route": "/pingstream",
|
|
73
|
+
"methods": "STREAM",
|
|
74
|
+
"description": "Send a stream request to check if it sending correctly",
|
|
75
|
+
"sampleInput": "{ }",
|
|
76
|
+
"suggested": [
|
|
77
|
+
{
|
|
78
|
+
"name": "I Wandered Lonely as a Cloud",
|
|
79
|
+
"urlparams": "?poem=I%20Wandered%20Lonely%20as%20a%20Cloud",
|
|
80
|
+
"content": "{}"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "The Sun Has Long Been Set",
|
|
84
|
+
"urlparams": "?poem=The%20Sun%20Has%20Long%20Been%20Set",
|
|
85
|
+
"content": "{}"
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
"expectedOutcome": "# Note \nYou should see the stream of words",
|
|
89
|
+
"availableFor": "public"
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
fs_extra_1.default.writeJsonSync(monorepoTimePath, defaultMonorepoTime, { spaces: 4 });
|
|
95
|
+
}
|
|
96
|
+
// 5. Create turbo.json if not exists
|
|
97
|
+
if (!fs_extra_1.default.existsSync(turboJsonPath) || !pkg.devDependencies?.turbo) {
|
|
98
|
+
if (!fs_extra_1.default.existsSync(turboJsonPath)) {
|
|
99
|
+
const defaultTurbo = {
|
|
100
|
+
"$schema": "https://turbo.build/schema.json",
|
|
101
|
+
"pipeline": {
|
|
102
|
+
"build": {
|
|
103
|
+
"outputs": ["dist/**", ".next/**"]
|
|
104
|
+
},
|
|
105
|
+
"lint": {}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
fs_extra_1.default.writeJsonSync(turboJsonPath, defaultTurbo, { spaces: 2 });
|
|
109
|
+
}
|
|
110
|
+
// 6. Commands
|
|
111
|
+
// Check if turbo is in devDependencies
|
|
112
|
+
const hasTurbo = pkg.devDependencies && pkg.devDependencies.turbo;
|
|
113
|
+
if (!hasTurbo) {
|
|
114
|
+
// installing turbo will install deps
|
|
115
|
+
await runCommand("npm install turbo -D", rootPath_1.ROOT);
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// just install to ensure workspaces are linked
|
|
119
|
+
await runCommand("npm install", rootPath_1.ROOT);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
// If everything existed, user requested "then npm install" implies we might still want to ensure state?
|
|
124
|
+
// But the prompt says: "if so [missing turbo.json or turbo dep], then ... then npm install".
|
|
125
|
+
// It also says "if the root package.json has no 'workspaces'... then npm install".
|
|
126
|
+
// To be safe, let's run npm install if we changed workspaces OR if we entered the 'turbo missing' block.
|
|
127
|
+
if (pkgChanged) {
|
|
128
|
+
await runCommand("npm install", rootPath_1.ROOT);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
res.json({ success: true, message: "Scaffolding complete" });
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error("Scaffolding error:", error);
|
|
135
|
+
res.status(500).json({
|
|
136
|
+
error: "Failed to scaffold",
|
|
137
|
+
details: error instanceof Error ? error.message : String(error)
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
function runCommand(cmd, cwd) {
|
|
142
|
+
console.log(`Running: ${cmd} in ${cwd}`);
|
|
143
|
+
return new Promise((resolve, reject) => {
|
|
144
|
+
(0, child_process_1.exec)(cmd, { cwd }, (error, stdout, stderr) => {
|
|
145
|
+
if (error) {
|
|
146
|
+
console.error("Exec error:", stderr);
|
|
147
|
+
reject(error);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
console.log(stdout); // Log output
|
|
151
|
+
resolve();
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
exports.default = router;
|