@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.
Files changed (102) hide show
  1. package/LICENSE +136 -0
  2. package/README.md +450 -0
  3. package/dist/client/api-client.js +1057 -0
  4. package/dist/client/index.js +21 -0
  5. package/dist/commands/agent.js +1280 -0
  6. package/dist/commands/ai.js +608 -0
  7. package/dist/commands/application.js +885 -0
  8. package/dist/commands/auth.js +570 -0
  9. package/dist/commands/base/BaseCommand.js +93 -0
  10. package/dist/commands/base/CommandHandler.js +7 -0
  11. package/dist/commands/base/command-wrapper.js +58 -0
  12. package/dist/commands/base/middleware.js +77 -0
  13. package/dist/commands/config.js +116 -0
  14. package/dist/commands/connectivity.js +59 -0
  15. package/dist/commands/debug.js +98 -0
  16. package/dist/commands/discover.js +144 -0
  17. package/dist/commands/examples/migrated-command-example.js +180 -0
  18. package/dist/commands/gateway.js +494 -0
  19. package/dist/commands/managedGateway.js +787 -0
  20. package/dist/commands/utils/config-validator.js +76 -0
  21. package/dist/commands/utils/gateway-prompt.js +79 -0
  22. package/dist/commands/utils/input-parser.js +120 -0
  23. package/dist/commands/utils/output-formatter.js +109 -0
  24. package/dist/config/app-config.js +99 -0
  25. package/dist/detection/SystemCapabilityDetector.js +1244 -0
  26. package/dist/detection/ToolDetector.js +305 -0
  27. package/dist/detection/WorkloadDetector.js +314 -0
  28. package/dist/di/bindings.js +99 -0
  29. package/dist/di/container.js +88 -0
  30. package/dist/di/types.js +32 -0
  31. package/dist/index.js +52 -0
  32. package/dist/interfaces/IDaemonManager.js +3 -0
  33. package/dist/repositories/config-repository.js +62 -0
  34. package/dist/repositories/gateway-repository.js +35 -0
  35. package/dist/scripts/postinstall.js +101 -0
  36. package/dist/services/AgentStatusManager.js +299 -0
  37. package/dist/services/ConnectivityTester.js +271 -0
  38. package/dist/services/DependencyInstaller.js +475 -0
  39. package/dist/services/LocalAgentManager.js +2216 -0
  40. package/dist/services/application/ApplicationService.js +299 -0
  41. package/dist/services/auth/AuthService.js +214 -0
  42. package/dist/services/aws.js +644 -0
  43. package/dist/services/daemon/DaemonManagerFactory.js +65 -0
  44. package/dist/services/daemon/DockerDaemonManager.js +395 -0
  45. package/dist/services/daemon/LaunchdDaemonManager.js +257 -0
  46. package/dist/services/daemon/PodmanDaemonManager.js +369 -0
  47. package/dist/services/daemon/SystemdDaemonManager.js +221 -0
  48. package/dist/services/daemon/WindowsServiceDaemonManager.js +210 -0
  49. package/dist/services/daemon/index.js +16 -0
  50. package/dist/services/edgible.js +3060 -0
  51. package/dist/services/gateway/GatewayService.js +334 -0
  52. package/dist/state/config.js +146 -0
  53. package/dist/types/AgentConfig.js +5 -0
  54. package/dist/types/AgentStatus.js +5 -0
  55. package/dist/types/ApiClient.js +5 -0
  56. package/dist/types/ApiRequests.js +5 -0
  57. package/dist/types/ApiResponses.js +5 -0
  58. package/dist/types/Application.js +5 -0
  59. package/dist/types/CaddyJson.js +5 -0
  60. package/dist/types/UnifiedAgentStatus.js +56 -0
  61. package/dist/types/WireGuard.js +5 -0
  62. package/dist/types/Workload.js +5 -0
  63. package/dist/types/agent.js +5 -0
  64. package/dist/types/command-options.js +5 -0
  65. package/dist/types/connectivity.js +5 -0
  66. package/dist/types/errors.js +250 -0
  67. package/dist/types/gateway-types.js +5 -0
  68. package/dist/types/index.js +48 -0
  69. package/dist/types/models/ApplicationData.js +5 -0
  70. package/dist/types/models/CertificateData.js +5 -0
  71. package/dist/types/models/DeviceData.js +5 -0
  72. package/dist/types/models/DevicePoolData.js +5 -0
  73. package/dist/types/models/OrganizationData.js +5 -0
  74. package/dist/types/models/OrganizationInviteData.js +5 -0
  75. package/dist/types/models/ProviderConfiguration.js +5 -0
  76. package/dist/types/models/ResourceData.js +5 -0
  77. package/dist/types/models/ServiceResourceData.js +5 -0
  78. package/dist/types/models/UserData.js +5 -0
  79. package/dist/types/route.js +5 -0
  80. package/dist/types/validation/schemas.js +218 -0
  81. package/dist/types/validation.js +5 -0
  82. package/dist/utils/FileIntegrityManager.js +256 -0
  83. package/dist/utils/PathMigration.js +219 -0
  84. package/dist/utils/PathResolver.js +235 -0
  85. package/dist/utils/PlatformDetector.js +277 -0
  86. package/dist/utils/console-logger.js +130 -0
  87. package/dist/utils/docker-compose-parser.js +179 -0
  88. package/dist/utils/errors.js +130 -0
  89. package/dist/utils/health-checker.js +155 -0
  90. package/dist/utils/json-logger.js +72 -0
  91. package/dist/utils/log-formatter.js +293 -0
  92. package/dist/utils/logger.js +59 -0
  93. package/dist/utils/network-utils.js +217 -0
  94. package/dist/utils/output.js +182 -0
  95. package/dist/utils/passwordValidation.js +91 -0
  96. package/dist/utils/progress.js +167 -0
  97. package/dist/utils/sudo-checker.js +22 -0
  98. package/dist/utils/urls.js +32 -0
  99. package/dist/utils/validation.js +31 -0
  100. package/dist/validation/schemas.js +175 -0
  101. package/dist/validation/validator.js +67 -0
  102. 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