UNPKG

titanium

Version:

Command line interface for building Titanium SDK apps

252 lines (227 loc) 6.89 kB
/* eslint-disable max-len */ import chalk from 'chalk'; import { ticonfig } from '../util/ticonfig.js'; import { TiError } from '../util/tierror.js'; import { expand } from '../util/expand.js'; const { cyan } = chalk; export const extendedDesc = `Gets and sets config options. If no key is specified, then all key/values are returned. When specifying only the __<key>__ and using the __--remove__ flag, the specified key and all of its descendants are removed. The __path.*__ config settings allow lists of values. You can specify multiple __<value>__'s following the __<key>__. Use the __--append__ flag to append a new value and the __--remove__ flag to remove an existing value. Set the SDK path overwriting the previous values __titanium config paths.sdks /path/to/sdk__ Add another SDK path __titanium config paths.sdks --append /path/to/another/sdk__ Remove an SDK path __titanium config paths.sdks --remove /path/to/sdk__ The config file is located at: __${ticonfig.getConfigPath()}__`; /** * Returns the configuration for the config command. * @param {Object} _logger - The logger instance * @param {Object} _config - The CLI config object * @param {CLI} _cli - The CLI instance * @returns {Object} Config command configuration */ export function config(_logger, _config, _cli) { return { title: 'Config', skipBanner: true, flags: { append: { abbr: 'a', desc: 'appends a value to a key containing a list of values' }, json: { desc: 'output config as JSON' }, remove: { abbr: 'r', desc: 'removes all values and all its descendants or a specific value from a list of values' } }, options: { output: { abbr: 'o', default: 'report', hidden: true, values: ['report', 'json'] } }, args: [ { name: 'key', desc: 'the key to get or set' }, { name: 'value', desc: 'the value to set the specified key' } ] }; } /** * Validates command line arguments. * @param {Object} logger - The logger instance * @param {Object} config - The CLI config object * @param {CLI} cli - The CLI instance */ export function validate(_logger, _config, cli) { const [key, value] = cli.argv._; if (key !== undefined && !/^([A-Za-z_]{1}[A-Za-z0-9-_]*(\.[A-Za-z-_]{1}[A-Za-z0-9-_]*)*)$/.test(key)) { throw new TiError(`Invalid key "${key}"`); } if (cli.argv.remove) { if (key === undefined) { throw new TiError('Missing key of the config setting to remove', { after: `Run ${cyan('titanium config --remove <key>')} to remove the config setting.` }); } // if the key is not a path setting, then we don't allow any values if (value !== undefined && !/^paths\..*$/.test(key)) { throw new TiError('Too many arguments for "--remove" flag', { after: `Run ${cyan( `titanium config --remove ${key.includes(' ') ? `"${key}"` : key}` )} to remove the config setting.` }); } } } /** * Displays config settings or sets a config value. * @param {Object} logger - The logger instance * @param {Object} config - The CLI config object * @param {CLI} cli - The CLI instance * @param {Function} finished - Callback when the command finishes */ export async function run(logger, config, cli) { const { argv } = cli; const key = argv._.length > 0 ? argv._.shift() : undefined; const value = argv._.length > 0 ? argv._[0] : undefined; const results = {}; const asJson = argv.json || argv.output === 'json'; function walk(obj, parts, parent) { const filter = Array.isArray(parts) ? parts.shift() : null; for (const name of Object.keys(obj)) { if (!filter || name === filter) { const p = parent ? parent + '.' + name : name; if (obj[name] && typeof obj[name] === 'object') { walk(obj[name], parts, p); } else if (!parts || !parts.length || !parent || parent.indexOf(parts) === 0) { results[p] = asJson ? obj[name] : JSON.stringify(obj[name]); } } } } function print(prefix) { if (asJson) { logger.log(JSON.stringify(config.get(prefix), null, '\t')); } else { walk(config, prefix && prefix.split('.')); const maxlen = Object.keys(results).reduce((a, b) => Math.max(a, b.length), 0); for (const key of Object.keys(results).sort()) { logger.log(`${key.padEnd(maxlen)} = ${cyan(results[key] || '')}`); } } } if (key) { try { if (value !== undefined) { // doing a set or removing a list item const listMatch = key.match(/^paths\.(.*)$/); if (listMatch) { const subPath = listMatch[1]; const validKeys = [ 'hooks', 'modules', 'sdks', 'templates', 'xcode' ]; if (!validKeys.includes(subPath)) { throw new TiError(`Unsupported key "${key}"\n`); } if (!config.paths) { config.paths = {}; } if (argv.append) { if (!Array.isArray(config.paths[subPath])) { config.paths[subPath] = []; } for (let v of argv._) { v = expand(v); if (!config.paths[subPath].includes(v)) { config.paths[subPath].push(v); } } } else if (argv.remove) { if (!Array.isArray(config.paths[subPath])) { config.paths[subPath] = []; } for (let v of argv._) { let p = config.paths[subPath].indexOf(v); if (p !== -1) { config.paths[subPath].splice(p, 1); } else { v = expand(v); p = config.paths[subPath].indexOf(v); if (p !== -1) { config.paths[subPath].splice(p, 1); } } } } else { config.paths[subPath] = argv._; } } else { config.set(key, value); } config.save(); logger.log(asJson ? JSON.stringify({ success: true }) : `${cyan(key)} saved`); return; } const parts = key.split('.'); let i = 0; let q = parts.pop(); let p = parts.length && parts[i++]; let obj = config; if (p) { do { obj = p in obj ? obj[p] : (obj[p] = {}); } while (obj && (p = parts[i++])); } if (obj) { if (argv.remove) { // doing a remove if (Object.hasOwn(obj, q)) { delete obj[q]; config.save(); logger.log(asJson ? JSON.stringify({ success: true }) : `${cyan(`"${key}"`)} removed`); return; } } else if (Array.isArray(obj[q])) { if (asJson) { logger.log(JSON.stringify(obj[q])); } else if (obj[q].length) { logger.log(obj[q].join('\n')); } return; } else if (obj[q] && typeof obj[q] === 'object') { print(key); return; } else if (obj[q] !== undefined) { logger.log(asJson ? JSON.stringify(obj[q]) : obj[q]); return; } } throw new TiError(`Key "${key}" not found`); } catch (e) { if (asJson) { logger.logerr(JSON.stringify({ success: false, error: e.message })); process.exit(1); } throw e; } } else { // print all key/values print(); } }