roku-pkg-cli
Version:
A comprehensive CLI tool for managing multiple Roku projects with automated device discovery, build integration, and package generation. Perfect for CI/CD pipelines with full automation support.
157 lines (156 loc) ⢠7.62 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.discoverCommand = discoverCommand;
const inquirer_1 = __importDefault(require("inquirer"));
const config_manager_1 = require("../lib/config-manager");
const roku_discovery_1 = require("../lib/roku-discovery");
const roku_api_1 = require("../lib/roku-api");
const chalk_1 = __importDefault(require("chalk"));
const ora_1 = __importDefault(require("ora"));
function discoverCommand(program) {
program
.command('discover')
.description('Discover Roku devices on the network and optionally configure one')
.option('--configure', 'Configure a discovered device immediately')
.option('--first-device', 'Automatically use the first discovered device (requires --configure)')
.option('--password <password>', 'Provide the developer password (avoids interactive prompt)')
.action(async (options) => {
// Validate flag combinations
if (options.firstDevice && !options.configure) {
console.log(chalk_1.default.red('\nError: --first-device can only be used with --configure\n'));
return;
}
console.log(chalk_1.default.bold('\nš” Discovering Roku devices on the network...\n'));
const spinner = (0, ora_1.default)('Scanning for Roku devices...').start();
try {
const devices = await roku_discovery_1.RokuDiscovery.discoverDevices();
spinner.stop();
if (devices.length === 0) {
console.log(chalk_1.default.yellow('No Roku devices found on the network.'));
console.log(chalk_1.default.gray('\nTroubleshooting tips:'));
console.log(chalk_1.default.gray('⢠Make sure your Roku device is connected to the same network'));
console.log(chalk_1.default.gray('⢠Enable "Developer mode" on your Roku device'));
console.log(chalk_1.default.gray('⢠Check that ECP (External Control Protocol) is enabled'));
console.log(chalk_1.default.gray('⢠Try configuring the device manually with "roku-pkg device"\n'));
return;
}
console.log(chalk_1.default.green(`ā Found ${devices.length} Roku device${devices.length === 1 ? '' : 's'}:\n`));
// Display discovered devices
devices.forEach((device, index) => {
console.log(chalk_1.default.cyan(`${index + 1}. ${device.name}`));
console.log(chalk_1.default.gray(` IP: ${device.ip}`));
console.log(chalk_1.default.gray(` Model: ${device.modelName}`));
console.log(chalk_1.default.gray(` Serial: ${device.serialNumber}`));
if (device.softwareVersion) {
console.log(chalk_1.default.gray(` Software: ${device.softwareVersion}`));
}
console.log();
});
// If configure option is provided, allow user to select and configure a device
if (options.configure) {
await configureDiscoveredDevice(devices, options.firstDevice, options.password);
}
else {
console.log(chalk_1.default.blue('Use "roku-pkg discover --configure" to set up one of these devices.'));
console.log(chalk_1.default.blue('Or use "roku-pkg generate --discover" to select a device during package generation.\n'));
}
}
catch (error) {
spinner.fail('Discovery failed');
console.log(chalk_1.default.red(`Error: ${error.message}\n`));
}
});
}
async function configureDiscoveredDevice(devices, autoSelectFirst, providedPassword) {
const configManager = new config_manager_1.ConfigManager();
let selectedDevice;
// Auto-select first device if flag is provided
if (autoSelectFirst) {
selectedDevice = devices[0];
console.log(chalk_1.default.blue(`š¤ Auto-selecting first device: ${selectedDevice.name} (${selectedDevice.ip})\n`));
}
else {
// Let user select a device interactively
const response = await inquirer_1.default.prompt([
{
type: 'list',
name: 'selectedDevice',
message: 'Select a device to configure:',
choices: [
...devices.map((device, index) => ({
name: `${device.name} (${device.ip}) - ${device.modelName}`,
value: device
})),
{ name: chalk_1.default.gray('Cancel'), value: null }
]
}
]);
selectedDevice = response.selectedDevice;
if (!selectedDevice) {
console.log(chalk_1.default.gray('\nConfiguration cancelled.\n'));
return;
}
}
// Test device connectivity first
const spinner = (0, ora_1.default)(`Testing connection to ${selectedDevice.name}...`).start();
const isReachable = await roku_discovery_1.RokuDiscovery.testDevice(selectedDevice);
if (!isReachable) {
spinner.fail(`Cannot connect to ${selectedDevice.name}`);
console.log(chalk_1.default.red('Device is not reachable. Please check network connectivity.\n'));
return;
}
spinner.succeed(`Connected to ${selectedDevice.name}`);
// Get developer password
let password = providedPassword;
if (!password) {
const response = await inquirer_1.default.prompt([
{
type: 'password',
name: 'password',
message: 'Enter the Roku developer password:',
mask: '*',
validate: (input) => input ? true : 'Password is required'
}
]);
password = response.password;
}
else {
console.log(chalk_1.default.gray(`Using provided password for ${selectedDevice.name}`));
}
// Ensure password is available at this point
if (!password) {
console.log(chalk_1.default.red('Password is required but not provided.\n'));
return;
}
// Test authentication
const authSpinner = (0, ora_1.default)('Testing authentication...').start();
try {
const rokuApi = new roku_api_1.RokuAPI(selectedDevice.ip, password);
const authSuccess = await rokuApi.testConnection();
if (!authSuccess) {
authSpinner.fail('Authentication test failed');
console.log(chalk_1.default.red('Unable to authenticate with the device. Please check your password.\n'));
return;
}
authSpinner.succeed('Authentication successful');
// Save device configuration
const deviceConfig = {
ip: selectedDevice.ip,
password: password,
name: selectedDevice.name,
modelName: selectedDevice.modelName,
serialNumber: selectedDevice.serialNumber,
softwareVersion: selectedDevice.softwareVersion
};
configManager.setRokuDevice(deviceConfig);
console.log(chalk_1.default.green(`\nā Device "${selectedDevice.name}" configured successfully!\n`));
console.log(chalk_1.default.blue('You can now use "roku-pkg generate" to build and deploy packages to this device.\n'));
}
catch (error) {
authSpinner.fail('Authentication failed');
console.log(chalk_1.default.red(`Error: ${error.message}\n`));
}
}