1 |
|
2 | import commander from "commander";
|
3 | import {exists, mkdir, readdir, readFile, stat, writeFile} from "mz/fs";
|
4 | import {join} from "path";
|
5 |
|
6 | import { transform} from "./index";
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 | export default function run() {
|
16 | commander
|
17 | .description(`Sucrase: super-fast Babel alternative.`)
|
18 | .usage("[options] <srcDir>")
|
19 | .option(
|
20 | "-d, --out-dir <out>",
|
21 | "Compile an input directory of modules into an output directory.",
|
22 | )
|
23 | .option("--out-extension <extension>", "File extension to use for all output files.", "js")
|
24 | .option("--exclude-dirs <paths>", "Names of directories that should not be traversed.")
|
25 | .option("-t, --transforms <transforms>", "Comma-separated list of transforms to run.")
|
26 | .option("-q, --quiet", "Don't print the names of converted files.")
|
27 | .option(
|
28 | "--enable-legacy-typescript-module-interop",
|
29 | "Use default TypeScript ESM/CJS interop strategy.",
|
30 | )
|
31 | .option("--enable-legacy-babel5-module-interop", "Use Babel 5 ESM/CJS interop strategy.")
|
32 | .option("--jsx-pragma <string>", "Element creation function, defaults to `React.createElement`")
|
33 | .option("--jsx-fragment-pragma <string>", "Fragment component, defaults to `React.Fragment`")
|
34 | .parse(process.argv);
|
35 |
|
36 | if (!commander.outDir) {
|
37 | console.error("Out directory is required");
|
38 | process.exit(1);
|
39 | }
|
40 |
|
41 | if (!commander.transforms) {
|
42 | console.error("Transforms option is required.");
|
43 | process.exit(1);
|
44 | }
|
45 |
|
46 | if (!commander.args[0]) {
|
47 | console.error("Source directory is required.");
|
48 | process.exit(1);
|
49 | }
|
50 |
|
51 | const outDir = commander.outDir;
|
52 | const srcDir = commander.args[0];
|
53 |
|
54 | const options = {
|
55 | outExtension: commander.outExtension,
|
56 | excludeDirs: commander.excludeDirs ? commander.excludeDirs.split(",") : [],
|
57 | quiet: commander.quiet,
|
58 | sucraseOptions: {
|
59 | transforms: commander.transforms.split(","),
|
60 | enableLegacyTypeScriptModuleInterop: commander.enableLegacyTypescriptModuleInterop,
|
61 | enableLegacyBabel5ModuleInterop: commander.enableLegacyBabel5ModuleInterop,
|
62 | jsxPragma: commander.jsxPragma || "React.createElement",
|
63 | jsxFragmentPragma: commander.jsxFragmentPragma || "React.Fragment",
|
64 | },
|
65 | };
|
66 |
|
67 | buildDirectory(srcDir, outDir, options).catch((e) => {
|
68 | process.exitCode = 1;
|
69 | console.error(e);
|
70 | });
|
71 | }
|
72 |
|
73 | async function buildDirectory(
|
74 | srcDirPath,
|
75 | outDirPath,
|
76 | options,
|
77 | ) {
|
78 | const extension = options.sucraseOptions.transforms.includes("typescript") ? ".ts" : ".js";
|
79 | if (!(await exists(outDirPath))) {
|
80 | await mkdir(outDirPath);
|
81 | }
|
82 | for (const child of await readdir(srcDirPath)) {
|
83 | if (["node_modules", ".git"].includes(child) || options.excludeDirs.includes(child)) {
|
84 | continue;
|
85 | }
|
86 | const srcChildPath = join(srcDirPath, child);
|
87 | const outChildPath = join(outDirPath, child);
|
88 | if ((await stat(srcChildPath)).isDirectory()) {
|
89 | await buildDirectory(srcChildPath, outChildPath, options);
|
90 | } else if (srcChildPath.endsWith(extension)) {
|
91 | const outPath = `${outChildPath.substr(0, outChildPath.length - extension.length)}.${
|
92 | options.outExtension
|
93 | }`;
|
94 | await buildFile(srcChildPath, outPath, options);
|
95 | }
|
96 | }
|
97 | }
|
98 |
|
99 | async function buildFile(srcPath, outPath, options) {
|
100 | if (!options.quiet) {
|
101 | console.log(`${srcPath} -> ${outPath}`);
|
102 | }
|
103 | const code = (await readFile(srcPath)).toString();
|
104 | const transformedCode = transform(code, {...options.sucraseOptions, filePath: srcPath}).code;
|
105 | await writeFile(outPath, transformedCode);
|
106 | }
|