UNPKG

webostv-app

Version:
221 lines (188 loc) 6.31 kB
#! /usr/bin/env node const path = require('path'); const fs = require('file-system'); const program = require('commander'); const childProcess = require('child_process'); const env = process.env; program .version(env.npm_package_version) .option('--sdk-cli-path <path>', '(Required) Path to the WebOSTV SDK CLI dir') .option('--source-dir <path>', 'Path to the dir containing all metadatas', 'webos-meta-data') .option('--appinfo-name <name>', 'Name of the JSON file containing appinfo (eg: appinfo.json)', 'appinfo.json') .option('--no-override', 'Prevent appinfo.json to be overridden by package.json') .option('--no-auto-bind', 'Prevent automatic binding to your app of options passed to ares '); program .command('meta <destDir>') .description('Copy all metadatas to the specified folder. Meta are feed by package.json') .action(meta); buildAresCommand('package', [ ['-c, --check', 'Check the application but don\'t package it'], ['-o, --outdir <OUTPUT_DIR>', 'Use OUTPUT_DIR as the output directory'], ['-e, --app-exclude <PATTERN>', 'Exclude files, given as a PATTERN'], ['-h, --help', 'Display this help'], ['-q', 'Display this verbose log'], ['-n, --no-minify', 'Skip the minification phase'], ['-r, --rom', 'Do not create ipk, instead output a folder structure'] ]); buildAresCommand('install', [ ['-d, --device <DEVICE>', 'Specify DEVICE to use'], ['-D, --device-list', 'List the available DEVICEs'], ['-l, --list', 'List the installed apps'], ['-F, --listfull', 'List the detailed info of the installed apps'], ['-h, --help', 'Display this help'], ['-v', 'Display this verbose log'], ['-S, --list-storage', 'List the storages of the DEVICE'], ['-s, --storage <STORAGE>', 'Specify STORAGE to install'], ['-r, --remove <APP_ID>', 'Specify the APP_ID to remove'] ]); buildAresCommand('inspect', [ ['-o, --open', 'Open url with a web browser'], ['-d, --device <DEVICE>', 'Specify DEVICE to use'], ['-D, --device-list', 'List the available DEVICEs'], ['-h, --help', 'Display this help'], ['-v', 'Display this verbose log'], ['-a, --app <APP_ID>', 'Specify the APP_ID to inspect'], ['-s, --service <SERVICE_ID>', 'Specify the SERVICE_ID to inspect'] ]); program.parse(process.argv); function buildAresCommand(name, cmds) { var command = program.command(name+' [args...]'); for (var i = 0; i < cmds.length; ++i) { command.option.apply(command, cmds[i]); } command .description('Shortcut to ares-'+name) .action(function(args, optns) { buildArgs(args, optns); autoBind(args, optns); runScript(name, args, optns); }); } function meta(destDir, optns) { var appInfo = getAppInfo(optns.parent); var fname = optns.parent.appinfoName; var srcDir = optns.parent.sourceDir; copyImages(appInfo, srcDir, destDir); var appInfoStr = JSON.stringify(appInfo); fs.mkdirSync(destDir, {recursive: true}); fs.writeFileSync(destDir+'/'+fname, appInfoStr); } function getAppInfo(optns) { var fname = optns.appinfoName; var srcDir = optns.sourceDir; mustExists(srcDir+'/'+fname); var appInfo = JSON.parse(fs.readFileSync(srcDir+'/'+fname, 'utf-8')); if (optns.override) { appInfo.version = env.npm_package_version; appInfo.title = env.npm_package_name; appInfo.appDescription = env.npm_package_description; } return appInfo; } function copyImages(appInfo, srcDir, destDir) { const array = ['icon', 'largeIcon', 'bgImage', 'splashBackground']; var attr; for (var i = 0; i < array.length; ++i) { attr = array[i]; if (attr[i]) { mustExists(srcDir+'/'+appInfo[attr]); fs.copyFileSync(srcDir+'/'+appInfo[attr], destDir+'/'+appInfo[attr]); } } } function mustExists(fname, errorMsg) { if (!fs.existsSync(fname)) { throw new Error(errorMsg || '"' + fname + '" does not exist.'); } } function toCamelCase(str) { var array = str.split('-'); for (var j = 1; j < array.length; ++j) { array[j] = array[j][0].toUpperCase() + array[j].slice(1); } return array.join(''); } function buildArgs(args, optns) { var optn, attr, val, reversed = false; for (var i = 0; i < optns.options.length; ++i) { optn = optns.options[i]; attr = getOptnAttr(optn); if (optns.hasOwnProperty(attr)) { val = optns[attr]; reversed = !!optn.long.match('--no-'); if (optn.optional && val) { val = ''; } if (!reversed || !val) { args.push(optn.long); if ((optn.required || optn.optional) && val !== '') { args.push(val); } } } } } function getOptnAttr(optn) { var attr; if (optn.short) { attr = toCamelCase(optn.long.replace(/^--no-|--/, '')); } else { attr = optn.long.replace(/^-/, '').toUpperCase(); } return attr; } function autoBind(args, optns) { if (!optns.parent.autoBind) { return; } var appInfo = getAppInfo(optns.parent); var isApp = appInfo.type === 'web'; const optnToOverrideSrv = { 'inspect': ['--service', '{id}'], 'install': ['{id}_{version}_all.ipk'] }; const optnToOverrideApp = { 'inspect': ['--app', '{id}'], 'install': ['{id}_{version}_all.ipk'] }; const optnToOverride = isApp? optnToOverrideApp : optnToOverrideSrv; var newArgs = optnToOverride[optns._name]; if (newArgs) { for (var j = 0; j < newArgs.length; ++j) { args.push(newArgs[j].replace(/{.*?}/gi, function (rep) { return appInfo[rep.slice(1, -1)]; })); } } } function runScript(name, args, optns) { if (!optns.parent.sdkCliPath) { throw new Error('You must specifie a path to WebOSTV SDK CLI dir'); } // keep track of whether callback has been invoked to prevent multiple invocations var invoked = false; var sname = optns.parent.sdkCliPath+'/bin/ares-'+name+'.js'; console.log('Running '+sname+' '+args.join(' ')); var process = childProcess.fork(sname, args); var callback = function (err) { if (err) { throw err; } console.log('finished running '+sname); }; // listen for errors as they may prevent the exit event from firing process.on('error', function (err) { if (!invoked) { invoked = true; callback(err); } }); // execute the callback once the process has finished running process.on('exit', function (code) { if (!invoked) { invoked = true; var err = code === 0 ? null : new Error('exit code ' + code); callback(err); } }); }