Skip to content
This repository has been archived by the owner on May 11, 2018. It is now read-only.

[WIP] Add node's "engines" option #114

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2d51bba
Parse engines node’s version from package.json.
yavorsky Dec 28, 2016
3f60aeb
Remove logs, move some staff to utils.
yavorsky Dec 28, 2016
3036ac5
Fix linting.
yavorsky Dec 28, 2016
0f1b25f
Fix indentation.
yavorsky Jan 1, 2017
3134576
Add engines option to package.json.
yavorsky Jan 1, 2017
b88e5f8
Use options for isPluginRequired.
yavorsky Jan 1, 2017
67f9c15
Add node-engines to fixtures.
yavorsky Jan 1, 2017
7a5da94
Add engines and getLowestFromSemverValue tests.
yavorsky Jan 1, 2017
b97d48b
Fix lint warns.
yavorsky Jan 1, 2017
568e0dc
Remove yarn.lock
yavorsky Jan 6, 2017
899b906
Add yarn.lock to gitignore.
yavorsky Jan 6, 2017
f1e3efd
Consider devEngines.
yavorsky Jan 6, 2017
29f7b6a
devEngines gt 4.x.
yavorsky Jan 6, 2017
f71eac9
Add BABEL_ENV production/development cases.
yavorsky Jan 6, 2017
2d22e03
Cover ‘*’ and wrong semver format.
yavorsky Jan 6, 2017
0696ea9
Fix indentation.
yavorsky Jan 6, 2017
ef95087
Use chrome is a number in node-engines fixtures.
yavorsky Jan 6, 2017
1838b68
Update engines and devEngines.
yavorsky Jan 7, 2017
b20ff6c
Merge branch 'master' into node-engines
yavorsky Jan 30, 2017
be36460
Refactor config parsing. Add annotations.
yavorsky Jan 31, 2017
f6cafdc
Update tests
yavorsky Jan 31, 2017
f4c75bc
Concat root path with process.cwd()
yavorsky Jan 31, 2017
9048897
Add engines/devEngines fixtures.
yavorsky Jan 31, 2017
1667ab7
Update yarn.lock
yavorsky Jan 31, 2017
419b3bc
Update yarn.lock.
yavorsky Jan 31, 2017
4db8341
Remove yarn.lock from gitignore
yavorsky Jan 31, 2017
8d0c085
Merge branch '2.0' into node-engines
yavorsky Apr 10, 2017
20153f0
After merge fixes.
yavorsky Apr 10, 2017
a42a0a8
Fix environment
yavorsky Apr 10, 2017
ac38247
Fix all supported versions list
yavorsky Apr 10, 2017
9268e16
Remove unused vars
yavorsky Apr 10, 2017
f16683e
Find package.json recursively.
yavorsky Apr 10, 2017
d8a97f0
Fix package path.
yavorsky Apr 10, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
"license": "MIT",
"repository": "https://github.com/babel/babel-preset-env",
"main": "lib/index.js",
"engines" : {
"node" : ">= 0.10.0"
},
"devEngines" : {
"node" : ">= 6"
},
"scripts": {
"build": "rimraf lib && babel src -d lib",
"build-data": "node ./scripts/build-data.js",
Expand Down
135 changes: 135 additions & 0 deletions src/config-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import semver from "semver";
import path from "path";
import fs from "fs";
import { getEnv, semverify } from "./utils";
import pluginList from "../data/plugins.json";
import builtInsList from "../data/built-ins.json";

/* Resolving path depending on what type of path was passed (directory or file).
../confg/ -> ../confg/package.json
./index.js -> ./package.json */
const resolvePackagePath = (packagePath = "") => {
return path.join(packagePath, "package.json");
};

// Just check wether the file exist.
export const fileExist = file =>
fs.existsSync(file) && fs.statSync(file).isFile();

const eachParent = (file, callback) => {
if (!file) return undefined;
let loc = path.resolve(file);
do {
const result = callback(loc);
if (typeof result !== "undefined") return result;
} while (loc !== (loc = path.dirname(loc)));
return undefined;
};

const parsePackage = path => JSON.parse(fs.readFileSync(path));

export const findPackageRecursively = entry => {
return eachParent(entry, dir => {
const pkg = resolvePackagePath(dir);

if (fileExist(pkg)) {
try {
return parsePackage(pkg);
} catch (e) {
console.warn("Can't parse " + pkg + ".");
}
}
});
};

/* Filter versions that satisfiyng to passed semver range.
Ex: 5.5 satisfies ^5.0, 1.0.1 satisfies >= 1.0 */
const filterSatisfiedVersions = (range, versions) => {
return versions.filter(targ => semver.satisfies(targ, range));
};

const getVersionsFromList = list => {
return Object.keys(list).reduce(
(allVersions, currentItem) => {
const currentVersions = list[currentItem];
for (const envName in currentVersions) {
const currentVersion = allVersions[envName];
const envVersion = currentVersions[envName];

if (!currentVersion) {
allVersions[envName] = [envVersion];
} else if (currentVersion.indexOf(envVersion) === -1) {
allVersions[envName].push(envVersion);
}
}

for (const env in allVersions) {
allVersions[env].sort((a, b) => a - b);
}

return allVersions;
},
{},
);
};

/* First, it checks whether passed version is a wildcat, a range or a simple string
- For wildcats(*) returs null. It means all node versions are matched.
- For versions in a simple string format (2.0) it converts it to the number.
- For ranged values (^4.5, ~2.1.0) it checks all versions we must support and returns lowest from the list.
*/
export const getLowestFromSemverValue = (version, versionsList) => {
if (version === "*") {
return null;
}

if (semver.valid(version)) {
return version;
} else if (semver.validRange(version)) {
const versions = versionsList.map(semverify);
const allSupported = filterSatisfiedVersions(version, versions);
if (allSupported.length) {
return allSupported[0];
}
}
return null;
};

/* Try to access `package.json` with passed path.
If can't - logs (but doesn't throw) an error. */
export const getPackageJSON = packagePath => {
try {
return findPackageRecursively(packagePath);
} catch (e) {
console.warn(`Can't parse package.json in ${packagePath}: `, e);
}
};

/* Gives `package.json` path and all versions to consider and
returns engines/devEngines version or `null`.
`null` means support all node.js versions. */
export const getEnginesNodeVersion = (packagePath, useBuiltIns) => {
const env = getEnv(process.env);
const pkg = getPackageJSON(packagePath);
if (!pkg) return null;
const engines = (env === "development" && pkg.devEngines) || pkg.engines;

if (engines && engines.node) {
const semverVersion = engines.node;

const list = [pluginList];
if (useBuiltIns) {
list.push(builtInsList);
}

const allSupportedVersions = getVersionsFromList(
Object.assign({}, ...list),
);

return getLowestFromSemverValue(
semverVersion,
allSupportedVersions["node"],
);
}
return null;
};
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ function getPlatformSpecificDefaultFor(targets) {
return isAnyTarget || isWebTarget ? defaultWebIncludes : [];
}

export default function buildPreset(context, opts = {}) {
export default function buildPreset(context, opts = {}, fileContext) {
const validatedOptions = normalizeOptions(opts);
const { debug, loose, moduleType, useBuiltIns } = validatedOptions;

const targets = getTargets(validatedOptions.targets);
const targets = getTargets(validatedOptions.targets, opts, fileContext);
const include = transformIncludesAndExcludes(validatedOptions.include);
const exclude = transformIncludesAndExcludes(validatedOptions.exclude);

Expand Down
24 changes: 17 additions & 7 deletions src/targets-parser.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import browserslist from "browserslist";
import semver from "semver";
import { semverify } from "./utils";
import { getEnginesNodeVersion } from "./config-utils";

const browserNameMap = {
chrome: "chrome",
Expand Down Expand Up @@ -65,11 +66,15 @@ const outputDecimalWarning = decimalTargets => {
const targetParserMap = {
__default: (target, value) => [target, semverify(value)],

// Parse `node: true` and `node: "current"` to version
node: (target, value) => {
const parsed = value === true || value === "current"
? process.versions.node
: semverify(value);
node: (target, value, options = {}, fileContext = {}) => {
let parsed;
if (value === true || value === "current") {
parsed = process.versions.node;
} else if (value === "engines") {
parsed = getEnginesNodeVersion(fileContext.dirname, options.useBuiltIns);
} else {
parsed = semverify(value);
}

return [target, parsed];
},
Expand All @@ -78,7 +83,7 @@ const targetParserMap = {
uglify: (target, value) => [target, value === true],
};

const getTargets = (targets = {}) => {
const getTargets = (targets = {}, options, fileContext) => {
let targetOpts = {};

// Parse browsers target via browserslist
Expand All @@ -99,7 +104,12 @@ const getTargets = (targets = {}) => {

// Check if we have a target parser?
const parser = targetParserMap[target] || targetParserMap.__default;
const [parsedTarget, parsedValue] = parser(target, value);
const [parsedTarget, parsedValue] = parser(
target,
value,
options,
fileContext,
);

if (parsedValue) {
// Merge (lowest wins)
Expand Down
68 changes: 68 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @flow
import semver from "semver";

const DEFAULT_ENV = "development";
// Convert version to a semver value.
// 2.5 -> 2.5.0; 1 -> 1.0.0;
export const semverify = version => {
Expand All @@ -17,6 +18,10 @@ export const semverify = version => {
return split.join(".");
};

export const desemverify = version => {
return parseFloat(version);
};

export const prettifyVersion = version => {
if (typeof version !== "string") {
return version;
Expand Down Expand Up @@ -52,3 +57,66 @@ export const prettifyTargets = (targets = {}) => {
{},
);
};

export const getEnv = env => {
return env.BABEL_ENV || env.NODE_ENV || DEFAULT_ENV;
};

// const DEFAULT_ENV = "development";
// const filePathRe = /^(\.\w+)|(\w+\.\w+)$/;
// const patchSpecifiedRe = /^\d+\.\d+\.\d+$/;

// export const _extends = Object.assign || function (target) {
// for (let i = 1; i < arguments.length; i++) {
// const source = arguments[i];
// for (const key in source) {
// if (Object.prototype.hasOwnProperty.call(source, key)) {
// target[key] = source[key];
// }
// }
// }
// return target;
// };

// /* Convert version to a semver value.
// 2.5 -> 2.5.0; 1 -> 1.0.0;
// */
// export const semverify = (version) => {
// if (typeof version === "string" && patchSpecifiedRe.test(version)) {
// return version;
// }
// const isInt = version % 1 === 0;
// const stringified = version.toString();
// const strEnd = isInt ? ".0.0" : ".0";
// return stringified + strEnd;
// };

// Convert semver value to a number.
// Be careful when passing ranges! It's better to use `getLowestFromSemverValue` from config-utils.js

// export const desemverify = (version) => {
// return parseFloat(version);
// };

// // Get current environment.

// /* Check passed argument includes filename.
// Ex: ./.babelerc, /my/path/package.json
// */
// export const pathIsFile = (targetPath) => {
// return filePathRe.test(targetPath);
// };

// /* Recline filename for the given path.
// Ex: my/path/package.json -> my/path/
// */
// export const getDirnameInPath = (targetPath) => {
// return targetPath.substring(0, targetPath.lastIndexOf("/") + 1);
// };

// /* Pick filename for the given path.
// Ex: my/path/package.json -> package.json
// */
// export const getFilenameInPath = (targetPath) => {
// return targetPath.substring(targetPath.lastIndexOf("/") + 1);
// };
1 change: 1 addition & 0 deletions test/fixtures/preset-options/dev-engines/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = 1;
3 changes: 3 additions & 0 deletions test/fixtures/preset-options/dev-engines/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"use strict";

const a = 1;
9 changes: 9 additions & 0 deletions test/fixtures/preset-options/dev-engines/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
["../../../../lib", {
"targets": {
"node": "engines"
}
}]
]
}
9 changes: 9 additions & 0 deletions test/fixtures/preset-options/dev-engines/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "fixtures-dev-engines-test",
"engines" : {
"node" : ">= 0.10.0"
},
"devEngines" : {
"node" : ">= 6"
}
}
1 change: 1 addition & 0 deletions test/fixtures/preset-options/engines/actual.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = 1;
3 changes: 3 additions & 0 deletions test/fixtures/preset-options/engines/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"use strict";

var a = 1;
9 changes: 9 additions & 0 deletions test/fixtures/preset-options/engines/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
["../../../../lib", {
"targets": {
"node": "engines"
}
}]
]
}
6 changes: 6 additions & 0 deletions test/fixtures/preset-options/engines/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "fixtures-dev-engines-test",
"engines" : {
"node" : ">= 0.10.0"
}
}
Loading