projax 3.3.39 → 3.3.51
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/README.md +73 -0
- package/dist/__tests__/port-scanner.test.js +7 -17
- package/dist/__tests__/script-runner.test.js +7 -17
- package/dist/api/__tests__/database.test.js +7 -17
- package/dist/api/__tests__/database.test.js.map +1 -1
- package/dist/api/__tests__/routes.test.js +7 -17
- package/dist/api/__tests__/routes.test.js.map +1 -1
- package/dist/api/__tests__/scanner.test.js +7 -17
- package/dist/api/__tests__/scanner.test.js.map +1 -1
- package/dist/api/database.d.ts +20 -1
- package/dist/api/database.d.ts.map +1 -1
- package/dist/api/database.js +192 -21
- package/dist/api/database.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +17 -19
- package/dist/api/index.js.map +1 -1
- package/dist/api/migrate.js +2 -1
- package/dist/api/migrate.js.map +1 -1
- package/dist/api/package.json +3 -2
- package/dist/api/routes/backup.d.ts +3 -0
- package/dist/api/routes/backup.d.ts.map +1 -0
- package/dist/api/routes/backup.js +51 -0
- package/dist/api/routes/backup.js.map +1 -0
- package/dist/api/routes/index.d.ts.map +1 -1
- package/dist/api/routes/index.js +6 -0
- package/dist/api/routes/index.js.map +1 -1
- package/dist/api/routes/mcp.d.ts +3 -0
- package/dist/api/routes/mcp.d.ts.map +1 -0
- package/dist/api/routes/mcp.js +147 -0
- package/dist/api/routes/mcp.js.map +1 -0
- package/dist/api/routes/projects.d.ts.map +1 -1
- package/dist/api/routes/projects.js +27 -17
- package/dist/api/routes/projects.js.map +1 -1
- package/dist/api/routes/settings.d.ts.map +1 -1
- package/dist/api/routes/settings.js +119 -11
- package/dist/api/routes/settings.js.map +1 -1
- package/dist/api/routes/workspaces.d.ts +3 -0
- package/dist/api/routes/workspaces.d.ts.map +1 -0
- package/dist/api/routes/workspaces.js +504 -0
- package/dist/api/routes/workspaces.js.map +1 -0
- package/dist/api/services/scanner.js +10 -19
- package/dist/api/services/scanner.js.map +1 -1
- package/dist/api/services/test-parser.js +3 -2
- package/dist/api/services/test-parser.js.map +1 -1
- package/dist/api/types.d.ts +31 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/core/__tests__/database.test.js +7 -17
- package/dist/core/__tests__/detector.test.js +7 -17
- package/dist/core/__tests__/index.test.js +7 -17
- package/dist/core/__tests__/scanner.test.js +7 -17
- package/dist/core/__tests__/settings.test.js +7 -17
- package/dist/core/backup-utils.d.ts +17 -0
- package/dist/core/backup-utils.js +157 -0
- package/dist/core/database.d.ts +1 -0
- package/dist/core/database.js +9 -18
- package/dist/core/detector.js +11 -21
- package/dist/core/git-utils.d.ts +12 -0
- package/dist/core/git-utils.js +87 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +8 -5
- package/dist/core/scanner.js +3 -2
- package/dist/core/settings.d.ts +85 -0
- package/dist/core/settings.js +306 -9
- package/dist/core/workspace-utils.d.ts +37 -0
- package/dist/core/workspace-utils.js +143 -0
- package/dist/core-bridge.js +7 -17
- package/dist/electron/core/__tests__/database.test.js +7 -17
- package/dist/electron/core/__tests__/detector.test.js +7 -17
- package/dist/electron/core/__tests__/index.test.js +7 -17
- package/dist/electron/core/__tests__/scanner.test.js +7 -17
- package/dist/electron/core/__tests__/settings.test.js +7 -17
- package/dist/electron/core/backup-utils.d.ts +17 -0
- package/dist/electron/core/backup-utils.js +157 -0
- package/dist/electron/core/database.d.ts +1 -0
- package/dist/electron/core/database.js +9 -18
- package/dist/electron/core/detector.js +11 -21
- package/dist/electron/core/git-utils.d.ts +12 -0
- package/dist/electron/core/git-utils.js +87 -0
- package/dist/electron/core/index.d.ts +3 -0
- package/dist/electron/core/index.js +8 -5
- package/dist/electron/core/scanner.js +3 -2
- package/dist/electron/core/settings.d.ts +85 -0
- package/dist/electron/core/settings.js +306 -9
- package/dist/electron/core/workspace-utils.d.ts +37 -0
- package/dist/electron/core/workspace-utils.js +143 -0
- package/dist/electron/core.js +7 -17
- package/dist/electron/main.js +663 -33
- package/dist/electron/port-extractor.js +9 -18
- package/dist/electron/port-scanner.js +11 -20
- package/dist/electron/port-utils.js +5 -4
- package/dist/electron/preload.d.ts +27 -2
- package/dist/electron/preload.js +18 -2
- package/dist/electron/renderer/assets/index-B-etDnj2.js +64 -0
- package/dist/electron/renderer/assets/index-Bx18Cyic.js +64 -0
- package/dist/electron/renderer/assets/index-C8f5yNYe.js +64 -0
- package/dist/electron/renderer/assets/index-CIZ3Wl6c.css +1 -0
- package/dist/electron/renderer/assets/index-CJbsU9y8.css +1 -0
- package/dist/electron/renderer/assets/index-CopVNRnR.js +64 -0
- package/dist/electron/renderer/assets/index-DUvcepWm.js +64 -0
- package/dist/electron/renderer/assets/index-DWe2TQFv.css +1 -0
- package/dist/electron/renderer/assets/index-DZzB20Xf.css +1 -0
- package/dist/electron/renderer/assets/index-DknLdADV.js +63 -0
- package/dist/electron/renderer/assets/index-DocuD8Lk.js +64 -0
- package/dist/electron/renderer/assets/index-DyU-xfd8.css +1 -0
- package/dist/electron/renderer/assets/index-GwC-JVUy.css +1 -0
- package/dist/electron/renderer/assets/index-fehviker.js +63 -0
- package/dist/electron/renderer/index.html +2 -2
- package/dist/electron/script-runner.js +20 -29
- package/dist/index.js +395 -21
- package/dist/port-extractor.js +9 -18
- package/dist/port-scanner.js +11 -20
- package/dist/port-utils.js +5 -4
- package/dist/script-runner.js +20 -29
- package/dist/test-parser.js +3 -2
- package/package.json +3 -2
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' http://localhost:* ws://localhost:*;" />
|
|
7
7
|
<title>projax</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-B-etDnj2.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="./assets/index-DyU-xfd8.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -15,36 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.detectProjectType =
|
|
37
|
-
exports.getProjectScripts = getProjectScripts;
|
|
38
|
-
exports.runScript = runScript;
|
|
39
|
-
exports.loadProcesses = loadProcesses;
|
|
40
|
-
exports.removeProcess = removeProcess;
|
|
41
|
-
exports.getProjectProcesses = getProjectProcesses;
|
|
42
|
-
exports.getRunningProcesses = getRunningProcesses;
|
|
43
|
-
exports.getRunningProcessesClean = getRunningProcessesClean;
|
|
44
|
-
exports.stopScript = stopScript;
|
|
45
|
-
exports.stopScriptByPort = stopScriptByPort;
|
|
46
|
-
exports.stopProjectProcesses = stopProjectProcesses;
|
|
47
|
-
exports.runScriptInBackground = runScriptInBackground;
|
|
26
|
+
exports.runScriptInBackground = exports.stopProjectProcesses = exports.stopScriptByPort = exports.stopScript = exports.getRunningProcessesClean = exports.getRunningProcesses = exports.getProjectProcesses = exports.removeProcess = exports.loadProcesses = exports.runScript = exports.getProjectScripts = exports.detectProjectType = void 0;
|
|
48
27
|
const fs = __importStar(require("fs"));
|
|
49
28
|
const path = __importStar(require("path"));
|
|
50
29
|
const os = __importStar(require("os"));
|
|
@@ -72,6 +51,7 @@ function detectProjectType(projectPath) {
|
|
|
72
51
|
}
|
|
73
52
|
return 'unknown';
|
|
74
53
|
}
|
|
54
|
+
exports.detectProjectType = detectProjectType;
|
|
75
55
|
/**
|
|
76
56
|
* Parse scripts from package.json (Node.js)
|
|
77
57
|
*/
|
|
@@ -272,6 +252,7 @@ function getProjectScripts(projectPath) {
|
|
|
272
252
|
scripts,
|
|
273
253
|
};
|
|
274
254
|
}
|
|
255
|
+
exports.getProjectScripts = getProjectScripts;
|
|
275
256
|
/**
|
|
276
257
|
* Handle port conflict - prompt user or auto-kill based on force flag
|
|
277
258
|
*/
|
|
@@ -476,6 +457,7 @@ function runScript(projectPath, scriptName, args = [], force = false) {
|
|
|
476
457
|
});
|
|
477
458
|
});
|
|
478
459
|
}
|
|
460
|
+
exports.runScript = runScript;
|
|
479
461
|
/**
|
|
480
462
|
* Get the path to the processes file
|
|
481
463
|
*/
|
|
@@ -502,6 +484,7 @@ function loadProcesses() {
|
|
|
502
484
|
return [];
|
|
503
485
|
}
|
|
504
486
|
}
|
|
487
|
+
exports.loadProcesses = loadProcesses;
|
|
505
488
|
/**
|
|
506
489
|
* Save running processes to disk
|
|
507
490
|
*/
|
|
@@ -525,6 +508,7 @@ function removeProcess(pid) {
|
|
|
525
508
|
const filtered = processes.filter(p => p.pid !== pid);
|
|
526
509
|
saveProcesses(filtered);
|
|
527
510
|
}
|
|
511
|
+
exports.removeProcess = removeProcess;
|
|
528
512
|
/**
|
|
529
513
|
* Get all running processes for a project
|
|
530
514
|
*/
|
|
@@ -532,6 +516,7 @@ function getProjectProcesses(projectPath) {
|
|
|
532
516
|
const processes = loadProcesses();
|
|
533
517
|
return processes.filter(p => p.projectPath === projectPath);
|
|
534
518
|
}
|
|
519
|
+
exports.getProjectProcesses = getProjectProcesses;
|
|
535
520
|
/**
|
|
536
521
|
* Check if a process is still running
|
|
537
522
|
*/
|
|
@@ -581,6 +566,7 @@ async function cleanupDeadProcesses() {
|
|
|
581
566
|
function getRunningProcesses() {
|
|
582
567
|
return loadProcesses();
|
|
583
568
|
}
|
|
569
|
+
exports.getRunningProcesses = getRunningProcesses;
|
|
584
570
|
/**
|
|
585
571
|
* Get all running processes with cleanup (async version)
|
|
586
572
|
*/
|
|
@@ -588,6 +574,7 @@ async function getRunningProcessesClean() {
|
|
|
588
574
|
await cleanupDeadProcesses();
|
|
589
575
|
return loadProcesses();
|
|
590
576
|
}
|
|
577
|
+
exports.getRunningProcessesClean = getRunningProcessesClean;
|
|
591
578
|
/**
|
|
592
579
|
* Extract URLs from text output
|
|
593
580
|
*/
|
|
@@ -693,6 +680,7 @@ async function stopScript(pid) {
|
|
|
693
680
|
return false;
|
|
694
681
|
}
|
|
695
682
|
}
|
|
683
|
+
exports.stopScript = stopScript;
|
|
696
684
|
/**
|
|
697
685
|
* Stop a script by port (finds process using port and kills it)
|
|
698
686
|
*/
|
|
@@ -719,6 +707,7 @@ async function stopScriptByPort(port) {
|
|
|
719
707
|
return false;
|
|
720
708
|
}
|
|
721
709
|
}
|
|
710
|
+
exports.stopScriptByPort = stopScriptByPort;
|
|
722
711
|
/**
|
|
723
712
|
* Stop all processes for a project
|
|
724
713
|
*/
|
|
@@ -732,6 +721,7 @@ async function stopProjectProcesses(projectPath) {
|
|
|
732
721
|
}
|
|
733
722
|
return stopped;
|
|
734
723
|
}
|
|
724
|
+
exports.stopProjectProcesses = stopProjectProcesses;
|
|
735
725
|
/**
|
|
736
726
|
* Execute a script in the background (minimal logging)
|
|
737
727
|
*/
|
|
@@ -945,6 +935,7 @@ function runScriptInBackground(projectPath, projectName, scriptName, args = [],
|
|
|
945
935
|
resolve(child.pid);
|
|
946
936
|
});
|
|
947
937
|
}
|
|
938
|
+
exports.runScriptInBackground = runScriptInBackground;
|
|
948
939
|
/**
|
|
949
940
|
* Check log file for test output and parse results
|
|
950
941
|
*/
|
package/dist/index.js
CHANGED
|
@@ -16,23 +16,13 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
16
16
|
}) : function(o, v) {
|
|
17
17
|
o["default"] = v;
|
|
18
18
|
});
|
|
19
|
-
var __importStar = (this && this.__importStar) ||
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
})();
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
36
26
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
27
|
const commander_1 = require("commander");
|
|
38
28
|
const path = __importStar(require("path"));
|
|
@@ -708,10 +698,23 @@ program
|
|
|
708
698
|
else {
|
|
709
699
|
// Table format
|
|
710
700
|
console.log(`\nTracked Projects (${projects.length}):\n`);
|
|
701
|
+
// Fetch git branches for all projects
|
|
702
|
+
const { getCurrentBranch } = await Promise.resolve().then(() => __importStar(require('../../core/src/git-utils')));
|
|
703
|
+
const branchMap = new Map();
|
|
704
|
+
for (const project of projects) {
|
|
705
|
+
try {
|
|
706
|
+
const branch = getCurrentBranch(project.path);
|
|
707
|
+
branchMap.set(project.id, branch);
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
branchMap.set(project.id, null);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
711
713
|
// Calculate column widths
|
|
712
714
|
const idWidth = Math.max(3, projects.length.toString().length);
|
|
713
715
|
const nameWidth = Math.max(4, ...projects.map(p => p.name.length));
|
|
714
|
-
const pathWidth = Math.max(4, Math.min(
|
|
716
|
+
const pathWidth = Math.max(4, Math.min(35, ...projects.map(p => p.path.length)));
|
|
717
|
+
const branchWidth = 15;
|
|
715
718
|
const portsWidth = 12;
|
|
716
719
|
const testsWidth = 6;
|
|
717
720
|
const scannedWidth = 20;
|
|
@@ -720,6 +723,7 @@ program
|
|
|
720
723
|
'ID'.padEnd(idWidth),
|
|
721
724
|
'Name'.padEnd(nameWidth),
|
|
722
725
|
'Path'.padEnd(pathWidth),
|
|
726
|
+
'Branch'.padEnd(branchWidth),
|
|
723
727
|
'Ports'.padEnd(portsWidth),
|
|
724
728
|
'Tests'.padEnd(testsWidth),
|
|
725
729
|
'Last Scanned'.padEnd(scannedWidth),
|
|
@@ -736,13 +740,16 @@ program
|
|
|
736
740
|
const portStr = ports.length > 0
|
|
737
741
|
? ports.map(p => p.port).sort((a, b) => a - b).join(', ')
|
|
738
742
|
: 'N/A';
|
|
739
|
-
const pathDisplay = project.path.length >
|
|
740
|
-
? '...' + project.path.slice(-
|
|
743
|
+
const pathDisplay = project.path.length > 35
|
|
744
|
+
? '...' + project.path.slice(-32)
|
|
741
745
|
: project.path;
|
|
746
|
+
const branch = branchMap.get(project.id) || 'N/A';
|
|
747
|
+
const branchDisplay = branch.length > 15 ? branch.slice(0, 12) + '...' : branch;
|
|
742
748
|
const row = [
|
|
743
749
|
project.id.toString().padEnd(idWidth),
|
|
744
750
|
project.name.padEnd(nameWidth),
|
|
745
751
|
pathDisplay.padEnd(pathWidth),
|
|
752
|
+
branchDisplay.padEnd(branchWidth),
|
|
746
753
|
portStr.padEnd(portsWidth),
|
|
747
754
|
tests.length.toString().padEnd(testsWidth),
|
|
748
755
|
lastScanned.padEnd(scannedWidth),
|
|
@@ -1860,11 +1867,378 @@ program
|
|
|
1860
1867
|
process.exit(1);
|
|
1861
1868
|
}
|
|
1862
1869
|
});
|
|
1870
|
+
// Workspace commands
|
|
1871
|
+
const workspaceCmd = program
|
|
1872
|
+
.command('workspace')
|
|
1873
|
+
.alias('ws')
|
|
1874
|
+
.description('Manage workspaces');
|
|
1875
|
+
workspaceCmd
|
|
1876
|
+
.command('list')
|
|
1877
|
+
.description('List all workspaces')
|
|
1878
|
+
.action(async () => {
|
|
1879
|
+
try {
|
|
1880
|
+
await ensureAPIServerRunning(true);
|
|
1881
|
+
const response = await fetch('http://localhost:3001/api/workspaces');
|
|
1882
|
+
if (!response.ok)
|
|
1883
|
+
throw new Error('Failed to fetch workspaces');
|
|
1884
|
+
const workspaces = await response.json();
|
|
1885
|
+
if (workspaces.length === 0) {
|
|
1886
|
+
console.log('No workspaces tracked yet.');
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
console.log(`\nWorkspaces (${workspaces.length}):\n`);
|
|
1890
|
+
workspaces.forEach((ws) => {
|
|
1891
|
+
console.log(`${ws.id}. ${ws.name}`);
|
|
1892
|
+
console.log(` File: ${ws.workspace_file_path}`);
|
|
1893
|
+
if (ws.description)
|
|
1894
|
+
console.log(` Description: ${ws.description}`);
|
|
1895
|
+
console.log('');
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
catch (error) {
|
|
1899
|
+
console.error('Error listing workspaces:', error instanceof Error ? error.message : error);
|
|
1900
|
+
process.exit(1);
|
|
1901
|
+
}
|
|
1902
|
+
});
|
|
1903
|
+
workspaceCmd
|
|
1904
|
+
.command('add')
|
|
1905
|
+
.description('Import workspace from .code-workspace file')
|
|
1906
|
+
.argument('<path>', 'Path to .code-workspace file')
|
|
1907
|
+
.action(async (filePath) => {
|
|
1908
|
+
try {
|
|
1909
|
+
await ensureAPIServerRunning(true);
|
|
1910
|
+
const resolvedPath = path.resolve(filePath);
|
|
1911
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
1912
|
+
console.error(`Error: Workspace file not found: ${resolvedPath}`);
|
|
1913
|
+
process.exit(1);
|
|
1914
|
+
}
|
|
1915
|
+
const response = await fetch('http://localhost:3001/api/workspaces/import', {
|
|
1916
|
+
method: 'POST',
|
|
1917
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1918
|
+
body: JSON.stringify({ workspace_file_path: resolvedPath }),
|
|
1919
|
+
});
|
|
1920
|
+
if (!response.ok) {
|
|
1921
|
+
const error = await response.json();
|
|
1922
|
+
throw new Error(error.error || 'Failed to import workspace');
|
|
1923
|
+
}
|
|
1924
|
+
const workspace = await response.json();
|
|
1925
|
+
console.log(`✓ Imported workspace: ${workspace.name}`);
|
|
1926
|
+
}
|
|
1927
|
+
catch (error) {
|
|
1928
|
+
console.error('Error importing workspace:', error instanceof Error ? error.message : error);
|
|
1929
|
+
process.exit(1);
|
|
1930
|
+
}
|
|
1931
|
+
});
|
|
1932
|
+
workspaceCmd
|
|
1933
|
+
.command('create')
|
|
1934
|
+
.description('Create a new workspace')
|
|
1935
|
+
.argument('<name>', 'Workspace name')
|
|
1936
|
+
.option('-o, --output <path>', 'Output directory for workspace file', process.cwd())
|
|
1937
|
+
.option('-p, --projects <paths>', 'Comma-separated project paths to include')
|
|
1938
|
+
.action(async (name, options) => {
|
|
1939
|
+
try {
|
|
1940
|
+
await ensureAPIServerRunning(true);
|
|
1941
|
+
const outputPath = options.output || process.cwd();
|
|
1942
|
+
const projectPaths = options.projects ? options.projects.split(',').map(p => p.trim()) : [];
|
|
1943
|
+
const response = await fetch('http://localhost:3001/api/workspaces/create', {
|
|
1944
|
+
method: 'POST',
|
|
1945
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1946
|
+
body: JSON.stringify({
|
|
1947
|
+
name,
|
|
1948
|
+
output_path: outputPath,
|
|
1949
|
+
projects: projectPaths,
|
|
1950
|
+
}),
|
|
1951
|
+
});
|
|
1952
|
+
if (!response.ok) {
|
|
1953
|
+
const error = await response.json();
|
|
1954
|
+
throw new Error(error.error || 'Failed to create workspace');
|
|
1955
|
+
}
|
|
1956
|
+
const workspace = await response.json();
|
|
1957
|
+
console.log(`✓ Created workspace: ${workspace.name}`);
|
|
1958
|
+
console.log(` File: ${workspace.workspace_file_path}`);
|
|
1959
|
+
}
|
|
1960
|
+
catch (error) {
|
|
1961
|
+
console.error('Error creating workspace:', error instanceof Error ? error.message : error);
|
|
1962
|
+
process.exit(1);
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1965
|
+
workspaceCmd
|
|
1966
|
+
.command('remove')
|
|
1967
|
+
.description('Remove a workspace')
|
|
1968
|
+
.argument('<id|name>', 'Workspace ID or name')
|
|
1969
|
+
.option('-f, --force', 'Skip confirmation')
|
|
1970
|
+
.action(async (identifier, options) => {
|
|
1971
|
+
try {
|
|
1972
|
+
await ensureAPIServerRunning(true);
|
|
1973
|
+
const response = await fetch('http://localhost:3001/api/workspaces');
|
|
1974
|
+
if (!response.ok)
|
|
1975
|
+
throw new Error('Failed to fetch workspaces');
|
|
1976
|
+
const workspaces = await response.json();
|
|
1977
|
+
const workspace = workspaces.find((w) => w.id.toString() === identifier || w.name === identifier);
|
|
1978
|
+
if (!workspace) {
|
|
1979
|
+
console.error(`Error: Workspace not found: ${identifier}`);
|
|
1980
|
+
process.exit(1);
|
|
1981
|
+
}
|
|
1982
|
+
if (!options.force) {
|
|
1983
|
+
const inquirer = (await Promise.resolve().then(() => __importStar(require('inquirer')))).default;
|
|
1984
|
+
const answer = await inquirer.prompt([{
|
|
1985
|
+
type: 'confirm',
|
|
1986
|
+
name: 'confirm',
|
|
1987
|
+
message: `Remove workspace "${workspace.name}"?`,
|
|
1988
|
+
default: false,
|
|
1989
|
+
}]);
|
|
1990
|
+
if (!answer.confirm) {
|
|
1991
|
+
console.log('Cancelled.');
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
}
|
|
1995
|
+
const deleteResponse = await fetch(`http://localhost:3001/api/workspaces/${workspace.id}`, {
|
|
1996
|
+
method: 'DELETE',
|
|
1997
|
+
});
|
|
1998
|
+
if (!deleteResponse.ok)
|
|
1999
|
+
throw new Error('Failed to remove workspace');
|
|
2000
|
+
console.log(`✓ Removed workspace: ${workspace.name}`);
|
|
2001
|
+
}
|
|
2002
|
+
catch (error) {
|
|
2003
|
+
console.error('Error removing workspace:', error instanceof Error ? error.message : error);
|
|
2004
|
+
process.exit(1);
|
|
2005
|
+
}
|
|
2006
|
+
});
|
|
2007
|
+
workspaceCmd
|
|
2008
|
+
.command('open')
|
|
2009
|
+
.description('Open workspace in editor')
|
|
2010
|
+
.argument('<id|name>', 'Workspace ID or name')
|
|
2011
|
+
.action(async (identifier) => {
|
|
2012
|
+
try {
|
|
2013
|
+
await ensureAPIServerRunning(true);
|
|
2014
|
+
const response = await fetch('http://localhost:3001/api/workspaces');
|
|
2015
|
+
if (!response.ok)
|
|
2016
|
+
throw new Error('Failed to fetch workspaces');
|
|
2017
|
+
const workspaces = await response.json();
|
|
2018
|
+
const workspace = workspaces.find((w) => w.id.toString() === identifier || w.name === identifier);
|
|
2019
|
+
if (!workspace) {
|
|
2020
|
+
console.error(`Error: Workspace not found: ${identifier}`);
|
|
2021
|
+
process.exit(1);
|
|
2022
|
+
}
|
|
2023
|
+
if (!fs.existsSync(workspace.workspace_file_path)) {
|
|
2024
|
+
console.error(`Error: Workspace file not found: ${workspace.workspace_file_path}`);
|
|
2025
|
+
process.exit(1);
|
|
2026
|
+
}
|
|
2027
|
+
const { spawn } = require('child_process');
|
|
2028
|
+
const corePath = path.join(__dirname, '..', '..', 'core', 'dist', 'settings');
|
|
2029
|
+
const localCorePath = path.join(__dirname, '..', '..', '..', 'core', 'dist', 'settings');
|
|
2030
|
+
let settings;
|
|
2031
|
+
try {
|
|
2032
|
+
settings = require(corePath);
|
|
2033
|
+
}
|
|
2034
|
+
catch {
|
|
2035
|
+
try {
|
|
2036
|
+
settings = require(localCorePath);
|
|
2037
|
+
}
|
|
2038
|
+
catch {
|
|
2039
|
+
console.error('Error: Could not load settings');
|
|
2040
|
+
process.exit(1);
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
const editorSettings = settings.getEditorSettings();
|
|
2044
|
+
let command;
|
|
2045
|
+
if (editorSettings.type === 'custom' && editorSettings.customPath) {
|
|
2046
|
+
command = editorSettings.customPath;
|
|
2047
|
+
}
|
|
2048
|
+
else {
|
|
2049
|
+
command = editorSettings.type === 'cursor' ? 'cursor' : editorSettings.type === 'windsurf' ? 'windsurf' : 'code';
|
|
2050
|
+
}
|
|
2051
|
+
spawn(command, [workspace.workspace_file_path], {
|
|
2052
|
+
detached: true,
|
|
2053
|
+
stdio: 'ignore',
|
|
2054
|
+
}).unref();
|
|
2055
|
+
console.log(`✓ Opening workspace "${workspace.name}" in ${editorSettings.type || 'editor'}...`);
|
|
2056
|
+
}
|
|
2057
|
+
catch (error) {
|
|
2058
|
+
console.error('Error opening workspace:', error instanceof Error ? error.message : error);
|
|
2059
|
+
process.exit(1);
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
// Backup commands
|
|
2063
|
+
program
|
|
2064
|
+
.command('backup')
|
|
2065
|
+
.description('Create a backup of PROJAX data')
|
|
2066
|
+
.argument('[path]', 'Output directory (default: current directory)')
|
|
2067
|
+
.action(async (outputPath) => {
|
|
2068
|
+
try {
|
|
2069
|
+
await ensureAPIServerRunning(true);
|
|
2070
|
+
const targetPath = outputPath ? path.resolve(outputPath) : process.cwd();
|
|
2071
|
+
const response = await fetch('http://localhost:3001/api/backup/create', {
|
|
2072
|
+
method: 'POST',
|
|
2073
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2074
|
+
body: JSON.stringify({ output_path: targetPath }),
|
|
2075
|
+
});
|
|
2076
|
+
if (!response.ok) {
|
|
2077
|
+
const error = await response.json();
|
|
2078
|
+
throw new Error(error.error || 'Failed to create backup');
|
|
2079
|
+
}
|
|
2080
|
+
const result = await response.json();
|
|
2081
|
+
console.log(`✓ Backup created: ${result.backup_path}`);
|
|
2082
|
+
}
|
|
2083
|
+
catch (error) {
|
|
2084
|
+
console.error('Error creating backup:', error instanceof Error ? error.message : error);
|
|
2085
|
+
process.exit(1);
|
|
2086
|
+
}
|
|
2087
|
+
});
|
|
2088
|
+
program
|
|
2089
|
+
.command('restore')
|
|
2090
|
+
.description('Restore PROJAX data from backup')
|
|
2091
|
+
.argument('<file>', 'Path to .pbz backup file')
|
|
2092
|
+
.option('-f, --force', 'Skip confirmation')
|
|
2093
|
+
.action(async (backupPath, options) => {
|
|
2094
|
+
try {
|
|
2095
|
+
await ensureAPIServerRunning(true);
|
|
2096
|
+
const resolvedPath = path.resolve(backupPath);
|
|
2097
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
2098
|
+
console.error(`Error: Backup file not found: ${resolvedPath}`);
|
|
2099
|
+
process.exit(1);
|
|
2100
|
+
}
|
|
2101
|
+
if (!options.force) {
|
|
2102
|
+
const inquirer = (await Promise.resolve().then(() => __importStar(require('inquirer')))).default;
|
|
2103
|
+
const answer = await inquirer.prompt([{
|
|
2104
|
+
type: 'confirm',
|
|
2105
|
+
name: 'confirm',
|
|
2106
|
+
message: 'This will overwrite your current PROJAX data. Continue?',
|
|
2107
|
+
default: false,
|
|
2108
|
+
}]);
|
|
2109
|
+
if (!answer.confirm) {
|
|
2110
|
+
console.log('Cancelled.');
|
|
2111
|
+
return;
|
|
2112
|
+
}
|
|
2113
|
+
}
|
|
2114
|
+
const response = await fetch('http://localhost:3001/api/backup/restore', {
|
|
2115
|
+
method: 'POST',
|
|
2116
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2117
|
+
body: JSON.stringify({ backup_path: resolvedPath }),
|
|
2118
|
+
});
|
|
2119
|
+
if (!response.ok) {
|
|
2120
|
+
const error = await response.json();
|
|
2121
|
+
throw new Error(error.error || 'Failed to restore backup');
|
|
2122
|
+
}
|
|
2123
|
+
console.log('✓ Backup restored successfully');
|
|
2124
|
+
}
|
|
2125
|
+
catch (error) {
|
|
2126
|
+
console.error('Error restoring backup:', error instanceof Error ? error.message : error);
|
|
2127
|
+
process.exit(1);
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
// MCP Server command
|
|
2131
|
+
program
|
|
2132
|
+
.command('mcp')
|
|
2133
|
+
.description('Start Projax MCP (Model Context Protocol) server for AI tools')
|
|
2134
|
+
.action(async () => {
|
|
2135
|
+
try {
|
|
2136
|
+
// Check if MCP server package is available
|
|
2137
|
+
const mcpServerPath = path.join(__dirname, '..', '..', 'mcp-server', 'dist', 'index.js');
|
|
2138
|
+
const isLocalDev = fs.existsSync(mcpServerPath);
|
|
2139
|
+
if (!isLocalDev) {
|
|
2140
|
+
// Try to find in node_modules (for global install)
|
|
2141
|
+
try {
|
|
2142
|
+
require.resolve('@projax/mcp-server');
|
|
2143
|
+
const { spawn } = require('child_process');
|
|
2144
|
+
const mcpServer = spawn('projax-mcp', [], {
|
|
2145
|
+
stdio: 'inherit',
|
|
2146
|
+
env: process.env,
|
|
2147
|
+
});
|
|
2148
|
+
mcpServer.on('exit', (code) => {
|
|
2149
|
+
process.exit(code || 0);
|
|
2150
|
+
});
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
catch (error) {
|
|
2154
|
+
console.error('Error: MCP server not found.');
|
|
2155
|
+
console.error('\nThe MCP server is not built or installed.');
|
|
2156
|
+
console.error('Please run: npm run build:mcp-server');
|
|
2157
|
+
process.exit(1);
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
// Local development mode
|
|
2161
|
+
const { spawn } = require('child_process');
|
|
2162
|
+
const mcpServer = spawn('node', [mcpServerPath], {
|
|
2163
|
+
stdio: 'inherit',
|
|
2164
|
+
env: process.env,
|
|
2165
|
+
});
|
|
2166
|
+
mcpServer.on('exit', (code) => {
|
|
2167
|
+
process.exit(code || 0);
|
|
2168
|
+
});
|
|
2169
|
+
}
|
|
2170
|
+
catch (error) {
|
|
2171
|
+
console.error('Error starting MCP server:', error instanceof Error ? error.message : error);
|
|
2172
|
+
process.exit(1);
|
|
2173
|
+
}
|
|
2174
|
+
});
|
|
2175
|
+
// MCP Config command
|
|
2176
|
+
program
|
|
2177
|
+
.command('mcp-config')
|
|
2178
|
+
.description('Display MCP server configuration for Cursor or VS Code')
|
|
2179
|
+
.option('--cursor', 'Show Cursor-specific configuration')
|
|
2180
|
+
.option('--vscode', 'Show VS Code-specific configuration')
|
|
2181
|
+
.action(async (options) => {
|
|
2182
|
+
try {
|
|
2183
|
+
// Find prx command path
|
|
2184
|
+
let prxPath = 'prx';
|
|
2185
|
+
try {
|
|
2186
|
+
prxPath = (0, child_process_1.execSync)('which prx', { encoding: 'utf-8' }).trim();
|
|
2187
|
+
}
|
|
2188
|
+
catch {
|
|
2189
|
+
// If which fails, use 'prx' as default
|
|
2190
|
+
}
|
|
2191
|
+
const cursorConfig = {
|
|
2192
|
+
mcpServers: {
|
|
2193
|
+
projax: {
|
|
2194
|
+
command: prxPath,
|
|
2195
|
+
args: ['mcp'],
|
|
2196
|
+
},
|
|
2197
|
+
},
|
|
2198
|
+
};
|
|
2199
|
+
const vscodeConfig = {
|
|
2200
|
+
"mcp.servers": {
|
|
2201
|
+
projax: {
|
|
2202
|
+
command: prxPath,
|
|
2203
|
+
args: ['mcp'],
|
|
2204
|
+
},
|
|
2205
|
+
},
|
|
2206
|
+
};
|
|
2207
|
+
console.log('\n╔═══════════════════════════════════════════════════════╗');
|
|
2208
|
+
console.log('║ Projax MCP Server Configuration ║');
|
|
2209
|
+
console.log('╚═══════════════════════════════════════════════════════╝\n');
|
|
2210
|
+
if (options.vscode) {
|
|
2211
|
+
console.log('VS Code Configuration (settings.json):');
|
|
2212
|
+
console.log(JSON.stringify(vscodeConfig, null, 2));
|
|
2213
|
+
}
|
|
2214
|
+
else if (options.cursor) {
|
|
2215
|
+
console.log('Cursor Configuration (~/.cursor/mcp.json):');
|
|
2216
|
+
console.log(JSON.stringify(cursorConfig, null, 2));
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
// Show both
|
|
2220
|
+
console.log('Cursor Configuration (~/.cursor/mcp.json):');
|
|
2221
|
+
console.log(JSON.stringify(cursorConfig, null, 2));
|
|
2222
|
+
console.log('\nVS Code Configuration (settings.json):');
|
|
2223
|
+
console.log(JSON.stringify(vscodeConfig, null, 2));
|
|
2224
|
+
}
|
|
2225
|
+
console.log('\n📝 Instructions:');
|
|
2226
|
+
console.log('1. Copy the configuration above');
|
|
2227
|
+
console.log('2. For Cursor: Paste into ~/.cursor/mcp.json (or use Cursor Settings > MCP)');
|
|
2228
|
+
console.log('3. For VS Code: Paste into settings.json (or use MCP extension)');
|
|
2229
|
+
console.log('4. Restart your editor');
|
|
2230
|
+
console.log('\n💡 Test with: Ask your AI assistant about your current project context');
|
|
2231
|
+
}
|
|
2232
|
+
catch (error) {
|
|
2233
|
+
console.error('Error displaying configuration:', error instanceof Error ? error.message : error);
|
|
2234
|
+
process.exit(1);
|
|
2235
|
+
}
|
|
2236
|
+
});
|
|
1863
2237
|
// Handle script execution before parsing
|
|
1864
2238
|
// Check if first argument is not a known command
|
|
1865
2239
|
(async () => {
|
|
1866
2240
|
const args = process.argv.slice(2);
|
|
1867
|
-
const knownCommands = ['prxi', 'i', 'add', 'list', 'scan', 'remove', 'rn', 'rename', 'cd', 'pwd', 'run', 'ps', 'stop', 'web', 'desktop', 'ui', 'scripts', 'scan-ports', 'api', 'docs', 'vscode-extension', 'extension', 'ext', 'desc', 'description', 'tags', 'open', 'files', 'urls', '--help', '-h', '--version', '-V'];
|
|
2241
|
+
const knownCommands = ['prxi', 'i', 'add', 'list', 'scan', 'remove', 'rn', 'rename', 'cd', 'pwd', 'run', 'ps', 'stop', 'web', 'desktop', 'ui', 'scripts', 'scan-ports', 'api', 'docs', 'vscode-extension', 'extension', 'ext', 'desc', 'description', 'tags', 'open', 'files', 'urls', 'workspace', 'ws', 'backup', 'restore', 'mcp', 'mcp-config', '--help', '-h', '--version', '-V'];
|
|
1868
2242
|
// If we have at least 1 argument and first is not a known command, treat as project identifier
|
|
1869
2243
|
if (args.length >= 1 && !knownCommands.includes(args[0])) {
|
|
1870
2244
|
const projectIdentifier = args[0];
|
package/dist/port-extractor.js
CHANGED
|
@@ -15,25 +15,15 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.extractPortsFromProject =
|
|
26
|
+
exports.extractPortsFromProject = void 0;
|
|
37
27
|
const fs = __importStar(require("fs"));
|
|
38
28
|
const path = __importStar(require("path"));
|
|
39
29
|
/**
|
|
@@ -66,6 +56,7 @@ async function extractPortsFromProject(projectPath) {
|
|
|
66
56
|
const uniquePorts = Array.from(new Map(ports.map(p => [`${p.port}-${p.script || ''}`, p])).values());
|
|
67
57
|
return uniquePorts;
|
|
68
58
|
}
|
|
59
|
+
exports.extractPortsFromProject = extractPortsFromProject;
|
|
69
60
|
/**
|
|
70
61
|
* Extract ports from package.json scripts
|
|
71
62
|
*/
|