draft: refactor project so it sits on top of a standalone app

This commit is contained in:
2020-05-11 15:34:47 +02:00
parent a9ee5acc1c
commit f97e8455fc
13068 changed files with 1735502 additions and 866 deletions
+1541
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+112
View File
@@ -0,0 +1,112 @@
<div align="center">
<a href="https://github.com/webpack/webpack-cli">
<img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
</a>
</div>
<h1 align="center">webpack CLI</h1>
<p align="center">
The official CLI of webpack
</p>
<br>
[![npm][npm]][npm-url]
[![Build Status][build-status]][build-status-url]
[![Build2 Status][build-status-azure]][build-status-azure-url]
[![deps][deps]][deps-url]
[![Code Climate][maintainability]][maintainability-url]
[![chat on gitter][chat]][chat-url]
[![Install Size][size]][size-url]
[![Downloads][downloads]][downloads-url]
[![lerna][lerna]][lerna-url]
[![GitHub contributors][contributors]][contributors-url]
- [About](#about)
- [How to install](#how-to-install)
- [Packages](#packages)
- [Commands](#commands)
- [Utilities](#utilities)
- [Getting started](#getting-started)
- [webpack CLI Scaffolds](#webpack-cli-scaffolds)
- [Contributing and Internal Documentation](#contributing-and-internal-documentation)
- [Open Collective](#open-collective)
## About
webpack CLI provides a flexible set of commands for developers to increase speed when setting up a custom webpack project. As of webpack v4, webpack is not expecting a configuration file, but often developers want to create a more custom webpack configuration based on their use-cases and needs. webpack CLI addresses these needs by providing a set of tools to improve the setup of custom webpack configuration.
### How to install
When you have followed the [Getting Started](https://webpack.js.org/guides/getting-started/) guide of webpack then webpack CLI is already installed!
Otherwise `npm install --save-dev webpack-cli` or `yarn add webpack-cli --dev` will install it.
## Packages
We organize webpack CLI as a multi-package repository using [lerna](https://github.com/lerna/lerna). Every command has a dedicated subfolder in the `packages` Folder. Here's a summary of commands provided by the CLI.
### Commands
Supporting developers is an important task for webpack CLI. Thus, webpack CLI provides different commands for many common tasks.
- [`webpack-cli init`](./packages/init/README.md#webpack-cli-init) - Create a new webpack configuration.
- [`webpack-cli info`](./packages/info/README.md#webpack-cli-info) - Returns information related to the local environment.
- [`webpack-cli migrate`](./packages/migrate/README.md#webpack-cli-migrate) - Migrate project from one version to another.
- [`webpack-cli generate-plugin`](./packages/generate-plugin/README.md#webpack-cli-generate-plugin) - Initiate new plugin project.
- [`webpack-cli generate-loader`](./packages/generate-loader/README.md#webpack-cli-generate-loader) - Initiate new loader project.
- [`webpack-cli serve`](./packages/serve/README.md#webpack-cli-serve) - Use webpack with a development server that provides live reloading.
### Utilities
The project also has several utility packages which are used by other commands
- [`utils`](./packages/utils/README.md) - Several utilities used across webpack-cli.
- [`generators`](./packages/generators/README.md) - Contains all webpack-cli related yeoman generators.
- [`webpack-scaffold`](./packages/webpack-scaffold/README.md) - Utilities to create a webpack scaffold.
## Getting started
When you have followed the [Getting Started](https://webpack.js.org/guides/getting-started/) guide of webpack then webpack CLI is already installed! Otherwise, you would need to install webpack CLI and the packages you want to use. If we want to use the `init` command to create a new `webpack.config.js` configuration file:
```sh
npm i webpack-cli @webpack-cli/init
npx webpack-cli init
```
You will be prompted for some questions about what how you want to generate your config file when running the `init` command so webpack CLI can provide the best fitting configuration.
## webpack CLI Scaffolds
With v3 of webpack CLI, we introduced scaffolding as an integral part of the CLI. Our goal is to simplify the creation of webpack configurations for different purposes. Additionally, sharing such solutions with the community is beneficial and with webpack, we want to allow this. We provide `webpack-scaffold` as a utility suite for creating these scaffolds. It contains functions that could be of use for creating a scaffold yourself.
You can read more about [Scaffolding](https://webpack.js.org/guides/scaffolding), learn [How to compose a webpack-scaffold?](https://webpack.js.org/contribute/writing-a-scaffold) or generate one with [webpack-scaffold-starter](https://github.com/rishabh3112/webpack-scaffold-starter).
## Contributing and Internal Documentation
The webpack family welcomes any contributor, small or big. We are happy to elaborate, guide you through the source code and find issues you might want to work on! To get started have a look at our [documentation on contributing](./.github/CONTRIBUTING.md).
## Open Collective
If you like **webpack**, please consider donating to our [Open Collective](https://opencollective.com/webpack) to help us maintain it.
[build-status]: https://travis-ci.org/webpack/webpack-cli.svg
[build-status-url]: https://travis-ci.org/webpack/webpack-cli
[build-status-azure]: https://dev.azure.com/webpack/webpack/_apis/build/status/webpack.webpack-cli
[build-status-azure-url]: https://dev.azure.com/webpack/webpack/_build/latest?definitionId=4
[chat]: https://badges.gitter.im/webpack/webpack.svg
[chat-url]: https://gitter.im/webpack/webpack
[contributors]: https://img.shields.io/github/contributors/webpack/webpack-cli.svg
[contributors-url]: https://github.com/webpack/webpack-cli/graphs/contributors
[deps]: https://img.shields.io/david/webpack/webpack.svg
[deps-url]: https://david-dm.org/webpack/webpack-cli
[downloads]: https://img.shields.io/npm/dw/webpack-cli.svg
[downloads-url]: https://www.npmjs.com/package/webpack-cli
[lerna]: https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg
[lerna-url]: http://www.lernajs.io/
[npm]: https://img.shields.io/npm/v/webpack-cli.svg
[npm-url]: https://www.npmjs.com/package/webpack-cli
[maintainability]: https://codeclimate.com/github/webpack/webpack-cli/badges/gpa.svg
[maintainability-url]: https://codeclimate.com/github/webpack/webpack-cli
[size]: https://packagephobia.now.sh/badge?p=webpack-cli
[size-url]: https://packagephobia.now.sh/result?p=webpack-cli
+63
View File
@@ -0,0 +1,63 @@
module.exports = {
root: true,
plugins: ["node"],
extends: ["../.eslintrc.js", "plugin:node/recommended"],
env: {
node: true,
es6: true,
jest: true
},
parserOptions: { ecmaVersion: 2017, sourceType: "module" },
rules: {
"node/no-unsupported-features": ["error", { version: 6 }],
"node/no-deprecated-api": "error",
"node/no-missing-import": "error",
"node/no-missing-require": [
"error",
{
resolvePaths: ["./packages"],
allowModules: [
"webpack",
"@webpack-cli/generators",
"@webpack-cli/init",
"@webpack-cli/migrate",
"@webpack-cli/utils",
"@webpack-cli/generate-loader",
"@webpack-cli/generate-plugin",
"@webpack-cli/webpack-scaffold"
]
}
],
"node/no-unpublished-bin": "error",
"node/no-unpublished-require": [
"error",
{
allowModules: [
"webpack",
"webpack-dev-server",
"@webpack-cli/generators",
"@webpack-cli/init",
"@webpack-cli/migrate",
"@webpack-cli/utils",
"@webpack-cli/generate-loader",
"@webpack-cli/generate-plugin",
"@webpack-cli/webpack-scaffold"
]
}
],
"node/no-extraneous-require": [
"error",
{
allowModules: [
"@webpack-cli/migrate",
"@webpack-cli/generators",
"@webpack-cli/utils",
"@webpack-cli/generate-loader",
"@webpack-cli/generate-plugin",
"@webpack-cli/webpack-scaffold"
]
}
],
"node/process-exit-as-throw": "error"
}
};
+366
View File
@@ -0,0 +1,366 @@
#!/usr/bin/env node
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
const { NON_COMPILATION_ARGS } = require("./utils/constants");
(function() {
// wrap in IIFE to be able to use return
const importLocal = require("import-local");
// Prefer the local installation of webpack-cli
if (importLocal(__filename)) {
return;
}
require("v8-compile-cache");
const ErrorHelpers = require("./utils/errorHelpers");
const NON_COMPILATION_CMD = process.argv.find(arg => {
if (arg === "serve") {
global.process.argv = global.process.argv.filter(a => a !== "serve");
process.argv = global.process.argv;
}
return NON_COMPILATION_ARGS.find(a => a === arg);
});
if (NON_COMPILATION_CMD) {
return require("./utils/prompt-command")(NON_COMPILATION_CMD, ...process.argv);
}
const yargs = require("yargs").usage(`webpack-cli ${require("../package.json").version}
Usage: webpack-cli [options]
webpack-cli [options] --entry <entry> --output <output>
webpack-cli [options] <entries...> --output <output>
webpack-cli <command> [options]
For more information, see https://webpack.js.org/api/cli/.`);
require("./config/config-yargs")(yargs);
// yargs will terminate the process early when the user uses help or version.
// This causes large help outputs to be cut short (https://github.com/nodejs/node/wiki/API-changes-between-v0.10-and-v4#process).
// To prevent this we use the yargs.parse API and exit the process normally
yargs.parse(process.argv.slice(2), (err, argv, output) => {
Error.stackTraceLimit = 30;
// arguments validation failed
if (err && output) {
console.error(output);
process.exitCode = 1;
return;
}
// help or version info
if (output) {
console.log(output);
return;
}
if (argv.verbose) {
argv["display"] = "verbose";
}
let options;
try {
options = require("./utils/convert-argv")(argv);
} catch (err) {
if (err.code === "MODULE_NOT_FOUND") {
const moduleName = err.message.split("'")[1];
let instructions = "";
let errorMessage = "";
if (moduleName === "webpack") {
errorMessage = `\n${moduleName} not installed`;
instructions = `Install webpack to start bundling: \u001b[32m\n $ npm install --save-dev ${moduleName}\n`;
if (process.env.npm_execpath !== undefined && process.env.npm_execpath.includes("yarn")) {
instructions = `Install webpack to start bundling: \u001b[32m\n $ yarn add ${moduleName} --dev\n`;
}
Error.stackTraceLimit = 1;
console.error(`${errorMessage}\n\n${instructions}`);
process.exitCode = 1;
return;
}
}
if (err.name !== "ValidationError") {
throw err;
}
const stack = ErrorHelpers.cleanUpWebpackOptions(err.stack, err.message);
const message = err.message + "\n" + stack;
if (argv.color) {
console.error(`\u001b[1m\u001b[31m${message}\u001b[39m\u001b[22m`);
} else {
console.error(message);
}
process.exitCode = 1;
return;
}
/**
* When --silent flag is present, an object with a no-op write method is
* used in place of process.stout
*/
const stdout = argv.silent ? { write: () => {} } : process.stdout;
function ifArg(name, fn, init) {
if (Array.isArray(argv[name])) {
if (init) init();
argv[name].forEach(fn);
} else if (typeof argv[name] !== "undefined") {
if (init) init();
fn(argv[name], -1);
}
}
function processOptions(options) {
// process Promise
if (typeof options.then === "function") {
options.then(processOptions).catch(function(err) {
console.error(err.stack || err);
// eslint-disable-next-line no-process-exit
process.exit(1);
});
return;
}
const firstOptions = [].concat(options)[0];
const statsPresetToOptions = require("webpack").Stats.presetToOptions;
let outputOptions = options.stats;
if (typeof outputOptions === "boolean" || typeof outputOptions === "string") {
outputOptions = statsPresetToOptions(outputOptions);
} else if (!outputOptions) {
outputOptions = {};
}
ifArg("display", function(preset) {
outputOptions = statsPresetToOptions(preset);
});
outputOptions = Object.create(outputOptions);
if (Array.isArray(options) && !outputOptions.children) {
outputOptions.children = options.map(o => o.stats);
}
if (typeof outputOptions.context === "undefined") outputOptions.context = firstOptions.context;
ifArg("env", function(value) {
if (outputOptions.env) {
outputOptions._env = value;
}
});
ifArg("json", function(bool) {
if (bool) {
outputOptions.json = bool;
outputOptions.modules = bool;
}
});
if (typeof outputOptions.colors === "undefined") outputOptions.colors = require("supports-color").stdout;
ifArg("sort-modules-by", function(value) {
outputOptions.modulesSort = value;
});
ifArg("sort-chunks-by", function(value) {
outputOptions.chunksSort = value;
});
ifArg("sort-assets-by", function(value) {
outputOptions.assetsSort = value;
});
ifArg("display-exclude", function(value) {
outputOptions.exclude = value;
});
if (!outputOptions.json) {
if (typeof outputOptions.cached === "undefined") outputOptions.cached = false;
if (typeof outputOptions.cachedAssets === "undefined") outputOptions.cachedAssets = false;
ifArg("display-chunks", function(bool) {
if (bool) {
outputOptions.modules = false;
outputOptions.chunks = true;
outputOptions.chunkModules = true;
}
});
ifArg("display-entrypoints", function(bool) {
outputOptions.entrypoints = bool;
});
ifArg("display-reasons", function(bool) {
if (bool) outputOptions.reasons = true;
});
ifArg("display-depth", function(bool) {
if (bool) outputOptions.depth = true;
});
ifArg("display-used-exports", function(bool) {
if (bool) outputOptions.usedExports = true;
});
ifArg("display-provided-exports", function(bool) {
if (bool) outputOptions.providedExports = true;
});
ifArg("display-optimization-bailout", function(bool) {
if (bool) outputOptions.optimizationBailout = bool;
});
ifArg("display-error-details", function(bool) {
if (bool) outputOptions.errorDetails = true;
});
ifArg("display-origins", function(bool) {
if (bool) outputOptions.chunkOrigins = true;
});
ifArg("display-max-modules", function(value) {
outputOptions.maxModules = +value;
});
ifArg("display-cached", function(bool) {
if (bool) outputOptions.cached = true;
});
ifArg("display-cached-assets", function(bool) {
if (bool) outputOptions.cachedAssets = true;
});
if (!outputOptions.exclude) outputOptions.exclude = ["node_modules", "bower_components", "components"];
if (argv["display-modules"]) {
outputOptions.maxModules = Infinity;
outputOptions.exclude = undefined;
outputOptions.modules = true;
}
}
ifArg("hide-modules", function(bool) {
if (bool) {
outputOptions.modules = false;
outputOptions.chunkModules = false;
}
});
ifArg("info-verbosity", function(value) {
outputOptions.infoVerbosity = value;
});
ifArg("build-delimiter", function(value) {
outputOptions.buildDelimiter = value;
});
const webpack = require("webpack");
let lastHash = null;
let compiler;
try {
compiler = webpack(options);
} catch (err) {
if (err.name === "WebpackOptionsValidationError") {
if (argv.color) console.error(`\u001b[1m\u001b[31m${err.message}\u001b[39m\u001b[22m`);
else console.error(err.message);
// eslint-disable-next-line no-process-exit
process.exit(1);
}
throw err;
}
if (argv.progress) {
const ProgressPlugin = require("webpack").ProgressPlugin;
new ProgressPlugin({
profile: argv.profile
}).apply(compiler);
}
if (outputOptions.infoVerbosity === "verbose") {
if (argv.w) {
compiler.hooks.watchRun.tap("WebpackInfo", compilation => {
const compilationName = compilation.name ? compilation.name : "";
console.error("\nCompilation " + compilationName + " starting…\n");
});
} else {
compiler.hooks.beforeRun.tap("WebpackInfo", compilation => {
const compilationName = compilation.name ? compilation.name : "";
console.error("\nCompilation " + compilationName + " starting…\n");
});
}
compiler.hooks.done.tap("WebpackInfo", compilation => {
const compilationName = compilation.name ? compilation.name : "";
console.error("\nCompilation " + compilationName + " finished\n");
});
}
function compilerCallback(err, stats) {
if (!options.watch || err) {
// Do not keep cache anymore
compiler.purgeInputFileSystem();
}
if (err) {
lastHash = null;
console.error(err.stack || err);
if (err.details) console.error(err.details);
process.exitCode = 1;
return;
}
if (outputOptions.json) {
stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + "\n");
} else if (stats.hash !== lastHash) {
lastHash = stats.hash;
if (stats.compilation && stats.compilation.errors.length !== 0) {
const errors = stats.compilation.errors;
if (errors[0].name === "EntryModuleNotFoundError") {
console.error("\n\u001b[1m\u001b[31mInsufficient number of arguments or no entry found.");
console.error(
"\u001b[1m\u001b[31mAlternatively, run 'webpack(-cli) --help' for usage info.\u001b[39m\u001b[22m\n"
);
}
}
const statsString = stats.toString(outputOptions);
const delimiter = outputOptions.buildDelimiter ? `${outputOptions.buildDelimiter}\n` : "";
if (statsString) stdout.write(`${statsString}\n${delimiter}`);
}
if (!options.watch && stats.hasErrors()) {
process.exitCode = 2;
}
}
if (firstOptions.watch || options.watch) {
const watchOptions =
firstOptions.watchOptions || options.watchOptions || firstOptions.watch || options.watch || {};
if (watchOptions.stdin) {
process.stdin.on("end", function(_) {
process.exit(); // eslint-disable-line
});
process.stdin.resume();
}
compiler.watch(watchOptions, compilerCallback);
if (outputOptions.infoVerbosity !== "none") console.error("\nwebpack is watching the files…\n");
} else {
compiler.run((err, stats) => {
if (compiler.close) {
compiler.close(err2 => {
compilerCallback(err || err2, stats);
});
} else {
compilerCallback(err, stats);
}
});
}
}
processOptions(options);
});
})();
+504
View File
@@ -0,0 +1,504 @@
const optionsSchema = require("../config/optionsSchema.json");
const { GROUPS } = require("../utils/constants");
const {
CONFIG_GROUP,
BASIC_GROUP,
MODULE_GROUP,
OUTPUT_GROUP,
ADVANCED_GROUP,
RESOLVE_GROUP,
OPTIMIZE_GROUP,
DISPLAY_GROUP
} = GROUPS;
const nestedProperties = ["anyOf", "oneOf", "allOf"];
const resolveSchema = schema => {
let current = schema;
if (schema && typeof schema === "object" && "$ref" in schema) {
const path = schema.$ref.split("/");
for (const element of path) {
if (element === "#") {
current = optionsSchema;
} else {
current = current[element];
}
}
}
return current;
};
const findPropertyInSchema = (schema, property, subProperty) => {
if (!schema) return null;
if (subProperty) {
if (schema[property] && typeof schema[property] === "object" && subProperty in schema[property]) {
return resolveSchema(schema[property][subProperty]);
}
} else {
if (property in schema) return resolveSchema(schema[property]);
}
for (const name of nestedProperties) {
if (schema[name]) {
for (const item of schema[name]) {
const resolvedItem = resolveSchema(item);
const result = findPropertyInSchema(resolvedItem, property, subProperty);
if (result) return result;
}
}
}
return undefined;
};
const getSchemaInfo = (path, property, subProperty) => {
const pathSegments = path.split(".");
let current = optionsSchema;
for (const segment of pathSegments) {
if (segment === "*") {
current = findPropertyInSchema(current, "additionalProperties") || findPropertyInSchema(current, "items");
} else {
current = findPropertyInSchema(current, "properties", segment);
}
if (!current) return undefined;
}
return findPropertyInSchema(current, property, subProperty);
};
module.exports = function(yargs) {
yargs
.help("help")
.alias("help", "h")
.version()
.alias("version", "v")
.options({
config: {
type: "string",
describe: "Path to the config file",
group: CONFIG_GROUP,
defaultDescription: "webpack.config.js or webpackfile.js",
requiresArg: true
},
"config-register": {
type: "array",
alias: "r",
describe: "Preload one or more modules before loading the webpack configuration",
group: CONFIG_GROUP,
defaultDescription: "module id or path",
requiresArg: true
},
"config-name": {
type: "string",
describe: "Name of the config to use",
group: CONFIG_GROUP,
requiresArg: true
},
env: {
describe: "Environment passed to the config, when it is a function",
group: CONFIG_GROUP
},
mode: {
type: getSchemaInfo("mode", "type"),
choices: getSchemaInfo("mode", "enum"),
describe: getSchemaInfo("mode", "description"),
group: CONFIG_GROUP,
requiresArg: true
},
context: {
type: getSchemaInfo("context", "type"),
describe: getSchemaInfo("context", "description"),
group: BASIC_GROUP,
defaultDescription: "The current directory",
requiresArg: true
},
entry: {
type: "string",
describe: getSchemaInfo("entry", "description"),
group: BASIC_GROUP,
requiresArg: true
},
"no-cache": {
type: "boolean",
describe: "Disables cached builds",
group: BASIC_GROUP
},
"module-bind": {
type: "string",
describe: "Bind an extension to a loader",
group: MODULE_GROUP,
requiresArg: true
},
"module-bind-post": {
type: "string",
describe: "Bind an extension to a post loader",
group: MODULE_GROUP,
requiresArg: true
},
"module-bind-pre": {
type: "string",
describe: "Bind an extension to a pre loader",
group: MODULE_GROUP,
requiresArg: true
},
output: {
alias: "o",
describe: "The output path and file for compilation assets",
group: OUTPUT_GROUP,
requiresArg: true
},
"output-path": {
type: "string",
describe: getSchemaInfo("output.path", "description"),
group: OUTPUT_GROUP,
defaultDescription: "The current directory",
requiresArg: true
},
"output-filename": {
type: "string",
describe: getSchemaInfo("output.filename", "description"),
group: OUTPUT_GROUP,
defaultDescription: "[name].js",
requiresArg: true
},
"output-chunk-filename": {
type: "string",
describe: getSchemaInfo("output.chunkFilename", "description"),
group: OUTPUT_GROUP,
defaultDescription: "filename with [id] instead of [name] or [id] prefixed",
requiresArg: true
},
"output-source-map-filename": {
type: "string",
describe: getSchemaInfo("output.sourceMapFilename", "description"),
group: OUTPUT_GROUP,
requiresArg: true
},
"output-public-path": {
type: "string",
describe: getSchemaInfo("output.publicPath", "description"),
group: OUTPUT_GROUP,
requiresArg: true
},
"output-jsonp-function": {
type: "string",
describe: getSchemaInfo("output.jsonpFunction", "description"),
group: OUTPUT_GROUP,
requiresArg: true
},
"output-pathinfo": {
type: "boolean",
describe: getSchemaInfo("output.pathinfo", "description"),
group: OUTPUT_GROUP
},
"output-library": {
type: "array",
describe: "Expose the exports of the entry point as library",
group: OUTPUT_GROUP,
requiresArg: true
},
"output-library-target": {
type: "string",
describe: getSchemaInfo("output.libraryTarget", "description"),
choices: getSchemaInfo("output.libraryTarget", "enum"),
group: OUTPUT_GROUP,
requiresArg: true
},
"records-input-path": {
type: "string",
describe: getSchemaInfo("recordsInputPath", "description"),
group: ADVANCED_GROUP,
requiresArg: true
},
"records-output-path": {
type: "string",
describe: getSchemaInfo("recordsOutputPath", "description"),
group: ADVANCED_GROUP,
requiresArg: true
},
"records-path": {
type: "string",
describe: getSchemaInfo("recordsPath", "description"),
group: ADVANCED_GROUP,
requiresArg: true
},
define: {
type: "string",
describe: "Define any free var in the bundle",
group: ADVANCED_GROUP,
requiresArg: true
},
target: {
type: "string",
describe: getSchemaInfo("target", "description"),
group: ADVANCED_GROUP,
requiresArg: true
},
cache: {
type: "boolean",
describe: getSchemaInfo("cache", "description"),
default: null,
group: ADVANCED_GROUP,
defaultDescription: "It's enabled by default when watching"
},
watch: {
type: "boolean",
alias: "w",
describe: getSchemaInfo("watch", "description"),
group: BASIC_GROUP
},
"watch-stdin": {
type: "boolean",
alias: "stdin",
describe: getSchemaInfo("watchOptions.stdin", "description"),
group: ADVANCED_GROUP
},
"watch-aggregate-timeout": {
describe: getSchemaInfo("watchOptions.aggregateTimeout", "description"),
type: getSchemaInfo("watchOptions.aggregateTimeout", "type"),
group: ADVANCED_GROUP,
requiresArg: true
},
"watch-poll": {
type: "string",
describe: getSchemaInfo("watchOptions.poll", "description"),
group: ADVANCED_GROUP
},
hot: {
type: "boolean",
describe: "Enables Hot Module Replacement",
group: ADVANCED_GROUP
},
debug: {
type: "boolean",
describe: "Switch loaders to debug mode",
group: BASIC_GROUP
},
devtool: {
type: "string",
describe: getSchemaInfo("devtool", "description"),
group: BASIC_GROUP,
requiresArg: true
},
"resolve-alias": {
type: "string",
describe: getSchemaInfo("resolve.alias", "description"),
group: RESOLVE_GROUP,
requiresArg: true
},
"resolve-extensions": {
type: "array",
describe: getSchemaInfo("resolve.alias", "description"),
group: RESOLVE_GROUP,
requiresArg: true
},
"resolve-loader-alias": {
type: "string",
describe: "Setup a loader alias for resolving",
group: RESOLVE_GROUP,
requiresArg: true
},
"optimize-max-chunks": {
describe: "Try to keep the chunk count below a limit",
group: OPTIMIZE_GROUP,
requiresArg: true
},
"optimize-min-chunk-size": {
describe: getSchemaInfo("optimization.splitChunks.minSize", "description"),
group: OPTIMIZE_GROUP,
requiresArg: true
},
"optimize-minimize": {
type: "boolean",
describe: getSchemaInfo("optimization.minimize", "description"),
group: OPTIMIZE_GROUP
},
prefetch: {
type: "string",
describe: "Prefetch this request (Example: --prefetch ./file.js)",
group: ADVANCED_GROUP,
requiresArg: true
},
provide: {
type: "string",
describe: "Provide these modules as free vars in all modules (Example: --provide jQuery=jquery)",
group: ADVANCED_GROUP,
requiresArg: true
},
"labeled-modules": {
type: "boolean",
describe: "Enables labeled modules",
group: ADVANCED_GROUP
},
plugin: {
type: "string",
describe: "Load this plugin",
group: ADVANCED_GROUP,
requiresArg: true
},
bail: {
type: getSchemaInfo("bail", "type"),
describe: getSchemaInfo("bail", "description"),
group: ADVANCED_GROUP,
default: null
},
profile: {
type: "boolean",
describe: getSchemaInfo("profile", "description"),
group: ADVANCED_GROUP,
default: null
},
d: {
type: "boolean",
describe: "shortcut for --debug --devtool eval-cheap-module-source-map --output-pathinfo",
group: BASIC_GROUP
},
p: {
type: "boolean",
// eslint-disable-next-line quotes
describe: 'shortcut for --optimize-minimize --define process.env.NODE_ENV="production"',
group: BASIC_GROUP
},
silent: {
type: "boolean",
describe: "Prevent output from being displayed in stdout"
},
json: {
type: "boolean",
alias: "j",
describe: "Prints the result as JSON."
},
progress: {
type: "boolean",
describe: "Print compilation progress in percentage",
group: BASIC_GROUP
},
color: {
type: "boolean",
alias: "colors",
default: function supportsColor() {
return require("supports-color").stdout;
},
group: DISPLAY_GROUP,
describe: "Force colors on the console"
},
"no-color": {
type: "boolean",
alias: "no-colors",
group: DISPLAY_GROUP,
describe: "Force no colors on the console"
},
"sort-modules-by": {
type: "string",
group: DISPLAY_GROUP,
describe: "Sorts the modules list by property in module"
},
"sort-chunks-by": {
type: "string",
group: DISPLAY_GROUP,
describe: "Sorts the chunks list by property in chunk"
},
"sort-assets-by": {
type: "string",
group: DISPLAY_GROUP,
describe: "Sorts the assets list by property in asset"
},
"hide-modules": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Hides info about modules"
},
"display-exclude": {
type: "string",
group: DISPLAY_GROUP,
describe: "Exclude modules in the output"
},
"display-modules": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display even excluded modules in the output"
},
"display-max-modules": {
type: "number",
group: DISPLAY_GROUP,
describe: "Sets the maximum number of visible modules in output"
},
"display-chunks": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display chunks in the output"
},
"display-entrypoints": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display entry points in the output"
},
"display-origins": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display origins of chunks in the output"
},
"display-cached": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display also cached modules in the output"
},
"display-cached-assets": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display also cached assets in the output"
},
"display-reasons": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display reasons about module inclusion in the output"
},
"display-depth": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display distance from entry point for each module"
},
"display-used-exports": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display information about used exports in modules (Tree Shaking)"
},
"display-provided-exports": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display information about exports provided from modules"
},
"display-optimization-bailout": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display information about why optimization bailed out for modules"
},
"display-error-details": {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Display details about errors"
},
display: {
type: "string",
choices: ["", "verbose", "detailed", "normal", "minimal", "errors-only", "none"],
group: DISPLAY_GROUP,
describe: "Select display preset"
},
verbose: {
type: "boolean",
group: DISPLAY_GROUP,
describe: "Show more details"
},
"info-verbosity": {
type: "string",
default: "info",
choices: ["none", "info", "verbose"],
group: DISPLAY_GROUP,
describe: "Controls the output of lifecycle messaging e.g. Started watching files..."
},
"build-delimiter": {
type: "string",
group: DISPLAY_GROUP,
describe: "Display custom text after build output"
}
});
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,20 @@
{
"anyOf": [
{
"type": "object",
"description": "A webpack configuration object."
},
{
"type": "array",
"description": "An array of webpack configuration objects.",
"items": {
"description": "A webpack configuration object.",
"type": "object"
}
},
{
"instanceof": "Promise",
"description": "A promise that resolves with a configuration object, or an array of configuration objects."
}
]
}
+28
View File
@@ -0,0 +1,28 @@
const NON_COMPILATION_ARGS = ["init", "migrate", "serve", "generate-loader", "generate-plugin", "info"];
const CONFIG_GROUP = "Config options:";
const BASIC_GROUP = "Basic options:";
const MODULE_GROUP = "Module options:";
const OUTPUT_GROUP = "Output options:";
const ADVANCED_GROUP = "Advanced options:";
const RESOLVE_GROUP = "Resolving options:";
const OPTIMIZE_GROUP = "Optimizing options:";
const DISPLAY_GROUP = "Stats options:";
const GROUPS = {
CONFIG_GROUP,
BASIC_GROUP,
MODULE_GROUP,
OUTPUT_GROUP,
ADVANCED_GROUP,
RESOLVE_GROUP,
OPTIMIZE_GROUP,
DISPLAY_GROUP
};
const WEBPACK_OPTIONS_FLAG = "WEBPACK_OPTIONS";
module.exports = {
NON_COMPILATION_ARGS,
GROUPS,
WEBPACK_OPTIONS_FLAG
};
+562
View File
@@ -0,0 +1,562 @@
const path = require("path");
const fs = require("fs");
fs.existsSync = fs.existsSync || path.existsSync;
const interpret = require("interpret");
const prepareOptions = require("./prepareOptions");
const findup = require("findup-sync");
const validateOptions = require("./validate-options");
module.exports = function(...args) {
const argv = args[1] || args[0];
const options = [];
// Shortcuts
if (argv.d) {
argv.debug = true;
argv["output-pathinfo"] = true;
if (!argv.devtool) {
argv.devtool = "eval-cheap-module-source-map";
}
if (!argv.mode) {
argv.mode = "development";
}
}
if (argv.p) {
argv["optimize-minimize"] = true;
// eslint-disable-next-line quotes
argv["define"] = [].concat(argv["define"] || []).concat('process.env.NODE_ENV="production"');
if (!argv.mode) {
argv.mode = "production";
}
}
if (argv.output) {
let output = argv.output;
if (!path.isAbsolute(argv.o)) {
output = path.resolve(process.cwd(), output);
}
argv["output-filename"] = path.basename(output);
argv["output-path"] = path.dirname(output);
}
let configFileLoaded = false;
let configFiles = [];
const extensions = Object.keys(interpret.extensions).sort(function(a, b) {
return a === ".js" ? -1 : b === ".js" ? 1 : a.length - b.length;
});
let i;
if (argv.config) {
const getConfigExtension = function getConfigExtension(configPath) {
for (i = extensions.length - 1; i >= 0; i--) {
const tmpExt = extensions[i];
if (configPath.indexOf(tmpExt, configPath.length - tmpExt.length) > -1) {
return tmpExt;
}
}
return path.extname(configPath);
};
const mapConfigArg = function mapConfigArg(configArg) {
const resolvedPath = path.resolve(configArg);
const extension = getConfigExtension(resolvedPath);
return {
path: resolvedPath,
ext: extension
};
};
const configArgList = Array.isArray(argv.config) ? argv.config : [argv.config];
configFiles = configArgList.map(mapConfigArg);
} else {
const defaultConfigFileNames = ["webpack.config", "webpackfile"].join("|");
const webpackConfigFileRegExp = `(${defaultConfigFileNames})(${extensions.join("|")})`;
const pathToWebpackConfig = findup(webpackConfigFileRegExp);
if (pathToWebpackConfig) {
const resolvedPath = path.resolve(pathToWebpackConfig);
const actualConfigFileName = path.basename(resolvedPath);
const ext = actualConfigFileName.replace(new RegExp(defaultConfigFileNames), "");
configFiles.push({
path: resolvedPath,
ext
});
}
}
if (configFiles.length > 0) {
const registerCompiler = function registerCompiler(moduleDescriptor) {
if (moduleDescriptor) {
if (typeof moduleDescriptor === "string") {
require(moduleDescriptor);
} else if (!Array.isArray(moduleDescriptor)) {
moduleDescriptor.register(require(moduleDescriptor.module));
} else {
for (let i = 0; i < moduleDescriptor.length; i++) {
try {
registerCompiler(moduleDescriptor[i]);
break;
} catch (e) {
// do nothing
}
}
}
}
};
const requireConfig = function requireConfig(configPath) {
let options = (function WEBPACK_OPTIONS() {
if (argv.configRegister && argv.configRegister.length) {
module.paths.unshift(path.resolve(process.cwd(), "node_modules"), process.cwd());
argv.configRegister.forEach(dep => {
require(dep);
});
return require(path.resolve(process.cwd(), configPath));
} else {
return require(path.resolve(process.cwd(), configPath));
}
})();
options = prepareOptions(options, argv);
return options;
};
configFiles.forEach(function(file) {
registerCompiler(interpret.extensions[file.ext]);
options.push(requireConfig(file.path));
});
configFileLoaded = true;
}
if (!configFileLoaded) {
return processConfiguredOptions();
} else if (options.length === 1) {
return processConfiguredOptions(options[0]);
} else {
return processConfiguredOptions(options);
}
function processConfiguredOptions(options) {
if (options) {
validateOptions(options);
} else {
options = {};
}
// process Promise
if (typeof options.then === "function") {
return options.then(processConfiguredOptions);
}
// process ES6 default
if (typeof options === "object" && typeof options.default === "object") {
return processConfiguredOptions(options.default);
}
// filter multi-config by name
if (Array.isArray(options) && argv["config-name"]) {
const namedOptions = options.filter(function(opt) {
return opt.name === argv["config-name"];
});
if (namedOptions.length === 0) {
console.error("Configuration with name '" + argv["config-name"] + "' was not found.");
process.exit(-1); // eslint-disable-line
} else if (namedOptions.length === 1) {
return processConfiguredOptions(namedOptions[0]);
}
options = namedOptions;
}
if (Array.isArray(options)) {
options.forEach(processOptions);
} else {
processOptions(options);
}
if (argv.context) {
options.context = path.resolve(argv.context);
}
if (!options.context) {
options.context = process.cwd();
}
if (argv.watch) {
options.watch = true;
}
if (argv["watch-aggregate-timeout"]) {
options.watchOptions = options.watchOptions || {};
options.watchOptions.aggregateTimeout = +argv["watch-aggregate-timeout"];
}
if (typeof argv["watch-poll"] !== "undefined") {
options.watchOptions = options.watchOptions || {};
if (argv["watch-poll"] === "true" || argv["watch-poll"] === "") options.watchOptions.poll = true;
else if (!isNaN(argv["watch-poll"])) options.watchOptions.poll = +argv["watch-poll"];
}
if (argv["watch-stdin"]) {
options.watchOptions = options.watchOptions || {};
options.watchOptions.stdin = true;
options.watch = true;
}
return options;
}
function processOptions(options) {
function ifArg(name, fn, init, finalize) {
const isArray = Array.isArray(argv[name]);
const isSet = typeof argv[name] !== "undefined" && argv[name] !== null;
if (!isArray && !isSet) return;
init && init();
if (isArray) argv[name].forEach(fn);
else if (isSet) fn(argv[name], -1);
finalize && finalize();
}
function ifArgPair(name, fn, init, finalize) {
ifArg(
name,
function(content, idx) {
const i = content.indexOf("=");
if (i < 0) {
return fn(null, content, idx);
} else {
return fn(content.substr(0, i), content.substr(i + 1), idx);
}
},
init,
finalize
);
}
function ifBooleanArg(name, fn) {
ifArg(name, function(bool) {
if (bool) {
fn();
}
});
}
function mapArgToBoolean(name, optionName) {
ifArg(name, function(bool) {
if (bool === true) options[optionName || name] = true;
else if (bool === false) options[optionName || name] = false;
});
}
function loadPlugin(name) {
const loadUtils = require("loader-utils");
let args;
try {
const p = name && name.indexOf("?");
if (p > -1) {
args = loadUtils.parseQuery(name.substring(p));
name = name.substring(0, p);
}
} catch (e) {
console.log("Invalid plugin arguments " + name + " (" + e + ").");
process.exit(-1); // eslint-disable-line
}
let path;
try {
const resolve = require("enhanced-resolve");
path = resolve.sync(process.cwd(), name);
} catch (e) {
console.log("Cannot resolve plugin " + name + ".");
process.exit(-1); // eslint-disable-line
}
let Plugin;
try {
Plugin = require(path);
} catch (e) {
console.log("Cannot load plugin " + name + ". (" + path + ")");
throw e;
}
try {
return new Plugin(args);
} catch (e) {
console.log("Cannot instantiate plugin " + name + ". (" + path + ")");
throw e;
}
}
function ensureObject(parent, name, force) {
if (force || typeof parent[name] !== "object" || parent[name] === null) {
parent[name] = {};
}
}
function ensureArray(parent, name) {
if (!Array.isArray(parent[name])) {
parent[name] = [];
}
}
function addPlugin(options, plugin) {
ensureArray(options, "plugins");
options.plugins.unshift(plugin);
}
ifArg("mode", function(value) {
options.mode = value;
});
ifArgPair(
"entry",
function(name, entry) {
if (typeof options.entry[name] !== "undefined" && options.entry[name] !== null) {
options.entry[name] = [].concat(options.entry[name]).concat(entry);
} else {
options.entry[name] = entry;
}
},
function() {
ensureObject(options, "entry", true);
}
);
function bindRules(arg) {
ifArgPair(
arg,
function(name, binding) {
if (name === null) {
name = binding;
binding += "-loader";
}
const rule = {
test: new RegExp("\\." + name.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + "$"), // eslint-disable-line no-useless-escape
loader: binding
};
if (arg === "module-bind-pre") {
rule.enforce = "pre";
} else if (arg === "module-bind-post") {
rule.enforce = "post";
}
options.module.rules.push(rule);
},
function() {
ensureObject(options, "module");
ensureArray(options.module, "rules");
}
);
}
bindRules("module-bind");
bindRules("module-bind-pre");
bindRules("module-bind-post");
let defineObject;
ifArgPair(
"define",
function(name, value) {
if (name === null) {
name = value;
value = true;
}
defineObject[name] = value;
},
function() {
defineObject = {};
},
function() {
const DefinePlugin = require("webpack").DefinePlugin;
addPlugin(options, new DefinePlugin(defineObject));
}
);
ifArg("output-path", function(value) {
ensureObject(options, "output");
options.output.path = path.resolve(value);
});
ifArg("output-filename", function(value) {
ensureObject(options, "output");
options.output.filename = value;
});
ifArg("output-chunk-filename", function(value) {
ensureObject(options, "output");
options.output.chunkFilename = value;
});
ifArg("output-source-map-filename", function(value) {
ensureObject(options, "output");
options.output.sourceMapFilename = value;
});
ifArg("output-public-path", function(value) {
ensureObject(options, "output");
options.output.publicPath = value;
});
ifArg("output-jsonp-function", function(value) {
ensureObject(options, "output");
options.output.jsonpFunction = value;
});
ifBooleanArg("output-pathinfo", function() {
ensureObject(options, "output");
options.output.pathinfo = true;
});
ifArg("output-library", function(value) {
ensureObject(options, "output");
ensureArray(options.output, "library");
options.output.library.push(value);
});
ifArg("output-library-target", function(value) {
ensureObject(options, "output");
options.output.libraryTarget = value;
});
ifArg("records-input-path", function(value) {
options.recordsInputPath = path.resolve(value);
});
ifArg("records-output-path", function(value) {
options.recordsOutputPath = path.resolve(value);
});
ifArg("records-path", function(value) {
options.recordsPath = path.resolve(value);
});
ifArg("target", function(value) {
options.target = value;
});
mapArgToBoolean("cache");
ifBooleanArg("hot", function() {
const HotModuleReplacementPlugin = require("webpack").HotModuleReplacementPlugin;
addPlugin(options, new HotModuleReplacementPlugin());
});
ifBooleanArg("no-cache", function() {
options.cache = false;
});
ifBooleanArg("debug", function() {
const LoaderOptionsPlugin = require("webpack").LoaderOptionsPlugin;
addPlugin(
options,
new LoaderOptionsPlugin({
debug: true
})
);
});
ifArg("devtool", function(value) {
options.devtool = value;
});
function processResolveAlias(arg, key) {
ifArgPair(arg, function(name, value) {
if (!name) {
throw new Error("--" + arg + " <string>=<string>");
}
ensureObject(options, key);
ensureObject(options[key], "alias");
options[key].alias[name] = value;
});
}
processResolveAlias("resolve-alias", "resolve");
processResolveAlias("resolve-loader-alias", "resolveLoader");
ifArg("resolve-extensions", function(value) {
ensureObject(options, "resolve");
if (Array.isArray(value)) {
options.resolve.extensions = value;
} else {
options.resolve.extensions = value.split(/,\s*/);
}
});
ifArg("optimize-max-chunks", function(value) {
const LimitChunkCountPlugin = require("webpack").optimize.LimitChunkCountPlugin;
addPlugin(
options,
new LimitChunkCountPlugin({
maxChunks: parseInt(value, 10)
})
);
});
ifArg("optimize-min-chunk-size", function(value) {
const MinChunkSizePlugin = require("webpack").optimize.MinChunkSizePlugin;
addPlugin(
options,
new MinChunkSizePlugin({
minChunkSize: parseInt(value, 10)
})
);
});
ifBooleanArg("optimize-minimize", function() {
const LoaderOptionsPlugin = require("webpack").LoaderOptionsPlugin;
addPlugin(
options,
new LoaderOptionsPlugin({
minimize: true
})
);
});
ifArg("prefetch", function(request) {
const PrefetchPlugin = require("webpack").PrefetchPlugin;
addPlugin(options, new PrefetchPlugin(request));
});
ifArg("provide", function(value) {
const idx = value.indexOf("=");
let name;
if (idx >= 0) {
name = value.substr(0, idx);
value = value.substr(idx + 1);
} else {
name = value;
}
const ProvidePlugin = require("webpack").ProvidePlugin;
addPlugin(options, new ProvidePlugin(name, value));
});
ifArg("plugin", function(value) {
addPlugin(options, loadPlugin(value));
});
mapArgToBoolean("bail");
mapArgToBoolean("profile");
if (argv._.length > 0) {
ensureObject(options, "entry", true);
const addTo = function addTo(name, entry) {
if (options.entry[name]) {
if (!Array.isArray(options.entry[name])) {
options.entry[name] = [options.entry[name]];
}
options.entry[name].push(entry);
} else {
options.entry[name] = entry;
}
};
argv._.forEach(function(content) {
const i = content.indexOf("=");
const j = content.indexOf("?");
if (i < 0 || (j >= 0 && j < i)) {
const resolved = path.resolve(content);
if (fs.existsSync(resolved)) {
addTo("main", `${resolved}${fs.statSync(resolved).isDirectory() ? path.sep : ""}`);
} else {
addTo("main", content);
}
} else {
addTo(content.substr(0, i), content.substr(i + 1));
}
});
}
}
};
+33
View File
@@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { WEBPACK_OPTIONS_FLAG } = require("./constants");
exports.cutOffByFlag = (stack, flag) => {
stack = stack.split("\n");
for (let i = 0; i < stack.length; i++) if (stack[i].indexOf(flag) >= 0) stack.length = i;
return stack.join("\n");
};
exports.cutOffWebpackOptions = stack => exports.cutOffByFlag(stack, WEBPACK_OPTIONS_FLAG);
exports.cutOffMultilineMessage = (stack, message) => {
stack = stack.split("\n");
message = message.split("\n");
return stack
.reduce(
(acc, line, idx) => (line === message[idx] || line === `Error: ${message[idx]}` ? acc : acc.concat(line)),
[]
)
.join("\n");
};
exports.cleanUpWebpackOptions = (stack, message) => {
stack = exports.cutOffWebpackOptions(stack);
stack = exports.cutOffMultilineMessage(stack, message);
return stack;
};
+24
View File
@@ -0,0 +1,24 @@
"use strict";
module.exports = function prepareOptions(options, argv) {
argv = argv || {};
options = handleExport(options);
return Array.isArray(options)
? options.map(_options => handleFunction(_options, argv))
: handleFunction(options, argv);
};
function handleExport(options) {
const isES6DefaultExported =
typeof options === "object" && options !== null && typeof options.default !== "undefined";
return isES6DefaultExported ? options.default : options;
}
function handleFunction(options, argv) {
if (typeof options === "function") {
options = options(argv.env, argv);
}
return options;
}
+142
View File
@@ -0,0 +1,142 @@
// based on https://github.com/webpack/webpack/blob/master/bin/webpack.js
/**
* @param {string} command process to run
* @param {string[]} args commandline arguments
* @returns {Promise<void>} promise
*/
const runCommand = (command, args) => {
const cp = require("child_process");
return new Promise((resolve, reject) => {
const executedCommand = cp.spawn(command, args, {
stdio: "inherit",
shell: true
});
executedCommand.on("error", error => {
reject(error);
});
executedCommand.on("exit", code => {
if (code === 0) {
resolve();
} else {
reject();
}
});
});
};
const npmGlobalRoot = () => {
const cp = require("child_process");
return new Promise((resolve, reject) => {
const command = cp.spawn("npm", ["root", "-g"]);
command.on("error", error => reject(error));
command.stdout.on("data", data => resolve(data.toString()));
command.stderr.on("data", data => reject(data));
});
};
const runWhenInstalled = (packages, pathForCmd, ...args) => {
const currentPackage = require(pathForCmd);
const func = currentPackage.default;
if (typeof func !== "function") {
throw new Error(`@webpack-cli/${packages} failed to export a default function`);
}
return func(...args);
};
module.exports = function promptForInstallation(packages, ...args) {
const nameOfPackage = "@webpack-cli/" + packages;
let packageIsInstalled = false;
let pathForCmd;
try {
const path = require("path");
const fs = require("fs");
pathForCmd = path.resolve(process.cwd(), "node_modules", "@webpack-cli", packages);
if (!fs.existsSync(pathForCmd)) {
const globalModules = require("global-modules");
pathForCmd = globalModules + "/@webpack-cli/" + packages;
require.resolve(pathForCmd);
} else {
require.resolve(pathForCmd);
}
packageIsInstalled = true;
} catch (err) {
packageIsInstalled = false;
}
if (!packageIsInstalled) {
const path = require("path");
const fs = require("fs");
const readLine = require("readline");
const isYarn = fs.existsSync(path.resolve(process.cwd(), "yarn.lock"));
const packageManager = isYarn ? "yarn" : "npm";
const options = ["install", "-D", nameOfPackage];
if (isYarn) {
options[0] = "add";
}
if (packages === "init") {
if (isYarn) {
options.splice(1, 1); // remove '-D'
options.splice(0, 0, "global");
} else {
options[1] = "-g";
}
}
const commandToBeRun = `${packageManager} ${options.join(" ")}`;
const question = `Would you like to install ${packages}? (That will run ${commandToBeRun}) (yes/NO) : `;
console.error(`The command moved into a separate package: ${nameOfPackage}`);
const questionInterface = readLine.createInterface({
input: process.stdin,
output: process.stdout
});
questionInterface.question(question, answer => {
questionInterface.close();
switch (answer.toLowerCase()) {
case "y":
case "yes":
case "1": {
runCommand(packageManager, options)
.then(_ => {
if (packages === "init") {
npmGlobalRoot()
.then(root => {
const pathtoInit = path.resolve(root.trim(), "@webpack-cli", "init");
return pathtoInit;
})
.then(pathForInit => {
return require(pathForInit).default(...args);
})
.catch(error => {
console.error(error);
process.exitCode = 1;
});
return;
}
pathForCmd = path.resolve(process.cwd(), "node_modules", "@webpack-cli", packages);
return runWhenInstalled(packages, pathForCmd, ...args);
})
.catch(error => {
console.error(error);
process.exitCode = 1;
});
break;
}
default: {
console.error(`${nameOfPackage} needs to be installed in order to run the command.`);
process.exitCode = 1;
break;
}
}
});
} else {
return runWhenInstalled(packages, pathForCmd, ...args);
}
};
+21
View File
@@ -0,0 +1,21 @@
const webpackConfigurationSchema = require("../config/webpackConfigurationSchema.json");
const validateSchema = require("webpack").validateSchema;
module.exports = function validateOptions(options) {
let error;
try {
const errors = validateSchema(webpackConfigurationSchema, options);
if (errors && errors.length > 0) {
const { WebpackOptionsValidationError } = require("webpack");
error = new WebpackOptionsValidationError(errors);
}
} catch (err) {
error = err;
}
if (error) {
console.error(error.message);
// eslint-disable-next-line no-process-exit
process.exit(-1);
}
};
+15
View File
@@ -0,0 +1,15 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../json5/lib/cli.js" "$@"
ret=$?
else
node "$basedir/../json5/lib/cli.js" "$@"
ret=$?
fi
exit $ret
+17
View File
@@ -0,0 +1,17 @@
@ECHO off
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
"%_prog%" "%dp0%\..\json5\lib\cli.js" %*
ENDLOCAL
EXIT /b %errorlevel%
:find_dp0
SET dp0=%~dp0
EXIT /b
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
& "$basedir/node$exe" "$basedir/../json5/lib/cli.js" $args
$ret=$LASTEXITCODE
} else {
& "node$exe" "$basedir/../json5/lib/cli.js" $args
$ret=$LASTEXITCODE
}
exit $ret
+14
View File
@@ -0,0 +1,14 @@
'use strict';
module.exports = options => {
options = Object.assign({
onlyFirst: false
}, options);
const pattern = [
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
].join('|');
return new RegExp(pattern, options.onlyFirst ? undefined : 'g');
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,85 @@
{
"_from": "ansi-regex@^4.1.0",
"_id": "ansi-regex@4.1.0",
"_inBundle": false,
"_integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"_location": "/webpack-cli/ansi-regex",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "ansi-regex@^4.1.0",
"name": "ansi-regex",
"escapedName": "ansi-regex",
"rawSpec": "^4.1.0",
"saveSpec": null,
"fetchSpec": "^4.1.0"
},
"_requiredBy": [
"/webpack-cli/strip-ansi"
],
"_resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"_shasum": "8b9f8f08cf1acb843756a839ca8c7e3168c51997",
"_spec": "ansi-regex@^4.1.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\strip-ansi",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/chalk/ansi-regex/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Regular expression for matching ANSI escape codes",
"devDependencies": {
"ava": "^0.25.0",
"xo": "^0.23.0"
},
"engines": {
"node": ">=6"
},
"files": [
"index.js"
],
"homepage": "https://github.com/chalk/ansi-regex#readme",
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"text",
"regex",
"regexp",
"re",
"match",
"test",
"find",
"pattern"
],
"license": "MIT",
"name": "ansi-regex",
"repository": {
"type": "git",
"url": "git+https://github.com/chalk/ansi-regex.git"
},
"scripts": {
"test": "xo && ava",
"view-supported": "node fixtures/view-codes.js"
},
"version": "4.1.0"
}
+87
View File
@@ -0,0 +1,87 @@
# ansi-regex [![Build Status](https://travis-ci.org/chalk/ansi-regex.svg?branch=master)](https://travis-ci.org/chalk/ansi-regex)
> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-ansi-regex?utm_source=npm-ansi-regex&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
---
## Install
```
$ npm install ansi-regex
```
## Usage
```js
const ansiRegex = require('ansi-regex');
ansiRegex().test('\u001B[4mcake\u001B[0m');
//=> true
ansiRegex().test('cake');
//=> false
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
//=> ['\u001B[4m', '\u001B[0m']
'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
//=> ['\u001B[4m']
'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
```
## API
### ansiRegex([options])
Returns a regex for matching ANSI escape codes.
#### options
##### onlyFirst
Type: `boolean`<br>
Default: `false` *(Matches any ANSI escape codes in a string)*
Match only the first ANSI escape.
## FAQ
### Why do you test for codes not in the ECMA 48 standard?
Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
## Security
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## License
MIT
+65
View File
@@ -0,0 +1,65 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
# [5.0.0](https://github.com/yargs/cliui/compare/v4.1.0...v5.0.0) (2019-04-10)
### Bug Fixes
* Update wrap-ansi to fix compatibility with latest versions of chalk. ([#60](https://github.com/yargs/cliui/issues/60)) ([7bf79ae](https://github.com/yargs/cliui/commit/7bf79ae))
### BREAKING CHANGES
* Drop support for node < 6.
<a name="4.1.0"></a>
# [4.1.0](https://github.com/yargs/cliui/compare/v4.0.0...v4.1.0) (2018-04-23)
### Features
* add resetOutput method ([#57](https://github.com/yargs/cliui/issues/57)) ([7246902](https://github.com/yargs/cliui/commit/7246902))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/yargs/cliui/compare/v3.2.0...v4.0.0) (2017-12-18)
### Bug Fixes
* downgrades strip-ansi to version 3.0.1 ([#54](https://github.com/yargs/cliui/issues/54)) ([5764c46](https://github.com/yargs/cliui/commit/5764c46))
* set env variable FORCE_COLOR. ([#56](https://github.com/yargs/cliui/issues/56)) ([7350e36](https://github.com/yargs/cliui/commit/7350e36))
### Chores
* drop support for node < 4 ([#53](https://github.com/yargs/cliui/issues/53)) ([b105376](https://github.com/yargs/cliui/commit/b105376))
### Features
* add fallback for window width ([#45](https://github.com/yargs/cliui/issues/45)) ([d064922](https://github.com/yargs/cliui/commit/d064922))
### BREAKING CHANGES
* officially drop support for Node < 4
<a name="3.2.0"></a>
# [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11)
### Bug Fixes
* reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33))
### Features
* adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32))
+14
View File
@@ -0,0 +1,14 @@
Copyright (c) 2015, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+115
View File
@@ -0,0 +1,115 @@
# cliui
[![Build Status](https://travis-ci.org/yargs/cliui.svg)](https://travis-ci.org/yargs/cliui)
[![Coverage Status](https://coveralls.io/repos/yargs/cliui/badge.svg?branch=)](https://coveralls.io/r/yargs/cliui?branch=)
[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui)
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
easily create complex multi-column command-line-interfaces.
## Example
```js
var ui = require('cliui')()
ui.div('Usage: $0 [command] [options]')
ui.div({
text: 'Options:',
padding: [2, 0, 2, 0]
})
ui.div(
{
text: "-f, --file",
width: 20,
padding: [0, 4, 0, 4]
},
{
text: "the file to load." +
chalk.green("(if this description is long it wraps).")
,
width: 20
},
{
text: chalk.red("[required]"),
align: 'right'
}
)
console.log(ui.toString())
```
<img width="500" src="screenshot.png">
## Layout DSL
cliui exposes a simple layout DSL:
If you create a single `ui.div`, passing a string rather than an
object:
* `\n`: characters will be interpreted as new rows.
* `\t`: characters will be interpreted as new columns.
* `\s`: characters will be interpreted as padding.
**as an example...**
```js
var ui = require('./')({
width: 60
})
ui.div(
'Usage: node ./bin/foo.js\n' +
' <regex>\t provide a regex\n' +
' <glob>\t provide a glob\t [required]'
)
console.log(ui.toString())
```
**will output:**
```shell
Usage: node ./bin/foo.js
<regex> provide a regex
<glob> provide a glob [required]
```
## Methods
```js
cliui = require('cliui')
```
### cliui({width: integer})
Specify the maximum width of the UI being generated.
If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`.
### cliui({wrap: boolean})
Enable or disable the wrapping of text in a column.
### cliui.div(column, column, column)
Create a row with any number of columns, a column
can either be a string, or an object with the following
options:
* **text:** some text to place in the column.
* **width:** the width of a column.
* **align:** alignment, `right` or `center`.
* **padding:** `[top, right, bottom, left]`.
* **border:** should a border be placed around the div?
### cliui.span(column, column, column)
Similar to `div`, except the next row will be appended without
a new line being created.
### cliui.resetOutput()
Resets the UI elements of the current cliui instance, maintaining the values
set for `width` and `wrap`.
+324
View File
@@ -0,0 +1,324 @@
var stringWidth = require('string-width')
var stripAnsi = require('strip-ansi')
var wrap = require('wrap-ansi')
var align = {
right: alignRight,
center: alignCenter
}
var top = 0
var right = 1
var bottom = 2
var left = 3
function UI (opts) {
this.width = opts.width
this.wrap = opts.wrap
this.rows = []
}
UI.prototype.span = function () {
var cols = this.div.apply(this, arguments)
cols.span = true
}
UI.prototype.resetOutput = function () {
this.rows = []
}
UI.prototype.div = function () {
if (arguments.length === 0) this.div('')
if (this.wrap && this._shouldApplyLayoutDSL.apply(this, arguments)) {
return this._applyLayoutDSL(arguments[0])
}
var cols = []
for (var i = 0, arg; (arg = arguments[i]) !== undefined; i++) {
if (typeof arg === 'string') cols.push(this._colFromString(arg))
else cols.push(arg)
}
this.rows.push(cols)
return cols
}
UI.prototype._shouldApplyLayoutDSL = function () {
return arguments.length === 1 && typeof arguments[0] === 'string' &&
/[\t\n]/.test(arguments[0])
}
UI.prototype._applyLayoutDSL = function (str) {
var _this = this
var rows = str.split('\n')
var leftColumnWidth = 0
// simple heuristic for layout, make sure the
// second column lines up along the left-hand.
// don't allow the first column to take up more
// than 50% of the screen.
rows.forEach(function (row) {
var columns = row.split('\t')
if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
leftColumnWidth = Math.min(
Math.floor(_this.width * 0.5),
stringWidth(columns[0])
)
}
})
// generate a table:
// replacing ' ' with padding calculations.
// using the algorithmically generated width.
rows.forEach(function (row) {
var columns = row.split('\t')
_this.div.apply(_this, columns.map(function (r, i) {
return {
text: r.trim(),
padding: _this._measurePadding(r),
width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
}
}))
})
return this.rows[this.rows.length - 1]
}
UI.prototype._colFromString = function (str) {
return {
text: str,
padding: this._measurePadding(str)
}
}
UI.prototype._measurePadding = function (str) {
// measure padding without ansi escape codes
var noAnsi = stripAnsi(str)
return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
}
UI.prototype.toString = function () {
var _this = this
var lines = []
_this.rows.forEach(function (row, i) {
_this.rowToString(row, lines)
})
// don't display any lines with the
// hidden flag set.
lines = lines.filter(function (line) {
return !line.hidden
})
return lines.map(function (line) {
return line.text
}).join('\n')
}
UI.prototype.rowToString = function (row, lines) {
var _this = this
var padding
var rrows = this._rasterize(row)
var str = ''
var ts
var width
var wrapWidth
rrows.forEach(function (rrow, r) {
str = ''
rrow.forEach(function (col, c) {
ts = '' // temporary string used during alignment/padding.
width = row[c].width // the width with padding.
wrapWidth = _this._negatePadding(row[c]) // the width without padding.
ts += col
for (var i = 0; i < wrapWidth - stringWidth(col); i++) {
ts += ' '
}
// align the string within its column.
if (row[c].align && row[c].align !== 'left' && _this.wrap) {
ts = align[row[c].align](ts, wrapWidth)
if (stringWidth(ts) < wrapWidth) ts += new Array(width - stringWidth(ts)).join(' ')
}
// apply border and padding to string.
padding = row[c].padding || [0, 0, 0, 0]
if (padding[left]) str += new Array(padding[left] + 1).join(' ')
str += addBorder(row[c], ts, '| ')
str += ts
str += addBorder(row[c], ts, ' |')
if (padding[right]) str += new Array(padding[right] + 1).join(' ')
// if prior row is span, try to render the
// current row on the prior line.
if (r === 0 && lines.length > 0) {
str = _this._renderInline(str, lines[lines.length - 1])
}
})
// remove trailing whitespace.
lines.push({
text: str.replace(/ +$/, ''),
span: row.span
})
})
return lines
}
function addBorder (col, ts, style) {
if (col.border) {
if (/[.']-+[.']/.test(ts)) return ''
else if (ts.trim().length) return style
else return ' '
}
return ''
}
// if the full 'source' can render in
// the target line, do so.
UI.prototype._renderInline = function (source, previousLine) {
var leadingWhitespace = source.match(/^ */)[0].length
var target = previousLine.text
var targetTextWidth = stringWidth(target.trimRight())
if (!previousLine.span) return source
// if we're not applying wrapping logic,
// just always append to the span.
if (!this.wrap) {
previousLine.hidden = true
return target + source
}
if (leadingWhitespace < targetTextWidth) return source
previousLine.hidden = true
return target.trimRight() + new Array(leadingWhitespace - targetTextWidth + 1).join(' ') + source.trimLeft()
}
UI.prototype._rasterize = function (row) {
var _this = this
var i
var rrow
var rrows = []
var widths = this._columnWidths(row)
var wrapped
// word wrap all columns, and create
// a data-structure that is easy to rasterize.
row.forEach(function (col, c) {
// leave room for left and right padding.
col.width = widths[c]
if (_this.wrap) wrapped = wrap(col.text, _this._negatePadding(col), { hard: true }).split('\n')
else wrapped = col.text.split('\n')
if (col.border) {
wrapped.unshift('.' + new Array(_this._negatePadding(col) + 3).join('-') + '.')
wrapped.push("'" + new Array(_this._negatePadding(col) + 3).join('-') + "'")
}
// add top and bottom padding.
if (col.padding) {
for (i = 0; i < (col.padding[top] || 0); i++) wrapped.unshift('')
for (i = 0; i < (col.padding[bottom] || 0); i++) wrapped.push('')
}
wrapped.forEach(function (str, r) {
if (!rrows[r]) rrows.push([])
rrow = rrows[r]
for (var i = 0; i < c; i++) {
if (rrow[i] === undefined) rrow.push('')
}
rrow.push(str)
})
})
return rrows
}
UI.prototype._negatePadding = function (col) {
var wrapWidth = col.width
if (col.padding) wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
if (col.border) wrapWidth -= 4
return wrapWidth
}
UI.prototype._columnWidths = function (row) {
var _this = this
var widths = []
var unset = row.length
var unsetWidth
var remainingWidth = this.width
// column widths can be set in config.
row.forEach(function (col, i) {
if (col.width) {
unset--
widths[i] = col.width
remainingWidth -= col.width
} else {
widths[i] = undefined
}
})
// any unset widths should be calculated.
if (unset) unsetWidth = Math.floor(remainingWidth / unset)
widths.forEach(function (w, i) {
if (!_this.wrap) widths[i] = row[i].width || stringWidth(row[i].text)
else if (w === undefined) widths[i] = Math.max(unsetWidth, _minWidth(row[i]))
})
return widths
}
// calculates the minimum width of
// a column, based on padding preferences.
function _minWidth (col) {
var padding = col.padding || []
var minWidth = 1 + (padding[left] || 0) + (padding[right] || 0)
if (col.border) minWidth += 4
return minWidth
}
function getWindowWidth () {
if (typeof process === 'object' && process.stdout && process.stdout.columns) return process.stdout.columns
}
function alignRight (str, width) {
str = str.trim()
var padding = ''
var strWidth = stringWidth(str)
if (strWidth < width) {
padding = new Array(width - strWidth + 1).join(' ')
}
return padding + str
}
function alignCenter (str, width) {
str = str.trim()
var padding = ''
var strWidth = stringWidth(str.trim())
if (strWidth < width) {
padding = new Array(parseInt((width - strWidth) / 2, 10) + 1).join(' ')
}
return padding + str
}
module.exports = function (opts) {
opts = opts || {}
return new UI({
width: (opts || {}).width || getWindowWidth() || 80,
wrap: typeof opts.wrap === 'boolean' ? opts.wrap : true
})
}
+99
View File
@@ -0,0 +1,99 @@
{
"_from": "cliui@^5.0.0",
"_id": "cliui@5.0.0",
"_inBundle": false,
"_integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"_location": "/webpack-cli/cliui",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cliui@^5.0.0",
"name": "cliui",
"escapedName": "cliui",
"rawSpec": "^5.0.0",
"saveSpec": null,
"fetchSpec": "^5.0.0"
},
"_requiredBy": [
"/webpack-cli/yargs"
],
"_resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"_shasum": "deefcfdb2e800784aa34f46fa08e06851c7bbbc5",
"_spec": "cliui@^5.0.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\yargs",
"author": {
"name": "Ben Coe",
"email": "ben@npmjs.com"
},
"bugs": {
"url": "https://github.com/yargs/cliui/issues"
},
"bundleDependencies": false,
"config": {
"blanket": {
"pattern": [
"index.js"
],
"data-cover-never": [
"node_modules",
"test"
],
"output-reporter": "spec"
}
},
"dependencies": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
},
"deprecated": false,
"description": "easily create complex multi-column command-line-interfaces",
"devDependencies": {
"chai": "^4.2.0",
"chalk": "^2.4.2",
"coveralls": "^3.0.3",
"mocha": "^6.0.2",
"nyc": "^13.3.0",
"standard": "^12.0.1",
"standard-version": "^5.0.2"
},
"engine": {
"node": ">=6"
},
"files": [
"index.js"
],
"homepage": "https://github.com/yargs/cliui#readme",
"keywords": [
"cli",
"command-line",
"layout",
"design",
"console",
"wrap",
"table"
],
"license": "ISC",
"main": "index.js",
"name": "cliui",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/yargs/cliui.git"
},
"scripts": {
"coverage": "nyc --reporter=text-lcov mocha | coveralls",
"pretest": "standard",
"release": "standard-version",
"test": "nyc mocha"
},
"standard": {
"ignore": [
"**/example/**"
],
"globals": [
"it"
]
},
"version": "5.0.0"
}
@@ -0,0 +1,100 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="6.0.5"></a>
## [6.0.5](https://github.com/moxystudio/node-cross-spawn/compare/v6.0.4...v6.0.5) (2018-03-02)
### Bug Fixes
* avoid using deprecated Buffer constructor ([#94](https://github.com/moxystudio/node-cross-spawn/issues/94)) ([d5770df](https://github.com/moxystudio/node-cross-spawn/commit/d5770df)), closes [/nodejs.org/api/deprecations.html#deprecations_dep0005](https://github.com//nodejs.org/api/deprecations.html/issues/deprecations_dep0005)
<a name="6.0.4"></a>
## [6.0.4](https://github.com/moxystudio/node-cross-spawn/compare/v6.0.3...v6.0.4) (2018-01-31)
### Bug Fixes
* fix paths being incorrectly normalized on unix ([06ee3c6](https://github.com/moxystudio/node-cross-spawn/commit/06ee3c6)), closes [#90](https://github.com/moxystudio/node-cross-spawn/issues/90)
<a name="6.0.3"></a>
## [6.0.3](https://github.com/moxystudio/node-cross-spawn/compare/v6.0.2...v6.0.3) (2018-01-23)
<a name="6.0.2"></a>
## [6.0.2](https://github.com/moxystudio/node-cross-spawn/compare/v6.0.1...v6.0.2) (2018-01-23)
<a name="6.0.1"></a>
## [6.0.1](https://github.com/moxystudio/node-cross-spawn/compare/v6.0.0...v6.0.1) (2018-01-23)
<a name="6.0.0"></a>
# [6.0.0](https://github.com/moxystudio/node-cross-spawn/compare/5.1.0...6.0.0) (2018-01-23)
### Bug Fixes
* fix certain arguments not being correctly escaped or causing batch syntax error ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10)), closes [#82](https://github.com/moxystudio/node-cross-spawn/issues/82) [#51](https://github.com/moxystudio/node-cross-spawn/issues/51)
* fix commands as posix relatixe paths not working correctly, e.g.: `./my-command` ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10))
* fix `options` argument being mutated ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10))
* fix commands resolution when PATH was actually Path ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10))
### Features
* improve compliance with node's ENOENT errors ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10))
* improve detection of node's shell option support ([900cf10](https://github.com/moxystudio/node-cross-spawn/commit/900cf10))
### Chores
* upgrade tooling
* upgrate project to es6 (node v4)
### BREAKING CHANGES
* remove support for older nodejs versions, only `node >= 4` is supported
<a name="5.1.0"></a>
## [5.1.0](https://github.com/moxystudio/node-cross-spawn/compare/5.0.1...5.1.0) (2017-02-26)
### Bug Fixes
* fix `options.shell` support for NodeJS [v4.8](https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V4.md#4.8.0)
<a name="5.0.1"></a>
## [5.0.1](https://github.com/moxystudio/node-cross-spawn/compare/5.0.0...5.0.1) (2016-11-04)
### Bug Fixes
* fix `options.shell` support for NodeJS v7
<a name="5.0.0"></a>
# [5.0.0](https://github.com/moxystudio/node-cross-spawn/compare/4.0.2...5.0.0) (2016-10-30)
## Features
* add support for `options.shell`
* improve parsing of shebangs by using [`shebang-command`](https://github.com/kevva/shebang-command) module
## Chores
* refactor some code to make it more clear
* update README caveats
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,94 @@
# cross-spawn
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Build status][appveyor-image]][appveyor-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url] [![Greenkeeper badge][greenkeeper-image]][greenkeeper-url]
[npm-url]:https://npmjs.org/package/cross-spawn
[downloads-image]:http://img.shields.io/npm/dm/cross-spawn.svg
[npm-image]:http://img.shields.io/npm/v/cross-spawn.svg
[travis-url]:https://travis-ci.org/moxystudio/node-cross-spawn
[travis-image]:http://img.shields.io/travis/moxystudio/node-cross-spawn/master.svg
[appveyor-url]:https://ci.appveyor.com/project/satazor/node-cross-spawn
[appveyor-image]:https://img.shields.io/appveyor/ci/satazor/node-cross-spawn/master.svg
[codecov-url]:https://codecov.io/gh/moxystudio/node-cross-spawn
[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/node-cross-spawn/master.svg
[david-dm-url]:https://david-dm.org/moxystudio/node-cross-spawn
[david-dm-image]:https://img.shields.io/david/moxystudio/node-cross-spawn.svg
[david-dm-dev-url]:https://david-dm.org/moxystudio/node-cross-spawn?type=dev
[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/node-cross-spawn.svg
[greenkeeper-image]:https://badges.greenkeeper.io/moxystudio/node-cross-spawn.svg
[greenkeeper-url]:https://greenkeeper.io/
A cross platform solution to node's spawn and spawnSync.
## Installation
`$ npm install cross-spawn`
## Why
Node has issues when using spawn on Windows:
- It ignores [PATHEXT](https://github.com/joyent/node/issues/2318)
- It does not support [shebangs](https://en.wikipedia.org/wiki/Shebang_(Unix))
- Has problems running commands with [spaces](https://github.com/nodejs/node/issues/7367)
- Has problems running commands with posix relative paths (e.g.: `./my-folder/my-executable`)
- Has an [issue](https://github.com/moxystudio/node-cross-spawn/issues/82) with command shims (files in `node_modules/.bin/`), where arguments with quotes and parenthesis would result in [invalid syntax error](https://github.com/moxystudio/node-cross-spawn/blob/e77b8f22a416db46b6196767bcd35601d7e11d54/test/index.test.js#L149)
- No `options.shell` support on node `<v4.8`
All these issues are handled correctly by `cross-spawn`.
There are some known modules, such as [win-spawn](https://github.com/ForbesLindesay/win-spawn), that try to solve this but they are either broken or provide faulty escaping of shell arguments.
## Usage
Exactly the same way as node's [`spawn`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) or [`spawnSync`](https://nodejs.org/api/child_process.html#child_process_child_process_spawnsync_command_args_options), so it's a drop in replacement.
```js
const spawn = require('cross-spawn');
// Spawn NPM asynchronously
const child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
// Spawn NPM synchronously
const result = spawn.sync('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
```
## Caveats
### Using `options.shell` as an alternative to `cross-spawn`
Starting from node `v4.8`, `spawn` has a `shell` option that allows you run commands from within a shell. This new option solves
the [PATHEXT](https://github.com/joyent/node/issues/2318) issue but:
- It's not supported in node `<v4.8`
- You must manually escape the command and arguments which is very error prone, specially when passing user input
- There are a lot of other unresolved issues from the [Why](#why) section that you must take into account
If you are using the `shell` option to spawn a command in a cross platform way, consider using `cross-spawn` instead. You have been warned.
### `options.shell` support
While `cross-spawn` adds support for `options.shell` in node `<v4.8`, all of its enhancements are disabled.
This mimics the Node.js behavior. More specifically, the command and its arguments will not be automatically escaped nor shebang support will be offered. This is by design because if you are using `options.shell` you are probably targeting a specific platform anyway and you don't want things to get into your way.
### Shebangs support
While `cross-spawn` handles shebangs on Windows, its support is limited. More specifically, it just supports `#!/usr/bin/env <program>` where `<program>` must not contain any arguments.
If you would like to have the shebang support improved, feel free to contribute via a pull-request.
Remember to always test your code on Windows!
## Tests
`$ npm test`
`$ npm test -- --watch` during development
## License
Released under the [MIT License](http://www.opensource.org/licenses/mit-license.php).
+39
View File
@@ -0,0 +1,39 @@
'use strict';
const cp = require('child_process');
const parse = require('./lib/parse');
const enoent = require('./lib/enoent');
function spawn(command, args, options) {
// Parse the arguments
const parsed = parse(command, args, options);
// Spawn the child process
const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
// Hook into child process "exit" event to emit an error if the command
// does not exists, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
enoent.hookChildProcess(spawned, parsed);
return spawned;
}
function spawnSync(command, args, options) {
// Parse the arguments
const parsed = parse(command, args, options);
// Spawn the child process
const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
// Analyze if the command does not exist, see: https://github.com/IndigoUnited/node-cross-spawn/issues/16
result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
return result;
}
module.exports = spawn;
module.exports.spawn = spawn;
module.exports.sync = spawnSync;
module.exports._parse = parse;
module.exports._enoent = enoent;
@@ -0,0 +1,59 @@
'use strict';
const isWin = process.platform === 'win32';
function notFoundError(original, syscall) {
return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
code: 'ENOENT',
errno: 'ENOENT',
syscall: `${syscall} ${original.command}`,
path: original.command,
spawnargs: original.args,
});
}
function hookChildProcess(cp, parsed) {
if (!isWin) {
return;
}
const originalEmit = cp.emit;
cp.emit = function (name, arg1) {
// If emitting "exit" event and exit code is 1, we need to check if
// the command exists and emit an "error" instead
// See https://github.com/IndigoUnited/node-cross-spawn/issues/16
if (name === 'exit') {
const err = verifyENOENT(arg1, parsed, 'spawn');
if (err) {
return originalEmit.call(cp, 'error', err);
}
}
return originalEmit.apply(cp, arguments); // eslint-disable-line prefer-rest-params
};
}
function verifyENOENT(status, parsed) {
if (isWin && status === 1 && !parsed.file) {
return notFoundError(parsed.original, 'spawn');
}
return null;
}
function verifyENOENTSync(status, parsed) {
if (isWin && status === 1 && !parsed.file) {
return notFoundError(parsed.original, 'spawnSync');
}
return null;
}
module.exports = {
hookChildProcess,
verifyENOENT,
verifyENOENTSync,
notFoundError,
};
@@ -0,0 +1,125 @@
'use strict';
const path = require('path');
const niceTry = require('nice-try');
const resolveCommand = require('./util/resolveCommand');
const escape = require('./util/escape');
const readShebang = require('./util/readShebang');
const semver = require('semver');
const isWin = process.platform === 'win32';
const isExecutableRegExp = /\.(?:com|exe)$/i;
const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
// `options.shell` is supported in Node ^4.8.0, ^5.7.0 and >= 6.0.0
const supportsShellOption = niceTry(() => semver.satisfies(process.version, '^4.8.0 || ^5.7.0 || >= 6.0.0', true)) || false;
function detectShebang(parsed) {
parsed.file = resolveCommand(parsed);
const shebang = parsed.file && readShebang(parsed.file);
if (shebang) {
parsed.args.unshift(parsed.file);
parsed.command = shebang;
return resolveCommand(parsed);
}
return parsed.file;
}
function parseNonShell(parsed) {
if (!isWin) {
return parsed;
}
// Detect & add support for shebangs
const commandFile = detectShebang(parsed);
// We don't need a shell if the command filename is an executable
const needsShell = !isExecutableRegExp.test(commandFile);
// If a shell is required, use cmd.exe and take care of escaping everything correctly
// Note that `forceShell` is an hidden option used only in tests
if (parsed.options.forceShell || needsShell) {
// Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/`
// The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument
// Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called,
// we need to double escape them
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
// Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar)
// This is necessary otherwise it will always fail with ENOENT in those cases
parsed.command = path.normalize(parsed.command);
// Escape command & arguments
parsed.command = escape.command(parsed.command);
parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
const shellCommand = [parsed.command].concat(parsed.args).join(' ');
parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
parsed.command = process.env.comspec || 'cmd.exe';
parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
}
return parsed;
}
function parseShell(parsed) {
// If node supports the shell option, there's no need to mimic its behavior
if (supportsShellOption) {
return parsed;
}
// Mimic node shell option
// See https://github.com/nodejs/node/blob/b9f6a2dc059a1062776133f3d4fd848c4da7d150/lib/child_process.js#L335
const shellCommand = [parsed.command].concat(parsed.args).join(' ');
if (isWin) {
parsed.command = typeof parsed.options.shell === 'string' ? parsed.options.shell : process.env.comspec || 'cmd.exe';
parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
} else {
if (typeof parsed.options.shell === 'string') {
parsed.command = parsed.options.shell;
} else if (process.platform === 'android') {
parsed.command = '/system/bin/sh';
} else {
parsed.command = '/bin/sh';
}
parsed.args = ['-c', shellCommand];
}
return parsed;
}
function parse(command, args, options) {
// Normalize arguments, similar to nodejs
if (args && !Array.isArray(args)) {
options = args;
args = null;
}
args = args ? args.slice(0) : []; // Clone array to avoid changing the original
options = Object.assign({}, options); // Clone object to avoid changing the original
// Build our parsed object
const parsed = {
command,
args,
options,
file: undefined,
original: {
command,
args,
},
};
// Delegate further parsing to shell or non-shell
return options.shell ? parseShell(parsed) : parseNonShell(parsed);
}
module.exports = parse;
@@ -0,0 +1,45 @@
'use strict';
// See http://www.robvanderwoude.com/escapechars.php
const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
function escapeCommand(arg) {
// Escape meta chars
arg = arg.replace(metaCharsRegExp, '^$1');
return arg;
}
function escapeArgument(arg, doubleEscapeMetaChars) {
// Convert to string
arg = `${arg}`;
// Algorithm below is based on https://qntm.org/cmd
// Sequence of backslashes followed by a double quote:
// double up all the backslashes and escape the double quote
arg = arg.replace(/(\\*)"/g, '$1$1\\"');
// Sequence of backslashes followed by the end of the string
// (which will become a double quote later):
// double up all the backslashes
arg = arg.replace(/(\\*)$/, '$1$1');
// All other backslashes occur literally
// Quote the whole thing:
arg = `"${arg}"`;
// Escape meta chars
arg = arg.replace(metaCharsRegExp, '^$1');
// Double escape meta chars if necessary
if (doubleEscapeMetaChars) {
arg = arg.replace(metaCharsRegExp, '^$1');
}
return arg;
}
module.exports.command = escapeCommand;
module.exports.argument = escapeArgument;
@@ -0,0 +1,32 @@
'use strict';
const fs = require('fs');
const shebangCommand = require('shebang-command');
function readShebang(command) {
// Read the first 150 bytes from the file
const size = 150;
let buffer;
if (Buffer.alloc) {
// Node.js v4.5+ / v5.10+
buffer = Buffer.alloc(size);
} else {
// Old Node.js API
buffer = new Buffer(size);
buffer.fill(0); // zero-fill
}
let fd;
try {
fd = fs.openSync(command, 'r');
fs.readSync(fd, buffer, 0, size, 0);
fs.closeSync(fd);
} catch (e) { /* Empty */ }
// Attempt to extract shebang (null is returned if not a shebang)
return shebangCommand(buffer.toString());
}
module.exports = readShebang;
@@ -0,0 +1,47 @@
'use strict';
const path = require('path');
const which = require('which');
const pathKey = require('path-key')();
function resolveCommandAttempt(parsed, withoutPathExt) {
const cwd = process.cwd();
const hasCustomCwd = parsed.options.cwd != null;
// If a custom `cwd` was specified, we need to change the process cwd
// because `which` will do stat calls but does not support a custom cwd
if (hasCustomCwd) {
try {
process.chdir(parsed.options.cwd);
} catch (err) {
/* Empty */
}
}
let resolved;
try {
resolved = which.sync(parsed.command, {
path: (parsed.options.env || process.env)[pathKey],
pathExt: withoutPathExt ? path.delimiter : undefined,
});
} catch (e) {
/* Empty */
} finally {
process.chdir(cwd);
}
// If we successfully resolved, ensure that an absolute path is returned
// Note that when a custom `cwd` was used, we need to resolve to an absolute path based on it
if (resolved) {
resolved = path.resolve(hasCustomCwd ? parsed.options.cwd : '', resolved);
}
return resolved;
}
function resolveCommand(parsed) {
return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
}
module.exports = resolveCommand;
@@ -0,0 +1,107 @@
{
"_from": "cross-spawn@6.0.5",
"_id": "cross-spawn@6.0.5",
"_inBundle": false,
"_integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
"_location": "/webpack-cli/cross-spawn",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "cross-spawn@6.0.5",
"name": "cross-spawn",
"escapedName": "cross-spawn",
"rawSpec": "6.0.5",
"saveSpec": null,
"fetchSpec": "6.0.5"
},
"_requiredBy": [
"/webpack-cli"
],
"_resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
"_shasum": "4a5ec7c64dfae22c3a14124dbacdee846d80cbc4",
"_spec": "cross-spawn@6.0.5",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli",
"author": {
"name": "André Cruz",
"email": "andre@moxy.studio"
},
"bugs": {
"url": "https://github.com/moxystudio/node-cross-spawn/issues"
},
"bundleDependencies": false,
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"dependencies": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
},
"deprecated": false,
"description": "Cross platform child_process#spawn and child_process#spawnSync",
"devDependencies": {
"@commitlint/cli": "^6.0.0",
"@commitlint/config-conventional": "^6.0.2",
"babel-core": "^6.26.0",
"babel-jest": "^22.1.0",
"babel-preset-moxy": "^2.2.1",
"eslint": "^4.3.0",
"eslint-config-moxy": "^5.0.0",
"husky": "^0.14.3",
"jest": "^22.0.0",
"lint-staged": "^7.0.0",
"mkdirp": "^0.5.1",
"regenerator-runtime": "^0.11.1",
"rimraf": "^2.6.2",
"standard-version": "^4.2.0"
},
"engines": {
"node": ">=4.8"
},
"files": [
"lib"
],
"homepage": "https://github.com/moxystudio/node-cross-spawn",
"keywords": [
"spawn",
"spawnSync",
"windows",
"cross-platform",
"path-ext",
"shebang",
"cmd",
"execute"
],
"license": "MIT",
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
},
"main": "index.js",
"name": "cross-spawn",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/moxystudio/node-cross-spawn.git"
},
"scripts": {
"commitmsg": "commitlint -e $GIT_PARAMS",
"lint": "eslint .",
"precommit": "lint-staged",
"prerelease": "npm t && npm run lint",
"release": "standard-version",
"test": "jest --env node --coverage"
},
"standard-version": {
"scripts": {
"posttag": "git push --follow-tags origin master && npm publish"
}
},
"version": "6.0.5"
}
@@ -0,0 +1,70 @@
<a name="2.1.0"></a>
# 2.1.0 (2016-10-03)
* Fetch new emoji ([7dbe84d](https://github.com/kikobeats/emojis-list/commit/7dbe84d))
<a name="2.0.1"></a>
## 2.0.1 (2016-05-12)
* Fix typo ([3808909](https://github.com/kikobeats/emojis-list/commit/3808909))
<a name="2.0.0"></a>
# 2.0.0 (2016-05-12)
* Add update script ([f846dd6](https://github.com/kikobeats/emojis-list/commit/f846dd6))
* Block dependencies in last version ([1d9e0a5](https://github.com/kikobeats/emojis-list/commit/1d9e0a5))
* Extract main file name ([9ffe7bb](https://github.com/kikobeats/emojis-list/commit/9ffe7bb))
* Remove unnecessary files ([4c34729](https://github.com/kikobeats/emojis-list/commit/4c34729))
* Update docs, special webpack setup is not necessary ([c4aefe9](https://github.com/kikobeats/emojis-list/commit/c4aefe9))
* Update example ([1e2ae03](https://github.com/kikobeats/emojis-list/commit/1e2ae03))
* Update how to generate emojis array ([b56bad9](https://github.com/kikobeats/emojis-list/commit/b56bad9))
* Update main file based in the new interface ([996fccb](https://github.com/kikobeats/emojis-list/commit/996fccb))
<a name="1.0.3"></a>
## 1.0.3 (2016-05-12)
* Add standard as linter ([5e939d6](https://github.com/kikobeats/emojis-list/commit/5e939d6))
* Change interface ([16bc0c0](https://github.com/kikobeats/emojis-list/commit/16bc0c0))
* Generate emoji file ([fbcf8e9](https://github.com/kikobeats/emojis-list/commit/fbcf8e9))
* Remove unnecessary special doc ([2b12bec](https://github.com/kikobeats/emojis-list/commit/2b12bec))
* chore(package): update browserify to version 13.0.1 ([e2c98bf](https://github.com/kikobeats/emojis-list/commit/e2c98bf))
* chore(package): update gulp-header to version 1.8.1 ([28de793](https://github.com/kikobeats/emojis-list/commit/28de793))
<a name="1.0.2"></a>
## 1.0.2 (2016-05-05)
* fixed #2 ([9a6abe7](https://github.com/kikobeats/emojis-list/commit/9a6abe7)), closes [#2](https://github.com/kikobeats/emojis-list/issues/2)
* Fomar using standard ([5202f9f](https://github.com/kikobeats/emojis-list/commit/5202f9f))
* Update badge ([53fad9b](https://github.com/kikobeats/emojis-list/commit/53fad9b))
<a name="1.0.1"></a>
## 1.0.1 (2016-04-13)
* lock versions ([4a5d82e](https://github.com/kikobeats/emojis-list/commit/4a5d82e))
* setup devDependencies ([d1de0fc](https://github.com/kikobeats/emojis-list/commit/d1de0fc))
* update bumped ([9941038](https://github.com/kikobeats/emojis-list/commit/9941038))
* Update package.json ([6c14b74](https://github.com/kikobeats/emojis-list/commit/6c14b74))
* Update README.md ([1d9beeb](https://github.com/kikobeats/emojis-list/commit/1d9beeb))
* Update README.md ([73f215e](https://github.com/kikobeats/emojis-list/commit/73f215e))
* Update tests ([a94f7dc](https://github.com/kikobeats/emojis-list/commit/a94f7dc))
<a name="1.0.0"></a>
# 1.0.0 (2015-05-12)
* first commit ([a65b79d](https://github.com/kikobeats/emojis-list/commit/a65b79d))
* updated ([9f0564c](https://github.com/kikobeats/emojis-list/commit/9f0564c))
@@ -0,0 +1,9 @@
The MIT License (MIT)
Copyright © 2015 Kiko Beats
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
# emojis-list
[![Dependency status](http://img.shields.io/david/Kikobeats/emojis-list.svg?style=flat-square)](https://david-dm.org/Kikobeats/emojis-list)
[![Dev Dependencies Status](http://img.shields.io/david/dev/Kikobeats/emojis-list.svg?style=flat-square)](https://david-dm.org/Kikobeats/emojis-list#info=devDependencies)
[![NPM Status](http://img.shields.io/npm/dm/emojis-list.svg?style=flat-square)](https://www.npmjs.org/package/emojis-list)
[![Donate](https://img.shields.io/badge/donate-paypal-blue.svg?style=flat-square)](https://paypal.me/kikobeats)
> Complete list of standard Unicode Hex Character Code that represent emojis.
**NOTE**: The lists is related with the Unicode Hex Character Code. The representation of the emoji depend of the system. Will be possible that the system don't have all the representations.
## Install
```bash
npm install emojis-list --save
```
If you want to use in the browser (powered by [Browserify](http://browserify.org/)):
```bash
bower install emojis-list --save
```
and later link in your HTML:
```html
<script src="bower_components/emojis-list/dist/emojis-list.js"></script>
```
## Usage
```
var emojis = require('emojis-list');
console.log(emojis[0]);
// => 🀄
```
## Related
* [emojis-unicode](https://github.com/Kikobeats/emojis-unicode) Complete list of standard Unicode codes that represent emojis.
* [emojis-keywords](https://github.com/Kikobeats/emojis-keywords) Complete list of am emoji shortcuts.
* [is-emoji-keyword](https://github.com/Kikobeats/is-emoji-keyword) Check if a word is a emoji shortcut.
* [is-standard-emoji](https://github.com/kikobeats/is-standard-emoji) Simply way to check if a emoji is a standard emoji.
* [trim-emoji](https://github.com/Kikobeats/trim-emoji) Deletes ':' from the begin and the end of an emoji shortcut.
## License
MIT © [Kiko Beats](http://www.kikobeats.com)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,76 @@
{
"_from": "emojis-list@^2.0.0",
"_id": "emojis-list@2.1.0",
"_inBundle": false,
"_integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
"_location": "/webpack-cli/emojis-list",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "emojis-list@^2.0.0",
"name": "emojis-list",
"escapedName": "emojis-list",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/webpack-cli/loader-utils"
],
"_resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
"_shasum": "4daa4d9db00f9819880c79fa457ae5b09a1fd389",
"_spec": "emojis-list@^2.0.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\loader-utils",
"author": {
"name": "Kiko Beats",
"email": "josefrancisco.verdu@gmail.com",
"url": "https://github.com/Kikobeats"
},
"bugs": {
"url": "https://github.com/Kikobeats/emojis-list/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Complete list of standard emojis.",
"devDependencies": {
"acho": "latest",
"browserify": "latest",
"cheerio": "latest",
"got": ">=5 <6",
"gulp": "latest",
"gulp-header": "latest",
"gulp-uglify": "latest",
"gulp-util": "latest",
"standard": "latest",
"vinyl-buffer": "latest",
"vinyl-source-stream": "latest"
},
"engines": {
"node": ">= 0.10"
},
"files": [
"index.js"
],
"homepage": "https://github.com/Kikobeats/emojis-list",
"keywords": [
"archive",
"complete",
"emoji",
"list",
"standard"
],
"license": "MIT",
"main": "./index.js",
"name": "emojis-list",
"repository": {
"type": "git",
"url": "git+https://github.com/kikobeats/emojis-list.git"
},
"scripts": {
"pretest": "standard update.js",
"test": "echo 'YOLO'",
"update": "node update"
},
"version": "2.1.0"
}
@@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,121 @@
# enhanced-resolve
Offers an async require.resolve function. It's highly configurable.
## Features
* plugin system
* provide a custom filesystem
* sync and async node.js filesystems included
## Getting Started
### Install
```sh
# npm
npm install enhanced-resolve
# or Yarn
yarn add enhanced-resolve
```
### Creating a Resolver
The easiest way to create a resolver is to use the `createResolver` function on `ResolveFactory`, along with one of the supplied File System implementations.
```js
const {
NodeJsInputFileSystem,
CachedInputFileSystem,
ResolverFactory
} = require('enhanced-resolve');
// create a resolver
const myResolver = ResolverFactory.createResolver({
// Typical usage will consume the `NodeJsInputFileSystem` + `CachedInputFileSystem`, which wraps the Node.js `fs` wrapper to add resilience + caching.
fileSystem: new CachedInputFileSystem(new NodeJsInputFileSystem(), 4000),
extensions: ['.js', '.json']
/* any other resolver options here. Options/defaults can be seen below */
});
// resolve a file with the new resolver
const context = {};
const resolveContext = {};
const lookupStartPath = '/Users/webpack/some/root/dir';
const request = './path/to-look-up.js';
myResolver.resolve({}, lookupStartPath, request, resolveContext, (err/*Error*/, filepath/*string*/) => {
// Do something with the path
});
```
For more examples creating different types resolvers (sync/async, context, etc) see `lib/node.js`.
#### Resolver Options
| Field | Default | Description |
| ------------------------ | --------------------------- | ---------------------------------------------------------------------------------- |
| alias | [] | A list of module alias configurations or an object which maps key to value |
| aliasFields | [] | A list of alias fields in description files |
| cacheWithContext | true | If unsafe cache is enabled, includes `request.context` in the cache key |
| descriptionFiles | ["package.json"] | A list of description files to read from |
| enforceExtension | false | Enforce that a extension from extensions must be used |
| enforceModuleExtension | false | Enforce that a extension from moduleExtensions must be used |
| extensions | [".js", ".json", ".node"] | A list of extensions which should be tried for files |
| mainFields | ["main"] | A list of main fields in description files |
| mainFiles | ["index"] | A list of main files in directories |
| modules | ["node_modules"] | A list of directories to resolve modules from, can be absolute path or folder name |
| unsafeCache | false | Use this cache object to unsafely cache the successful requests |
| plugins | [] | A list of additional resolve plugins which should be applied |
| symlinks | true | Whether to resolve symlinks to their symlinked location |
| cachePredicate | function() { return true }; | A function which decides whether a request should be cached or not. An object is passed to the function with `path` and `request` properties. |
| moduleExtensions | [] | A list of module extensions which should be tried for modules |
| resolveToContext | false | Resolve to a context instead of a file |
| fileSystem | | The file system which should be used |
| resolver | undefined | A prepared Resolver to which the plugins are attached |
## Plugins
Similar to `webpack`, the core of `enhanced-resolve` functionality is implemented as individual plugins that are executed using [`Tapable`](https://github.com/webpack/tapable). These plugins can extend the functionality of the library, adding other ways for files/contexts to be resolved.
A plugin should be a `class` (or its ES5 equivalent) with an `apply` method. The `apply` method will receive a `resolver` instance, that can be used to hook in to the event system.
### Plugin Boilerplate
```js
class MyResolverPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("MyResolverPlugin", (request, resolveContext, callback) => {
// Any logic you need to create a new `request` can go here
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
}
```
Plugins are executed in a pipeline, and register which event they should be executed before/after. In the example above, `source` is the name of the event that starts the pipeline, and `target` is what event this plugin should fire, which is what continues the execution of the pipeline. For an example of how these different plugin events create a chain, see `lib/ResolverFactory.js`, in the `//// pipeline ////` section.
## Tests
``` javascript
npm test
```
[![Build Status](https://secure.travis-ci.org/webpack/enhanced-resolve.png?branch=master)](http://travis-ci.org/webpack/enhanced-resolve)
## Passing options from webpack
If you are using `webpack`, and you want to pass custom options to `enhanced-resolve`, the options are passed from the `resolve` key of your webpack configuration e.g.:
```
resolve: {
extensions: ['', '.js', '.jsx'],
modules: ['src', 'node_modules'],
plugins: [new DirectoryNamedWebpackPlugin()]
...
},
```
## License
Copyright (c) 2012-2016 Tobias Koppers
MIT (http://www.opensource.org/licenses/mit-license.php)
@@ -0,0 +1,52 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
const getInnerRequest = require("./getInnerRequest");
module.exports = class AliasFieldPlugin {
constructor(source, field, target) {
this.source = source;
this.field = field;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AliasFieldPlugin", (request, resolveContext, callback) => {
if(!request.descriptionFileData) return callback();
const innerRequest = getInnerRequest(resolver, request);
if(!innerRequest) return callback();
const fieldData = DescriptionFileUtils.getField(request.descriptionFileData, this.field);
if(typeof fieldData !== "object") {
if(resolveContext.log) resolveContext.log("Field '" + this.field + "' doesn't contain a valid alias configuration");
return callback();
}
const data1 = fieldData[innerRequest];
const data2 = fieldData[innerRequest.replace(/^\.\//, "")];
const data = typeof data1 !== "undefined" ? data1 : data2;
if(data === innerRequest) return callback();
if(data === undefined) return callback();
if(data === false) {
const ignoreObj = Object.assign({}, request, {
path: false
});
return callback(null, ignoreObj);
}
const obj = Object.assign({}, request, {
path: request.descriptionFileRoot,
request: data
});
resolver.doResolve(target, obj, "aliased from description file " + request.descriptionFilePath + " with mapping '" + innerRequest + "' to '" + data + "'", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other aliasing or raw request
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
}
};
@@ -0,0 +1,56 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
function startsWith(string, searchString) {
const stringLength = string.length;
const searchLength = searchString.length;
// early out if the search length is greater than the search string
if(searchLength > stringLength) {
return false;
}
let index = -1;
while(++index < searchLength) {
if(string.charCodeAt(index) !== searchString.charCodeAt(index)) {
return false;
}
}
return true;
}
module.exports = class AliasPlugin {
constructor(source, options, target) {
this.source = source;
this.options = Array.isArray(options) ? options : [options];
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AliasPlugin", (request, resolveContext, callback) => {
const innerRequest = request.request || request.path;
if(!innerRequest) return callback();
for(const item of this.options) {
if(innerRequest === item.name || (!item.onlyModule && startsWith(innerRequest, item.name + "/"))) {
if(innerRequest !== item.alias && !startsWith(innerRequest, item.alias + "/")) {
const newRequestStr = item.alias + innerRequest.substr(item.name.length);
const obj = Object.assign({}, request, {
request: newRequestStr
});
return resolver.doResolve(target, obj, "aliased with mapping '" + item.name + "': '" + item.alias + "' to '" + newRequestStr + "'", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other aliasing or raw request
if(result === undefined) return callback(null, null);
callback(null, result);
});
}
}
}
return callback();
});
}
};
@@ -0,0 +1,24 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class AppendPlugin {
constructor(source, appending, target) {
this.source = source;
this.appending = appending;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("AppendPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: request.path + this.appending,
relativePath: request.relativePath && (request.relativePath + this.appending)
});
resolver.doResolve(target, obj, this.appending, resolveContext, callback);
});
}
};
@@ -0,0 +1,277 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
class Storage {
constructor(duration) {
this.duration = duration;
this.running = new Map();
this.data = new Map();
this.levels = [];
if(duration > 0) {
this.levels.push(new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set(), new Set());
for(let i = 8000; i < duration; i += 500)
this.levels.push(new Set());
}
this.count = 0;
this.interval = null;
this.needTickCheck = false;
this.nextTick = null;
this.passive = true;
this.tick = this.tick.bind(this);
}
ensureTick() {
if(!this.interval && this.duration > 0 && !this.nextTick)
this.interval = setInterval(this.tick, Math.floor(this.duration / this.levels.length));
}
finished(name, err, result) {
const callbacks = this.running.get(name);
this.running.delete(name);
if(this.duration > 0) {
this.data.set(name, [err, result]);
const levelData = this.levels[0];
this.count -= levelData.size;
levelData.add(name);
this.count += levelData.size;
this.ensureTick();
}
for(let i = 0; i < callbacks.length; i++) {
callbacks[i](err, result);
}
}
finishedSync(name, err, result) {
if(this.duration > 0) {
this.data.set(name, [err, result]);
const levelData = this.levels[0];
this.count -= levelData.size;
levelData.add(name);
this.count += levelData.size;
this.ensureTick();
}
}
provide(name, provider, callback) {
if(typeof name !== "string") {
callback(new TypeError("path must be a string"));
return;
}
let running = this.running.get(name);
if(running) {
running.push(callback);
return;
}
if(this.duration > 0) {
this.checkTicks();
const data = this.data.get(name);
if(data) {
return process.nextTick(() => {
callback.apply(null, data);
});
}
}
this.running.set(name, running = [callback]);
provider(name, (err, result) => {
this.finished(name, err, result);
});
}
provideSync(name, provider) {
if(typeof name !== "string") {
throw new TypeError("path must be a string");
}
if(this.duration > 0) {
this.checkTicks();
const data = this.data.get(name);
if(data) {
if(data[0])
throw data[0];
return data[1];
}
}
let result;
try {
result = provider(name);
} catch(e) {
this.finishedSync(name, e);
throw e;
}
this.finishedSync(name, null, result);
return result;
}
tick() {
const decay = this.levels.pop();
for(let item of decay) {
this.data.delete(item);
}
this.count -= decay.size;
decay.clear();
this.levels.unshift(decay);
if(this.count === 0) {
clearInterval(this.interval);
this.interval = null;
this.nextTick = null;
return true;
} else if(this.nextTick) {
this.nextTick += Math.floor(this.duration / this.levels.length);
const time = new Date().getTime();
if(this.nextTick > time) {
this.nextTick = null;
this.interval = setInterval(this.tick, Math.floor(this.duration / this.levels.length));
return true;
}
} else if(this.passive) {
clearInterval(this.interval);
this.interval = null;
this.nextTick = new Date().getTime() + Math.floor(this.duration / this.levels.length);
} else {
this.passive = true;
}
}
checkTicks() {
this.passive = false;
if(this.nextTick) {
while(!this.tick());
}
}
purge(what) {
if(!what) {
this.count = 0;
clearInterval(this.interval);
this.nextTick = null;
this.data.clear();
this.levels.forEach(level => {
level.clear();
});
} else if(typeof what === "string") {
for(let key of this.data.keys()) {
if(key.startsWith(what))
this.data.delete(key);
}
} else {
for(let i = what.length - 1; i >= 0; i--) {
this.purge(what[i]);
}
}
}
}
module.exports = class CachedInputFileSystem {
constructor(fileSystem, duration) {
this.fileSystem = fileSystem;
this._statStorage = new Storage(duration);
this._readdirStorage = new Storage(duration);
this._readFileStorage = new Storage(duration);
this._readJsonStorage = new Storage(duration);
this._readlinkStorage = new Storage(duration);
this._stat = this.fileSystem.stat ? this.fileSystem.stat.bind(this.fileSystem) : null;
if(!this._stat) this.stat = null;
this._statSync = this.fileSystem.statSync ? this.fileSystem.statSync.bind(this.fileSystem) : null;
if(!this._statSync) this.statSync = null;
this._readdir = this.fileSystem.readdir ? this.fileSystem.readdir.bind(this.fileSystem) : null;
if(!this._readdir) this.readdir = null;
this._readdirSync = this.fileSystem.readdirSync ? this.fileSystem.readdirSync.bind(this.fileSystem) : null;
if(!this._readdirSync) this.readdirSync = null;
this._readFile = this.fileSystem.readFile ? this.fileSystem.readFile.bind(this.fileSystem) : null;
if(!this._readFile) this.readFile = null;
this._readFileSync = this.fileSystem.readFileSync ? this.fileSystem.readFileSync.bind(this.fileSystem) : null;
if(!this._readFileSync) this.readFileSync = null;
if(this.fileSystem.readJson) {
this._readJson = this.fileSystem.readJson.bind(this.fileSystem);
} else if(this.readFile) {
this._readJson = (path, callback) => {
this.readFile(path, (err, buffer) => {
if(err) return callback(err);
let data;
try {
data = JSON.parse(buffer.toString("utf-8"));
} catch(e) {
return callback(e);
}
callback(null, data);
});
};
} else {
this.readJson = null;
}
if(this.fileSystem.readJsonSync) {
this._readJsonSync = this.fileSystem.readJsonSync.bind(this.fileSystem);
} else if(this.readFileSync) {
this._readJsonSync = (path) => {
const buffer = this.readFileSync(path);
const data = JSON.parse(buffer.toString("utf-8"));
return data;
};
} else {
this.readJsonSync = null;
}
this._readlink = this.fileSystem.readlink ? this.fileSystem.readlink.bind(this.fileSystem) : null;
if(!this._readlink) this.readlink = null;
this._readlinkSync = this.fileSystem.readlinkSync ? this.fileSystem.readlinkSync.bind(this.fileSystem) : null;
if(!this._readlinkSync) this.readlinkSync = null;
}
stat(path, callback) {
this._statStorage.provide(path, this._stat, callback);
}
readdir(path, callback) {
this._readdirStorage.provide(path, this._readdir, callback);
}
readFile(path, callback) {
this._readFileStorage.provide(path, this._readFile, callback);
}
readJson(path, callback) {
this._readJsonStorage.provide(path, this._readJson, callback);
}
readlink(path, callback) {
this._readlinkStorage.provide(path, this._readlink, callback);
}
statSync(path) {
return this._statStorage.provideSync(path, this._statSync);
}
readdirSync(path) {
return this._readdirStorage.provideSync(path, this._readdirSync);
}
readFileSync(path) {
return this._readFileStorage.provideSync(path, this._readFileSync);
}
readJsonSync(path) {
return this._readJsonStorage.provideSync(path, this._readJsonSync);
}
readlinkSync(path) {
return this._readlinkStorage.provideSync(path, this._readlinkSync);
}
purge(what) {
this._statStorage.purge(what);
this._readdirStorage.purge(what);
this._readFileStorage.purge(what);
this._readlinkStorage.purge(what);
this._readJsonStorage.purge(what);
}
};
@@ -0,0 +1,27 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const basename = require("./getPaths").basename;
module.exports = class CloneBasenamePlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("CloneBasenamePlugin", (request, resolveContext, callback) => {
const filename = basename(request.path);
const filePath = resolver.join(request.path, filename);
const obj = Object.assign({}, request, {
path: filePath,
relativePath: request.relativePath && resolver.join(request.relativePath, filename)
});
resolver.doResolve(target, obj, "using path: " + filePath, resolveContext, callback);
});
}
};
@@ -0,0 +1,40 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const concord = require("./concord");
const DescriptionFileUtils = require("./DescriptionFileUtils");
const forEachBail = require("./forEachBail");
module.exports = class ConcordExtensionsPlugin {
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ConcordExtensionsPlugin", (request, resolveContext, callback) => {
const concordField = DescriptionFileUtils.getField(request.descriptionFileData, "concord");
if(!concordField) return callback();
const extensions = concord.getExtensions(request.context, concordField);
if(!extensions) return callback();
forEachBail(extensions, (appending, callback) => {
const obj = Object.assign({}, request, {
path: request.path + appending,
relativePath: request.relativePath && (request.relativePath + appending)
});
resolver.doResolve(target, obj, "concord extension: " + appending, resolveContext, callback);
}, (err, result) => {
if(err) return callback(err);
// Don't allow other processing
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
}
};
@@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
const concord = require("./concord");
const DescriptionFileUtils = require("./DescriptionFileUtils");
module.exports = class ConcordMainPlugin {
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ConcordMainPlugin", (request, resolveContext, callback) => {
if(request.path !== request.descriptionFileRoot) return callback();
const concordField = DescriptionFileUtils.getField(request.descriptionFileData, "concord");
if(!concordField) return callback();
const mainModule = concord.getMain(request.context, concordField);
if(!mainModule) return callback();
const obj = Object.assign({}, request, {
request: mainModule
});
const filename = path.basename(request.descriptionFilePath);
return resolver.doResolve(target, obj, "use " + mainModule + " from " + filename, resolveContext, callback);
});
}
};
@@ -0,0 +1,47 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const concord = require("./concord");
const DescriptionFileUtils = require("./DescriptionFileUtils");
const getInnerRequest = require("./getInnerRequest");
module.exports = class ConcordModulesPlugin {
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ConcordModulesPlugin", (request, resolveContext, callback) => {
const innerRequest = getInnerRequest(resolver, request);
if(!innerRequest) return callback();
const concordField = DescriptionFileUtils.getField(request.descriptionFileData, "concord");
if(!concordField) return callback();
const data = concord.matchModule(request.context, concordField, innerRequest);
if(data === innerRequest) return callback();
if(data === undefined) return callback();
if(data === false) {
const ignoreObj = Object.assign({}, request, {
path: false
});
return callback(null, ignoreObj);
}
const obj = Object.assign({}, request, {
path: request.descriptionFileRoot,
request: data
});
resolver.doResolve(target, obj, "aliased from description file " + request.descriptionFilePath + " with mapping '" + innerRequest + "' to '" + data + "'", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other aliasing or raw request
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
}
};
@@ -0,0 +1,48 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const DescriptionFileUtils = require("./DescriptionFileUtils");
module.exports = class DescriptionFilePlugin {
constructor(source, filenames, target) {
this.source = source;
this.filenames = [].concat(filenames);
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("DescriptionFilePlugin", (request, resolveContext, callback) => {
const directory = request.path;
DescriptionFileUtils.loadDescriptionFile(resolver, directory, this.filenames, resolveContext, (err, result) => {
if(err) return callback(err);
if(!result) {
if(resolveContext.missing) {
this.filenames.forEach((filename) => {
resolveContext.missing.add(resolver.join(directory, filename));
});
}
if(resolveContext.log) resolveContext.log("No description file found");
return callback();
}
const relativePath = "." + request.path.substr(result.directory.length).replace(/\\/g, "/");
const obj = Object.assign({}, request, {
descriptionFilePath: result.path,
descriptionFileData: result.content,
descriptionFileRoot: result.directory,
relativePath: relativePath
});
resolver.doResolve(target, obj, "using description file: " + result.path + " (relative path: " + relativePath + ")", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other processing
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
});
}
};
@@ -0,0 +1,96 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
function loadDescriptionFile(resolver, directory, filenames, resolveContext, callback) {
(function findDescriptionFile() {
forEachBail(filenames, (filename, callback) => {
const descriptionFilePath = resolver.join(directory, filename);
if(resolver.fileSystem.readJson) {
resolver.fileSystem.readJson(descriptionFilePath, (err, content) => {
if(err) {
if(typeof err.code !== "undefined") return callback();
return onJson(err);
}
onJson(null, content);
});
} else {
resolver.fileSystem.readFile(descriptionFilePath, (err, content) => {
if(err) return callback();
let json;
try {
json = JSON.parse(content);
} catch(e) {
onJson(e);
}
onJson(null, json);
});
}
function onJson(err, content) {
if(err) {
if(resolveContext.log)
resolveContext.log(descriptionFilePath + " (directory description file): " + err);
else
err.message = descriptionFilePath + " (directory description file): " + err;
return callback(err);
}
callback(null, {
content: content,
directory: directory,
path: descriptionFilePath
});
}
}, (err, result) => {
if(err) return callback(err);
if(result) {
return callback(null, result);
} else {
directory = cdUp(directory);
if(!directory) {
return callback();
} else {
return findDescriptionFile();
}
}
});
}());
}
function getField(content, field) {
if(!content) return undefined;
if(Array.isArray(field)) {
let current = content;
for(let j = 0; j < field.length; j++) {
if(current === null || typeof current !== "object") {
current = null;
break;
}
current = current[field[j]];
}
if(typeof current === "object") {
return current;
}
} else {
if(typeof content[field] === "object") {
return content[field];
}
}
}
function cdUp(directory) {
if(directory === "/") return null;
const i = directory.lastIndexOf("/"),
j = directory.lastIndexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if(p < 0) return null;
return directory.substr(0, p || 1);
}
exports.loadDescriptionFile = loadDescriptionFile;
exports.getField = getField;
exports.cdUp = cdUp;
@@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class DirectoryExistsPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("DirectoryExistsPlugin", (request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const directory = request.path;
fs.stat(directory, (err, stat) => {
if(err || !stat) {
if(resolveContext.missing) resolveContext.missing.add(directory);
if(resolveContext.log) resolveContext.log(directory + " doesn't exist");
return callback();
}
if(!stat.isDirectory()) {
if(resolveContext.missing) resolveContext.missing.add(directory);
if(resolveContext.log) resolveContext.log(directory + " is not a directory");
return callback();
}
resolver.doResolve(target, request, "existing directory", resolveContext, callback);
});
});
}
};
@@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class FileExistsPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
const fs = resolver.fileSystem;
resolver.getHook(this.source).tapAsync("FileExistsPlugin", (request, resolveContext, callback) => {
const file = request.path;
fs.stat(file, (err, stat) => {
if(err || !stat) {
if(resolveContext.missing) resolveContext.missing.add(file);
if(resolveContext.log) resolveContext.log(file + " doesn't exist");
return callback();
}
if(!stat.isFile()) {
if(resolveContext.missing) resolveContext.missing.add(file);
if(resolveContext.log) resolveContext.log(file + " is not a file");
return callback();
}
resolver.doResolve(target, request, "existing file: " + file, resolveContext, callback);
});
});
}
};
@@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class FileKindPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("FileKindPlugin", (request, resolveContext, callback) => {
if(request.directory) return callback();
const obj = Object.assign({}, request);
delete obj.directory;
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};
@@ -0,0 +1,24 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class JoinRequestPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("JoinRequestPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: resolver.join(request.path, request.request),
relativePath: request.relativePath && resolver.join(request.relativePath, request.request),
request: undefined
});
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};
@@ -0,0 +1,28 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class LogInfoPlugin {
constructor(source) {
this.source = source;
}
apply(resolver) {
const source = this.source;
resolver.getHook(this.source).tapAsync("LogInfoPlugin", (request, resolveContext, callback) => {
if(!resolveContext.log) return callback();
const log = resolveContext.log;
const prefix = "[" + source + "] ";
if(request.path) log(prefix + "Resolving in directory: " + request.path);
if(request.request) log(prefix + "Resolving request: " + request.request);
if(request.module) log(prefix + "Request is an module request.");
if(request.directory) log(prefix + "Request is a directory request.");
if(request.query) log(prefix + "Resolving request query: " + request.query);
if(request.descriptionFilePath) log(prefix + "Has description data from " + request.descriptionFilePath);
if(request.relativePath) log(prefix + "Relative path from description file is: " + request.relativePath);
callback();
});
}
};
@@ -0,0 +1,52 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
module.exports = class MainFieldPlugin {
constructor(source, options, target) {
this.source = source;
this.options = options;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("MainFieldPlugin", (request, resolveContext, callback) => {
if(request.path !== request.descriptionFileRoot) return callback();
if(request.alreadyTriedMainField === request.descriptionFilePath) return callback();
const content = request.descriptionFileData;
const filename = path.basename(request.descriptionFilePath);
let mainModule;
const field = this.options.name;
if(Array.isArray(field)) {
let current = content;
for(let j = 0; j < field.length; j++) {
if(current === null || typeof current !== "object") {
current = null;
break;
}
current = current[field[j]];
}
if(typeof current === "string") {
mainModule = current;
}
} else {
if(typeof content[field] === "string") {
mainModule = content[field];
}
}
if(!mainModule) return callback();
if(this.options.forceRelative && !/^\.\.?\//.test(mainModule))
mainModule = "./" + mainModule;
const obj = Object.assign({}, request, {
request: mainModule,
alreadyTriedMainField: request.descriptionFilePath
});
return resolver.doResolve(target, obj, "use " + mainModule + " from " + this.options.name + " in " + filename, resolveContext, callback);
});
}
};
@@ -0,0 +1,37 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class ModuleAppendPlugin {
constructor(source, appending, target) {
this.source = source;
this.appending = appending;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModuleAppendPlugin", (request, resolveContext, callback) => {
const i = request.request.indexOf("/"),
j = request.request.indexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? i : j;
let moduleName, remainingRequest;
if(p < 0) {
moduleName = request.request;
remainingRequest = "";
} else {
moduleName = request.request.substr(0, p);
remainingRequest = request.request.substr(p);
}
if(moduleName === "." || moduleName === "..")
return callback();
const moduleFinalName = moduleName + this.appending;
const obj = Object.assign({}, request, {
request: moduleFinalName + remainingRequest
});
resolver.doResolve(target, obj, "module variation " + moduleFinalName, resolveContext, callback);
});
}
};
@@ -0,0 +1,28 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class ModuleKindPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModuleKindPlugin", (request, resolveContext, callback) => {
if(!request.module) return callback();
const obj = Object.assign({}, request);
delete obj.module;
resolver.doResolve(target, obj, "resolve as module", resolveContext, (err, result) => {
if(err) return callback(err);
// Don't allow other alternatives
if(result === undefined) return callback(null, null);
callback(null, result);
});
});
}
};
@@ -0,0 +1,44 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const forEachBail = require("./forEachBail");
const getPaths = require("./getPaths");
module.exports = class ModulesInHierachicDirectoriesPlugin {
constructor(source, directories, target) {
this.source = source;
this.directories = [].concat(directories);
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModulesInHierachicDirectoriesPlugin", (request, resolveContext, callback) => {
const fs = resolver.fileSystem;
const addrs = getPaths(request.path).paths.map(p => {
return this.directories.map(d => resolver.join(p, d));
}).reduce((array, p) => {
array.push.apply(array, p);
return array;
}, []);
forEachBail(addrs, (addr, callback) => {
fs.stat(addr, (err, stat) => {
if(!err && stat && stat.isDirectory()) {
const obj = Object.assign({}, request, {
path: addr,
request: "./" + request.request
});
const message = "looking for modules in " + addr;
return resolver.doResolve(target, obj, message, resolveContext, callback);
}
if(resolveContext.log) resolveContext.log(addr + " doesn't exist or is not a directory");
if(resolveContext.missing) resolveContext.missing.add(addr);
return callback();
});
}, callback);
});
}
};
@@ -0,0 +1,24 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class ModulesInRootPlugin {
constructor(source, path, target) {
this.source = source;
this.path = path;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ModulesInRootPlugin", (request, resolveContext, callback) => {
const obj = Object.assign({}, request, {
path: this.path,
request: "./" + request.request
});
resolver.doResolve(target, obj, "looking for modules in " + this.path, resolveContext, callback);
});
}
};
@@ -0,0 +1,19 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class NextPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("NextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, null, resolveContext, callback);
});
}
};
@@ -0,0 +1,43 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const fs = require("graceful-fs");
class NodeJsInputFileSystem {
readdir(path, callback) {
fs.readdir(path, (err, files) => {
callback(err, files && files.map(file => {
return file.normalize ? file.normalize("NFC") : file;
}));
});
}
readdirSync(path) {
const files = fs.readdirSync(path);
return files && files.map(file => {
return file.normalize ? file.normalize("NFC") : file;
});
}
}
const fsMethods = [
"stat",
"statSync",
"readFile",
"readFileSync",
"readlink",
"readlinkSync"
];
for(const key of fsMethods) {
Object.defineProperty(NodeJsInputFileSystem.prototype, key, {
configurable: true,
writable: true,
value: fs[key].bind(fs)
});
}
module.exports = NodeJsInputFileSystem;
@@ -0,0 +1,30 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class ParsePlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("ParsePlugin", (request, resolveContext, callback) => {
const parsed = resolver.parse(request.request);
const obj = Object.assign({}, request, parsed);
if(request.query && !parsed.query) {
obj.query = request.query;
}
if(parsed && resolveContext.log) {
if(parsed.module)
resolveContext.log("Parsed request is a module");
if(parsed.directory)
resolveContext.log("Parsed request is a directory");
}
resolver.doResolve(target, obj, null, resolveContext, callback);
});
}
};
@@ -0,0 +1,301 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const util = require("util");
const Tapable = require("tapable/lib/Tapable");
const SyncHook = require("tapable/lib/SyncHook");
const AsyncSeriesBailHook = require("tapable/lib/AsyncSeriesBailHook");
const AsyncSeriesHook = require("tapable/lib/AsyncSeriesHook");
const createInnerContext = require("./createInnerContext");
const REGEXP_NOT_MODULE = /^\.$|^\.[\\\/]|^\.\.$|^\.\.[\/\\]|^\/|^[A-Z]:[\\\/]/i;
const REGEXP_DIRECTORY = /[\/\\]$/i;
const memoryFsJoin = require("memory-fs/lib/join");
const memoizedJoin = new Map();
const memoryFsNormalize = require("memory-fs/lib/normalize");
function withName(name, hook) {
hook.name = name;
return hook;
}
function toCamelCase(str) {
return str.replace(/-([a-z])/g, str => str.substr(1).toUpperCase());
}
const deprecatedPushToMissing = util.deprecate((set, item) => {
set.add(item);
}, "Resolver: 'missing' is now a Set. Use add instead of push.");
const deprecatedResolveContextInCallback = util.deprecate((x) => {
return x;
}, "Resolver: The callback argument was splitted into resolveContext and callback.");
const deprecatedHookAsString = util.deprecate((x) => {
return x;
}, "Resolver#doResolve: The type arguments (string) is now a hook argument (Hook). Pass a reference to the hook instead.");
class Resolver extends Tapable {
constructor(fileSystem) {
super();
this.fileSystem = fileSystem;
this.hooks = {
resolveStep: withName("resolveStep", new SyncHook(["hook", "request"])),
noResolve: withName("noResolve", new SyncHook(["request", "error"])),
resolve: withName("resolve", new AsyncSeriesBailHook(["request", "resolveContext"])),
result: new AsyncSeriesHook(["result", "resolveContext"])
};
this._pluginCompat.tap("Resolver: before/after", options => {
if(/^before-/.test(options.name)) {
options.name = options.name.substr(7);
options.stage = -10;
} else if(/^after-/.test(options.name)) {
options.name = options.name.substr(6);
options.stage = 10;
}
});
this._pluginCompat.tap("Resolver: step hooks", options => {
const name = options.name;
const stepHook = !/^resolve(-s|S)tep$|^no(-r|R)esolve$/.test(name);
if(stepHook) {
options.async = true;
this.ensureHook(name);
const fn = options.fn;
options.fn = (request, resolverContext, callback) => {
const innerCallback = (err, result) => {
if(err) return callback(err);
if(result !== undefined) return callback(null, result);
callback();
};
for(const key in resolverContext) {
innerCallback[key] = resolverContext[key];
}
fn.call(this, request, innerCallback);
};
}
});
}
ensureHook(name) {
if(typeof name !== "string") return name;
name = toCamelCase(name);
if(/^before/.test(name)) {
return this.ensureHook(name[6].toLowerCase() + name.substr(7)).withOptions({
stage: -10
});
}
if(/^after/.test(name)) {
return this.ensureHook(name[5].toLowerCase() + name.substr(6)).withOptions({
stage: 10
});
}
const hook = this.hooks[name];
if(!hook) {
return this.hooks[name] = withName(name, new AsyncSeriesBailHook(["request", "resolveContext"]));
}
return hook;
}
getHook(name) {
if(typeof name !== "string") return name;
name = toCamelCase(name);
if(/^before/.test(name)) {
return this.getHook(name[6].toLowerCase() + name.substr(7)).withOptions({
stage: -10
});
}
if(/^after/.test(name)) {
return this.getHook(name[5].toLowerCase() + name.substr(6)).withOptions({
stage: 10
});
}
const hook = this.hooks[name];
if(!hook) {
throw new Error(`Hook ${name} doesn't exist`);
}
return hook;
}
resolveSync(context, path, request) {
let err, result, sync = false;
this.resolve(context, path, request, {}, (e, r) => {
err = e;
result = r;
sync = true;
});
if(!sync) throw new Error("Cannot 'resolveSync' because the fileSystem is not sync. Use 'resolve'!");
if(err) throw err;
return result;
}
resolve(context, path, request, resolveContext, callback) {
// TODO remove in enhanced-resolve 5
// For backward compatiblity START
if(typeof callback !== "function") {
callback = deprecatedResolveContextInCallback(resolveContext);
// resolveContext is a function containing additional properties
// It's now used for resolveContext and callback
}
// END
const obj = {
context: context,
path: path,
request: request
};
const message = "resolve '" + request + "' in '" + path + "'";
// Try to resolve assuming there is no error
// We don't log stuff in this case
return this.doResolve(this.hooks.resolve, obj, message, {
missing: resolveContext.missing,
stack: resolveContext.stack
}, (err, result) => {
if(!err && result) {
return callback(null, result.path === false ? false : result.path + (result.query || ""), result);
}
const localMissing = new Set();
// TODO remove in enhanced-resolve 5
localMissing.push = item => deprecatedPushToMissing(localMissing, item);
const log = [];
return this.doResolve(this.hooks.resolve, obj, message, {
log: msg => {
if(resolveContext.log) {
resolveContext.log(msg);
}
log.push(msg);
},
missing: localMissing,
stack: resolveContext.stack
}, (err, result) => {
if(err) return callback(err);
const error = new Error("Can't " + message);
error.details = log.join("\n");
error.missing = Array.from(localMissing);
this.hooks.noResolve.call(obj, error);
return callback(error);
});
});
}
doResolve(hook, request, message, resolveContext, callback) {
// TODO remove in enhanced-resolve 5
// For backward compatiblity START
if(typeof callback !== "function") {
callback = deprecatedResolveContextInCallback(resolveContext);
// resolveContext is a function containing additional properties
// It's now used for resolveContext and callback
}
if(typeof hook === "string") {
const name = toCamelCase(hook);
hook = deprecatedHookAsString(this.hooks[name]);
if(!hook) {
throw new Error(`Hook "${name}" doesn't exist`);
}
}
// END
if(typeof callback !== "function") throw new Error("callback is not a function " + Array.from(arguments));
if(!resolveContext) throw new Error("resolveContext is not an object " + Array.from(arguments));
const stackLine = hook.name + ": (" + request.path + ") " +
(request.request || "") + (request.query || "") +
(request.directory ? " directory" : "") +
(request.module ? " module" : "");
let newStack;
if(resolveContext.stack) {
newStack = new Set(resolveContext.stack);
if(resolveContext.stack.has(stackLine)) {
// Prevent recursion
const recursionError = new Error("Recursion in resolving\nStack:\n " + Array.from(newStack).join("\n "));
recursionError.recursion = true;
if(resolveContext.log) resolveContext.log("abort resolving because of recursion");
return callback(recursionError);
}
newStack.add(stackLine);
} else {
newStack = new Set([stackLine]);
}
this.hooks.resolveStep.call(hook, request);
if(hook.isUsed()) {
const innerContext = createInnerContext({
log: resolveContext.log,
missing: resolveContext.missing,
stack: newStack
}, message);
return hook.callAsync(request, innerContext, (err, result) => {
if(err) return callback(err);
if(result) return callback(null, result);
callback();
});
} else {
callback();
}
}
parse(identifier) {
if(identifier === "") return null;
const part = {
request: "",
query: "",
module: false,
directory: false,
file: false
};
const idxQuery = identifier.indexOf("?");
if(idxQuery === 0) {
part.query = identifier;
} else if(idxQuery > 0) {
part.request = identifier.slice(0, idxQuery);
part.query = identifier.slice(idxQuery);
} else {
part.request = identifier;
}
if(part.request) {
part.module = this.isModule(part.request);
part.directory = this.isDirectory(part.request);
if(part.directory) {
part.request = part.request.substr(0, part.request.length - 1);
}
}
return part;
}
isModule(path) {
return !REGEXP_NOT_MODULE.test(path);
}
isDirectory(path) {
return REGEXP_DIRECTORY.test(path);
}
join(path, request) {
let cacheEntry;
let pathCache = memoizedJoin.get(path);
if(typeof pathCache === "undefined") {
memoizedJoin.set(path, pathCache = new Map());
} else {
cacheEntry = pathCache.get(request);
if(typeof cacheEntry !== "undefined")
return cacheEntry;
}
cacheEntry = memoryFsJoin(path, request);
pathCache.set(request, cacheEntry);
return cacheEntry;
}
normalize(path) {
return memoryFsNormalize(path);
}
}
module.exports = Resolver;
@@ -0,0 +1,301 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Resolver = require("./Resolver");
const SyncAsyncFileSystemDecorator = require("./SyncAsyncFileSystemDecorator");
const ParsePlugin = require("./ParsePlugin");
const DescriptionFilePlugin = require("./DescriptionFilePlugin");
const NextPlugin = require("./NextPlugin");
const TryNextPlugin = require("./TryNextPlugin");
const ModuleKindPlugin = require("./ModuleKindPlugin");
const FileKindPlugin = require("./FileKindPlugin");
const JoinRequestPlugin = require("./JoinRequestPlugin");
const ModulesInHierachicDirectoriesPlugin = require("./ModulesInHierachicDirectoriesPlugin");
const ModulesInRootPlugin = require("./ModulesInRootPlugin");
const AliasPlugin = require("./AliasPlugin");
const AliasFieldPlugin = require("./AliasFieldPlugin");
const ConcordExtensionsPlugin = require("./ConcordExtensionsPlugin");
const ConcordMainPlugin = require("./ConcordMainPlugin");
const ConcordModulesPlugin = require("./ConcordModulesPlugin");
const DirectoryExistsPlugin = require("./DirectoryExistsPlugin");
const FileExistsPlugin = require("./FileExistsPlugin");
const SymlinkPlugin = require("./SymlinkPlugin");
const MainFieldPlugin = require("./MainFieldPlugin");
const UseFilePlugin = require("./UseFilePlugin");
const AppendPlugin = require("./AppendPlugin");
const ResultPlugin = require("./ResultPlugin");
const ModuleAppendPlugin = require("./ModuleAppendPlugin");
const UnsafeCachePlugin = require("./UnsafeCachePlugin");
exports.createResolver = function(options) {
//// OPTIONS ////
// A list of directories to resolve modules from, can be absolute path or folder name
let modules = options.modules || ["node_modules"];
// A list of description files to read from
const descriptionFiles = options.descriptionFiles || ["package.json"];
// A list of additional resolve plugins which should be applied
// The slice is there to create a copy, because otherwise pushing into plugins
// changes the original options.plugins array, causing duplicate plugins
const plugins = (options.plugins && options.plugins.slice()) || [];
// A list of main fields in description files
let mainFields = options.mainFields || ["main"];
// A list of alias fields in description files
const aliasFields = options.aliasFields || [];
// A list of main files in directories
const mainFiles = options.mainFiles || ["index"];
// A list of extensions which should be tried for files
let extensions = options.extensions || [".js", ".json", ".node"];
// Enforce that a extension from extensions must be used
const enforceExtension = options.enforceExtension || false;
// A list of module extensions which should be tried for modules
let moduleExtensions = options.moduleExtensions || [];
// Enforce that a extension from moduleExtensions must be used
const enforceModuleExtension = options.enforceModuleExtension || false;
// A list of module alias configurations or an object which maps key to value
let alias = options.alias || [];
// Resolve symlinks to their symlinked location
const symlinks = typeof options.symlinks !== "undefined" ? options.symlinks : true;
// Resolve to a context instead of a file
const resolveToContext = options.resolveToContext || false;
// Use this cache object to unsafely cache the successful requests
let unsafeCache = options.unsafeCache || false;
// Whether or not the unsafeCache should include request context as part of the cache key.
const cacheWithContext = typeof options.cacheWithContext !== "undefined" ? options.cacheWithContext : true;
// Enable concord description file instructions
const enableConcord = options.concord || false;
// A function which decides whether a request should be cached or not.
// an object is passed with `path` and `request` properties.
const cachePredicate = options.cachePredicate || function() {
return true;
};
// The file system which should be used
const fileSystem = options.fileSystem;
// Use only the sync constiants of the file system calls
const useSyncFileSystemCalls = options.useSyncFileSystemCalls;
// A prepared Resolver to which the plugins are attached
let resolver = options.resolver;
//// options processing ////
if(!resolver) {
resolver = new Resolver(useSyncFileSystemCalls ? new SyncAsyncFileSystemDecorator(fileSystem) : fileSystem);
}
extensions = [].concat(extensions);
moduleExtensions = [].concat(moduleExtensions);
modules = mergeFilteredToArray([].concat(modules), item => {
return !isAbsolutePath(item);
});
mainFields = mainFields.map(item => {
if(typeof item === "string" || Array.isArray(item)) {
item = {
name: item,
forceRelative: true
};
}
return item;
});
if(typeof alias === "object" && !Array.isArray(alias)) {
alias = Object.keys(alias).map(key => {
let onlyModule = false;
let obj = alias[key];
if(/\$$/.test(key)) {
onlyModule = true;
key = key.substr(0, key.length - 1);
}
if(typeof obj === "string") {
obj = {
alias: obj
};
}
obj = Object.assign({
name: key,
onlyModule: onlyModule
}, obj);
return obj;
});
}
if(unsafeCache && typeof unsafeCache !== "object") {
unsafeCache = {};
}
//// pipeline ////
resolver.ensureHook("resolve");
resolver.ensureHook("parsedResolve");
resolver.ensureHook("describedResolve");
resolver.ensureHook("rawModule");
resolver.ensureHook("module");
resolver.ensureHook("relative");
resolver.ensureHook("describedRelative");
resolver.ensureHook("directory");
resolver.ensureHook("existingDirectory");
resolver.ensureHook("undescribedRawFile");
resolver.ensureHook("rawFile");
resolver.ensureHook("file");
resolver.ensureHook("existingFile");
resolver.ensureHook("resolved");
// resolve
if(unsafeCache) {
plugins.push(new UnsafeCachePlugin("resolve", cachePredicate, unsafeCache, cacheWithContext, "new-resolve"));
plugins.push(new ParsePlugin("new-resolve", "parsed-resolve"));
} else {
plugins.push(new ParsePlugin("resolve", "parsed-resolve"));
}
// parsed-resolve
plugins.push(new DescriptionFilePlugin("parsed-resolve", descriptionFiles, "described-resolve"));
plugins.push(new NextPlugin("after-parsed-resolve", "described-resolve"));
// described-resolve
if(alias.length > 0)
plugins.push(new AliasPlugin("described-resolve", alias, "resolve"));
if(enableConcord) {
plugins.push(new ConcordModulesPlugin("described-resolve", {}, "resolve"));
}
aliasFields.forEach(item => {
plugins.push(new AliasFieldPlugin("described-resolve", item, "resolve"));
});
plugins.push(new ModuleKindPlugin("after-described-resolve", "raw-module"));
plugins.push(new JoinRequestPlugin("after-described-resolve", "relative"));
// raw-module
moduleExtensions.forEach(item => {
plugins.push(new ModuleAppendPlugin("raw-module", item, "module"));
});
if(!enforceModuleExtension)
plugins.push(new TryNextPlugin("raw-module", null, "module"));
// module
modules.forEach(item => {
if(Array.isArray(item))
plugins.push(new ModulesInHierachicDirectoriesPlugin("module", item, "resolve"));
else
plugins.push(new ModulesInRootPlugin("module", item, "resolve"));
});
// relative
plugins.push(new DescriptionFilePlugin("relative", descriptionFiles, "described-relative"));
plugins.push(new NextPlugin("after-relative", "described-relative"));
// described-relative
plugins.push(new FileKindPlugin("described-relative", "raw-file"));
plugins.push(new TryNextPlugin("described-relative", "as directory", "directory"));
// directory
plugins.push(new DirectoryExistsPlugin("directory", "existing-directory"));
if(resolveToContext) {
// existing-directory
plugins.push(new NextPlugin("existing-directory", "resolved"));
} else {
// existing-directory
if(enableConcord) {
plugins.push(new ConcordMainPlugin("existing-directory", {}, "resolve"));
}
mainFields.forEach(item => {
plugins.push(new MainFieldPlugin("existing-directory", item, "resolve"));
});
mainFiles.forEach(item => {
plugins.push(new UseFilePlugin("existing-directory", item, "undescribed-raw-file"));
});
// undescribed-raw-file
plugins.push(new DescriptionFilePlugin("undescribed-raw-file", descriptionFiles, "raw-file"));
plugins.push(new NextPlugin("after-undescribed-raw-file", "raw-file"));
// raw-file
if(!enforceExtension) {
plugins.push(new TryNextPlugin("raw-file", "no extension", "file"));
}
if(enableConcord) {
plugins.push(new ConcordExtensionsPlugin("raw-file", {}, "file"));
}
extensions.forEach(item => {
plugins.push(new AppendPlugin("raw-file", item, "file"));
});
// file
if(alias.length > 0)
plugins.push(new AliasPlugin("file", alias, "resolve"));
if(enableConcord) {
plugins.push(new ConcordModulesPlugin("file", {}, "resolve"));
}
aliasFields.forEach(item => {
plugins.push(new AliasFieldPlugin("file", item, "resolve"));
});
if(symlinks)
plugins.push(new SymlinkPlugin("file", "relative"));
plugins.push(new FileExistsPlugin("file", "existing-file"));
// existing-file
plugins.push(new NextPlugin("existing-file", "resolved"));
}
// resolved
plugins.push(new ResultPlugin(resolver.hooks.resolved));
//// RESOLVER ////
plugins.forEach(plugin => {
plugin.apply(resolver);
});
return resolver;
};
function mergeFilteredToArray(array, filter) {
return array.reduce((array, item) => {
if(filter(item)) {
const lastElement = array[array.length - 1];
if(Array.isArray(lastElement)) {
lastElement.push(item);
} else {
array.push([item]);
}
return array;
} else {
array.push(item);
return array;
}
}, []);
}
function isAbsolutePath(path) {
return /^[A-Z]:|^\//.test(path);
}
@@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class ResultPlugin {
constructor(source) {
this.source = source;
}
apply(resolver) {
this.source.tapAsync("ResultPlugin", (request, resolverContext, callback) => {
const obj = Object.assign({}, request);
if(resolverContext.log) resolverContext.log("reporting result " + obj.path);
resolver.hooks.result.callAsync(obj, resolverContext, err => {
if(err) return callback(err);
callback(null, obj);
});
});
}
};
@@ -0,0 +1,49 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const getPaths = require("./getPaths");
const forEachBail = require("./forEachBail");
module.exports = class SymlinkPlugin {
constructor(source, target) {
this.source = source;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
const fs = resolver.fileSystem;
resolver.getHook(this.source).tapAsync("SymlinkPlugin", (request, resolveContext, callback) => {
const pathsResult = getPaths(request.path);
const pathSeqments = pathsResult.seqments;
const paths = pathsResult.paths;
let containsSymlink = false;
forEachBail.withIndex(paths, (path, idx, callback) => {
fs.readlink(path, (err, result) => {
if(!err && result) {
pathSeqments[idx] = result;
containsSymlink = true;
// Shortcut when absolute symlink found
if(/^(\/|[a-zA-Z]:($|\\))/.test(result))
return callback(null, idx);
}
callback();
});
}, (err, idx) => {
if(!containsSymlink) return callback();
const resultSeqments = typeof idx === "number" ? pathSeqments.slice(0, idx + 1) : pathSeqments.slice();
const result = resultSeqments.reverse().reduce((a, b) => {
return resolver.join(a, b);
});
const obj = Object.assign({}, request, {
path: result
});
resolver.doResolve(target, obj, "resolved symlink to " + result, resolveContext, callback);
});
});
}
};
@@ -0,0 +1,65 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
function SyncAsyncFileSystemDecorator(fs) {
this.fs = fs;
if(fs.statSync) {
this.stat = function(arg, callback) {
let result;
try {
result = fs.statSync(arg);
} catch(e) {
return callback(e);
}
callback(null, result);
};
}
if(fs.readdirSync) {
this.readdir = function(arg, callback) {
let result;
try {
result = fs.readdirSync(arg);
} catch(e) {
return callback(e);
}
callback(null, result);
};
}
if(fs.readFileSync) {
this.readFile = function(arg, callback) {
let result;
try {
result = fs.readFileSync(arg);
} catch(e) {
return callback(e);
}
callback(null, result);
};
}
if(fs.readlinkSync) {
this.readlink = function(arg, callback) {
let result;
try {
result = fs.readlinkSync(arg);
} catch(e) {
return callback(e);
}
callback(null, result);
};
}
if(fs.readJsonSync) {
this.readJson = function(arg, callback) {
let result;
try {
result = fs.readJsonSync(arg);
} catch(e) {
return callback(e);
}
callback(null, result);
};
}
}
module.exports = SyncAsyncFileSystemDecorator;
@@ -0,0 +1,20 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class TryNextPlugin {
constructor(source, message, target) {
this.source = source;
this.message = message;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("TryNextPlugin", (request, resolveContext, callback) => {
resolver.doResolve(target, request, this.message, resolveContext, callback);
});
}
};
@@ -0,0 +1,41 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
function getCacheId(request, withContext) {
return JSON.stringify({
context: withContext ? request.context : "",
path: request.path,
query: request.query,
request: request.request
});
}
module.exports = class UnsafeCachePlugin {
constructor(source, filterPredicate, cache, withContext, target) {
this.source = source;
this.filterPredicate = filterPredicate;
this.withContext = withContext;
this.cache = cache || {};
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("UnsafeCachePlugin", (request, resolveContext, callback) => {
if(!this.filterPredicate(request)) return callback();
const cacheId = getCacheId(request, this.withContext);
const cacheEntry = this.cache[cacheId];
if(cacheEntry) {
return callback(null, cacheEntry);
}
resolver.doResolve(target, request, null, resolveContext, (err, result) => {
if(err) return callback(err);
if(result) return callback(null, this.cache[cacheId] = result);
callback();
});
});
}
};
@@ -0,0 +1,25 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = class UseFilePlugin {
constructor(source, filename, target) {
this.source = source;
this.filename = filename;
this.target = target;
}
apply(resolver) {
const target = resolver.ensureHook(this.target);
resolver.getHook(this.source).tapAsync("UseFilePlugin", (request, resolveContext, callback) => {
const filePath = resolver.join(request.path, this.filename);
const obj = Object.assign({}, request, {
path: filePath,
relativePath: request.relativePath && resolver.join(request.relativePath, this.filename)
});
resolver.doResolve(target, obj, "using path: " + filePath, resolveContext, callback);
});
}
};
@@ -0,0 +1,195 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const globToRegExp = require("./globToRegExp").globToRegExp;
function parseType(type) {
const items = type.split("+");
const t = items.shift();
return {
type: t === "*" ? null : t,
features: items
};
}
function isTypeMatched(baseType, testedType) {
if(typeof baseType === "string") baseType = parseType(baseType);
if(typeof testedType === "string") testedType = parseType(testedType);
if(testedType.type && testedType.type !== baseType.type) return false;
return testedType.features.every(requiredFeature => {
return baseType.features.indexOf(requiredFeature) >= 0;
});
}
function isResourceTypeMatched(baseType, testedType) {
baseType = baseType.split("/");
testedType = testedType.split("/");
if(baseType.length !== testedType.length) return false;
for(let i = 0; i < baseType.length; i++) {
if(!isTypeMatched(baseType[i], testedType[i]))
return false;
}
return true;
}
function isResourceTypeSupported(context, type) {
return context.supportedResourceTypes && context.supportedResourceTypes.some(supportedType => {
return isResourceTypeMatched(supportedType, type);
});
}
function isEnvironment(context, env) {
return context.environments && context.environments.every(environment => {
return isTypeMatched(environment, env);
});
}
const globCache = {};
function getGlobRegExp(glob) {
const regExp = globCache[glob] || (globCache[glob] = globToRegExp(glob));
return regExp;
}
function matchGlob(glob, relativePath) {
const regExp = getGlobRegExp(glob);
return regExp.exec(relativePath);
}
function isGlobMatched(glob, relativePath) {
return !!matchGlob(glob, relativePath);
}
function isConditionMatched(context, condition) {
const items = condition.split("|");
return items.some(function testFn(item) {
item = item.trim();
const inverted = /^!/.test(item);
if(inverted) return !testFn(item.substr(1));
if(/^[a-z]+:/.test(item)) {
// match named condition
const match = /^([a-z]+):\s*/.exec(item);
const value = item.substr(match[0].length);
const name = match[1];
switch(name) {
case "referrer":
return isGlobMatched(value, context.referrer);
default:
return false;
}
} else if(item.indexOf("/") >= 0) {
// match supported type
return isResourceTypeSupported(context, item);
} else {
// match environment
return isEnvironment(context, item);
}
});
}
function isKeyMatched(context, key) {
while(true) { //eslint-disable-line
const match = /^\[([^\]]+)\]\s*/.exec(key);
if(!match) return key;
key = key.substr(match[0].length);
const condition = match[1];
if(!isConditionMatched(context, condition)) {
return false;
}
}
}
function getField(context, configuration, field) {
let value;
Object.keys(configuration).forEach(key => {
const pureKey = isKeyMatched(context, key);
if(pureKey === field) {
value = configuration[key];
}
});
return value;
}
function getMain(context, configuration) {
return getField(context, configuration, "main");
}
function getExtensions(context, configuration) {
return getField(context, configuration, "extensions");
}
function matchModule(context, configuration, request) {
const modulesField = getField(context, configuration, "modules");
if(!modulesField) return request;
let newRequest = request;
const keys = Object.keys(modulesField);
let iteration = 0;
let match;
let index;
for(let i = 0; i < keys.length; i++) {
const key = keys[i];
const pureKey = isKeyMatched(context, key);
match = matchGlob(pureKey, newRequest);
if(match) {
const value = modulesField[key];
if(typeof value !== "string") {
return value;
} else if(/^\(.+\)$/.test(pureKey)) {
newRequest = newRequest.replace(getGlobRegExp(pureKey), value);
} else {
index = 1;
newRequest = value.replace(/(\/?\*)?\*/g, replaceMatcher);
}
i = -1;
if(iteration++ > keys.length) {
throw new Error("Request '" + request + "' matches recursively");
}
}
}
return newRequest;
function replaceMatcher(find) {
switch(find) {
case "/**":
{
const m = match[index++];
return m ? "/" + m : "";
}
case "**":
case "*":
return match[index++];
}
}
}
function matchType(context, configuration, relativePath) {
const typesField = getField(context, configuration, "types");
if(!typesField) return undefined;
let type;
Object.keys(typesField).forEach(key => {
const pureKey = isKeyMatched(context, key);
if(isGlobMatched(pureKey, relativePath)) {
const value = typesField[key];
if(!type && /\/\*$/.test(value))
throw new Error("value ('" + value + "') of key '" + key + "' contains '*', but there is no previous value defined");
type = value.replace(/\/\*$/, "/" + type);
}
});
return type;
}
exports.parseType = parseType;
exports.isTypeMatched = isTypeMatched;
exports.isResourceTypeSupported = isResourceTypeSupported;
exports.isEnvironment = isEnvironment;
exports.isGlobMatched = isGlobMatched;
exports.isConditionMatched = isConditionMatched;
exports.isKeyMatched = isKeyMatched;
exports.getField = getField;
exports.getMain = getMain;
exports.getExtensions = getExtensions;
exports.matchModule = matchModule;
exports.matchType = matchType;
@@ -0,0 +1,47 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const util = require("util");
// TODO remove in enhanced-resolve 5
module.exports = util.deprecate(function createInnerCallback(callback, options, message, messageOptional) {
const log = options.log;
if(!log) {
if(options.stack !== callback.stack) {
const callbackWrapper = function callbackWrapper() {
return callback.apply(this, arguments);
};
callbackWrapper.stack = options.stack;
callbackWrapper.missing = options.missing;
return callbackWrapper;
}
return callback;
}
function loggingCallbackWrapper() {
return callback.apply(this, arguments);
}
if(message) {
if(!messageOptional) {
log(message);
}
loggingCallbackWrapper.log = function writeLog(msg) {
if(messageOptional) {
log(message);
messageOptional = false;
}
log(" " + msg);
};
} else {
loggingCallbackWrapper.log = function writeLog(msg) {
log(msg);
};
}
loggingCallbackWrapper.stack = options.stack;
loggingCallbackWrapper.missing = options.missing;
return loggingCallbackWrapper;
}, "Pass resolveContext instead and use createInnerContext");
@@ -0,0 +1,26 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = function createInnerContext(options, message, messageOptional) {
let messageReported = false;
const childContext = {
log: (() => {
if(!options.log) return undefined;
if(!message) return options.log;
const logFunction = (msg) => {
if(!messageReported) {
options.log(message);
messageReported = true;
}
options.log(" " + msg);
};
return logFunction;
})(),
stack: options.stack,
missing: options.missing
};
return childContext;
};
@@ -0,0 +1,65 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = function forEachBail(array, iterator, callback) {
if(array.length === 0) return callback();
let currentPos = array.length;
let currentResult;
let done = [];
for(let i = 0; i < array.length; i++) {
const itCb = createIteratorCallback(i);
iterator(array[i], itCb);
if(currentPos === 0) break;
}
function createIteratorCallback(i) {
return(...args) => { // eslint-disable-line
if(i >= currentPos) return; // ignore
done.push(i);
if(args.length > 0) {
currentPos = i + 1;
done = done.filter(item => {
return item <= i;
});
currentResult = args;
}
if(done.length === currentPos) {
callback.apply(null, currentResult);
currentPos = 0;
}
};
}
};
module.exports.withIndex = function forEachBailWithIndex(array, iterator, callback) {
if(array.length === 0) return callback();
let currentPos = array.length;
let currentResult;
let done = [];
for(let i = 0; i < array.length; i++) {
const itCb = createIteratorCallback(i);
iterator(array[i], i, itCb);
if(currentPos === 0) break;
}
function createIteratorCallback(i) {
return(...args) => { // eslint-disable-line
if(i >= currentPos) return; // ignore
done.push(i);
if(args.length > 0) {
currentPos = i + 1;
done = done.filter(item => {
return item <= i;
});
currentResult = args;
}
if(done.length === currentPos) {
callback.apply(null, currentResult);
currentPos = 0;
}
};
}
};
@@ -0,0 +1,24 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = function getInnerRequest(resolver, request) {
if(typeof request.__innerRequest === "string" &&
request.__innerRequest_request === request.request &&
request.__innerRequest_relativePath === request.relativePath)
return request.__innerRequest;
let innerRequest;
if(request.request) {
innerRequest = request.request;
if(/^\.\.?\//.test(innerRequest) && request.relativePath) {
innerRequest = resolver.join(request.relativePath, innerRequest);
}
} else {
innerRequest = request.relativePath;
}
request.__innerRequest_request = request.request;
request.__innerRequest_relativePath = request.relativePath;
return request.__innerRequest = innerRequest;
};
@@ -0,0 +1,35 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
module.exports = function getPaths(path) {
const parts = path.split(/(.*?[\\\/]+)/);
const paths = [path];
const seqments = [parts[parts.length - 1]];
let part = parts[parts.length - 1];
path = path.substr(0, path.length - part.length - 1);
for(let i = parts.length - 2; i > 2; i -= 2) {
paths.push(path);
part = parts[i];
path = path.substr(0, path.length - part.length) || "/";
seqments.push(part.substr(0, part.length - 1));
}
part = parts[1];
seqments.push(part);
paths.push(part);
return {
paths: paths,
seqments: seqments
};
};
module.exports.basename = function basename(path) {
const i = path.lastIndexOf("/"),
j = path.lastIndexOf("\\");
const p = i < 0 ? j : j < 0 ? i : i < j ? j : i;
if(p < 0) return null;
const s = path.substr(p + 1);
return s;
};
@@ -0,0 +1,194 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
function globToRegExp(glob) {
// * [^\\\/]*
// /**/ /.+/
// ^* \./.+ (concord special)
// ? [^\\\/]
// [!...] [^...]
// [^...] [^...]
// / [\\\/]
// {...,...} (...|...)
// ?(...|...) (...|...)?
// +(...|...) (...|...)+
// *(...|...) (...|...)*
// @(...|...) (...|...)
if(/^\(.+\)$/.test(glob)) {
// allow to pass an RegExp in brackets
return new RegExp(glob.substr(1, glob.length - 2));
}
const tokens = tokenize(glob);
const process = createRoot();
const regExpStr = tokens.map(process).join("");
return new RegExp("^" + regExpStr + "$");
}
const SIMPLE_TOKENS = {
"@(": "one",
"?(": "zero-one",
"+(": "one-many",
"*(": "zero-many",
"|": "segment-sep",
"/**/": "any-path-segments",
"**": "any-path",
"*": "any-path-segment",
"?": "any-char",
"{": "or",
"/": "path-sep",
",": "comma",
")": "closing-segment",
"}": "closing-or"
};
function tokenize(glob) {
return glob.split(/([@?+*]\(|\/\*\*\/|\*\*|[?*]|\[[\!\^]?(?:[^\]\\]|\\.)+\]|\{|,|\/|[|)}])/g).map(item => {
if(!item)
return null;
const t = SIMPLE_TOKENS[item];
if(t) {
return {
type: t
};
}
if(item[0] === "[") {
if(item[1] === "^" || item[1] === "!") {
return {
type: "inverted-char-set",
value: item.substr(2, item.length - 3)
};
} else {
return {
type: "char-set",
value: item.substr(1, item.length - 2)
};
}
}
return {
type: "string",
value: item
};
}).filter(Boolean).concat({
type: "end"
});
}
function createRoot() {
const inOr = [];
const process = createSeqment();
let initial = true;
return function(token) {
switch(token.type) {
case "or":
inOr.push(initial);
return "(";
case "comma":
if(inOr.length) {
initial = inOr[inOr.length - 1];
return "|";
} else {
return process({
type: "string",
value: ","
}, initial);
}
case "closing-or":
if(inOr.length === 0)
throw new Error("Unmatched '}'");
inOr.pop();
return ")";
case "end":
if(inOr.length)
throw new Error("Unmatched '{'");
return process(token, initial);
default:
{
const result = process(token, initial);
initial = false;
return result;
}
}
};
}
function createSeqment() {
const inSeqment = [];
const process = createSimple();
return function(token, initial) {
switch(token.type) {
case "one":
case "one-many":
case "zero-many":
case "zero-one":
inSeqment.push(token.type);
return "(";
case "segment-sep":
if(inSeqment.length) {
return "|";
} else {
return process({
type: "string",
value: "|"
}, initial);
}
case "closing-segment":
{
const segment = inSeqment.pop();
switch(segment) {
case "one":
return ")";
case "one-many":
return ")+";
case "zero-many":
return ")*";
case "zero-one":
return ")?";
}
throw new Error("Unexcepted segment " + segment);
}
case "end":
if(inSeqment.length > 0) {
throw new Error("Unmatched segment, missing ')'");
}
return process(token, initial);
default:
return process(token, initial);
}
};
}
function createSimple() {
return function(token, initial) {
switch(token.type) {
case "path-sep":
return "[\\\\/]+";
case "any-path-segments":
return "[\\\\/]+(?:(.+)[\\\\/]+)?";
case "any-path":
return "(.*)";
case "any-path-segment":
if(initial) {
return "\\.[\\\\/]+(?:.*[\\\\/]+)?([^\\\\/]+)";
} else {
return "([^\\\\/]*)";
}
case "any-char":
return "[^\\\\/]";
case "inverted-char-set":
return "[^" + token.value + "]";
case "char-set":
return "[" + token.value + "]";
case "string":
return token.value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
case "end":
return "";
default:
throw new Error("Unsupported token '" + token.type + "'");
}
};
}
exports.globToRegExp = globToRegExp;
@@ -0,0 +1,162 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ResolverFactory = require("./ResolverFactory");
const NodeJsInputFileSystem = require("./NodeJsInputFileSystem");
const CachedInputFileSystem = require("./CachedInputFileSystem");
const nodeFileSystem = new CachedInputFileSystem(new NodeJsInputFileSystem(), 4000);
const nodeContext = {
environments: [
"node+es3+es5+process+native"
]
};
const asyncResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
fileSystem: nodeFileSystem
});
module.exports = function resolve(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
asyncResolver.resolve(context, path, request, resolveContext, callback);
};
const syncResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
module.exports.sync = function resolveSync(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncResolver.resolveSync(context, path, request);
};
const asyncContextResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
resolveToContext: true,
fileSystem: nodeFileSystem
});
module.exports.context = function resolveContext(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
asyncContextResolver.resolve(context, path, request, resolveContext, callback);
};
const syncContextResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
resolveToContext: true,
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
module.exports.context.sync = function resolveContextSync(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncContextResolver.resolveSync(context, path, request);
};
const asyncLoaderResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
moduleExtensions: ["-loader"],
mainFields: ["loader", "main"],
fileSystem: nodeFileSystem
});
module.exports.loader = function resolveLoader(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
asyncLoaderResolver.resolve(context, path, request, resolveContext, callback);
};
const syncLoaderResolver = ResolverFactory.createResolver({
extensions: [".js", ".json", ".node"],
moduleExtensions: ["-loader"],
mainFields: ["loader", "main"],
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
});
module.exports.loader.sync = function resolveLoaderSync(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return syncLoaderResolver.resolveSync(context, path, request);
};
module.exports.create = function create(options) {
options = Object.assign({
fileSystem: nodeFileSystem
}, options);
const resolver = ResolverFactory.createResolver(options);
return function(context, path, request, resolveContext, callback) {
if(typeof context === "string") {
callback = resolveContext;
resolveContext = request;
request = path;
path = context;
context = nodeContext;
}
if(typeof callback !== "function") {
callback = resolveContext;
}
resolver.resolve(context, path, request, resolveContext, callback);
};
};
module.exports.create.sync = function createSync(options) {
options = Object.assign({
useSyncFileSystemCalls: true,
fileSystem: nodeFileSystem
}, options);
const resolver = ResolverFactory.createResolver(options);
return function(context, path, request) {
if(typeof context === "string") {
request = path;
path = context;
context = nodeContext;
}
return resolver.resolveSync(context, path, request);
};
};
// Export Resolver, FileSystems and Plugins
module.exports.ResolverFactory = ResolverFactory;
module.exports.NodeJsInputFileSystem = NodeJsInputFileSystem;
module.exports.CachedInputFileSystem = CachedInputFileSystem;
@@ -0,0 +1,82 @@
{
"_from": "enhanced-resolve@4.1.0",
"_id": "enhanced-resolve@4.1.0",
"_inBundle": false,
"_integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
"_location": "/webpack-cli/enhanced-resolve",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "enhanced-resolve@4.1.0",
"name": "enhanced-resolve",
"escapedName": "enhanced-resolve",
"rawSpec": "4.1.0",
"saveSpec": null,
"fetchSpec": "4.1.0"
},
"_requiredBy": [
"/webpack-cli"
],
"_resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
"_shasum": "41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f",
"_spec": "enhanced-resolve@4.1.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli",
"author": {
"name": "Tobias Koppers @sokra"
},
"bugs": {
"url": "https://github.com/webpack/enhanced-resolve/issues"
},
"bundleDependencies": false,
"dependencies": {
"graceful-fs": "^4.1.2",
"memory-fs": "^0.4.0",
"tapable": "^1.0.0"
},
"deprecated": false,
"description": "Offers a async require.resolve function. It's highly configurable.",
"devDependencies": {
"beautify-lint": "^1.0.3",
"codecov.io": "^0.1.6",
"coveralls": "^2.11.6",
"eslint": "^3.14.1",
"eslint-plugin-node": "^3.0.5",
"eslint-plugin-nodeca": "^1.0.3",
"istanbul": "^0.4.1",
"js-beautify": "^1.5.10",
"mocha": "^2.3.4",
"should": "^8.0.2"
},
"engines": {
"node": ">=6.9.0"
},
"files": [
"lib",
"LICENSE"
],
"homepage": "http://github.com/webpack/enhanced-resolve",
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"main": "lib/node.js",
"name": "enhanced-resolve",
"repository": {
"type": "git",
"url": "git://github.com/webpack/enhanced-resolve.git"
},
"scripts": {
"beautify": "beautify-rewrite lib/**.js test/*.js",
"beautify-lint": "beautify-lint lib/**.js test/*.js",
"cover": "istanbul cover node_modules/mocha/bin/_mocha",
"lint": "eslint lib test",
"precover": "npm run lint && npm run beautify-lint",
"pretest": "npm run lint && npm run beautify-lint",
"test": "mocha --full-trace --check-leaks",
"travis": "npm run cover -- --report lcovonly"
},
"version": "4.1.0"
}
+46
View File
@@ -0,0 +1,46 @@
'use strict';
const path = require('path');
const locatePath = require('locate-path');
module.exports = (filename, opts = {}) => {
const startDir = path.resolve(opts.cwd || '');
const {root} = path.parse(startDir);
const filenames = [].concat(filename);
return new Promise(resolve => {
(function find(dir) {
locatePath(filenames, {cwd: dir}).then(file => {
if (file) {
resolve(path.join(dir, file));
} else if (dir === root) {
resolve(null);
} else {
find(path.dirname(dir));
}
});
})(startDir);
});
};
module.exports.sync = (filename, opts = {}) => {
let dir = path.resolve(opts.cwd || '');
const {root} = path.parse(dir);
const filenames = [].concat(filename);
// eslint-disable-next-line no-constant-condition
while (true) {
const file = locatePath.sync(filenames, {cwd: dir});
if (file) {
return path.join(dir, file);
}
if (dir === root) {
return null;
}
dir = path.dirname(dir);
}
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+82
View File
@@ -0,0 +1,82 @@
{
"_from": "find-up@^3.0.0",
"_id": "find-up@3.0.0",
"_inBundle": false,
"_integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"_location": "/webpack-cli/find-up",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "find-up@^3.0.0",
"name": "find-up",
"escapedName": "find-up",
"rawSpec": "^3.0.0",
"saveSpec": null,
"fetchSpec": "^3.0.0"
},
"_requiredBy": [
"/webpack-cli/yargs"
],
"_resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"_shasum": "49169f1d7993430646da61ecc5ae355c21c97b73",
"_spec": "find-up@^3.0.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\yargs",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/find-up/issues"
},
"bundleDependencies": false,
"dependencies": {
"locate-path": "^3.0.0"
},
"deprecated": false,
"description": "Find a file or directory by walking up parent directories",
"devDependencies": {
"ava": "*",
"tempy": "^0.2.1",
"xo": "*"
},
"engines": {
"node": ">=6"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/find-up#readme",
"keywords": [
"find",
"up",
"find-up",
"findup",
"look-up",
"look",
"file",
"search",
"match",
"package",
"resolve",
"parent",
"parents",
"folder",
"directory",
"dir",
"walk",
"walking",
"path"
],
"license": "MIT",
"name": "find-up",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/find-up.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "3.0.0"
}
+87
View File
@@ -0,0 +1,87 @@
# find-up [![Build Status: Linux and macOS](https://travis-ci.org/sindresorhus/find-up.svg?branch=master)](https://travis-ci.org/sindresorhus/find-up) [![Build Status: Windows](https://ci.appveyor.com/api/projects/status/l0cyjmvh5lq72vq2/branch/master?svg=true)](https://ci.appveyor.com/project/sindresorhus/find-up/branch/master)
> Find a file or directory by walking up parent directories
## Install
```
$ npm install find-up
```
## Usage
```
/
└── Users
└── sindresorhus
├── unicorn.png
└── foo
└── bar
├── baz
└── example.js
```
`example.js`
```js
const findUp = require('find-up');
(async () => {
console.log(await findUp('unicorn.png'));
//=> '/Users/sindresorhus/unicorn.png'
console.log(await findUp(['rainbow.png', 'unicorn.png']));
//=> '/Users/sindresorhus/unicorn.png'
})();
```
## API
### findUp(filename, [options])
Returns a `Promise` for either the filepath or `null` if it couldn't be found.
### findUp([filenameA, filenameB], [options])
Returns a `Promise` for either the first filepath found (by respecting the order) or `null` if none could be found.
### findUp.sync(filename, [options])
Returns a filepath or `null`.
### findUp.sync([filenameA, filenameB], [options])
Returns the first filepath found (by respecting the order) or `null`.
#### filename
Type: `string`
Filename of the file to find.
#### options
Type: `Object`
##### cwd
Type: `string`<br>
Default: `process.cwd()`
Directory to start from.
## Related
- [find-up-cli](https://github.com/sindresorhus/find-up-cli) - CLI for this module
- [pkg-up](https://github.com/sindresorhus/pkg-up) - Find the closest package.json file
- [pkg-dir](https://github.com/sindresorhus/pkg-dir) - Find the root directory of an npm package
- [resolve-from](https://github.com/sindresorhus/resolve-from) - Resolve the path of a module like `require.resolve()` but from a given path
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,6 @@
ISC License (ISC)
Copyright 2018 Stefan Penner
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,41 @@
# get-caller-file
[![Build Status](https://travis-ci.org/stefanpenner/get-caller-file.svg?branch=master)](https://travis-ci.org/stefanpenner/get-caller-file)
[![Build status](https://ci.appveyor.com/api/projects/status/ol2q94g1932cy14a/branch/master?svg=true)](https://ci.appveyor.com/project/embercli/get-caller-file/branch/master)
This is a utility, which allows a function to figure out from which file it was invoked. It does so by inspecting v8's stack trace at the time it is invoked.
Inspired by http://stackoverflow.com/questions/13227489
*note: this relies on Node/V8 specific APIs, as such other runtimes may not work*
## Installation
```bash
yarn add get-caller-file
```
## Usage
Given:
```js
// ./foo.js
const getCallerFile = require('get-caller-file');
module.exports = function() {
return getCallerFile(); // figures out who called it
};
```
```js
// index.js
const foo = require('./foo');
foo() // => /full/path/to/this/file/index.js
```
## Options:
* `getCallerFile(position = 2)`: where position is stack frame whos fileName we want.
@@ -0,0 +1,2 @@
declare const _default: (position?: number) => any;
export = _default;
@@ -0,0 +1,22 @@
"use strict";
// Call this function in a another function to find out the file from
// which that function was called from. (Inspects the v8 stack trace)
//
// Inspired by http://stackoverflow.com/questions/13227489
module.exports = function getCallerFile(position) {
if (position === void 0) { position = 2; }
if (position >= Error.stackTraceLimit) {
throw new TypeError('getCallerFile(position) requires position be less then Error.stackTraceLimit but position was: `' + position + '` and Error.stackTraceLimit was: `' + Error.stackTraceLimit + '`');
}
var oldPrepareStackTrace = Error.prepareStackTrace;
Error.prepareStackTrace = function (_, stack) { return stack; };
var stack = new Error().stack;
Error.prepareStackTrace = oldPrepareStackTrace;
if (stack !== null && typeof stack === 'object') {
// stack[0] holds this file
// stack[1] holds where this function was called
// stack[2] holds the file we're interested in
return stack[position] ? stack[position].getFileName() : undefined;
}
};
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AAAA,qEAAqE;AACrE,qEAAqE;AACrE,EAAE;AACF,0DAA0D;AAE1D,iBAAS,SAAS,aAAa,CAAC,QAAY;IAAZ,yBAAA,EAAA,YAAY;IAC1C,IAAI,QAAQ,IAAI,KAAK,CAAC,eAAe,EAAE;QACrC,MAAM,IAAI,SAAS,CAAC,kGAAkG,GAAG,QAAQ,GAAG,oCAAoC,GAAG,KAAK,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC;KACzM;IAED,IAAM,oBAAoB,GAAG,KAAK,CAAC,iBAAiB,CAAC;IACrD,KAAK,CAAC,iBAAiB,GAAG,UAAC,CAAC,EAAE,KAAK,IAAM,OAAA,KAAK,EAAL,CAAK,CAAC;IAC/C,IAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC;IAChC,KAAK,CAAC,iBAAiB,GAAG,oBAAoB,CAAC;IAG/C,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC/C,2BAA2B;QAC3B,gDAAgD;QAChD,8CAA8C;QAC9C,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAE,KAAK,CAAC,QAAQ,CAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;KAC7E;AACH,CAAC,CAAC"}
@@ -0,0 +1,69 @@
{
"_from": "get-caller-file@^2.0.1",
"_id": "get-caller-file@2.0.5",
"_inBundle": false,
"_integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"_location": "/webpack-cli/get-caller-file",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "get-caller-file@^2.0.1",
"name": "get-caller-file",
"escapedName": "get-caller-file",
"rawSpec": "^2.0.1",
"saveSpec": null,
"fetchSpec": "^2.0.1"
},
"_requiredBy": [
"/webpack-cli/yargs"
],
"_resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"_shasum": "4f94412a82db32f36e3b0b9741f8a97feb031f7e",
"_spec": "get-caller-file@^2.0.1",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\yargs",
"author": {
"name": "Stefan Penner"
},
"bugs": {
"url": "https://github.com/stefanpenner/get-caller-file/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "[![Build Status](https://travis-ci.org/stefanpenner/get-caller-file.svg?branch=master)](https://travis-ci.org/stefanpenner/get-caller-file) [![Build status](https://ci.appveyor.com/api/projects/status/ol2q94g1932cy14a/branch/master?svg=true)](https://ci.appveyor.com/project/embercli/get-caller-file/branch/master)",
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/ensure-posix-path": "^1.0.0",
"@types/mocha": "^5.2.6",
"@types/node": "^11.10.5",
"chai": "^4.1.2",
"ensure-posix-path": "^1.0.1",
"mocha": "^5.2.0",
"typescript": "^3.3.3333"
},
"directories": {
"test": "tests"
},
"engines": {
"node": "6.* || 8.* || >= 10.*"
},
"files": [
"index.js",
"index.js.map",
"index.d.ts"
],
"homepage": "https://github.com/stefanpenner/get-caller-file#readme",
"license": "ISC",
"main": "index.js",
"name": "get-caller-file",
"repository": {
"type": "git",
"url": "git+https://github.com/stefanpenner/get-caller-file.git"
},
"scripts": {
"prepare": "tsc",
"test": "mocha test",
"test:debug": "mocha test"
},
"version": "2.0.5"
}
+15
View File
@@ -0,0 +1,15 @@
'use strict';
module.exports = object => {
if (typeof object !== 'object') {
throw new TypeError('Expected an object');
}
const ret = {};
for (const key of Object.keys(object)) {
const value = object[key];
ret[value] = key;
}
return ret;
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
{
"_from": "invert-kv@^2.0.0",
"_id": "invert-kv@2.0.0",
"_inBundle": false,
"_integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==",
"_location": "/webpack-cli/invert-kv",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "invert-kv@^2.0.0",
"name": "invert-kv",
"escapedName": "invert-kv",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/webpack-cli/lcid"
],
"_resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
"_shasum": "7393f5afa59ec9ff5f67a27620d11c226e3eec02",
"_spec": "invert-kv@^2.0.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\lcid",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/invert-kv/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Invert the key/value of an object. Example: `{foo: 'bar'}` → `{bar: 'foo'}`",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/invert-kv#readme",
"keywords": [
"object",
"key",
"value",
"kv",
"invert"
],
"license": "MIT",
"name": "invert-kv",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/invert-kv.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "2.0.0"
}
+25
View File
@@ -0,0 +1,25 @@
# invert-kv [![Build Status](https://travis-ci.org/sindresorhus/invert-kv.svg?branch=master)](https://travis-ci.org/sindresorhus/invert-kv)
> Invert the key/value of an object. Example: `{foo: 'bar'}` → `{bar: 'foo'}`
## Install
```
$ npm install invert-kv
```
## Usage
```js
const invertKv = require('invert-kv');
invertKv({foo: 'bar', unicorn: 'rainbow'});
//=> {bar: 'foo', rainbow: 'unicorn'}
```
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
@@ -0,0 +1,46 @@
'use strict';
/* eslint-disable yoda */
module.exports = x => {
if (Number.isNaN(x)) {
return false;
}
// code points are derived from:
// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
if (
x >= 0x1100 && (
x <= 0x115f || // Hangul Jamo
x === 0x2329 || // LEFT-POINTING ANGLE BRACKET
x === 0x232a || // RIGHT-POINTING ANGLE BRACKET
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
(0x2e80 <= x && x <= 0x3247 && x !== 0x303f) ||
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
(0x3250 <= x && x <= 0x4dbf) ||
// CJK Unified Ideographs .. Yi Radicals
(0x4e00 <= x && x <= 0xa4c6) ||
// Hangul Jamo Extended-A
(0xa960 <= x && x <= 0xa97c) ||
// Hangul Syllables
(0xac00 <= x && x <= 0xd7a3) ||
// CJK Compatibility Ideographs
(0xf900 <= x && x <= 0xfaff) ||
// Vertical Forms
(0xfe10 <= x && x <= 0xfe19) ||
// CJK Compatibility Forms .. Small Form Variants
(0xfe30 <= x && x <= 0xfe6b) ||
// Halfwidth and Fullwidth Forms
(0xff01 <= x && x <= 0xff60) ||
(0xffe0 <= x && x <= 0xffe6) ||
// Kana Supplement
(0x1b000 <= x && x <= 0x1b001) ||
// Enclosed Ideographic Supplement
(0x1f200 <= x && x <= 0x1f251) ||
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
(0x20000 <= x && x <= 0x3fffd)
)
) {
return true;
}
return false;
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,77 @@
{
"_from": "is-fullwidth-code-point@^2.0.0",
"_id": "is-fullwidth-code-point@2.0.0",
"_inBundle": false,
"_integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"_location": "/webpack-cli/is-fullwidth-code-point",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "is-fullwidth-code-point@^2.0.0",
"name": "is-fullwidth-code-point",
"escapedName": "is-fullwidth-code-point",
"rawSpec": "^2.0.0",
"saveSpec": null,
"fetchSpec": "^2.0.0"
},
"_requiredBy": [
"/webpack-cli/string-width"
],
"_resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"_shasum": "a3b30a5c4f199183167aaab93beefae3ddfb654f",
"_spec": "is-fullwidth-code-point@^2.0.0",
"_where": "O:\\zero\\zero.Web\\node_modules\\webpack-cli\\node_modules\\string-width",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"bugs": {
"url": "https://github.com/sindresorhus/is-fullwidth-code-point/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Check if the character represented by a given Unicode code point is fullwidth",
"devDependencies": {
"ava": "*",
"xo": "*"
},
"engines": {
"node": ">=4"
},
"files": [
"index.js"
],
"homepage": "https://github.com/sindresorhus/is-fullwidth-code-point#readme",
"keywords": [
"fullwidth",
"full-width",
"full",
"width",
"unicode",
"character",
"char",
"string",
"str",
"codepoint",
"code",
"point",
"is",
"detect",
"check"
],
"license": "MIT",
"name": "is-fullwidth-code-point",
"repository": {
"type": "git",
"url": "git+https://github.com/sindresorhus/is-fullwidth-code-point.git"
},
"scripts": {
"test": "xo && ava"
},
"version": "2.0.0",
"xo": {
"esnext": true
}
}

Some files were not shown because too many files have changed in this diff Show More