projax 3.3.39 → 3.3.41
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 +12 -1
- package/dist/api/database.d.ts.map +1 -1
- package/dist/api/database.js +139 -1
- package/dist/api/database.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -1
- 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 +4 -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 +20 -0
- 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 +64 -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 +429 -0
- package/dist/api/routes/workspaces.js.map +1 -0
- package/dist/api/types.d.ts +26 -0
- package/dist/api/types.d.ts.map +1 -1
- package/dist/core/backup-utils.d.ts +17 -0
- package/dist/core/backup-utils.js +166 -0
- package/dist/core/database.d.ts +1 -0
- package/dist/core/git-utils.d.ts +12 -0
- package/dist/core/git-utils.js +96 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +3 -0
- package/dist/core/workspace-utils.d.ts +37 -0
- package/dist/core/workspace-utils.js +152 -0
- package/dist/electron/core/backup-utils.d.ts +17 -0
- package/dist/electron/core/backup-utils.js +166 -0
- package/dist/electron/core/database.d.ts +1 -0
- package/dist/electron/core/git-utils.d.ts +12 -0
- package/dist/electron/core/git-utils.js +96 -0
- package/dist/electron/core/index.d.ts +3 -0
- package/dist/electron/core/index.js +3 -0
- package/dist/electron/core/workspace-utils.d.ts +37 -0
- package/dist/electron/core/workspace-utils.js +152 -0
- package/dist/electron/main.js +324 -9
- package/dist/electron/preload.d.ts +14 -0
- package/dist/electron/preload.js +9 -0
- 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-CWxXs5M7.css +1 -0
- package/dist/electron/renderer/assets/index-CopVNRnR.js +64 -0
- package/dist/electron/renderer/assets/index-CtXtIMer.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/index.js +281 -4
- package/package.json +1 -1
package/dist/api/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface Project {
|
|
|
7
7
|
last_scanned: number | null;
|
|
8
8
|
created_at: number;
|
|
9
9
|
tags?: string[];
|
|
10
|
+
git_branch?: string | null;
|
|
10
11
|
}
|
|
11
12
|
export interface Test {
|
|
12
13
|
id: number;
|
|
@@ -50,6 +51,28 @@ export interface TestResult {
|
|
|
50
51
|
timestamp: number;
|
|
51
52
|
raw_output: string | null;
|
|
52
53
|
}
|
|
54
|
+
export interface Workspace {
|
|
55
|
+
id: number;
|
|
56
|
+
name: string;
|
|
57
|
+
workspace_file_path: string;
|
|
58
|
+
description: string | null;
|
|
59
|
+
tags?: string[];
|
|
60
|
+
created_at: number;
|
|
61
|
+
last_opened: number | null;
|
|
62
|
+
}
|
|
63
|
+
export interface WorkspaceProject {
|
|
64
|
+
id: number;
|
|
65
|
+
workspace_id: number;
|
|
66
|
+
project_path: string;
|
|
67
|
+
order: number;
|
|
68
|
+
created_at: number;
|
|
69
|
+
}
|
|
70
|
+
export interface ProjectSettings {
|
|
71
|
+
id: number;
|
|
72
|
+
project_id: number;
|
|
73
|
+
script_sort_order: 'default' | 'alphabetical' | 'last-used';
|
|
74
|
+
updated_at: number;
|
|
75
|
+
}
|
|
53
76
|
export interface DatabaseSchema {
|
|
54
77
|
projects: Project[];
|
|
55
78
|
tests: Test[];
|
|
@@ -61,5 +84,8 @@ export interface DatabaseSchema {
|
|
|
61
84
|
value: string;
|
|
62
85
|
updated_at: number;
|
|
63
86
|
}>;
|
|
87
|
+
workspaces: Workspace[];
|
|
88
|
+
workspace_projects: WorkspaceProject[];
|
|
89
|
+
project_settings: ProjectSettings[];
|
|
64
90
|
}
|
|
65
91
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/api/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a backup of the PROJAX database
|
|
3
|
+
* @param outputPath Directory where the backup should be created
|
|
4
|
+
* @returns Path to the created backup file
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBackup(outputPath: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Restore PROJAX database from a backup file
|
|
9
|
+
* @param backupPath Path to the .pbz backup file
|
|
10
|
+
*/
|
|
11
|
+
export declare function restoreBackup(backupPath: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Validate a backup file without restoring
|
|
14
|
+
* @param backupPath Path to the .pbz backup file
|
|
15
|
+
* @returns true if valid, throws error if invalid
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateBackup(backupPath: string): Promise<boolean>;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
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
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createBackup = createBackup;
|
|
37
|
+
exports.restoreBackup = restoreBackup;
|
|
38
|
+
exports.validateBackup = validateBackup;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
/**
|
|
43
|
+
* Create a backup of the PROJAX database
|
|
44
|
+
* @param outputPath Directory where the backup should be created
|
|
45
|
+
* @returns Path to the created backup file
|
|
46
|
+
*/
|
|
47
|
+
async function createBackup(outputPath) {
|
|
48
|
+
const dataDir = path.join(os.homedir(), '.projax');
|
|
49
|
+
const dbPath = path.join(dataDir, 'data.json');
|
|
50
|
+
if (!fs.existsSync(dbPath)) {
|
|
51
|
+
throw new Error('PROJAX database not found');
|
|
52
|
+
}
|
|
53
|
+
// Generate timestamped filename
|
|
54
|
+
const now = new Date();
|
|
55
|
+
const timestamp = now.toISOString().replace(/[:.]/g, '-').slice(0, 19); // YYYY-MM-DDTHHmmss
|
|
56
|
+
const filename = `projax-backup-${timestamp}.pbz`;
|
|
57
|
+
const backupPath = path.join(outputPath, filename);
|
|
58
|
+
// Ensure output directory exists
|
|
59
|
+
if (!fs.existsSync(outputPath)) {
|
|
60
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
// Read database file
|
|
63
|
+
const dbContent = fs.readFileSync(dbPath, 'utf-8');
|
|
64
|
+
// Create metadata
|
|
65
|
+
const metadata = {
|
|
66
|
+
version: '1.0',
|
|
67
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
68
|
+
projax_version: '3.4.0', // This should ideally come from package.json
|
|
69
|
+
created_at: now.toISOString(),
|
|
70
|
+
};
|
|
71
|
+
// Create ZIP-like structure manually (simple approach)
|
|
72
|
+
// For a proper ZIP, we'd use a library like adm-zip or archiver
|
|
73
|
+
// For now, we'll create a simple JSON structure that can be restored
|
|
74
|
+
const backupData = {
|
|
75
|
+
metadata,
|
|
76
|
+
data: JSON.parse(dbContent),
|
|
77
|
+
};
|
|
78
|
+
// Write backup file
|
|
79
|
+
fs.writeFileSync(backupPath, JSON.stringify(backupData, null, 2), 'utf-8');
|
|
80
|
+
return backupPath;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Restore PROJAX database from a backup file
|
|
84
|
+
* @param backupPath Path to the .pbz backup file
|
|
85
|
+
*/
|
|
86
|
+
async function restoreBackup(backupPath) {
|
|
87
|
+
if (!fs.existsSync(backupPath)) {
|
|
88
|
+
throw new Error(`Backup file not found: ${backupPath}`);
|
|
89
|
+
}
|
|
90
|
+
if (!backupPath.endsWith('.pbz')) {
|
|
91
|
+
throw new Error('Invalid backup file extension. Expected .pbz');
|
|
92
|
+
}
|
|
93
|
+
// Read and parse backup file
|
|
94
|
+
let backupContent;
|
|
95
|
+
try {
|
|
96
|
+
const content = fs.readFileSync(backupPath, 'utf-8');
|
|
97
|
+
backupContent = JSON.parse(content);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (error instanceof SyntaxError) {
|
|
101
|
+
throw new Error(`Invalid backup file format: ${error.message}`);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`Failed to read backup file: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
104
|
+
}
|
|
105
|
+
// Validate backup structure
|
|
106
|
+
if (!backupContent.metadata || !backupContent.data) {
|
|
107
|
+
throw new Error('Invalid backup file structure: missing metadata or data');
|
|
108
|
+
}
|
|
109
|
+
// Validate metadata
|
|
110
|
+
const metadata = backupContent.metadata;
|
|
111
|
+
if (!metadata.version || !metadata.timestamp) {
|
|
112
|
+
throw new Error('Invalid backup metadata');
|
|
113
|
+
}
|
|
114
|
+
// Validate data structure (basic check)
|
|
115
|
+
if (typeof backupContent.data !== 'object' || !Array.isArray(backupContent.data.projects)) {
|
|
116
|
+
throw new Error('Invalid backup data structure');
|
|
117
|
+
}
|
|
118
|
+
// Create backup of current database before restoring
|
|
119
|
+
const dataDir = path.join(os.homedir(), '.projax');
|
|
120
|
+
const dbPath = path.join(dataDir, 'data.json');
|
|
121
|
+
if (fs.existsSync(dbPath)) {
|
|
122
|
+
const backupTimestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19);
|
|
123
|
+
const currentBackupPath = path.join(dataDir, `data.backup-${backupTimestamp}.json`);
|
|
124
|
+
fs.copyFileSync(dbPath, currentBackupPath);
|
|
125
|
+
}
|
|
126
|
+
// Ensure data directory exists
|
|
127
|
+
if (!fs.existsSync(dataDir)) {
|
|
128
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
129
|
+
}
|
|
130
|
+
// Write restored data
|
|
131
|
+
fs.writeFileSync(dbPath, JSON.stringify(backupContent.data, null, 2), 'utf-8');
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Validate a backup file without restoring
|
|
135
|
+
* @param backupPath Path to the .pbz backup file
|
|
136
|
+
* @returns true if valid, throws error if invalid
|
|
137
|
+
*/
|
|
138
|
+
async function validateBackup(backupPath) {
|
|
139
|
+
if (!fs.existsSync(backupPath)) {
|
|
140
|
+
throw new Error(`Backup file not found: ${backupPath}`);
|
|
141
|
+
}
|
|
142
|
+
if (!backupPath.endsWith('.pbz')) {
|
|
143
|
+
throw new Error('Invalid backup file extension. Expected .pbz');
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const content = fs.readFileSync(backupPath, 'utf-8');
|
|
147
|
+
const backupContent = JSON.parse(content);
|
|
148
|
+
if (!backupContent.metadata || !backupContent.data) {
|
|
149
|
+
throw new Error('Invalid backup file structure');
|
|
150
|
+
}
|
|
151
|
+
const metadata = backupContent.metadata;
|
|
152
|
+
if (!metadata.version || !metadata.timestamp) {
|
|
153
|
+
throw new Error('Invalid backup metadata');
|
|
154
|
+
}
|
|
155
|
+
if (typeof backupContent.data !== 'object' || !Array.isArray(backupContent.data.projects)) {
|
|
156
|
+
throw new Error('Invalid backup data structure');
|
|
157
|
+
}
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (error instanceof SyntaxError) {
|
|
162
|
+
throw new Error(`Invalid JSON in backup file: ${error.message}`);
|
|
163
|
+
}
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
}
|
package/dist/core/database.d.ts
CHANGED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current git branch for a project
|
|
3
|
+
* @param projectPath The path to the project directory
|
|
4
|
+
* @returns The current branch name, or null if not a git repo or on error
|
|
5
|
+
*/
|
|
6
|
+
export declare function getCurrentBranch(projectPath: string): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Get git branches for multiple projects
|
|
9
|
+
* @param projectPaths Array of project paths
|
|
10
|
+
* @returns Map of project path to branch name (or null)
|
|
11
|
+
*/
|
|
12
|
+
export declare function getBranchesForProjects(projectPaths: string[]): Map<string, string | null>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
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
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getCurrentBranch = getCurrentBranch;
|
|
37
|
+
exports.getBranchesForProjects = getBranchesForProjects;
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
/**
|
|
42
|
+
* Get the current git branch for a project
|
|
43
|
+
* @param projectPath The path to the project directory
|
|
44
|
+
* @returns The current branch name, or null if not a git repo or on error
|
|
45
|
+
*/
|
|
46
|
+
function getCurrentBranch(projectPath) {
|
|
47
|
+
try {
|
|
48
|
+
// Check if .git directory exists
|
|
49
|
+
const gitDir = path.join(projectPath, '.git');
|
|
50
|
+
if (!fs.existsSync(gitDir) && !fs.existsSync(path.join(projectPath, '.git', 'HEAD'))) {
|
|
51
|
+
// Check if it's a worktree or submodule
|
|
52
|
+
const gitConfig = path.join(projectPath, '.git');
|
|
53
|
+
if (!fs.existsSync(gitConfig)) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Try to get the current branch
|
|
58
|
+
const branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', {
|
|
59
|
+
cwd: projectPath,
|
|
60
|
+
encoding: 'utf-8',
|
|
61
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
62
|
+
}).trim();
|
|
63
|
+
// Handle detached HEAD state (returns "HEAD")
|
|
64
|
+
if (branch === 'HEAD') {
|
|
65
|
+
// Try to get the commit hash instead
|
|
66
|
+
try {
|
|
67
|
+
const commit = (0, child_process_1.execSync)('git rev-parse --short HEAD', {
|
|
68
|
+
cwd: projectPath,
|
|
69
|
+
encoding: 'utf-8',
|
|
70
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
71
|
+
}).trim();
|
|
72
|
+
return `detached@${commit}`;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return 'detached';
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return branch || null;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
// Not a git repo, or git command failed
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get git branches for multiple projects
|
|
87
|
+
* @param projectPaths Array of project paths
|
|
88
|
+
* @returns Map of project path to branch name (or null)
|
|
89
|
+
*/
|
|
90
|
+
function getBranchesForProjects(projectPaths) {
|
|
91
|
+
const branches = new Map();
|
|
92
|
+
for (const projectPath of projectPaths) {
|
|
93
|
+
branches.set(projectPath, getCurrentBranch(projectPath));
|
|
94
|
+
}
|
|
95
|
+
return branches;
|
|
96
|
+
}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,6 +2,9 @@ export * from './database';
|
|
|
2
2
|
export * from './detector';
|
|
3
3
|
export * from './scanner';
|
|
4
4
|
export * from './settings';
|
|
5
|
+
export * from './git-utils';
|
|
6
|
+
export * from './workspace-utils';
|
|
7
|
+
export * from './backup-utils';
|
|
5
8
|
export { getDatabaseManager } from './database';
|
|
6
9
|
import { Project, Test } from './database';
|
|
7
10
|
export declare function getAllProjects(): Project[];
|
package/dist/core/index.js
CHANGED
|
@@ -23,6 +23,9 @@ __exportStar(require("./database"), exports);
|
|
|
23
23
|
__exportStar(require("./detector"), exports);
|
|
24
24
|
__exportStar(require("./scanner"), exports);
|
|
25
25
|
__exportStar(require("./settings"), exports);
|
|
26
|
+
__exportStar(require("./git-utils"), exports);
|
|
27
|
+
__exportStar(require("./workspace-utils"), exports);
|
|
28
|
+
__exportStar(require("./backup-utils"), exports);
|
|
26
29
|
var database_1 = require("./database");
|
|
27
30
|
Object.defineProperty(exports, "getDatabaseManager", { enumerable: true, get: function () { return database_1.getDatabaseManager; } });
|
|
28
31
|
// Convenience functions for common operations
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface WorkspaceFolder {
|
|
2
|
+
path: string;
|
|
3
|
+
name?: string;
|
|
4
|
+
}
|
|
5
|
+
export interface WorkspaceSettings {
|
|
6
|
+
[key: string]: any;
|
|
7
|
+
}
|
|
8
|
+
export interface WorkspaceExtensions {
|
|
9
|
+
recommendations?: string[];
|
|
10
|
+
unwantedRecommendations?: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface ParsedWorkspace {
|
|
13
|
+
folders: WorkspaceFolder[];
|
|
14
|
+
settings?: WorkspaceSettings;
|
|
15
|
+
extensions?: WorkspaceExtensions;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Parse a .code-workspace file
|
|
19
|
+
* @param filePath Path to the .code-workspace file
|
|
20
|
+
* @returns Parsed workspace structure
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseWorkspaceFile(filePath: string): ParsedWorkspace;
|
|
23
|
+
/**
|
|
24
|
+
* Generate a .code-workspace file
|
|
25
|
+
* @param workspaceName Name of the workspace (used in comments)
|
|
26
|
+
* @param projects Array of project paths (absolute or relative)
|
|
27
|
+
* @param outputPath Path where the .code-workspace file should be created
|
|
28
|
+
* @param settings Optional workspace settings
|
|
29
|
+
* @param extensions Optional workspace extensions recommendations
|
|
30
|
+
*/
|
|
31
|
+
export declare function generateWorkspaceFile(workspaceName: string, projects: string[], outputPath: string, settings?: WorkspaceSettings, extensions?: WorkspaceExtensions): void;
|
|
32
|
+
/**
|
|
33
|
+
* Validate that a path is a valid workspace file
|
|
34
|
+
* @param filePath Path to check
|
|
35
|
+
* @returns true if the path exists and is a valid .code-workspace file
|
|
36
|
+
*/
|
|
37
|
+
export declare function validateWorkspacePath(filePath: string): boolean;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
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
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.parseWorkspaceFile = parseWorkspaceFile;
|
|
37
|
+
exports.generateWorkspaceFile = generateWorkspaceFile;
|
|
38
|
+
exports.validateWorkspacePath = validateWorkspacePath;
|
|
39
|
+
const fs = __importStar(require("fs"));
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
/**
|
|
42
|
+
* Parse a .code-workspace file
|
|
43
|
+
* @param filePath Path to the .code-workspace file
|
|
44
|
+
* @returns Parsed workspace structure
|
|
45
|
+
*/
|
|
46
|
+
function parseWorkspaceFile(filePath) {
|
|
47
|
+
if (!fs.existsSync(filePath)) {
|
|
48
|
+
throw new Error(`Workspace file not found: ${filePath}`);
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
52
|
+
const workspace = JSON.parse(content);
|
|
53
|
+
// Validate structure
|
|
54
|
+
if (!workspace.folders || !Array.isArray(workspace.folders)) {
|
|
55
|
+
throw new Error('Invalid workspace file: missing or invalid folders array');
|
|
56
|
+
}
|
|
57
|
+
// Normalize folder paths to absolute paths
|
|
58
|
+
const workspaceDir = path.dirname(filePath);
|
|
59
|
+
workspace.folders = workspace.folders.map(folder => {
|
|
60
|
+
if (typeof folder === 'string') {
|
|
61
|
+
// Legacy format: folders can be strings
|
|
62
|
+
const absolutePath = path.isAbsolute(folder)
|
|
63
|
+
? folder
|
|
64
|
+
: path.resolve(workspaceDir, folder);
|
|
65
|
+
return { path: absolutePath };
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Modern format: folders are objects with path property
|
|
69
|
+
const absolutePath = path.isAbsolute(folder.path)
|
|
70
|
+
? folder.path
|
|
71
|
+
: path.resolve(workspaceDir, folder.path);
|
|
72
|
+
return {
|
|
73
|
+
...folder,
|
|
74
|
+
path: absolutePath,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return workspace;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error instanceof SyntaxError) {
|
|
82
|
+
throw new Error(`Invalid JSON in workspace file: ${error.message}`);
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Generate a .code-workspace file
|
|
89
|
+
* @param workspaceName Name of the workspace (used in comments)
|
|
90
|
+
* @param projects Array of project paths (absolute or relative)
|
|
91
|
+
* @param outputPath Path where the .code-workspace file should be created
|
|
92
|
+
* @param settings Optional workspace settings
|
|
93
|
+
* @param extensions Optional workspace extensions recommendations
|
|
94
|
+
*/
|
|
95
|
+
function generateWorkspaceFile(workspaceName, projects, outputPath, settings, extensions) {
|
|
96
|
+
const workspaceDir = path.dirname(outputPath);
|
|
97
|
+
// Convert project paths to relative paths if they're within the workspace directory
|
|
98
|
+
const folders = projects.map(projectPath => {
|
|
99
|
+
const absolutePath = path.isAbsolute(projectPath)
|
|
100
|
+
? projectPath
|
|
101
|
+
: path.resolve(process.cwd(), projectPath);
|
|
102
|
+
// Try to make path relative to workspace directory if possible
|
|
103
|
+
let relativePath;
|
|
104
|
+
try {
|
|
105
|
+
relativePath = path.relative(workspaceDir, absolutePath);
|
|
106
|
+
// If relative path goes outside workspace dir, use absolute
|
|
107
|
+
if (relativePath.startsWith('..')) {
|
|
108
|
+
relativePath = absolutePath;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
relativePath = absolutePath;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
path: relativePath,
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
const workspace = {
|
|
119
|
+
folders,
|
|
120
|
+
...(settings && { settings }),
|
|
121
|
+
...(extensions && { extensions }),
|
|
122
|
+
};
|
|
123
|
+
// Add comment header
|
|
124
|
+
const content = JSON.stringify(workspace, null, 2);
|
|
125
|
+
const withHeader = `// ${workspaceName} Workspace\n${content}`;
|
|
126
|
+
// Ensure output directory exists
|
|
127
|
+
const outputDir = path.dirname(outputPath);
|
|
128
|
+
if (!fs.existsSync(outputDir)) {
|
|
129
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
fs.writeFileSync(outputPath, withHeader, 'utf-8');
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Validate that a path is a valid workspace file
|
|
135
|
+
* @param filePath Path to check
|
|
136
|
+
* @returns true if the path exists and is a valid .code-workspace file
|
|
137
|
+
*/
|
|
138
|
+
function validateWorkspacePath(filePath) {
|
|
139
|
+
if (!fs.existsSync(filePath)) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (!filePath.endsWith('.code-workspace')) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
parseWorkspaceFile(filePath);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a backup of the PROJAX database
|
|
3
|
+
* @param outputPath Directory where the backup should be created
|
|
4
|
+
* @returns Path to the created backup file
|
|
5
|
+
*/
|
|
6
|
+
export declare function createBackup(outputPath: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Restore PROJAX database from a backup file
|
|
9
|
+
* @param backupPath Path to the .pbz backup file
|
|
10
|
+
*/
|
|
11
|
+
export declare function restoreBackup(backupPath: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Validate a backup file without restoring
|
|
14
|
+
* @param backupPath Path to the .pbz backup file
|
|
15
|
+
* @returns true if valid, throws error if invalid
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateBackup(backupPath: string): Promise<boolean>;
|