@edgible-team/cli 1.0.1
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/LICENSE +136 -0
- package/README.md +450 -0
- package/dist/client/api-client.js +1057 -0
- package/dist/client/index.js +21 -0
- package/dist/commands/agent.js +1280 -0
- package/dist/commands/ai.js +608 -0
- package/dist/commands/application.js +885 -0
- package/dist/commands/auth.js +570 -0
- package/dist/commands/base/BaseCommand.js +93 -0
- package/dist/commands/base/CommandHandler.js +7 -0
- package/dist/commands/base/command-wrapper.js +58 -0
- package/dist/commands/base/middleware.js +77 -0
- package/dist/commands/config.js +116 -0
- package/dist/commands/connectivity.js +59 -0
- package/dist/commands/debug.js +98 -0
- package/dist/commands/discover.js +144 -0
- package/dist/commands/examples/migrated-command-example.js +180 -0
- package/dist/commands/gateway.js +494 -0
- package/dist/commands/managedGateway.js +787 -0
- package/dist/commands/utils/config-validator.js +76 -0
- package/dist/commands/utils/gateway-prompt.js +79 -0
- package/dist/commands/utils/input-parser.js +120 -0
- package/dist/commands/utils/output-formatter.js +109 -0
- package/dist/config/app-config.js +99 -0
- package/dist/detection/SystemCapabilityDetector.js +1244 -0
- package/dist/detection/ToolDetector.js +305 -0
- package/dist/detection/WorkloadDetector.js +314 -0
- package/dist/di/bindings.js +99 -0
- package/dist/di/container.js +88 -0
- package/dist/di/types.js +32 -0
- package/dist/index.js +52 -0
- package/dist/interfaces/IDaemonManager.js +3 -0
- package/dist/repositories/config-repository.js +62 -0
- package/dist/repositories/gateway-repository.js +35 -0
- package/dist/scripts/postinstall.js +101 -0
- package/dist/services/AgentStatusManager.js +299 -0
- package/dist/services/ConnectivityTester.js +271 -0
- package/dist/services/DependencyInstaller.js +475 -0
- package/dist/services/LocalAgentManager.js +2216 -0
- package/dist/services/application/ApplicationService.js +299 -0
- package/dist/services/auth/AuthService.js +214 -0
- package/dist/services/aws.js +644 -0
- package/dist/services/daemon/DaemonManagerFactory.js +65 -0
- package/dist/services/daemon/DockerDaemonManager.js +395 -0
- package/dist/services/daemon/LaunchdDaemonManager.js +257 -0
- package/dist/services/daemon/PodmanDaemonManager.js +369 -0
- package/dist/services/daemon/SystemdDaemonManager.js +221 -0
- package/dist/services/daemon/WindowsServiceDaemonManager.js +210 -0
- package/dist/services/daemon/index.js +16 -0
- package/dist/services/edgible.js +3060 -0
- package/dist/services/gateway/GatewayService.js +334 -0
- package/dist/state/config.js +146 -0
- package/dist/types/AgentConfig.js +5 -0
- package/dist/types/AgentStatus.js +5 -0
- package/dist/types/ApiClient.js +5 -0
- package/dist/types/ApiRequests.js +5 -0
- package/dist/types/ApiResponses.js +5 -0
- package/dist/types/Application.js +5 -0
- package/dist/types/CaddyJson.js +5 -0
- package/dist/types/UnifiedAgentStatus.js +56 -0
- package/dist/types/WireGuard.js +5 -0
- package/dist/types/Workload.js +5 -0
- package/dist/types/agent.js +5 -0
- package/dist/types/command-options.js +5 -0
- package/dist/types/connectivity.js +5 -0
- package/dist/types/errors.js +250 -0
- package/dist/types/gateway-types.js +5 -0
- package/dist/types/index.js +48 -0
- package/dist/types/models/ApplicationData.js +5 -0
- package/dist/types/models/CertificateData.js +5 -0
- package/dist/types/models/DeviceData.js +5 -0
- package/dist/types/models/DevicePoolData.js +5 -0
- package/dist/types/models/OrganizationData.js +5 -0
- package/dist/types/models/OrganizationInviteData.js +5 -0
- package/dist/types/models/ProviderConfiguration.js +5 -0
- package/dist/types/models/ResourceData.js +5 -0
- package/dist/types/models/ServiceResourceData.js +5 -0
- package/dist/types/models/UserData.js +5 -0
- package/dist/types/route.js +5 -0
- package/dist/types/validation/schemas.js +218 -0
- package/dist/types/validation.js +5 -0
- package/dist/utils/FileIntegrityManager.js +256 -0
- package/dist/utils/PathMigration.js +219 -0
- package/dist/utils/PathResolver.js +235 -0
- package/dist/utils/PlatformDetector.js +277 -0
- package/dist/utils/console-logger.js +130 -0
- package/dist/utils/docker-compose-parser.js +179 -0
- package/dist/utils/errors.js +130 -0
- package/dist/utils/health-checker.js +155 -0
- package/dist/utils/json-logger.js +72 -0
- package/dist/utils/log-formatter.js +293 -0
- package/dist/utils/logger.js +59 -0
- package/dist/utils/network-utils.js +217 -0
- package/dist/utils/output.js +182 -0
- package/dist/utils/passwordValidation.js +91 -0
- package/dist/utils/progress.js +167 -0
- package/dist/utils/sudo-checker.js +22 -0
- package/dist/utils/urls.js +32 -0
- package/dist/utils/validation.js +31 -0
- package/dist/validation/schemas.js +175 -0
- package/dist/validation/validator.js +67 -0
- package/package.json +83 -0
|
@@ -0,0 +1,256 @@
|
|
|
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.FileIntegrityManager = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const crypto_1 = require("crypto");
|
|
40
|
+
class FileIntegrityManager {
|
|
41
|
+
/**
|
|
42
|
+
* Check file integrity with multiple validation methods
|
|
43
|
+
*/
|
|
44
|
+
static async checkFileIntegrity(filePath) {
|
|
45
|
+
try {
|
|
46
|
+
// Check if file exists
|
|
47
|
+
const stats = await fs.stat(filePath);
|
|
48
|
+
// Read file content
|
|
49
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
50
|
+
// Validate JSON structure
|
|
51
|
+
let parsedContent;
|
|
52
|
+
try {
|
|
53
|
+
parsedContent = JSON.parse(content);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
isValid: false,
|
|
58
|
+
checksum: '',
|
|
59
|
+
size: stats.size,
|
|
60
|
+
lastModified: stats.mtime.getTime(),
|
|
61
|
+
error: 'Invalid JSON format'
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
// Calculate checksum
|
|
65
|
+
const checksum = (0, crypto_1.createHash)('sha256').update(content).digest('hex').substring(0, 16);
|
|
66
|
+
// Check for required fields if it's a status file
|
|
67
|
+
if (filePath.includes('status.json')) {
|
|
68
|
+
const requiredFields = ['running', 'health', 'timestamp', 'pid'];
|
|
69
|
+
for (const field of requiredFields) {
|
|
70
|
+
if (parsedContent[field] === undefined) {
|
|
71
|
+
return {
|
|
72
|
+
isValid: false,
|
|
73
|
+
checksum,
|
|
74
|
+
size: stats.size,
|
|
75
|
+
lastModified: stats.mtime.getTime(),
|
|
76
|
+
error: `Missing required field: ${field}`
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Check file age (not older than 1 hour)
|
|
82
|
+
const age = Date.now() - stats.mtime.getTime();
|
|
83
|
+
if (age > 3600000) { // 1 hour
|
|
84
|
+
return {
|
|
85
|
+
isValid: false,
|
|
86
|
+
checksum,
|
|
87
|
+
size: stats.size,
|
|
88
|
+
lastModified: stats.mtime.getTime(),
|
|
89
|
+
error: 'File is too old'
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
isValid: true,
|
|
94
|
+
checksum,
|
|
95
|
+
size: stats.size,
|
|
96
|
+
lastModified: stats.mtime.getTime()
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return {
|
|
101
|
+
isValid: false,
|
|
102
|
+
checksum: '',
|
|
103
|
+
size: 0,
|
|
104
|
+
lastModified: 0,
|
|
105
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Safely read JSON file with integrity check
|
|
111
|
+
*/
|
|
112
|
+
static async readJsonFileSafely(filePath) {
|
|
113
|
+
try {
|
|
114
|
+
const integrity = await this.checkFileIntegrity(filePath);
|
|
115
|
+
if (!integrity.isValid) {
|
|
116
|
+
return {
|
|
117
|
+
data: null,
|
|
118
|
+
isValid: false,
|
|
119
|
+
error: integrity.error
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
123
|
+
const data = JSON.parse(content);
|
|
124
|
+
return {
|
|
125
|
+
data,
|
|
126
|
+
isValid: true
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
return {
|
|
131
|
+
data: null,
|
|
132
|
+
isValid: false,
|
|
133
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Safely write JSON file with atomic operation
|
|
139
|
+
*/
|
|
140
|
+
static async writeJsonFileSafely(filePath, data) {
|
|
141
|
+
try {
|
|
142
|
+
const tempFile = `${filePath}.tmp`;
|
|
143
|
+
const backupFile = `${filePath}.backup`;
|
|
144
|
+
// Create backup if file exists
|
|
145
|
+
try {
|
|
146
|
+
await fs.copyFile(filePath, backupFile);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// Backup failed, but continue
|
|
150
|
+
console.warn('Failed to create backup file:', error);
|
|
151
|
+
}
|
|
152
|
+
// Write to temporary file
|
|
153
|
+
const jsonContent = JSON.stringify(data, null, 2);
|
|
154
|
+
await fs.writeFile(tempFile, jsonContent, 'utf8');
|
|
155
|
+
// Atomic move
|
|
156
|
+
await fs.rename(tempFile, filePath);
|
|
157
|
+
// Clean up backup after successful write
|
|
158
|
+
try {
|
|
159
|
+
await fs.unlink(backupFile);
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
// Ignore cleanup errors
|
|
163
|
+
}
|
|
164
|
+
return { success: true };
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
// Try to restore from backup if write failed
|
|
168
|
+
try {
|
|
169
|
+
const backupFile = `${filePath}.backup`;
|
|
170
|
+
await fs.copyFile(backupFile, filePath);
|
|
171
|
+
console.log('Restored file from backup');
|
|
172
|
+
}
|
|
173
|
+
catch (restoreError) {
|
|
174
|
+
console.error('Failed to restore from backup:', restoreError);
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
success: false,
|
|
178
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Clean up corrupted files
|
|
184
|
+
*/
|
|
185
|
+
static async cleanupCorruptedFiles(directory) {
|
|
186
|
+
try {
|
|
187
|
+
const files = await fs.readdir(directory);
|
|
188
|
+
for (const file of files) {
|
|
189
|
+
if (file.endsWith('.json')) {
|
|
190
|
+
const filePath = path.join(directory, file);
|
|
191
|
+
const integrity = await this.checkFileIntegrity(filePath);
|
|
192
|
+
if (!integrity.isValid) {
|
|
193
|
+
console.warn(`Cleaning up corrupted file: ${file}`);
|
|
194
|
+
// Try to restore from backup
|
|
195
|
+
const backupFile = `${filePath}.backup`;
|
|
196
|
+
try {
|
|
197
|
+
await fs.copyFile(backupFile, filePath);
|
|
198
|
+
console.log(`Restored ${file} from backup`);
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
// If no backup, remove corrupted file
|
|
202
|
+
await fs.unlink(filePath);
|
|
203
|
+
console.log(`Removed corrupted file: ${file}`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
console.error('Failed to cleanup corrupted files:', error);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Create file lock to prevent concurrent access
|
|
215
|
+
*/
|
|
216
|
+
static async withFileLock(filePath, operation) {
|
|
217
|
+
const lockFile = `${filePath}.lock`;
|
|
218
|
+
const maxWait = 5000; // 5 seconds
|
|
219
|
+
const checkInterval = 100; // 100ms
|
|
220
|
+
let waited = 0;
|
|
221
|
+
// Wait for lock to be released
|
|
222
|
+
while (waited < maxWait) {
|
|
223
|
+
try {
|
|
224
|
+
await fs.access(lockFile);
|
|
225
|
+
// Lock exists, wait
|
|
226
|
+
await new Promise(resolve => setTimeout(resolve, checkInterval));
|
|
227
|
+
waited += checkInterval;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// Lock doesn't exist, we can proceed
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (waited >= maxWait) {
|
|
235
|
+
throw new Error('File lock timeout - another process may be using the file');
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
// Create lock
|
|
239
|
+
await fs.writeFile(lockFile, process.pid.toString());
|
|
240
|
+
// Perform operation
|
|
241
|
+
const result = await operation();
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
// Remove lock
|
|
246
|
+
try {
|
|
247
|
+
await fs.unlink(lockFile);
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
// Ignore lock cleanup errors
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
exports.FileIntegrityManager = FileIntegrityManager;
|
|
256
|
+
//# sourceMappingURL=FileIntegrityManager.js.map
|
|
@@ -0,0 +1,219 @@
|
|
|
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.PathMigration = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const os = __importStar(require("os"));
|
|
40
|
+
const PathResolver_1 = require("./PathResolver");
|
|
41
|
+
/**
|
|
42
|
+
* PathMigration utility handles migration from legacy ~/.edgible paths
|
|
43
|
+
* to the new XDG/platform-specific paths.
|
|
44
|
+
*/
|
|
45
|
+
class PathMigration {
|
|
46
|
+
/**
|
|
47
|
+
* Check if legacy paths exist
|
|
48
|
+
*/
|
|
49
|
+
static hasLegacyPaths() {
|
|
50
|
+
const legacyPath = path.join(os.homedir(), '.edgible');
|
|
51
|
+
return fs.existsSync(legacyPath);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the legacy config path
|
|
55
|
+
*/
|
|
56
|
+
static getLegacyConfigPath() {
|
|
57
|
+
return path.join(os.homedir(), '.edgible', 'config.json');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the legacy agent path
|
|
61
|
+
*/
|
|
62
|
+
static getLegacyAgentPath() {
|
|
63
|
+
return path.join(os.homedir(), '.edgible', 'agent');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Migrate configuration from legacy paths to new paths
|
|
67
|
+
*
|
|
68
|
+
* @returns true if migration was successful or not needed, false if migration failed
|
|
69
|
+
*/
|
|
70
|
+
static async migrateConfig() {
|
|
71
|
+
try {
|
|
72
|
+
const legacyConfigPath = this.getLegacyConfigPath();
|
|
73
|
+
const newConfigPath = PathResolver_1.PathResolver.getCliConfigPath();
|
|
74
|
+
const newConfigDir = path.dirname(newConfigPath);
|
|
75
|
+
// Check if legacy config exists
|
|
76
|
+
if (!fs.existsSync(legacyConfigPath)) {
|
|
77
|
+
return true; // No migration needed
|
|
78
|
+
}
|
|
79
|
+
// Check if new config already exists
|
|
80
|
+
if (fs.existsSync(newConfigPath)) {
|
|
81
|
+
// Both exist - check if they're different
|
|
82
|
+
const legacyContent = fs.readFileSync(legacyConfigPath, 'utf8');
|
|
83
|
+
const newContent = fs.readFileSync(newConfigPath, 'utf8');
|
|
84
|
+
if (legacyContent === newContent) {
|
|
85
|
+
// Same content, migration already done
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
// Different content - backup new and use legacy
|
|
89
|
+
const backupPath = `${newConfigPath}.backup.${Date.now()}`;
|
|
90
|
+
fs.copyFileSync(newConfigPath, backupPath);
|
|
91
|
+
}
|
|
92
|
+
// Ensure new directory exists
|
|
93
|
+
if (!fs.existsSync(newConfigDir)) {
|
|
94
|
+
fs.mkdirSync(newConfigDir, { recursive: true });
|
|
95
|
+
}
|
|
96
|
+
// Copy config file
|
|
97
|
+
fs.copyFileSync(legacyConfigPath, newConfigPath);
|
|
98
|
+
// Preserve permissions
|
|
99
|
+
try {
|
|
100
|
+
const legacyStats = fs.statSync(legacyConfigPath);
|
|
101
|
+
fs.chmodSync(newConfigPath, legacyStats.mode);
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Ignore permission errors
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.warn('Failed to migrate config:', error);
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Migrate agent data from legacy paths to new paths
|
|
115
|
+
*
|
|
116
|
+
* @returns true if migration was successful or not needed, false if migration failed
|
|
117
|
+
*/
|
|
118
|
+
static async migrateAgentData() {
|
|
119
|
+
try {
|
|
120
|
+
const legacyAgentPath = this.getLegacyAgentPath();
|
|
121
|
+
const newAgentPath = PathResolver_1.PathResolver.getAgentConfigPath(false); // User path for CLI
|
|
122
|
+
// Check if legacy agent path exists
|
|
123
|
+
if (!fs.existsSync(legacyAgentPath)) {
|
|
124
|
+
return true; // No migration needed
|
|
125
|
+
}
|
|
126
|
+
// Check if new agent path already exists
|
|
127
|
+
if (fs.existsSync(newAgentPath)) {
|
|
128
|
+
// Both exist - skip migration to avoid overwriting
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
// Ensure new directory exists
|
|
132
|
+
if (!fs.existsSync(path.dirname(newAgentPath))) {
|
|
133
|
+
fs.mkdirSync(path.dirname(newAgentPath), { recursive: true });
|
|
134
|
+
}
|
|
135
|
+
// Copy entire agent directory
|
|
136
|
+
this.copyDirectory(legacyAgentPath, newAgentPath);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.warn('Failed to migrate agent data:', error);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Perform full migration from legacy paths to new paths
|
|
146
|
+
*
|
|
147
|
+
* @returns Migration result with details
|
|
148
|
+
*/
|
|
149
|
+
static async migrate() {
|
|
150
|
+
const result = {
|
|
151
|
+
success: true,
|
|
152
|
+
migrated: [],
|
|
153
|
+
errors: []
|
|
154
|
+
};
|
|
155
|
+
if (!this.hasLegacyPaths()) {
|
|
156
|
+
return result; // No legacy paths to migrate
|
|
157
|
+
}
|
|
158
|
+
// Migrate config
|
|
159
|
+
try {
|
|
160
|
+
if (await this.migrateConfig()) {
|
|
161
|
+
result.migrated.push('config');
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
result.errors.push('Failed to migrate config');
|
|
165
|
+
result.success = false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
result.errors.push(`Config migration error: ${error instanceof Error ? error.message : String(error)}`);
|
|
170
|
+
result.success = false;
|
|
171
|
+
}
|
|
172
|
+
// Migrate agent data
|
|
173
|
+
try {
|
|
174
|
+
if (await this.migrateAgentData()) {
|
|
175
|
+
result.migrated.push('agent-data');
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
result.errors.push('Failed to migrate agent data');
|
|
179
|
+
result.success = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
result.errors.push(`Agent data migration error: ${error instanceof Error ? error.message : String(error)}`);
|
|
184
|
+
result.success = false;
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Copy directory recursively
|
|
190
|
+
*/
|
|
191
|
+
static copyDirectory(src, dest) {
|
|
192
|
+
// Create destination directory
|
|
193
|
+
if (!fs.existsSync(dest)) {
|
|
194
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
195
|
+
}
|
|
196
|
+
// Read source directory
|
|
197
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
198
|
+
for (const entry of entries) {
|
|
199
|
+
const srcPath = path.join(src, entry.name);
|
|
200
|
+
const destPath = path.join(dest, entry.name);
|
|
201
|
+
if (entry.isDirectory()) {
|
|
202
|
+
this.copyDirectory(srcPath, destPath);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
fs.copyFileSync(srcPath, destPath);
|
|
206
|
+
// Preserve permissions
|
|
207
|
+
try {
|
|
208
|
+
const stats = fs.statSync(srcPath);
|
|
209
|
+
fs.chmodSync(destPath, stats.mode);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Ignore permission errors
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.PathMigration = PathMigration;
|
|
219
|
+
//# sourceMappingURL=PathMigration.js.map
|