From 43e00b5e8b4556ac5c50860505a8c292e58bd443 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Tue, 18 Apr 2017 16:33:41 +0200 Subject: [PATCH 1/7] Node API and CLI update Add yargs-parser Add key not exist case in options parser Remove deadcode Cleanup options parser Improve filtering input CLI options --- packages/babili/bin/babili.js | 2 +- packages/babili/package.json | 12 +-- packages/babili/src/cli.js | 125 ++++++++++++++++++++++++++ packages/babili/src/index.js | 39 +++++--- packages/babili/src/options-parser.js | 65 ++++++++++++++ 5 files changed, 224 insertions(+), 19 deletions(-) create mode 100644 packages/babili/src/cli.js create mode 100644 packages/babili/src/options-parser.js diff --git a/packages/babili/bin/babili.js b/packages/babili/bin/babili.js index 74638147f..b465f9fa3 100755 --- a/packages/babili/bin/babili.js +++ b/packages/babili/bin/babili.js @@ -1,3 +1,3 @@ #!/usr/bin/env node -require("../lib/index"); +require("../lib/cli"); diff --git a/packages/babili/package.json b/packages/babili/package.json index 3696697a0..5e85eca88 100644 --- a/packages/babili/package.json +++ b/packages/babili/package.json @@ -11,11 +11,11 @@ "bin": { "babili": "./bin/babili.js" }, - "keywords": [ - "babel-preset" - ], + "keywords": ["babel-preset"], "dependencies": { - "babel-cli": "^6.24.1", - "babel-preset-babili": "^0.1.4" - } + "babel-core": "^6.24.1", + "babel-preset-babili": "^0.0.12", + "yargs-parser": "^5.0.0" + }, + "devDependencies": {} } diff --git a/packages/babili/src/cli.js b/packages/babili/src/cli.js new file mode 100644 index 000000000..d6ecaef60 --- /dev/null +++ b/packages/babili/src/cli.js @@ -0,0 +1,125 @@ +const yargsParser = require("yargs-parser"); +// const babili = require("./index"); +const optionsParser = require("./options-parser"); + +const plugins = [ + "booleans", + "builtIns", + "consecutiveAdds", + "deadcode", + "evaluate", + "flipComparisons", + "guards", + "infinity", + "mangle", + "memberExpressions", + "mergeVars", + "numericLiterals", + "propertyLiterals", + "regexpConstructors", + "removeConsole", + "removeDebugger", + "removeUndefined", + "replace", + "simplify", + "simplifyComparisons", + "typeConstructors", + "undefinedToVoid" +]; + +const proxies = ["keepFnName", "keepClassName"]; + +const dceBooleanOpts = [ + "deadcode.keepFnName", + "deadcode.keepFnArgs", + "deadcode.keepClassName" +]; + +const mangleBooleanOpts = [ + "mangle.eval", + "mangle.keepFnName", + "mangle.topLevel", + "mangle.keepClassName" +]; + +const mangleArrayOpts = ["mangle.blacklist"]; + +const typeConsOpts = [ + "typeConstructors.array", + "typeConstructors.boolean", + "typeConstructors.number", + "typeConstructors.object", + "typeConstructors.string" +]; + +function validate(opts) { + const allOpts = [ + ...plugins, + ...proxies, + ...dceBooleanOpts, + ...mangleBooleanOpts, + ...typeConsOpts, + ...mangleArrayOpts + ]; + + return Object.keys(opts).filter( + opt => opt !== "_" && allOpts.indexOf(opt) === -1 + ); +} + +function run(args) { + const presetOpts = [...plugins, ...proxies]; + + const booleanOpts = [ + ...presetOpts, + ...dceBooleanOpts, + ...mangleBooleanOpts, + ...typeConsOpts + ]; + + const booleanDefaults = booleanOpts.reduce( + (acc, cur) => + Object.assign(acc, { + [cur]: void 0 + }), + {} + ); + + const arrayOpts = [...mangleArrayOpts]; + + const arrayDefaults = arrayOpts.reduce( + (acc, cur) => + Object.assign(acc, { + [cur]: [] + }), + {} + ); + + const argv = yargsParser(args, { + boolean: booleanOpts, + array: mangleArrayOpts, + default: Object.assign({}, arrayDefaults, booleanDefaults), + configuration: { + "dot-notation": false + } + }); + + const inputOpts = Object.keys(argv) + .filter(key => { + if (Array.isArray(argv[key])) { + return argv[key].length > 0; + } + return argv[key] !== void 0; + }) + .reduce((acc, cur) => Object.assign(acc, { [cur]: argv[cur] }), {}); + + const invalidOpts = validate(inputOpts); + + if (invalidOpts.length > 0) { + throw new Error("Invalid Options passed: " + invalidOpts.join(",")); + } + + console.log(optionsParser(inputOpts)); +} + +run(process.argv.slice(2)); diff --git a/packages/babili/src/index.js b/packages/babili/src/index.js index a7e030e5b..928fdbb71 100644 --- a/packages/babili/src/index.js +++ b/packages/babili/src/index.js @@ -1,15 +1,30 @@ -import child from "child_process"; +const babelCore = require("babel-core"); +const babelPresetBabili = require("babel-preset-babili"); -const args = [ - require.resolve("babel-cli/bin/babel.js"), - ...process.argv.slice(2), - `--presets=${require.resolve("babel-preset-babili")}`, - "--no-babelrc" -]; +module.exports = function babili( + input, + // Minify options passed to babiliPreset + // defaults are handled in preset + options = {}, + // overrides and other options + { + minified = true, + inputSourceMap = null, + sourceMaps = false, -const opts = { - stdio: "inherit", - env: process.env -}; + // to override the default babelCore used + babel = babelCore, -child.spawn(process.execPath, args, opts); + // to override the default babiliPreset used + babiliPreset = babelPresetBabili + } = {} +) { + return babel.transform({ + babelrc: false, + presets: [[babiliPreset, options]], + comments: false, + inputSourceMap, + sourceMaps, + minified + }); +}; diff --git a/packages/babili/src/options-parser.js b/packages/babili/src/options-parser.js new file mode 100644 index 000000000..df86c9d23 --- /dev/null +++ b/packages/babili/src/options-parser.js @@ -0,0 +1,65 @@ +"use strict"; + +const DELIMITTER = "."; + +module.exports = function parseOpts(argv) { + return dotsToObject(argv); +}; + +/** + * Converts and Object of the form - {key: value} to deep object + * following rules of babili preset options + * + * A preset option can be `true` | `object` which enables the particular plugin + * `false` disables the plugin + * + * @param input - An Object with dot-notation keys + */ +function dotsToObject(input) { + const dots = Object.keys(input).map(key => [ + ...key.split(DELIMITTER), + input[key] + ]); + + // sort to ensure dot notation occurs after parent key + dots.sort((a, b) => { + if (a.length === b.length) { + return a[0] > b[0]; + } + return a.length > b.length; + }); + + const obj = {}; + + for (const parts of dots) { + add(obj, ...parts); + } + + // make object + function add(o, first, ...rest) { + if (rest.length < 1) { + // something went wrong + throw new Error("Option Parse Error"); + } else if (rest.length === 1) { + // there is only a key and a value + // for example: mangle: true + o[first] = rest[0]; + } else { + // create the current path and recurse if the plugin is enabled + if (!hop(o, first) || o[first] === true) { + // if the plugin is enabled + o[first] = {}; + } + if (o[first] !== false) { + // if the plugin is NOT disabled then recurse + add(o[first], ...rest); + } + } + } + + return obj; +} + +function hop(o, key) { + return Object.prototype.hasOwnProperty.call(o, key); +} From 956ecb1d3e56eef03c75b06a94792d43f4db305b Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Mon, 24 Apr 2017 21:51:06 +0200 Subject: [PATCH 2/7] file handling in cli cli options and fs add out-file, out-dir and accept alias add small validation for cli set up cli tests and help option add help options and fix stdin fix test cases Add tests for cli file/dir and help option add eslintrc for tests ignore fixtures in test suite update package deps small changes for stdin --- package.json | 14 +-- packages/babili/__tests__/.eslintrc | 5 + .../__tests__/__snapshots__/cli-tests.js.snap | 7 ++ packages/babili/__tests__/cli-tests.js | 69 +++++++++++ .../__tests__/fixtures/out-dir/a/foo.js | 1 + .../babili/__tests__/fixtures/out-file/foo.js | 1 + packages/babili/package.json | 6 +- packages/babili/src/cli.js | 104 +++++++++++++++- packages/babili/src/fs.js | 114 ++++++++++++++++++ packages/babili/src/index.js | 2 +- yarn.lock | 8 -- 11 files changed, 307 insertions(+), 24 deletions(-) create mode 100644 packages/babili/__tests__/.eslintrc create mode 100644 packages/babili/__tests__/__snapshots__/cli-tests.js.snap create mode 100644 packages/babili/__tests__/cli-tests.js create mode 100644 packages/babili/__tests__/fixtures/out-dir/a/foo.js create mode 100644 packages/babili/__tests__/fixtures/out-file/foo.js create mode 100644 packages/babili/src/fs.js diff --git a/package.json b/package.json index cd0eaadca..b306c7589 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,8 @@ ".*": "/node_modules/babel-jest" }, "testEnvironment": "node", - "roots": [ - "packages" - ], - "transformIgnorePatterns": [ - "/node_modules/" - ], + "testPathIgnorePatterns": ["/node_modules/", "/fixtures/"], + "roots": ["packages"], "coverageDirectory": "./coverage/" }, "devDependencies": { @@ -51,6 +47,7 @@ "codecov": "^2.3.0", "commander": "^2.11.0", "eslint": "^4.4.0", + "fs-readdir-recursive": "^1.0.0", "google-closure-compiler-js": "^20170626.0.0", "gulp": "github:gulpjs/gulp#4.0", "gulp-babel": "^6.1.2", @@ -60,12 +57,11 @@ "lerna": "^2.0.0", "lerna-changelog": "^0.6.0", "markdown-table": "^1.1.1", + "output-file-sync": "^2.0.0", "prettier": "^1.5.3", "request": "^2.81.0", "through2": "^2.0.3", "uglify-js": "^3.0.27" }, - "workspaces": [ - "packages/*" - ] + "workspaces": ["packages/*"] } diff --git a/packages/babili/__tests__/.eslintrc b/packages/babili/__tests__/.eslintrc new file mode 100644 index 000000000..76e6cf969 --- /dev/null +++ b/packages/babili/__tests__/.eslintrc @@ -0,0 +1,5 @@ +{ + "rules": { + "no-unused-vars": "off" + } +} diff --git a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap new file mode 100644 index 000000000..fee1079f6 --- /dev/null +++ b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap @@ -0,0 +1,7 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Babili CLI should read from stdin and o/p to stdout 1`] = `"let a=10,b=20;"`; + +exports[`Babili CLI should throw if both out-file and out-dir is true 1`] = `"Cannot have out-file and out-dir"`; + +exports[`Babili CLI should throw on all invalid options 1`] = `"Invalid Options passed: foo,bar"`; diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js new file mode 100644 index 000000000..156996938 --- /dev/null +++ b/packages/babili/__tests__/cli-tests.js @@ -0,0 +1,69 @@ +jest.autoMockOff(); + +const { execFileSync } = require("child_process"); +const { join } = require("path"); +const fs = require("fs"); +const rimraf = require("rimraf"); +const babiliCli = require.resolve("../bin/babili"); + +function exec(stdin, ...opts) { + let options = { encoding: "utf-8" }; + if (stdin !== "") { + options = Object.assign(options, { + input: stdin + }); + } + return execFileSync(`${babiliCli}`, [].concat(opts), options); +} + +function testFile(input, output, ...opts) { + exec("", "--mangle.topLevel", input, ...opts); + expect(fs.readFileSync(output, "utf-8")).toEqual("let a=10;"); + rimraf.sync(output); // delete the file +} + +describe("Babili CLI", () => { + it("should show help for --help", () => { + expect(exec("", "--help")).toBeDefined(); + }); + + it("should show version for --vevrsion", () => { + const { version } = require("../package"); + expect(exec("", "--version")).toEqual(version); + }); + + it("should throw on all invalid options", () => { + expect(exec("", "--foo", "--bar")).toMatchSnapshot(); + }); + + it("should throw if both out-file and out-dir is true", () => { + expect(exec("", "--out-file", "--out-dir")).toMatchSnapshot(); + }); + + it("should read from stdin and o/p to stdout", () => { + let source = "let abcd = 10, bcdsa = 20"; + expect(exec(source, "--mangle.topLevel")).toMatchSnapshot(); + }); + + it("should handle input file and --out-file option", () => { + const inputPath = join(__dirname, "/fixtures/out-file/foo.js"); + // creates .min.js by default + const defaultPath = join(__dirname, "/fixtures/out-file/foo.min.js"); + testFile(inputPath, defaultPath); + // creates bar.js using --out-file option + const outFilePath = join(__dirname, "/fixtures/out-file/bar.js"); + testFile(inputPath, outFilePath, "--out-file", outFilePath); + }); + + it("should handle directory and --out-dir option", () => { + const inputPath = join(__dirname, "/fixtures/out-dir"); + //creates .min.js in the src directory by default + const outputPath = join(__dirname, "/fixtures/out-dir/a/foo.min.js"); + testFile(inputPath, outputPath); + // creates .min.js in --out-dir + const outDir = join(__dirname, "/fixtures/out-dir/bar"); + const checkFilePath = join(outDir, "/a/foo.min.js"); + testFile(inputPath, checkFilePath, "--out-dir", outDir); + rimraf.sync(outDir); + }); +}); diff --git a/packages/babili/__tests__/fixtures/out-dir/a/foo.js b/packages/babili/__tests__/fixtures/out-dir/a/foo.js new file mode 100644 index 000000000..1fda16226 --- /dev/null +++ b/packages/babili/__tests__/fixtures/out-dir/a/foo.js @@ -0,0 +1 @@ +let foo = 10; diff --git a/packages/babili/__tests__/fixtures/out-file/foo.js b/packages/babili/__tests__/fixtures/out-file/foo.js new file mode 100644 index 000000000..1fda16226 --- /dev/null +++ b/packages/babili/__tests__/fixtures/out-file/foo.js @@ -0,0 +1 @@ +let foo = 10; diff --git a/packages/babili/package.json b/packages/babili/package.json index 5e85eca88..eea3f97b9 100644 --- a/packages/babili/package.json +++ b/packages/babili/package.json @@ -15,7 +15,11 @@ "dependencies": { "babel-core": "^6.24.1", "babel-preset-babili": "^0.0.12", + "fs-readdir-recursive": "^1.0.0", + "output-file-sync": "^2.0.0", "yargs-parser": "^5.0.0" }, - "devDependencies": {} + "devDependencies": { + "rimraf": "^2.6.1" + } } diff --git a/packages/babili/src/cli.js b/packages/babili/src/cli.js index d6ecaef60..21c4fd739 100644 --- a/packages/babili/src/cli.js +++ b/packages/babili/src/cli.js @@ -1,6 +1,7 @@ const yargsParser = require("yargs-parser"); -// const babili = require("./index"); const optionsParser = require("./options-parser"); +const { version } = require("../package.json"); +const { processFiles } = require("./fs"); const plugins = [ "booleans", @@ -52,6 +53,65 @@ const typeConsOpts = [ "typeConstructors.string" ]; +const cliBooleanOpts = ["stdin", "help", "version"]; +const cliOpts = ["out-file", "out-dir"]; +const alias = { + outFile: "o", + outDir: "d", + version: "V" +}; + +function aliasArr(obj) { + const r = Object.keys(obj).reduce((acc, val) => { + return acc.concat(val, obj[val]); + }, []); + return r; +} + +function printHelpInfo() { + const msg = ` + Usage: babili index.js [options] + + Options: + --out-file, -o Output to a specific file + --out-dir, -d Output to a specific directory + --mangle Context and scope aware variable renaming + --simplify Simplifies code for minification by reducing statements into + expressions + --booleans Transform boolean literals into !0 for true and !1 for false + --builtIns Minify standard built-in objects + --consecutiveAdds Inlines consecutive property assignments, array pushes, etc. + --deadcode Inlines bindings and tries to evaluate expressions. + --evaluate Tries to evaluate expressions and inline the result. Deals + with numbers and strings + --flipComparisons Optimize code for repetition-based compression algorithms + such as gzip. + --infinity Minify Infinity to 1/0 + --memberExpressions Convert valid member expression property literals into plain + identifiers + --mergeVars Merge sibling variables into single variable declaration + --numericLiterals Shortening of numeric literals via scientific notation + --propertyLiterals Transform valid identifier property key literals into identifiers + --regexpConstructors Change RegExp constructors into literals + --removeConsole Removes all console.* calls + --removeDebugger Removes all debugger statements + --removeUndefined Removes rval's for variable assignments, return arguments from + functions that evaluate to undefined + --replace Replaces matching nodes in the tree with a given replacement node + --simplifyComparisons Convert === and !== to == and != if their types are inferred + to be the same + --typeConstructors Minify constructors to equivalent version + --undefinedToVoid Transforms undefined into void 0 + --version, -V Prints the current version number + `; + log(msg); +} + +function log(msg) { + process.stdout.write(msg + "\n"); + process.exit(0); +} + function validate(opts) { const allOpts = [ ...plugins, @@ -59,7 +119,10 @@ function validate(opts) { ...dceBooleanOpts, ...mangleBooleanOpts, ...typeConsOpts, - ...mangleArrayOpts + ...mangleArrayOpts, + ...cliBooleanOpts, + ...cliOpts, + ...aliasArr(alias) ]; return Object.keys(opts).filter( @@ -74,7 +137,8 @@ function run(args) { ...presetOpts, ...dceBooleanOpts, ...mangleBooleanOpts, - ...typeConsOpts + ...typeConsOpts, + ...cliBooleanOpts ]; const booleanDefaults = booleanOpts.reduce( @@ -99,11 +163,28 @@ function run(args) { boolean: booleanOpts, array: mangleArrayOpts, default: Object.assign({}, arrayDefaults, booleanDefaults), + alias, configuration: { "dot-notation": false } }); + const files = argv["_"]; + argv["stdin"] = argv["stdin"] || (!files.length && !process.stdin.isTTY); + const errors = []; + + if (argv.help) { + printHelpInfo(); + } + + if (argv.V) { + log(version); + } + + if (argv.outFile && argv.outDir) { + errors.push("Cannot have both out-file and out-dir"); + } + const inputOpts = Object.keys(argv) .filter(key => { if (Array.isArray(argv[key])) { @@ -116,10 +197,23 @@ function run(args) { const invalidOpts = validate(inputOpts); if (invalidOpts.length > 0) { - throw new Error("Invalid Options passed: " + invalidOpts.join(",")); + errors.push("Invalid Options passed: " + invalidOpts.join(",")); } - console.log(optionsParser(inputOpts)); + if (errors.length > 0) { + log(errors.join("\n")); + } + + const options = optionsParser(inputOpts); + + // delete unncessary options to babili preset + delete options["_"]; + delete options.d; + delete options["out-dir"]; + delete options.o; + delete options["out-file"]; + + processFiles(files, options); } run(process.argv.slice(2)); diff --git a/packages/babili/src/fs.js b/packages/babili/src/fs.js new file mode 100644 index 000000000..f3ba457b2 --- /dev/null +++ b/packages/babili/src/fs.js @@ -0,0 +1,114 @@ +const fs = require("fs"); +const path = require("path"); +const readdir = require("fs-readdir-recursive"); +const outputFileSync = require("output-file-sync"); +const babili = require("./"); +const EXTENSIONS = [".js", ".mjs"]; + +module.exports.processFiles = function(fileList, options) { + const { fileOpts, options: babiliOpts } = detachOptions(options); + const { stdin, outFile } = fileOpts; + if (stdin) { + readStdin().then(input => { + let { code } = babili(input, babiliOpts); + // write to stdout if ouput file is not specified + if (outFile === void 0) { + process.stdout.write(code + "\n"); + } else { + fs.writeFileSync(path.resolve(outFile), code, "utf-8"); + } + }); + } else { + for (let filename of fileList) { + handle(filename, fileOpts, babiliOpts); + } + } +}; + +function handle(filename, fileOpts, babiliOpts) { + if (!fs.existsSync(filename)) return; + + const { outFile } = fileOpts; + if (outFile !== undefined) { + transform(filename, outFile, babiliOpts); + return; + } + + const stat = fs.statSync(filename); + if (stat.isDirectory()) { + const dirname = filename; + readdir(dirname).forEach(filename => { + const src = path.join(dirname, filename); + handleFile(src, filename, fileOpts, babiliOpts); + }); + } else { + handleFile(filename, filename, fileOpts, babiliOpts); + } +} + +function handleFile(src, relative, fileOpts, babiliOpts) { + const ext = getValidFileExt(relative); + if (ext === undefined) { + return; + } + const { outDir } = fileOpts; + let dest; + const filename = getFileName(relative, ext); + if (outDir) { + dest = path.join(outDir, path.dirname(relative), filename); + } else { + dest = path.join(path.dirname(src), filename); + } + transform(src, dest, babiliOpts); +} + +function transform(src, dest, babiliOpts) { + const input = fs.readFileSync(src, "utf-8"); + const { code } = babili(input, babiliOpts); + outputFileSync(dest, code, "utf-8"); +} + +function detachOptions(options) { + const cliOpts = ["stdin", "outFile", "outDir"]; + const fileOpts = {}; + cliOpts.forEach(k => { + fileOpts[k] = options[k]; + delete options[k]; + }); + + return { fileOpts, options }; +} + +function readStdin() { + let code = ""; + const stdin = process.stdin; + + return new Promise(resolve => { + stdin.setEncoding("utf8"); + + stdin.on("readable", () => { + const chunk = process.stdin.read(); + if (chunk !== null) code += chunk; + }); + + stdin.on("end", () => { + resolve(code); + }); + }); +} + +function getValidFileExt(filename) { + const ext = path.extname(filename); + const isValidExt = EXTENSIONS.some(e => e.indexOf(ext) >= 0); + + if (isValidExt) { + return ext; + } + return ""; +} + +function getFileName(filePath, ext) { + let filename = path.basename(filePath, ext); + filename = filename.indexOf(".min") >= 0 ? filename : `${filename}.min`; + return `${filename}${ext}`; +} diff --git a/packages/babili/src/index.js b/packages/babili/src/index.js index 928fdbb71..d72f11226 100644 --- a/packages/babili/src/index.js +++ b/packages/babili/src/index.js @@ -19,7 +19,7 @@ module.exports = function babili( babiliPreset = babelPresetBabili } = {} ) { - return babel.transform({ + return babel.transform(input, { babelrc: false, presets: [[babiliPreset, options]], comments: false, diff --git a/yarn.lock b/yarn.lock index 3c6362e9c..8967fb9ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3758,14 +3758,6 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -output-file-sync@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" - dependencies: - graceful-fs "^4.1.4" - mkdirp "^0.5.1" - object-assign "^4.1.0" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" From 4e6b35ed9f6bbf3f80342ee60e3a3c882b093587 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Thu, 10 Aug 2017 00:08:41 +0200 Subject: [PATCH 3/7] Async fs Fix up Simplify Fix lint handle default case Fix some tests --- .babelrc | 13 +- .eslintrc.js | 2 +- package.json | 19 ++- packages/babili/__tests__/cli-tests.js | 2 +- packages/babili/package.json | 5 +- packages/babili/src/cli.js | 131 +++++++++------ packages/babili/src/fs.js | 190 +++++++++++++--------- yarn.lock | 216 +++++++++++++++++++------ 8 files changed, 384 insertions(+), 194 deletions(-) diff --git a/.babelrc b/.babelrc index 6e6df8faf..47125d57a 100644 --- a/.babelrc +++ b/.babelrc @@ -1,9 +1,14 @@ { "presets": [ - ["env", { - "targets": { - "node": 4 + [ + "env", + { + "targets": { + "node": 4 + }, + "include": ["transform-async-to-generator"], + "exclude": ["transform-regenerator"] } - }] + ] ] } diff --git a/.eslintrc.js b/.eslintrc.js index 71efe17ac..ba766ca76 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,7 +3,7 @@ const OFF = "off"; module.exports = { extends: "eslint:recommended", parserOptions: { - ecmaVersion: 7, + ecmaVersion: 2017, sourceType: "module" }, env: { diff --git a/package.json b/package.json index b306c7589..d17998b4c 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,13 @@ ".*": "/node_modules/babel-jest" }, "testEnvironment": "node", - "testPathIgnorePatterns": ["/node_modules/", "/fixtures/"], - "roots": ["packages"], + "testPathIgnorePatterns": [ + "/node_modules/", + "/fixtures/" + ], + "roots": [ + "packages" + ], "coverageDirectory": "./coverage/" }, "devDependencies": { @@ -57,11 +62,17 @@ "lerna": "^2.0.0", "lerna-changelog": "^0.6.0", "markdown-table": "^1.1.1", - "output-file-sync": "^2.0.0", "prettier": "^1.5.3", "request": "^2.81.0", + "rimraf": "^2.6.1", "through2": "^2.0.3", "uglify-js": "^3.0.27" }, - "workspaces": ["packages/*"] + "workspaces": [ + "packages/*" + ], + "dependencies": { + "mkdirp": "^0.5.1", + "util.promisify": "^1.0.0" + } } diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js index 156996938..f3ce995d2 100644 --- a/packages/babili/__tests__/cli-tests.js +++ b/packages/babili/__tests__/cli-tests.js @@ -29,7 +29,7 @@ describe("Babili CLI", () => { it("should show version for --vevrsion", () => { const { version } = require("../package"); - expect(exec("", "--version")).toEqual(version); + expect(exec("", "--version").trim()).toEqual(version); }); it("should throw on all invalid options", () => { diff --git a/packages/babili/package.json b/packages/babili/package.json index eea3f97b9..4e5014329 100644 --- a/packages/babili/package.json +++ b/packages/babili/package.json @@ -16,10 +16,9 @@ "babel-core": "^6.24.1", "babel-preset-babili": "^0.0.12", "fs-readdir-recursive": "^1.0.0", + "mkdirp": "^0.5.1", "output-file-sync": "^2.0.0", + "util.promisify": "^1.0.0", "yargs-parser": "^5.0.0" - }, - "devDependencies": { - "rimraf": "^2.6.1" } } diff --git a/packages/babili/src/cli.js b/packages/babili/src/cli.js index 21c4fd739..17c6422ea 100644 --- a/packages/babili/src/cli.js +++ b/packages/babili/src/cli.js @@ -1,7 +1,7 @@ const yargsParser = require("yargs-parser"); const optionsParser = require("./options-parser"); const { version } = require("../package.json"); -const { processFiles } = require("./fs"); +const { handleStdin, handleFile, handleArgs, isFile } = require("./fs"); const plugins = [ "booleans", @@ -53,7 +53,7 @@ const typeConsOpts = [ "typeConstructors.string" ]; -const cliBooleanOpts = ["stdin", "help", "version"]; +const cliBooleanOpts = ["help", "version"]; const cliOpts = ["out-file", "out-dir"]; const alias = { outFile: "o", @@ -68,7 +68,7 @@ function aliasArr(obj) { return r; } -function printHelpInfo() { +function printHelpInfo({ exitCode = 0 } = {}) { const msg = ` Usage: babili index.js [options] @@ -104,33 +104,20 @@ function printHelpInfo() { --undefinedToVoid Transforms undefined into void 0 --version, -V Prints the current version number `; - log(msg); + log(msg, exitCode); } -function log(msg) { +function log(msg, exitCode = 0) { process.stdout.write(msg + "\n"); - process.exit(0); + process.exit(exitCode); } -function validate(opts) { - const allOpts = [ - ...plugins, - ...proxies, - ...dceBooleanOpts, - ...mangleBooleanOpts, - ...typeConsOpts, - ...mangleArrayOpts, - ...cliBooleanOpts, - ...cliOpts, - ...aliasArr(alias) - ]; - - return Object.keys(opts).filter( - opt => opt !== "_" && allOpts.indexOf(opt) === -1 - ); +function error(err) { + process.stderr.write(err + "\n"); + process.exit(1); } -function run(args) { +function getArgv(args) { const presetOpts = [...plugins, ...proxies]; const booleanOpts = [ @@ -159,7 +146,7 @@ function run(args) { {} ); - const argv = yargsParser(args, { + return yargsParser(args, { boolean: booleanOpts, array: mangleArrayOpts, default: Object.assign({}, arrayDefaults, booleanDefaults), @@ -168,28 +155,12 @@ function run(args) { "dot-notation": false } }); +} - const files = argv["_"]; - argv["stdin"] = argv["stdin"] || (!files.length && !process.stdin.isTTY); - const errors = []; - - if (argv.help) { - printHelpInfo(); - } - - if (argv.V) { - log(version); - } - - if (argv.outFile && argv.outDir) { - errors.push("Cannot have both out-file and out-dir"); - } - +function getBabiliOpts(argv) { const inputOpts = Object.keys(argv) .filter(key => { - if (Array.isArray(argv[key])) { - return argv[key].length > 0; - } + if (Array.isArray(argv[key])) return argv[key].length > 0; return argv[key] !== void 0; }) .reduce((acc, cur) => Object.assign(acc, { [cur]: argv[cur] }), {}); @@ -197,11 +168,7 @@ function run(args) { const invalidOpts = validate(inputOpts); if (invalidOpts.length > 0) { - errors.push("Invalid Options passed: " + invalidOpts.join(",")); - } - - if (errors.length > 0) { - log(errors.join("\n")); + throw new Error("Invalid Options passed: " + invalidOpts.join(",")); } const options = optionsParser(inputOpts); @@ -213,7 +180,71 @@ function run(args) { delete options.o; delete options["out-file"]; - processFiles(files, options); + return options; +} + +function validate(opts) { + const allOpts = [ + ...plugins, + ...proxies, + ...dceBooleanOpts, + ...mangleBooleanOpts, + ...typeConsOpts, + ...mangleArrayOpts, + ...cliBooleanOpts, + ...cliOpts, + ...aliasArr(alias) + ]; + + return Object.keys(opts).filter( + opt => opt !== "_" && allOpts.indexOf(opt) === -1 + ); +} + +function runStdin(argv, options) { + if (argv._.length > 0) { + throw new Error("Reading input from STDIN. Cannot take file params"); + } + + return handleStdin(argv.outFile, options); +} + +function runFile(argv, options) { + const file = argv._[0]; + + // prefer outFile + if (argv.outFile) { + return handleFile(file, argv.outFile, options); + } else if (argv.outDir) { + return handleArgs([file], argv.outDir, options); + } else { + // prints to STDOUT + return handleFile(file, void 0, options); + } +} + +function runArgs(argv, options) { + return handleArgs(argv._, argv.outDir, options); +} + +async function run(args) { + const argv = getArgv(args); + + // early exits + if (argv.help) printHelpInfo(); + if (argv.V) log(version); + + const options = getBabiliOpts(argv); + + if (!process.stdin.isTTY) { + return runStdin(argv, options); + } else if (argv._.length <= 0) { + return printHelpInfo({ exitCode: 1 }); + } else if (argv._.length === 1 && (await isFile(argv._[0]))) { + return runFile(argv, options); + } else { + return runArgs(argv, options); + } } -run(process.argv.slice(2)); +run(process.argv.slice(2)).catch(e => error(e)); diff --git a/packages/babili/src/fs.js b/packages/babili/src/fs.js index f3ba457b2..b6c9a5593 100644 --- a/packages/babili/src/fs.js +++ b/packages/babili/src/fs.js @@ -1,114 +1,144 @@ const fs = require("fs"); const path = require("path"); const readdir = require("fs-readdir-recursive"); -const outputFileSync = require("output-file-sync"); +const promisify = require("util.promisify"); +const mkdirp = promisify(require("mkdirp")); + const babili = require("./"); const EXTENSIONS = [".js", ".mjs"]; -module.exports.processFiles = function(fileList, options) { - const { fileOpts, options: babiliOpts } = detachOptions(options); - const { stdin, outFile } = fileOpts; - if (stdin) { - readStdin().then(input => { - let { code } = babili(input, babiliOpts); - // write to stdout if ouput file is not specified - if (outFile === void 0) { - process.stdout.write(code + "\n"); - } else { - fs.writeFileSync(path.resolve(outFile), code, "utf-8"); - } - }); - } else { - for (let filename of fileList) { - handle(filename, fileOpts, babiliOpts); - } - } -}; +const readFileAsync = promisify(fs.readFile); +const writeFileAsync = promisify(fs.writeFile); +const lstat = promisify(fs.lstat); -function handle(filename, fileOpts, babiliOpts) { - if (!fs.existsSync(filename)) return; +// set defaults +const readFile = file => readFileAsync(file, { encoding: "utf-8" }); +const writeFile = (file, data) => + writeFileAsync(file, data, { encoding: "utf-8" }); - const { outFile } = fileOpts; - if (outFile !== undefined) { - transform(filename, outFile, babiliOpts); - return; - } - - const stat = fs.statSync(filename); - if (stat.isDirectory()) { - const dirname = filename; - readdir(dirname).forEach(filename => { - const src = path.join(dirname, filename); - handleFile(src, filename, fileOpts, babiliOpts); - }); - } else { - handleFile(filename, filename, fileOpts, babiliOpts); - } +function isJsFile(file) { + return EXTENSIONS.some(ext => path.basename(file, ext) !== file); } -function handleFile(src, relative, fileOpts, babiliOpts) { - const ext = getValidFileExt(relative); - if (ext === undefined) { - return; +async function isDir(p) { + try { + return (await lstat(p)).isDirectory(); + } catch (e) { + return false; } - const { outDir } = fileOpts; - let dest; - const filename = getFileName(relative, ext); - if (outDir) { - dest = path.join(outDir, path.dirname(relative), filename); - } else { - dest = path.join(path.dirname(src), filename); - } - transform(src, dest, babiliOpts); -} - -function transform(src, dest, babiliOpts) { - const input = fs.readFileSync(src, "utf-8"); - const { code } = babili(input, babiliOpts); - outputFileSync(dest, code, "utf-8"); } -function detachOptions(options) { - const cliOpts = ["stdin", "outFile", "outDir"]; - const fileOpts = {}; - cliOpts.forEach(k => { - fileOpts[k] = options[k]; - delete options[k]; - }); - - return { fileOpts, options }; +async function isFile(p) { + try { + return (await lstat(p)).isFile(); + } catch (e) { + return false; + } } -function readStdin() { +// the async keyword simply exists to denote we are returning a promise +// even though we don't use await inside it +async function readStdin() { let code = ""; const stdin = process.stdin; - return new Promise(resolve => { stdin.setEncoding("utf8"); - stdin.on("readable", () => { const chunk = process.stdin.read(); if (chunk !== null) code += chunk; }); - stdin.on("end", () => { resolve(code); }); }); } -function getValidFileExt(filename) { - const ext = path.extname(filename); - const isValidExt = EXTENSIONS.some(e => e.indexOf(ext) >= 0); +async function handleStdin(outputFilename, options) { + const { code } = babili(await readStdin(), options); + if (outputFilename) { + await writeFile(outputFilename, code); + } else { + process.stdout.write(code); + } +} - if (isValidExt) { - return ext; +async function handleFile(filename, outputFilename, options) { + const { code } = babili(await readFile(filename), options); + if (outputFilename) { + await writeFile(outputFilename, code); + } else { + process.stdout.write(code); } - return ""; } -function getFileName(filePath, ext) { - let filename = path.basename(filePath, ext); - filename = filename.indexOf(".min") >= 0 ? filename : `${filename}.min`; - return `${filename}${ext}`; +async function handleFiles(files, outputDir, options) { + if (!outputDir) { + throw new TypeError(`outputDir is falsy. Got "${outputDir}"`); + } + + return Promise.all( + files.map(file => { + const outputFilename = path.join(outputDir, path.basename(file)); + return mkdirp(path.dirname(outputFilename)).then(() => + handleFile(file, outputFilename, options) + ); + }) + ); +} + +async function handleDir(dir, outputDir, options) { + if (!outputDir) { + throw new TypeError(`outputDir is falsy`); + } + + // relative paths + const files = readdir(dir); + + return Promise.all( + files.filter(file => isJsFile(file)).map(file => { + const outputFilename = path.join(outputDir, file); + const inputFilename = path.join(dir, file); + + return mkdirp(path.dirname(outputFilename)).then(() => + handleFile(inputFilename, outputFilename, options) + ); + }) + ); } + +async function handleArgs(args, outputDir, options) { + const files = []; + const dirs = []; + + if (!Array.isArray(args)) { + throw new TypeError(`Expected Array. Got ${JSON.stringify(args)}`); + } + + for (const arg of args) { + if (await isFile(arg)) { + files.push(arg); + } else if (await isDir(arg)) { + dirs.push(arg); + } else { + throw new TypeError(`Input "${arg}" is neither a file nor a directory.`); + } + } + + return Promise.all([ + handleFiles(files, outputDir, options), + ...dirs.map(dir => handleDir(dir, outputDir, options)) + ]); +} + +module.exports = { + handleFile, + handleStdin, + handleFiles, + handleDir, + handleArgs, + isFile, + isDir, + isJsFile, + readFile, + writeFile +}; diff --git a/yarn.lock b/yarn.lock index 8967fb9ec..605430cd3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -271,27 +271,6 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-cli@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.24.1.tgz#207cd705bba61489b2ea41b5312341cf6aca2283" - dependencies: - babel-core "^6.24.1" - babel-polyfill "^6.23.0" - babel-register "^6.24.1" - babel-runtime "^6.22.0" - commander "^2.8.1" - convert-source-map "^1.1.0" - fs-readdir-recursive "^1.0.0" - glob "^7.0.0" - lodash "^4.2.0" - output-file-sync "^1.1.0" - path-is-absolute "^1.0.0" - slash "^1.0.0" - source-map "^0.5.0" - v8flags "^2.0.10" - optionalDependencies: - chokidar "^1.6.1" - babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" @@ -372,6 +351,10 @@ babel-helper-define-map@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" +babel-helper-evaluate-path@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.0.3.tgz#1d103ac9d4a59e5d431842212f151785f7ac547b" + babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" @@ -380,6 +363,10 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" +babel-helper-flip-expressions@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" + babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -408,6 +395,14 @@ babel-helper-is-nodes-equiv@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" +babel-helper-is-void-0@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.0.1.tgz#ed74553b883e68226ae45f989a99b02c190f105a" + +babel-helper-mark-eval-scopes@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz#902f75aeb537336edc35eb9f52b6f09db7785328" + babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" @@ -444,6 +439,10 @@ babel-helper-replace-supers@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" +babel-helper-to-multiple-sequence-expressions@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.0.4.tgz#d94414b386b6286fbaad77f073dea9b34324b01c" + babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" @@ -483,6 +482,63 @@ babel-plugin-jest-hoist@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767" +babel-plugin-minify-builtins@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" + dependencies: + babel-helper-evaluate-path "^0.0.3" + +babel-plugin-minify-constant-folding@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.0.4.tgz#b6e231026a6035e88ceadd206128d7db2b5c15e6" + dependencies: + babel-helper-evaluate-path "^0.0.3" + jsesc "^2.4.0" + +babel-plugin-minify-flip-comparisons@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.0.2.tgz#7d0953aa5876ede6118966bda9edecc63bf346ab" + dependencies: + babel-helper-is-void-0 "^0.0.1" + +babel-plugin-minify-guarded-expressions@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.0.4.tgz#957104a760e6a7ffd967005a7a11621bb42fd11c" + dependencies: + babel-helper-flip-expressions "^0.0.2" + +babel-plugin-minify-infinity@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.0.3.tgz#4cc99b61d12b434ce80ad675103335c589cba9a1" + +babel-plugin-minify-mangle-names@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.0.8.tgz#1e2fea856dd742d5697aa26b427e41258a8c5b79" + dependencies: + babel-helper-mark-eval-scopes "^0.0.3" + +babel-plugin-minify-numeric-literals@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.0.1.tgz#9597e6c31154d7daf3744d0bd417c144b275bd53" + +babel-plugin-minify-replace@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.0.1.tgz#5d5aea7cb9899245248d1ee9ce7a2fe556a8facc" + +babel-plugin-minify-simplify@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.0.8.tgz#597b23327bba4373fed1c51461a689bce9ff4979" + dependencies: + babel-helper-flip-expressions "^0.0.2" + babel-helper-is-nodes-equiv "^0.0.1" + babel-helper-to-multiple-sequence-expressions "^0.0.4" + +babel-plugin-minify-type-constructors@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.0.4.tgz#52d8b623775107523227719ade2d0b7458758b5f" + dependencies: + babel-helper-is-void-0 "^0.0.1" + babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -679,12 +735,24 @@ babel-plugin-transform-exponentiation-operator@^6.22.0: babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" +babel-plugin-transform-inline-consecutive-adds@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" + babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" dependencies: regenerator-transform "0.9.11" +babel-plugin-transform-regexp-constructors@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.0.6.tgz#0d92607f0d26268296980cb7c1dea5f2dd3e1e20" + +babel-plugin-transform-remove-undefined@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.0.5.tgz#12ef11805e06e861dd2eb0c7cc041d2184b8f410" + babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" @@ -692,13 +760,33 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-polyfill@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" +babel-preset-babili@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/babel-preset-babili/-/babel-preset-babili-0.0.12.tgz#74d79205d54feae6470bc84231da0b9ac9fc7de9" + dependencies: + babel-plugin-minify-builtins "^0.0.2" + babel-plugin-minify-constant-folding "^0.0.4" + babel-plugin-minify-dead-code-elimination "^0.1.4" + babel-plugin-minify-flip-comparisons "^0.0.2" + babel-plugin-minify-guarded-expressions "^0.0.4" + babel-plugin-minify-infinity "^0.0.3" + babel-plugin-minify-mangle-names "^0.0.8" + babel-plugin-minify-numeric-literals "^0.0.1" + babel-plugin-minify-replace "^0.0.1" + babel-plugin-minify-simplify "^0.0.8" + babel-plugin-minify-type-constructors "^0.0.4" + babel-plugin-transform-inline-consecutive-adds "^0.0.2" + babel-plugin-transform-member-expression-literals "^6.8.1" + babel-plugin-transform-merge-sibling-variables "^6.8.2" + babel-plugin-transform-minify-booleans "^6.8.0" + babel-plugin-transform-property-literals "^6.8.1" + babel-plugin-transform-regexp-constructors "^0.0.6" + babel-plugin-transform-remove-console "^6.8.1" + babel-plugin-transform-remove-debugger "^6.8.1" + babel-plugin-transform-remove-undefined "^0.0.5" + babel-plugin-transform-simplify-comparison-operators "^6.8.1" + babel-plugin-transform-undefined-to-void "^6.8.0" + lodash.isplainobject "^4.0.6" babel-preset-env@^1.6.0: version "1.6.0" @@ -892,10 +980,10 @@ browser-resolve@^1.11.2: resolve "1.1.7" browserslist@^2.1.2: - version "2.3.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.3.0.tgz#b2aa76415c71643fe2368f6243b43bbbb4211752" + version "2.3.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.3.1.tgz#39500a2090330b2a090120ea6c7fc78b6e091c5e" dependencies: - caniuse-lite "^1.0.30000710" + caniuse-lite "^1.0.30000712" electron-to-chromium "^1.3.17" bser@1.0.2: @@ -969,9 +1057,9 @@ camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" -caniuse-lite@^1.0.30000710: - version "1.0.30000710" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000710.tgz#1c249bf7c6a61161c9b10906e3ad9fa5b6761af1" +caniuse-lite@^1.0.30000712: + version "1.0.30000713" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000713.tgz#33957ecb4a2154a5d40a60d13d8bf1cfa0881a8a" caseless@~0.12.0: version "0.12.0" @@ -995,14 +1083,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: supports-color "^2.0.0" chalk@^2.0.0, chalk@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" dependencies: ansi-styles "^3.1.0" escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chokidar@^1.4.3, chokidar@^1.6.1: +chokidar@^1.4.3: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" dependencies: @@ -1153,7 +1241,7 @@ command-join@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/command-join/-/command-join-2.0.0.tgz#52e8b984f4872d952ff1bdc8b98397d27c7144cf" -commander@^2.11.0, commander@^2.8.1, commander@~2.11.0: +commander@^2.11.0, commander@~2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -1355,8 +1443,8 @@ copy-props@^1.4.1: is-plain-object "^2.0.1" core-js@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + version "2.5.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086" core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -1579,7 +1667,7 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.4.3: +es-abstract@^1.4.3, es-abstract@^1.5.1: version "1.8.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.8.0.tgz#3b00385e85729932beffa9163bbea1234e932914" dependencies: @@ -1651,8 +1739,8 @@ eslint-scope@^3.7.1: estraverse "^4.1.1" eslint@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.0.tgz#a3e153e704b64f78290ef03592494eaba228d3bc" + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.1.tgz#99cd7eafcffca2ff99a5c8f5f2a474d6364b4bd3" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" @@ -2151,7 +2239,7 @@ glob@^5.0.3, glob@~5.0.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2221,7 +2309,7 @@ google-closure-compiler@20150901.x: version "20150901.0.0" resolved "https://registry.yarnpkg.com/google-closure-compiler/-/google-closure-compiler-20150901.0.0.tgz#3d01c6cade65790a9bfb4e30b2158b7635acbade" -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2611,7 +2699,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.0.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -3001,8 +3089,8 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" jschardet@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" + version "1.5.1" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.1.tgz#c519f629f86b3a5bedba58a88d311309eec097f9" jsdom@^9.12.0: version "9.12.0" @@ -3032,6 +3120,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.4.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -3559,8 +3651,8 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" node-fetch@^1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5" + version "1.7.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.2.tgz#c54e9aac57e432875233525f3c891c4159ffefd7" dependencies: encoding "^0.1.11" is-stream "^1.0.1" @@ -3672,6 +3764,13 @@ object.defaults@^1.0.0, object.defaults@^1.1.0: for-own "^1.0.0" isobject "^3.0.0" +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + object.omit@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" @@ -3758,6 +3857,14 @@ osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +output-file-sync@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-2.0.0.tgz#5d348a1a1eaed1ad168648a01a2d6d13078ce987" + dependencies: + graceful-fs "^4.1.11" + is-plain-obj "^1.1.0" + mkdirp "^0.5.1" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -4764,6 +4871,13 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" +util.promisify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + uuid@^2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" @@ -4772,7 +4886,7 @@ uuid@^3.0.0, uuid@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" -v8flags@^2.0.10, v8flags@^2.0.9: +v8flags@^2.0.9: version "2.1.1" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" dependencies: From ac6cd4920280bcf0e3f9ac1458ca0968bce97931 Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Thu, 10 Aug 2017 23:25:32 +0200 Subject: [PATCH 4/7] move to spawnSync from exec to capture stderr, stdout --- .../__tests__/__snapshots__/cli-tests.js.snap | 7 ++-- packages/babili/__tests__/cli-tests.js | 38 +++++++------------ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap index fee1079f6..86439ade6 100644 --- a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap +++ b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap @@ -2,6 +2,7 @@ exports[`Babili CLI should read from stdin and o/p to stdout 1`] = `"let a=10,b=20;"`; -exports[`Babili CLI should throw if both out-file and out-dir is true 1`] = `"Cannot have out-file and out-dir"`; - -exports[`Babili CLI should throw on all invalid options 1`] = `"Invalid Options passed: foo,bar"`; +exports[`Babili CLI should throw on all invalid options 1`] = ` +"Error: Invalid Options passed: foo,bar +" +`; diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js index f3ce995d2..583283ca8 100644 --- a/packages/babili/__tests__/cli-tests.js +++ b/packages/babili/__tests__/cli-tests.js @@ -1,61 +1,51 @@ jest.autoMockOff(); -const { execFileSync } = require("child_process"); +const { spawnSync } = require("child_process"); const { join } = require("path"); const fs = require("fs"); const rimraf = require("rimraf"); -const babiliCli = require.resolve("../bin/babili"); +const babili = require.resolve("../bin/babili"); -function exec(stdin, ...opts) { +function spawn(stdin, ...opts) { let options = { encoding: "utf-8" }; if (stdin !== "") { - options = Object.assign(options, { - input: stdin - }); + options = Object.assign(options, { input: stdin }); } - return execFileSync(`${babiliCli}`, [].concat(opts), options); + return spawnSync(`${babili}`, [].concat(opts), options); } function testFile(input, output, ...opts) { - exec("", "--mangle.topLevel", input, ...opts); + spawn("", "--mangle.topLevel", input, ...opts); expect(fs.readFileSync(output, "utf-8")).toEqual("let a=10;"); rimraf.sync(output); // delete the file } describe("Babili CLI", () => { it("should show help for --help", () => { - expect(exec("", "--help")).toBeDefined(); + expect(spawn("", "--help")).toBeDefined(); }); - it("should show version for --vevrsion", () => { + it("should show version for --version", () => { const { version } = require("../package"); - expect(exec("", "--version").trim()).toEqual(version); + expect(spawn("", "--version").stdout.trim()).toEqual(version); }); it("should throw on all invalid options", () => { - expect(exec("", "--foo", "--bar")).toMatchSnapshot(); - }); - - it("should throw if both out-file and out-dir is true", () => { - expect(exec("", "--out-file", "--out-dir")).toMatchSnapshot(); + expect(spawn("", "--foo", "--bar").stderr).toMatchSnapshot(); }); it("should read from stdin and o/p to stdout", () => { - let source = "let abcd = 10, bcdsa = 20"; - expect(exec(source, "--mangle.topLevel")).toMatchSnapshot(); + const source = "let abcd = 10, bcdsa = 20"; + expect(spawn(source, "--mangle.topLevel").stdout).toMatchSnapshot(); }); - it("should handle input file and --out-file option", () => { + xit("should handle input file and --out-file option", () => { const inputPath = join(__dirname, "/fixtures/out-file/foo.js"); - // creates .min.js by default - const defaultPath = join(__dirname, "/fixtures/out-file/foo.min.js"); - testFile(inputPath, defaultPath); - // creates bar.js using --out-file option const outFilePath = join(__dirname, "/fixtures/out-file/bar.js"); testFile(inputPath, outFilePath, "--out-file", outFilePath); }); - it("should handle directory and --out-dir option", () => { + xit("should handle directory and --out-dir option", () => { const inputPath = join(__dirname, "/fixtures/out-dir"); //creates .min.js in the src directory by default const outputPath = join(__dirname, "/fixtures/out-dir/a/foo.min.js"); From b15834813d83b059bdaf7d3d890b6f4ee25d51f2 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Fri, 11 Aug 2017 12:20:19 +0200 Subject: [PATCH 5/7] Move tests to async Format jest snapshots Fix yarn deps --- packages/babili/__tests__/.eslintrc | 5 - .../__tests__/__snapshots__/cli-tests.js.snap | 29 ++++- packages/babili/__tests__/cli-tests.js | 118 ++++++++++++----- packages/babili/__tests__/fixtures/.eslintrc | 6 + .../babili/__tests__/fixtures/out-file/foo.js | 6 +- packages/babili/package.json | 2 +- yarn.lock | 121 ------------------ 7 files changed, 122 insertions(+), 165 deletions(-) delete mode 100644 packages/babili/__tests__/.eslintrc create mode 100644 packages/babili/__tests__/fixtures/.eslintrc diff --git a/packages/babili/__tests__/.eslintrc b/packages/babili/__tests__/.eslintrc deleted file mode 100644 index 76e6cf969..000000000 --- a/packages/babili/__tests__/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "no-unused-vars": "off" - } -} diff --git a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap index 86439ade6..a35a04bc4 100644 --- a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap +++ b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap @@ -1,8 +1,31 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Babili CLI should read from stdin and o/p to stdout 1`] = `"let a=10,b=20;"`; +exports[`Babili CLI input dir + outdir 1`] = `"let foo=10;"`; + +exports[`Babili CLI input file + outDir 1`] = `"function foo(){const a=x(1),b=y(2);return z(a,b)}"`; + +exports[`Babili CLI input file + outFile 1`] = `"function foo(){const a=x(1),b=y(2);return z(a,b)}"`; + +exports[`Babili CLI input file + stdout 1`] = ` +Object { + "stderr": "", + "stdout": "function foo(){const a=x(1),b=y(2);return z(a,b)}", +} +`; exports[`Babili CLI should throw on all invalid options 1`] = ` -"Error: Invalid Options passed: foo,bar -" +Object { + "code": 1, + "stderr": "Error: Invalid Options passed: foo,bar +", +} +`; + +exports[`Babili CLI stdin + outFile 1`] = `"function foo(){const a=x(1),b=y(2);return z(a,b)}"`; + +exports[`Babili CLI stdin + stdout 1`] = ` +Object { + "stderr": "", + "stdout": "function a(){const b=x(1),c=y(2);return z(b,c)}", +} `; diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js index 583283ca8..15e561227 100644 --- a/packages/babili/__tests__/cli-tests.js +++ b/packages/babili/__tests__/cli-tests.js @@ -1,59 +1,109 @@ jest.autoMockOff(); -const { spawnSync } = require("child_process"); -const { join } = require("path"); +const { spawn } = require("child_process"); +const path = require("path"); +const { Readable } = require("stream"); const fs = require("fs"); +const promisify = require("util.promisify"); const rimraf = require("rimraf"); -const babili = require.resolve("../bin/babili"); - -function spawn(stdin, ...opts) { - let options = { encoding: "utf-8" }; - if (stdin !== "") { - options = Object.assign(options, { input: stdin }); - } - return spawnSync(`${babili}`, [].concat(opts), options); +const babiliCli = require.resolve("../bin/babili"); + +const readFileAsync = promisify(fs.readFile); +const readFile = file => readFileAsync(file).then(out => out.toString()); +const unlink = promisify(rimraf); + +function runCli(args = [], stdin) { + return new Promise((resolve, reject) => { + const child = spawn(babiliCli, args, { + stdio: [stdin ? "pipe" : "inherit", "pipe", "pipe"], + shell: true + }); + + if (stdin) { + const s = new Readable(); + s.push(stdin); + s.push(null); + + child.stdin.isTTY = true; + s.pipe(child.stdin); + } + + let stdout = ""; + let stderr = ""; + + child.stdout.on("data", data => (stdout += data)); + child.stderr.on("data", data => (stderr += data)); + child.on( + "close", + code => + code === 0 ? resolve({ stdout, stderr }) : reject({ code, stderr }) + ); + }); } -function testFile(input, output, ...opts) { - spawn("", "--mangle.topLevel", input, ...opts); - expect(fs.readFileSync(output, "utf-8")).toEqual("let a=10;"); - rimraf.sync(output); // delete the file +let tempSource = ` +function foo() { + const bar = x(1); + const baz = y(2); + return z(bar, baz); } +`; + +const sampleInputFile = path.join(__dirname, "fixtures/out-file/foo.js"); +const sampleInputDir = path.join(__dirname, "fixtures/out-dir/a"); + +const tempOutFile = path.join(__dirname, "fixtures/out-file/foo.min.js"); +const tempOutDir = path.join(__dirname, "fixtures/out-dir/min"); +const tempOutDirFile = path.join(__dirname, "fixtures/out-dir/min/foo.js"); describe("Babili CLI", () => { + afterEach(async () => { + await unlink(tempOutDir); + await unlink(tempOutFile); + }); + it("should show help for --help", () => { - expect(spawn("", "--help")).toBeDefined(); + return expect(runCli(["--help"])).resolves.toBeDefined(); }); it("should show version for --version", () => { const { version } = require("../package"); - expect(spawn("", "--version").stdout.trim()).toEqual(version); + return expect( + runCli(["--version"]).then(({ stdout }) => stdout.trim()) + ).resolves.toBe(version); }); it("should throw on all invalid options", () => { - expect(spawn("", "--foo", "--bar").stderr).toMatchSnapshot(); + return expect(runCli(["--foo", "--bar"])).rejects.toMatchSnapshot(); + }); + + it("stdin + stdout", () => { + return expect( + runCli(["--mangle.topLevel"], tempSource) + ).resolves.toMatchSnapshot(); + }); + + it("stdin + outFile", async () => { + await runCli(["--out-file", tempOutFile], tempSource); + expect(await readFile(tempOutFile)).toMatchSnapshot(); + }); + + it("input file + stdout", async () => { + return expect(runCli([sampleInputFile])).resolves.toMatchSnapshot(); }); - it("should read from stdin and o/p to stdout", () => { - const source = "let abcd = 10, bcdsa = 20"; - expect(spawn(source, "--mangle.topLevel").stdout).toMatchSnapshot(); + it("input file + outFile", async () => { + await runCli([sampleInputFile, "--out-file", tempOutFile]); + expect(await readFile(tempOutFile)).toMatchSnapshot(); }); - xit("should handle input file and --out-file option", () => { - const inputPath = join(__dirname, "/fixtures/out-file/foo.js"); - const outFilePath = join(__dirname, "/fixtures/out-file/bar.js"); - testFile(inputPath, outFilePath, "--out-file", outFilePath); + it("input file + outDir", async () => { + await runCli([sampleInputFile, "--out-dir", tempOutDir]); + expect(await readFile(tempOutDirFile)).toMatchSnapshot(); }); - xit("should handle directory and --out-dir option", () => { - const inputPath = join(__dirname, "/fixtures/out-dir"); - //creates .min.js in the src directory by default - const outputPath = join(__dirname, "/fixtures/out-dir/a/foo.min.js"); - testFile(inputPath, outputPath); - // creates .min.js in --out-dir - const outDir = join(__dirname, "/fixtures/out-dir/bar"); - const checkFilePath = join(outDir, "/a/foo.min.js"); - testFile(inputPath, checkFilePath, "--out-dir", outDir); - rimraf.sync(outDir); + it("input dir + outdir", async () => { + await runCli([sampleInputDir, "--out-dir", tempOutDir]); + expect(await readFile(tempOutDirFile)).toMatchSnapshot(); }); }); diff --git a/packages/babili/__tests__/fixtures/.eslintrc b/packages/babili/__tests__/fixtures/.eslintrc new file mode 100644 index 000000000..35aae7b37 --- /dev/null +++ b/packages/babili/__tests__/fixtures/.eslintrc @@ -0,0 +1,6 @@ +{ + "rules": { + "no-unused-vars": "off", + "no-undef": "off" + } +} diff --git a/packages/babili/__tests__/fixtures/out-file/foo.js b/packages/babili/__tests__/fixtures/out-file/foo.js index 1fda16226..8232e690b 100644 --- a/packages/babili/__tests__/fixtures/out-file/foo.js +++ b/packages/babili/__tests__/fixtures/out-file/foo.js @@ -1 +1,5 @@ -let foo = 10; +function foo() { + const bar = x(1); + const baz = y(2); + return z(bar, baz); +} diff --git a/packages/babili/package.json b/packages/babili/package.json index 4e5014329..ba45b4c73 100644 --- a/packages/babili/package.json +++ b/packages/babili/package.json @@ -14,7 +14,7 @@ "keywords": ["babel-preset"], "dependencies": { "babel-core": "^6.24.1", - "babel-preset-babili": "^0.0.12", + "babel-preset-babili": "^0.1.4", "fs-readdir-recursive": "^1.0.0", "mkdirp": "^0.5.1", "output-file-sync": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index 605430cd3..7fb2cf1bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -351,10 +351,6 @@ babel-helper-define-map@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" -babel-helper-evaluate-path@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.0.3.tgz#1d103ac9d4a59e5d431842212f151785f7ac547b" - babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" @@ -363,10 +359,6 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helper-flip-expressions@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" - babel-helper-function-name@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" @@ -395,14 +387,6 @@ babel-helper-is-nodes-equiv@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" -babel-helper-is-void-0@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.0.1.tgz#ed74553b883e68226ae45f989a99b02c190f105a" - -babel-helper-mark-eval-scopes@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz#902f75aeb537336edc35eb9f52b6f09db7785328" - babel-helper-optimise-call-expression@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" @@ -439,10 +423,6 @@ babel-helper-replace-supers@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helper-to-multiple-sequence-expressions@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.0.4.tgz#d94414b386b6286fbaad77f073dea9b34324b01c" - babel-helpers@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" @@ -482,63 +462,6 @@ babel-plugin-jest-hoist@^20.0.3: version "20.0.3" resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-20.0.3.tgz#afedc853bd3f8dc3548ea671fbe69d03cc2c1767" -babel-plugin-minify-builtins@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" - dependencies: - babel-helper-evaluate-path "^0.0.3" - -babel-plugin-minify-constant-folding@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.0.4.tgz#b6e231026a6035e88ceadd206128d7db2b5c15e6" - dependencies: - babel-helper-evaluate-path "^0.0.3" - jsesc "^2.4.0" - -babel-plugin-minify-flip-comparisons@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.0.2.tgz#7d0953aa5876ede6118966bda9edecc63bf346ab" - dependencies: - babel-helper-is-void-0 "^0.0.1" - -babel-plugin-minify-guarded-expressions@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.0.4.tgz#957104a760e6a7ffd967005a7a11621bb42fd11c" - dependencies: - babel-helper-flip-expressions "^0.0.2" - -babel-plugin-minify-infinity@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.0.3.tgz#4cc99b61d12b434ce80ad675103335c589cba9a1" - -babel-plugin-minify-mangle-names@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.0.8.tgz#1e2fea856dd742d5697aa26b427e41258a8c5b79" - dependencies: - babel-helper-mark-eval-scopes "^0.0.3" - -babel-plugin-minify-numeric-literals@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.0.1.tgz#9597e6c31154d7daf3744d0bd417c144b275bd53" - -babel-plugin-minify-replace@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.0.1.tgz#5d5aea7cb9899245248d1ee9ce7a2fe556a8facc" - -babel-plugin-minify-simplify@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.0.8.tgz#597b23327bba4373fed1c51461a689bce9ff4979" - dependencies: - babel-helper-flip-expressions "^0.0.2" - babel-helper-is-nodes-equiv "^0.0.1" - babel-helper-to-multiple-sequence-expressions "^0.0.4" - -babel-plugin-minify-type-constructors@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.0.4.tgz#52d8b623775107523227719ade2d0b7458758b5f" - dependencies: - babel-helper-is-void-0 "^0.0.1" - babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -735,24 +658,12 @@ babel-plugin-transform-exponentiation-operator@^6.22.0: babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-inline-consecutive-adds@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" - babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" dependencies: regenerator-transform "0.9.11" -babel-plugin-transform-regexp-constructors@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.0.6.tgz#0d92607f0d26268296980cb7c1dea5f2dd3e1e20" - -babel-plugin-transform-remove-undefined@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.0.5.tgz#12ef11805e06e861dd2eb0c7cc041d2184b8f410" - babel-plugin-transform-strict-mode@^6.24.1: version "6.24.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" @@ -760,34 +671,6 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-preset-babili@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/babel-preset-babili/-/babel-preset-babili-0.0.12.tgz#74d79205d54feae6470bc84231da0b9ac9fc7de9" - dependencies: - babel-plugin-minify-builtins "^0.0.2" - babel-plugin-minify-constant-folding "^0.0.4" - babel-plugin-minify-dead-code-elimination "^0.1.4" - babel-plugin-minify-flip-comparisons "^0.0.2" - babel-plugin-minify-guarded-expressions "^0.0.4" - babel-plugin-minify-infinity "^0.0.3" - babel-plugin-minify-mangle-names "^0.0.8" - babel-plugin-minify-numeric-literals "^0.0.1" - babel-plugin-minify-replace "^0.0.1" - babel-plugin-minify-simplify "^0.0.8" - babel-plugin-minify-type-constructors "^0.0.4" - babel-plugin-transform-inline-consecutive-adds "^0.0.2" - babel-plugin-transform-member-expression-literals "^6.8.1" - babel-plugin-transform-merge-sibling-variables "^6.8.2" - babel-plugin-transform-minify-booleans "^6.8.0" - babel-plugin-transform-property-literals "^6.8.1" - babel-plugin-transform-regexp-constructors "^0.0.6" - babel-plugin-transform-remove-console "^6.8.1" - babel-plugin-transform-remove-debugger "^6.8.1" - babel-plugin-transform-remove-undefined "^0.0.5" - babel-plugin-transform-simplify-comparison-operators "^6.8.1" - babel-plugin-transform-undefined-to-void "^6.8.0" - lodash.isplainobject "^4.0.6" - babel-preset-env@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" @@ -3120,10 +3003,6 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" -jsesc@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" From 7d8ee5582c6b9620566473602dbd9a90945b26f1 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Fri, 11 Aug 2017 12:48:33 +0200 Subject: [PATCH 6/7] Add node api tests Remove outFile and outDir from options passed to babili Update snapshot --- .../__tests__/__snapshots__/cli-tests.js.snap | 2 +- .../__snapshots__/node-api-tests.js.snap | 3 +++ packages/babili/__tests__/cli-tests.js | 2 -- packages/babili/__tests__/node-api-tests.js | 21 +++++++++++++++++++ packages/babili/src/cli.js | 2 ++ 5 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 packages/babili/__tests__/__snapshots__/node-api-tests.js.snap create mode 100644 packages/babili/__tests__/node-api-tests.js diff --git a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap index a35a04bc4..075c88c8c 100644 --- a/packages/babili/__tests__/__snapshots__/cli-tests.js.snap +++ b/packages/babili/__tests__/__snapshots__/cli-tests.js.snap @@ -26,6 +26,6 @@ exports[`Babili CLI stdin + outFile 1`] = `"function foo(){const a=x(1),b=y(2);r exports[`Babili CLI stdin + stdout 1`] = ` Object { "stderr": "", - "stdout": "function a(){const b=x(1),c=y(2);return z(b,c)}", + "stdout": "function a(){const a=x(1),b=y(2);return z(a,b)}", } `; diff --git a/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap b/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap new file mode 100644 index 000000000..e3d0053ed --- /dev/null +++ b/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Babili Node API simple usage 1`] = `"function foo(){const a=x(1),b=y(2);return z(a,b)}"`; diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js index 15e561227..9c29f623c 100644 --- a/packages/babili/__tests__/cli-tests.js +++ b/packages/babili/__tests__/cli-tests.js @@ -23,8 +23,6 @@ function runCli(args = [], stdin) { const s = new Readable(); s.push(stdin); s.push(null); - - child.stdin.isTTY = true; s.pipe(child.stdin); } diff --git a/packages/babili/__tests__/node-api-tests.js b/packages/babili/__tests__/node-api-tests.js new file mode 100644 index 000000000..2cc9c3b24 --- /dev/null +++ b/packages/babili/__tests__/node-api-tests.js @@ -0,0 +1,21 @@ +jest.autoMockOff(); + +const babili = require("../src/index"); + +const sampleInput = ` +function foo() { + const bar = x(1); + const baz = y(2); + return z(bar, baz); +} +`; + +describe("Babili Node API", () => { + it("simple usage", () => { + expect(babili(sampleInput).code).toMatchSnapshot(); + }); + + it("throw on invalid options", () => { + expect(() => babili(sampleInput, { foo: false, bar: true }).code).toThrow(); + }); +}); diff --git a/packages/babili/src/cli.js b/packages/babili/src/cli.js index 17c6422ea..50cb747f8 100644 --- a/packages/babili/src/cli.js +++ b/packages/babili/src/cli.js @@ -179,6 +179,8 @@ function getBabiliOpts(argv) { delete options["out-dir"]; delete options.o; delete options["out-file"]; + delete options.outFile; + delete options.outDir; return options; } From 82dfd83cbe86a4ef8980da7eaabd3ba89cc1f3f3 Mon Sep 17 00:00:00 2001 From: Vignesh Shanmugam Date: Fri, 11 Aug 2017 14:02:09 +0200 Subject: [PATCH 7/7] use stdin stream and api test Update package.json --- package.json | 6 +----- .../babili/__tests__/__snapshots__/node-api-tests.js.snap | 2 ++ packages/babili/__tests__/cli-tests.js | 6 +----- packages/babili/__tests__/node-api-tests.js | 5 +++++ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index d17998b4c..402d44f8c 100644 --- a/package.json +++ b/package.json @@ -70,9 +70,5 @@ }, "workspaces": [ "packages/*" - ], - "dependencies": { - "mkdirp": "^0.5.1", - "util.promisify": "^1.0.0" - } + ] } diff --git a/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap b/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap index e3d0053ed..02bcca18a 100644 --- a/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap +++ b/packages/babili/__tests__/__snapshots__/node-api-tests.js.snap @@ -1,3 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Babili Node API override default babili options 1`] = `"function foo(){const bar=x(1),baz=y(2);return z(bar,baz)}"`; + exports[`Babili Node API simple usage 1`] = `"function foo(){const a=x(1),b=y(2);return z(a,b)}"`; diff --git a/packages/babili/__tests__/cli-tests.js b/packages/babili/__tests__/cli-tests.js index 9c29f623c..31bdb48d9 100644 --- a/packages/babili/__tests__/cli-tests.js +++ b/packages/babili/__tests__/cli-tests.js @@ -2,7 +2,6 @@ jest.autoMockOff(); const { spawn } = require("child_process"); const path = require("path"); -const { Readable } = require("stream"); const fs = require("fs"); const promisify = require("util.promisify"); const rimraf = require("rimraf"); @@ -20,10 +19,7 @@ function runCli(args = [], stdin) { }); if (stdin) { - const s = new Readable(); - s.push(stdin); - s.push(null); - s.pipe(child.stdin); + child.stdin.end(stdin); } let stdout = ""; diff --git a/packages/babili/__tests__/node-api-tests.js b/packages/babili/__tests__/node-api-tests.js index 2cc9c3b24..857471fd5 100644 --- a/packages/babili/__tests__/node-api-tests.js +++ b/packages/babili/__tests__/node-api-tests.js @@ -18,4 +18,9 @@ describe("Babili Node API", () => { it("throw on invalid options", () => { expect(() => babili(sampleInput, { foo: false, bar: true }).code).toThrow(); }); + + it("override default babili options", () => { + const babiliOpts = { mangle: false }; + expect(babili(sampleInput, babiliOpts).code).toMatchSnapshot(); + }); });