projax 1.0.2 → 1.3.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/api/database.d.ts +34 -0
- package/dist/api/database.d.ts.map +1 -0
- package/dist/api/database.js +318 -0
- package/dist/api/database.js.map +1 -0
- package/dist/api/index.d.ts +5 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +130 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/migrate.d.ts +2 -0
- package/dist/api/migrate.d.ts.map +1 -0
- package/dist/api/migrate.js +158 -0
- package/dist/api/migrate.js.map +1 -0
- package/dist/api/package.json +27 -0
- package/dist/api/routes/index.d.ts +3 -0
- package/dist/api/routes/index.d.ts.map +1 -0
- package/dist/api/routes/index.js +17 -0
- package/dist/api/routes/index.js.map +1 -0
- package/dist/api/routes/projects.d.ts +3 -0
- package/dist/api/routes/projects.d.ts.map +1 -0
- package/dist/api/routes/projects.js +198 -0
- package/dist/api/routes/projects.js.map +1 -0
- package/dist/api/routes/settings.d.ts +3 -0
- package/dist/api/routes/settings.d.ts.map +1 -0
- package/dist/api/routes/settings.js +33 -0
- package/dist/api/routes/settings.js.map +1 -0
- package/dist/api/services/scanner.d.ts +9 -0
- package/dist/api/services/scanner.d.ts.map +1 -0
- package/dist/api/services/scanner.js +172 -0
- package/dist/api/services/scanner.js.map +1 -0
- package/dist/api/types.d.ts +48 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +3 -0
- package/dist/api/types.js.map +1 -0
- package/dist/core/database.d.ts +15 -5
- package/dist/core/database.js +136 -208
- package/dist/core/detector.d.ts +5 -0
- package/dist/core/detector.js +135 -0
- package/dist/core/index.d.ts +1 -2
- package/dist/core/index.js +2 -4
- package/dist/core/scanner.js +2 -105
- package/dist/core/settings.d.ts +50 -0
- package/dist/core/settings.js +102 -0
- package/dist/electron/main.js +86 -28
- package/dist/electron/port-scanner.js +4 -4
- package/dist/electron/preload.d.ts +1 -1
- package/dist/electron/renderer/assets/index-7KIJIiIM.js +42 -0
- package/dist/electron/renderer/assets/{index-CdMlFqhB.js → index-BRymlmJj.js} +10 -10
- package/dist/electron/renderer/assets/{index-DohAcUCg.css → index-ezVMxZrM.css} +1 -1
- package/dist/electron/renderer/index.html +2 -2
- package/dist/electron/script-runner.js +4 -4
- package/dist/index.js +240 -75
- package/dist/port-scanner.js +4 -4
- package/dist/script-runner.js +4 -4
- package/package.json +13 -11
- package/dist/electron/renderer/assets/index-BZ6USRnW.js +0 -42
- package/dist/electron/renderer/assets/index-DNtxfrZe.js +0 -42
- package/dist/electron/renderer/assets/index-khk3K-qG.css +0 -1
package/dist/index.js
CHANGED
|
@@ -37,14 +37,133 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
37
37
|
const commander_1 = require("commander");
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
39
|
const fs = __importStar(require("fs"));
|
|
40
|
-
const
|
|
40
|
+
const http = __importStar(require("http"));
|
|
41
|
+
const projax_core_1 = require("projax-core");
|
|
41
42
|
const script_runner_1 = require("./script-runner");
|
|
42
43
|
const port_scanner_1 = require("./port-scanner");
|
|
43
44
|
// Read version from package.json
|
|
44
45
|
const packageJson = require('../package.json');
|
|
46
|
+
// Function to check API status
|
|
47
|
+
async function checkAPIStatus() {
|
|
48
|
+
const dataDir = path.join(require('os').homedir(), '.projax');
|
|
49
|
+
const portFile = path.join(dataDir, 'api-port.txt');
|
|
50
|
+
let port = null;
|
|
51
|
+
if (fs.existsSync(portFile)) {
|
|
52
|
+
try {
|
|
53
|
+
const portStr = fs.readFileSync(portFile, 'utf-8').trim();
|
|
54
|
+
port = parseInt(portStr, 10) || null;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// Ignore
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!port) {
|
|
61
|
+
// Try common ports
|
|
62
|
+
const ports = [3001, 3002, 3003, 3004, 3005];
|
|
63
|
+
for (const p of ports) {
|
|
64
|
+
try {
|
|
65
|
+
const result = await new Promise((resolve) => {
|
|
66
|
+
const req = http.get(`http://localhost:${p}/health`, (res) => {
|
|
67
|
+
resolve(res.statusCode === 200);
|
|
68
|
+
});
|
|
69
|
+
req.on('error', () => resolve(false));
|
|
70
|
+
req.setTimeout(500, () => {
|
|
71
|
+
req.destroy();
|
|
72
|
+
resolve(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
if (result) {
|
|
76
|
+
port = p;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Continue
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (port) {
|
|
86
|
+
try {
|
|
87
|
+
const result = await new Promise((resolve) => {
|
|
88
|
+
const req = http.get(`http://localhost:${port}/health`, (res) => {
|
|
89
|
+
resolve(res.statusCode === 200);
|
|
90
|
+
});
|
|
91
|
+
req.on('error', () => resolve(false));
|
|
92
|
+
req.setTimeout(500, () => {
|
|
93
|
+
req.destroy();
|
|
94
|
+
resolve(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
return { running: result, port };
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return { running: false, port };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { running: false, port: null };
|
|
104
|
+
}
|
|
105
|
+
// Function to start the API server
|
|
106
|
+
async function startAPIServer(silent = false) {
|
|
107
|
+
const { spawn } = require('child_process');
|
|
108
|
+
const apiPath = path.join(__dirname, '..', '..', 'api', 'dist', 'index.js');
|
|
109
|
+
if (!fs.existsSync(apiPath)) {
|
|
110
|
+
if (!silent) {
|
|
111
|
+
console.error('Error: API server not found. Please build it first: npm run build --workspace=packages/api');
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
if (!silent) {
|
|
116
|
+
console.log('Starting API server...');
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
spawn('node', [apiPath], {
|
|
120
|
+
detached: true,
|
|
121
|
+
stdio: 'ignore',
|
|
122
|
+
}).unref();
|
|
123
|
+
if (!silent) {
|
|
124
|
+
console.log('✓ API server started');
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (!silent) {
|
|
130
|
+
console.error('Error starting API server:', error instanceof Error ? error.message : error);
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Function to ensure API server is running (auto-start if needed)
|
|
136
|
+
async function ensureAPIServerRunning(silent = true) {
|
|
137
|
+
const apiStatus = await checkAPIStatus();
|
|
138
|
+
if (apiStatus.running) {
|
|
139
|
+
// API is already running, nothing to do
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
// API is not running, start it
|
|
143
|
+
if (!silent) {
|
|
144
|
+
console.log('Starting API server...');
|
|
145
|
+
}
|
|
146
|
+
const started = await startAPIServer(silent);
|
|
147
|
+
if (!started) {
|
|
148
|
+
// Failed to start, but don't throw - let the command continue
|
|
149
|
+
// The error message was already shown if not silent
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// Wait a bit for the API server to start up
|
|
153
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
154
|
+
// Verify it's running
|
|
155
|
+
const verifyStatus = await checkAPIStatus();
|
|
156
|
+
if (!verifyStatus.running && !silent) {
|
|
157
|
+
console.warn('⚠️ API server may not have started successfully. Check logs if needed.');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
45
160
|
// ASCII logo for projax - using a clearer style that shows all 6 letters
|
|
46
161
|
function displayLogo() {
|
|
47
162
|
return `
|
|
163
|
+
PROJAX ${packageJson.version}
|
|
164
|
+
|
|
165
|
+
`;
|
|
166
|
+
return `
|
|
48
167
|
╔═══════════════════════════════════════════════════════╗
|
|
49
168
|
║ ║
|
|
50
169
|
║ ██████╗ ██████╗ ██████╗ ██╗ ██╗ █████╗ ██╗ ║
|
|
@@ -56,6 +175,8 @@ function displayLogo() {
|
|
|
56
175
|
║ ║
|
|
57
176
|
║ Version ${packageJson.version} ║
|
|
58
177
|
║ ║
|
|
178
|
+
║ Use "prx api" to check API server status ║
|
|
179
|
+
║ ║
|
|
59
180
|
╚═══════════════════════════════════════════════════════╝
|
|
60
181
|
`;
|
|
61
182
|
}
|
|
@@ -107,7 +228,7 @@ program
|
|
|
107
228
|
console.error(`Error: Path is not a directory: ${resolvedPath}`);
|
|
108
229
|
process.exit(1);
|
|
109
230
|
}
|
|
110
|
-
const db = (0,
|
|
231
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
111
232
|
const existingProject = db.getProjectByPath(resolvedPath);
|
|
112
233
|
if (existingProject) {
|
|
113
234
|
console.log(`Project already exists: ${existingProject.name} (ID: ${existingProject.id})`);
|
|
@@ -152,7 +273,7 @@ program
|
|
|
152
273
|
]);
|
|
153
274
|
if (scanAnswer.scan) {
|
|
154
275
|
console.log('Scanning for tests...');
|
|
155
|
-
const result = (0,
|
|
276
|
+
const result = (0, projax_core_1.scanProject)(project.id);
|
|
156
277
|
console.log(`✓ Found ${result.testsFound} test file(s)`);
|
|
157
278
|
if (result.tests.length > 0) {
|
|
158
279
|
console.log(' Test files:');
|
|
@@ -193,8 +314,8 @@ program
|
|
|
193
314
|
.option('--ports', 'Show detailed port information per script')
|
|
194
315
|
.action(async (options) => {
|
|
195
316
|
try {
|
|
196
|
-
const db = (0,
|
|
197
|
-
const projects = (0,
|
|
317
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
318
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
198
319
|
if (projects.length === 0) {
|
|
199
320
|
console.log('No projects tracked yet. Use "prx add" to add a project.');
|
|
200
321
|
return;
|
|
@@ -301,17 +422,17 @@ program
|
|
|
301
422
|
.argument('[project]', 'Project ID or name to scan (leave empty to scan all)')
|
|
302
423
|
.action(async (projectIdentifier) => {
|
|
303
424
|
try {
|
|
304
|
-
const db = (0,
|
|
425
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
305
426
|
if (projectIdentifier) {
|
|
306
427
|
// Find project by ID or name
|
|
307
|
-
const projects = (0,
|
|
428
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
308
429
|
const project = projects.find((p) => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
|
|
309
430
|
if (!project) {
|
|
310
431
|
console.error(`Error: Project not found: ${projectIdentifier}`);
|
|
311
432
|
process.exit(1);
|
|
312
433
|
}
|
|
313
434
|
console.log(`Scanning project: ${project.name}...`);
|
|
314
|
-
const result = (0,
|
|
435
|
+
const result = (0, projax_core_1.scanProject)(project.id);
|
|
315
436
|
console.log(`✓ Found ${result.testsFound} test file(s)`);
|
|
316
437
|
if (result.tests.length > 0) {
|
|
317
438
|
console.log('\nTest files:');
|
|
@@ -340,7 +461,7 @@ program
|
|
|
340
461
|
else {
|
|
341
462
|
// Scan all projects
|
|
342
463
|
console.log('Scanning all projects...\n');
|
|
343
|
-
const results = (0,
|
|
464
|
+
const results = (0, projax_core_1.scanAllProjects)();
|
|
344
465
|
for (const result of results) {
|
|
345
466
|
console.log(`${result.project.name}: ${result.testsFound} test file(s)`);
|
|
346
467
|
}
|
|
@@ -372,8 +493,8 @@ program
|
|
|
372
493
|
.argument('<newName>', 'New name for the project')
|
|
373
494
|
.action((projectIdentifier, newName) => {
|
|
374
495
|
try {
|
|
375
|
-
const db = (0,
|
|
376
|
-
const projects = (0,
|
|
496
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
497
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
377
498
|
const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
|
|
378
499
|
if (!project) {
|
|
379
500
|
console.error(`Error: Project not found: ${projectIdentifier}`);
|
|
@@ -400,8 +521,8 @@ program
|
|
|
400
521
|
.option('-f, --force', 'Skip confirmation')
|
|
401
522
|
.action(async (projectIdentifier, options) => {
|
|
402
523
|
try {
|
|
403
|
-
const db = (0,
|
|
404
|
-
const projects = (0,
|
|
524
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
525
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
405
526
|
const project = projects.find(p => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
|
|
406
527
|
if (!project) {
|
|
407
528
|
console.error(`Error: Project not found: ${projectIdentifier}`);
|
|
@@ -422,7 +543,7 @@ program
|
|
|
422
543
|
return;
|
|
423
544
|
}
|
|
424
545
|
}
|
|
425
|
-
(0,
|
|
546
|
+
(0, projax_core_1.removeProject)(project.id);
|
|
426
547
|
console.log(`✓ Removed project: ${project.name}`);
|
|
427
548
|
}
|
|
428
549
|
catch (error) {
|
|
@@ -437,7 +558,7 @@ program
|
|
|
437
558
|
.argument('[project]', 'Project ID or name (leave empty for interactive selection)')
|
|
438
559
|
.action(async (projectIdentifier) => {
|
|
439
560
|
try {
|
|
440
|
-
const projects = (0,
|
|
561
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
441
562
|
if (projects.length === 0) {
|
|
442
563
|
console.error('Error: No projects tracked yet. Use "prx add" to add a project.');
|
|
443
564
|
process.exit(1);
|
|
@@ -501,7 +622,7 @@ program
|
|
|
501
622
|
.argument('[project]', 'Project ID or name (leave empty for interactive selection)')
|
|
502
623
|
.action(async (projectIdentifier) => {
|
|
503
624
|
try {
|
|
504
|
-
const projects = (0,
|
|
625
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
505
626
|
if (projects.length === 0) {
|
|
506
627
|
console.error('Error: No projects tracked yet. Use "prx add" to add a project.');
|
|
507
628
|
process.exit(1);
|
|
@@ -551,7 +672,7 @@ program
|
|
|
551
672
|
.argument('[project]', 'Project ID or name (leave empty for interactive selection)')
|
|
552
673
|
.action(async (projectIdentifier) => {
|
|
553
674
|
try {
|
|
554
|
-
const projects = (0,
|
|
675
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
555
676
|
if (projects.length === 0) {
|
|
556
677
|
console.error('Error: No projects tracked yet. Use "prx add" to add a project.');
|
|
557
678
|
process.exit(1);
|
|
@@ -596,55 +717,57 @@ program
|
|
|
596
717
|
process.exit(1);
|
|
597
718
|
}
|
|
598
719
|
});
|
|
599
|
-
// Start
|
|
720
|
+
// Start Desktop UI command
|
|
600
721
|
program
|
|
601
722
|
.command('web')
|
|
602
|
-
.description('Start the
|
|
723
|
+
.description('Start the Desktop web interface')
|
|
603
724
|
.option('--dev', 'Start in development mode (with hot reload)')
|
|
604
725
|
.action(async (options) => {
|
|
605
726
|
try {
|
|
606
|
-
//
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
const
|
|
614
|
-
// Check if
|
|
615
|
-
const
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
727
|
+
// Ensure API server is running before starting Desktop app
|
|
728
|
+
await ensureAPIServerRunning(false);
|
|
729
|
+
// Check for bundled Desktop app first (in dist/desktop when installed globally)
|
|
730
|
+
// Then check for local development (packages/cli/dist -> packages/desktop)
|
|
731
|
+
const bundledDesktopPath = path.join(__dirname, 'desktop');
|
|
732
|
+
const bundledDesktopMain = path.join(bundledDesktopPath, 'main.js');
|
|
733
|
+
const localDesktopPath = path.join(__dirname, '..', '..', 'desktop');
|
|
734
|
+
const localDesktopMain = path.join(localDesktopPath, 'dist', 'main.js');
|
|
735
|
+
// Check if bundled desktop exists (global install)
|
|
736
|
+
const hasBundledDesktop = fs.existsSync(bundledDesktopMain);
|
|
737
|
+
// Check if local desktop exists (development mode)
|
|
738
|
+
const isLocalDev = fs.existsSync(localDesktopPath) && fs.existsSync(path.join(localDesktopPath, 'package.json'));
|
|
739
|
+
let desktopPackagePath;
|
|
740
|
+
let desktopMainPath;
|
|
741
|
+
if (hasBundledDesktop) {
|
|
742
|
+
// Bundled Desktop app (global install)
|
|
743
|
+
desktopPackagePath = bundledDesktopPath;
|
|
744
|
+
desktopMainPath = bundledDesktopMain;
|
|
622
745
|
}
|
|
623
746
|
else if (isLocalDev) {
|
|
624
747
|
// Local development - use relative path
|
|
625
|
-
|
|
626
|
-
|
|
748
|
+
desktopPackagePath = localDesktopPath;
|
|
749
|
+
desktopMainPath = localDesktopMain;
|
|
627
750
|
}
|
|
628
751
|
else {
|
|
629
|
-
console.error('Error:
|
|
630
|
-
console.error('\nThe
|
|
752
|
+
console.error('Error: Desktop app not found.');
|
|
753
|
+
console.error('\nThe Desktop web interface is not available.');
|
|
631
754
|
console.error('This may be a packaging issue. Please report this error.');
|
|
632
755
|
process.exit(1);
|
|
633
756
|
}
|
|
634
757
|
if (options.dev) {
|
|
635
|
-
// Development mode - start Vite dev server and
|
|
758
|
+
// Development mode - start Vite dev server and Desktop app
|
|
636
759
|
if (!isLocalDev) {
|
|
637
760
|
console.error('Error: Development mode is only available in local development.');
|
|
638
|
-
console.error('The
|
|
761
|
+
console.error('The Desktop app must be built for production use.');
|
|
639
762
|
process.exit(1);
|
|
640
763
|
}
|
|
641
|
-
console.log('Starting
|
|
764
|
+
console.log('Starting Desktop app in development mode...');
|
|
642
765
|
console.log('Starting Vite dev server on port 7898...');
|
|
643
766
|
const { spawn } = require('child_process');
|
|
644
767
|
const electron = require('electron');
|
|
645
768
|
// Start Vite dev server in background
|
|
646
769
|
const viteProcess = spawn('npm', ['run', 'dev:renderer'], {
|
|
647
|
-
cwd:
|
|
770
|
+
cwd: desktopPackagePath,
|
|
648
771
|
stdio: 'pipe',
|
|
649
772
|
detached: false,
|
|
650
773
|
});
|
|
@@ -654,8 +777,8 @@ program
|
|
|
654
777
|
// Wait for Vite to be ready
|
|
655
778
|
if (output.includes('Local:') || output.includes('ready')) {
|
|
656
779
|
setTimeout(() => {
|
|
657
|
-
console.log('\nStarting
|
|
658
|
-
spawn(electron, [
|
|
780
|
+
console.log('\nStarting Desktop window...');
|
|
781
|
+
spawn(electron, [desktopMainPath], {
|
|
659
782
|
stdio: 'inherit',
|
|
660
783
|
detached: true,
|
|
661
784
|
env: { ...process.env, NODE_ENV: 'development' },
|
|
@@ -674,44 +797,44 @@ program
|
|
|
674
797
|
return;
|
|
675
798
|
}
|
|
676
799
|
// Production mode - check if built
|
|
677
|
-
if (!fs.existsSync(
|
|
800
|
+
if (!fs.existsSync(desktopMainPath)) {
|
|
678
801
|
if (!isLocalDev) {
|
|
679
|
-
console.error('Error:
|
|
680
|
-
console.error('The @projax/
|
|
802
|
+
console.error('Error: Desktop app is not built.');
|
|
803
|
+
console.error('The @projax/desktop package needs to be built.');
|
|
681
804
|
console.error('Please contact the package maintainer or build it locally.');
|
|
682
805
|
process.exit(1);
|
|
683
806
|
}
|
|
684
|
-
console.log('
|
|
685
|
-
console.log('Building
|
|
807
|
+
console.log('Desktop app not built.');
|
|
808
|
+
console.log('Building Desktop app...');
|
|
686
809
|
const { execSync } = require('child_process');
|
|
687
810
|
try {
|
|
688
|
-
// When in local dev,
|
|
811
|
+
// When in local dev, desktopPackagePath points to packages/desktop
|
|
689
812
|
// So go up two levels to get to project root
|
|
690
|
-
const projectRoot = path.join(
|
|
691
|
-
execSync('npm run build:
|
|
813
|
+
const projectRoot = path.join(desktopPackagePath, '..', '..');
|
|
814
|
+
execSync('npm run build:desktop', {
|
|
692
815
|
cwd: projectRoot,
|
|
693
816
|
stdio: 'inherit'
|
|
694
817
|
});
|
|
695
818
|
}
|
|
696
819
|
catch (error) {
|
|
697
820
|
console.error('\nBuild failed. Try running in dev mode: prx web --dev');
|
|
698
|
-
console.error('Or manually build: npm run build:
|
|
821
|
+
console.error('Or manually build: npm run build:desktop');
|
|
699
822
|
process.exit(1);
|
|
700
823
|
}
|
|
701
824
|
}
|
|
702
825
|
// Check if renderer is built
|
|
703
826
|
let rendererIndex;
|
|
704
|
-
if (
|
|
705
|
-
// Bundled: renderer is in dist/
|
|
706
|
-
rendererIndex = path.join(
|
|
827
|
+
if (hasBundledDesktop) {
|
|
828
|
+
// Bundled: renderer is in dist/desktop/renderer
|
|
829
|
+
rendererIndex = path.join(desktopPackagePath, 'renderer', 'index.html');
|
|
707
830
|
}
|
|
708
831
|
else {
|
|
709
832
|
// Local dev: renderer is in dist/renderer
|
|
710
|
-
rendererIndex = path.join(
|
|
833
|
+
rendererIndex = path.join(desktopPackagePath, 'dist', 'renderer', 'index.html');
|
|
711
834
|
}
|
|
712
835
|
if (!fs.existsSync(rendererIndex)) {
|
|
713
|
-
if (
|
|
714
|
-
console.error('Error: Renderer files not found in bundled
|
|
836
|
+
if (hasBundledDesktop) {
|
|
837
|
+
console.error('Error: Renderer files not found in bundled Desktop app.');
|
|
715
838
|
console.error('This is a packaging issue. Please report this error.');
|
|
716
839
|
process.exit(1);
|
|
717
840
|
}
|
|
@@ -724,9 +847,9 @@ program
|
|
|
724
847
|
// Ensure NODE_ENV is not set to development when using bundled files
|
|
725
848
|
process.env.NODE_ENV = 'production';
|
|
726
849
|
}
|
|
727
|
-
// Automatically rebuild better-sqlite3 for Electron if needed
|
|
850
|
+
// Automatically rebuild better-sqlite3 for Desktop/Electron if needed
|
|
728
851
|
// This ensures it's compiled for Electron's Node.js version
|
|
729
|
-
if (
|
|
852
|
+
if (hasBundledDesktop) {
|
|
730
853
|
try {
|
|
731
854
|
const electronPkg = require('electron/package.json');
|
|
732
855
|
let rebuild;
|
|
@@ -746,7 +869,7 @@ program
|
|
|
746
869
|
const nodeModulesDir = path.dirname(betterSqlite3Dir); // .../node_modules
|
|
747
870
|
// The package root is the directory containing node_modules (i.e., projax package root)
|
|
748
871
|
const packageRoot = path.dirname(nodeModulesDir); // .../projax
|
|
749
|
-
console.log('Ensuring better-sqlite3 is built for Electron...');
|
|
872
|
+
console.log('Ensuring better-sqlite3 is built for Desktop/Electron...');
|
|
750
873
|
try {
|
|
751
874
|
await new Promise((resolve, reject) => {
|
|
752
875
|
rebuild({
|
|
@@ -756,7 +879,7 @@ program
|
|
|
756
879
|
force: true,
|
|
757
880
|
})
|
|
758
881
|
.then(() => {
|
|
759
|
-
console.log('✓ better-sqlite3 ready for Electron');
|
|
882
|
+
console.log('✓ better-sqlite3 ready for Desktop/Electron');
|
|
760
883
|
resolve();
|
|
761
884
|
})
|
|
762
885
|
.catch((err) => {
|
|
@@ -776,24 +899,66 @@ program
|
|
|
776
899
|
}
|
|
777
900
|
}
|
|
778
901
|
catch (checkError) {
|
|
779
|
-
// If we can't check, just continue - the error will show when
|
|
902
|
+
// If we can't check, just continue - the error will show when Desktop app tries to use it
|
|
780
903
|
}
|
|
781
904
|
}
|
|
782
|
-
console.log('Starting
|
|
905
|
+
console.log('Starting Desktop app...');
|
|
783
906
|
const { spawn } = require('child_process');
|
|
784
907
|
const electron = require('electron');
|
|
785
|
-
spawn(electron, [
|
|
908
|
+
spawn(electron, [desktopMainPath], {
|
|
786
909
|
stdio: 'inherit',
|
|
787
910
|
detached: true,
|
|
788
911
|
env: { ...process.env },
|
|
789
912
|
}).unref();
|
|
790
913
|
}
|
|
791
914
|
catch (error) {
|
|
792
|
-
console.error('Error starting
|
|
915
|
+
console.error('Error starting Desktop app:', error instanceof Error ? error.message : error);
|
|
793
916
|
console.log('\nTroubleshooting:');
|
|
794
917
|
console.log('1. Try dev mode: prx web --dev');
|
|
795
|
-
console.log('2. Or build manually: npm run build:
|
|
796
|
-
console.log('3. Or run dev server: cd packages/
|
|
918
|
+
console.log('2. Or build manually: npm run build:desktop');
|
|
919
|
+
console.log('3. Or run dev server: cd packages/desktop && npm run dev');
|
|
920
|
+
process.exit(1);
|
|
921
|
+
}
|
|
922
|
+
});
|
|
923
|
+
// API command - show API info and manage API server
|
|
924
|
+
program
|
|
925
|
+
.command('api')
|
|
926
|
+
.description('Show API server information and status')
|
|
927
|
+
.option('-s, --start', 'Start the API server')
|
|
928
|
+
.option('-k, --kill', 'Stop the API server')
|
|
929
|
+
.action(async (options) => {
|
|
930
|
+
try {
|
|
931
|
+
const apiStatus = await checkAPIStatus();
|
|
932
|
+
if (options.start) {
|
|
933
|
+
const started = await startAPIServer(false);
|
|
934
|
+
if (!started) {
|
|
935
|
+
process.exit(1);
|
|
936
|
+
}
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
if (options.kill) {
|
|
940
|
+
console.log('Stopping API server...');
|
|
941
|
+
// This would require process management - for now just inform user
|
|
942
|
+
console.log('Note: API server process management not yet implemented.');
|
|
943
|
+
console.log('Please stop the API server manually if needed.');
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
// Show status
|
|
947
|
+
console.log('\nAPI Server Status:');
|
|
948
|
+
console.log(` Running: ${apiStatus.running ? 'Yes' : 'No'}`);
|
|
949
|
+
if (apiStatus.port) {
|
|
950
|
+
console.log(` Port: ${apiStatus.port}`);
|
|
951
|
+
console.log(` URL: http://localhost:${apiStatus.port}`);
|
|
952
|
+
console.log(` Health: http://localhost:${apiStatus.port}/health`);
|
|
953
|
+
console.log(` API Base: http://localhost:${apiStatus.port}/api`);
|
|
954
|
+
}
|
|
955
|
+
else {
|
|
956
|
+
console.log(' Port: Not detected');
|
|
957
|
+
}
|
|
958
|
+
console.log('');
|
|
959
|
+
}
|
|
960
|
+
catch (error) {
|
|
961
|
+
console.error('Error checking API status:', error instanceof Error ? error.message : error);
|
|
797
962
|
process.exit(1);
|
|
798
963
|
}
|
|
799
964
|
});
|
|
@@ -805,9 +970,9 @@ program
|
|
|
805
970
|
.action(async (projectIdentifier) => {
|
|
806
971
|
try {
|
|
807
972
|
const { scanProjectPorts, scanAllProjectPorts } = await Promise.resolve().then(() => __importStar(require('./port-scanner')));
|
|
808
|
-
const db = (0,
|
|
973
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
809
974
|
if (projectIdentifier) {
|
|
810
|
-
const projects = (0,
|
|
975
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
811
976
|
const project = projects.find((p) => p.id.toString() === projectIdentifier || p.name === projectIdentifier);
|
|
812
977
|
if (!project) {
|
|
813
978
|
console.error(`Error: Project not found: ${projectIdentifier}`);
|
|
@@ -830,7 +995,7 @@ program
|
|
|
830
995
|
else {
|
|
831
996
|
console.log('Scanning ports for all projects...\n');
|
|
832
997
|
await scanAllProjectPorts();
|
|
833
|
-
const projects = (0,
|
|
998
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
834
999
|
for (const project of projects) {
|
|
835
1000
|
const ports = db.getProjectPorts(project.id);
|
|
836
1001
|
if (ports.length > 0) {
|
|
@@ -850,14 +1015,14 @@ program
|
|
|
850
1015
|
// Check if first argument is not a known command
|
|
851
1016
|
(async () => {
|
|
852
1017
|
const args = process.argv.slice(2);
|
|
853
|
-
const knownCommands = ['add', 'list', 'scan', 'remove', 'rn', 'rename', 'cd', 'pwd', 'web', 'scripts', 'scan-ports', '--help', '-h', '--version', '-V'];
|
|
1018
|
+
const knownCommands = ['add', 'list', 'scan', 'remove', 'rn', 'rename', 'cd', 'pwd', 'web', 'scripts', 'scan-ports', 'api', '--help', '-h', '--version', '-V'];
|
|
854
1019
|
// If we have at least 1 argument and first is not a known command, treat as project identifier
|
|
855
1020
|
if (args.length >= 1 && !knownCommands.includes(args[0])) {
|
|
856
1021
|
const projectIdentifier = args[0];
|
|
857
1022
|
// Check if it's actually a project (not a flag)
|
|
858
1023
|
if (!projectIdentifier.startsWith('-')) {
|
|
859
1024
|
try {
|
|
860
|
-
const projects = (0,
|
|
1025
|
+
const projects = (0, projax_core_1.getAllProjects)();
|
|
861
1026
|
// Try to find project by ID (if identifier is numeric) or by name
|
|
862
1027
|
let project;
|
|
863
1028
|
const numericId = parseInt(projectIdentifier, 10);
|
package/dist/port-scanner.js
CHANGED
|
@@ -36,14 +36,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.scanProjectPorts = scanProjectPorts;
|
|
37
37
|
exports.scanAllProjectPorts = scanAllProjectPorts;
|
|
38
38
|
exports.shouldRescanPorts = shouldRescanPorts;
|
|
39
|
-
const
|
|
39
|
+
const projax_core_1 = require("projax-core");
|
|
40
40
|
const port_extractor_1 = require("./port-extractor");
|
|
41
41
|
const fs = __importStar(require("fs"));
|
|
42
42
|
/**
|
|
43
43
|
* Scan and index ports for a specific project
|
|
44
44
|
*/
|
|
45
45
|
async function scanProjectPorts(projectId) {
|
|
46
|
-
const db = (0,
|
|
46
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
47
47
|
const project = db.getProject(projectId);
|
|
48
48
|
if (!project) {
|
|
49
49
|
throw new Error(`Project with id ${projectId} not found`);
|
|
@@ -64,7 +64,7 @@ async function scanProjectPorts(projectId) {
|
|
|
64
64
|
* Scan ports for all projects
|
|
65
65
|
*/
|
|
66
66
|
async function scanAllProjectPorts() {
|
|
67
|
-
const db = (0,
|
|
67
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
68
68
|
const projects = db.getAllProjects();
|
|
69
69
|
for (const project of projects) {
|
|
70
70
|
try {
|
|
@@ -81,7 +81,7 @@ async function scanAllProjectPorts() {
|
|
|
81
81
|
* Returns true if ports haven't been scanned in the last 24 hours
|
|
82
82
|
*/
|
|
83
83
|
function shouldRescanPorts(projectId) {
|
|
84
|
-
const db = (0,
|
|
84
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
85
85
|
const ports = db.getProjectPorts(projectId);
|
|
86
86
|
if (ports.length === 0) {
|
|
87
87
|
return true; // No ports found, should scan
|
package/dist/script-runner.js
CHANGED
|
@@ -48,7 +48,7 @@ const fs = __importStar(require("fs"));
|
|
|
48
48
|
const path = __importStar(require("path"));
|
|
49
49
|
const os = __importStar(require("os"));
|
|
50
50
|
const child_process_1 = require("child_process");
|
|
51
|
-
const
|
|
51
|
+
const projax_core_1 = require("projax-core");
|
|
52
52
|
const port_utils_1 = require("./port-utils");
|
|
53
53
|
/**
|
|
54
54
|
* Detect the project type based on files in the directory
|
|
@@ -324,7 +324,7 @@ async function handlePortConflict(port, projectName, force) {
|
|
|
324
324
|
* Check ports proactively before script execution
|
|
325
325
|
*/
|
|
326
326
|
async function checkPortsBeforeExecution(projectPath, scriptName, force) {
|
|
327
|
-
const db = (0,
|
|
327
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
328
328
|
const project = db.getProjectByPath(projectPath);
|
|
329
329
|
if (!project)
|
|
330
330
|
return true; // Can't check if project not in DB
|
|
@@ -447,7 +447,7 @@ function runScript(projectPath, scriptName, args = [], force = false) {
|
|
|
447
447
|
const errorOutput = stderrOutput + stdoutOutput;
|
|
448
448
|
const port = (0, port_utils_1.extractPortFromError)(errorOutput);
|
|
449
449
|
if (port) {
|
|
450
|
-
const db = (0,
|
|
450
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
451
451
|
const project = db.getProjectByPath(projectPath);
|
|
452
452
|
const projectName = project?.name || 'project';
|
|
453
453
|
const resolved = await handlePortConflict(port, projectName, force);
|
|
@@ -801,7 +801,7 @@ function runScriptInBackground(projectPath, projectName, scriptName, args = [],
|
|
|
801
801
|
// Also check for URLs from detected ports
|
|
802
802
|
setTimeout(async () => {
|
|
803
803
|
try {
|
|
804
|
-
const db = (0,
|
|
804
|
+
const db = (0, projax_core_1.getDatabaseManager)();
|
|
805
805
|
const project = db.getProjectByPath(projectPath);
|
|
806
806
|
if (project) {
|
|
807
807
|
const ports = db.getProjectPorts(project.id);
|