"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }/* eslint-disable no-console */ var _commander = require('commander'); var _commander2 = _interopRequireDefault(_commander); var _glob = require('glob'); var _fs = require('mz/fs'); var _path = require('path'); var _index = require('./index'); function run() { _commander2.default .description(`Sucrase: super-fast Babel alternative.`) .usage("[options] ") .option( "-d, --out-dir ", "Compile an input directory of modules into an output directory.", ) .option( "-p, --project ", "Compile a TypeScript project, will read from tsconfig.json in ", ) .option("--out-extension ", "File extension to use for all output files.", "js") .option("--exclude-dirs ", "Names of directories that should not be traversed.") .option("-q, --quiet", "Don't print the names of converted files.") .option("-t, --transforms ", "Comma-separated list of transforms to run.") .option("--disable-es-transforms", "Opt out of all ES syntax transforms.") .option("--jsx-runtime ", "Transformation mode for the JSX transform.") .option("--production", "Disable debugging information from JSX in output.") .option( "--jsx-import-source ", "Automatic JSX transform import path prefix, defaults to `React.Fragment`.", ) .option( "--jsx-pragma ", "Classic JSX transform element creation function, defaults to `React.createElement`.", ) .option( "--jsx-fragment-pragma ", "Classic JSX transform fragment component, defaults to `React.Fragment`.", ) .option("--keep-unused-imports", "Disable automatic removal of type-only imports/exports.") .option("--preserve-dynamic-import", "Don't transpile dynamic import() to require.") .option( "--inject-create-require-for-import-require", "Use `createRequire` when transpiling TS `import = require` to ESM.", ) .option( "--enable-legacy-typescript-module-interop", "Use default TypeScript ESM/CJS interop strategy.", ) .option("--enable-legacy-babel5-module-interop", "Use Babel 5 ESM/CJS interop strategy.") .parse(process.argv); if (_commander2.default.project) { if ( _commander2.default.outDir || _commander2.default.transforms || _commander2.default.args[0] || _commander2.default.enableLegacyTypescriptModuleInterop ) { console.error( "If TypeScript project is specified, out directory, transforms, source " + "directory, and --enable-legacy-typescript-module-interop may not be specified.", ); process.exit(1); } } else { if (!_commander2.default.outDir) { console.error("Out directory is required"); process.exit(1); } if (!_commander2.default.transforms) { console.error("Transforms option is required."); process.exit(1); } if (!_commander2.default.args[0]) { console.error("Source directory is required."); process.exit(1); } } const options = { outDirPath: _commander2.default.outDir, srcDirPath: _commander2.default.args[0], project: _commander2.default.project, outExtension: _commander2.default.outExtension, excludeDirs: _commander2.default.excludeDirs ? _commander2.default.excludeDirs.split(",") : [], quiet: _commander2.default.quiet, sucraseOptions: { transforms: _commander2.default.transforms ? _commander2.default.transforms.split(",") : [], disableESTransforms: _commander2.default.disableEsTransforms, jsxRuntime: _commander2.default.jsxRuntime, production: _commander2.default.production, jsxImportSource: _commander2.default.jsxImportSource, jsxPragma: _commander2.default.jsxPragma || "React.createElement", jsxFragmentPragma: _commander2.default.jsxFragmentPragma || "React.Fragment", keepUnusedImports: _commander2.default.keepUnusedImports, preserveDynamicImport: _commander2.default.preserveDynamicImport, injectCreateRequireForImportRequire: _commander2.default.injectCreateRequireForImportRequire, enableLegacyTypeScriptModuleInterop: _commander2.default.enableLegacyTypescriptModuleInterop, enableLegacyBabel5ModuleInterop: _commander2.default.enableLegacyBabel5ModuleInterop, }, }; buildDirectory(options).catch((e) => { process.exitCode = 1; console.error(e); }); } exports.default = run; async function findFiles(options) { const outDirPath = options.outDirPath; const srcDirPath = options.srcDirPath; const extensions = options.sucraseOptions.transforms.includes("typescript") ? [".ts", ".tsx"] : [".js", ".jsx"]; if (!(await _fs.exists.call(void 0, outDirPath))) { await _fs.mkdir.call(void 0, outDirPath); } const outArr = []; for (const child of await _fs.readdir.call(void 0, srcDirPath)) { if (["node_modules", ".git"].includes(child) || options.excludeDirs.includes(child)) { continue; } const srcChildPath = _path.join.call(void 0, srcDirPath, child); const outChildPath = _path.join.call(void 0, outDirPath, child); if ((await _fs.stat.call(void 0, srcChildPath)).isDirectory()) { const innerOptions = {...options}; innerOptions.srcDirPath = srcChildPath; innerOptions.outDirPath = outChildPath; const innerFiles = await findFiles(innerOptions); outArr.push(...innerFiles); } else if (extensions.some((ext) => srcChildPath.endsWith(ext))) { const outPath = outChildPath.replace(/\.\w+$/, `.${options.outExtension}`); outArr.push({ srcPath: srcChildPath, outPath, }); } } return outArr; } async function runGlob(options) { const tsConfigPath = _path.join.call(void 0, options.project, "tsconfig.json"); let str; try { str = await _fs.readFile.call(void 0, tsConfigPath, "utf8"); } catch (err) { console.error("Could not find project tsconfig.json"); console.error(` --project=${options.project}`); console.error(err); process.exit(1); } const json = JSON.parse(str); const foundFiles = []; const files = json.files; const include = json.include; const absProject = _path.join.call(void 0, process.cwd(), options.project); const outDirs = []; if (!(await _fs.exists.call(void 0, options.outDirPath))) { await _fs.mkdir.call(void 0, options.outDirPath); } if (files) { for (const file of files) { if (file.endsWith(".d.ts")) { continue; } if (!file.endsWith(".ts") && !file.endsWith(".js")) { continue; } const srcFile = _path.join.call(void 0, absProject, file); const outFile = _path.join.call(void 0, options.outDirPath, file); const outPath = outFile.replace(/\.\w+$/, `.${options.outExtension}`); const outDir = _path.dirname.call(void 0, outPath); if (!outDirs.includes(outDir)) { outDirs.push(outDir); } foundFiles.push({ srcPath: srcFile, outPath, }); } } if (include) { for (const pattern of include) { const globFiles = await _glob.glob.call(void 0, _path.join.call(void 0, absProject, pattern)); for (const file of globFiles) { if (!file.endsWith(".ts") && !file.endsWith(".js")) { continue; } if (file.endsWith(".d.ts")) { continue; } const relativeFile = _path.relative.call(void 0, absProject, file); const outFile = _path.join.call(void 0, options.outDirPath, relativeFile); const outPath = outFile.replace(/\.\w+$/, `.${options.outExtension}`); const outDir = _path.dirname.call(void 0, outPath); if (!outDirs.includes(outDir)) { outDirs.push(outDir); } foundFiles.push({ srcPath: file, outPath, }); } } } for (const outDirPath of outDirs) { if (!(await _fs.exists.call(void 0, outDirPath))) { await _fs.mkdir.call(void 0, outDirPath); } } // TODO: read exclude return foundFiles; } async function updateOptionsFromProject(options) { /** * Read the project information and assign the following. * - outDirPath * - transform: imports * - transform: typescript * - enableLegacyTypescriptModuleInterop: true/false. */ const tsConfigPath = _path.join.call(void 0, options.project, "tsconfig.json"); let str; try { str = await _fs.readFile.call(void 0, tsConfigPath, "utf8"); } catch (err) { console.error("Could not find project tsconfig.json"); console.error(` --project=${options.project}`); console.error(err); process.exit(1); } const json = JSON.parse(str); const sucraseOpts = options.sucraseOptions; if (!sucraseOpts.transforms.includes("typescript")) { sucraseOpts.transforms.push("typescript"); } const compilerOpts = json.compilerOptions; if (compilerOpts.outDir) { options.outDirPath = _path.join.call(void 0, process.cwd(), options.project, compilerOpts.outDir); } if (compilerOpts.esModuleInterop !== true) { sucraseOpts.enableLegacyTypeScriptModuleInterop = true; } if (compilerOpts.module === "commonjs") { if (!sucraseOpts.transforms.includes("imports")) { sucraseOpts.transforms.push("imports"); } } } async function buildDirectory(options) { let files; if (options.outDirPath && options.srcDirPath) { files = await findFiles(options); } else if (options.project) { await updateOptionsFromProject(options); files = await runGlob(options); } else { console.error("Project or Source directory required."); process.exit(1); } for (const file of files) { await buildFile(file.srcPath, file.outPath, options); } } async function buildFile(srcPath, outPath, options) { if (!options.quiet) { console.log(`${srcPath} -> ${outPath}`); } const code = (await _fs.readFile.call(void 0, srcPath)).toString(); const transformedCode = _index.transform.call(void 0, code, {...options.sucraseOptions, filePath: srcPath}).code; await _fs.writeFile.call(void 0, outPath, transformedCode); }