runway-cli 0.8.0

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.
@@ -0,0 +1,84 @@
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.listCommand = listCommand;
7
+ const ora_1 = __importDefault(require("ora"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const uploadService_1 = require("../services/uploadService");
10
+ const config_1 = require("../utils/config");
11
+ const logger_1 = require("../utils/logger");
12
+ async function listCommand() {
13
+ // Check configuration
14
+ if (!(0, config_1.isConfigured)()) {
15
+ logger_1.logger.error('CLI not configured. Run "runway init" first.');
16
+ return;
17
+ }
18
+ const config = (0, config_1.getConfig)();
19
+ logger_1.logger.dim(`Server: ${config.serverUrl}`);
20
+ logger_1.logger.blank();
21
+ const spinner = (0, ora_1.default)('Fetching projects...').start();
22
+ try {
23
+ const uploadService = (0, uploadService_1.createUploadService)();
24
+ const projects = await uploadService.listProjects();
25
+ spinner.stop();
26
+ if (projects.length === 0) {
27
+ logger_1.logger.info('No projects deployed yet.');
28
+ logger_1.logger.blank();
29
+ logger_1.logger.dim('Deploy your first project with: runway deploy');
30
+ return;
31
+ }
32
+ console.log('');
33
+ console.log(chalk_1.default.bold(' Deployed Projects:'));
34
+ console.log('');
35
+ for (const project of projects) {
36
+ const statusColor = getStatusColor(project.status);
37
+ const statusIcon = getStatusIcon(project.status);
38
+ console.log(` ${statusIcon} ${chalk_1.default.bold(project.name)} ` +
39
+ chalk_1.default.dim(`(${project.type})`) +
40
+ ` - ${statusColor(project.status)}`);
41
+ }
42
+ console.log('');
43
+ logger_1.logger.dim(`Total: ${projects.length} project(s)`);
44
+ }
45
+ catch (error) {
46
+ spinner.fail('Failed to fetch projects');
47
+ logger_1.logger.error(error instanceof Error ? error.message : 'Unknown error');
48
+ }
49
+ }
50
+ function getStatusColor(status) {
51
+ switch (status) {
52
+ case 'running':
53
+ case 'online':
54
+ return chalk_1.default.green;
55
+ case 'stopped':
56
+ return chalk_1.default.yellow;
57
+ case 'failed':
58
+ case 'error':
59
+ return chalk_1.default.red;
60
+ case 'building':
61
+ case 'deploying':
62
+ return chalk_1.default.blue;
63
+ default:
64
+ return chalk_1.default.gray;
65
+ }
66
+ }
67
+ function getStatusIcon(status) {
68
+ switch (status) {
69
+ case 'running':
70
+ case 'online':
71
+ return chalk_1.default.green('●');
72
+ case 'stopped':
73
+ return chalk_1.default.yellow('○');
74
+ case 'failed':
75
+ case 'error':
76
+ return chalk_1.default.red('●');
77
+ case 'building':
78
+ case 'deploying':
79
+ return chalk_1.default.blue('◐');
80
+ default:
81
+ return chalk_1.default.gray('○');
82
+ }
83
+ }
84
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb21tYW5kcy9saXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBTUEsa0NBK0NDO0FBckRELDhDQUFzQjtBQUN0QixrREFBMEI7QUFDMUIsNkRBQWdFO0FBQ2hFLDRDQUEwRDtBQUMxRCw0Q0FBeUM7QUFFbEMsS0FBSyxVQUFVLFdBQVc7SUFDL0Isc0JBQXNCO0lBQ3RCLElBQUksQ0FBQyxJQUFBLHFCQUFZLEdBQUUsRUFBRSxDQUFDO1FBQ3BCLGVBQU0sQ0FBQyxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUM3RCxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sTUFBTSxHQUFHLElBQUEsa0JBQVMsR0FBRSxDQUFDO0lBQzNCLGVBQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUMxQyxlQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFZixNQUFNLE9BQU8sR0FBRyxJQUFBLGFBQUcsRUFBQyxzQkFBc0IsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO0lBRXBELElBQUksQ0FBQztRQUNILE1BQU0sYUFBYSxHQUFHLElBQUEsbUNBQW1CLEdBQUUsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQWEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUVwRCxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFZixJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDMUIsZUFBTSxDQUFDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1lBQ3pDLGVBQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNmLGVBQU0sQ0FBQyxHQUFHLENBQUMsK0NBQStDLENBQUMsQ0FBQztZQUM1RCxPQUFPO1FBQ1QsQ0FBQztRQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFLLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsQ0FBQztRQUNoRCxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRWhCLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDL0IsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNuRCxNQUFNLFVBQVUsR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRWpELE9BQU8sQ0FBQyxHQUFHLENBQ1QsS0FBSyxVQUFVLElBQUksZUFBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUc7Z0JBQzlDLGVBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUM7Z0JBQzlCLE1BQU0sV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUNwQyxDQUFDO1FBQ0osQ0FBQztRQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDaEIsZUFBTSxDQUFDLEdBQUcsQ0FBQyxVQUFVLFFBQVEsQ0FBQyxNQUFNLGFBQWEsQ0FBQyxDQUFDO0lBQ3JELENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQ3pDLGVBQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDekUsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxNQUFjO0lBQ3BDLFFBQVEsTUFBTSxFQUFFLENBQUM7UUFDZixLQUFLLFNBQVMsQ0FBQztRQUNmLEtBQUssUUFBUTtZQUNYLE9BQU8sZUFBSyxDQUFDLEtBQUssQ0FBQztRQUNyQixLQUFLLFNBQVM7WUFDWixPQUFPLGVBQUssQ0FBQyxNQUFNLENBQUM7UUFDdEIsS0FBSyxRQUFRLENBQUM7UUFDZCxLQUFLLE9BQU87WUFDVixPQUFPLGVBQUssQ0FBQyxHQUFHLENBQUM7UUFDbkIsS0FBSyxVQUFVLENBQUM7UUFDaEIsS0FBSyxXQUFXO1lBQ2QsT0FBTyxlQUFLLENBQUMsSUFBSSxDQUFDO1FBQ3BCO1lBQ0UsT0FBTyxlQUFLLENBQUMsSUFBSSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsTUFBYztJQUNuQyxRQUFRLE1BQU0sRUFBRSxDQUFDO1FBQ2YsS0FBSyxTQUFTLENBQUM7UUFDZixLQUFLLFFBQVE7WUFDWCxPQUFPLGVBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDMUIsS0FBSyxTQUFTO1lBQ1osT0FBTyxlQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzNCLEtBQUssUUFBUSxDQUFDO1FBQ2QsS0FBSyxPQUFPO1lBQ1YsT0FBTyxlQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLEtBQUssVUFBVSxDQUFDO1FBQ2hCLEtBQUssV0FBVztZQUNkLE9BQU8sZUFBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6QjtZQUNFLE9BQU8sZUFBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBvcmEgZnJvbSAnb3JhJztcbmltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBjcmVhdGVVcGxvYWRTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdXBsb2FkU2VydmljZSc7XG5pbXBvcnQgeyBpc0NvbmZpZ3VyZWQsIGdldENvbmZpZyB9IGZyb20gJy4uL3V0aWxzL2NvbmZpZyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXInO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlzdENvbW1hbmQoKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIENoZWNrIGNvbmZpZ3VyYXRpb25cbiAgaWYgKCFpc0NvbmZpZ3VyZWQoKSkge1xuICAgIGxvZ2dlci5lcnJvcignQ0xJIG5vdCBjb25maWd1cmVkLiBSdW4gXCJydW53YXkgaW5pdFwiIGZpcnN0LicpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGNvbmZpZyA9IGdldENvbmZpZygpO1xuICBsb2dnZXIuZGltKGBTZXJ2ZXI6ICR7Y29uZmlnLnNlcnZlclVybH1gKTtcbiAgbG9nZ2VyLmJsYW5rKCk7XG5cbiAgY29uc3Qgc3Bpbm5lciA9IG9yYSgnRmV0Y2hpbmcgcHJvamVjdHMuLi4nKS5zdGFydCgpO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgdXBsb2FkU2VydmljZSA9IGNyZWF0ZVVwbG9hZFNlcnZpY2UoKTtcbiAgICBjb25zdCBwcm9qZWN0cyA9IGF3YWl0IHVwbG9hZFNlcnZpY2UubGlzdFByb2plY3RzKCk7XG5cbiAgICBzcGlubmVyLnN0b3AoKTtcblxuICAgIGlmIChwcm9qZWN0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdObyBwcm9qZWN0cyBkZXBsb3llZCB5ZXQuJyk7XG4gICAgICBsb2dnZXIuYmxhbmsoKTtcbiAgICAgIGxvZ2dlci5kaW0oJ0RlcGxveSB5b3VyIGZpcnN0IHByb2plY3Qgd2l0aDogcnVud2F5IGRlcGxveScpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ib2xkKCcgIERlcGxveWVkIFByb2plY3RzOicpKTtcbiAgICBjb25zb2xlLmxvZygnJyk7XG5cbiAgICBmb3IgKGNvbnN0IHByb2plY3Qgb2YgcHJvamVjdHMpIHtcbiAgICAgIGNvbnN0IHN0YXR1c0NvbG9yID0gZ2V0U3RhdHVzQ29sb3IocHJvamVjdC5zdGF0dXMpO1xuICAgICAgY29uc3Qgc3RhdHVzSWNvbiA9IGdldFN0YXR1c0ljb24ocHJvamVjdC5zdGF0dXMpO1xuXG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYCAgJHtzdGF0dXNJY29ufSAke2NoYWxrLmJvbGQocHJvamVjdC5uYW1lKX0gYCArXG4gICAgICAgIGNoYWxrLmRpbShgKCR7cHJvamVjdC50eXBlfSlgKSArXG4gICAgICAgIGAgLSAke3N0YXR1c0NvbG9yKHByb2plY3Quc3RhdHVzKX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICBsb2dnZXIuZGltKGBUb3RhbDogJHtwcm9qZWN0cy5sZW5ndGh9IHByb2plY3QocylgKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBzcGlubmVyLmZhaWwoJ0ZhaWxlZCB0byBmZXRjaCBwcm9qZWN0cycpO1xuICAgIGxvZ2dlci5lcnJvcihlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdVbmtub3duIGVycm9yJyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0U3RhdHVzQ29sb3Ioc3RhdHVzOiBzdHJpbmcpOiAodGV4dDogc3RyaW5nKSA9PiBzdHJpbmcge1xuICBzd2l0Y2ggKHN0YXR1cykge1xuICAgIGNhc2UgJ3J1bm5pbmcnOlxuICAgIGNhc2UgJ29ubGluZSc6XG4gICAgICByZXR1cm4gY2hhbGsuZ3JlZW47XG4gICAgY2FzZSAnc3RvcHBlZCc6XG4gICAgICByZXR1cm4gY2hhbGsueWVsbG93O1xuICAgIGNhc2UgJ2ZhaWxlZCc6XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIGNoYWxrLnJlZDtcbiAgICBjYXNlICdidWlsZGluZyc6XG4gICAgY2FzZSAnZGVwbG95aW5nJzpcbiAgICAgIHJldHVybiBjaGFsay5ibHVlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gY2hhbGsuZ3JheTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTdGF0dXNJY29uKHN0YXR1czogc3RyaW5nKTogc3RyaW5nIHtcbiAgc3dpdGNoIChzdGF0dXMpIHtcbiAgICBjYXNlICdydW5uaW5nJzpcbiAgICBjYXNlICdvbmxpbmUnOlxuICAgICAgcmV0dXJuIGNoYWxrLmdyZWVuKCfil48nKTtcbiAgICBjYXNlICdzdG9wcGVkJzpcbiAgICAgIHJldHVybiBjaGFsay55ZWxsb3coJ+KXiycpO1xuICAgIGNhc2UgJ2ZhaWxlZCc6XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIGNoYWxrLnJlZCgn4pePJyk7XG4gICAgY2FzZSAnYnVpbGRpbmcnOlxuICAgIGNhc2UgJ2RlcGxveWluZyc6XG4gICAgICByZXR1cm4gY2hhbGsuYmx1ZSgn4peQJyk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBjaGFsay5ncmF5KCfil4snKTtcbiAgfVxufVxuIl19
@@ -0,0 +1 @@
1
+ export declare function statusCommand(projectName: string): Promise<void>;
@@ -0,0 +1,117 @@
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.statusCommand = statusCommand;
7
+ const ora_1 = __importDefault(require("ora"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const config_1 = require("../utils/config");
11
+ const logger_1 = require("../utils/logger");
12
+ async function statusCommand(projectName) {
13
+ if (!projectName) {
14
+ logger_1.logger.error('Project name is required');
15
+ logger_1.logger.dim('Usage: runway status <project-name>');
16
+ return;
17
+ }
18
+ // Check configuration
19
+ if (!(0, config_1.isConfigured)()) {
20
+ logger_1.logger.error('CLI not configured. Run "runway init" first.');
21
+ return;
22
+ }
23
+ const config = (0, config_1.getConfig)();
24
+ const spinner = (0, ora_1.default)(`Fetching status for ${projectName}...`).start();
25
+ try {
26
+ // First, get the list of projects to find the one we want
27
+ const response = await axios_1.default.get(`${config.serverUrl}/api/project`, {
28
+ headers: {
29
+ Authorization: `Bearer ${config.token}`,
30
+ },
31
+ });
32
+ const projects = response.data.data || [];
33
+ const project = projects.find((p) => p.name.toLowerCase() === projectName.toLowerCase());
34
+ spinner.stop();
35
+ if (!project) {
36
+ logger_1.logger.error(`Project "${projectName}" not found`);
37
+ logger_1.logger.blank();
38
+ logger_1.logger.dim('Available projects:');
39
+ for (const p of projects) {
40
+ logger_1.logger.dim(` - ${p.name}`);
41
+ }
42
+ return;
43
+ }
44
+ // Display project details
45
+ logger_1.logger.blank();
46
+ console.log(chalk_1.default.bold(` ${project.name}`));
47
+ console.log('');
48
+ console.log(` ${chalk_1.default.dim('Type:')} ${project.type}`);
49
+ console.log(` ${chalk_1.default.dim('Status:')} ${getStatusBadge(project.status)}`);
50
+ if (project.port) {
51
+ console.log(` ${chalk_1.default.dim('Port:')} ${project.port}`);
52
+ }
53
+ if (project.uptime !== undefined) {
54
+ console.log(` ${chalk_1.default.dim('Uptime:')} ${formatUptime(project.uptime)}`);
55
+ }
56
+ if (project.memory !== undefined) {
57
+ console.log(` ${chalk_1.default.dim('Memory:')} ${formatBytes(project.memory)}`);
58
+ }
59
+ if (project.cpu !== undefined) {
60
+ console.log(` ${chalk_1.default.dim('CPU:')} ${project.cpu.toFixed(1)}%`);
61
+ }
62
+ const safeName = project.name.toLowerCase().replace(/[^a-z0-9]/g, '-');
63
+ console.log(` ${chalk_1.default.dim('URL:')} ${config.serverUrl}/app/${safeName}`);
64
+ logger_1.logger.blank();
65
+ }
66
+ catch (error) {
67
+ spinner.fail('Failed to fetch status');
68
+ if (axios_1.default.isAxiosError(error)) {
69
+ logger_1.logger.error(error.response?.data?.error || error.message);
70
+ }
71
+ else {
72
+ logger_1.logger.error(error instanceof Error ? error.message : 'Unknown error');
73
+ }
74
+ }
75
+ }
76
+ function getStatusBadge(status) {
77
+ switch (status) {
78
+ case 'running':
79
+ case 'online':
80
+ return chalk_1.default.black.bgGreen(` ${status.toUpperCase()} `);
81
+ case 'stopped':
82
+ return chalk_1.default.black.bgYellow(` ${status.toUpperCase()} `);
83
+ case 'failed':
84
+ case 'error':
85
+ return chalk_1.default.white.bgRed(` ${status.toUpperCase()} `);
86
+ case 'building':
87
+ case 'deploying':
88
+ return chalk_1.default.black.bgBlue(` ${status.toUpperCase()} `);
89
+ default:
90
+ return chalk_1.default.white.bgGray(` ${status.toUpperCase()} `);
91
+ }
92
+ }
93
+ function formatUptime(seconds) {
94
+ if (seconds < 60) {
95
+ return `${Math.floor(seconds)}s`;
96
+ }
97
+ if (seconds < 3600) {
98
+ return `${Math.floor(seconds / 60)}m`;
99
+ }
100
+ if (seconds < 86400) {
101
+ return `${Math.floor(seconds / 3600)}h ${Math.floor((seconds % 3600) / 60)}m`;
102
+ }
103
+ return `${Math.floor(seconds / 86400)}d ${Math.floor((seconds % 86400) / 3600)}h`;
104
+ }
105
+ function formatBytes(bytes) {
106
+ if (bytes < 1024) {
107
+ return `${bytes} B`;
108
+ }
109
+ if (bytes < 1024 * 1024) {
110
+ return `${(bytes / 1024).toFixed(1)} KB`;
111
+ }
112
+ if (bytes < 1024 * 1024 * 1024) {
113
+ return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
114
+ }
115
+ return `${(bytes / 1024 / 1024 / 1024).toFixed(1)} GB`;
116
+ }
117
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhdHVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1hbmRzL3N0YXR1cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQU1BLHNDQStFQztBQXJGRCw4Q0FBc0I7QUFDdEIsa0RBQTBCO0FBQzFCLGtEQUEwQjtBQUMxQiw0Q0FBMEQ7QUFDMUQsNENBQXlDO0FBRWxDLEtBQUssVUFBVSxhQUFhLENBQUMsV0FBbUI7SUFDckQsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pCLGVBQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUN6QyxlQUFNLENBQUMsR0FBRyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7UUFDbEQsT0FBTztJQUNULENBQUM7SUFFRCxzQkFBc0I7SUFDdEIsSUFBSSxDQUFDLElBQUEscUJBQVksR0FBRSxFQUFFLENBQUM7UUFDcEIsZUFBTSxDQUFDLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1FBQzdELE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBQSxrQkFBUyxHQUFFLENBQUM7SUFDM0IsTUFBTSxPQUFPLEdBQUcsSUFBQSxhQUFHLEVBQUMsdUJBQXVCLFdBQVcsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFckUsSUFBSSxDQUFDO1FBQ0gsMERBQTBEO1FBQzFELE1BQU0sUUFBUSxHQUFHLE1BQU0sZUFBSyxDQUFDLEdBQUcsQ0FDOUIsR0FBRyxNQUFNLENBQUMsU0FBUyxjQUFjLEVBQ2pDO1lBQ0UsT0FBTyxFQUFFO2dCQUNQLGFBQWEsRUFBRSxVQUFVLE1BQU0sQ0FBQyxLQUFLLEVBQUU7YUFDeEM7U0FDRixDQUNGLENBQUM7UUFFRixNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDMUMsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FDM0IsQ0FBQyxDQUFtQixF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QUcsSUFBSSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztBQUN6RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IG9yYSBmcm9tICdvcmEnO1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJztcbmltcG9ydCBheGlvcyBmcm9tICdheGlvcyc7XG5pbXBvcnQgeyBpc0NvbmZpZ3VyZWQsIGdldENvbmZpZyB9IGZyb20gJy4uL3V0aWxzL2NvbmZpZyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXInO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhdHVzQ29tbWFuZChwcm9qZWN0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICghcHJvamVjdE5hbWUpIHtcbiAgICBsb2dnZXIuZXJyb3IoJ1Byb2plY3QgbmFtZSBpcyByZXF1aXJlZCcpO1xuICAgIGxvZ2dlci5kaW0oJ1VzYWdlOiBydW53YXkgc3RhdHVzIDxwcm9qZWN0LW5hbWU+Jyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gQ2hlY2sgY29uZmlndXJhdGlvblxuICBpZiAoIWlzQ29uZmlndXJlZCgpKSB7XG4gICAgbG9nZ2VyLmVycm9yKCdDTEkgbm90IGNvbmZpZ3VyZWQuIFJ1biBcInJ1bndheSBpbml0XCIgZmlyc3QuJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgY29uZmlnID0gZ2V0Q29uZmlnKCk7XG4gIGNvbnN0IHNwaW5uZXIgPSBvcmEoYEZldGNoaW5nIHN0YXR1cyBmb3IgJHtwcm9qZWN0TmFtZX0uLi5gKS5zdGFydCgpO1xuXG4gIHRyeSB7XG4gICAgLy8gRmlyc3QsIGdldCB0aGUgbGlzdCBvZiBwcm9qZWN0cyB0byBmaW5kIHRoZSBvbmUgd2Ugd2FudFxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MuZ2V0KFxuICAgICAgYCR7Y29uZmlnLnNlcnZlclVybH0vYXBpL3Byb2plY3RgLFxuICAgICAge1xuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2NvbmZpZy50b2tlbn1gLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgICk7XG5cbiAgICBjb25zdCBwcm9qZWN0cyA9IHJlc3BvbnNlLmRhdGEuZGF0YSB8fCBbXTtcbiAgICBjb25zdCBwcm9qZWN0ID0gcHJvamVjdHMuZmluZChcbiAgICAgIChwOiB7IG5hbWU6IHN0cmluZyB9KSA9PiBwLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gcHJvamVjdE5hbWUudG9Mb3dlckNhc2UoKVxuICAgICk7XG5cbiAgICBzcGlubmVyLnN0b3AoKTtcblxuICAgIGlmICghcHJvamVjdCkge1xuICAgICAgbG9nZ2VyLmVycm9yKGBQcm9qZWN0IFwiJHtwcm9qZWN0TmFtZX1cIiBub3QgZm91bmRgKTtcbiAgICAgIGxvZ2dlci5ibGFuaygpO1xuICAgICAgbG9nZ2VyLmRpbSgnQXZhaWxhYmxlIHByb2plY3RzOicpO1xuICAgICAgZm9yIChjb25zdCBwIG9mIHByb2plY3RzKSB7XG4gICAgICAgIGxvZ2dlci5kaW0oYCAgLSAke3AubmFtZX1gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBEaXNwbGF5IHByb2plY3QgZGV0YWlsc1xuICAgIGxvZ2dlci5ibGFuaygpO1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLmJvbGQoYCAgJHtwcm9qZWN0Lm5hbWV9YCkpO1xuICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICBjb25zb2xlLmxvZyhgICAke2NoYWxrLmRpbSgnVHlwZTonKX0gICAgICR7cHJvamVjdC50eXBlfWApO1xuICAgIGNvbnNvbGUubG9nKGAgICR7Y2hhbGsuZGltKCdTdGF0dXM6Jyl9ICAgJHtnZXRTdGF0dXNCYWRnZShwcm9qZWN0LnN0YXR1cyl9YCk7XG5cbiAgICBpZiAocHJvamVjdC5wb3J0KSB7XG4gICAgICBjb25zb2xlLmxvZyhgICAke2NoYWxrLmRpbSgnUG9ydDonKX0gICAgICR7cHJvamVjdC5wb3J0fWApO1xuICAgIH1cblxuICAgIGlmIChwcm9qZWN0LnVwdGltZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zb2xlLmxvZyhgICAke2NoYWxrLmRpbSgnVXB0aW1lOicpfSAgICR7Zm9ybWF0VXB0aW1lKHByb2plY3QudXB0aW1lKX1gKTtcbiAgICB9XG5cbiAgICBpZiAocHJvamVjdC5tZW1vcnkgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc29sZS5sb2coYCAgJHtjaGFsay5kaW0oJ01lbW9yeTonKX0gICAke2Zvcm1hdEJ5dGVzKHByb2plY3QubWVtb3J5KX1gKTtcbiAgICB9XG5cbiAgICBpZiAocHJvamVjdC5jcHUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc29sZS5sb2coYCAgJHtjaGFsay5kaW0oJ0NQVTonKX0gICAgICAke3Byb2plY3QuY3B1LnRvRml4ZWQoMSl9JWApO1xuICAgIH1cblxuICAgIGNvbnN0IHNhZmVOYW1lID0gcHJvamVjdC5uYW1lLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvW15hLXowLTldL2csICctJyk7XG4gICAgY29uc29sZS5sb2coYCAgJHtjaGFsay5kaW0oJ1VSTDonKX0gICAgICAke2NvbmZpZy5zZXJ2ZXJVcmx9L2FwcC8ke3NhZmVOYW1lfWApO1xuXG4gICAgbG9nZ2VyLmJsYW5rKCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gZmV0Y2ggc3RhdHVzJyk7XG4gICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnJvcikpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihlcnJvci5yZXNwb25zZT8uZGF0YT8uZXJyb3IgfHwgZXJyb3IubWVzc2FnZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5lcnJvcihlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdVbmtub3duIGVycm9yJyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldFN0YXR1c0JhZGdlKHN0YXR1czogc3RyaW5nKTogc3RyaW5nIHtcbiAgc3dpdGNoIChzdGF0dXMpIHtcbiAgICBjYXNlICdydW5uaW5nJzpcbiAgICBjYXNlICdvbmxpbmUnOlxuICAgICAgcmV0dXJuIGNoYWxrLmJsYWNrLmJnR3JlZW4oYCAke3N0YXR1cy50b1VwcGVyQ2FzZSgpfSBgKTtcbiAgICBjYXNlICdzdG9wcGVkJzpcbiAgICAgIHJldHVybiBjaGFsay5ibGFjay5iZ1llbGxvdyhgICR7c3RhdHVzLnRvVXBwZXJDYXNlKCl9IGApO1xuICAgIGNhc2UgJ2ZhaWxlZCc6XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIGNoYWxrLndoaXRlLmJnUmVkKGAgJHtzdGF0dXMudG9VcHBlckNhc2UoKX0gYCk7XG4gICAgY2FzZSAnYnVpbGRpbmcnOlxuICAgIGNhc2UgJ2RlcGxveWluZyc6XG4gICAgICByZXR1cm4gY2hhbGsuYmxhY2suYmdCbHVlKGAgJHtzdGF0dXMudG9VcHBlckNhc2UoKX0gYCk7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBjaGFsay53aGl0ZS5iZ0dyYXkoYCAke3N0YXR1cy50b1VwcGVyQ2FzZSgpfSBgKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBmb3JtYXRVcHRpbWUoc2Vjb25kczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKHNlY29uZHMgPCA2MCkge1xuICAgIHJldHVybiBgJHtNYXRoLmZsb29yKHNlY29uZHMpfXNgO1xuICB9XG4gIGlmIChzZWNvbmRzIDwgMzYwMCkge1xuICAgIHJldHVybiBgJHtNYXRoLmZsb29yKHNlY29uZHMgLyA2MCl9bWA7XG4gIH1cbiAgaWYgKHNlY29uZHMgPCA4NjQwMCkge1xuICAgIHJldHVybiBgJHtNYXRoLmZsb29yKHNlY29uZHMgLyAzNjAwKX1oICR7TWF0aC5mbG9vcigoc2Vjb25kcyAlIDM2MDApIC8gNjApfW1gO1xuICB9XG4gIHJldHVybiBgJHtNYXRoLmZsb29yKHNlY29uZHMgLyA4NjQwMCl9ZCAke01hdGguZmxvb3IoKHNlY29uZHMgJSA4NjQwMCkgLyAzNjAwKX1oYDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0Qnl0ZXMoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gIGlmIChieXRlcyA8IDEwMjQpIHtcbiAgICByZXR1cm4gYCR7Ynl0ZXN9IEJgO1xuICB9XG4gIGlmIChieXRlcyA8IDEwMjQgKiAxMDI0KSB7XG4gICAgcmV0dXJuIGAkeyhieXRlcyAvIDEwMjQpLnRvRml4ZWQoMSl9IEtCYDtcbiAgfVxuICBpZiAoYnl0ZXMgPCAxMDI0ICogMTAyNCAqIDEwMjQpIHtcbiAgICByZXR1cm4gYCR7KGJ5dGVzIC8gMTAyNCAvIDEwMjQpLnRvRml4ZWQoMSl9IE1CYDtcbiAgfVxuICByZXR1cm4gYCR7KGJ5dGVzIC8gMTAyNCAvIDEwMjQgLyAxMDI0KS50b0ZpeGVkKDEpfSBHQmA7XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const init_1 = require("./commands/init");
6
+ const deploy_1 = require("./commands/deploy");
7
+ const list_1 = require("./commands/list");
8
+ const status_1 = require("./commands/status");
9
+ const program = new commander_1.Command();
10
+ program
11
+ .name('runway')
12
+ .description('CLI tool for deploying projects to Runway')
13
+ .version('0.0.1');
14
+ // Init command
15
+ program
16
+ .command('init')
17
+ .description('Configure the Runway CLI')
18
+ .option('-s, --server <url>', 'Server URL')
19
+ .action(init_1.initCommand);
20
+ // Deploy command
21
+ program
22
+ .command('deploy')
23
+ .description('Deploy the current project')
24
+ .option('-n, --name <name>', 'Project name')
25
+ .option('-t, --type <type>', 'Project type (react, next, node)')
26
+ .option('-v, --version <version>', 'Version string')
27
+ .option('--build-local', 'Build locally before uploading (default)')
28
+ .option('--build-server', 'Upload source and build on server')
29
+ .option('-e, --env-file <path>', 'Path to environment file')
30
+ .action(deploy_1.deployCommand);
31
+ // List command
32
+ program
33
+ .command('list')
34
+ .alias('ls')
35
+ .description('List deployed projects')
36
+ .action(list_1.listCommand);
37
+ // Status command
38
+ program
39
+ .command('status <project>')
40
+ .description('Get status of a deployed project')
41
+ .action(status_1.statusCommand);
42
+ // Parse command line arguments
43
+ program.parse();
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBRUEseUNBQW9DO0FBQ3BDLDBDQUE4QztBQUM5Qyw4Q0FBa0Q7QUFDbEQsMENBQThDO0FBQzlDLDhDQUFrRDtBQUVsRCxNQUFNLE9BQU8sR0FBRyxJQUFJLG1CQUFPLEVBQUUsQ0FBQztBQUU5QixPQUFPO0tBQ0osSUFBSSxDQUFDLFFBQVEsQ0FBQztLQUNkLFdBQVcsQ0FBQywyQ0FBMkMsQ0FBQztLQUN4RCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7QUFFcEIsZUFBZTtBQUNmLE9BQU87S0FDSixPQUFPLENBQUMsTUFBTSxDQUFDO0tBQ2YsV0FBVyxDQUFDLDBCQUEwQixDQUFDO0tBQ3ZDLE1BQU0sQ0FBQyxvQkFBb0IsRUFBRSxZQUFZLENBQUM7S0FDMUMsTUFBTSxDQUFDLGtCQUFXLENBQUMsQ0FBQztBQUV2QixpQkFBaUI7QUFDakIsT0FBTztLQUNKLE9BQU8sQ0FBQyxRQUFRLENBQUM7S0FDakIsV0FBVyxDQUFDLDRCQUE0QixDQUFDO0tBQ3pDLE1BQU0sQ0FBQyxtQkFBbUIsRUFBRSxjQUFjLENBQUM7S0FDM0MsTUFBTSxDQUFDLG1CQUFtQixFQUFFLGtDQUFrQyxDQUFDO0tBQy9ELE1BQU0sQ0FBQyx5QkFBeUIsRUFBRSxnQkFBZ0IsQ0FBQztLQUNuRCxNQUFNLENBQUMsZUFBZSxFQUFFLDBDQUEwQyxDQUFDO0tBQ25FLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxtQ0FBbUMsQ0FBQztLQUM3RCxNQUFNLENBQUMsdUJBQXVCLEVBQUUsMEJBQTBCLENBQUM7S0FDM0QsTUFBTSxDQUFDLHNCQUFhLENBQUMsQ0FBQztBQUV6QixlQUFlO0FBQ2YsT0FBTztLQUNKLE9BQU8sQ0FBQyxNQUFNLENBQUM7S0FDZixLQUFLLENBQUMsSUFBSSxDQUFDO0tBQ1gsV0FBVyxDQUFDLHdCQUF3QixDQUFDO0tBQ3JDLE1BQU0sQ0FBQyxrQkFBVyxDQUFDLENBQUM7QUFFdkIsaUJBQWlCO0FBQ2pCLE9BQU87S0FDSixPQUFPLENBQUMsa0JBQWtCLENBQUM7S0FDM0IsV0FBVyxDQUFDLGtDQUFrQyxDQUFDO0tBQy9DLE1BQU0sQ0FBQyxzQkFBYSxDQUFDLENBQUM7QUFFekIsK0JBQStCO0FBQy9CLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIiMhL3Vzci9iaW4vZW52IG5vZGVcblxuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgeyBpbml0Q29tbWFuZCB9IGZyb20gJy4vY29tbWFuZHMvaW5pdCc7XG5pbXBvcnQgeyBkZXBsb3lDb21tYW5kIH0gZnJvbSAnLi9jb21tYW5kcy9kZXBsb3knO1xuaW1wb3J0IHsgbGlzdENvbW1hbmQgfSBmcm9tICcuL2NvbW1hbmRzL2xpc3QnO1xuaW1wb3J0IHsgc3RhdHVzQ29tbWFuZCB9IGZyb20gJy4vY29tbWFuZHMvc3RhdHVzJztcblxuY29uc3QgcHJvZ3JhbSA9IG5ldyBDb21tYW5kKCk7XG5cbnByb2dyYW1cbiAgLm5hbWUoJ3J1bndheScpXG4gIC5kZXNjcmlwdGlvbignQ0xJIHRvb2wgZm9yIGRlcGxveWluZyBwcm9qZWN0cyB0byBSdW53YXknKVxuICAudmVyc2lvbignMC4wLjEnKTtcblxuLy8gSW5pdCBjb21tYW5kXG5wcm9ncmFtXG4gIC5jb21tYW5kKCdpbml0JylcbiAgLmRlc2NyaXB0aW9uKCdDb25maWd1cmUgdGhlIFJ1bndheSBDTEknKVxuICAub3B0aW9uKCctcywgLS1zZXJ2ZXIgPHVybD4nLCAnU2VydmVyIFVSTCcpXG4gIC5hY3Rpb24oaW5pdENvbW1hbmQpO1xuXG4vLyBEZXBsb3kgY29tbWFuZFxucHJvZ3JhbVxuICAuY29tbWFuZCgnZGVwbG95JylcbiAgLmRlc2NyaXB0aW9uKCdEZXBsb3kgdGhlIGN1cnJlbnQgcHJvamVjdCcpXG4gIC5vcHRpb24oJy1uLCAtLW5hbWUgPG5hbWU+JywgJ1Byb2plY3QgbmFtZScpXG4gIC5vcHRpb24oJy10LCAtLXR5cGUgPHR5cGU+JywgJ1Byb2plY3QgdHlwZSAocmVhY3QsIG5leHQsIG5vZGUpJylcbiAgLm9wdGlvbignLXYsIC0tdmVyc2lvbiA8dmVyc2lvbj4nLCAnVmVyc2lvbiBzdHJpbmcnKVxuICAub3B0aW9uKCctLWJ1aWxkLWxvY2FsJywgJ0J1aWxkIGxvY2FsbHkgYmVmb3JlIHVwbG9hZGluZyAoZGVmYXVsdCknKVxuICAub3B0aW9uKCctLWJ1aWxkLXNlcnZlcicsICdVcGxvYWQgc291cmNlIGFuZCBidWlsZCBvbiBzZXJ2ZXInKVxuICAub3B0aW9uKCctZSwgLS1lbnYtZmlsZSA8cGF0aD4nLCAnUGF0aCB0byBlbnZpcm9ubWVudCBmaWxlJylcbiAgLmFjdGlvbihkZXBsb3lDb21tYW5kKTtcblxuLy8gTGlzdCBjb21tYW5kXG5wcm9ncmFtXG4gIC5jb21tYW5kKCdsaXN0JylcbiAgLmFsaWFzKCdscycpXG4gIC5kZXNjcmlwdGlvbignTGlzdCBkZXBsb3llZCBwcm9qZWN0cycpXG4gIC5hY3Rpb24obGlzdENvbW1hbmQpO1xuXG4vLyBTdGF0dXMgY29tbWFuZFxucHJvZ3JhbVxuICAuY29tbWFuZCgnc3RhdHVzIDxwcm9qZWN0PicpXG4gIC5kZXNjcmlwdGlvbignR2V0IHN0YXR1cyBvZiBhIGRlcGxveWVkIHByb2plY3QnKVxuICAuYWN0aW9uKHN0YXR1c0NvbW1hbmQpO1xuXG4vLyBQYXJzZSBjb21tYW5kIGxpbmUgYXJndW1lbnRzXG5wcm9ncmFtLnBhcnNlKCk7XG4iXX0=
@@ -0,0 +1,64 @@
1
+ export type SecurityMode = 'ip-http' | 'domain-https';
2
+ export interface SecurityModeResponse {
3
+ success: boolean;
4
+ data: {
5
+ securityMode: SecurityMode;
6
+ serverIp: string | null;
7
+ domain: string | null;
8
+ domainActive: boolean;
9
+ requiresRSA: boolean;
10
+ tokenMaxAge: number;
11
+ tokenType: 'pairing' | 'standard';
12
+ };
13
+ }
14
+ export interface PublicKeyResponse {
15
+ success: boolean;
16
+ data: {
17
+ publicKey: string;
18
+ };
19
+ warning?: string;
20
+ }
21
+ export interface AuthResponse {
22
+ success: boolean;
23
+ data: {
24
+ token: string;
25
+ expiresIn: number;
26
+ expiresAt: string;
27
+ tokenType: 'pairing' | 'standard';
28
+ securityMode: SecurityMode;
29
+ };
30
+ }
31
+ /**
32
+ * CLI Authentication Service
33
+ *
34
+ * Handles authentication flow for both HTTP (RSA) and HTTPS (direct) modes.
35
+ */
36
+ export declare class AuthService {
37
+ private serverUrl;
38
+ constructor(serverUrl: string);
39
+ /**
40
+ * Get server security mode and connection info
41
+ */
42
+ getSecurityMode(): Promise<SecurityModeResponse['data']>;
43
+ /**
44
+ * Authenticate with the server
45
+ * Automatically handles RSA or direct auth based on security mode
46
+ */
47
+ authenticate(username: string, password: string): Promise<AuthResponse['data']>;
48
+ /**
49
+ * RSA-encrypted authentication (HTTP mode)
50
+ */
51
+ private authenticateWithRSA;
52
+ /**
53
+ * Direct authentication (HTTPS mode)
54
+ */
55
+ private authenticateDirect;
56
+ /**
57
+ * Refresh token (only works in HTTPS mode)
58
+ */
59
+ refreshToken(currentToken: string): Promise<AuthResponse['data'] | null>;
60
+ /**
61
+ * Handle axios errors with user-friendly messages
62
+ */
63
+ private handleError;
64
+ }
@@ -0,0 +1,162 @@
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.AuthService = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const logger_1 = require("../utils/logger");
10
+ /**
11
+ * CLI Authentication Service
12
+ *
13
+ * Handles authentication flow for both HTTP (RSA) and HTTPS (direct) modes.
14
+ */
15
+ class AuthService {
16
+ constructor(serverUrl) {
17
+ // Normalize URL
18
+ this.serverUrl = serverUrl.replace(/\/+$/, '');
19
+ }
20
+ /**
21
+ * Get server security mode and connection info
22
+ */
23
+ async getSecurityMode() {
24
+ try {
25
+ const response = await axios_1.default.get(`${this.serverUrl}/api/cli/security-mode`, { timeout: 10000 });
26
+ return response.data.data;
27
+ }
28
+ catch (error) {
29
+ this.handleError(error, 'Failed to get security mode');
30
+ throw error;
31
+ }
32
+ }
33
+ /**
34
+ * Authenticate with the server
35
+ * Automatically handles RSA or direct auth based on security mode
36
+ */
37
+ async authenticate(username, password) {
38
+ const modeInfo = await this.getSecurityMode();
39
+ if (modeInfo.requiresRSA) {
40
+ return this.authenticateWithRSA(username, password);
41
+ }
42
+ else {
43
+ return this.authenticateDirect(username, password);
44
+ }
45
+ }
46
+ /**
47
+ * RSA-encrypted authentication (HTTP mode)
48
+ */
49
+ async authenticateWithRSA(username, password) {
50
+ // Show MITM warning
51
+ logger_1.logger.blank();
52
+ logger_1.logger.warn('WARNING: Using RSA key exchange over HTTP');
53
+ logger_1.logger.warn('This method is vulnerable to man-in-the-middle attacks.');
54
+ logger_1.logger.warn('Configure a domain on your server for secure authentication.');
55
+ logger_1.logger.blank();
56
+ // Fetch public key
57
+ let publicKey;
58
+ try {
59
+ const keyResponse = await axios_1.default.get(`${this.serverUrl}/api/cli/public-key`, { timeout: 10000 });
60
+ publicKey = keyResponse.data.data.publicKey;
61
+ }
62
+ catch (error) {
63
+ this.handleError(error, 'Failed to fetch RSA public key');
64
+ throw error;
65
+ }
66
+ // Encrypt credentials
67
+ const credentials = JSON.stringify({ username, password });
68
+ let encrypted;
69
+ try {
70
+ const encryptedBuffer = crypto_1.default.publicEncrypt({
71
+ key: publicKey,
72
+ padding: crypto_1.default.constants.RSA_PKCS1_OAEP_PADDING,
73
+ oaepHash: 'sha256',
74
+ }, Buffer.from(credentials));
75
+ encrypted = encryptedBuffer.toString('base64');
76
+ }
77
+ catch (error) {
78
+ logger_1.logger.error('Failed to encrypt credentials');
79
+ throw new Error('Encryption failed');
80
+ }
81
+ // Send encrypted credentials
82
+ try {
83
+ const authResponse = await axios_1.default.post(`${this.serverUrl}/api/cli/auth`, { encryptedCredentials: encrypted }, { timeout: 10000 });
84
+ const data = authResponse.data.data;
85
+ logger_1.logger.info(`Token expires in ${Math.round(data.expiresIn / 60000)} minutes`);
86
+ logger_1.logger.warn('Short token lifetime due to HTTP mode. Re-authenticate as needed.');
87
+ return data;
88
+ }
89
+ catch (error) {
90
+ this.handleError(error, 'Authentication failed');
91
+ throw error;
92
+ }
93
+ }
94
+ /**
95
+ * Direct authentication (HTTPS mode)
96
+ */
97
+ async authenticateDirect(username, password) {
98
+ try {
99
+ const response = await axios_1.default.post(`${this.serverUrl}/api/cli/auth`, { username, password }, { timeout: 10000 });
100
+ const data = response.data.data;
101
+ const hours = Math.round(data.expiresIn / 3600000);
102
+ logger_1.logger.success(`Authenticated successfully`);
103
+ logger_1.logger.info(`Token expires in ${hours} hours`);
104
+ return data;
105
+ }
106
+ catch (error) {
107
+ this.handleError(error, 'Authentication failed');
108
+ throw error;
109
+ }
110
+ }
111
+ /**
112
+ * Refresh token (only works in HTTPS mode)
113
+ */
114
+ async refreshToken(currentToken) {
115
+ try {
116
+ const response = await axios_1.default.post(`${this.serverUrl}/api/cli/refresh`, {}, {
117
+ timeout: 10000,
118
+ headers: {
119
+ Authorization: `Bearer ${currentToken}`,
120
+ },
121
+ });
122
+ logger_1.logger.success('Token refreshed successfully');
123
+ return response.data.data;
124
+ }
125
+ catch (error) {
126
+ if (axios_1.default.isAxiosError(error)) {
127
+ const status = error.response?.status;
128
+ if (status === 400) {
129
+ // Token refresh not available (HTTP mode)
130
+ logger_1.logger.warn('Token refresh not available. Please re-authenticate.');
131
+ return null;
132
+ }
133
+ if (status === 401) {
134
+ logger_1.logger.warn('Token expired. Please re-authenticate.');
135
+ return null;
136
+ }
137
+ }
138
+ logger_1.logger.error('Failed to refresh token');
139
+ return null;
140
+ }
141
+ }
142
+ /**
143
+ * Handle axios errors with user-friendly messages
144
+ */
145
+ handleError(error, context) {
146
+ if (axios_1.default.isAxiosError(error)) {
147
+ const axiosError = error;
148
+ const message = axiosError.response?.data?.error ||
149
+ axiosError.response?.data?.message ||
150
+ axiosError.message;
151
+ logger_1.logger.error(`${context}: ${message}`);
152
+ }
153
+ else if (error instanceof Error) {
154
+ logger_1.logger.error(`${context}: ${error.message}`);
155
+ }
156
+ else {
157
+ logger_1.logger.error(`${context}: Unknown error`);
158
+ }
159
+ }
160
+ }
161
+ exports.AuthService = AuthService;
162
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aFNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvYXV0aFNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsb0RBQTRCO0FBQzVCLGtEQUEwQztBQUMxQyw0Q0FBeUM7QUFvQ3pDOzs7O0dBSUc7QUFDSCxNQUFhLFdBQVc7SUFHdEIsWUFBWSxTQUFpQjtRQUMzQixnQkFBZ0I7UUFDaEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsZUFBZTtRQUNuQixJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLGVBQUssQ0FBQyxHQUFHLENBQzlCLEdBQUcsSUFBSSxDQUFDLFNBQVMsd0JBQXdCLEVBQ3pDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxDQUNuQixDQUFDO1lBQ0YsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM1QixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLDZCQUE2QixDQUFDLENBQUM7WUFDdkQsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxZQUFZLENBQUMsUUFBZ0IsRUFBRSxRQUFnQjtRQUNuRCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUU5QyxJQUFJLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN6QixPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDdEQsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVB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Y3J5cHRvJztcbmltcG9ydCBheGlvcywgeyBBeGlvc0Vycm9yIH0gZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyJztcblxuZXhwb3J0IHR5cGUgU2VjdXJpdHlNb2RlID0gJ2lwLWh0dHAnIHwgJ2RvbWFpbi1odHRwcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VjdXJpdHlNb2RlUmVzcG9uc2Uge1xuICBzdWNjZXNzOiBib29sZWFuO1xuICBkYXRhOiB7XG4gICAgc2VjdXJpdHlNb2RlOiBTZWN1cml0eU1vZGU7XG4gICAgc2VydmVySXA6IHN0cmluZyB8IG51bGw7XG4gICAgZG9tYWluOiBzdHJpbmcgfCBudWxsO1xuICAgIGRvbWFpbkFjdGl2ZTogYm9vbGVhbjtcbiAgICByZXF1aXJlc1JTQTogYm9vbGVhbjtcbiAgICB0b2tlbk1heEFnZTogbnVtYmVyO1xuICAgIHRva2VuVHlwZTogJ3BhaXJpbmcnIHwgJ3N0YW5kYXJkJztcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQdWJsaWNLZXlSZXNwb25zZSB7XG4gIHN1Y2Nlc3M6IGJvb2xlYW47XG4gIGRhdGE6IHtcbiAgICBwdWJsaWNLZXk6IHN0cmluZztcbiAgfTtcbiAgd2FybmluZz86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBdXRoUmVzcG9uc2Uge1xuICBzdWNjZXNzOiBib29sZWFuO1xuICBkYXRhOiB7XG4gICAgdG9rZW46IHN0cmluZztcbiAgICBleHBpcmVzSW46IG51bWJlcjtcbiAgICBleHBpcmVzQXQ6IHN0cmluZztcbiAgICB0b2tlblR5cGU6ICdwYWlyaW5nJyB8ICdzdGFuZGFyZCc7XG4gICAgc2VjdXJpdHlNb2RlOiBTZWN1cml0eU1vZGU7XG4gIH07XG59XG5cbi8qKlxuICogQ0xJIEF1dGhlbnRpY2F0aW9uIFNlcnZpY2VcbiAqXG4gKiBIYW5kbGVzIGF1dGhlbnRpY2F0aW9uIGZsb3cgZm9yIGJvdGggSFRUUCAoUlNBKSBhbmQgSFRUUFMgKGRpcmVjdCkgbW9kZXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBdXRoU2VydmljZSB7XG4gIHByaXZhdGUgc2VydmVyVXJsOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3Ioc2VydmVyVXJsOiBzdHJpbmcpIHtcbiAgICAvLyBOb3JtYWxpemUgVVJMXG4gICAgdGhpcy5zZXJ2ZXJVcmwgPSBzZXJ2ZXJVcmwucmVwbGFjZSgvXFwvKyQvLCAnJyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNlcnZlciBzZWN1cml0eSBtb2RlIGFuZCBjb25uZWN0aW9uIGluZm9cbiAgICovXG4gIGFzeW5jIGdldFNlY3VyaXR5TW9kZSgpOiBQcm9taXNlPFNlY3VyaXR5TW9kZVJlc3BvbnNlWydkYXRhJ10+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQ8U2VjdXJpdHlNb2RlUmVzcG9uc2U+KFxuICAgICAgICBgJHt0aGlzLnNlcnZlclVybH0vYXBpL2NsaS9zZWN1cml0eS1tb2RlYCxcbiAgICAgICAgeyB0aW1lb3V0OiAxMDAwMCB9XG4gICAgICApO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEuZGF0YTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5oYW5kbGVFcnJvcihlcnJvciwgJ0ZhaWxlZCB0byBnZXQgc2VjdXJpdHkgbW9kZScpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEF1dGhlbnRpY2F0ZSB3aXRoIHRoZSBzZXJ2ZXJcbiAgICogQXV0b21hdGljYWxseSBoYW5kbGVzIFJTQSBvciBkaXJlY3QgYXV0aCBiYXNlZCBvbiBzZWN1cml0eSBtb2RlXG4gICAqL1xuICBhc3luYyBhdXRoZW50aWNhdGUodXNlcm5hbWU6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZyk6IFByb21pc2U8QXV0aFJlc3BvbnNlWydkYXRhJ10+IHtcbiAgICBjb25zdCBtb2RlSW5mbyA9IGF3YWl0IHRoaXMuZ2V0U2VjdXJpdHlNb2RlKCk7XG5cbiAgICBpZiAobW9kZUluZm8ucmVxdWlyZXNSU0EpIHtcbiAgICAgIHJldHVybiB0aGlzLmF1dGhlbnRpY2F0ZVdpdGhSU0EodXNlcm5hbWUsIHBhc3N3b3JkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuYXV0aGVudGljYXRlRGlyZWN0KHVzZXJuYW1lLCBwYXNzd29yZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJTQS1lbmNyeXB0ZWQgYXV0aGVudGljYXRpb24gKEhUVFAgbW9kZSlcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYXV0aGVudGljYXRlV2l0aFJTQShcbiAgICB1c2VybmFtZTogc3RyaW5nLFxuICAgIHBhc3N3b3JkOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxBdXRoUmVzcG9uc2VbJ2RhdGEnXT4ge1xuICAgIC8vIFNob3cgTUlUTSB3YXJuaW5nXG4gICAgbG9nZ2VyLmJsYW5rKCk7XG4gICAgbG9nZ2VyLndhcm4oJ1dBUk5JTkc6IFVzaW5nIFJTQSBrZXkgZXhjaGFuZ2Ugb3ZlciBIVFRQJyk7XG4gICAgbG9nZ2VyLndhcm4oJ1RoaXMgbWV0aG9kIGlzIHZ1bG5lcmFibGUgdG8gbWFuLWluLXRoZS1taWRkbGUgYXR0YWNrcy4nKTtcbiAgICBsb2dnZXIud2FybignQ29uZmlndXJlIGEgZG9tYWluIG9uIHlvdXIgc2VydmVyIGZvciBzZWN1cmUgYXV0aGVudGljYXRpb24uJyk7XG4gICAgbG9nZ2VyLmJsYW5rKCk7XG5cbiAgICAvLyBGZXRjaCBwdWJsaWMga2V5XG4gICAgbGV0IHB1YmxpY0tleTogc3RyaW5nO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBrZXlSZXNwb25zZSA9IGF3YWl0IGF4aW9zLmdldDxQdWJsaWNLZXlSZXNwb25zZT4oXG4gICAgICAgIGAke3RoaXMuc2VydmVyVXJsfS9hcGkvY2xpL3B1YmxpYy1rZXlgLFxuICAgICAgICB7IHRpbWVvdXQ6IDEwMDAwIH1cbiAgICAgICk7XG4gICAgICBwdWJsaWNLZXkgPSBrZXlSZXNwb25zZS5kYXRhLmRhdGEucHVibGljS2V5O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmhhbmRsZUVycm9yKGVycm9yLCAnRmFpbGVkIHRvIGZldGNoIFJTQSBwdWJsaWMga2V5Jyk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG5cbiAgICAvLyBFbmNyeXB0IGNyZWRlbnRpYWxzXG4gICAgY29uc3QgY3JlZGVudGlhbHMgPSBKU09OLnN0cmluZ2lmeSh7IHVzZXJuYW1lLCBwYXNzd29yZCB9KTtcbiAgICBsZXQgZW5jcnlwdGVkOiBzdHJpbmc7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZW5jcnlwdGVkQnVmZmVyID0gY3J5cHRvLnB1YmxpY0VuY3J5cHQoXG4gICAgICAgIHtcbiAgICAgICAgICBrZXk6IHB1YmxpY0tleSxcbiAgICAgICAgICBwYWRkaW5nOiBjcnlwdG8uY29uc3RhbnRzLlJTQV9QS0NTMV9PQUVQX1BBRERJTkcsXG4gICAgICAgICAgb2FlcEhhc2g6ICdzaGEyNTYnLFxuICAgICAgICB9LFxuICAgICAgICBCdWZmZXIuZnJvbShjcmVkZW50aWFscylcbiAgICAgICk7XG4gICAgICBlbmNyeXB0ZWQgPSBlbmNyeXB0ZWRCdWZmZXIudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0ZhaWxlZCB0byBlbmNyeXB0IGNyZWRlbnRpYWxzJyk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VuY3J5cHRpb24gZmFpbGVkJyk7XG4gICAgfVxuXG4gICAgLy8gU2VuZCBlbmNyeXB0ZWQgY3JlZGVudGlhbHNcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXV0aFJlc3BvbnNlID0gYXdhaXQgYXhpb3MucG9zdDxBdXRoUmVzcG9uc2U+KFxuICAgICAgICBgJHt0aGlzLnNlcnZlclVybH0vYXBpL2NsaS9hdXRoYCxcbiAgICAgICAgeyBlbmNyeXB0ZWRDcmVkZW50aWFsczogZW5jcnlwdGVkIH0sXG4gICAgICAgIHsgdGltZW91dDogMTAwMDAgfVxuICAgICAgKTtcblxuICAgICAgY29uc3QgZGF0YSA9IGF1dGhSZXNwb25zZS5kYXRhLmRhdGE7XG4gICAgICBsb2dnZXIuaW5mbyhgVG9rZW4gZXhwaXJlcyBpbiAke01hdGgucm91bmQoZGF0YS5leHBpcmVzSW4gLyA2MDAwMCl9IG1pbnV0ZXNgKTtcbiAgICAgIGxvZ2dlci53YXJuKCdTaG9ydCB0b2tlbiBsaWZldGltZSBkdWUgdG8gSFRUUCBtb2RlLiBSZS1hdXRoZW50aWNhdGUgYXMgbmVlZGVkLicpO1xuXG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5oYW5kbGVFcnJvcihlcnJvciwgJ0F1dGhlbnRpY2F0aW9uIGZhaWxlZCcpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERpcmVjdCBhdXRoZW50aWNhdGlvbiAoSFRUUFMgbW9kZSlcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYXV0aGVudGljYXRlRGlyZWN0KFxuICAgIHVzZXJuYW1lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBQcm9taXNlPEF1dGhSZXNwb25zZVsnZGF0YSddPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MucG9zdDxBdXRoUmVzcG9uc2U+KFxuICAgICAgICBgJHt0aGlzLnNlcnZlclVybH0vYXBpL2NsaS9hdXRoYCxcbiAgICAgICAgeyB1c2VybmFtZSwgcGFzc3dvcmQgfSxcbiAgICAgICAgeyB0aW1lb3V0OiAxMDAwMCB9XG4gICAgICApO1xuXG4gICAgICBjb25zdCBkYXRhID0gcmVzcG9uc2UuZGF0YS5kYXRhO1xuICAgICAgY29uc3QgaG91cnMgPSBNYXRoLnJvdW5kKGRhdGEuZXhwaXJlc0luIC8gMzYwMDAwMCk7XG4gICAgICBsb2dnZXIuc3VjY2VzcyhgQXV0aGVudGljYXRlZCBzdWNjZXNzZnVsbHlgKTtcbiAgICAgIGxvZ2dlci5pbmZvKGBUb2tlbiBleHBpcmVzIGluICR7aG91cnN9IGhvdXJzYCk7XG5cbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aGlzLmhhbmRsZUVycm9yKGVycm9yLCAnQXV0aGVudGljYXRpb24gZmFpbGVkJyk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaCB0b2tlbiAob25seSB3b3JrcyBpbiBIVFRQUyBtb2RlKVxuICAgKi9cbiAgYXN5bmMgcmVmcmVzaFRva2VuKGN1cnJlbnRUb2tlbjogc3RyaW5nKTogUHJvbWlzZTxBdXRoUmVzcG9uc2VbJ2RhdGEnXSB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBheGlvcy5wb3N0PEF1dGhSZXNwb25zZT4oXG4gICAgICAgIGAke3RoaXMuc2VydmVyVXJsfS9hcGkvY2xpL3JlZnJlc2hgLFxuICAgICAgICB7fSxcbiAgICAgICAge1xuICAgICAgICAgIHRpbWVvdXQ6IDEwMDAwLFxuICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHtjdXJyZW50VG9rZW59YCxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICApO1xuXG4gICAgICBsb2dnZXIuc3VjY2VzcygnVG9rZW4gcmVmcmVzaGVkIHN1Y2Nlc3NmdWxseScpO1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmRhdGEuZGF0YTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGF4aW9zLmlzQXhpb3NFcnJvcihlcnJvcikpIHtcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gZXJyb3IucmVzcG9uc2U/LnN0YXR1cztcbiAgICAgICAgaWYgKHN0YXR1cyA9PT0gNDAwKSB7XG4gICAgICAgICAgLy8gVG9rZW4gcmVmcmVzaCBub3QgYXZhaWxhYmxlIChIVFRQIG1vZGUpXG4gICAgICAgICAgbG9nZ2VyLndhcm4oJ1Rva2VuIHJlZnJlc2ggbm90IGF2YWlsYWJsZS4gUGxlYXNlIHJlLWF1dGhlbnRpY2F0ZS4nKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgICBsb2dnZXIud2FybignVG9rZW4gZXhwaXJlZC4gUGxlYXNlIHJlLWF1dGhlbnRpY2F0ZS4nKTtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gcmVmcmVzaCB0b2tlbicpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBheGlvcyBlcnJvcnMgd2l0aCB1c2VyLWZyaWVuZGx5IG1lc3NhZ2VzXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZUVycm9yKGVycm9yOiB1bmtub3duLCBjb250ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoYXhpb3MuaXNBeGlvc0Vycm9yKGVycm9yKSkge1xuICAgICAgY29uc3QgYXhpb3NFcnJvciA9IGVycm9yIGFzIEF4aW9zRXJyb3I8eyBlcnJvcj86IHN0cmluZzsgbWVzc2FnZT86IHN0cmluZyB9PjtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPVxuICAgICAgICBheGlvc0Vycm9yLnJlc3BvbnNlPy5kYXRhPy5lcnJvciB8fFxuICAgICAgICBheGlvc0Vycm9yLnJlc3BvbnNlPy5kYXRhPy5tZXNzYWdlIHx8XG4gICAgICAgIGF4aW9zRXJyb3IubWVzc2FnZTtcbiAgICAgIGxvZ2dlci5lcnJvcihgJHtjb250ZXh0fTogJHttZXNzYWdlfWApO1xuICAgIH0gZWxzZSBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKGAke2NvbnRleHR9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgJHtjb250ZXh0fTogVW5rbm93biBlcnJvcmApO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,21 @@
1
+ import { ProjectType, PackageManager } from '../types';
2
+ export interface BuildOptions {
3
+ projectPath: string;
4
+ projectType: ProjectType;
5
+ projectName: string;
6
+ packageManager: PackageManager;
7
+ envFile?: string;
8
+ }
9
+ export interface BuildResult {
10
+ success: boolean;
11
+ outputDir: string;
12
+ duration: number;
13
+ error?: string;
14
+ }
15
+ export declare class BuildService {
16
+ build(options: BuildOptions): Promise<BuildResult>;
17
+ private getBuildArgs;
18
+ private getOutputDir;
19
+ private runCommand;
20
+ }
21
+ export declare const buildService: BuildService;