@edgible-team/cli 1.2.4 → 1.2.8
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/commands/agent/agent-handlers.d.ts +45 -0
- package/dist/commands/agent/agent-handlers.d.ts.map +1 -0
- package/dist/commands/agent/agent-handlers.js +1159 -0
- package/dist/commands/agent/install.d.ts +11 -0
- package/dist/commands/agent/install.d.ts.map +1 -0
- package/dist/commands/agent/install.js +399 -0
- package/dist/commands/agent/logs.d.ts +12 -0
- package/dist/commands/agent/logs.d.ts.map +1 -0
- package/dist/commands/agent/logs.js +77 -0
- package/dist/commands/agent/restart.d.ts +4 -0
- package/dist/commands/agent/restart.d.ts.map +1 -0
- package/dist/commands/agent/restart.js +33 -0
- package/dist/commands/agent/set-log-level.d.ts +8 -0
- package/dist/commands/agent/set-log-level.d.ts.map +1 -0
- package/dist/commands/agent/set-log-level.js +133 -0
- package/dist/commands/agent/setup.d.ts +9 -0
- package/dist/commands/agent/setup.d.ts.map +1 -0
- package/dist/commands/agent/setup.js +149 -0
- package/dist/commands/agent/start.d.ts +12 -0
- package/dist/commands/agent/start.d.ts.map +1 -0
- package/dist/commands/agent/start.js +308 -0
- package/dist/commands/agent/status.d.ts +7 -0
- package/dist/commands/agent/status.d.ts.map +1 -0
- package/dist/commands/agent/status.js +68 -0
- package/dist/commands/agent/stop.d.ts +4 -0
- package/dist/commands/agent/stop.d.ts.map +1 -0
- package/dist/commands/agent/stop.js +33 -0
- package/dist/commands/agent/uninstall.d.ts +7 -0
- package/dist/commands/agent/uninstall.d.ts.map +1 -0
- package/dist/commands/agent/uninstall.js +168 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +24 -1190
- package/dist/commands/ai/helpers.d.ts +139 -0
- package/dist/commands/ai/helpers.d.ts.map +1 -0
- package/dist/commands/ai/helpers.js +1470 -0
- package/dist/commands/ai/serve.d.ts +6 -0
- package/dist/commands/ai/serve.d.ts.map +1 -0
- package/dist/commands/ai/serve.js +124 -0
- package/dist/commands/ai/setup.d.ts +14 -0
- package/dist/commands/ai/setup.d.ts.map +1 -0
- package/dist/commands/ai/setup.js +86 -0
- package/dist/commands/ai/status.d.ts +2 -0
- package/dist/commands/ai/status.d.ts.map +1 -0
- package/dist/commands/ai/status.js +160 -0
- package/dist/commands/ai/stop.d.ts +2 -0
- package/dist/commands/ai/stop.d.ts.map +1 -0
- package/dist/commands/ai/stop.js +21 -0
- package/dist/commands/ai/teardown.d.ts +5 -0
- package/dist/commands/ai/teardown.d.ts.map +1 -0
- package/dist/commands/ai/teardown.js +78 -0
- package/dist/commands/ai/test.d.ts +4 -0
- package/dist/commands/ai/test.d.ts.map +1 -0
- package/dist/commands/ai/test.js +65 -0
- package/dist/commands/ai.d.ts.map +1 -1
- package/dist/commands/ai.js +16 -1938
- package/dist/commands/application/api-keys/create.d.ts +6 -0
- package/dist/commands/application/api-keys/create.d.ts.map +1 -0
- package/dist/commands/application/api-keys/create.js +68 -0
- package/dist/commands/application/api-keys/delete.d.ts +6 -0
- package/dist/commands/application/api-keys/delete.d.ts.map +1 -0
- package/dist/commands/application/api-keys/delete.js +79 -0
- package/dist/commands/application/api-keys/list.d.ts +5 -0
- package/dist/commands/application/api-keys/list.d.ts.map +1 -0
- package/dist/commands/application/api-keys/list.js +65 -0
- package/dist/commands/application/api-keys.d.ts +3 -0
- package/dist/commands/application/api-keys.d.ts.map +1 -0
- package/dist/commands/application/api-keys.js +227 -0
- package/dist/commands/application/create-compose.d.ts +3 -0
- package/dist/commands/application/create-compose.d.ts.map +1 -0
- package/dist/commands/application/create-compose.js +381 -0
- package/dist/commands/application/create-docker-compose.d.ts +10 -0
- package/dist/commands/application/create-docker-compose.d.ts.map +1 -0
- package/dist/commands/application/create-docker-compose.js +334 -0
- package/dist/commands/application/create-existing.d.ts +14 -0
- package/dist/commands/application/create-existing.d.ts.map +1 -0
- package/dist/commands/application/create-existing.js +359 -0
- package/dist/commands/application/create-interactive.d.ts +3 -0
- package/dist/commands/application/create-interactive.d.ts.map +1 -0
- package/dist/commands/application/create-interactive.js +326 -0
- package/dist/commands/application/create-managed-process.d.ts +15 -0
- package/dist/commands/application/create-managed-process.d.ts.map +1 -0
- package/dist/commands/application/create-managed-process.js +371 -0
- package/dist/commands/application/create-stubs.d.ts +4 -0
- package/dist/commands/application/create-stubs.d.ts.map +1 -0
- package/dist/commands/application/create-stubs.js +19 -0
- package/dist/commands/application/create-workload.d.ts +5 -0
- package/dist/commands/application/create-workload.d.ts.map +1 -0
- package/dist/commands/application/create-workload.js +48 -0
- package/dist/commands/application/delete.d.ts +6 -0
- package/dist/commands/application/delete.d.ts.map +1 -0
- package/dist/commands/application/delete.js +76 -0
- package/dist/commands/application/get.d.ts +5 -0
- package/dist/commands/application/get.d.ts.map +1 -0
- package/dist/commands/application/get.js +35 -0
- package/dist/commands/application/list.d.ts +4 -0
- package/dist/commands/application/list.d.ts.map +1 -0
- package/dist/commands/application/list.js +41 -0
- package/dist/commands/application/short-codes/create.d.ts +7 -0
- package/dist/commands/application/short-codes/create.d.ts.map +1 -0
- package/dist/commands/application/short-codes/create.js +69 -0
- package/dist/commands/application/short-codes/delete.d.ts +6 -0
- package/dist/commands/application/short-codes/delete.d.ts.map +1 -0
- package/dist/commands/application/short-codes/delete.js +79 -0
- package/dist/commands/application/short-codes/list.d.ts +5 -0
- package/dist/commands/application/short-codes/list.d.ts.map +1 -0
- package/dist/commands/application/short-codes/list.js +63 -0
- package/dist/commands/application/short-codes/toggle.d.ts +5 -0
- package/dist/commands/application/short-codes/toggle.d.ts.map +1 -0
- package/dist/commands/application/short-codes/toggle.js +71 -0
- package/dist/commands/application/short-codes.d.ts +3 -0
- package/dist/commands/application/short-codes.d.ts.map +1 -0
- package/dist/commands/application/short-codes.js +226 -0
- package/dist/commands/application/toggle.d.ts +2 -0
- package/dist/commands/application/toggle.d.ts.map +1 -0
- package/dist/commands/application/toggle.js +78 -0
- package/dist/commands/application/update.d.ts +4 -0
- package/dist/commands/application/update.d.ts.map +1 -0
- package/dist/commands/application/update.js +11 -0
- package/dist/commands/application.d.ts.map +1 -1
- package/dist/commands/application.js +32 -1630
- package/dist/commands/auth.d.ts.map +1 -1
- package/dist/commands/auth.js +31 -49
- package/dist/commands/base/BaseCommand.d.ts +3 -3
- package/dist/commands/base/BaseCommand.d.ts.map +1 -1
- package/dist/commands/base/BaseCommand.js +3 -3
- package/dist/commands/base/command-wrapper.d.ts +0 -4
- package/dist/commands/base/command-wrapper.d.ts.map +1 -1
- package/dist/commands/base/command-wrapper.js +13 -14
- package/dist/commands/base/middleware.d.ts +3 -3
- package/dist/commands/base/middleware.d.ts.map +1 -1
- package/dist/commands/base/middleware.js +4 -4
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +15 -32
- package/dist/commands/connectivity.d.ts.map +1 -1
- package/dist/commands/connectivity.js +6 -11
- package/dist/commands/debug.d.ts.map +1 -1
- package/dist/commands/debug.js +187 -46
- package/dist/commands/discover.d.ts.map +1 -1
- package/dist/commands/discover.js +4 -17
- package/dist/commands/gateway.d.ts.map +1 -1
- package/dist/commands/gateway.js +37 -77
- package/dist/commands/managedGateway/create.d.ts +6 -0
- package/dist/commands/managedGateway/create.d.ts.map +1 -0
- package/dist/commands/managedGateway/create.js +50 -0
- package/dist/commands/managedGateway/delete.d.ts +5 -0
- package/dist/commands/managedGateway/delete.d.ts.map +1 -0
- package/dist/commands/managedGateway/delete.js +57 -0
- package/dist/commands/managedGateway/get.d.ts +4 -0
- package/dist/commands/managedGateway/get.d.ts.map +1 -0
- package/dist/commands/managedGateway/get.js +71 -0
- package/dist/commands/managedGateway/haproxy-stats.d.ts +6 -0
- package/dist/commands/managedGateway/haproxy-stats.d.ts.map +1 -0
- package/dist/commands/managedGateway/haproxy-stats.js +131 -0
- package/dist/commands/managedGateway/list.d.ts +4 -0
- package/dist/commands/managedGateway/list.d.ts.map +1 -0
- package/dist/commands/managedGateway/list.js +50 -0
- package/dist/commands/managedGateway/logs.d.ts +10 -0
- package/dist/commands/managedGateway/logs.d.ts.map +1 -0
- package/dist/commands/managedGateway/logs.js +100 -0
- package/dist/commands/managedGateway/reboot.d.ts +5 -0
- package/dist/commands/managedGateway/reboot.d.ts.map +1 -0
- package/dist/commands/managedGateway/reboot.js +95 -0
- package/dist/commands/managedGateway/resync.d.ts +10 -0
- package/dist/commands/managedGateway/resync.d.ts.map +1 -0
- package/dist/commands/managedGateway/resync.js +69 -0
- package/dist/commands/managedGateway/ssh.d.ts +4 -0
- package/dist/commands/managedGateway/ssh.d.ts.map +1 -0
- package/dist/commands/managedGateway/ssh.js +130 -0
- package/dist/commands/managedGateway/wipe-logs.d.ts +4 -0
- package/dist/commands/managedGateway/wipe-logs.d.ts.map +1 -0
- package/dist/commands/managedGateway/wipe-logs.js +67 -0
- package/dist/commands/managedGateway/wireguard.d.ts +4 -0
- package/dist/commands/managedGateway/wireguard.d.ts.map +1 -0
- package/dist/commands/managedGateway/wireguard.js +68 -0
- package/dist/commands/managedGateway.d.ts.map +1 -1
- package/dist/commands/managedGateway.js +61 -117
- package/dist/commands/utils/config-validator.d.ts +5 -5
- package/dist/commands/utils/config-validator.d.ts.map +1 -1
- package/dist/commands/utils/config-validator.js +8 -8
- package/dist/commands/utils/output-formatter.js +1 -1
- package/dist/config/app-config.d.ts +1 -1
- package/dist/config/app-config.js +2 -2
- package/dist/index.js +0 -3
- package/dist/services/LocalAgentManager.d.ts.map +1 -1
- package/dist/services/LocalAgentManager.js +4 -2
- package/dist/services/agentDeployment/AgentDeploymentService.d.ts +35 -0
- package/dist/services/agentDeployment/AgentDeploymentService.d.ts.map +1 -0
- package/dist/services/agentDeployment/AgentDeploymentService.js +35 -0
- package/dist/services/application/ApplicationService.d.ts +5 -4
- package/dist/services/application/ApplicationService.d.ts.map +1 -1
- package/dist/services/application/ApplicationService.js +22 -35
- package/dist/services/auth/AuthService.d.ts +5 -5
- package/dist/services/auth/AuthService.d.ts.map +1 -1
- package/dist/services/auth/AuthService.js +11 -58
- package/dist/services/daemon/DaemonManagerFactory.d.ts +2 -0
- package/dist/services/daemon/DaemonManagerFactory.d.ts.map +1 -1
- package/dist/services/daemon/DaemonManagerFactory.js +14 -6
- package/dist/services/diagnostics/DiagnosticsService.d.ts +89 -0
- package/dist/services/diagnostics/DiagnosticsService.d.ts.map +1 -0
- package/dist/services/diagnostics/DiagnosticsService.js +37 -0
- package/dist/services/edgible.d.ts +6 -4
- package/dist/services/edgible.d.ts.map +1 -1
- package/dist/services/edgible.js +36 -86
- package/dist/services/gateway/GatewayService.d.ts +5 -6
- package/dist/services/gateway/GatewayService.d.ts.map +1 -1
- package/dist/services/gateway/GatewayService.js +22 -36
- package/dist/services/instances.d.ts +34 -0
- package/dist/services/instances.d.ts.map +1 -0
- package/dist/services/instances.js +64 -0
- package/dist/services/managedGateway/ManagedGatewayService.d.ts +75 -0
- package/dist/services/managedGateway/ManagedGatewayService.d.ts.map +1 -0
- package/dist/services/managedGateway/ManagedGatewayService.js +44 -0
- package/dist/services/token/TokenManager.d.ts +56 -0
- package/dist/services/token/TokenManager.d.ts.map +1 -0
- package/dist/services/token/TokenManager.js +85 -0
- package/dist/types/validation/schemas.d.ts +22 -22
- package/dist/utils/PlatformDetector.d.ts +2 -0
- package/dist/utils/PlatformDetector.d.ts.map +1 -1
- package/dist/utils/PlatformDetector.js +5 -34
- package/dist/validation/schemas.d.ts +6 -6
- package/package.json +1 -1
|
@@ -1,56 +1,23 @@
|
|
|
1
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
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.setupApplicationCommands = setupApplicationCommands;
|
|
40
4
|
const commander_1 = require("commander");
|
|
41
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
42
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
-
const child_process_1 = require("child_process");
|
|
44
|
-
const path = __importStar(require("path"));
|
|
45
|
-
const WorkloadDetector_1 = require("../detection/WorkloadDetector");
|
|
46
5
|
const command_wrapper_1 = require("./base/command-wrapper");
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
6
|
+
const list_1 = require("./application/list");
|
|
7
|
+
const get_1 = require("./application/get");
|
|
8
|
+
const update_1 = require("./application/update");
|
|
9
|
+
const delete_1 = require("./application/delete");
|
|
10
|
+
const create_existing_1 = require("./application/create-existing");
|
|
11
|
+
const create_docker_compose_1 = require("./application/create-docker-compose");
|
|
12
|
+
const create_managed_process_1 = require("./application/create-managed-process");
|
|
13
|
+
const create_stubs_1 = require("./application/create-stubs");
|
|
14
|
+
const list_2 = require("./application/api-keys/list");
|
|
15
|
+
const create_1 = require("./application/api-keys/create");
|
|
16
|
+
const delete_2 = require("./application/api-keys/delete");
|
|
17
|
+
const list_3 = require("./application/short-codes/list");
|
|
18
|
+
const create_2 = require("./application/short-codes/create");
|
|
19
|
+
const delete_3 = require("./application/short-codes/delete");
|
|
20
|
+
const toggle_1 = require("./application/short-codes/toggle");
|
|
54
21
|
/**
|
|
55
22
|
* Application command group
|
|
56
23
|
*/
|
|
@@ -65,40 +32,8 @@ function setupApplicationCommands(program) {
|
|
|
65
32
|
.option('--json', 'Output as JSON')
|
|
66
33
|
.alias('ls')
|
|
67
34
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
68
|
-
|
|
69
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
70
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
71
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
72
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
73
|
-
requireAuth: true,
|
|
74
|
-
requireOrganization: true,
|
|
75
|
-
});
|
|
76
|
-
logger.debug('Getting applications');
|
|
77
|
-
const applications = await applicationService.getApplications();
|
|
78
|
-
if (applications.length === 0) {
|
|
79
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
80
|
-
console.log(chalk_1.default.gray('Use "edgible application create" to create an application'));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (options.json) {
|
|
84
|
-
console.log(JSON.stringify({
|
|
85
|
-
applications: applications.map((app) => ({
|
|
86
|
-
id: app.id,
|
|
87
|
-
name: app.name,
|
|
88
|
-
servingIp: app.servingIp,
|
|
89
|
-
port: app.port,
|
|
90
|
-
protocol: app.protocol,
|
|
91
|
-
status: app.status,
|
|
92
|
-
workloadId: app.workloadId,
|
|
93
|
-
createdAt: app.createdAt,
|
|
94
|
-
description: app.description || '',
|
|
95
|
-
})),
|
|
96
|
-
}, null, 2));
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
console.log((0, output_formatter_1.formatList)(applications, (app, index) => `${index + 1}. ${(0, output_formatter_1.formatApplication)(app)}`, '📱 Configured Applications:', 'No applications configured'));
|
|
35
|
+
await (0, list_1.handleApplicationList)(options);
|
|
100
36
|
}, {
|
|
101
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
102
37
|
requireAuth: true,
|
|
103
38
|
requireOrganization: true,
|
|
104
39
|
}));
|
|
@@ -127,358 +62,8 @@ Examples:
|
|
|
127
62
|
.option('--hostnames <hostnames>', 'Comma-separated additional hostnames to route to this app')
|
|
128
63
|
.option('--no-interactive', 'Run in non-interactive mode')
|
|
129
64
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
130
|
-
|
|
131
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
132
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
133
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
134
|
-
const gatewayService = container.get(types_1.TYPES.GatewayService);
|
|
135
|
-
const edgibleService = container.get(types_1.TYPES.EdgibleService);
|
|
136
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
137
|
-
requireAuth: true,
|
|
138
|
-
requireOrganization: true,
|
|
139
|
-
});
|
|
140
|
-
logger.debug('Creating application', { name: options.name });
|
|
141
|
-
// Name
|
|
142
|
-
let appName = options.name;
|
|
143
|
-
let useManagedGateway = false;
|
|
144
|
-
if (!appName && !options.noInteractive) {
|
|
145
|
-
const { name } = await inquirer_1.default.prompt([
|
|
146
|
-
{
|
|
147
|
-
type: 'input',
|
|
148
|
-
name: 'name',
|
|
149
|
-
message: 'Enter application name:',
|
|
150
|
-
validate: (i) => !!i.trim() || 'Application name is required',
|
|
151
|
-
},
|
|
152
|
-
]);
|
|
153
|
-
appName = name.trim();
|
|
154
|
-
}
|
|
155
|
-
if (!appName) {
|
|
156
|
-
throw new Error('Application name is required');
|
|
157
|
-
}
|
|
158
|
-
// Description
|
|
159
|
-
let description = options.description || `Application for ${appName}`;
|
|
160
|
-
// Port (may be overridden by workload selection in interactive mode)
|
|
161
|
-
let port = (0, input_parser_1.parsePort)(options.port);
|
|
162
|
-
// Protocol
|
|
163
|
-
let protocolUnion = (0, input_parser_1.parseProtocol)(options.protocol);
|
|
164
|
-
// HTTPS upgrade: if --https-upgrade is set and protocol is http, change to https
|
|
165
|
-
if (options.httpsUpgrade && protocolUnion === 'http') {
|
|
166
|
-
protocolUnion = 'https';
|
|
167
|
-
}
|
|
168
|
-
// Device IDs (serving) and Gateway IDs
|
|
169
|
-
let deviceId = options.deviceId;
|
|
170
|
-
let gatewayIds = (0, input_parser_1.parseGatewayIds)(options.gatewayIds);
|
|
171
|
-
let hostnames = Array.isArray(options.hostnames)
|
|
172
|
-
? options.hostnames
|
|
173
|
-
: (typeof options.hostnames === 'string' && options.hostnames.trim().length > 0
|
|
174
|
-
? options.hostnames.split(',').map(s => s.trim()).filter(Boolean)
|
|
175
|
-
: []);
|
|
176
|
-
// Organization auth settings
|
|
177
|
-
let requireOrgAuth = options.requireOrgAuth || false;
|
|
178
|
-
let allowedOrgs = [];
|
|
179
|
-
if (options.allowedOrgs) {
|
|
180
|
-
allowedOrgs = options.allowedOrgs.split(',').map(s => s.trim()).filter(Boolean);
|
|
181
|
-
}
|
|
182
|
-
if (!options.noInteractive) {
|
|
183
|
-
// Prompt for HTTPS upgrade if protocol is http and --https-upgrade wasn't explicitly set
|
|
184
|
-
if (protocolUnion === 'http' && options.httpsUpgrade === undefined) {
|
|
185
|
-
const { upgradeToHttps } = await inquirer_1.default.prompt([
|
|
186
|
-
{
|
|
187
|
-
type: 'confirm',
|
|
188
|
-
name: 'upgradeToHttps',
|
|
189
|
-
message: 'Upgrade protocol from HTTP to HTTPS?',
|
|
190
|
-
default: false,
|
|
191
|
-
},
|
|
192
|
-
]);
|
|
193
|
-
if (upgradeToHttps) {
|
|
194
|
-
protocolUnion = 'https';
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
// Optional: prompt for additional hostnames
|
|
198
|
-
const { addHostnames } = await inquirer_1.default.prompt([
|
|
199
|
-
{
|
|
200
|
-
type: 'input',
|
|
201
|
-
name: 'addHostnames',
|
|
202
|
-
message: 'Additional hostnames (comma-separated, optional):',
|
|
203
|
-
when: () => hostnames.length === 0,
|
|
204
|
-
},
|
|
205
|
-
]);
|
|
206
|
-
if (addHostnames && typeof addHostnames === 'string') {
|
|
207
|
-
hostnames = addHostnames.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
208
|
-
}
|
|
209
|
-
// Prompt for organization authentication
|
|
210
|
-
if (options.requireOrgAuth === undefined) {
|
|
211
|
-
const { enableOrgAuth } = await inquirer_1.default.prompt([
|
|
212
|
-
{
|
|
213
|
-
type: 'confirm',
|
|
214
|
-
name: 'enableOrgAuth',
|
|
215
|
-
message: 'Require organization authentication to access this application?',
|
|
216
|
-
default: false,
|
|
217
|
-
},
|
|
218
|
-
]);
|
|
219
|
-
requireOrgAuth = enableOrgAuth;
|
|
220
|
-
if (requireOrgAuth) {
|
|
221
|
-
const { allowOtherOrgs } = await inquirer_1.default.prompt([
|
|
222
|
-
{
|
|
223
|
-
type: 'confirm',
|
|
224
|
-
name: 'allowOtherOrgs',
|
|
225
|
-
message: 'Allow other organizations to access this application?',
|
|
226
|
-
default: false,
|
|
227
|
-
},
|
|
228
|
-
]);
|
|
229
|
-
if (allowOtherOrgs) {
|
|
230
|
-
const { orgIds } = await inquirer_1.default.prompt([
|
|
231
|
-
{
|
|
232
|
-
type: 'input',
|
|
233
|
-
name: 'orgIds',
|
|
234
|
-
message: 'Enter comma-separated organization IDs to allow access:',
|
|
235
|
-
},
|
|
236
|
-
]);
|
|
237
|
-
if (orgIds && typeof orgIds === 'string') {
|
|
238
|
-
allowedOrgs = orgIds.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
// Prompt for managed gateway option
|
|
244
|
-
if (gatewayIds.length === 0) {
|
|
245
|
-
const { useManaged } = await inquirer_1.default.prompt([
|
|
246
|
-
{
|
|
247
|
-
type: 'confirm',
|
|
248
|
-
name: 'useManaged',
|
|
249
|
-
message: 'Use Edgible managed gateway?',
|
|
250
|
-
default: false,
|
|
251
|
-
},
|
|
252
|
-
]);
|
|
253
|
-
useManagedGateway = useManaged;
|
|
254
|
-
if (!useManagedGateway) {
|
|
255
|
-
// Ask if they want to assign a gateway at all
|
|
256
|
-
const { assignGateway } = await inquirer_1.default.prompt([
|
|
257
|
-
{
|
|
258
|
-
type: 'confirm',
|
|
259
|
-
name: 'assignGateway',
|
|
260
|
-
message: 'Assign a gateway to this application? (No = local/internal access only)',
|
|
261
|
-
default: true,
|
|
262
|
-
},
|
|
263
|
-
]);
|
|
264
|
-
if (assignGateway) {
|
|
265
|
-
// Try to offer a list of gateways (via service), else fallback to manual input
|
|
266
|
-
try {
|
|
267
|
-
const gatewaysResp = await gatewayService.listGateways();
|
|
268
|
-
const gatewayChoices = gatewaysResp.gateways.map((g) => ({
|
|
269
|
-
name: `${g.device.name} (${g.device.id})`,
|
|
270
|
-
value: g.device.id,
|
|
271
|
-
}));
|
|
272
|
-
if (gatewayChoices.length > 0) {
|
|
273
|
-
const { selectedGateways } = await inquirer_1.default.prompt([
|
|
274
|
-
{
|
|
275
|
-
type: 'checkbox',
|
|
276
|
-
name: 'selectedGateways',
|
|
277
|
-
message: 'Select gateway device(s):',
|
|
278
|
-
choices: gatewayChoices,
|
|
279
|
-
validate: (vals) => vals.length > 0 ? true : 'Select at least one gateway',
|
|
280
|
-
},
|
|
281
|
-
]);
|
|
282
|
-
gatewayIds = selectedGateways;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
catch (error) {
|
|
286
|
-
logger.warn('Failed to list gateways', error);
|
|
287
|
-
}
|
|
288
|
-
if (gatewayIds.length === 0) {
|
|
289
|
-
const ans2 = await inquirer_1.default.prompt([
|
|
290
|
-
{
|
|
291
|
-
type: 'input',
|
|
292
|
-
name: 'gatewayIds',
|
|
293
|
-
message: 'Enter comma-separated gateway device IDs (or leave empty for no gateway):',
|
|
294
|
-
validate: (v) => true, // Allow empty input
|
|
295
|
-
},
|
|
296
|
-
]);
|
|
297
|
-
if (ans2.gatewayIds && ans2.gatewayIds.trim()) {
|
|
298
|
-
gatewayIds = (0, input_parser_1.parseGatewayIds)(ans2.gatewayIds);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
logger.info('Application will be created without gateway assignment (local/internal access only)');
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
// Serving device selection - fetch available serving devices from organization
|
|
308
|
-
if (!deviceId) {
|
|
309
|
-
try {
|
|
310
|
-
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
311
|
-
const servingDeviceChoices = Array.isArray(servingDevicesResp?.devices)
|
|
312
|
-
? servingDevicesResp.devices.map((d) => ({
|
|
313
|
-
name: `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}`,
|
|
314
|
-
value: d.id,
|
|
315
|
-
}))
|
|
316
|
-
: [];
|
|
317
|
-
if (servingDeviceChoices.length > 0) {
|
|
318
|
-
const { selectedDeviceId } = await inquirer_1.default.prompt([
|
|
319
|
-
{
|
|
320
|
-
type: 'list',
|
|
321
|
-
name: 'selectedDeviceId',
|
|
322
|
-
message: 'Select serving device:',
|
|
323
|
-
choices: servingDeviceChoices,
|
|
324
|
-
},
|
|
325
|
-
]);
|
|
326
|
-
deviceId = selectedDeviceId;
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
// Fallback to manual input if no serving devices found
|
|
330
|
-
const ans = await inquirer_1.default.prompt([
|
|
331
|
-
{
|
|
332
|
-
type: 'input',
|
|
333
|
-
name: 'deviceId',
|
|
334
|
-
message: 'Enter serving device ID:',
|
|
335
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
336
|
-
},
|
|
337
|
-
]);
|
|
338
|
-
deviceId = String(ans.deviceId).trim();
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
catch (error) {
|
|
342
|
-
logger.warn('Failed to list serving devices', error);
|
|
343
|
-
// Fallback to manual input if listing fails
|
|
344
|
-
const ans = await inquirer_1.default.prompt([
|
|
345
|
-
{
|
|
346
|
-
type: 'input',
|
|
347
|
-
name: 'deviceId',
|
|
348
|
-
message: 'Enter serving device ID:',
|
|
349
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
350
|
-
},
|
|
351
|
-
]);
|
|
352
|
-
deviceId = String(ans.deviceId).trim();
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
if (!deviceId) {
|
|
357
|
-
throw new Error('--device-id (serving) is required');
|
|
358
|
-
}
|
|
359
|
-
if (!useManagedGateway && gatewayIds.length === 0) {
|
|
360
|
-
logger.warn('No gateways assigned - application will only be accessible locally/internally');
|
|
361
|
-
}
|
|
362
|
-
const subtype = 'local-preexisting';
|
|
363
|
-
// If interactive, allow choosing a local workload
|
|
364
|
-
if (!options.noInteractive) {
|
|
365
|
-
try {
|
|
366
|
-
const workloads = await WorkloadDetector_1.WorkloadDetector.detectWorkloads();
|
|
367
|
-
const running = workloads.filter((w) => w.status === 'running');
|
|
368
|
-
if (running.length > 0) {
|
|
369
|
-
const { selectedWorkloadId } = await inquirer_1.default.prompt([
|
|
370
|
-
{
|
|
371
|
-
type: 'list',
|
|
372
|
-
name: 'selectedWorkloadId',
|
|
373
|
-
message: 'Select local workload to associate:',
|
|
374
|
-
choices: running.map((w) => ({ name: `${w.name} (${w.type})`, value: w.id })),
|
|
375
|
-
},
|
|
376
|
-
]);
|
|
377
|
-
// Attach to description so the backend can persist in configuration via service call
|
|
378
|
-
description = description || '';
|
|
379
|
-
description = `${description} [workloadId=${selectedWorkloadId}]`;
|
|
380
|
-
// If the selected workload exposes ports, allow user to choose one to override the app port
|
|
381
|
-
const selectedWorkload = running.find((w) => w.id === selectedWorkloadId);
|
|
382
|
-
const availablePorts = Array.isArray(selectedWorkload?.ports)
|
|
383
|
-
? Array.from(new Set((selectedWorkload.ports || [])
|
|
384
|
-
.map((p) => (typeof p.hostPort === 'number' ? p.hostPort : p.containerPort))
|
|
385
|
-
.filter((n) => typeof n === 'number')))
|
|
386
|
-
: [];
|
|
387
|
-
if (availablePorts.length > 0) {
|
|
388
|
-
const portChoices = [
|
|
389
|
-
...availablePorts.sort((a, b) => a - b).map((p) => ({ name: `${p}`, value: String(p) })),
|
|
390
|
-
{ name: 'Enter a custom port', value: 'custom' },
|
|
391
|
-
];
|
|
392
|
-
const { chosenPort } = await inquirer_1.default.prompt([
|
|
393
|
-
{
|
|
394
|
-
type: 'list',
|
|
395
|
-
name: 'chosenPort',
|
|
396
|
-
message: 'Select port to expose for this application:',
|
|
397
|
-
choices: portChoices,
|
|
398
|
-
default: String(availablePorts[0]),
|
|
399
|
-
},
|
|
400
|
-
]);
|
|
401
|
-
if (chosenPort === 'custom') {
|
|
402
|
-
const { customPort } = await inquirer_1.default.prompt([
|
|
403
|
-
{
|
|
404
|
-
type: 'input',
|
|
405
|
-
name: 'customPort',
|
|
406
|
-
message: 'Enter custom port:',
|
|
407
|
-
validate: (v) => {
|
|
408
|
-
try {
|
|
409
|
-
(0, input_parser_1.parsePort)(v);
|
|
410
|
-
return true;
|
|
411
|
-
}
|
|
412
|
-
catch (e) {
|
|
413
|
-
return e.message;
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
},
|
|
417
|
-
]);
|
|
418
|
-
port = (0, input_parser_1.parsePort)(customPort);
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
port = (0, input_parser_1.parsePort)(chosenPort);
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
catch (error) {
|
|
427
|
-
logger.debug('Failed to detect workloads', error);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
logger.info('Creating application', {
|
|
431
|
-
name: appName,
|
|
432
|
-
port,
|
|
433
|
-
protocol: protocolUnion,
|
|
434
|
-
deviceId,
|
|
435
|
-
gatewayIds,
|
|
436
|
-
subtype,
|
|
437
|
-
});
|
|
438
|
-
console.log(chalk_1.default.blue(`\nCreating application: ${appName}`));
|
|
439
|
-
console.log(chalk_1.default.gray(`Port: ${port}`));
|
|
440
|
-
console.log(chalk_1.default.gray(`Protocol: ${protocolUnion.toUpperCase()}`));
|
|
441
|
-
console.log(chalk_1.default.gray(`Serving device: ${deviceId}`));
|
|
442
|
-
if (useManagedGateway) {
|
|
443
|
-
console.log(chalk_1.default.gray(`Using Edgible managed gateway`));
|
|
444
|
-
}
|
|
445
|
-
else {
|
|
446
|
-
console.log(chalk_1.default.gray(`Gateways: ${gatewayIds.join(', ')}`));
|
|
447
|
-
}
|
|
448
|
-
if (hostnames.length > 0) {
|
|
449
|
-
console.log(chalk_1.default.gray(`Additional hostnames: ${hostnames.join(', ')}`));
|
|
450
|
-
}
|
|
451
|
-
if (requireOrgAuth) {
|
|
452
|
-
console.log(chalk_1.default.gray(`Organization authentication: ${chalk_1.default.green('Enabled')}`));
|
|
453
|
-
if (allowedOrgs.length > 0) {
|
|
454
|
-
console.log(chalk_1.default.gray(`Allowed organizations: ${allowedOrgs.join(', ')}`));
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
const result = await applicationService.createApplicationProgrammatically({
|
|
458
|
-
name: appName,
|
|
459
|
-
description,
|
|
460
|
-
port,
|
|
461
|
-
protocol: protocolUnion,
|
|
462
|
-
hostnames,
|
|
463
|
-
deviceIds: [deviceId],
|
|
464
|
-
gatewayIds: useManagedGateway ? undefined : gatewayIds,
|
|
465
|
-
useManagedGateway,
|
|
466
|
-
subtype,
|
|
467
|
-
requireOrgAuth,
|
|
468
|
-
allowedOrganizations: allowedOrgs.length > 0 ? allowedOrgs : undefined,
|
|
469
|
-
});
|
|
470
|
-
console.log(chalk_1.default.green('\n✓ Application created successfully!'));
|
|
471
|
-
console.log(chalk_1.default.blue('\n📋 Application Details:'));
|
|
472
|
-
if (result && typeof result === 'object' && 'name' in result) {
|
|
473
|
-
const app = result;
|
|
474
|
-
console.log(chalk_1.default.white(` Name: ${app.name}`));
|
|
475
|
-
console.log(chalk_1.default.white(` ID: ${app.id}`));
|
|
476
|
-
if (app.url)
|
|
477
|
-
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan.bold(app.url)}`));
|
|
478
|
-
console.log(chalk_1.default.white(` Status: ${app.status}`));
|
|
479
|
-
}
|
|
65
|
+
await (0, create_existing_1.handleApplicationCreateExisting)(options);
|
|
480
66
|
}, {
|
|
481
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
482
67
|
requireAuth: true,
|
|
483
68
|
requireOrganization: true,
|
|
484
69
|
}));
|
|
@@ -499,297 +84,8 @@ Examples:
|
|
|
499
84
|
.option('--hostnames <hostnames>', 'Comma-separated additional hostnames to route to this app')
|
|
500
85
|
.option('--no-interactive', 'Run in non-interactive mode')
|
|
501
86
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
502
|
-
|
|
503
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
504
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
505
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
506
|
-
const gatewayService = container.get(types_1.TYPES.GatewayService);
|
|
507
|
-
const edgibleService = container.get(types_1.TYPES.EdgibleService);
|
|
508
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
509
|
-
requireAuth: true,
|
|
510
|
-
requireOrganization: true,
|
|
511
|
-
});
|
|
512
|
-
// Check sudo permissions
|
|
513
|
-
if (!(0, sudo_checker_1.checkSudoPermissions)()) {
|
|
514
|
-
console.log(chalk_1.default.yellow('⚠ Warning: Not running as sudo. Docker commands may fail without proper permissions.'));
|
|
515
|
-
}
|
|
516
|
-
// Find docker-compose file
|
|
517
|
-
let composeFilePath;
|
|
518
|
-
try {
|
|
519
|
-
composeFilePath = (0, docker_compose_parser_1.findDockerComposeFile)(options.composeFile);
|
|
520
|
-
}
|
|
521
|
-
catch (error) {
|
|
522
|
-
throw new Error(`Failed to find docker-compose file: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
523
|
-
}
|
|
524
|
-
if (!composeFilePath) {
|
|
525
|
-
throw new Error('Docker compose file not found. Please provide --compose-file or ensure docker-compose.yml or docker-compose.yaml exists in the current directory.');
|
|
526
|
-
}
|
|
527
|
-
console.log(chalk_1.default.blue(`Using docker-compose file: ${composeFilePath}`));
|
|
528
|
-
console.log(chalk_1.default.gray('Note: Using Docker Compose v2 (docker compose command)'));
|
|
529
|
-
// Parse compose file
|
|
530
|
-
let composeData;
|
|
531
|
-
try {
|
|
532
|
-
composeData = (0, docker_compose_parser_1.parseDockerComposeFile)(composeFilePath);
|
|
533
|
-
}
|
|
534
|
-
catch (error) {
|
|
535
|
-
throw new Error(`Failed to parse docker-compose file: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
536
|
-
}
|
|
537
|
-
if (composeData.containers.length === 0) {
|
|
538
|
-
throw new Error('No containers with exposed ports found in docker-compose file');
|
|
539
|
-
}
|
|
540
|
-
// Build port selection choices
|
|
541
|
-
const portChoices = [];
|
|
542
|
-
for (const containerInfo of composeData.containers) {
|
|
543
|
-
for (const portInfo of containerInfo.ports) {
|
|
544
|
-
portChoices.push({
|
|
545
|
-
name: `${containerInfo.name}:${portInfo.host}->${portInfo.container}/${portInfo.protocol}`,
|
|
546
|
-
value: { container: containerInfo.name, port: portInfo.host },
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
if (portChoices.length === 0) {
|
|
551
|
-
throw new Error('No ports found in docker-compose file');
|
|
552
|
-
}
|
|
553
|
-
// Get application name
|
|
554
|
-
let appName = options.name;
|
|
555
|
-
if (!appName && !options.noInteractive) {
|
|
556
|
-
const { name } = await inquirer_1.default.prompt([
|
|
557
|
-
{
|
|
558
|
-
type: 'input',
|
|
559
|
-
name: 'name',
|
|
560
|
-
message: 'Enter application name:',
|
|
561
|
-
validate: (i) => !!i.trim() || 'Application name is required',
|
|
562
|
-
},
|
|
563
|
-
]);
|
|
564
|
-
appName = name.trim();
|
|
565
|
-
}
|
|
566
|
-
if (!appName) {
|
|
567
|
-
throw new Error('Application name is required');
|
|
568
|
-
}
|
|
569
|
-
// Select port
|
|
570
|
-
let selectedPort;
|
|
571
|
-
let selectedContainer;
|
|
572
|
-
if (!options.noInteractive) {
|
|
573
|
-
const { selected } = await inquirer_1.default.prompt([
|
|
574
|
-
{
|
|
575
|
-
type: 'list',
|
|
576
|
-
name: 'selected',
|
|
577
|
-
message: 'Select container and port to expose:',
|
|
578
|
-
choices: portChoices,
|
|
579
|
-
},
|
|
580
|
-
]);
|
|
581
|
-
selectedPort = selected.port;
|
|
582
|
-
selectedContainer = selected.container;
|
|
583
|
-
}
|
|
584
|
-
else {
|
|
585
|
-
// In non-interactive mode, use first available port
|
|
586
|
-
selectedPort = portChoices[0].value.port;
|
|
587
|
-
selectedContainer = portChoices[0].value.container;
|
|
588
|
-
}
|
|
589
|
-
// Description
|
|
590
|
-
const description = options.description || `Application for ${appName} (docker-compose: ${selectedContainer})`;
|
|
591
|
-
// Device IDs and Gateway IDs
|
|
592
|
-
let deviceId = options.deviceId;
|
|
593
|
-
let gatewayIds = (0, input_parser_1.parseGatewayIds)(options.gatewayIds);
|
|
594
|
-
let hostnames = Array.isArray(options.hostnames)
|
|
595
|
-
? options.hostnames
|
|
596
|
-
: (typeof options.hostnames === 'string' && options.hostnames.trim().length > 0
|
|
597
|
-
? options.hostnames.split(',').map(s => s.trim()).filter(Boolean)
|
|
598
|
-
: []);
|
|
599
|
-
let useManagedGateway = false;
|
|
600
|
-
if (!options.noInteractive) {
|
|
601
|
-
// Optional: prompt for additional hostnames
|
|
602
|
-
const { addHostnames } = await inquirer_1.default.prompt([
|
|
603
|
-
{
|
|
604
|
-
type: 'input',
|
|
605
|
-
name: 'addHostnames',
|
|
606
|
-
message: 'Additional hostnames (comma-separated, optional):',
|
|
607
|
-
when: () => hostnames.length === 0,
|
|
608
|
-
},
|
|
609
|
-
]);
|
|
610
|
-
if (addHostnames && typeof addHostnames === 'string') {
|
|
611
|
-
hostnames = addHostnames.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
612
|
-
}
|
|
613
|
-
// Prompt for managed gateway option
|
|
614
|
-
if (gatewayIds.length === 0) {
|
|
615
|
-
const { useManaged } = await inquirer_1.default.prompt([
|
|
616
|
-
{
|
|
617
|
-
type: 'confirm',
|
|
618
|
-
name: 'useManaged',
|
|
619
|
-
message: 'Use Edgible managed gateway?',
|
|
620
|
-
default: false,
|
|
621
|
-
},
|
|
622
|
-
]);
|
|
623
|
-
useManagedGateway = useManaged;
|
|
624
|
-
if (!useManagedGateway) {
|
|
625
|
-
// Ask if they want to assign a gateway at all
|
|
626
|
-
const { assignGateway } = await inquirer_1.default.prompt([
|
|
627
|
-
{
|
|
628
|
-
type: 'confirm',
|
|
629
|
-
name: 'assignGateway',
|
|
630
|
-
message: 'Assign a gateway to this application? (No = local/internal access only)',
|
|
631
|
-
default: true,
|
|
632
|
-
},
|
|
633
|
-
]);
|
|
634
|
-
if (assignGateway) {
|
|
635
|
-
// Try to offer a list of gateways (via service), else fallback to manual input
|
|
636
|
-
try {
|
|
637
|
-
const gatewaysResp = await gatewayService.listGateways();
|
|
638
|
-
const gatewayChoices = gatewaysResp.gateways.map((g) => ({
|
|
639
|
-
name: `${g.device.name} (${g.device.id})`,
|
|
640
|
-
value: g.device.id,
|
|
641
|
-
}));
|
|
642
|
-
if (gatewayChoices.length > 0) {
|
|
643
|
-
const { selectedGateways } = await inquirer_1.default.prompt([
|
|
644
|
-
{
|
|
645
|
-
type: 'checkbox',
|
|
646
|
-
name: 'selectedGateways',
|
|
647
|
-
message: 'Select gateway device(s):',
|
|
648
|
-
choices: gatewayChoices,
|
|
649
|
-
validate: (vals) => vals.length > 0 ? true : 'Select at least one gateway',
|
|
650
|
-
},
|
|
651
|
-
]);
|
|
652
|
-
gatewayIds = selectedGateways;
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
catch (error) {
|
|
656
|
-
logger.warn('Failed to list gateways', error);
|
|
657
|
-
}
|
|
658
|
-
if (gatewayIds.length === 0) {
|
|
659
|
-
const ans2 = await inquirer_1.default.prompt([
|
|
660
|
-
{
|
|
661
|
-
type: 'input',
|
|
662
|
-
name: 'gatewayIds',
|
|
663
|
-
message: 'Enter comma-separated gateway device IDs (or leave empty for no gateway):',
|
|
664
|
-
validate: (v) => true, // Allow empty input
|
|
665
|
-
},
|
|
666
|
-
]);
|
|
667
|
-
if (ans2.gatewayIds && ans2.gatewayIds.trim()) {
|
|
668
|
-
gatewayIds = (0, input_parser_1.parseGatewayIds)(ans2.gatewayIds);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
else {
|
|
673
|
-
logger.info('Application will be created without gateway assignment (local/internal access only)');
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
// Serving device selection
|
|
678
|
-
if (!deviceId) {
|
|
679
|
-
try {
|
|
680
|
-
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
681
|
-
const servingDeviceChoices = Array.isArray(servingDevicesResp?.devices)
|
|
682
|
-
? servingDevicesResp.devices.map((d) => ({
|
|
683
|
-
name: `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}`,
|
|
684
|
-
value: d.id,
|
|
685
|
-
}))
|
|
686
|
-
: [];
|
|
687
|
-
if (servingDeviceChoices.length > 0) {
|
|
688
|
-
const { selectedDeviceId } = await inquirer_1.default.prompt([
|
|
689
|
-
{
|
|
690
|
-
type: 'list',
|
|
691
|
-
name: 'selectedDeviceId',
|
|
692
|
-
message: 'Select serving device:',
|
|
693
|
-
choices: servingDeviceChoices,
|
|
694
|
-
},
|
|
695
|
-
]);
|
|
696
|
-
deviceId = selectedDeviceId;
|
|
697
|
-
}
|
|
698
|
-
else {
|
|
699
|
-
// Fallback to manual input if no serving devices found
|
|
700
|
-
const ans = await inquirer_1.default.prompt([
|
|
701
|
-
{
|
|
702
|
-
type: 'input',
|
|
703
|
-
name: 'deviceId',
|
|
704
|
-
message: 'Enter serving device ID:',
|
|
705
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
706
|
-
},
|
|
707
|
-
]);
|
|
708
|
-
deviceId = String(ans.deviceId).trim();
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
catch (error) {
|
|
712
|
-
logger.warn('Failed to list serving devices', error);
|
|
713
|
-
// Fallback to manual input if listing fails
|
|
714
|
-
const ans = await inquirer_1.default.prompt([
|
|
715
|
-
{
|
|
716
|
-
type: 'input',
|
|
717
|
-
name: 'deviceId',
|
|
718
|
-
message: 'Enter serving device ID:',
|
|
719
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
720
|
-
},
|
|
721
|
-
]);
|
|
722
|
-
deviceId = String(ans.deviceId).trim();
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (!deviceId) {
|
|
727
|
-
throw new Error('--device-id (serving) is required');
|
|
728
|
-
}
|
|
729
|
-
if (!useManagedGateway && gatewayIds.length === 0) {
|
|
730
|
-
logger.warn('No gateways assigned - application will only be accessible locally/internally');
|
|
731
|
-
}
|
|
732
|
-
// Run docker compose up
|
|
733
|
-
console.log(chalk_1.default.blue(`\nRunning docker compose up...`));
|
|
734
|
-
try {
|
|
735
|
-
const composeDir = path.dirname(composeFilePath);
|
|
736
|
-
const composeFileName = path.basename(composeFilePath);
|
|
737
|
-
(0, child_process_1.execSync)(`docker compose -f "${composeFileName}" up -d`, {
|
|
738
|
-
cwd: composeDir,
|
|
739
|
-
stdio: 'inherit',
|
|
740
|
-
});
|
|
741
|
-
console.log(chalk_1.default.green('✓ Docker compose up completed successfully'));
|
|
742
|
-
}
|
|
743
|
-
catch (error) {
|
|
744
|
-
console.log(chalk_1.default.red('✗ Docker compose up failed'));
|
|
745
|
-
throw new Error(`Failed to run docker compose up: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
746
|
-
}
|
|
747
|
-
// Create application
|
|
748
|
-
logger.info('Creating application', {
|
|
749
|
-
name: appName,
|
|
750
|
-
port: selectedPort,
|
|
751
|
-
protocol: 'https',
|
|
752
|
-
deviceId,
|
|
753
|
-
gatewayIds,
|
|
754
|
-
subtype: 'docker-compose',
|
|
755
|
-
});
|
|
756
|
-
console.log(chalk_1.default.blue(`\nCreating application: ${appName}`));
|
|
757
|
-
console.log(chalk_1.default.gray(`Port: ${selectedPort}`));
|
|
758
|
-
console.log(chalk_1.default.gray(`Protocol: HTTPS`));
|
|
759
|
-
console.log(chalk_1.default.gray(`Container: ${selectedContainer}`));
|
|
760
|
-
console.log(chalk_1.default.gray(`Serving device: ${deviceId}`));
|
|
761
|
-
if (useManagedGateway) {
|
|
762
|
-
console.log(chalk_1.default.gray(`Using Edgible managed gateway`));
|
|
763
|
-
}
|
|
764
|
-
else {
|
|
765
|
-
console.log(chalk_1.default.gray(`Gateways: ${gatewayIds.join(', ')}`));
|
|
766
|
-
}
|
|
767
|
-
if (hostnames.length > 0) {
|
|
768
|
-
console.log(chalk_1.default.gray(`Additional hostnames: ${hostnames.join(', ')}`));
|
|
769
|
-
}
|
|
770
|
-
const result = await applicationService.createApplicationProgrammatically({
|
|
771
|
-
name: appName,
|
|
772
|
-
description,
|
|
773
|
-
port: selectedPort,
|
|
774
|
-
protocol: 'https',
|
|
775
|
-
hostnames,
|
|
776
|
-
deviceIds: [deviceId],
|
|
777
|
-
gatewayIds: useManagedGateway ? undefined : gatewayIds,
|
|
778
|
-
useManagedGateway,
|
|
779
|
-
subtype: 'docker-compose',
|
|
780
|
-
});
|
|
781
|
-
console.log(chalk_1.default.green('\n✓ Application created successfully!'));
|
|
782
|
-
console.log(chalk_1.default.blue('\n📋 Application Details:'));
|
|
783
|
-
if (result && typeof result === 'object' && 'name' in result) {
|
|
784
|
-
const app = result;
|
|
785
|
-
console.log(chalk_1.default.white(` Name: ${app.name}`));
|
|
786
|
-
console.log(chalk_1.default.white(` ID: ${app.id}`));
|
|
787
|
-
if (app.url)
|
|
788
|
-
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan.bold(app.url)}`));
|
|
789
|
-
console.log(chalk_1.default.white(` Status: ${app.status}`));
|
|
790
|
-
}
|
|
87
|
+
await (0, create_docker_compose_1.handleApplicationCreateDockerCompose)(options);
|
|
791
88
|
}, {
|
|
792
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
793
89
|
requireAuth: true,
|
|
794
90
|
requireOrganization: true,
|
|
795
91
|
}));
|
|
@@ -815,371 +111,8 @@ Examples:
|
|
|
815
111
|
.option('--hostnames <hostnames>', 'Comma-separated additional hostnames')
|
|
816
112
|
.option('--no-interactive', 'Run in non-interactive mode')
|
|
817
113
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
818
|
-
|
|
819
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
820
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
821
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
822
|
-
const gatewayService = container.get(types_1.TYPES.GatewayService);
|
|
823
|
-
const edgibleService = container.get(types_1.TYPES.EdgibleService);
|
|
824
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
825
|
-
requireAuth: true,
|
|
826
|
-
requireOrganization: true,
|
|
827
|
-
});
|
|
828
|
-
// Application name
|
|
829
|
-
let appName = options.name;
|
|
830
|
-
if (!appName && !options.noInteractive) {
|
|
831
|
-
const { name } = await inquirer_1.default.prompt([
|
|
832
|
-
{
|
|
833
|
-
type: 'input',
|
|
834
|
-
name: 'name',
|
|
835
|
-
message: 'Enter application name:',
|
|
836
|
-
validate: (i) => !!i.trim() || 'Application name is required',
|
|
837
|
-
},
|
|
838
|
-
]);
|
|
839
|
-
appName = name.trim();
|
|
840
|
-
}
|
|
841
|
-
if (!appName) {
|
|
842
|
-
throw new Error('Application name is required');
|
|
843
|
-
}
|
|
844
|
-
// Command
|
|
845
|
-
let command = options.command;
|
|
846
|
-
if (!command && !options.noInteractive) {
|
|
847
|
-
const { cmd } = await inquirer_1.default.prompt([
|
|
848
|
-
{
|
|
849
|
-
type: 'input',
|
|
850
|
-
name: 'cmd',
|
|
851
|
-
message: 'Enter command to run:',
|
|
852
|
-
validate: (i) => !!i.trim() || 'Command is required',
|
|
853
|
-
},
|
|
854
|
-
]);
|
|
855
|
-
command = cmd.trim();
|
|
856
|
-
}
|
|
857
|
-
if (!command) {
|
|
858
|
-
throw new Error('Command is required');
|
|
859
|
-
}
|
|
860
|
-
// Port
|
|
861
|
-
let port = options.port ? (0, input_parser_1.parsePort)(options.port) : undefined;
|
|
862
|
-
if (!port && !options.noInteractive) {
|
|
863
|
-
const { portInput } = await inquirer_1.default.prompt([
|
|
864
|
-
{
|
|
865
|
-
type: 'input',
|
|
866
|
-
name: 'portInput',
|
|
867
|
-
message: 'Enter port number the process will listen on:',
|
|
868
|
-
default: '3000',
|
|
869
|
-
validate: (i) => {
|
|
870
|
-
const p = parseInt(i, 10);
|
|
871
|
-
return (p > 0 && p <= 65535) || 'Port must be between 1 and 65535';
|
|
872
|
-
},
|
|
873
|
-
},
|
|
874
|
-
]);
|
|
875
|
-
port = (0, input_parser_1.parsePort)(portInput);
|
|
876
|
-
}
|
|
877
|
-
if (!port) {
|
|
878
|
-
throw new Error('Port is required');
|
|
879
|
-
}
|
|
880
|
-
// Working directory
|
|
881
|
-
let workingDirectory = options.workingDir;
|
|
882
|
-
if (!workingDirectory && !options.noInteractive) {
|
|
883
|
-
const { dir } = await inquirer_1.default.prompt([
|
|
884
|
-
{
|
|
885
|
-
type: 'input',
|
|
886
|
-
name: 'dir',
|
|
887
|
-
message: 'Enter working directory (leave empty for current directory):',
|
|
888
|
-
default: process.cwd(),
|
|
889
|
-
},
|
|
890
|
-
]);
|
|
891
|
-
workingDirectory = dir.trim();
|
|
892
|
-
}
|
|
893
|
-
// Environment variables
|
|
894
|
-
let env = {};
|
|
895
|
-
if (options.env) {
|
|
896
|
-
// Parse format: KEY=VALUE,KEY2=VALUE2
|
|
897
|
-
const pairs = options.env.split(',');
|
|
898
|
-
for (const pair of pairs) {
|
|
899
|
-
const [key, value] = pair.split('=');
|
|
900
|
-
if (key && value) {
|
|
901
|
-
env[key.trim()] = value.trim();
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
else if (!options.noInteractive) {
|
|
906
|
-
const { addEnv } = await inquirer_1.default.prompt([
|
|
907
|
-
{
|
|
908
|
-
type: 'confirm',
|
|
909
|
-
name: 'addEnv',
|
|
910
|
-
message: 'Add environment variables?',
|
|
911
|
-
default: false,
|
|
912
|
-
},
|
|
913
|
-
]);
|
|
914
|
-
if (addEnv) {
|
|
915
|
-
let continueAdding = true;
|
|
916
|
-
while (continueAdding) {
|
|
917
|
-
const { key, value } = await inquirer_1.default.prompt([
|
|
918
|
-
{
|
|
919
|
-
type: 'input',
|
|
920
|
-
name: 'key',
|
|
921
|
-
message: 'Environment variable name:',
|
|
922
|
-
},
|
|
923
|
-
{
|
|
924
|
-
type: 'input',
|
|
925
|
-
name: 'value',
|
|
926
|
-
message: 'Environment variable value:',
|
|
927
|
-
},
|
|
928
|
-
]);
|
|
929
|
-
if (key && value) {
|
|
930
|
-
env[key.trim()] = value.trim();
|
|
931
|
-
}
|
|
932
|
-
const { more } = await inquirer_1.default.prompt([
|
|
933
|
-
{
|
|
934
|
-
type: 'confirm',
|
|
935
|
-
name: 'more',
|
|
936
|
-
message: 'Add another environment variable?',
|
|
937
|
-
default: false,
|
|
938
|
-
},
|
|
939
|
-
]);
|
|
940
|
-
continueAdding = more;
|
|
941
|
-
}
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
// Log file
|
|
945
|
-
let logFile = options.logFile;
|
|
946
|
-
if (!logFile && !options.noInteractive) {
|
|
947
|
-
const { addLog } = await inquirer_1.default.prompt([
|
|
948
|
-
{
|
|
949
|
-
type: 'confirm',
|
|
950
|
-
name: 'addLog',
|
|
951
|
-
message: 'Capture logs to file?',
|
|
952
|
-
default: false,
|
|
953
|
-
},
|
|
954
|
-
]);
|
|
955
|
-
if (addLog) {
|
|
956
|
-
const { path: logPath } = await inquirer_1.default.prompt([
|
|
957
|
-
{
|
|
958
|
-
type: 'input',
|
|
959
|
-
name: 'path',
|
|
960
|
-
message: 'Log file path:',
|
|
961
|
-
default: `/var/log/${appName}.log`,
|
|
962
|
-
},
|
|
963
|
-
]);
|
|
964
|
-
logFile = logPath.trim();
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
// Description
|
|
968
|
-
const description = options.description || `Managed process application for ${appName}`;
|
|
969
|
-
// Protocol
|
|
970
|
-
const protocol = (0, input_parser_1.parseProtocol)(options.protocol);
|
|
971
|
-
// Device IDs and Gateway IDs
|
|
972
|
-
let deviceId = options.deviceId;
|
|
973
|
-
let gatewayIds = (0, input_parser_1.parseGatewayIds)(options.gatewayIds);
|
|
974
|
-
let hostnames = Array.isArray(options.hostnames)
|
|
975
|
-
? options.hostnames
|
|
976
|
-
: (typeof options.hostnames === 'string' && options.hostnames.trim().length > 0
|
|
977
|
-
? options.hostnames.split(',').map(s => s.trim()).filter(Boolean)
|
|
978
|
-
: []);
|
|
979
|
-
let useManagedGateway = false;
|
|
980
|
-
if (!options.noInteractive) {
|
|
981
|
-
// Optional: prompt for additional hostnames
|
|
982
|
-
const { addHostnames } = await inquirer_1.default.prompt([
|
|
983
|
-
{
|
|
984
|
-
type: 'input',
|
|
985
|
-
name: 'addHostnames',
|
|
986
|
-
message: 'Additional hostnames (comma-separated, optional):',
|
|
987
|
-
when: () => hostnames.length === 0,
|
|
988
|
-
},
|
|
989
|
-
]);
|
|
990
|
-
if (addHostnames && typeof addHostnames === 'string') {
|
|
991
|
-
hostnames = addHostnames.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
|
|
992
|
-
}
|
|
993
|
-
// Prompt for managed gateway option
|
|
994
|
-
if (gatewayIds.length === 0) {
|
|
995
|
-
const { useManaged } = await inquirer_1.default.prompt([
|
|
996
|
-
{
|
|
997
|
-
type: 'confirm',
|
|
998
|
-
name: 'useManaged',
|
|
999
|
-
message: 'Use Edgible managed gateway?',
|
|
1000
|
-
default: false,
|
|
1001
|
-
},
|
|
1002
|
-
]);
|
|
1003
|
-
useManagedGateway = useManaged;
|
|
1004
|
-
if (!useManagedGateway) {
|
|
1005
|
-
// Ask if they want to assign a gateway at all
|
|
1006
|
-
const { assignGateway } = await inquirer_1.default.prompt([
|
|
1007
|
-
{
|
|
1008
|
-
type: 'confirm',
|
|
1009
|
-
name: 'assignGateway',
|
|
1010
|
-
message: 'Assign a gateway to this application? (No = local/internal access only)',
|
|
1011
|
-
default: true,
|
|
1012
|
-
},
|
|
1013
|
-
]);
|
|
1014
|
-
if (assignGateway) {
|
|
1015
|
-
// Try to offer a list of gateways (via service), else fallback to manual input
|
|
1016
|
-
try {
|
|
1017
|
-
const gatewaysResp = await gatewayService.listGateways();
|
|
1018
|
-
const gatewayChoices = gatewaysResp.gateways.map((g) => ({
|
|
1019
|
-
name: `${g.device.name} (${g.device.id})`,
|
|
1020
|
-
value: g.device.id,
|
|
1021
|
-
}));
|
|
1022
|
-
if (gatewayChoices.length > 0) {
|
|
1023
|
-
const { selectedGateways } = await inquirer_1.default.prompt([
|
|
1024
|
-
{
|
|
1025
|
-
type: 'checkbox',
|
|
1026
|
-
name: 'selectedGateways',
|
|
1027
|
-
message: 'Select gateway device(s):',
|
|
1028
|
-
choices: gatewayChoices,
|
|
1029
|
-
validate: (vals) => vals.length > 0 ? true : 'Select at least one gateway',
|
|
1030
|
-
},
|
|
1031
|
-
]);
|
|
1032
|
-
gatewayIds = selectedGateways;
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
catch (error) {
|
|
1036
|
-
logger.warn('Failed to list gateways', error);
|
|
1037
|
-
}
|
|
1038
|
-
if (gatewayIds.length === 0) {
|
|
1039
|
-
const ans2 = await inquirer_1.default.prompt([
|
|
1040
|
-
{
|
|
1041
|
-
type: 'input',
|
|
1042
|
-
name: 'gatewayIds',
|
|
1043
|
-
message: 'Enter comma-separated gateway device IDs (or leave empty for no gateway):',
|
|
1044
|
-
validate: (v) => true, // Allow empty input
|
|
1045
|
-
},
|
|
1046
|
-
]);
|
|
1047
|
-
if (ans2.gatewayIds && ans2.gatewayIds.trim()) {
|
|
1048
|
-
gatewayIds = (0, input_parser_1.parseGatewayIds)(ans2.gatewayIds);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
}
|
|
1052
|
-
else {
|
|
1053
|
-
logger.info('Application will be created without gateway assignment (local/internal access only)');
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
// Serving device selection
|
|
1058
|
-
if (!deviceId) {
|
|
1059
|
-
try {
|
|
1060
|
-
const servingDevicesResp = await edgibleService.listServingDevices();
|
|
1061
|
-
const servingDeviceChoices = Array.isArray(servingDevicesResp?.devices)
|
|
1062
|
-
? servingDevicesResp.devices.map((d) => ({
|
|
1063
|
-
name: `${d.name || d.id}${d.description ? ` - ${d.description}` : ''}`,
|
|
1064
|
-
value: d.id,
|
|
1065
|
-
}))
|
|
1066
|
-
: [];
|
|
1067
|
-
if (servingDeviceChoices.length > 0) {
|
|
1068
|
-
const { selectedDeviceId } = await inquirer_1.default.prompt([
|
|
1069
|
-
{
|
|
1070
|
-
type: 'list',
|
|
1071
|
-
name: 'selectedDeviceId',
|
|
1072
|
-
message: 'Select serving device:',
|
|
1073
|
-
choices: servingDeviceChoices,
|
|
1074
|
-
},
|
|
1075
|
-
]);
|
|
1076
|
-
deviceId = selectedDeviceId;
|
|
1077
|
-
}
|
|
1078
|
-
else {
|
|
1079
|
-
// Fallback to manual input if no serving devices found
|
|
1080
|
-
const ans = await inquirer_1.default.prompt([
|
|
1081
|
-
{
|
|
1082
|
-
type: 'input',
|
|
1083
|
-
name: 'deviceId',
|
|
1084
|
-
message: 'Enter serving device ID:',
|
|
1085
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
1086
|
-
},
|
|
1087
|
-
]);
|
|
1088
|
-
deviceId = String(ans.deviceId).trim();
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
catch (error) {
|
|
1092
|
-
logger.warn('Failed to list serving devices', error);
|
|
1093
|
-
// Fallback to manual input if listing fails
|
|
1094
|
-
const ans = await inquirer_1.default.prompt([
|
|
1095
|
-
{
|
|
1096
|
-
type: 'input',
|
|
1097
|
-
name: 'deviceId',
|
|
1098
|
-
message: 'Enter serving device ID:',
|
|
1099
|
-
validate: (v) => v && v.trim().length > 0 ? true : 'Serving device ID is required',
|
|
1100
|
-
},
|
|
1101
|
-
]);
|
|
1102
|
-
deviceId = String(ans.deviceId).trim();
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
if (!deviceId) {
|
|
1107
|
-
throw new Error('--device-id (serving) is required');
|
|
1108
|
-
}
|
|
1109
|
-
if (!useManagedGateway && gatewayIds.length === 0) {
|
|
1110
|
-
logger.warn('No gateways assigned - application will only be accessible locally/internally');
|
|
1111
|
-
}
|
|
1112
|
-
// Build configuration
|
|
1113
|
-
const configuration = {
|
|
1114
|
-
command,
|
|
1115
|
-
};
|
|
1116
|
-
if (workingDirectory) {
|
|
1117
|
-
configuration.workingDirectory = workingDirectory;
|
|
1118
|
-
}
|
|
1119
|
-
if (Object.keys(env).length > 0) {
|
|
1120
|
-
configuration.env = env;
|
|
1121
|
-
}
|
|
1122
|
-
if (logFile) {
|
|
1123
|
-
configuration.logFile = logFile;
|
|
1124
|
-
}
|
|
1125
|
-
// Create application
|
|
1126
|
-
logger.info('Creating managed process application', {
|
|
1127
|
-
name: appName,
|
|
1128
|
-
port,
|
|
1129
|
-
protocol,
|
|
1130
|
-
command,
|
|
1131
|
-
deviceId,
|
|
1132
|
-
gatewayIds,
|
|
1133
|
-
subtype: 'managed-process',
|
|
1134
|
-
});
|
|
1135
|
-
console.log(chalk_1.default.blue(`\nCreating managed process application: ${appName}`));
|
|
1136
|
-
console.log(chalk_1.default.gray(`Command: ${command}`));
|
|
1137
|
-
console.log(chalk_1.default.gray(`Port: ${port}`));
|
|
1138
|
-
console.log(chalk_1.default.gray(`Protocol: ${protocol.toUpperCase()}`));
|
|
1139
|
-
if (workingDirectory) {
|
|
1140
|
-
console.log(chalk_1.default.gray(`Working directory: ${workingDirectory}`));
|
|
1141
|
-
}
|
|
1142
|
-
if (Object.keys(env).length > 0) {
|
|
1143
|
-
console.log(chalk_1.default.gray(`Environment variables: ${Object.keys(env).length} variable(s)`));
|
|
1144
|
-
}
|
|
1145
|
-
if (logFile) {
|
|
1146
|
-
console.log(chalk_1.default.gray(`Log file: ${logFile}`));
|
|
1147
|
-
}
|
|
1148
|
-
console.log(chalk_1.default.gray(`Serving device: ${deviceId}`));
|
|
1149
|
-
if (useManagedGateway) {
|
|
1150
|
-
console.log(chalk_1.default.gray(`Using Edgible managed gateway`));
|
|
1151
|
-
}
|
|
1152
|
-
else {
|
|
1153
|
-
console.log(chalk_1.default.gray(`Gateways: ${gatewayIds.join(', ')}`));
|
|
1154
|
-
}
|
|
1155
|
-
if (hostnames.length > 0) {
|
|
1156
|
-
console.log(chalk_1.default.gray(`Additional hostnames: ${hostnames.join(', ')}`));
|
|
1157
|
-
}
|
|
1158
|
-
const result = await applicationService.createApplicationProgrammatically({
|
|
1159
|
-
name: appName,
|
|
1160
|
-
description,
|
|
1161
|
-
port,
|
|
1162
|
-
protocol,
|
|
1163
|
-
hostnames,
|
|
1164
|
-
deviceIds: [deviceId],
|
|
1165
|
-
gatewayIds: useManagedGateway ? undefined : gatewayIds,
|
|
1166
|
-
useManagedGateway,
|
|
1167
|
-
subtype: 'managed-process',
|
|
1168
|
-
configuration,
|
|
1169
|
-
});
|
|
1170
|
-
console.log(chalk_1.default.green('\n✓ Managed process application created successfully!'));
|
|
1171
|
-
console.log(chalk_1.default.blue('\n📋 Application Details:'));
|
|
1172
|
-
if (result && typeof result === 'object' && 'name' in result) {
|
|
1173
|
-
const app = result;
|
|
1174
|
-
console.log(chalk_1.default.white(` Name: ${app.name}`));
|
|
1175
|
-
console.log(chalk_1.default.white(` ID: ${app.id}`));
|
|
1176
|
-
if (app.url)
|
|
1177
|
-
console.log(chalk_1.default.white(` URL: ${chalk_1.default.cyan.bold(app.url)}`));
|
|
1178
|
-
console.log(chalk_1.default.white(` Status: ${app.status}`));
|
|
1179
|
-
}
|
|
1180
|
-
console.log(chalk_1.default.yellow('\n⚠ Note: The agent will start the process when it receives the configuration.'));
|
|
114
|
+
await (0, create_managed_process_1.handleApplicationCreateManagedProcess)(options);
|
|
1181
115
|
}, {
|
|
1182
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1183
116
|
requireAuth: true,
|
|
1184
117
|
requireOrganization: true,
|
|
1185
118
|
}));
|
|
@@ -1187,27 +120,24 @@ Examples:
|
|
|
1187
120
|
const createDockerCommand = new commander_1.Command('docker')
|
|
1188
121
|
.description('Create application from Docker container (not implemented)')
|
|
1189
122
|
.action((0, command_wrapper_1.wrapCommand)(async () => {
|
|
1190
|
-
|
|
123
|
+
await (0, create_stubs_1.handleApplicationCreateDocker)();
|
|
1191
124
|
}, {
|
|
1192
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1193
125
|
requireAuth: false,
|
|
1194
126
|
requireOrganization: false,
|
|
1195
127
|
}));
|
|
1196
128
|
const createQemuCommand = new commander_1.Command('qemu')
|
|
1197
129
|
.description('Create application from QEMU VM (not implemented)')
|
|
1198
130
|
.action((0, command_wrapper_1.wrapCommand)(async () => {
|
|
1199
|
-
|
|
131
|
+
await (0, create_stubs_1.handleApplicationCreateQemu)();
|
|
1200
132
|
}, {
|
|
1201
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1202
133
|
requireAuth: false,
|
|
1203
134
|
requireOrganization: false,
|
|
1204
135
|
}));
|
|
1205
136
|
const createPodmanCommand = new commander_1.Command('podman')
|
|
1206
137
|
.description('Create application from Podman container (not implemented)')
|
|
1207
138
|
.action((0, command_wrapper_1.wrapCommand)(async () => {
|
|
1208
|
-
|
|
139
|
+
await (0, create_stubs_1.handleApplicationCreatePodman)();
|
|
1209
140
|
}, {
|
|
1210
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1211
141
|
requireAuth: false,
|
|
1212
142
|
requireOrganization: false,
|
|
1213
143
|
}));
|
|
@@ -1226,38 +156,8 @@ Examples:
|
|
|
1226
156
|
.alias('status')
|
|
1227
157
|
.alias('info')
|
|
1228
158
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1229
|
-
|
|
1230
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1231
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1232
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1233
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1234
|
-
requireAuth: true,
|
|
1235
|
-
requireOrganization: true,
|
|
1236
|
-
});
|
|
1237
|
-
if (!options.appId) {
|
|
1238
|
-
throw new Error('--app-id is required. Usage: edgible application get --app-id <id> [--json]');
|
|
1239
|
-
}
|
|
1240
|
-
logger.debug('Getting application', { appId: options.appId });
|
|
1241
|
-
const app = await applicationService.getApplication(options.appId);
|
|
1242
|
-
if (options.json) {
|
|
1243
|
-
console.log(JSON.stringify({
|
|
1244
|
-
id: app.id,
|
|
1245
|
-
name: app.name,
|
|
1246
|
-
description: app.description || '',
|
|
1247
|
-
url: app.url || '',
|
|
1248
|
-
servingIp: app.servingIp,
|
|
1249
|
-
port: app.port,
|
|
1250
|
-
protocol: app.protocol,
|
|
1251
|
-
status: app.status,
|
|
1252
|
-
workloadId: app.workloadId || '',
|
|
1253
|
-
createdAt: app.createdAt,
|
|
1254
|
-
}, null, 2));
|
|
1255
|
-
}
|
|
1256
|
-
else {
|
|
1257
|
-
console.log((0, output_formatter_1.formatApplication)(app));
|
|
1258
|
-
}
|
|
159
|
+
await (0, get_1.handleApplicationGet)(options);
|
|
1259
160
|
}, {
|
|
1260
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1261
161
|
requireAuth: true,
|
|
1262
162
|
requireOrganization: true,
|
|
1263
163
|
}));
|
|
@@ -1266,7 +166,7 @@ Examples:
|
|
|
1266
166
|
.description('Update an existing application')
|
|
1267
167
|
.option('-i, --app-id <id>', 'Application ID')
|
|
1268
168
|
.action(async (options) => {
|
|
1269
|
-
|
|
169
|
+
await (0, update_1.handleApplicationUpdate)(options);
|
|
1270
170
|
});
|
|
1271
171
|
appCommand
|
|
1272
172
|
.command('delete')
|
|
@@ -1276,75 +176,8 @@ Examples:
|
|
|
1276
176
|
.option('--no-interactive', 'Run in non-interactive mode')
|
|
1277
177
|
.alias('rm')
|
|
1278
178
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1279
|
-
|
|
1280
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1281
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1282
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1283
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1284
|
-
requireAuth: true,
|
|
1285
|
-
requireOrganization: true,
|
|
1286
|
-
});
|
|
1287
|
-
let appId = options.appId;
|
|
1288
|
-
// Interactive mode: prompt for application if not provided
|
|
1289
|
-
if (!appId && options.interactive !== false) {
|
|
1290
|
-
logger.debug('Fetching applications for interactive selection');
|
|
1291
|
-
const applications = await applicationService.getApplications();
|
|
1292
|
-
if (applications.length === 0) {
|
|
1293
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1294
|
-
console.log(chalk_1.default.gray('Use "edgible application create" to create an application'));
|
|
1295
|
-
return;
|
|
1296
|
-
}
|
|
1297
|
-
const choices = applications.map((app) => ({
|
|
1298
|
-
name: `${app.name} (${app.id})${app.description ? ` - ${app.description}` : ''}`,
|
|
1299
|
-
value: app.id,
|
|
1300
|
-
}));
|
|
1301
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1302
|
-
{
|
|
1303
|
-
type: 'list',
|
|
1304
|
-
name: 'selectedAppId',
|
|
1305
|
-
message: 'Select application to delete:',
|
|
1306
|
-
choices,
|
|
1307
|
-
},
|
|
1308
|
-
]);
|
|
1309
|
-
appId = selectedAppId;
|
|
1310
|
-
}
|
|
1311
|
-
if (!appId) {
|
|
1312
|
-
throw new Error('--app-id is required in non-interactive mode. Usage: edgible application delete --app-id <id>');
|
|
1313
|
-
}
|
|
1314
|
-
logger.debug('Deleting application', { appId });
|
|
1315
|
-
// Get application details for confirmation
|
|
1316
|
-
let appName = appId;
|
|
1317
|
-
let app;
|
|
1318
|
-
try {
|
|
1319
|
-
app = await applicationService.getApplication(appId);
|
|
1320
|
-
appName = app.name;
|
|
1321
|
-
}
|
|
1322
|
-
catch (error) {
|
|
1323
|
-
logger.debug('Could not fetch application details for confirmation', error);
|
|
1324
|
-
}
|
|
1325
|
-
// Confirm deletion unless --force is used
|
|
1326
|
-
if (!options.force) {
|
|
1327
|
-
const confirmMessage = app
|
|
1328
|
-
? `Are you sure you want to delete application "${appName}" (${appId})?`
|
|
1329
|
-
: `Are you sure you want to delete application ${appId}?`;
|
|
1330
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
1331
|
-
{
|
|
1332
|
-
type: 'confirm',
|
|
1333
|
-
name: 'confirm',
|
|
1334
|
-
message: confirmMessage,
|
|
1335
|
-
default: false,
|
|
1336
|
-
},
|
|
1337
|
-
]);
|
|
1338
|
-
if (!confirm) {
|
|
1339
|
-
logger.info('Application deletion cancelled');
|
|
1340
|
-
console.log(chalk_1.default.gray('Deletion cancelled'));
|
|
1341
|
-
return;
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
await applicationService.deleteApplication(appId);
|
|
1345
|
-
console.log(chalk_1.default.green('\n✓ Application deleted successfully!'));
|
|
179
|
+
await (0, delete_1.handleApplicationDelete)(options);
|
|
1346
180
|
}, {
|
|
1347
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1348
181
|
requireAuth: true,
|
|
1349
182
|
requireOrganization: true,
|
|
1350
183
|
}));
|
|
@@ -1360,64 +193,8 @@ Examples:
|
|
|
1360
193
|
.option('--json', 'Output as JSON')
|
|
1361
194
|
.alias('ls')
|
|
1362
195
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1363
|
-
|
|
1364
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1365
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1366
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1367
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1368
|
-
requireAuth: true,
|
|
1369
|
-
requireOrganization: true,
|
|
1370
|
-
});
|
|
1371
|
-
let appId = options.appId;
|
|
1372
|
-
if (!appId) {
|
|
1373
|
-
const applications = await applicationService.getApplications();
|
|
1374
|
-
if (applications.length === 0) {
|
|
1375
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1376
|
-
return;
|
|
1377
|
-
}
|
|
1378
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1379
|
-
{
|
|
1380
|
-
type: 'list',
|
|
1381
|
-
name: 'selectedAppId',
|
|
1382
|
-
message: 'Select application:',
|
|
1383
|
-
choices: applications.map((app) => ({
|
|
1384
|
-
name: `${app.name} (${app.id})`,
|
|
1385
|
-
value: app.id,
|
|
1386
|
-
})),
|
|
1387
|
-
},
|
|
1388
|
-
]);
|
|
1389
|
-
appId = selectedAppId;
|
|
1390
|
-
}
|
|
1391
|
-
if (!appId) {
|
|
1392
|
-
throw new Error('Application ID is required');
|
|
1393
|
-
}
|
|
1394
|
-
const keys = await applicationService.listApiKeys(appId);
|
|
1395
|
-
if (options.json) {
|
|
1396
|
-
console.log(JSON.stringify({ keys }, null, 2));
|
|
1397
|
-
return;
|
|
1398
|
-
}
|
|
1399
|
-
if (keys.length === 0) {
|
|
1400
|
-
console.log(chalk_1.default.yellow('⚠ No API keys configured'));
|
|
1401
|
-
console.log(chalk_1.default.gray('Use "edgible application api-keys create" to create an API key'));
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
console.log(chalk_1.default.bold('\n🔑 API Keys:\n'));
|
|
1405
|
-
keys.forEach((key, index) => {
|
|
1406
|
-
console.log(`${index + 1}. ${chalk_1.default.cyan(key.name)}`);
|
|
1407
|
-
console.log(` ID: ${chalk_1.default.gray(key.id)}`);
|
|
1408
|
-
console.log(` Prefix: ${chalk_1.default.gray(key.keyPrefix)}`);
|
|
1409
|
-
console.log(` Created: ${chalk_1.default.gray(new Date(key.createdAt).toLocaleString())}`);
|
|
1410
|
-
console.log(` Status: ${key.enabled ? chalk_1.default.green('Enabled') : chalk_1.default.red('Disabled')}`);
|
|
1411
|
-
if (key.expiresAt) {
|
|
1412
|
-
console.log(` Expires: ${chalk_1.default.gray(new Date(key.expiresAt).toLocaleString())}`);
|
|
1413
|
-
}
|
|
1414
|
-
if (key.lastUsedAt) {
|
|
1415
|
-
console.log(` Last used: ${chalk_1.default.gray(new Date(key.lastUsedAt).toLocaleString())}`);
|
|
1416
|
-
}
|
|
1417
|
-
console.log();
|
|
1418
|
-
});
|
|
196
|
+
await (0, list_2.handleApiKeysList)(options);
|
|
1419
197
|
}, {
|
|
1420
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1421
198
|
requireAuth: true,
|
|
1422
199
|
requireOrganization: true,
|
|
1423
200
|
}));
|
|
@@ -1429,67 +206,8 @@ Examples:
|
|
|
1429
206
|
.option('--expires <date>', 'Expiration date (ISO format)')
|
|
1430
207
|
.alias('new')
|
|
1431
208
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1432
|
-
|
|
1433
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1434
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1435
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1436
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1437
|
-
requireAuth: true,
|
|
1438
|
-
requireOrganization: true,
|
|
1439
|
-
});
|
|
1440
|
-
let appId = options.appId;
|
|
1441
|
-
if (!appId) {
|
|
1442
|
-
const applications = await applicationService.getApplications();
|
|
1443
|
-
if (applications.length === 0) {
|
|
1444
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1445
|
-
return;
|
|
1446
|
-
}
|
|
1447
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1448
|
-
{
|
|
1449
|
-
type: 'list',
|
|
1450
|
-
name: 'selectedAppId',
|
|
1451
|
-
message: 'Select application:',
|
|
1452
|
-
choices: applications.map((app) => ({
|
|
1453
|
-
name: `${app.name} (${app.id})`,
|
|
1454
|
-
value: app.id,
|
|
1455
|
-
})),
|
|
1456
|
-
},
|
|
1457
|
-
]);
|
|
1458
|
-
appId = selectedAppId;
|
|
1459
|
-
}
|
|
1460
|
-
if (!appId) {
|
|
1461
|
-
throw new Error('Application ID is required');
|
|
1462
|
-
}
|
|
1463
|
-
let name = options.name;
|
|
1464
|
-
if (!name) {
|
|
1465
|
-
const { keyName } = await inquirer_1.default.prompt([
|
|
1466
|
-
{
|
|
1467
|
-
type: 'input',
|
|
1468
|
-
name: 'keyName',
|
|
1469
|
-
message: 'Enter a name for this API key:',
|
|
1470
|
-
validate: (input) => input.trim().length > 0 || 'Name is required',
|
|
1471
|
-
},
|
|
1472
|
-
]);
|
|
1473
|
-
name = keyName;
|
|
1474
|
-
}
|
|
1475
|
-
if (!name) {
|
|
1476
|
-
throw new Error('Name is required');
|
|
1477
|
-
}
|
|
1478
|
-
const result = await applicationService.createApiKey(appId, name, options.expires);
|
|
1479
|
-
console.log(chalk_1.default.green('\n✓ API key created successfully!\n'));
|
|
1480
|
-
console.log(chalk_1.default.bold.red('⚠️ IMPORTANT: Save this API key now. It will not be shown again!\n'));
|
|
1481
|
-
console.log(chalk_1.default.cyan('API Key:'), chalk_1.default.bold(result.apiKey));
|
|
1482
|
-
console.log(chalk_1.default.gray('\nKey Details:'));
|
|
1483
|
-
console.log(` Name: ${result.keyData.name}`);
|
|
1484
|
-
console.log(` Key ID: ${result.keyData.id}`);
|
|
1485
|
-
console.log(` Key Prefix: ${result.keyData.keyPrefix}`);
|
|
1486
|
-
console.log(` Full ID: ${result.keyData.keyPrefix}-${result.keyData.id}`);
|
|
1487
|
-
if (result.keyData.expiresAt) {
|
|
1488
|
-
console.log(` Expires: ${new Date(result.keyData.expiresAt).toLocaleString()}`);
|
|
1489
|
-
}
|
|
1490
|
-
console.log();
|
|
209
|
+
await (0, create_1.handleApiKeysCreate)(options);
|
|
1491
210
|
}, {
|
|
1492
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1493
211
|
requireAuth: true,
|
|
1494
212
|
requireOrganization: true,
|
|
1495
213
|
}));
|
|
@@ -1501,78 +219,8 @@ Examples:
|
|
|
1501
219
|
.option('-f, --force', 'Skip confirmation prompt')
|
|
1502
220
|
.alias('rm')
|
|
1503
221
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1504
|
-
|
|
1505
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1506
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1507
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1508
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1509
|
-
requireAuth: true,
|
|
1510
|
-
requireOrganization: true,
|
|
1511
|
-
});
|
|
1512
|
-
let appId = options.appId;
|
|
1513
|
-
if (!appId) {
|
|
1514
|
-
const applications = await applicationService.getApplications();
|
|
1515
|
-
if (applications.length === 0) {
|
|
1516
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1517
|
-
return;
|
|
1518
|
-
}
|
|
1519
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1520
|
-
{
|
|
1521
|
-
type: 'list',
|
|
1522
|
-
name: 'selectedAppId',
|
|
1523
|
-
message: 'Select application:',
|
|
1524
|
-
choices: applications.map((app) => ({
|
|
1525
|
-
name: `${app.name} (${app.id})`,
|
|
1526
|
-
value: app.id,
|
|
1527
|
-
})),
|
|
1528
|
-
},
|
|
1529
|
-
]);
|
|
1530
|
-
appId = selectedAppId;
|
|
1531
|
-
}
|
|
1532
|
-
if (!appId) {
|
|
1533
|
-
throw new Error('Application ID is required');
|
|
1534
|
-
}
|
|
1535
|
-
let keyId = options.keyId;
|
|
1536
|
-
if (!keyId) {
|
|
1537
|
-
const keys = await applicationService.listApiKeys(appId);
|
|
1538
|
-
if (keys.length === 0) {
|
|
1539
|
-
console.log(chalk_1.default.yellow('⚠ No API keys configured'));
|
|
1540
|
-
return;
|
|
1541
|
-
}
|
|
1542
|
-
const { selectedKeyId } = await inquirer_1.default.prompt([
|
|
1543
|
-
{
|
|
1544
|
-
type: 'list',
|
|
1545
|
-
name: 'selectedKeyId',
|
|
1546
|
-
message: 'Select API key to delete:',
|
|
1547
|
-
choices: keys.map((key) => ({
|
|
1548
|
-
name: `${key.name} (${key.keyPrefix})`,
|
|
1549
|
-
value: key.id,
|
|
1550
|
-
})),
|
|
1551
|
-
},
|
|
1552
|
-
]);
|
|
1553
|
-
keyId = selectedKeyId;
|
|
1554
|
-
}
|
|
1555
|
-
if (!options.force) {
|
|
1556
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
1557
|
-
{
|
|
1558
|
-
type: 'confirm',
|
|
1559
|
-
name: 'confirm',
|
|
1560
|
-
message: 'Are you sure you want to delete this API key?',
|
|
1561
|
-
default: false,
|
|
1562
|
-
},
|
|
1563
|
-
]);
|
|
1564
|
-
if (!confirm) {
|
|
1565
|
-
console.log(chalk_1.default.gray('Deletion cancelled'));
|
|
1566
|
-
return;
|
|
1567
|
-
}
|
|
1568
|
-
}
|
|
1569
|
-
if (!keyId) {
|
|
1570
|
-
throw new Error('Key ID is required');
|
|
1571
|
-
}
|
|
1572
|
-
await applicationService.deleteApiKey(appId, keyId);
|
|
1573
|
-
console.log(chalk_1.default.green('\n✓ API key deleted successfully!'));
|
|
222
|
+
await (0, delete_2.handleApiKeysDelete)(options);
|
|
1574
223
|
}, {
|
|
1575
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1576
224
|
requireAuth: true,
|
|
1577
225
|
requireOrganization: true,
|
|
1578
226
|
}));
|
|
@@ -1588,62 +236,8 @@ Examples:
|
|
|
1588
236
|
.option('--json', 'Output as JSON')
|
|
1589
237
|
.alias('ls')
|
|
1590
238
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1591
|
-
|
|
1592
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1593
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1594
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1595
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1596
|
-
requireAuth: true,
|
|
1597
|
-
requireOrganization: true,
|
|
1598
|
-
});
|
|
1599
|
-
let appId = options.appId;
|
|
1600
|
-
if (!appId) {
|
|
1601
|
-
const applications = await applicationService.getApplications();
|
|
1602
|
-
if (applications.length === 0) {
|
|
1603
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1604
|
-
return;
|
|
1605
|
-
}
|
|
1606
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1607
|
-
{
|
|
1608
|
-
type: 'list',
|
|
1609
|
-
name: 'selectedAppId',
|
|
1610
|
-
message: 'Select application:',
|
|
1611
|
-
choices: applications.map((app) => ({
|
|
1612
|
-
name: `${app.name} (${app.id})`,
|
|
1613
|
-
value: app.id,
|
|
1614
|
-
})),
|
|
1615
|
-
},
|
|
1616
|
-
]);
|
|
1617
|
-
appId = selectedAppId;
|
|
1618
|
-
}
|
|
1619
|
-
if (!appId) {
|
|
1620
|
-
throw new Error('Application ID is required');
|
|
1621
|
-
}
|
|
1622
|
-
const codes = await applicationService.listShortCodes(appId);
|
|
1623
|
-
if (options.json) {
|
|
1624
|
-
console.log(JSON.stringify({ codes }, null, 2));
|
|
1625
|
-
return;
|
|
1626
|
-
}
|
|
1627
|
-
if (codes.length === 0) {
|
|
1628
|
-
console.log(chalk_1.default.yellow('⚠ No short codes configured'));
|
|
1629
|
-
console.log(chalk_1.default.gray('Use "edgible application short-codes create" to create a short code'));
|
|
1630
|
-
return;
|
|
1631
|
-
}
|
|
1632
|
-
console.log(chalk_1.default.bold('\n🔗 Short Codes:\n'));
|
|
1633
|
-
codes.forEach((code, index) => {
|
|
1634
|
-
console.log(`${index + 1}. ${chalk_1.default.cyan(code.name)}`);
|
|
1635
|
-
console.log(` Code: ${chalk_1.default.bold.green(code.code)}`);
|
|
1636
|
-
console.log(` ID: ${chalk_1.default.gray(code.id)}`);
|
|
1637
|
-
console.log(` Created: ${chalk_1.default.gray(new Date(code.createdAt).toLocaleString())}`);
|
|
1638
|
-
console.log(` Status: ${code.enabled ? chalk_1.default.green('Enabled') : chalk_1.default.red('Disabled')}`);
|
|
1639
|
-
console.log(` Uses: ${chalk_1.default.gray(code.usedCount)}${code.maxUses ? ` / ${code.maxUses}` : ''}`);
|
|
1640
|
-
if (code.expiresAt) {
|
|
1641
|
-
console.log(` Expires: ${chalk_1.default.gray(new Date(code.expiresAt).toLocaleString())}`);
|
|
1642
|
-
}
|
|
1643
|
-
console.log();
|
|
1644
|
-
});
|
|
239
|
+
await (0, list_3.handleShortCodesList)(options);
|
|
1645
240
|
}, {
|
|
1646
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1647
241
|
requireAuth: true,
|
|
1648
242
|
requireOrganization: true,
|
|
1649
243
|
}));
|
|
@@ -1656,68 +250,8 @@ Examples:
|
|
|
1656
250
|
.option('--max-uses <number>', 'Maximum number of uses')
|
|
1657
251
|
.alias('new')
|
|
1658
252
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1659
|
-
|
|
1660
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1661
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1662
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1663
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1664
|
-
requireAuth: true,
|
|
1665
|
-
requireOrganization: true,
|
|
1666
|
-
});
|
|
1667
|
-
let appId = options.appId;
|
|
1668
|
-
if (!appId) {
|
|
1669
|
-
const applications = await applicationService.getApplications();
|
|
1670
|
-
if (applications.length === 0) {
|
|
1671
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1672
|
-
return;
|
|
1673
|
-
}
|
|
1674
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1675
|
-
{
|
|
1676
|
-
type: 'list',
|
|
1677
|
-
name: 'selectedAppId',
|
|
1678
|
-
message: 'Select application:',
|
|
1679
|
-
choices: applications.map((app) => ({
|
|
1680
|
-
name: `${app.name} (${app.id})`,
|
|
1681
|
-
value: app.id,
|
|
1682
|
-
})),
|
|
1683
|
-
},
|
|
1684
|
-
]);
|
|
1685
|
-
appId = selectedAppId;
|
|
1686
|
-
}
|
|
1687
|
-
if (!appId) {
|
|
1688
|
-
throw new Error('Application ID is required');
|
|
1689
|
-
}
|
|
1690
|
-
let name = options.name;
|
|
1691
|
-
if (!name) {
|
|
1692
|
-
const { codeName } = await inquirer_1.default.prompt([
|
|
1693
|
-
{
|
|
1694
|
-
type: 'input',
|
|
1695
|
-
name: 'codeName',
|
|
1696
|
-
message: 'Enter a name/description for this short code:',
|
|
1697
|
-
validate: (input) => input.trim().length > 0 || 'Name is required',
|
|
1698
|
-
},
|
|
1699
|
-
]);
|
|
1700
|
-
name = codeName;
|
|
1701
|
-
}
|
|
1702
|
-
if (!name) {
|
|
1703
|
-
throw new Error('Name is required');
|
|
1704
|
-
}
|
|
1705
|
-
const maxUses = options.maxUses ? parseInt(options.maxUses) : undefined;
|
|
1706
|
-
const code = await applicationService.createShortCode(appId, name, options.expires, maxUses);
|
|
1707
|
-
console.log(chalk_1.default.green('\n✓ Short code created successfully!\n'));
|
|
1708
|
-
console.log(chalk_1.default.bold('Share this code:'), chalk_1.default.bold.green(code.code));
|
|
1709
|
-
console.log(chalk_1.default.gray('\nCode Details:'));
|
|
1710
|
-
console.log(` Name: ${code.name}`);
|
|
1711
|
-
console.log(` ID: ${code.id}`);
|
|
1712
|
-
if (code.maxUses) {
|
|
1713
|
-
console.log(` Max uses: ${code.maxUses}`);
|
|
1714
|
-
}
|
|
1715
|
-
if (code.expiresAt) {
|
|
1716
|
-
console.log(` Expires: ${new Date(code.expiresAt).toLocaleString()}`);
|
|
1717
|
-
}
|
|
1718
|
-
console.log();
|
|
253
|
+
await (0, create_2.handleShortCodesCreate)(options);
|
|
1719
254
|
}, {
|
|
1720
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1721
255
|
requireAuth: true,
|
|
1722
256
|
requireOrganization: true,
|
|
1723
257
|
}));
|
|
@@ -1729,78 +263,8 @@ Examples:
|
|
|
1729
263
|
.option('-f, --force', 'Skip confirmation prompt')
|
|
1730
264
|
.alias('rm')
|
|
1731
265
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1732
|
-
|
|
1733
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1734
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1735
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1736
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1737
|
-
requireAuth: true,
|
|
1738
|
-
requireOrganization: true,
|
|
1739
|
-
});
|
|
1740
|
-
let appId = options.appId;
|
|
1741
|
-
if (!appId) {
|
|
1742
|
-
const applications = await applicationService.getApplications();
|
|
1743
|
-
if (applications.length === 0) {
|
|
1744
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1745
|
-
return;
|
|
1746
|
-
}
|
|
1747
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1748
|
-
{
|
|
1749
|
-
type: 'list',
|
|
1750
|
-
name: 'selectedAppId',
|
|
1751
|
-
message: 'Select application:',
|
|
1752
|
-
choices: applications.map((app) => ({
|
|
1753
|
-
name: `${app.name} (${app.id})`,
|
|
1754
|
-
value: app.id,
|
|
1755
|
-
})),
|
|
1756
|
-
},
|
|
1757
|
-
]);
|
|
1758
|
-
appId = selectedAppId;
|
|
1759
|
-
}
|
|
1760
|
-
if (!appId) {
|
|
1761
|
-
throw new Error('Application ID is required');
|
|
1762
|
-
}
|
|
1763
|
-
let codeId = options.codeId;
|
|
1764
|
-
if (!codeId) {
|
|
1765
|
-
const codes = await applicationService.listShortCodes(appId);
|
|
1766
|
-
if (codes.length === 0) {
|
|
1767
|
-
console.log(chalk_1.default.yellow('⚠ No short codes configured'));
|
|
1768
|
-
return;
|
|
1769
|
-
}
|
|
1770
|
-
const { selectedCodeId } = await inquirer_1.default.prompt([
|
|
1771
|
-
{
|
|
1772
|
-
type: 'list',
|
|
1773
|
-
name: 'selectedCodeId',
|
|
1774
|
-
message: 'Select short code to delete:',
|
|
1775
|
-
choices: codes.map((code) => ({
|
|
1776
|
-
name: `${code.name} (${code.code})`,
|
|
1777
|
-
value: code.id,
|
|
1778
|
-
})),
|
|
1779
|
-
},
|
|
1780
|
-
]);
|
|
1781
|
-
codeId = selectedCodeId;
|
|
1782
|
-
}
|
|
1783
|
-
if (!options.force) {
|
|
1784
|
-
const { confirm } = await inquirer_1.default.prompt([
|
|
1785
|
-
{
|
|
1786
|
-
type: 'confirm',
|
|
1787
|
-
name: 'confirm',
|
|
1788
|
-
message: 'Are you sure you want to delete this short code?',
|
|
1789
|
-
default: false,
|
|
1790
|
-
},
|
|
1791
|
-
]);
|
|
1792
|
-
if (!confirm) {
|
|
1793
|
-
console.log(chalk_1.default.gray('Deletion cancelled'));
|
|
1794
|
-
return;
|
|
1795
|
-
}
|
|
1796
|
-
}
|
|
1797
|
-
if (!codeId) {
|
|
1798
|
-
throw new Error('Code ID is required');
|
|
1799
|
-
}
|
|
1800
|
-
await applicationService.deleteShortCode(appId, codeId);
|
|
1801
|
-
console.log(chalk_1.default.green('\n✓ Short code deleted successfully!'));
|
|
266
|
+
await (0, delete_3.handleShortCodesDelete)(options);
|
|
1802
267
|
}, {
|
|
1803
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1804
268
|
requireAuth: true,
|
|
1805
269
|
requireOrganization: true,
|
|
1806
270
|
}));
|
|
@@ -1810,70 +274,8 @@ Examples:
|
|
|
1810
274
|
.option('-i, --app-id <id>', 'Application ID')
|
|
1811
275
|
.option('-c, --code-id <id>', 'Short Code ID')
|
|
1812
276
|
.action((0, command_wrapper_1.wrapCommand)(async (options) => {
|
|
1813
|
-
|
|
1814
|
-
const logger = container.get(types_1.TYPES.Logger);
|
|
1815
|
-
const configRepository = container.get(types_1.TYPES.ConfigRepository);
|
|
1816
|
-
const applicationService = container.get(types_1.TYPES.ApplicationService);
|
|
1817
|
-
(0, config_validator_1.validateConfig)(configRepository, {
|
|
1818
|
-
requireAuth: true,
|
|
1819
|
-
requireOrganization: true,
|
|
1820
|
-
});
|
|
1821
|
-
let appId = options.appId;
|
|
1822
|
-
if (!appId) {
|
|
1823
|
-
const applications = await applicationService.getApplications();
|
|
1824
|
-
if (applications.length === 0) {
|
|
1825
|
-
console.log(chalk_1.default.yellow('⚠ No applications configured'));
|
|
1826
|
-
return;
|
|
1827
|
-
}
|
|
1828
|
-
const { selectedAppId } = await inquirer_1.default.prompt([
|
|
1829
|
-
{
|
|
1830
|
-
type: 'list',
|
|
1831
|
-
name: 'selectedAppId',
|
|
1832
|
-
message: 'Select application:',
|
|
1833
|
-
choices: applications.map((app) => ({
|
|
1834
|
-
name: `${app.name} (${app.id})`,
|
|
1835
|
-
value: app.id,
|
|
1836
|
-
})),
|
|
1837
|
-
},
|
|
1838
|
-
]);
|
|
1839
|
-
appId = selectedAppId;
|
|
1840
|
-
}
|
|
1841
|
-
if (!appId) {
|
|
1842
|
-
throw new Error('Application ID is required');
|
|
1843
|
-
}
|
|
1844
|
-
let codeId = options.codeId;
|
|
1845
|
-
if (!codeId) {
|
|
1846
|
-
const codes = await applicationService.listShortCodes(appId);
|
|
1847
|
-
if (codes.length === 0) {
|
|
1848
|
-
console.log(chalk_1.default.yellow('⚠ No short codes configured'));
|
|
1849
|
-
return;
|
|
1850
|
-
}
|
|
1851
|
-
const { selectedCodeId } = await inquirer_1.default.prompt([
|
|
1852
|
-
{
|
|
1853
|
-
type: 'list',
|
|
1854
|
-
name: 'selectedCodeId',
|
|
1855
|
-
message: 'Select short code to toggle:',
|
|
1856
|
-
choices: codes.map((code) => ({
|
|
1857
|
-
name: `${code.name} (${code.code}) - ${code.enabled ? 'Enabled' : 'Disabled'}`,
|
|
1858
|
-
value: code.id,
|
|
1859
|
-
})),
|
|
1860
|
-
},
|
|
1861
|
-
]);
|
|
1862
|
-
codeId = selectedCodeId;
|
|
1863
|
-
}
|
|
1864
|
-
if (!codeId || !appId) {
|
|
1865
|
-
throw new Error('Application ID and Code ID are required');
|
|
1866
|
-
}
|
|
1867
|
-
// Get current status
|
|
1868
|
-
const codes = await applicationService.listShortCodes(appId);
|
|
1869
|
-
const code = codes.find((c) => c.id === codeId);
|
|
1870
|
-
if (!code) {
|
|
1871
|
-
throw new Error('Short code not found');
|
|
1872
|
-
}
|
|
1873
|
-
await applicationService.updateShortCode(appId, codeId, { enabled: !code.enabled });
|
|
1874
|
-
console.log(chalk_1.default.green(`\n✓ Short code ${code.enabled ? 'disabled' : 'enabled'} successfully!`));
|
|
277
|
+
await (0, toggle_1.handleShortCodesToggle)(options);
|
|
1875
278
|
}, {
|
|
1876
|
-
configRepository: (0, container_1.getContainer)().get(types_1.TYPES.ConfigRepository),
|
|
1877
279
|
requireAuth: true,
|
|
1878
280
|
requireOrganization: true,
|
|
1879
281
|
}));
|