@tscc/tscc
Version:
A typescript transpiler and bundler that wires up tsickle and closure compiler seamlessly
163 lines (162 loc) • 6.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildTsccSpecJSONAndTsArgsFromArgs = exports.parseTsccCommandLineArgs = void 0;
const yargs = require("yargs/yargs");
const chalk = require("chalk");
const tscc_1 = require("./tscc");
const TsccSpecWithTS_1 = require("./spec/TsccSpecWithTS");
const tscc_spec_1 = require("@tscc/tscc-spec");
const ClosureDependencyGraph_1 = require("./graph/ClosureDependencyGraph");
const Logger_1 = require("./log/Logger");
const console = require("console");
/**
* example: tscc -s src/tscc.spec.json -- --experimentalDecorators -- --assume_function_wrapper
*/
async function main(args) {
if (args.clean) {
require('rimraf').sync(tscc_1.TEMP_DIR);
console.log(`Removed ${tscc_1.TEMP_DIR}.`);
return 0;
}
if (args['module'] === undefined && args['spec'] === undefined) {
// Assumes that --spec was set to the current working directory implicitly.
args['spec'] = '.';
}
const { tsccSpecJSON, tsArgs } = buildTsccSpecJSONAndTsArgsFromArgs(args);
await (0, tscc_1.default)(tsccSpecJSON, tsArgs);
return 0;
}
function parseTsccCommandLineArgs(args, strict = true) {
return yargs()
.scriptName('tscc')
.usage(`tscc [--help] [--clean] [--spec <spec_file_path>] [-- <typescript_flags> [-- <closure_compiler_flags>]]`)
.describe('spec', `Perform compilation with tscc spec file at the specified path. ` +
`Defaults to the current working directory.`)
.string('spec')
.describe('module', `Module spec descriptions. ` +
`Format: <name>:<entry_file>[:<dependency_name>[,<dependency2_name>[...]][:<extra_source>[,...]]]`)
.string('module')
.array('module')
.describe('external', 'External module descriptions. Format: <module_name>:<global_name>')
.string('external')
.array('external')
.describe('prefix', `Directory names to emit outputs in, or prefixes for output file names. ` +
`It will just be prepended to module names, so if its last character is not a path separator, ` +
`it will modify the output file's name. Sub-flags --prefix.cc and --prefix.rollup are available.`)
.describe('prefix.cc', `Prefix to be used only by closure compiler build.`)
.describe('prefix.rollup', `Prefix to be used only by rollup build.`)
.describe('debug', `A namespace for debugging options.`)
.describe('debug.persistArtifacts', `Writes intermediate tsickle outputs to .tscc_temp directory.`)
.describe('debug.ignoreWarningsPath', `Prevents tsickle warnings for files whose path contains substrings provided by this flag.`)
.array('debug.ignoreWarningsPath')
.describe('clean', `Clear temporary files in .tscc_temp directory.`)
.describe('-', `Any flags after the first "--" and before the second "--" (if exists) ` +
`will be provided to the typescript compiler.`)
.describe('{2}', `Any flags after the second "--" will be provided to the closure compiler.`)
.epilogue(`For more information or bug reports, please visit https://github.com/theseanl/tscc.`)
.alias({
"spec": "s",
"h": "help",
"v": "version",
})
.parserConfiguration({
'populate--': true,
'camel-case-expansion': false
})
.strict(strict)
.help('h')
.version()
.parse(args);
}
exports.parseTsccCommandLineArgs = parseTsccCommandLineArgs;
function buildTsccSpecJSONAndTsArgsFromArgs(args) {
const tsArgs = args["--"] || [];
const closureCompilerArgs = yargs()
.parserConfiguration({ 'populate--': true })
.parse(tsArgs)["--"] || [];
let i = tsArgs.indexOf('--');
if (i !== -1) {
tsArgs.splice(i);
}
const out = {};
// module flags
// Using "--module" instead of "--modules" looks more natural for a command line interface.
let moduleFlags = args["module"];
if (moduleFlags) {
const moduleFlagValue = [];
for (let moduleFlag of moduleFlags) {
// --modules chunk2:./src/chunk2.ts:chunk0,chunk1:css_renaming_map.js
let [moduleName, entry, dependenciesStr, extraSourcesStr] = moduleFlag.split(':');
let dependencies, extraSources;
if (dependenciesStr)
dependencies = dependenciesStr.split(',');
if (extraSourcesStr)
extraSources = extraSourcesStr.split(',');
moduleFlagValue.push({ moduleName, entry, dependencies, extraSources });
}
out.modules = moduleFlagValue;
}
// external flags
// --external react-dom:ReactDOM
let external = args["external"];
if (external) {
const externalValue = {};
for (let externalEntry of external) {
let [moduleName, globalName] = externalEntry.split(':');
externalValue[moduleName] = globalName;
}
out.external = externalValue;
}
// prefix flags
if (args["prefix"]) {
out.prefix = args["prefix"];
}
// compilerFlags flags
if (closureCompilerArgs.length) {
let compilerFlags = yargs().parse(closureCompilerArgs);
// delete special args produced by yargs
delete compilerFlags["_"];
delete compilerFlags["$0"];
out.compilerFlags = compilerFlags;
}
// debug flags
let debugArgs = args["debug"];
if (debugArgs && typeof debugArgs === 'object') {
out.debug = debugArgs;
}
// spec file
if (args["spec"]) {
out.specFile = args["spec"];
}
return { tsccSpecJSON: out, tsArgs };
}
exports.buildTsccSpecJSONAndTsArgsFromArgs = buildTsccSpecJSONAndTsArgsFromArgs;
if (require.main === module) {
const tsccWarning = new Logger_1.default(chalk.green('TSCC: '));
const tsWarning = new Logger_1.default(chalk.blue('TS: '));
const parsedArgs = parseTsccCommandLineArgs(process.argv.slice(2));
main(parsedArgs)
.then(code => process.exit(code))
.catch(e => {
if (e instanceof tscc_spec_1.TsccSpecError || e instanceof tscc_1.TsccError) {
tsccWarning.log(chalk.red(e.message));
}
else if (e instanceof TsccSpecWithTS_1.TsError) {
tsWarning.log(chalk.red(e.message));
}
else if (e instanceof ClosureDependencyGraph_1.ClosureDepsError) {
tsccWarning.log(chalk.red(e.message));
}
else if (e instanceof tscc_1.CcError) {
tsccWarning.log(chalk.red(e.message));
}
else {
tsccWarning.log(chalk.red(`The compilation has terminated with an unexpected error.`));
tsccWarning.log(e.stack);
return process.exit(1);
}
tsccWarning.log(`The compilation has terminated with an error.`);
return process.exit(1);
});
}