@edgible-team/cli 1.2.17 → 1.2.20

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 (69) hide show
  1. package/dist/client/api-client.d.ts +13 -0
  2. package/dist/client/api-client.d.ts.map +1 -1
  3. package/dist/client/api-client.js +12 -0
  4. package/dist/commands/agent/install.d.ts.map +1 -1
  5. package/dist/commands/agent/install.js +23 -4
  6. package/dist/commands/agent/uninstall.d.ts.map +1 -1
  7. package/dist/commands/agent/uninstall.js +1 -2
  8. package/dist/commands/ai/setup.d.ts.map +1 -1
  9. package/dist/commands/ai/setup.js +1 -2
  10. package/dist/commands/application/create-stubs.d.ts +0 -1
  11. package/dist/commands/application/create-stubs.d.ts.map +1 -1
  12. package/dist/commands/application/create-stubs.js +0 -4
  13. package/dist/commands/application/create-vm.d.ts +19 -0
  14. package/dist/commands/application/create-vm.d.ts.map +1 -0
  15. package/dist/commands/application/create-vm.js +390 -0
  16. package/dist/commands/application/events.d.ts +6 -0
  17. package/dist/commands/application/events.d.ts.map +1 -0
  18. package/dist/commands/application/events.js +60 -0
  19. package/dist/commands/application/get.d.ts.map +1 -1
  20. package/dist/commands/application/get.js +29 -1
  21. package/dist/commands/application/list.d.ts.map +1 -1
  22. package/dist/commands/application/list.js +2 -0
  23. package/dist/commands/application/ssh.d.ts +7 -0
  24. package/dist/commands/application/ssh.d.ts.map +1 -0
  25. package/dist/commands/application/ssh.js +146 -0
  26. package/dist/commands/application/update.d.ts +1 -0
  27. package/dist/commands/application/update.d.ts.map +1 -1
  28. package/dist/commands/application/update.js +6 -1
  29. package/dist/commands/application.d.ts.map +1 -1
  30. package/dist/commands/application.js +62 -7
  31. package/dist/commands/auth.js +1 -1
  32. package/dist/commands/base/command-wrapper.js +1 -1
  33. package/dist/commands/config.js +2 -2
  34. package/dist/commands/debug.d.ts.map +1 -1
  35. package/dist/commands/debug.js +1 -2
  36. package/dist/commands/stack/validate.d.ts +5 -0
  37. package/dist/commands/stack/validate.d.ts.map +1 -1
  38. package/dist/commands/stack/validate.js +15 -4
  39. package/dist/commands/utils/config-validator.js +1 -1
  40. package/dist/detection/WorkloadDetector.d.ts +3 -1
  41. package/dist/detection/WorkloadDetector.d.ts.map +1 -1
  42. package/dist/scripts/postinstall.js +2 -2
  43. package/dist/services/LocalAgentManager.js +1 -1
  44. package/dist/services/application/ApplicationService.d.ts +24 -2
  45. package/dist/services/application/ApplicationService.d.ts.map +1 -1
  46. package/dist/services/application/ApplicationService.js +54 -2
  47. package/dist/services/device/DeviceService.js +1 -1
  48. package/dist/services/edgible.js +1 -1
  49. package/dist/services/stack/DependencyGraphManager.d.ts.map +1 -1
  50. package/dist/services/stack/DependencyGraphManager.js +3 -8
  51. package/dist/services/stack/StackService.d.ts.map +1 -1
  52. package/dist/services/stack/StackService.js +19 -8
  53. package/dist/types/ApiRequests.d.ts +1 -1
  54. package/dist/types/ApiRequests.d.ts.map +1 -1
  55. package/dist/types/ApiResponses.d.ts +4 -0
  56. package/dist/types/ApiResponses.d.ts.map +1 -1
  57. package/dist/types/Workload.d.ts +1 -1
  58. package/dist/types/Workload.d.ts.map +1 -1
  59. package/dist/types/models/ApplicationData.d.ts +1 -1
  60. package/dist/types/models/ApplicationData.d.ts.map +1 -1
  61. package/dist/types/stack.d.ts +9 -1
  62. package/dist/types/stack.d.ts.map +1 -1
  63. package/dist/types/validation/schemas.d.ts +45 -5
  64. package/dist/types/validation/schemas.d.ts.map +1 -1
  65. package/dist/types/validation/schemas.js +10 -1
  66. package/dist/validation/stack-schemas.d.ts +319 -27
  67. package/dist/validation/stack-schemas.d.ts.map +1 -1
  68. package/dist/validation/stack-schemas.js +20 -5
  69. package/package.json +1 -1
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.handleApplicationEvents = handleApplicationEvents;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const instances_1 = require("../../services/instances");
9
+ const config_validator_1 = require("../utils/config-validator");
10
+ const application_prompt_1 = require("../utils/application-prompt");
11
+ function formatTimestamp(ms) {
12
+ return new Date(ms).toISOString().replace('T', ' ').replace('Z', ' UTC');
13
+ }
14
+ function eventTypeColor(eventType) {
15
+ if (eventType.includes('error') || eventType.includes('stopped'))
16
+ return chalk_1.default.red;
17
+ if (eventType.includes('started') || eventType.includes('ready'))
18
+ return chalk_1.default.green;
19
+ if (eventType.includes('deploying') || eventType.includes('pending'))
20
+ return chalk_1.default.yellow;
21
+ return chalk_1.default.white;
22
+ }
23
+ async function handleApplicationEvents(options) {
24
+ (0, config_validator_1.validateConfig)(instances_1.configManager, {
25
+ requireAuth: true,
26
+ requireOrganization: true,
27
+ });
28
+ const appId = await (0, application_prompt_1.getApplicationId)(instances_1.applicationService, options.appId, {
29
+ message: 'Select application to view events for:',
30
+ required: true,
31
+ });
32
+ if (!appId) {
33
+ throw new Error('Application ID is required');
34
+ }
35
+ const limit = options.limit ? parseInt(options.limit, 10) : 50;
36
+ const events = await instances_1.applicationService.getApplicationLifecycleEvents(appId, limit);
37
+ if (options.json) {
38
+ console.log(JSON.stringify(events, null, 2));
39
+ return;
40
+ }
41
+ if (events.length === 0) {
42
+ console.log(chalk_1.default.yellow('No lifecycle events found for this application'));
43
+ return;
44
+ }
45
+ console.log(chalk_1.default.bold(`Lifecycle events for application ${appId}`) + chalk_1.default.gray(` (${events.length} events)\n`));
46
+ for (const event of events) {
47
+ const color = eventTypeColor(event.eventType ?? '');
48
+ const time = chalk_1.default.gray(formatTimestamp(event.timestamp));
49
+ const source = chalk_1.default.gray(`[${event.source ?? 'unknown'}]`);
50
+ const action = color(event.eventAction ?? event.eventType);
51
+ console.log(`${time} ${source} ${action}`);
52
+ if (event.message) {
53
+ console.log(` ${event.message}`);
54
+ }
55
+ if (event.metadata && Object.keys(event.metadata).length > 0) {
56
+ console.log(chalk_1.default.gray(` ${JSON.stringify(event.metadata)}`));
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/application/get.ts"],"names":[],"mappings":"AAMA,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmCrG"}
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/application/get.ts"],"names":[],"mappings":"AAMA,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CrG"}
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.handleApplicationGet = handleApplicationGet;
7
+ const chalk_1 = __importDefault(require("chalk"));
4
8
  const instances_1 = require("../../services/instances");
5
9
  const config_validator_1 = require("../utils/config-validator");
6
10
  const output_formatter_1 = require("../utils/output-formatter");
@@ -18,7 +22,10 @@ async function handleApplicationGet(options) {
18
22
  throw new Error('Application ID is required');
19
23
  }
20
24
  instances_1.logger.debug('Getting application', { appId });
21
- const app = await instances_1.applicationService.getApplication(appId);
25
+ const [app, details] = await Promise.all([
26
+ instances_1.applicationService.getApplication(appId),
27
+ instances_1.applicationService.getApplicationDetails(appId),
28
+ ]);
22
29
  if (options.json) {
23
30
  console.log(JSON.stringify({
24
31
  id: app.id,
@@ -29,12 +36,33 @@ async function handleApplicationGet(options) {
29
36
  port: app.port,
30
37
  protocol: app.protocol,
31
38
  status: app.status,
39
+ subtype: details.subtype,
40
+ configuration: details.configuration,
32
41
  workloadId: app.workloadId || '',
33
42
  createdAt: app.createdAt,
34
43
  }, null, 2));
35
44
  }
36
45
  else {
37
46
  console.log((0, output_formatter_1.formatApplication)(app));
47
+ if (details.subtype === 'vm') {
48
+ printVmDetails(details.configuration ?? {}, app.id);
49
+ }
38
50
  }
39
51
  }
52
+ function printVmDetails(cfg, appId) {
53
+ console.log(chalk_1.default.blue('\nVM Details:'));
54
+ if (cfg.vmBackend)
55
+ console.log(chalk_1.default.gray(` Backend: ${cfg.vmBackend}`));
56
+ if (cfg.diskImage)
57
+ console.log(chalk_1.default.gray(` Disk image: ${cfg.diskImage}`));
58
+ if (cfg.memory)
59
+ console.log(chalk_1.default.gray(` Memory: ${cfg.memory} MiB`));
60
+ if (cfg.cpus)
61
+ console.log(chalk_1.default.gray(` CPUs: ${cfg.cpus}`));
62
+ if (cfg.sshPort)
63
+ console.log(chalk_1.default.gray(` SSH port: ${cfg.sshPort}`));
64
+ if (cfg.vmArch)
65
+ console.log(chalk_1.default.gray(` Arch: ${cfg.vmArch}`));
66
+ console.log(chalk_1.default.gray(` SSH access: edgible application ssh --id ${appId}`));
67
+ }
40
68
  //# sourceMappingURL=get.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/application/list.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCtF"}
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/commands/application/list.ts"],"names":[],"mappings":"AAKA,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyCtF"}
@@ -28,6 +28,8 @@ async function handleApplicationList(options) {
28
28
  servingIp: app.servingIp,
29
29
  port: app.port,
30
30
  protocol: app.protocol,
31
+ subtype: app.subtype,
32
+ configuration: app.configuration,
31
33
  status: app.status,
32
34
  workloadId: app.workloadId,
33
35
  createdAt: app.createdAt,
@@ -0,0 +1,7 @@
1
+ export declare function handleApplicationSsh(options: {
2
+ id?: string;
3
+ user?: string;
4
+ key?: string;
5
+ command?: string;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=ssh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssh.d.ts","sourceRoot":"","sources":["../../../src/commands/application/ssh.ts"],"names":[],"mappings":"AAQA,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6EhB"}
@@ -0,0 +1,146 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.handleApplicationSsh = handleApplicationSsh;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const child_process_1 = require("child_process");
42
+ const fs_1 = require("fs");
43
+ const os = __importStar(require("os"));
44
+ const path = __importStar(require("path"));
45
+ const instances_1 = require("../../services/instances");
46
+ const config_validator_1 = require("../utils/config-validator");
47
+ async function handleApplicationSsh(options) {
48
+ (0, config_validator_1.validateConfig)(instances_1.configManager, {
49
+ requireAuth: true,
50
+ requireOrganization: true,
51
+ });
52
+ const appId = options.id;
53
+ if (!appId)
54
+ throw new Error('--id is required');
55
+ console.log(chalk_1.default.gray(`Fetching application ${appId}...`));
56
+ const app = await instances_1.applicationService.getApplicationDetails(appId);
57
+ if (app.subtype !== 'vm') {
58
+ throw new Error(`Application "${app.name}" is not a VM application (subtype: ${app.subtype}). ` +
59
+ `Only vm applications support SSH access via this command.`);
60
+ }
61
+ const sshPort = Number(app.configuration?.sshPort) || 2222;
62
+ const sshUser = options.user ?? 'ubuntu';
63
+ // Resolve target host from serving device WireGuard IP
64
+ const deviceConfigs = (app.deviceApplicationConfigs ?? {});
65
+ const servingEntry = Object.values(deviceConfigs).find((c) => c.deviceType === 'serving' && c.deviceIp);
66
+ if (!servingEntry?.deviceIp) {
67
+ throw new Error(`Could not resolve serving device IP for application "${app.name}". ` +
68
+ `Ensure the agent is registered, connected, and the application is deployed.`);
69
+ }
70
+ const targetHost = servingEntry.deviceIp;
71
+ // Resolve the private key: explicit --key flag → auto-fetch from backend → error
72
+ let resolvedKeyPath = options.key;
73
+ let tempKeyPath;
74
+ if (!resolvedKeyPath) {
75
+ console.log(chalk_1.default.gray('No --key provided, fetching SSH key from backend...'));
76
+ try {
77
+ const privateKey = await instances_1.applicationService.getApplicationVmSshKey(appId);
78
+ if (privateKey) {
79
+ tempKeyPath = path.join(os.tmpdir(), `edgible-vm-ssh-${appId}-${Date.now()}.pem`);
80
+ await fs_1.promises.writeFile(tempKeyPath, privateKey, { mode: 0o600, encoding: 'utf-8' });
81
+ resolvedKeyPath = tempKeyPath;
82
+ console.log(chalk_1.default.gray('SSH key retrieved from backend.'));
83
+ }
84
+ }
85
+ catch (err) {
86
+ instances_1.logger.debug('Failed to auto-fetch VM SSH key', err);
87
+ }
88
+ }
89
+ if (!resolvedKeyPath) {
90
+ throw new Error('No SSH key available. Either:\n' +
91
+ ' - Pass --key <path> to your private key, or\n' +
92
+ ' - Re-create the application with --ssh-public-key to inject a key via cloud-init.');
93
+ }
94
+ try {
95
+ await runSshSession({
96
+ host: targetHost,
97
+ port: sshPort,
98
+ user: sshUser,
99
+ keyPath: resolvedKeyPath,
100
+ command: options.command,
101
+ });
102
+ }
103
+ finally {
104
+ if (tempKeyPath) {
105
+ try {
106
+ await fs_1.promises.unlink(tempKeyPath);
107
+ }
108
+ catch { /* already gone */ }
109
+ }
110
+ }
111
+ }
112
+ async function runSshSession(opts) {
113
+ const { host, port, user, keyPath, command } = opts;
114
+ const sshArgs = [
115
+ '-o', 'StrictHostKeyChecking=no',
116
+ '-o', 'UserKnownHostsFile=/dev/null',
117
+ '-p', String(port),
118
+ ];
119
+ if (keyPath)
120
+ sshArgs.push('-i', keyPath);
121
+ sshArgs.push(`${user}@${host}`);
122
+ if (command)
123
+ sshArgs.push(command);
124
+ console.log(chalk_1.default.blue(`\nConnecting to VM: ${user}@${host}:${port}`));
125
+ if (!command) {
126
+ console.log(chalk_1.default.yellow('Opening interactive SSH session...\n'));
127
+ console.log(chalk_1.default.gray('Tip: Type "exit" to disconnect\n'));
128
+ }
129
+ const proc = (0, child_process_1.spawn)('ssh', sshArgs, { stdio: 'inherit' });
130
+ await new Promise((resolve, reject) => {
131
+ proc.on('error', (err) => {
132
+ instances_1.logger.error('SSH error', err);
133
+ console.error(chalk_1.default.red('✗ SSH error:'), err.message);
134
+ reject(err);
135
+ });
136
+ proc.on('exit', (code) => {
137
+ if (!command)
138
+ console.log(chalk_1.default.gray('\nSSH session ended'));
139
+ if (code === 0 || code === null)
140
+ resolve();
141
+ else
142
+ reject(new Error(`SSH exited with code ${code}`));
143
+ });
144
+ });
145
+ }
146
+ //# sourceMappingURL=ssh.js.map
@@ -3,5 +3,6 @@ export declare function handleApplicationUpdate(options: {
3
3
  name?: string;
4
4
  authModes?: string;
5
5
  allowedOrgs?: string;
6
+ targetState?: string;
6
7
  }): Promise<void>;
7
8
  //# sourceMappingURL=update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/application/update.ts"],"names":[],"mappings":"AAMA,wBAAsB,uBAAuB,CAAC,OAAO,EAAE;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhB"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/commands/application/update.ts"],"names":[],"mappings":"AAMA,wBAAsB,uBAAuB,CAAC,OAAO,EAAE;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DhB"}
@@ -37,8 +37,11 @@ async function handleApplicationUpdate(options) {
37
37
  .map((s) => s.trim())
38
38
  .filter(Boolean);
39
39
  }
40
+ if (options.targetState !== undefined && options.targetState.trim().length > 0) {
41
+ updates.targetState = options.targetState.trim();
42
+ }
40
43
  if (Object.keys(updates).length === 0) {
41
- console.log(chalk_1.default.yellow('No updates specified. Use --name, --auth-modes, or --allowed-orgs.'));
44
+ console.log(chalk_1.default.yellow('No updates specified. Use --name, --auth-modes, --allowed-orgs, or --target-state.'));
42
45
  return;
43
46
  }
44
47
  instances_1.logger.debug('Updating application', { appId, updates });
@@ -51,5 +54,7 @@ async function handleApplicationUpdate(options) {
51
54
  if (updates.allowedOrganizations && updates.allowedOrganizations.length > 0) {
52
55
  console.log(chalk_1.default.gray(` Allowed organizations: ${updates.allowedOrganizations.join(', ')}`));
53
56
  }
57
+ if (updates.targetState)
58
+ console.log(chalk_1.default.gray(` Target state: ${updates.targetState}`));
54
59
  }
55
60
  //# sourceMappingURL=update.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/commands/application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkBpC;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+Z/D"}
1
+ {"version":3,"file":"application.d.ts","sourceRoot":"","sources":["../../src/commands/application.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+e/D"}
@@ -11,6 +11,9 @@ const create_existing_1 = require("./application/create-existing");
11
11
  const create_docker_compose_1 = require("./application/create-docker-compose");
12
12
  const create_managed_process_1 = require("./application/create-managed-process");
13
13
  const create_stubs_1 = require("./application/create-stubs");
14
+ const create_vm_1 = require("./application/create-vm");
15
+ const ssh_1 = require("./application/ssh");
16
+ const events_1 = require("./application/events");
14
17
  const list_2 = require("./application/api-keys/list");
15
18
  const create_1 = require("./application/api-keys/create");
16
19
  const delete_2 = require("./application/api-keys/delete");
@@ -132,13 +135,33 @@ Examples:
132
135
  requireAuth: false,
133
136
  requireOrganization: false,
134
137
  }));
135
- const createQemuCommand = new commander_1.Command('qemu')
136
- .description('Create application from QEMU VM (not implemented)')
137
- .action((0, command_wrapper_1.wrapCommand)(async () => {
138
- await (0, create_stubs_1.handleApplicationCreateQemu)();
138
+ const createVmCommand = new commander_1.Command('vm')
139
+ .description('Create a VM application (managed by the agent via QEMU or other backends)')
140
+ .addHelpText('after', `
141
+ Examples:
142
+ $ edgible application create vm --name my-vm --backend qemu --disk-image /var/lib/vms/ubuntu.qcow2 --device-id <id>
143
+ $ edgible application create vm --non-interactive --name my-vm --backend qemu --disk-image /path/to/disk.qcow2 --memory 1024 --cpus 2 --ssh-port 2222 --device-id <id>
144
+ `)
145
+ .option('-n, --name <name>', 'Application name')
146
+ .option('-d, --description <description>', 'Application description')
147
+ .option('--backend <backend>', 'VM backend (qemu)', 'qemu')
148
+ .option('--disk-image <path>', 'Disk image path or URL')
149
+ .option('--memory <mib>', 'Memory in MiB (default: 512)')
150
+ .option('--cpus <count>', 'Number of CPUs (default: 1)')
151
+ .option('--ssh-port <port>', 'Host port forwarded to VM port 22 (default: 2222)')
152
+ .option('--ssh-public-key <key>', 'SSH public key to inject via cloud-init')
153
+ .option('--arch <arch>', 'VM architecture: x86_64 or aarch64 (default: x86_64)')
154
+ .option('--device-id <id>', 'Serving device ID')
155
+ .option('--gateway-ids <ids>', 'Comma-separated gateway device IDs')
156
+ .option('--hostnames <hostnames>', 'Comma-separated additional hostnames')
157
+ .option('--auth-modes <modes>', 'Auth modes: none, org, api-key')
158
+ .option('--allowed-orgs <ids>', 'Comma-separated allowed organization IDs')
159
+ .option('--non-interactive', 'Run in non-interactive mode')
160
+ .action((0, command_wrapper_1.wrapCommand)(async (options) => {
161
+ await (0, create_vm_1.handleApplicationCreateVm)(options);
139
162
  }, {
140
- requireAuth: false,
141
- requireOrganization: false,
163
+ requireAuth: true,
164
+ requireOrganization: true,
142
165
  }));
143
166
  const createPodmanCommand = new commander_1.Command('podman')
144
167
  .description('Create application from Podman container (not implemented)')
@@ -153,7 +176,7 @@ Examples:
153
176
  createCommand.addCommand(createDockerComposeCommand);
154
177
  createCommand.addCommand(createManagedProcessCommand);
155
178
  createCommand.addCommand(createDockerCommand);
156
- createCommand.addCommand(createQemuCommand);
179
+ createCommand.addCommand(createVmCommand);
157
180
  createCommand.addCommand(createPodmanCommand);
158
181
  appCommand
159
182
  .command('get')
@@ -168,6 +191,18 @@ Examples:
168
191
  requireAuth: true,
169
192
  requireOrganization: true,
170
193
  }));
194
+ appCommand
195
+ .command('events')
196
+ .description('Show lifecycle events for an application')
197
+ .option('-i, --app-id <id>', 'Application ID')
198
+ .option('-n, --limit <number>', 'Maximum number of events to return', '50')
199
+ .option('--json', 'Output as JSON')
200
+ .action((0, command_wrapper_1.wrapCommand)(async (options) => {
201
+ await (0, events_1.handleApplicationEvents)(options);
202
+ }, {
203
+ requireAuth: true,
204
+ requireOrganization: true,
205
+ }));
171
206
  appCommand
172
207
  .command('update')
173
208
  .description('Update an existing application (e.g. auth modes, name)')
@@ -175,6 +210,7 @@ Examples:
175
210
  .option('-n, --name <name>', 'Application name')
176
211
  .option('--auth-modes <modes>', 'Auth modes: none, org, api-key (comma-separated for multiple)')
177
212
  .option('--allowed-orgs <ids>', 'Comma-separated organization IDs allowed (when org auth is used)')
213
+ .option('--target-state <state>', 'Target lifecycle state: running, suspended')
178
214
  .action((0, command_wrapper_1.wrapCommand)(async (options) => {
179
215
  await (0, update_1.handleApplicationUpdate)(options);
180
216
  }, {
@@ -293,5 +329,24 @@ Examples:
293
329
  requireAuth: true,
294
330
  requireOrganization: true,
295
331
  }));
332
+ appCommand
333
+ .command('ssh')
334
+ .description('Open an SSH session to a VM application')
335
+ .addHelpText('after', `
336
+ Examples:
337
+ $ edgible application ssh --id <app-id>
338
+ $ edgible application ssh --id <app-id> --user root --key ~/.ssh/id_ed25519
339
+ $ edgible application ssh --id <app-id> --command "uname -a"
340
+ `)
341
+ .requiredOption('-i, --id <id>', 'Application ID')
342
+ .option('-u, --user <username>', 'SSH username (default: ubuntu)')
343
+ .option('-k, --key <path>', 'Path to SSH private key')
344
+ .option('--command <cmd>', 'Run a single command instead of interactive session')
345
+ .action((0, command_wrapper_1.wrapCommand)(async (options) => {
346
+ await (0, ssh_1.handleApplicationSsh)(options);
347
+ }, {
348
+ requireAuth: true,
349
+ requireOrganization: true,
350
+ }));
296
351
  }
297
352
  //# sourceMappingURL=application.js.map
@@ -365,7 +365,7 @@ async function handleUserLogin(configManager, authService, savedEmail, isFirstRu
365
365
  console.log(chalk_1.default.gray('1. Use the "edgible signup" command'));
366
366
  console.log(chalk_1.default.gray('2. Visit https://edgible.com/signup in your browser'));
367
367
  console.log(chalk_1.default.gray('3. Use device login to create a device without an account'));
368
- console.log(chalk_1.default.gray('4. Come back later and run "edgible login" again\n'));
368
+ console.log(chalk_1.default.gray('4. Come back later and run "edgible auth login" again\n'));
369
369
  }
370
370
  else {
371
371
  console.log(chalk_1.default.gray('You can create an account by visiting the Edgible website or using the signup command.'));
@@ -20,7 +20,7 @@ function wrapCommand(action, wrapperOptions = {}) {
20
20
  const hasTokens = !!(config.accessToken || config.idToken);
21
21
  const hasDeviceCreds = !!(config.deviceId && config.devicePassword);
22
22
  if (!hasTokens && !hasDeviceCreds) {
23
- throw new errors_1.ConfigError('Not authenticated. Please run "edgible login" first.');
23
+ throw new errors_1.ConfigError('Not authenticated. Please run "edgible auth login" first.');
24
24
  }
25
25
  }
26
26
  if (requireOrganization) {
@@ -71,7 +71,7 @@ function setupConfigCommands(program) {
71
71
  instances_1.configManager.clearConfig();
72
72
  instances_1.logger.info('Configuration reset (non-interactive)');
73
73
  console.log(chalk_1.default.green('✓ CLI state has been reset'));
74
- console.log(chalk_1.default.gray('Run "edgible login" to start fresh'));
74
+ console.log(chalk_1.default.gray('Run "edgible auth login" to start fresh'));
75
75
  }
76
76
  else {
77
77
  // Interactive mode: ask for confirmation
@@ -87,7 +87,7 @@ function setupConfigCommands(program) {
87
87
  instances_1.configManager.clearConfig();
88
88
  instances_1.logger.info('Configuration reset (interactive)');
89
89
  console.log(chalk_1.default.green('✓ CLI state has been reset'));
90
- console.log(chalk_1.default.gray('Run "edgible login" to start fresh'));
90
+ console.log(chalk_1.default.gray('Run "edgible auth login" to start fresh'));
91
91
  }
92
92
  else {
93
93
  instances_1.logger.debug('Configuration reset cancelled');
@@ -1 +1 @@
1
- {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAkmBzD"}
1
+ {"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../../src/commands/debug.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqmBzD"}
@@ -61,8 +61,7 @@ function setupDebugCommands(program) {
61
61
  .option('--local', 'Use local agent build from agent-v2/dist/ (development only)')
62
62
  .action((0, command_wrapper_1.wrapCommand)(async (options) => {
63
63
  if (!(0, sudo_checker_1.checkSudoPermissions)()) {
64
- console.log(chalk_1.default.redBright("Please run this command with administrator privileges (i.e. sudo)"));
65
- return;
64
+ console.log(chalk_1.default.yellow('⚠ Warning: Not running as root/sudo. Debug full-cycle steps (install, services) may fail without proper privileges.'));
66
65
  }
67
66
  console.log(chalk_1.default.blue.bold('\n═══════════════════════════════════════════'));
68
67
  console.log(chalk_1.default.blue.bold(' Full Debug Cycle'));
@@ -1,5 +1,10 @@
1
1
  /**
2
2
  * Stack validate command handler
3
+ *
4
+ * Validation is purely local (YAML parsing + dependency graph check).
5
+ * It does NOT require authentication or an organization ID.
6
+ * Use StackParser and DependencyGraphManager directly to avoid the eager
7
+ * org-ID check in getServiceInstances().
3
8
  */
4
9
  export declare function handleStackValidate(options: {
5
10
  file?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/stack/validate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCnF"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/commands/stack/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCnF"}
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  /**
3
3
  * Stack validate command handler
4
+ *
5
+ * Validation is purely local (YAML parsing + dependency graph check).
6
+ * It does NOT require authentication or an organization ID.
7
+ * Use StackParser and DependencyGraphManager directly to avoid the eager
8
+ * org-ID check in getServiceInstances().
4
9
  */
5
10
  var __importDefault = (this && this.__importDefault) || function (mod) {
6
11
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -9,14 +14,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
14
  exports.handleStackValidate = handleStackValidate;
10
15
  const chalk_1 = __importDefault(require("chalk"));
11
16
  const instances_1 = require("../../services/instances");
17
+ const StackParser_1 = require("../../services/stack/StackParser");
18
+ const DependencyGraphManager_1 = require("../../services/stack/DependencyGraphManager");
12
19
  const stack_file_1 = require("../../utils/stack-file");
13
20
  async function handleStackValidate(options) {
14
- const { stackService, logger } = (0, instances_1.getServiceInstances)();
21
+ const parser = new StackParser_1.StackParser(instances_1.logger);
22
+ const depManager = new DependencyGraphManager_1.DependencyGraphManager(instances_1.logger);
15
23
  try {
16
24
  const file = (0, stack_file_1.findStackFile)(options.file);
17
- logger.info(`Validating stack file: ${file}`);
18
- const result = await stackService.validateStack(file);
25
+ instances_1.logger.info(`Validating stack file: ${file}`);
26
+ const result = await parser.validate(file);
19
27
  if (result.valid) {
28
+ // Additional validation: dependency graph
29
+ const stack = await parser.parseFile(file);
30
+ depManager.validate(stack.applications);
20
31
  console.log(chalk_1.default.green('✓ Stack validation passed'));
21
32
  if (result.warnings.length > 0) {
22
33
  console.log(chalk_1.default.yellow('\nWarnings:'));
@@ -36,7 +47,7 @@ async function handleStackValidate(options) {
36
47
  }
37
48
  }
38
49
  catch (error) {
39
- logger.error(`Validation error: ${error instanceof Error ? error.message : 'Unknown error'}`);
50
+ instances_1.logger.error(`Validation error: ${error instanceof Error ? error.message : 'Unknown error'}`);
40
51
  console.log(chalk_1.default.red(`\n✗ Validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`));
41
52
  process.exit(1);
42
53
  }
@@ -19,7 +19,7 @@ function validateConfig(configManager, options = {}) {
19
19
  const hasTokens = !!(config.accessToken || config.idToken);
20
20
  const hasDeviceCreds = !!(config.deviceId && config.devicePassword);
21
21
  if (!hasTokens && !hasDeviceCreds) {
22
- throw new errors_1.ConfigError('Not authenticated. Please run "edgible login" first.');
22
+ throw new errors_1.ConfigError('Not authenticated. Please run "edgible auth login" first.');
23
23
  }
24
24
  }
25
25
  if (requireOrganization) {
@@ -24,7 +24,9 @@ export interface Application {
24
24
  servingIp: string;
25
25
  port: number;
26
26
  protocol: 'http' | 'https' | 'tcp' | 'udp';
27
- status: 'active' | 'inactive' | 'pending';
27
+ status: 'active' | 'inactive' | 'pending' | 'deployed' | 'error' | 'shutdown' | 'deploying' | 'unknown';
28
+ subtype?: string;
29
+ configuration?: Record<string, unknown>;
28
30
  createdAt: string;
29
31
  description?: string;
30
32
  url?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"WorkloadDetector.d.ts","sourceRoot":"","sources":["../../src/detection/WorkloadDetector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;IAC3C,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;WACiB,eAAe,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA2B1D;;OAEG;mBACkB,qBAAqB;IAmE1C;;OAEG;mBACkB,yBAAyB;IA4D9C;;OAEG;mBACkB,iBAAiB;IAsDtC;;OAEG;mBACkB,sBAAsB;IAyD3C;;OAEG;WACW,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI;IAwD3D;;OAEG;WACW,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM;CAMhE"}
1
+ {"version":3,"file":"WorkloadDetector.d.ts","sourceRoot":"","sources":["../../src/detection/WorkloadDetector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,KAAK,CAAC;IAC3C,MAAM,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;IACxG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,gBAAgB;IAC3B;;OAEG;WACiB,eAAe,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IA2B1D;;OAEG;mBACkB,qBAAqB;IAmE1C;;OAEG;mBACkB,yBAAyB;IA4D9C;;OAEG;mBACkB,iBAAiB;IAsDtC;;OAEG;mBACkB,sBAAsB;IAyD3C;;OAEG;WACW,gBAAgB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI;IAwD3D;;OAEG;WACW,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM;CAMhE"}
@@ -68,14 +68,14 @@ function main() {
68
68
  log('✅ Edgible CLI installed globally', colors.green);
69
69
  log('\n');
70
70
  log('Quick Start:', colors.bright);
71
- log(' 1. Run: edgible login', colors.gray);
71
+ log(' 1. Run: edgible auth login', colors.gray);
72
72
  log(' 2. Run: edgible --help', colors.gray);
73
73
  log('\n');
74
74
  } else {
75
75
  log('📦 Edgible CLI installed locally', colors.cyan);
76
76
  log('\n');
77
77
  log('Quick Start:', colors.bright);
78
- log(' 1. Run: npx edgible login', colors.gray);
78
+ log(' 1. Run: npx edgible auth login', colors.gray);
79
79
  log(' 2. Run: npx edgible --help', colors.gray);
80
80
  log('\n');
81
81
  log('For global access, install with: npm install -g edgible-cli', colors.gray);
@@ -745,7 +745,7 @@ class LocalAgentManager {
745
745
  provideTroubleshootingSteps(errorMessage) {
746
746
  console.log(chalk_1.default.yellow('\nTroubleshooting steps:'));
747
747
  if (errorMessage.includes('Device ID')) {
748
- console.log(' 1. Run "edgible login" to authenticate');
748
+ console.log(' 1. Run "edgible auth login" to authenticate');
749
749
  console.log(' 2. Run "edgible device-login" if using device credentials');
750
750
  }
751
751
  if (errorMessage.includes('Agent binary not found')) {