projax 1.0.1 → 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 +253 -88
- 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/core/database.js
CHANGED
|
@@ -32,274 +32,202 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
exports.getDatabaseManager = getDatabaseManager;
|
|
40
|
-
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
41
37
|
const path = __importStar(require("path"));
|
|
42
38
|
const os = __importStar(require("os"));
|
|
43
39
|
const fs = __importStar(require("fs"));
|
|
40
|
+
const child_process_1 = require("child_process");
|
|
44
41
|
class DatabaseManager {
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
apiBaseUrl;
|
|
43
|
+
defaultPort = 3001;
|
|
47
44
|
constructor() {
|
|
45
|
+
// Read API port from file, or use default
|
|
48
46
|
const dataDir = path.join(os.homedir(), '.projax');
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const newDbPath = path.join(dataDir, 'dashboard.db');
|
|
53
|
-
if (fs.existsSync(oldDataDir) && fs.existsSync(oldDbPath) && !fs.existsSync(newDbPath)) {
|
|
54
|
-
console.log('Migrating data from ~/.vids-dashboard to ~/.projax...');
|
|
47
|
+
const portFile = path.join(dataDir, 'api-port.txt');
|
|
48
|
+
let port = this.defaultPort;
|
|
49
|
+
if (fs.existsSync(portFile)) {
|
|
55
50
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
const portStr = fs.readFileSync(portFile, 'utf-8').trim();
|
|
52
|
+
port = parseInt(portStr, 10) || this.defaultPort;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Use default if file read fails
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.apiBaseUrl = `http://localhost:${port}/api`;
|
|
59
|
+
}
|
|
60
|
+
request(endpoint, options = {}) {
|
|
61
|
+
const url = `${this.apiBaseUrl}${endpoint}`;
|
|
62
|
+
const method = options.method || 'GET';
|
|
63
|
+
const body = options.body;
|
|
64
|
+
try {
|
|
65
|
+
let curlCmd;
|
|
66
|
+
if (method === 'GET') {
|
|
67
|
+
curlCmd = `curl -s -f "${url}"`;
|
|
68
|
+
}
|
|
69
|
+
else if (method === 'DELETE') {
|
|
70
|
+
curlCmd = `curl -s -f -X DELETE "${url}"`;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// POST, PUT, PATCH
|
|
74
|
+
const tempFile = path.join(os.tmpdir(), `prx-${Date.now()}.json`);
|
|
75
|
+
if (body) {
|
|
76
|
+
fs.writeFileSync(tempFile, body);
|
|
77
|
+
}
|
|
78
|
+
curlCmd = `curl -s -f -X ${method} -H "Content-Type: application/json" ${body ? `-d @${tempFile}` : ''} "${url}"`;
|
|
79
|
+
}
|
|
80
|
+
const result = (0, child_process_1.execSync)(curlCmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
81
|
+
// Clean up temp file if created
|
|
82
|
+
if (method !== 'GET' && method !== 'DELETE' && body) {
|
|
83
|
+
const tempFile = path.join(os.tmpdir(), `prx-${Date.now()}.json`);
|
|
84
|
+
try {
|
|
85
|
+
fs.unlinkSync(tempFile);
|
|
66
86
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const newLogsDir = path.join(dataDir, 'logs');
|
|
70
|
-
fs.mkdirSync(newLogsDir, { recursive: true });
|
|
71
|
-
// Copy all log files
|
|
72
|
-
const logFiles = fs.readdirSync(oldLogsDir);
|
|
73
|
-
for (const file of logFiles) {
|
|
74
|
-
const oldLogPath = path.join(oldLogsDir, file);
|
|
75
|
-
const newLogPath = path.join(newLogsDir, file);
|
|
76
|
-
if (fs.statSync(oldLogPath).isFile()) {
|
|
77
|
-
fs.copyFileSync(oldLogPath, newLogPath);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
87
|
+
catch {
|
|
88
|
+
// Ignore cleanup errors
|
|
80
89
|
}
|
|
81
|
-
console.log('✓ Migration complete. You can safely remove ~/.vids-dashboard if desired.');
|
|
82
90
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
console.error(' Continuing with new directory. Old data remains in ~/.vids-dashboard');
|
|
91
|
+
if (!result || result.trim() === '') {
|
|
92
|
+
return undefined;
|
|
86
93
|
}
|
|
94
|
+
return JSON.parse(result);
|
|
87
95
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (!this.db) {
|
|
95
|
-
this.db = new better_sqlite3_1.default(this.dbPath);
|
|
96
|
-
this.db.pragma('journal_mode = WAL');
|
|
97
|
-
this.initializeSchema();
|
|
96
|
+
catch (error) {
|
|
97
|
+
// Check if it's a 404 or other HTTP error
|
|
98
|
+
if (error instanceof Error && error.message.includes('404')) {
|
|
99
|
+
throw new Error('Resource not found');
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`API request failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
98
102
|
}
|
|
99
|
-
return this.db;
|
|
100
|
-
}
|
|
101
|
-
initializeSchema() {
|
|
102
|
-
if (!this.db)
|
|
103
|
-
return;
|
|
104
|
-
// Projects table
|
|
105
|
-
this.db.exec(`
|
|
106
|
-
CREATE TABLE IF NOT EXISTS projects (
|
|
107
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
108
|
-
name TEXT NOT NULL,
|
|
109
|
-
path TEXT NOT NULL UNIQUE,
|
|
110
|
-
last_scanned INTEGER,
|
|
111
|
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now'))
|
|
112
|
-
)
|
|
113
|
-
`);
|
|
114
|
-
// Tests table
|
|
115
|
-
this.db.exec(`
|
|
116
|
-
CREATE TABLE IF NOT EXISTS tests (
|
|
117
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
118
|
-
project_id INTEGER NOT NULL,
|
|
119
|
-
file_path TEXT NOT NULL,
|
|
120
|
-
framework TEXT,
|
|
121
|
-
status TEXT,
|
|
122
|
-
last_run INTEGER,
|
|
123
|
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
124
|
-
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
125
|
-
UNIQUE(project_id, file_path)
|
|
126
|
-
)
|
|
127
|
-
`);
|
|
128
|
-
// Jenkins jobs table (for future integration)
|
|
129
|
-
this.db.exec(`
|
|
130
|
-
CREATE TABLE IF NOT EXISTS jenkins_jobs (
|
|
131
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
132
|
-
project_id INTEGER NOT NULL,
|
|
133
|
-
job_name TEXT NOT NULL,
|
|
134
|
-
job_url TEXT NOT NULL,
|
|
135
|
-
last_build_status TEXT,
|
|
136
|
-
last_build_number INTEGER,
|
|
137
|
-
last_updated INTEGER,
|
|
138
|
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
139
|
-
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
140
|
-
UNIQUE(project_id, job_name)
|
|
141
|
-
)
|
|
142
|
-
`);
|
|
143
|
-
// Project ports table
|
|
144
|
-
this.db.exec(`
|
|
145
|
-
CREATE TABLE IF NOT EXISTS project_ports (
|
|
146
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
147
|
-
project_id INTEGER NOT NULL,
|
|
148
|
-
port INTEGER NOT NULL,
|
|
149
|
-
script_name TEXT,
|
|
150
|
-
config_source TEXT NOT NULL,
|
|
151
|
-
last_detected INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
152
|
-
created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
|
153
|
-
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
|
154
|
-
UNIQUE(project_id, port, script_name)
|
|
155
|
-
)
|
|
156
|
-
`);
|
|
157
|
-
// Create indexes
|
|
158
|
-
this.db.exec(`
|
|
159
|
-
CREATE INDEX IF NOT EXISTS idx_tests_project_id ON tests(project_id);
|
|
160
|
-
CREATE INDEX IF NOT EXISTS idx_jenkins_jobs_project_id ON jenkins_jobs(project_id);
|
|
161
|
-
CREATE INDEX IF NOT EXISTS idx_project_ports_project_id ON project_ports(project_id);
|
|
162
|
-
CREATE INDEX IF NOT EXISTS idx_project_ports_port ON project_ports(port);
|
|
163
|
-
`);
|
|
164
103
|
}
|
|
165
104
|
// Project operations
|
|
166
105
|
addProject(name, projectPath) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
`);
|
|
172
|
-
const result = stmt.run(name, projectPath);
|
|
173
|
-
return this.getProject(result.lastInsertRowid);
|
|
106
|
+
return this.request('/projects', {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
body: JSON.stringify({ name, path: projectPath }),
|
|
109
|
+
});
|
|
174
110
|
}
|
|
175
111
|
getProject(id) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
112
|
+
try {
|
|
113
|
+
return this.request(`/projects/${id}`);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
if (error instanceof Error && error.message.includes('404')) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
179
121
|
}
|
|
180
122
|
getProjectByPath(projectPath) {
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
return stmt.get(projectPath);
|
|
123
|
+
const projects = this.getAllProjects();
|
|
124
|
+
return projects.find(p => p.path === projectPath) || null;
|
|
184
125
|
}
|
|
185
126
|
getAllProjects() {
|
|
186
|
-
|
|
187
|
-
const stmt = db.prepare('SELECT * FROM projects ORDER BY id');
|
|
188
|
-
return stmt.all();
|
|
127
|
+
return this.request('/projects');
|
|
189
128
|
}
|
|
190
129
|
updateProjectLastScanned(id) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
130
|
+
// Fire and forget - this is handled by the scan endpoint
|
|
131
|
+
// No need to explicitly update last_scanned
|
|
132
|
+
}
|
|
133
|
+
updateProjectFramework(id, framework) {
|
|
134
|
+
// This will be called during scan to update the detected framework
|
|
135
|
+
this.request(`/projects/${id}`, {
|
|
136
|
+
method: 'PUT',
|
|
137
|
+
body: JSON.stringify({ framework }),
|
|
138
|
+
});
|
|
194
139
|
}
|
|
195
140
|
updateProjectName(id, newName) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (!updated) {
|
|
201
|
-
throw new Error('Failed to update project name');
|
|
202
|
-
}
|
|
203
|
-
return updated;
|
|
141
|
+
return this.request(`/projects/${id}`, {
|
|
142
|
+
method: 'PUT',
|
|
143
|
+
body: JSON.stringify({ name: newName }),
|
|
144
|
+
});
|
|
204
145
|
}
|
|
205
146
|
removeProject(id) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
147
|
+
this.request(`/projects/${id}`, {
|
|
148
|
+
method: 'DELETE',
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
scanProject(id) {
|
|
152
|
+
return this.request(`/projects/${id}/scan`, {
|
|
153
|
+
method: 'POST',
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
scanAllProjects() {
|
|
157
|
+
return this.request('/projects/scan/all', {
|
|
158
|
+
method: 'POST',
|
|
159
|
+
});
|
|
209
160
|
}
|
|
210
161
|
// Test operations
|
|
211
162
|
addTest(projectId, filePath, framework = null) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
INSERT OR REPLACE INTO tests (project_id, file_path, framework)
|
|
215
|
-
VALUES (?, ?, ?)
|
|
216
|
-
`);
|
|
217
|
-
const result = stmt.run(projectId, filePath, framework);
|
|
218
|
-
return this.getTest(result.lastInsertRowid);
|
|
163
|
+
// Tests are added via scan endpoint, not directly
|
|
164
|
+
throw new Error('addTest should not be called directly. Use scan endpoint instead.');
|
|
219
165
|
}
|
|
220
166
|
getTest(id) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
return stmt.get(id);
|
|
167
|
+
// This endpoint doesn't exist yet
|
|
168
|
+
throw new Error('getTest endpoint not yet implemented in API');
|
|
224
169
|
}
|
|
225
170
|
getTestsByProject(projectId) {
|
|
226
|
-
|
|
227
|
-
const stmt = db.prepare('SELECT * FROM tests WHERE project_id = ? ORDER BY file_path');
|
|
228
|
-
return stmt.all(projectId);
|
|
171
|
+
return this.request(`/projects/${projectId}/tests`);
|
|
229
172
|
}
|
|
230
173
|
removeTestsByProject(projectId) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
174
|
+
// This is handled by the scan endpoint
|
|
175
|
+
// For now, we'll just call scan which removes and re-adds
|
|
176
|
+
throw new Error('removeTestsByProject should not be called directly. Use scan endpoint instead.');
|
|
234
177
|
}
|
|
235
|
-
// Jenkins operations
|
|
178
|
+
// Jenkins operations
|
|
236
179
|
addJenkinsJob(projectId, jobName, jobUrl) {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
INSERT OR REPLACE INTO jenkins_jobs (project_id, job_name, job_url)
|
|
240
|
-
VALUES (?, ?, ?)
|
|
241
|
-
`);
|
|
242
|
-
const result = stmt.run(projectId, jobName, jobUrl);
|
|
243
|
-
return this.getJenkinsJob(result.lastInsertRowid);
|
|
180
|
+
// This endpoint doesn't exist yet
|
|
181
|
+
throw new Error('addJenkinsJob endpoint not yet implemented in API');
|
|
244
182
|
}
|
|
245
183
|
getJenkinsJob(id) {
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return stmt.get(id);
|
|
184
|
+
// This endpoint doesn't exist yet
|
|
185
|
+
throw new Error('getJenkinsJob endpoint not yet implemented in API');
|
|
249
186
|
}
|
|
250
187
|
getJenkinsJobsByProject(projectId) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return stmt.all(projectId);
|
|
188
|
+
// This endpoint doesn't exist yet
|
|
189
|
+
throw new Error('getJenkinsJobsByProject endpoint not yet implemented in API');
|
|
254
190
|
}
|
|
255
191
|
// Project port operations
|
|
256
192
|
addProjectPort(projectId, port, configSource, scriptName = null) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
INSERT OR REPLACE INTO project_ports (project_id, port, script_name, config_source, last_detected)
|
|
260
|
-
VALUES (?, ?, ?, ?, strftime('%s', 'now'))
|
|
261
|
-
`);
|
|
262
|
-
const result = stmt.run(projectId, port, scriptName, configSource);
|
|
263
|
-
const portRecord = this.getProjectPort(result.lastInsertRowid);
|
|
264
|
-
if (!portRecord) {
|
|
265
|
-
throw new Error('Failed to create project port record');
|
|
266
|
-
}
|
|
267
|
-
return portRecord;
|
|
193
|
+
// This endpoint doesn't exist yet
|
|
194
|
+
throw new Error('addProjectPort endpoint not yet implemented in API');
|
|
268
195
|
}
|
|
269
196
|
getProjectPort(id) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
return stmt.get(id);
|
|
197
|
+
// This endpoint doesn't exist yet
|
|
198
|
+
throw new Error('getProjectPort endpoint not yet implemented in API');
|
|
273
199
|
}
|
|
274
200
|
getProjectPorts(projectId) {
|
|
275
|
-
|
|
276
|
-
const stmt = db.prepare('SELECT * FROM project_ports WHERE project_id = ? ORDER BY port');
|
|
277
|
-
return stmt.all(projectId);
|
|
201
|
+
return this.request(`/projects/${projectId}/ports`);
|
|
278
202
|
}
|
|
279
203
|
getProjectPortsByScript(projectId, scriptName) {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
return stmt.all(projectId, scriptName);
|
|
204
|
+
const ports = this.getProjectPorts(projectId);
|
|
205
|
+
return ports.filter(p => p.script_name === scriptName);
|
|
283
206
|
}
|
|
284
207
|
removeProjectPorts(projectId) {
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
stmt.run(projectId);
|
|
208
|
+
// This endpoint doesn't exist yet
|
|
209
|
+
throw new Error('removeProjectPorts endpoint not yet implemented in API');
|
|
288
210
|
}
|
|
289
211
|
updateProjectPortLastDetected(projectId, port, scriptName) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
212
|
+
// This endpoint doesn't exist yet - no-op for now
|
|
213
|
+
// Ports are updated via the scan endpoint
|
|
214
|
+
}
|
|
215
|
+
// Settings operations
|
|
216
|
+
getSetting(key) {
|
|
217
|
+
const settings = this.getAllSettings();
|
|
218
|
+
return settings[key] || null;
|
|
219
|
+
}
|
|
220
|
+
setSetting(key, value) {
|
|
221
|
+
this.request(`/settings/${encodeURIComponent(key)}`, {
|
|
222
|
+
method: 'PUT',
|
|
223
|
+
body: JSON.stringify({ value }),
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
getAllSettings() {
|
|
227
|
+
return this.request('/settings');
|
|
297
228
|
}
|
|
298
229
|
close() {
|
|
299
|
-
|
|
300
|
-
this.db.close();
|
|
301
|
-
this.db = null;
|
|
302
|
-
}
|
|
230
|
+
// No-op for API client
|
|
303
231
|
}
|
|
304
232
|
}
|
|
305
233
|
// Singleton instance
|
package/dist/core/detector.d.ts
CHANGED
|
@@ -7,3 +7,8 @@ export interface TestFramework {
|
|
|
7
7
|
export declare const FRAMEWORKS: TestFramework[];
|
|
8
8
|
export declare function detectTestFramework(projectPath: string): string | null;
|
|
9
9
|
export declare function isTestFile(filePath: string, detectedFramework?: string | null): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Detect the main framework/library used in a project
|
|
12
|
+
* Returns null if no framework is detected
|
|
13
|
+
*/
|
|
14
|
+
export declare function detectProjectFramework(projectPath: string): string | null;
|
package/dist/core/detector.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.FRAMEWORKS = void 0;
|
|
37
37
|
exports.detectTestFramework = detectTestFramework;
|
|
38
38
|
exports.isTestFile = isTestFile;
|
|
39
|
+
exports.detectProjectFramework = detectProjectFramework;
|
|
39
40
|
const fs = __importStar(require("fs"));
|
|
40
41
|
const path = __importStar(require("path"));
|
|
41
42
|
exports.FRAMEWORKS = [
|
|
@@ -147,3 +148,137 @@ function isTestFile(filePath, detectedFramework = null) {
|
|
|
147
148
|
}
|
|
148
149
|
return false;
|
|
149
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Detect the main framework/library used in a project
|
|
153
|
+
* Returns null if no framework is detected
|
|
154
|
+
*/
|
|
155
|
+
function detectProjectFramework(projectPath) {
|
|
156
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
157
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
158
|
+
// Check for non-JS projects
|
|
159
|
+
if (fs.existsSync(path.join(projectPath, 'Cargo.toml')))
|
|
160
|
+
return 'rust';
|
|
161
|
+
if (fs.existsSync(path.join(projectPath, 'go.mod')))
|
|
162
|
+
return 'go';
|
|
163
|
+
if (fs.existsSync(path.join(projectPath, 'requirements.txt')) ||
|
|
164
|
+
fs.existsSync(path.join(projectPath, 'setup.py')) ||
|
|
165
|
+
fs.existsSync(path.join(projectPath, 'pyproject.toml'))) {
|
|
166
|
+
return 'python';
|
|
167
|
+
}
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
172
|
+
const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
173
|
+
// Meta-frameworks (check these first as they often include the base frameworks)
|
|
174
|
+
if (deps['next'] || deps['next.js'])
|
|
175
|
+
return 'next.js';
|
|
176
|
+
if (deps['@nuxt/kit'] || deps['nuxt'] || deps['nuxt3'])
|
|
177
|
+
return 'nuxt.js';
|
|
178
|
+
if (deps['gatsby'])
|
|
179
|
+
return 'gatsby';
|
|
180
|
+
if (deps['@remix-run/react'] || deps['remix'])
|
|
181
|
+
return 'remix';
|
|
182
|
+
if (deps['@astro'] || deps['astro'])
|
|
183
|
+
return 'astro';
|
|
184
|
+
if (deps['@angular/core'])
|
|
185
|
+
return 'angular';
|
|
186
|
+
if (deps['expo'] || deps['expo-cli'])
|
|
187
|
+
return 'expo';
|
|
188
|
+
// React Native (check before React)
|
|
189
|
+
if (deps['react-native'])
|
|
190
|
+
return 'react-native';
|
|
191
|
+
// Frontend frameworks
|
|
192
|
+
if (deps['react'] || deps['react-dom'])
|
|
193
|
+
return 'react';
|
|
194
|
+
if (deps['vue']) {
|
|
195
|
+
// Check Vue version
|
|
196
|
+
const vueVersion = deps['vue']?.match(/\d+/)?.[0];
|
|
197
|
+
return vueVersion === '3' ? 'vue 3' : 'vue';
|
|
198
|
+
}
|
|
199
|
+
if (deps['svelte'])
|
|
200
|
+
return 'svelte';
|
|
201
|
+
if (deps['solid-js'])
|
|
202
|
+
return 'solid';
|
|
203
|
+
if (deps['preact'])
|
|
204
|
+
return 'preact';
|
|
205
|
+
if (deps['alpine'] || deps['alpinejs'])
|
|
206
|
+
return 'alpine.js';
|
|
207
|
+
if (deps['lit'] || deps['lit-element'])
|
|
208
|
+
return 'lit';
|
|
209
|
+
if (deps['hyperapp'])
|
|
210
|
+
return 'hyperapp';
|
|
211
|
+
if (deps['mithril'])
|
|
212
|
+
return 'mithril';
|
|
213
|
+
if (deps['inferno'])
|
|
214
|
+
return 'inferno';
|
|
215
|
+
if (deps['marko'])
|
|
216
|
+
return 'marko';
|
|
217
|
+
// Backend frameworks
|
|
218
|
+
if (deps['express'])
|
|
219
|
+
return 'express';
|
|
220
|
+
if (deps['@nestjs/core'])
|
|
221
|
+
return 'nest.js';
|
|
222
|
+
if (deps['fastify'])
|
|
223
|
+
return 'fastify';
|
|
224
|
+
if (deps['koa'])
|
|
225
|
+
return 'koa';
|
|
226
|
+
if (deps['hapi'] || deps['@hapi/hapi'])
|
|
227
|
+
return 'hapi';
|
|
228
|
+
if (deps['@apollo/server'] || deps['apollo-server'])
|
|
229
|
+
return 'apollo';
|
|
230
|
+
if (deps['graphql'] && (deps['@graphql-yoga/node'] || deps['graphql-yoga']))
|
|
231
|
+
return 'graphql-yoga';
|
|
232
|
+
if (deps['@trpc/server'])
|
|
233
|
+
return 'trpc';
|
|
234
|
+
if (deps['@redwoodjs/core'])
|
|
235
|
+
return 'redwood.js';
|
|
236
|
+
if (deps['@blitzjs/core'])
|
|
237
|
+
return 'blitz.js';
|
|
238
|
+
// Electron
|
|
239
|
+
if (deps['electron'])
|
|
240
|
+
return 'electron';
|
|
241
|
+
// Static site generators
|
|
242
|
+
if (deps['@11ty/eleventy'])
|
|
243
|
+
return '11ty';
|
|
244
|
+
if (deps['hexo'])
|
|
245
|
+
return 'hexo';
|
|
246
|
+
if (deps['jekyll'])
|
|
247
|
+
return 'jekyll';
|
|
248
|
+
if (deps['hugo'])
|
|
249
|
+
return 'hugo';
|
|
250
|
+
// Mobile development
|
|
251
|
+
if (deps['@ionic/core'] || deps['@ionic/angular'] || deps['@ionic/react'])
|
|
252
|
+
return 'ionic';
|
|
253
|
+
if (deps['@nativescript/core'])
|
|
254
|
+
return 'nativescript';
|
|
255
|
+
if (deps['@capacitor/core'])
|
|
256
|
+
return 'capacitor';
|
|
257
|
+
if (deps['cordova'])
|
|
258
|
+
return 'cordova';
|
|
259
|
+
// Desktop development
|
|
260
|
+
if (deps['tauri'])
|
|
261
|
+
return 'tauri';
|
|
262
|
+
if (deps['nw.js'] || deps['nw'])
|
|
263
|
+
return 'nw.js';
|
|
264
|
+
// Build tools / bundlers (as last resort)
|
|
265
|
+
if (deps['vite'])
|
|
266
|
+
return 'vite';
|
|
267
|
+
if (deps['webpack'])
|
|
268
|
+
return 'webpack';
|
|
269
|
+
if (deps['parcel'])
|
|
270
|
+
return 'parcel';
|
|
271
|
+
if (deps['rollup'])
|
|
272
|
+
return 'rollup';
|
|
273
|
+
if (deps['esbuild'])
|
|
274
|
+
return 'esbuild';
|
|
275
|
+
if (deps['turbopack'])
|
|
276
|
+
return 'turbopack';
|
|
277
|
+
// Generic Node.js if no specific framework found but package.json exists
|
|
278
|
+
return 'node.js';
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
// Invalid JSON or read error
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
export * from './database';
|
|
2
2
|
export * from './detector';
|
|
3
3
|
export * from './scanner';
|
|
4
|
+
export * from './settings';
|
|
4
5
|
export { getDatabaseManager } from './database';
|
|
5
6
|
import { Project, Test } from './database';
|
|
6
|
-
import { scanProject, scanAllProjects } from './scanner';
|
|
7
7
|
export declare function getAllProjects(): Project[];
|
|
8
8
|
export declare function addProject(name: string, projectPath: string): Project;
|
|
9
9
|
export declare function removeProject(id: number): void;
|
|
10
10
|
export declare function getTestsByProject(projectId: number): Test[];
|
|
11
|
-
export { scanProject, scanAllProjects };
|
package/dist/core/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.getDatabaseManager = void 0;
|
|
18
18
|
exports.getAllProjects = getAllProjects;
|
|
19
19
|
exports.addProject = addProject;
|
|
20
20
|
exports.removeProject = removeProject;
|
|
@@ -22,13 +22,11 @@ exports.getTestsByProject = getTestsByProject;
|
|
|
22
22
|
__exportStar(require("./database"), exports);
|
|
23
23
|
__exportStar(require("./detector"), exports);
|
|
24
24
|
__exportStar(require("./scanner"), exports);
|
|
25
|
+
__exportStar(require("./settings"), exports);
|
|
25
26
|
var database_1 = require("./database");
|
|
26
27
|
Object.defineProperty(exports, "getDatabaseManager", { enumerable: true, get: function () { return database_1.getDatabaseManager; } });
|
|
27
28
|
// Convenience functions for common operations
|
|
28
29
|
const database_2 = require("./database");
|
|
29
|
-
const scanner_1 = require("./scanner");
|
|
30
|
-
Object.defineProperty(exports, "scanProject", { enumerable: true, get: function () { return scanner_1.scanProject; } });
|
|
31
|
-
Object.defineProperty(exports, "scanAllProjects", { enumerable: true, get: function () { return scanner_1.scanAllProjects; } });
|
|
32
30
|
function getAllProjects() {
|
|
33
31
|
return (0, database_2.getDatabaseManager)().getAllProjects();
|
|
34
32
|
}
|