From 5ee8f7568bd626a28614e160b1881c5d1f1cbe85 Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Tue, 3 Nov 2015 10:04:20 +0000 Subject: [PATCH] add babel-doctor --- package.json | 1 - packages/babel-cli/bin/babel-doctor.js | 3 + packages/babel-cli/bin/babel-plugin.js | 3 - packages/babel-cli/package.json | 8 +- packages/babel-cli/src/babel-doctor/index.js | 94 +++++++++++++++++++ .../src/babel-doctor/rules/deduped.js | 34 +++++++ .../src/babel-doctor/rules/has-config.js | 30 ++++++ .../babel-cli/src/babel-doctor/rules/index.js | 3 + .../src/babel-doctor/rules/latest-packages.js | 53 +++++++++++ 9 files changed, 223 insertions(+), 6 deletions(-) create mode 100755 packages/babel-cli/bin/babel-doctor.js delete mode 100755 packages/babel-cli/bin/babel-plugin.js create mode 100644 packages/babel-cli/src/babel-doctor/index.js create mode 100644 packages/babel-cli/src/babel-doctor/rules/deduped.js create mode 100644 packages/babel-cli/src/babel-doctor/rules/has-config.js create mode 100644 packages/babel-cli/src/babel-doctor/rules/index.js create mode 100644 packages/babel-cli/src/babel-doctor/rules/latest-packages.js diff --git a/package.json b/package.json index b8926cfb2d..5a490a1796 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ ], "optional": [ "optimisation.flow.forOf", - "bluebirdCoroutines", "runtime" ], "env": { diff --git a/packages/babel-cli/bin/babel-doctor.js b/packages/babel-cli/bin/babel-doctor.js new file mode 100755 index 0000000000..e22664f438 --- /dev/null +++ b/packages/babel-cli/bin/babel-doctor.js @@ -0,0 +1,3 @@ +#!/usr/bin/env node + +require("../lib/babel-doctor"); diff --git a/packages/babel-cli/bin/babel-plugin.js b/packages/babel-cli/bin/babel-plugin.js deleted file mode 100755 index 96507ed3e4..0000000000 --- a/packages/babel-cli/bin/babel-plugin.js +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env node - -require("../lib/babel-plugin"); diff --git a/packages/babel-cli/package.json b/packages/babel-cli/package.json index d8d92fbb32..a580af445e 100644 --- a/packages/babel-cli/package.json +++ b/packages/babel-cli/package.json @@ -10,21 +10,25 @@ "dependencies": { "babel-core": "^6.0.15", "babel-polyfill": "^6.0.14", + "babel-runtime": "^5.0.0", + "chalk": "1.1.1", "chokidar": "^1.0.0", "commander": "^2.8.1", "convert-source-map": "^1.1.0", "fs-readdir-recursive": "^0.1.0", "glob": "^5.0.5", "lodash": "^3.2.0", + "log-symbols": "^1.0.2", "output-file-sync": "^1.1.0", "path-exists": "^1.0.0", "path-is-absolute": "^1.0.0", + "request": "^2.65.0", "slash": "^1.0.0", "source-map": "^0.5.0", - "v8flags": "^2.0.10", - "babel-runtime": "^5.0.0" + "v8flags": "^2.0.10" }, "bin": { + "babel-doctor": "./bin/babel-doctor.js", "babel": "./bin/babel.js", "babel-node": "./bin/babel-node.js", "babel-external-helpers": "./bin/babel-external-helpers.js" diff --git a/packages/babel-cli/src/babel-doctor/index.js b/packages/babel-cli/src/babel-doctor/index.js new file mode 100644 index 0000000000..5d3729de7f --- /dev/null +++ b/packages/babel-cli/src/babel-doctor/index.js @@ -0,0 +1,94 @@ +import chalk from "chalk"; +import path from "path"; +import fs from "fs"; +import * as rules from "./rules"; +import symbols from "log-symbols"; + +let didError = false; +let lastWasSep = false; + +function sep() { + if (lastWasSep) return; + lastWasSep = true; + + console.log(); +} + +function log(msg) { + lastWasSep = false; + console.log(msg); +} + +// + +log("\n" + chalk.underline.yellow("Babel Doctor")); +log("Running sanity checks on your system. This may take a few minutes...\n"); + +// + +let packages = []; + +let nodeModulesDirectories = [ + path.join(process.cwd(), "node_modules") +]; + +while (nodeModulesDirectories.length) { + let loc = nodeModulesDirectories.shift(); + if (!fs.existsSync(loc)) continue; + + let packagesNames: Array = fs.readdirSync(loc); + + for (let packageName of packagesNames) { + if (packageName[0] === ".") continue; + + let packageLoc = path.join(loc, packageName); + + packages.push({ + name: packageName, + loc: packageLoc, + version: require(path.join(packageLoc, "package.json")).version + }); + + nodeModulesDirectories.push(path.join(packageLoc, "node_modules")); + } +} + +// + +async function run() { + let promises = []; + + for (let key in rules) { + if (key[0] === "_") continue; + + let fn = rules[key]; + promises.push(fn(packages)); + } + + let results = await Promise.all(promises); + + for (let [success, message] of results) { + if (!success) didError = true; + let multiline = message.indexOf("\n") >= 0; + if (multiline) sep(); + log(`${success ? symbols.success : symbols.error} ${message}`); + if (multiline) sep(); + } + + sep(); + + if (didError) { + log(chalk.red("Found potential issues on your machine :(")); + } else { + log(chalk.green("Everything looks all right!")); + } + + sep(); +} + +run().then(function () { + process.exit(0); +}, function (err) { + console.error(err.stack); + process.exit(1); +}); diff --git a/packages/babel-cli/src/babel-doctor/rules/deduped.js b/packages/babel-cli/src/babel-doctor/rules/deduped.js new file mode 100644 index 0000000000..e75499be4c --- /dev/null +++ b/packages/babel-cli/src/babel-doctor/rules/deduped.js @@ -0,0 +1,34 @@ +import path from "path"; +import fs from "fs"; + +export default async function (packages) { + let foundDeps = {}; + let foundDuplicated = false; + let duplicatedPackages = {}; + + function checkDep(name) { + if (name.indexOf("babel-") === 0 && foundDeps[name]) { + foundDuplicated = true; + duplicatedPackages[name] = (duplicatedPackages[name] || 0) + 1; + } + + foundDeps[name] = true; + } + + for (let pkg of packages) { + checkDep(pkg.name); + } + + if (foundDuplicated) { + let msg = "Found these duplicate packages:\n\n"; + + for (let name in duplicatedPackages) { + msg += `- ${name} x ${duplicatedPackages[name]}\n`; + } + + msg += "\nRecommend running `npm dedupe`"; + return [false, msg]; + } else { + return [true, "No duplicate babel packages found"]; + } +} diff --git a/packages/babel-cli/src/babel-doctor/rules/has-config.js b/packages/babel-cli/src/babel-doctor/rules/has-config.js new file mode 100644 index 0000000000..9c98d717dc --- /dev/null +++ b/packages/babel-cli/src/babel-doctor/rules/has-config.js @@ -0,0 +1,30 @@ +import path from "path"; +import fs from "fs"; + +export default async function () { + let cwd = process.cwd(); + let parts = cwd.split(path.sep); + + let found = false; + + do { + let loc = parts.join(path.sep); + + let babelrc = path.join(loc, ".babelrc"); + if (fs.existsSync(babelrc)) { + return [true, `Found config at ${babelrc}`]; + } + + let packagejson = path.join(loc, "package.json"); + if (fs.existsSync(packagejson)) { + let pkg = require(packagejson); + if (pkg.babel) { + return [true, `Found config at ${packagejson}`]; + } + } + + parts.pop(); + } while(parts.length); + + return [false, "Found no .babelrc config"]; +} diff --git a/packages/babel-cli/src/babel-doctor/rules/index.js b/packages/babel-cli/src/babel-doctor/rules/index.js new file mode 100644 index 0000000000..52ee06abb7 --- /dev/null +++ b/packages/babel-cli/src/babel-doctor/rules/index.js @@ -0,0 +1,3 @@ +export { default as hasConfig } from "./has-config"; +export { default as deduped } from "./deduped"; +export { default as latestPackages } from "./latest-packages"; diff --git a/packages/babel-cli/src/babel-doctor/rules/latest-packages.js b/packages/babel-cli/src/babel-doctor/rules/latest-packages.js new file mode 100644 index 0000000000..787aeedffa --- /dev/null +++ b/packages/babel-cli/src/babel-doctor/rules/latest-packages.js @@ -0,0 +1,53 @@ +import request from "request"; +import path from "path"; + +let cache = {}; + +function getInfo(packageName) { + if (cache[packageName]) { + return cache[packageName]; + } else { + return cache[packageName] = new Promise(function (resolve, reject) { + request.get({ + url: `https://registry.npmjs.org/${packageName}/latest`, + json: true + }, function (err, res, body) { + if (err) { + reject(err); + } else { + resolve(cache[packageName] = body); + } + }); + }); + } +} + +export default async function (packages) { + let filteredPackages = []; + let promises = []; + + for (let pkg of packages) { + if (pkg.name.indexOf("babel-") !== 0) continue; + + promises.push(getInfo(pkg.name)); + filteredPackages.push(pkg); + } + + let infos = await Promise.all(promises); + let messages = []; + + for (let i = 0; i < infos.length; i++) { + let info = infos[i]; + let pkg = filteredPackages[i]; + + if (info.version !== pkg.version) { + messages.push(`${pkg.name} - Latest is ${info.version}. Local version is ${pkg.version}`); + } + } + + if (messages.length) { + return [false, `We found some outdated packages:\n\n- ${messages.join("\n- ")}`]; + } else { + return [true, "All babel packages appear to be up to date"]; + } +}