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.
174 lines (173 loc) • 6.03 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.readVSCodeTasks = readVSCodeTasks;
exports.getBuildTasks = getBuildTasks;
exports.executeTask = executeTask;
exports.getAllTasks = getAllTasks;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const child_process_1 = require("child_process");
/**
* Read and parse VSCode tasks.json configuration
*/
function readVSCodeTasks(projectRootDir) {
const tasksJsonPath = path.join(projectRootDir, '.vscode', 'tasks.json');
if (!fs.existsSync(tasksJsonPath)) {
return null;
}
try {
// Read the file content
const content = fs.readFileSync(tasksJsonPath, 'utf8');
// Remove comments and trailing commas (more aggressive cleaning)
let jsonContent = content
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments
.replace(/\/\/.*$/gm, ''); // Remove line comments
// Remove trailing commas before ] or }
jsonContent = jsonContent
.replace(/,\s*\]/g, ']') // Remove trailing comma before ]
.replace(/,\s*\}/g, '}'); // Remove trailing comma before }
// Parse JSON
const config = JSON.parse(jsonContent);
return config;
}
catch (error) {
console.error('Error parsing tasks.json:', error);
return null;
}
}
/**
* Get build-related tasks from tasks.json
*/
function getBuildTasks(projectRootDir) {
const tasksConfig = readVSCodeTasks(projectRootDir);
if (!tasksConfig || !tasksConfig.tasks) {
return [];
}
// Filter tasks that are likely build tasks
return tasksConfig.tasks.filter(task => {
const label = task.label.toLowerCase();
return label.includes('build') ||
label.includes('compile') ||
label.includes('package') ||
label.includes('deploy') ||
(task.group && task.group.kind === 'build');
});
}
/**
* Execute a VSCode task
*/
async function executeTask(task, projectRootDir, timeout) {
return new Promise((resolve, reject) => {
let command;
let args = [];
if (task.type === 'npm' && task.script) {
command = 'npm';
args = ['run', task.script];
}
else if (task.type === 'shell' && task.command) {
// Parse command and args
const parts = task.command.split(' ');
command = parts[0];
args = parts.slice(1);
if (task.args) {
args = args.concat(task.args);
}
}
else if (task.command) {
command = task.command;
args = task.args || [];
}
else {
reject(new Error(`Cannot determine command for task: ${task.label}`));
return;
}
const cwd = task.options?.cwd
? path.isAbsolute(task.options.cwd)
? task.options.cwd
: path.join(projectRootDir, task.options.cwd)
: projectRootDir;
console.log(`Executing: ${command} ${args.join(' ')}`);
console.log(`Working directory: ${cwd}`);
const child = (0, child_process_1.spawn)(command, args, {
cwd,
env: { ...process.env, ...task.options?.env },
stdio: 'inherit',
shell: true
});
let timeoutId;
if (timeout) {
timeoutId = setTimeout(() => {
console.log(`\nTask timed out after ${timeout}ms. Killing process...`);
child.kill('SIGTERM');
setTimeout(() => {
if (!child.killed) {
child.kill('SIGKILL');
}
}, 5000);
}, timeout);
}
child.on('close', (code) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (code === 0) {
resolve();
}
else if (code === null) {
reject(new Error(`Task "${task.label}" was terminated`));
}
else {
reject(new Error(`Task "${task.label}" failed with exit code ${code}`));
}
});
child.on('error', (err) => {
if (timeoutId) {
clearTimeout(timeoutId);
}
reject(err);
});
});
}
/**
* Get all tasks from tasks.json
*/
function getAllTasks(projectRootDir) {
const tasksConfig = readVSCodeTasks(projectRootDir);
if (!tasksConfig || !tasksConfig.tasks) {
return [];
}
return tasksConfig.tasks;
}