mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Build: Lint files after removing their code fences (#12075)
* Add linting * Type the eslintInstance variable * Update documentation
This commit is contained in:
parent
2b1e05f086
commit
2b104603d5
@ -1,5 +1,5 @@
|
|||||||
# Development
|
# Development
|
||||||
|
|
||||||
Several files which are needed for developing on(!) MetaMask.
|
Several files which are needed for developing on MetaMask.
|
||||||
|
|
||||||
Usually each files contains information about its scope / usage.
|
Usually each file or directory contains information about its scope / usage.
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
> _tl;dr_ `yarn dist` for prod, `yarn start` for local development
|
> _tl;dr_ `yarn dist` for prod, `yarn start` for local development
|
||||||
|
|
||||||
This directory contains the MetaMask build system, which is used to build the MetaMask Extension such that it can be used in a supported browser.
|
This directory contains the MetaMask build system, which is used to build the MetaMask Extension such that it can be used in a supported browser.
|
||||||
From the repository root, the build system entry file is located at `development/build/index.js`.
|
From the repository root, the build system entry file is located at [`./development/build/index.js`](https://github.com/MetaMask/metamask-extension/blob/develop/development/build/index.js).
|
||||||
|
|
||||||
Several package scripts invoke the build system.
|
Several package scripts invoke the build system.
|
||||||
For example, `yarn start` creates a watched development build, and `yarn dist` creates a production build.
|
For example, `yarn start` creates a watched development build, and `yarn dist` creates a production build.
|
||||||
@ -13,7 +13,17 @@ For local development, building without `lavamoat` is faster and therefore prefe
|
|||||||
The build system is not a full-featured CLI, but rather a script that expects some command line arguments and environment variables.
|
The build system is not a full-featured CLI, but rather a script that expects some command line arguments and environment variables.
|
||||||
For instructions regarding environment variables, see [the main repository readme](../../README.md#building-locally).
|
For instructions regarding environment variables, see [the main repository readme](../../README.md#building-locally).
|
||||||
|
|
||||||
Here follows basic usage information for the build system.
|
Generally speaking, the build system consists of [`gulp`](https://npmjs.com/package/gulp) tasks that either manipulate static assets or bundle source files using [Browserify](https://browserify.org/).
|
||||||
|
Production-ready zip files are written to the `./builds` directory, while "unpacked" extension builds
|
||||||
|
are written to the `./dist` directory.
|
||||||
|
|
||||||
|
Our JavaScript source files are transformed using [Babel](https://babeljs.io/), specifically using
|
||||||
|
the [`babelify`](https://npmjs.com/package/babelify) Browserify transform.
|
||||||
|
Source file bundling tasks are implemented in the [`./development/build/scripts.js`](https://github.com/MetaMask/metamask-extension/blob/develop/development/build/scripts.js).
|
||||||
|
|
||||||
|
> Locally implemented Browserify transforms, _some of which affect how we write JavaScript_, are listed and documented [here](./transforms/README.md).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Usage: yarn build <entry-task> [options]
|
Usage: yarn build <entry-task> [options]
|
||||||
@ -30,15 +40,21 @@ Commands:
|
|||||||
e2e tests.
|
e2e tests.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--beta-version If the build type is "beta", the beta version number.
|
--beta-version If the build type is "beta", the beta version number.
|
||||||
[number] [default: 0]
|
[number] [default: 0]
|
||||||
--build-type The "type" of build to create. One of: "beta", "main"
|
--build-type The "type" of build to create. One of: "beta", "main"
|
||||||
[string] [default: "main"]
|
[string] [default: "main"]
|
||||||
--omit-lockdown Whether to omit SES lockdown files from the extension
|
--lint-fence-files Whether files with code fences should be linted after
|
||||||
bundle. Useful when linking dependencies that are
|
fences have been removed by the code fencing transform.
|
||||||
incompatible with lockdown.
|
The build will fail if linting fails.
|
||||||
|
Defaults to `false` if the entry task is `dev` or
|
||||||
|
`testDev`, and `true` otherwise.
|
||||||
|
[boolean] [default: <varies>]
|
||||||
|
--omit-lockdown Whether to omit SES lockdown files from the extension
|
||||||
|
bundle. Useful when linking dependencies that are
|
||||||
|
incompatible with lockdown.
|
||||||
[boolean] [default: false]
|
[boolean] [default: false]
|
||||||
--skip-stats Whether to refrain from logging build progress. Mostly used
|
--skip-stats Whether to refrain from logging build progress. Mostly
|
||||||
internally.
|
used internally.
|
||||||
[boolean] [default: false]
|
[boolean] [default: false]
|
||||||
```
|
```
|
||||||
|
@ -40,6 +40,7 @@ function defineAndRunBuildTasks() {
|
|||||||
isBeta,
|
isBeta,
|
||||||
isLavaMoat,
|
isLavaMoat,
|
||||||
shouldIncludeLockdown,
|
shouldIncludeLockdown,
|
||||||
|
shouldLintFenceFiles,
|
||||||
skipStats,
|
skipStats,
|
||||||
} = parseArgv();
|
} = parseArgv();
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ function defineAndRunBuildTasks() {
|
|||||||
buildType,
|
buildType,
|
||||||
isLavaMoat,
|
isLavaMoat,
|
||||||
livereload,
|
livereload,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { clean, reload, zip } = createEtcTasks({
|
const { clean, reload, zip } = createEtcTasks({
|
||||||
@ -146,16 +148,22 @@ function parseArgv() {
|
|||||||
const NamedArgs = {
|
const NamedArgs = {
|
||||||
BetaVersion: 'beta-version',
|
BetaVersion: 'beta-version',
|
||||||
BuildType: 'build-type',
|
BuildType: 'build-type',
|
||||||
|
LintFenceFiles: 'lint-fence-files',
|
||||||
OmitLockdown: 'omit-lockdown',
|
OmitLockdown: 'omit-lockdown',
|
||||||
SkipStats: 'skip-stats',
|
SkipStats: 'skip-stats',
|
||||||
};
|
};
|
||||||
|
|
||||||
const argv = minimist(process.argv.slice(2), {
|
const argv = minimist(process.argv.slice(2), {
|
||||||
boolean: [NamedArgs.OmitLockdown, NamedArgs.SkipStats],
|
boolean: [
|
||||||
|
NamedArgs.LintFenceFiles,
|
||||||
|
NamedArgs.OmitLockdown,
|
||||||
|
NamedArgs.SkipStats,
|
||||||
|
],
|
||||||
string: [NamedArgs.BuildType],
|
string: [NamedArgs.BuildType],
|
||||||
default: {
|
default: {
|
||||||
[NamedArgs.BetaVersion]: 0,
|
[NamedArgs.BetaVersion]: 0,
|
||||||
[NamedArgs.BuildType]: BuildTypes.main,
|
[NamedArgs.BuildType]: BuildTypes.main,
|
||||||
|
[NamedArgs.LintFenceFiles]: true,
|
||||||
[NamedArgs.OmitLockdown]: false,
|
[NamedArgs.OmitLockdown]: false,
|
||||||
[NamedArgs.SkipStats]: false,
|
[NamedArgs.SkipStats]: false,
|
||||||
},
|
},
|
||||||
@ -182,6 +190,13 @@ function parseArgv() {
|
|||||||
throw new Error(`MetaMask build: Invalid build type: "${buildType}"`);
|
throw new Error(`MetaMask build: Invalid build type: "${buildType}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Manually default this to `false` for dev builds only.
|
||||||
|
const shouldLintFenceFiles = process.argv.includes(
|
||||||
|
`--${NamedArgs.LintFenceFiles}`,
|
||||||
|
)
|
||||||
|
? argv[NamedArgs.LintFenceFiles]
|
||||||
|
: !/dev/iu.test(entryTask);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
betaVersion: String(betaVersion),
|
betaVersion: String(betaVersion),
|
||||||
buildType,
|
buildType,
|
||||||
@ -189,6 +204,7 @@ function parseArgv() {
|
|||||||
isBeta: argv[NamedArgs.BuildType] === BuildTypes.beta,
|
isBeta: argv[NamedArgs.BuildType] === BuildTypes.beta,
|
||||||
isLavaMoat: process.argv[0].includes('lavamoat'),
|
isLavaMoat: process.argv[0].includes('lavamoat'),
|
||||||
shouldIncludeLockdown: argv[NamedArgs.OmitLockdown],
|
shouldIncludeLockdown: argv[NamedArgs.OmitLockdown],
|
||||||
|
shouldLintFenceFiles,
|
||||||
skipStats: argv[NamedArgs.SkipStats],
|
skipStats: argv[NamedArgs.SkipStats],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ function createScriptTasks({
|
|||||||
buildType,
|
buildType,
|
||||||
isLavaMoat,
|
isLavaMoat,
|
||||||
livereload,
|
livereload,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}) {
|
}) {
|
||||||
// internal tasks
|
// internal tasks
|
||||||
const core = {
|
const core = {
|
||||||
@ -97,6 +98,7 @@ function createScriptTasks({
|
|||||||
return `./app/scripts/${label}.js`;
|
return `./app/scripts/${label}.js`;
|
||||||
}),
|
}),
|
||||||
testing,
|
testing,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -151,6 +153,7 @@ function createScriptTasks({
|
|||||||
runInChildProcess(subtask, {
|
runInChildProcess(subtask, {
|
||||||
buildType,
|
buildType,
|
||||||
isLavaMoat,
|
isLavaMoat,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
// make a parent task that runs each task in a child thread
|
// make a parent task that runs each task in a child thread
|
||||||
@ -166,6 +169,7 @@ function createScriptTasks({
|
|||||||
devMode,
|
devMode,
|
||||||
entryFilepath: `./app/scripts/${label}.js`,
|
entryFilepath: `./app/scripts/${label}.js`,
|
||||||
label,
|
label,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +182,7 @@ function createScriptTasks({
|
|||||||
devMode,
|
devMode,
|
||||||
entryFilepath: `./app/scripts/${label}.js`,
|
entryFilepath: `./app/scripts/${label}.js`,
|
||||||
label,
|
label,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +195,7 @@ function createScriptTasks({
|
|||||||
devMode,
|
devMode,
|
||||||
entryFilepath: `./app/scripts/${label}.js`,
|
entryFilepath: `./app/scripts/${label}.js`,
|
||||||
label,
|
label,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,6 +212,7 @@ function createScriptTasks({
|
|||||||
entryFilepath: `./app/scripts/${inpage}.js`,
|
entryFilepath: `./app/scripts/${inpage}.js`,
|
||||||
label: inpage,
|
label: inpage,
|
||||||
testing,
|
testing,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}),
|
}),
|
||||||
createNormalBundle({
|
createNormalBundle({
|
||||||
buildType,
|
buildType,
|
||||||
@ -215,6 +222,7 @@ function createScriptTasks({
|
|||||||
entryFilepath: `./app/scripts/${contentscript}.js`,
|
entryFilepath: `./app/scripts/${contentscript}.js`,
|
||||||
label: contentscript,
|
label: contentscript,
|
||||||
testing,
|
testing,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -226,6 +234,7 @@ function createFactoredBuild({
|
|||||||
devMode,
|
devMode,
|
||||||
entryFiles,
|
entryFiles,
|
||||||
testing,
|
testing,
|
||||||
|
shouldLintFenceFiles,
|
||||||
}) {
|
}) {
|
||||||
return async function () {
|
return async function () {
|
||||||
// create bundler setup and apply defaults
|
// create bundler setup and apply defaults
|
||||||
@ -244,6 +253,7 @@ function createFactoredBuild({
|
|||||||
envVars,
|
envVars,
|
||||||
minify,
|
minify,
|
||||||
reloadOnChange,
|
reloadOnChange,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
|
|
||||||
// set bundle entries
|
// set bundle entries
|
||||||
@ -344,6 +354,7 @@ function createNormalBundle({
|
|||||||
extraEntries = [],
|
extraEntries = [],
|
||||||
label,
|
label,
|
||||||
modulesToExpose,
|
modulesToExpose,
|
||||||
|
shouldLintFenceFiles,
|
||||||
testing,
|
testing,
|
||||||
}) {
|
}) {
|
||||||
return async function () {
|
return async function () {
|
||||||
@ -363,6 +374,7 @@ function createNormalBundle({
|
|||||||
envVars,
|
envVars,
|
||||||
minify,
|
minify,
|
||||||
reloadOnChange,
|
reloadOnChange,
|
||||||
|
shouldLintFenceFiles,
|
||||||
});
|
});
|
||||||
|
|
||||||
// set bundle entries
|
// set bundle entries
|
||||||
@ -409,7 +421,7 @@ function createBuildConfiguration() {
|
|||||||
|
|
||||||
function setupBundlerDefaults(
|
function setupBundlerDefaults(
|
||||||
buildConfiguration,
|
buildConfiguration,
|
||||||
{ buildType, devMode, envVars, minify, reloadOnChange },
|
{ buildType, devMode, envVars, minify, reloadOnChange, shouldLintFenceFiles },
|
||||||
) {
|
) {
|
||||||
const { bundlerOpts } = buildConfiguration;
|
const { bundlerOpts } = buildConfiguration;
|
||||||
|
|
||||||
@ -417,7 +429,7 @@ function setupBundlerDefaults(
|
|||||||
// Source transforms
|
// Source transforms
|
||||||
transform: [
|
transform: [
|
||||||
// Remove code that should be excluded from builds of the current type
|
// Remove code that should be excluded from builds of the current type
|
||||||
createRemoveFencedCodeTransform(buildType),
|
createRemoveFencedCodeTransform(buildType, shouldLintFenceFiles),
|
||||||
// Transpile top-level code
|
// Transpile top-level code
|
||||||
babelify,
|
babelify,
|
||||||
// Inline `fs.readFileSync` files
|
// Inline `fs.readFileSync` files
|
||||||
|
@ -48,7 +48,10 @@ function createTask(taskName, taskFn) {
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runInChildProcess(task, { buildType, isLavaMoat }) {
|
function runInChildProcess(
|
||||||
|
task,
|
||||||
|
{ buildType, isLavaMoat, shouldLintFenceFiles },
|
||||||
|
) {
|
||||||
const taskName = typeof task === 'string' ? task : task.taskName;
|
const taskName = typeof task === 'string' ? task : task.taskName;
|
||||||
if (!taskName) {
|
if (!taskName) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -63,7 +66,15 @@ function runInChildProcess(task, { buildType, isLavaMoat }) {
|
|||||||
if (isLavaMoat) {
|
if (isLavaMoat) {
|
||||||
childProcess = spawn(
|
childProcess = spawn(
|
||||||
'yarn',
|
'yarn',
|
||||||
['build', taskName, '--build-type', buildType, '--skip-stats'],
|
[
|
||||||
|
'build',
|
||||||
|
taskName,
|
||||||
|
'--build-type',
|
||||||
|
buildType,
|
||||||
|
'--lint-fence-files',
|
||||||
|
shouldLintFenceFiles,
|
||||||
|
'--skip-stats',
|
||||||
|
],
|
||||||
{
|
{
|
||||||
env: process.env,
|
env: process.env,
|
||||||
},
|
},
|
||||||
@ -71,7 +82,15 @@ function runInChildProcess(task, { buildType, isLavaMoat }) {
|
|||||||
} else {
|
} else {
|
||||||
childProcess = spawn(
|
childProcess = spawn(
|
||||||
'yarn',
|
'yarn',
|
||||||
['build:dev', taskName, '--build-type', buildType, '--skip-stats'],
|
[
|
||||||
|
'build:dev',
|
||||||
|
taskName,
|
||||||
|
'--build-type',
|
||||||
|
buildType,
|
||||||
|
'--lint-fence-files',
|
||||||
|
shouldLintFenceFiles,
|
||||||
|
'--skip-stats',
|
||||||
|
],
|
||||||
{
|
{
|
||||||
env: process.env,
|
env: process.env,
|
||||||
},
|
},
|
||||||
|
@ -52,6 +52,13 @@ commands inside the parameter parentheses:
|
|||||||
///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
|
///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Gotchas
|
||||||
|
|
||||||
|
By default, the transform will invoke ESLint on files that are modified by the transform.
|
||||||
|
This is our first line of defense against creating unsyntactic code using code fences, and the transform will error if linting fails.
|
||||||
|
(Live reloading will continue to work if enabled.)
|
||||||
|
To toggle this behavior via build system arguments, see [the build system readme](../README.md).
|
||||||
|
|
||||||
### Code Fencing Syntax
|
### Code Fencing Syntax
|
||||||
|
|
||||||
> In the specification, angle brackets, `< >`, indicate required tokens, while
|
> In the specification, angle brackets, `< >`, indicate required tokens, while
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const { PassThrough, Transform } = require('stream');
|
const { PassThrough, Transform } = require('stream');
|
||||||
const { BuildTypes } = require('../utils');
|
const { BuildTypes } = require('../utils');
|
||||||
|
const { lintTransformedFile } = require('./utils');
|
||||||
|
|
||||||
const hasOwnProperty = (obj, key) => Reflect.hasOwnProperty.call(obj, key);
|
const hasOwnProperty = (obj, key) => Reflect.hasOwnProperty.call(obj, key);
|
||||||
|
|
||||||
@ -14,13 +15,18 @@ class RemoveFencedCodeTransform extends Transform {
|
|||||||
* A transform stream that calls {@link removeFencedCode} on the complete
|
* A transform stream that calls {@link removeFencedCode} on the complete
|
||||||
* string contents of the file read by Browserify.
|
* string contents of the file read by Browserify.
|
||||||
*
|
*
|
||||||
|
* Optionally lints the file if it was modified.
|
||||||
|
*
|
||||||
* @param {string} filePath - The path to the file being transformed.
|
* @param {string} filePath - The path to the file being transformed.
|
||||||
* @param {string} buildType - The type of the current build process.env.
|
* @param {string} buildType - The type of the current build process.
|
||||||
|
* @param {boolean} shouldLintTransformedFiles - Whether the file should be
|
||||||
|
* linted if modified by the transform.
|
||||||
*/
|
*/
|
||||||
constructor(filePath, buildType) {
|
constructor(filePath, buildType, shouldLintTransformedFiles) {
|
||||||
super();
|
super();
|
||||||
this.filePath = filePath;
|
this.filePath = filePath;
|
||||||
this.buildType = buildType;
|
this.buildType = buildType;
|
||||||
|
this.shouldLintTransformedFiles = shouldLintTransformedFiles;
|
||||||
this._fileBuffers = [];
|
this._fileBuffers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,14 +41,24 @@ class RemoveFencedCodeTransform extends Transform {
|
|||||||
// stream, immediately before the "end" event is emitted.
|
// stream, immediately before the "end" event is emitted.
|
||||||
// It applies the transform to the concatenated file contents.
|
// It applies the transform to the concatenated file contents.
|
||||||
_flush(end) {
|
_flush(end) {
|
||||||
const [fileContent] = removeFencedCode(
|
const [fileContent, didModify] = removeFencedCode(
|
||||||
this.filePath,
|
this.filePath,
|
||||||
this.buildType,
|
this.buildType,
|
||||||
Buffer.concat(this._fileBuffers).toString('utf8'),
|
Buffer.concat(this._fileBuffers).toString('utf8'),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.push(fileContent);
|
const pushAndEnd = () => {
|
||||||
end();
|
this.push(fileContent);
|
||||||
|
end();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.shouldLintTransformedFiles && didModify) {
|
||||||
|
lintTransformedFile(fileContent, this.filePath)
|
||||||
|
.then(pushAndEnd)
|
||||||
|
.catch((error) => end(error));
|
||||||
|
} else {
|
||||||
|
pushAndEnd();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +73,19 @@ class RemoveFencedCodeTransform extends Transform {
|
|||||||
* For details on how the transform mutates source files, see
|
* For details on how the transform mutates source files, see
|
||||||
* {@link removeFencedCode} and the documentation.
|
* {@link removeFencedCode} and the documentation.
|
||||||
*
|
*
|
||||||
|
* If specified (and by default), the transform will call ESLint on the text
|
||||||
|
* contents of any file that it modifies. The transform will error if such a
|
||||||
|
* file is ignored by ESLint, since linting is our first line of defense against
|
||||||
|
* making un-syntactic modifications to files using code fences.
|
||||||
|
*
|
||||||
* @param {string} buildType - The type of the current build.
|
* @param {string} buildType - The type of the current build.
|
||||||
|
* @param {boolean} shouldLintTransformedFiles - Whether to lint transformed files.
|
||||||
* @returns {(filePath: string) => Transform} The transform function.
|
* @returns {(filePath: string) => Transform} The transform function.
|
||||||
*/
|
*/
|
||||||
function createRemoveFencedCodeTransform(buildType) {
|
function createRemoveFencedCodeTransform(
|
||||||
|
buildType,
|
||||||
|
shouldLintTransformedFiles = true,
|
||||||
|
) {
|
||||||
if (!hasOwnProperty(BuildTypes, buildType)) {
|
if (!hasOwnProperty(BuildTypes, buildType)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Code fencing transform received unrecognized build type "${buildType}".`,
|
`Code fencing transform received unrecognized build type "${buildType}".`,
|
||||||
@ -81,7 +106,11 @@ function createRemoveFencedCodeTransform(buildType) {
|
|||||||
return new PassThrough();
|
return new PassThrough();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RemoveFencedCodeTransform(filePath, buildType);
|
return new RemoveFencedCodeTransform(
|
||||||
|
filePath,
|
||||||
|
buildType,
|
||||||
|
shouldLintTransformedFiles,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +185,7 @@ const directiveParsingRegex = /^([A-Z]+):([A-Z_]+)(?:\(((?:\w+,)*\w+)\))?$/u;
|
|||||||
* For details, please see the documentation.
|
* For details, please see the documentation.
|
||||||
*
|
*
|
||||||
* @param {string} filePath - The path to the file being transformed.
|
* @param {string} filePath - The path to the file being transformed.
|
||||||
* @param {string} typeOfCurrentBuild - The type of the current build process.
|
* @param {string} typeOfCurrentBuild - The type of the current build.
|
||||||
* @param {string} fileContent - The contents of the file being transformed.
|
* @param {string} fileContent - The contents of the file being transformed.
|
||||||
* @returns {[string, modified]} A tuple of the post-transform file contents and
|
* @returns {[string, modified]} A tuple of the post-transform file contents and
|
||||||
* a boolean indicating whether they were modified.
|
* a boolean indicating whether they were modified.
|
||||||
|
@ -4,6 +4,11 @@ const {
|
|||||||
createRemoveFencedCodeTransform,
|
createRemoveFencedCodeTransform,
|
||||||
removeFencedCode,
|
removeFencedCode,
|
||||||
} = require('./remove-fenced-code');
|
} = require('./remove-fenced-code');
|
||||||
|
const transformUtils = require('./utils');
|
||||||
|
|
||||||
|
jest.mock('./utils', () => ({
|
||||||
|
lintTransformedFile: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
// The test data is just strings. We get it from a function at the end of this
|
// The test data is just strings. We get it from a function at the end of this
|
||||||
// file because it takes up a lot of lines and is very distracting.
|
// file because it takes up a lot of lines and is very distracting.
|
||||||
@ -17,8 +22,13 @@ Conditionally_Included
|
|||||||
|
|
||||||
describe('build/transforms/remove-fenced-code', () => {
|
describe('build/transforms/remove-fenced-code', () => {
|
||||||
describe('createRemoveFencedCodeTransform', () => {
|
describe('createRemoveFencedCodeTransform', () => {
|
||||||
|
const { lintTransformedFile: lintTransformedFileMock } = transformUtils;
|
||||||
const mockJsFileName = 'file.js';
|
const mockJsFileName = 'file.js';
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
lintTransformedFileMock.mockImplementation(() => Promise.resolve());
|
||||||
|
});
|
||||||
|
|
||||||
it('rejects invalid build types', () => {
|
it('rejects invalid build types', () => {
|
||||||
expect(() => createRemoveFencedCodeTransform('foobar')).toThrow(
|
expect(() => createRemoveFencedCodeTransform('foobar')).toThrow(
|
||||||
/received unrecognized build type "foobar".$/u,
|
/received unrecognized build type "foobar".$/u,
|
||||||
@ -37,6 +47,7 @@ describe('build/transforms/remove-fenced-code', () => {
|
|||||||
|
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
expect(streamOutput).toStrictEqual(fileContent);
|
expect(streamOutput).toStrictEqual(fileContent);
|
||||||
|
expect(lintTransformedFileMock).not.toHaveBeenCalled();
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -59,6 +70,11 @@ describe('build/transforms/remove-fenced-code', () => {
|
|||||||
|
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
expect(streamOutput).toStrictEqual(filePrefix);
|
expect(streamOutput).toStrictEqual(filePrefix);
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledWith(
|
||||||
|
filePrefix,
|
||||||
|
mockJsFileName,
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -86,6 +102,11 @@ describe('build/transforms/remove-fenced-code', () => {
|
|||||||
|
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
expect(streamOutput).toStrictEqual(filePrefix);
|
expect(streamOutput).toStrictEqual(filePrefix);
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledWith(
|
||||||
|
filePrefix,
|
||||||
|
mockJsFileName,
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -107,6 +128,57 @@ describe('build/transforms/remove-fenced-code', () => {
|
|||||||
|
|
||||||
stream.on('end', () => {
|
stream.on('end', () => {
|
||||||
expect(streamOutput).toStrictEqual(fileContent);
|
expect(streamOutput).toStrictEqual(fileContent);
|
||||||
|
expect(lintTransformedFileMock).not.toHaveBeenCalled();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.end(fileContent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('skips linting for transformed file if shouldLintTransformedFiles is false', async () => {
|
||||||
|
const filePrefix = '// A comment\n';
|
||||||
|
const fileContent = filePrefix.concat(getMinimalFencedCode());
|
||||||
|
|
||||||
|
const stream = createRemoveFencedCodeTransform(
|
||||||
|
'main',
|
||||||
|
false,
|
||||||
|
)(mockJsFileName);
|
||||||
|
let streamOutput = '';
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
stream.on('data', (data) => {
|
||||||
|
streamOutput = streamOutput.concat(data.toString('utf8'));
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', () => {
|
||||||
|
expect(streamOutput).toStrictEqual(filePrefix);
|
||||||
|
expect(lintTransformedFileMock).not.toHaveBeenCalled();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.end(fileContent);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles transformed file lint failure', async () => {
|
||||||
|
lintTransformedFileMock.mockImplementationOnce(() =>
|
||||||
|
Promise.reject(new Error('lint failure')),
|
||||||
|
);
|
||||||
|
|
||||||
|
const filePrefix = '// A comment\n';
|
||||||
|
const fileContent = filePrefix.concat(getMinimalFencedCode());
|
||||||
|
|
||||||
|
const stream = createRemoveFencedCodeTransform('main')(mockJsFileName);
|
||||||
|
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
stream.on('error', (error) => {
|
||||||
|
expect(error).toStrictEqual(new Error('lint failure'));
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledTimes(1);
|
||||||
|
expect(lintTransformedFileMock).toHaveBeenCalledWith(
|
||||||
|
filePrefix,
|
||||||
|
mockJsFileName,
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
68
development/build/transforms/utils.js
Normal file
68
development/build/transforms/utils.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
const { ESLint } = require('eslint');
|
||||||
|
const eslintrc = require('../../../.eslintrc.js');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The singleton ESLint instance.
|
||||||
|
*
|
||||||
|
* @type {ESLint}
|
||||||
|
*/
|
||||||
|
let eslintInstance;
|
||||||
|
|
||||||
|
// We only need a single ESLint instance, and we only initialize it if necessary
|
||||||
|
const initializeESLint = () => {
|
||||||
|
if (!eslintInstance) {
|
||||||
|
eslintInstance = new ESLint({ baseConfig: eslintrc, useEslintrc: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Four spaces
|
||||||
|
const TAB = ' ';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
lintTransformedFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lints a transformed file by invoking ESLint programmatically on the string
|
||||||
|
* file contents. The path to the file must be specified so that the repository
|
||||||
|
* ESLint config can be applied properly.
|
||||||
|
*
|
||||||
|
* An error is thrown if linting produced any errors, or if the file is ignored
|
||||||
|
* by ESLint. Files linted by this function should never be ignored.
|
||||||
|
*
|
||||||
|
* @param {string} content - The file content.
|
||||||
|
* @param {string} filePath - The path to the file.
|
||||||
|
* @returns {Promise<void>} Returns `undefined` or throws an error if linting produced
|
||||||
|
* any errors, or if the linted file is ignored.
|
||||||
|
*/
|
||||||
|
async function lintTransformedFile(content, filePath) {
|
||||||
|
initializeESLint();
|
||||||
|
|
||||||
|
const lintResult = (
|
||||||
|
await eslintInstance.lintText(content, { filePath, warnIgnored: false })
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
// This indicates that the file is ignored, which should never be the case for
|
||||||
|
// a transformed file.
|
||||||
|
if (lintResult === undefined) {
|
||||||
|
throw new Error(
|
||||||
|
`MetaMask build: Transformed file "${filePath}" appears to be ignored by ESLint.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the success case
|
||||||
|
if (lintResult.errorCount === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errors are stored in the messages array, and their "severity" is 2
|
||||||
|
const errorsString = lintResult.messages
|
||||||
|
.filter(({ severity }) => severity === 2)
|
||||||
|
.reduce((allErrors, { message, ruleId }) => {
|
||||||
|
return allErrors.concat(`${TAB}${ruleId}\n${TAB}${message}\n\n`);
|
||||||
|
}, '');
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`MetaMask build: Lint errors encountered for transformed file "${filePath}":\n\n${errorsString}`,
|
||||||
|
);
|
||||||
|
}
|
71
development/build/transforms/utils.test.js
Normal file
71
development/build/transforms/utils.test.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
const { lintTransformedFile } = require('./utils');
|
||||||
|
|
||||||
|
let mockESLint;
|
||||||
|
|
||||||
|
jest.mock('eslint', () => ({
|
||||||
|
ESLint: class MockESLint {
|
||||||
|
constructor() {
|
||||||
|
if (mockESLint) {
|
||||||
|
throw new Error('Mock ESLint ref already assigned!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line consistent-this
|
||||||
|
mockESLint = this;
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/prefer-spy-on
|
||||||
|
this.lintText = jest.fn();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('transform utils', () => {
|
||||||
|
describe('lintTransformedFile', () => {
|
||||||
|
it('initializes the ESLint singleton', async () => {
|
||||||
|
expect(mockESLint).not.toBeDefined();
|
||||||
|
|
||||||
|
// This error is an artifact of how we're mocking the ESLint singleton,
|
||||||
|
// and won't actually occur in production.
|
||||||
|
await expect(() => lintTransformedFile()).rejects.toThrow(
|
||||||
|
`Cannot read property '0' of undefined`,
|
||||||
|
);
|
||||||
|
expect(mockESLint).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns if linting passes with no errors', async () => {
|
||||||
|
mockESLint.lintText.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve([{ errorCount: 0 }]),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await lintTransformedFile('/* JavaScript */', 'file.js'),
|
||||||
|
).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws if the file is ignored by ESLint', async () => {
|
||||||
|
mockESLint.lintText.mockImplementationOnce(() => Promise.resolve([]));
|
||||||
|
|
||||||
|
await expect(() =>
|
||||||
|
lintTransformedFile('/* JavaScript */', 'file.js'),
|
||||||
|
).rejects.toThrow(
|
||||||
|
/Transformed file "file\.js" appears to be ignored by ESLint\.$/u,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws if linting produced any errors', async () => {
|
||||||
|
const ruleId = 'some-eslint-rule';
|
||||||
|
const message = 'You violated the rule!';
|
||||||
|
|
||||||
|
mockESLint.lintText.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve([
|
||||||
|
{ errorCount: 1, messages: [{ message, ruleId, severity: 2 }] },
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(() =>
|
||||||
|
lintTransformedFile('/* JavaScript */', 'file.js'),
|
||||||
|
).rejects.toThrow(
|
||||||
|
/Lint errors encountered for transformed file "file\.js":\n\n {4}some-eslint-rule\n {4}You violated the rule!\n\n$/u,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -785,6 +785,42 @@
|
|||||||
"console.log": true
|
"console.log": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@eslint/eslintrc": {
|
||||||
|
"builtin": {
|
||||||
|
"assert": true,
|
||||||
|
"fs.existsSync": true,
|
||||||
|
"fs.readFileSync": true,
|
||||||
|
"module.createRequire": true,
|
||||||
|
"module.createRequireFromPath": true,
|
||||||
|
"os.homedir": true,
|
||||||
|
"path.basename": true,
|
||||||
|
"path.dirname": true,
|
||||||
|
"path.extname": true,
|
||||||
|
"path.isAbsolute": true,
|
||||||
|
"path.join": true,
|
||||||
|
"path.relative": true,
|
||||||
|
"path.resolve": true,
|
||||||
|
"path.sep": true,
|
||||||
|
"util.inspect": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"__dirname": true,
|
||||||
|
"process.cwd": true,
|
||||||
|
"process.emitWarning": true,
|
||||||
|
"process.platform": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"ajv": true,
|
||||||
|
"debug": true,
|
||||||
|
"espree": true,
|
||||||
|
"globals": true,
|
||||||
|
"ignore": true,
|
||||||
|
"import-fresh": true,
|
||||||
|
"js-yaml": true,
|
||||||
|
"minimatch": true,
|
||||||
|
"strip-json-comments": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"@gulp-sourcemaps/identity-map": {
|
"@gulp-sourcemaps/identity-map": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"acorn": true,
|
"acorn": true,
|
||||||
@ -897,6 +933,11 @@
|
|||||||
"acorn": true
|
"acorn": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"acorn-jsx": {
|
||||||
|
"packages": {
|
||||||
|
"acorn": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"acorn-node": {
|
"acorn-node": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"acorn": true,
|
"acorn": true,
|
||||||
@ -911,8 +952,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ajv": {
|
"ajv": {
|
||||||
|
"globals": {
|
||||||
|
"console": true
|
||||||
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"fast-deep-equal": true
|
"fast-deep-equal": true,
|
||||||
|
"fast-json-stable-stringify": true,
|
||||||
|
"json-schema-traverse": true,
|
||||||
|
"uri-js": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"amdefine": {
|
"amdefine": {
|
||||||
@ -970,6 +1017,16 @@
|
|||||||
"buffer-equal": true
|
"buffer-equal": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"are-we-there-yet": {
|
||||||
|
"builtin": {
|
||||||
|
"events.EventEmitter": true,
|
||||||
|
"util.inherits": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"delegates": true,
|
||||||
|
"readable-stream": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"arr-diff": {
|
"arr-diff": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"arr-flatten": true,
|
"arr-flatten": true,
|
||||||
@ -1329,6 +1386,7 @@
|
|||||||
"anymatch": true,
|
"anymatch": true,
|
||||||
"async-each": true,
|
"async-each": true,
|
||||||
"braces": true,
|
"braces": true,
|
||||||
|
"fsevents": true,
|
||||||
"glob-parent": true,
|
"glob-parent": true,
|
||||||
"inherits": true,
|
"inherits": true,
|
||||||
"is-binary-path": true,
|
"is-binary-path": true,
|
||||||
@ -1580,6 +1638,16 @@
|
|||||||
"through2": true
|
"through2": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"detect-libc": {
|
||||||
|
"builtin": {
|
||||||
|
"child_process.spawnSync": true,
|
||||||
|
"fs.readdirSync": true,
|
||||||
|
"os.platform": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"process.env": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"detective": {
|
"detective": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"acorn-node": true,
|
"acorn-node": true,
|
||||||
@ -1600,6 +1668,14 @@
|
|||||||
"path-type": true
|
"path-type": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"doctrine": {
|
||||||
|
"builtin": {
|
||||||
|
"assert": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"esutils": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"dom-serializer": {
|
"dom-serializer": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"domelementtype": true,
|
"domelementtype": true,
|
||||||
@ -1729,6 +1805,92 @@
|
|||||||
"source-map": true
|
"source-map": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"eslint": {
|
||||||
|
"builtin": {
|
||||||
|
"assert": true,
|
||||||
|
"fs.existsSync": true,
|
||||||
|
"fs.lstatSync": true,
|
||||||
|
"fs.readFileSync": true,
|
||||||
|
"fs.readdirSync": true,
|
||||||
|
"fs.statSync": true,
|
||||||
|
"fs.unlinkSync": true,
|
||||||
|
"fs.writeFile": true,
|
||||||
|
"fs.writeFileSync": true,
|
||||||
|
"path.extname": true,
|
||||||
|
"path.isAbsolute": true,
|
||||||
|
"path.join": true,
|
||||||
|
"path.normalize": true,
|
||||||
|
"path.relative": true,
|
||||||
|
"path.resolve": true,
|
||||||
|
"path.sep": true,
|
||||||
|
"util.format": true,
|
||||||
|
"util.inspect": true,
|
||||||
|
"util.promisify": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"__dirname": true,
|
||||||
|
"console.log": true,
|
||||||
|
"describe": true,
|
||||||
|
"it": true,
|
||||||
|
"process": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@eslint/eslintrc": true,
|
||||||
|
"ajv": true,
|
||||||
|
"debug": true,
|
||||||
|
"doctrine": true,
|
||||||
|
"eslint-scope": true,
|
||||||
|
"eslint-utils": true,
|
||||||
|
"eslint-visitor-keys": true,
|
||||||
|
"espree": true,
|
||||||
|
"esquery": true,
|
||||||
|
"esutils": true,
|
||||||
|
"file-entry-cache": true,
|
||||||
|
"functional-red-black-tree": true,
|
||||||
|
"glob-parent": true,
|
||||||
|
"globals": true,
|
||||||
|
"ignore": true,
|
||||||
|
"imurmurhash": true,
|
||||||
|
"is-glob": true,
|
||||||
|
"json-stable-stringify-without-jsonify": true,
|
||||||
|
"levn": true,
|
||||||
|
"lodash": true,
|
||||||
|
"minimatch": true,
|
||||||
|
"natural-compare": true,
|
||||||
|
"regexpp": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslint-scope": {
|
||||||
|
"builtin": {
|
||||||
|
"assert": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"esrecurse": true,
|
||||||
|
"estraverse": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"eslint-utils": {
|
||||||
|
"packages": {
|
||||||
|
"eslint-visitor-keys": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"espree": {
|
||||||
|
"packages": {
|
||||||
|
"acorn": true,
|
||||||
|
"acorn-jsx": true,
|
||||||
|
"eslint-visitor-keys": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esquery": {
|
||||||
|
"globals": {
|
||||||
|
"define": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"esrecurse": {
|
||||||
|
"packages": {
|
||||||
|
"estraverse": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"event-emitter": {
|
"event-emitter": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"d": true,
|
"d": true,
|
||||||
@ -1911,7 +2073,9 @@
|
|||||||
"flat-cache": {
|
"flat-cache": {
|
||||||
"builtin": {
|
"builtin": {
|
||||||
"fs.existsSync": true,
|
"fs.existsSync": true,
|
||||||
|
"fs.mkdirSync": true,
|
||||||
"fs.readFileSync": true,
|
"fs.readFileSync": true,
|
||||||
|
"fs.writeFileSync": true,
|
||||||
"path.basename": true,
|
"path.basename": true,
|
||||||
"path.dirname": true,
|
"path.dirname": true,
|
||||||
"path.resolve": true
|
"path.resolve": true
|
||||||
@ -2020,6 +2184,45 @@
|
|||||||
"process.version": true
|
"process.version": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"builtin": {
|
||||||
|
"events.EventEmitter": true,
|
||||||
|
"fs.stat": true,
|
||||||
|
"path.join": true,
|
||||||
|
"util.inherits": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"__dirname": true,
|
||||||
|
"process.nextTick": true,
|
||||||
|
"process.platform": true,
|
||||||
|
"setImmediate": true
|
||||||
|
},
|
||||||
|
"native": true,
|
||||||
|
"packages": {
|
||||||
|
"node-pre-gyp": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gauge": {
|
||||||
|
"builtin": {
|
||||||
|
"util.format": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"clearInterval": true,
|
||||||
|
"process": true,
|
||||||
|
"setImmediate": true,
|
||||||
|
"setInterval": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"aproba": true,
|
||||||
|
"console-control-strings": true,
|
||||||
|
"has-unicode": true,
|
||||||
|
"object-assign": true,
|
||||||
|
"signal-exit": true,
|
||||||
|
"string-width": true,
|
||||||
|
"strip-ansi": true,
|
||||||
|
"wide-align": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"get-assigned-identifiers": {
|
"get-assigned-identifiers": {
|
||||||
"builtin": {
|
"builtin": {
|
||||||
"assert.equal": true
|
"assert.equal": true
|
||||||
@ -2380,6 +2583,16 @@
|
|||||||
"process.argv": true
|
"process.argv": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"has-unicode": {
|
||||||
|
"builtin": {
|
||||||
|
"os.type": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"process.env.LANG": true,
|
||||||
|
"process.env.LC_ALL": true,
|
||||||
|
"process.env.LC_CTYPE": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"has-value": {
|
"has-value": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"get-value": true,
|
"get-value": true,
|
||||||
@ -2533,6 +2746,11 @@
|
|||||||
"is-plain-object": true
|
"is-plain-object": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-fullwidth-code-point": {
|
||||||
|
"packages": {
|
||||||
|
"number-is-nan": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"is-extglob": true
|
"is-extglob": true
|
||||||
@ -2611,6 +2829,11 @@
|
|||||||
"isarray": true
|
"isarray": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"js-yaml": {
|
||||||
|
"globals": {
|
||||||
|
"esprima": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"Buffer.isBuffer": true
|
"Buffer.isBuffer": true
|
||||||
@ -2688,6 +2911,12 @@
|
|||||||
"flush-write-stream": true
|
"flush-write-stream": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"levn": {
|
||||||
|
"packages": {
|
||||||
|
"prelude-ls": true,
|
||||||
|
"type-check": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"define": true
|
"define": true
|
||||||
@ -2917,6 +3146,56 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node-pre-gyp": {
|
||||||
|
"builtin": {
|
||||||
|
"events.EventEmitter": true,
|
||||||
|
"fs.existsSync": true,
|
||||||
|
"fs.readFileSync": true,
|
||||||
|
"fs.renameSync": true,
|
||||||
|
"path.dirname": true,
|
||||||
|
"path.existsSync": true,
|
||||||
|
"path.join": true,
|
||||||
|
"path.resolve": true,
|
||||||
|
"url.parse": true,
|
||||||
|
"url.resolve": true,
|
||||||
|
"util.inherits": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"__dirname": true,
|
||||||
|
"console.log": true,
|
||||||
|
"process.arch": true,
|
||||||
|
"process.cwd": true,
|
||||||
|
"process.env": true,
|
||||||
|
"process.platform": true,
|
||||||
|
"process.version.substr": true,
|
||||||
|
"process.versions": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"detect-libc": true,
|
||||||
|
"nopt": true,
|
||||||
|
"npmlog": true,
|
||||||
|
"rimraf": true,
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nopt": {
|
||||||
|
"builtin": {
|
||||||
|
"path": true,
|
||||||
|
"stream.Stream": true,
|
||||||
|
"url": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"console": true,
|
||||||
|
"process.argv": true,
|
||||||
|
"process.env.DEBUG_NOPT": true,
|
||||||
|
"process.env.NOPT_DEBUG": true,
|
||||||
|
"process.platform": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"abbrev": true,
|
||||||
|
"osenv": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"remove-trailing-separator": true
|
"remove-trailing-separator": true
|
||||||
@ -2932,6 +3211,22 @@
|
|||||||
"once": true
|
"once": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"npmlog": {
|
||||||
|
"builtin": {
|
||||||
|
"events.EventEmitter": true,
|
||||||
|
"util": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"process.nextTick": true,
|
||||||
|
"process.stderr": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"are-we-there-yet": true,
|
||||||
|
"console-control-strings": true,
|
||||||
|
"gauge": true,
|
||||||
|
"set-blocking": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"object-copy": {
|
"object-copy": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"copy-descriptor": true,
|
"copy-descriptor": true,
|
||||||
@ -2998,6 +3293,54 @@
|
|||||||
"readable-stream": true
|
"readable-stream": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"os-homedir": {
|
||||||
|
"builtin": {
|
||||||
|
"os.homedir": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"process.env": true,
|
||||||
|
"process.getuid": true,
|
||||||
|
"process.platform": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os-tmpdir": {
|
||||||
|
"globals": {
|
||||||
|
"process.env.SystemRoot": true,
|
||||||
|
"process.env.TEMP": true,
|
||||||
|
"process.env.TMP": true,
|
||||||
|
"process.env.TMPDIR": true,
|
||||||
|
"process.env.windir": true,
|
||||||
|
"process.platform": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"osenv": {
|
||||||
|
"builtin": {
|
||||||
|
"child_process.exec": true,
|
||||||
|
"path": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"process.env.COMPUTERNAME": true,
|
||||||
|
"process.env.ComSpec": true,
|
||||||
|
"process.env.EDITOR": true,
|
||||||
|
"process.env.HOSTNAME": true,
|
||||||
|
"process.env.PATH": true,
|
||||||
|
"process.env.PROMPT": true,
|
||||||
|
"process.env.PS1": true,
|
||||||
|
"process.env.Path": true,
|
||||||
|
"process.env.SHELL": true,
|
||||||
|
"process.env.USER": true,
|
||||||
|
"process.env.USERDOMAIN": true,
|
||||||
|
"process.env.USERNAME": true,
|
||||||
|
"process.env.VISUAL": true,
|
||||||
|
"process.env.path": true,
|
||||||
|
"process.nextTick": true,
|
||||||
|
"process.platform": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"os-homedir": true,
|
||||||
|
"os-tmpdir": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"parent-module": {
|
"parent-module": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"callsites": true
|
"callsites": true
|
||||||
@ -3580,6 +3923,12 @@
|
|||||||
"process": true
|
"process": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"set-blocking": {
|
||||||
|
"globals": {
|
||||||
|
"process.stderr": true,
|
||||||
|
"process.stdout": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"set-value": {
|
"set-value": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"extend-shallow": true,
|
"extend-shallow": true,
|
||||||
@ -3782,6 +4131,7 @@
|
|||||||
},
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"code-point-at": true,
|
||||||
"emoji-regex": true,
|
"emoji-regex": true,
|
||||||
"is-fullwidth-code-point": true,
|
"is-fullwidth-code-point": true,
|
||||||
"strip-ansi": true
|
"strip-ansi": true
|
||||||
@ -4040,6 +4390,11 @@
|
|||||||
"through2": true
|
"through2": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"type-check": {
|
||||||
|
"packages": {
|
||||||
|
"prelude-ls": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"typedarray-to-buffer": {
|
"typedarray-to-buffer": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"Buffer.from": true
|
"Buffer.from": true
|
||||||
@ -4145,6 +4500,11 @@
|
|||||||
"path": true
|
"path": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"uri-js": {
|
||||||
|
"globals": {
|
||||||
|
"define": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"urix": {
|
"urix": {
|
||||||
"builtin": {
|
"builtin": {
|
||||||
"path.sep": true
|
"path.sep": true
|
||||||
@ -4348,6 +4708,11 @@
|
|||||||
"isexe": true
|
"isexe": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"wide-align": {
|
||||||
|
"packages": {
|
||||||
|
"string-width": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"write": {
|
"write": {
|
||||||
"builtin": {
|
"builtin": {
|
||||||
"fs.createWriteStream": true,
|
"fs.createWriteStream": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user