Use local-registry for E2E tests (#2821)

This commit is contained in:
Adam L Barrett 2020-05-09 10:05:17 -06:00 committed by GitHub
parent 2c7bcbdd74
commit 515cc37ec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 203 additions and 273 deletions

View File

@ -40,7 +40,7 @@ forEachCli('nx', () => {
expect(affectedHelp).toContain('Run task for affected projects');
const version = runCLI(`--version`);
expect(version).toContain('*'); // stub value
expect(version).toContain(process.env.PUBLISHED_VERSION); // stub value
}, 120000);
});
});
@ -72,7 +72,7 @@ forEachCli('angular', () => {
expect(affectedHelp).toContain('Run task for affected projects');
const version = runCLI(`--version`);
expect(version).toContain('*'); // stub value
expect(version).toContain(process.env.PUBLISHED_VERSION); // stub value
}, 120000);
});
});

7
e2e/jest-config.ts Normal file
View File

@ -0,0 +1,7 @@
const pkg = require('../../package.json');
module.exports = {
...pkg.jest,
globalSetup: '<rootDir>/local-registry/setup.js',
globalTeardown: '<rootDir>/local-registry/teardown.js',
};

View File

@ -13,8 +13,16 @@ forEachCli(() => {
it('should be able to generate a testable library using karma', async (done) => {
ensureProject();
// run an app
const myapp = uniq('myapp');
runCLI(
`generate @nrwl/angular:app ${myapp} --unit-test-runner karma --no-interactive`
);
const mylib = uniq('mylib');
runCLI(`generate @nrwl/angular:lib ${mylib} --unit-test-runner karma`);
runCLI(
`generate @nrwl/angular:lib ${mylib} --unit-test-runner karma --no-interactive`
);
patchKarmaToWorkOnWSL();
await Promise.all([
@ -24,13 +32,16 @@ forEachCli(() => {
const karmaResult = await runCLIAsync(`test ${mylib}`);
expect(karmaResult.stdout).toContain('3 SUCCESS');
done();
}, 30000);
}, 45000);
it('should be able to generate a testable application using karma', async (done) => {
ensureProject();
const myapp = uniq('myapp');
runCLI(`generate @nrwl/angular:app ${myapp} --unit-test-runner karma`);
runCLI(
`generate @nrwl/angular:app ${myapp} --unit-test-runner karma --no-interactive`
);
patchKarmaToWorkOnWSL();
await Promise.all([

View File

@ -0,0 +1,38 @@
# path to a directory with all packages
storage: ../../build/e2e/local-registry/storage
auth:
htpasswd:
file: ./htpasswd
# a list of other known repositories we can talk to
uplinks:
npmjs:
url: https://registry.npmjs.org/
cache: true
yarn:
url: https://registry.yarnpkg.com
cache: true
packages:
'@*/*':
# scoped packages
access: $all
publish: $all
unpublish: $all
proxy: npmjs
'**':
# allow all users (including non-authenticated users) to read and
# publish all packages
access: $all
# allow all users (including non-authenticated users) to publish/publish packages
publish: $all
unpublish: $all
# if package is not available locally, proxy requests to 'yarn' registry
proxy: npmjs
# log settings
logs:
- { type: stdout, format: pretty, level: http }

View File

@ -0,0 +1 @@
test:$6FrCaT/v0dwE:autocreated 2020-03-25T19:10:50.254Z

View File

@ -0,0 +1,58 @@
import { promisify } from 'util';
import { spawn, exec } from 'child_process';
import { getDirectories } from '../utils';
const asyncExec = promisify(exec);
process.env.PUBLISHED_VERSION = `9999.0.0`;
async function spawnLocalRegistry() {
const localRegistryProcess = spawn('npx', [
'verdaccio',
'--config',
'./e2e/local-registry/config.yml',
'--listen',
'4872',
]);
try {
await new Promise((res, rej) => {
localRegistryProcess.stdout.on('data', (data) => {
// wait for local-registry to come online
if (data.includes('http address')) {
res();
}
});
localRegistryProcess.on('error', (err) => {
rej(err);
});
});
} catch (err) {
console.error(err);
throw err;
}
return localRegistryProcess;
}
async function updateVersion(packagePath) {
return exec(`npm version ${process.env.PUBLISHED_VERSION}`, {
cwd: packagePath,
});
}
async function publishPackage(packagePath) {
await asyncExec(`npm publish`, {
cwd: packagePath,
env: process.env,
});
}
module.exports = async function setup() {
// @ts-ignore
global.localRegistryProcess = await spawnLocalRegistry();
await Promise.all(
getDirectories('./build/packages').map(async (pkg) => {
await updateVersion(`./build/packages/${pkg}`);
return await publishPackage(`./build/packages/${pkg}`);
})
);
};

View File

@ -0,0 +1,10 @@
module.exports = async function teardown() {
const { exec } = require('child_process');
const { promisify } = require('util');
const asyncExec = promisify(exec);
// @ts-ignore
global.localRegistryProcess.kill();
// get rid of the local-registry storage
await asyncExec(`rm -rf build/e2e/local-registry/storage`);
};

View File

@ -1,10 +1,8 @@
import {
checkFilesExist,
cleanup,
copyMissingPackages,
readJson,
runCLI,
runCLIAsync,
runCommand,
runNew,
updateFile,
@ -51,8 +49,7 @@ forEachCli('angular', () => {
updateFile('angular.json', JSON.stringify(angularCLIJson, null, 2));
// run the command
runNgAdd('add @nrwl/workspace --npmScope projscope --skip-install');
copyMissingPackages();
runNgAdd('add @nrwl/workspace --npmScope projscope');
// check that prettier config exits and that files have been moved!
checkFilesExist(

View File

@ -8,7 +8,6 @@ import {
checkFilesDoNotExist,
checkFilesExist,
cleanup,
copyMissingPackages,
ensureProject,
forEachCli,
readFile,
@ -21,6 +20,7 @@ import {
uniq,
updateFile,
workspaceConfigName,
yarnAdd,
} from './utils';
function getData(): Promise<any> {
@ -161,8 +161,8 @@ forEachCli((currentCLIName) => {
// them from their config files as happened with emitDecoratorMetadata.
cleanup();
runNew('', false, false);
runNgAdd('add @nrwl/workspace --npmScope projscope --skip-install');
copyMissingPackages();
runNgAdd('add @nrwl/workspace --npmScope projscope');
yarnAdd('@nrwl/nest');
} else {
ensureProject();
}

View File

@ -89,13 +89,29 @@ function patchPackageJsonDeps(addWorkspace = true) {
}
export function runYarnInstall(silent: boolean = true) {
const install = execSync('yarn install', {
const install = execSync(`yarn install`, {
cwd: tmpProjPath(),
...(silent ? { stdio: ['ignore', 'ignore', 'ignore'] } : {}),
env: process.env,
});
return install ? install.toString() : '';
}
export function yarnAdd(pkg: string) {
console.log(`YARN ADDING PACKAGES: ${pkg}`);
const install = execSync(`yarn add ${pkg}`, {
cwd: tmpProjPath(),
...{ stdio: ['ignore', 'ignore', 'ignore'] },
env: process.env,
});
return install ? install.toString() : '';
}
export const getDirectories = (source) =>
readdirSync(source, { withFileTypes: true })
.filter((dirent) => dirent.isDirectory())
.map((dirent) => dirent.name);
export function runNgcc(silent: boolean = true, async: boolean = true) {
const install = execSync(
'node ./node_modules/@angular/compiler-cli/ngcc/main-ngcc.js' +
@ -103,6 +119,7 @@ export function runNgcc(silent: boolean = true, async: boolean = true) {
{
cwd: tmpProjPath(),
...(silent ? { stdio: ['ignore', 'ignore', 'ignore'] } : {}),
env: process.env,
}
);
return install ? install.toString() : '';
@ -123,29 +140,26 @@ export function runNew(
let gen;
if (cli === 'angular') {
gen = execSync(
`../../node_modules/.bin/ng new proj --no-interactive --skip-install ${
args || ''
}`,
`../../node_modules/.bin/ng new proj --no-interactive ${args || ''}`,
{
cwd: `./tmp/${cli}`,
...(silent ? { stdio: ['ignore', 'ignore', 'ignore'] } : {}),
env: process.env,
}
);
} else {
gen = execSync(
`node ../../node_modules/@nrwl/tao/index.js new proj --no-interactive --skip-install ${
`node ../../node_modules/@nrwl/tao/index.js new proj --no-interactive ${
args || ''
}`,
{
cwd: `./tmp/${cli}`,
...(silent && false ? { stdio: ['ignore', 'ignore', 'ignore'] } : {}),
env: process.env,
}
);
}
patchPackageJsonDeps(addWorkspace);
const install = runYarnInstall(silent && false);
return silent ? null : `${gen ? gen.toString() : ''}${install}`;
return silent ? null : `${gen ? gen.toString() : ''}`;
}
/**
@ -156,27 +170,11 @@ export function newProject(): void {
cleanup();
if (!directoryExists(tmpBackupProjPath())) {
runNew('--collection=@nrwl/workspace --npmScope=proj', true);
copyMissingPackages();
writeFileSync(
tmpProjPath(
'node_modules/@angular-devkit/schematics/tasks/node-package/executor.js'
),
`
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const rxjs_1 = require("rxjs");
function default_1(factoryOptions = {}) {
return (options) => {
return new rxjs_1.Observable(obs => {
obs.complete();
});
};
}
exports.default = default_1;`
);
const inCI = process.env['CIRCLECI'] ? true : false;
runNgcc(!inCI, !inCI);
const packages = getDirectories('./build/packages')
.filter((pkg) => !pkg.startsWith('create-'))
.map((pkg) => `@nrwl/${pkg}`);
yarnAdd(packages.join(' '));
execSync(`mv ${tmpProjPath()} ${tmpBackupProjPath()}`);
}
@ -191,9 +189,7 @@ exports.default = default_1;`
* If one is not found, it creates a new project.
*/
export function ensureProject(): void {
if (!directoryExists(tmpProjPath())) {
newProject();
}
newProject();
}
export function supportUi() {
@ -201,160 +197,6 @@ export function supportUi() {
// return !process.env.NO_CHROME;
}
export function copyMissingPackages(): void {
const modulesToCopy = [
'@ngrx',
'@nrwl',
'angular',
'@angular',
'@angular-devkit',
'codelyzer',
'ngrx-store-freeze',
'npm-run-all',
'yargs',
'yargs-parser',
'ng-packagr',
'cypress',
'@jest',
'jest',
'@types/jest',
'@types/node',
'jest-preset-angular',
'identity-obj-proxy',
'karma',
'karma-chrome-launcher',
'karma-coverage-istanbul-reporter',
'karma-jasmine',
'karma-jasmine-html-reporter',
'jasmine-core',
'jasmine-spec-reporter',
'jasmine-marbles',
'@types/jasmine',
'@types/jasminewd2',
'@nestjs',
'express',
'@types/express',
'protractor',
'react',
'react-dom',
'react-redux',
'react-router-dom',
'@reduxjs',
'@reduxjs/toolkit',
'styled-components',
'@types/react',
'@types/react-dom',
'@types/react-redux',
'@types/react-router-dom',
'@testing-library',
// For testing webpack config with babel-loader
'@babel',
'@svgr/webpack',
'babel-loader',
'babel-plugin-const-enum',
'babel-plugin-macros',
'eslint-plugin-import',
'eslint-plugin-jsx-a11y',
'eslint-plugin-react',
'eslint-plugin-react-hooks',
'url-loader',
// For testing web bundle
'rollup',
'@rollup',
'rollup-plugin-babel',
'rollup-plugin-filesize',
'rollup-plugin-local-resolve',
'rollup-plugin-peer-deps-external',
'rollup-plugin-postcss',
'rollup-plugin-typescript2',
'next',
'document-register-element',
'@angular/forms',
'@storybook',
'fork-ts-checker-webpack-plugin',
// For web builder with inlined build-angular
'source-map',
'webpack-sources',
'terser',
'caniuse-lite',
'browserslist',
'license-webpack-plugin',
'webpack-subresource-integrity',
'autoprefixer',
'mini-css-extract-plugin',
'postcss-import',
'worker-plugin',
'regenerator-runtime',
'clean-css',
'loader-utils',
'postcss',
'url',
'circular-dependency-plugin',
'terser-webpack-plugin',
'parse5',
'cacache',
'find-cache-dir',
'tree-kill',
'speed-measure-webpack-plugin',
'webpack-merge',
'semver',
'css-loader',
'mime',
'less',
'send',
'@bazel',
];
modulesToCopy.forEach((m) => copyNodeModule(m));
updateFile(
'node_modules/@angular-devkit/schematics/tasks/node-package/executor.js',
`
function default_1() {
return () => {
const rxjs = require("rxjs");
return new rxjs.Observable(obs => {
obs.next();
obs.complete();
});
};
}
exports.default = default_1;
`
);
execSync(`rm -rf ${tmpProjPath('node_modules/.bin/webpack')}`);
execSync(
`cp -a node_modules/.bin/webpack ${tmpProjPath(
'node_modules/.bin/webpack'
)}`
);
execSync(`rm -rf ${tmpProjPath('node_modules/.bin/bazel')}`);
execSync(
`cp -a node_modules/.bin/bazel ${tmpProjPath('node_modules/.bin/bazel')}`
);
execSync(`rm -rf ${tmpProjPath('node_modules/cypress/node_modules/@types')}`);
execSync(`rm -rf node_modules/karma/node_modules/mime`);
execSync(`rm -rf node_modules/ng-packagr/node_modules/mime`);
}
function copyNodeModule(name: string) {
const source = `node_modules/${name}`;
const destination = tmpProjPath(source);
execSync(`rm -rf ${destination}`);
execSync(`cp -a ${source} ${destination}`);
}
export function runCommandAsync(
command: string,
opts: RunCmdOpts = {
@ -364,9 +206,10 @@ export function runCommandAsync(
): Promise<{ stdout: string; stderr: string }> {
return new Promise((resolve, reject) => {
exec(
`${command}`,
command,
{
cwd: tmpProjPath(),
env: process.env,
},
(err, stdout, stderr) => {
if (!opts.silenceError && err) {
@ -385,10 +228,7 @@ export function runCLIAsync(
env: process.env,
}
): Promise<{ stdout: string; stderr: string }> {
return runCommandAsync(
`node ./node_modules/@nrwl/cli/bin/nx.js ${command}`,
opts
);
return runCommandAsync(`./node_modules/.bin/nx ${command}`, opts);
}
export function runNgAdd(
@ -426,7 +266,7 @@ export function runCLI(
}
): string {
try {
const r = execSync(`node ./node_modules/@nrwl/cli/bin/nx.js ${command}`, {
const r = execSync(`./node_modules/.bin/nx ${command}`, {
cwd: tmpProjPath(),
env: opts.env,
})
@ -463,6 +303,7 @@ export function runCommand(command: string): string {
const r = execSync(command, {
cwd: tmpProjPath(),
stdio: ['pipe', 'pipe', 'pipe'],
env: process.env,
}).toString();
console.log(r);
return r;

View File

@ -19,7 +19,7 @@
"e2e-ci4": "./scripts/e2e-ci4.sh",
"test-create-nx-workspace": "./scripts/test-create-nx-workspace.sh",
"format": "./scripts/format.sh",
"linknpm": "./scripts/link.sh",
"linknpm": "./scripts/link.sh --local",
"nx-release": "./scripts/nx-release.js",
"copy": "./scripts/copy.sh",
"test": "yarn linknpm fast && ./scripts/test.sh",
@ -90,7 +90,7 @@
"@types/jasmine": "~2.8.6",
"@types/jasminewd2": "~2.0.3",
"@types/jest": "25.1.4",
"@types/node": "10.0.1",
"@types/node": "12.12.38",
"@types/prettier": "2.0.0",
"@types/react": "16.9.17",
"@types/react-dom": "16.9.4",

View File

@ -1,21 +1,24 @@
import { Rule } from '@angular-devkit/schematics';
import { angularJsVersion } from './versions';
import { updateJsonInTree } from '@nrwl/workspace';
import { addDepsToPackageJson, readJsonInTree } from '@nrwl/workspace';
export function addUpgradeToPackageJson(): Rule {
return updateJsonInTree('package.json', (packageJson) => {
return (host, context) => {
const packageJson = readJsonInTree(host, './package.json');
const dependencies = {};
if (!packageJson['dependencies']) {
packageJson['dependencies'] = {};
packageJson['dependencies'] = dependencies;
}
if (!packageJson['dependencies']['@angular/upgrade']) {
packageJson['dependencies']['@angular/upgrade'] =
dependencies['@angular/upgrade'] =
packageJson['dependencies']['@angular/core'];
}
if (!packageJson['dependencies']['angular']) {
packageJson['dependencies']['angular'] = angularJsVersion;
dependencies['angular'] = angularJsVersion;
}
return packageJson;
});
return addDepsToPackageJson(dependencies, {});
};
}

View File

@ -1,11 +1,4 @@
import {
Rule,
Tree,
externalSchematic,
noop,
} from '@angular-devkit/schematics';
import { readJsonInTree } from '../ast-utils';
import { externalSchematic, Rule } from '@angular-devkit/schematics';
/**
* Calls init _if_ the package does not already exist
@ -17,13 +10,5 @@ export function addPackageWithInit(
e2eTestRunner?: 'cypress' | 'none';
} = { unitTestRunner: 'jest', e2eTestRunner: 'cypress' }
): Rule {
return (host: Tree) => {
const { dependencies, devDependencies } = readJsonInTree(
host,
'package.json'
);
return dependencies[packageName] || devDependencies[packageName]
? noop()
: externalSchematic(packageName, 'init', { ...testRunners });
};
return externalSchematic(packageName, 'init', { ...testRunners });
}

View File

@ -1,11 +1,8 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
mkdir -p tmp/nx
jest --maxWorkers=1 ./build/e2e/commands/create-playground.test.js
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest --maxWorkers=1 -c "./build/e2e/jest-config.js" ./build/e2e/commands/create-playground.test.js

View File

@ -1,14 +1,9 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
mkdir -p tmp/nx
export SELECTED_CLI=$1
jest --maxWorkers=1 ./build/e2e/angular.test.js &&
jest --maxWorkers=1 ./build/e2e/cli.test.js &&
jest --maxWorkers=1 ./build/e2e/workspace.test.js &&
jest --maxWorkers=1 ./build/e2e/workspace-aux-commands.test.js &&
jest --maxWorkers=1 ./build/e2e/cypress.test.js
PUBLISHED_VERSION=9999.0.0 npm_config_registry=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 "./build/e2e/(angular|cli|workspace|workspace-aux-commands|cypress).test.js"

View File

@ -1,14 +1,10 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
mkdir -p tmp/nx
export SELECTED_CLI=$1
jest --maxWorkers=1 ./build/e2e/jest.test.js &&
jest --maxWorkers=1 ./build/e2e/karma.test.js &&
jest --maxWorkers=1 ./build/e2e/next.test.js &&
jest --maxWorkers=1 ./build/e2e/nx-plugin.test.js &&
jest --maxWorkers=1 ./build/e2e/downgrade-module.test.js
PUBLISHED_VERSION=9999.0.0 npm_config_registry=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 "./build/e2e/(jest|karma|next|nx-plugin|downgrade-module).test.js"

View File

@ -1,15 +1,10 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
mkdir -p tmp/nx
export SELECTED_CLI=$1
jest --maxWorkers=1 ./build/e2e/storybook.test.js &&
jest --maxWorkers=1 ./build/e2e/upgrade-module.test.js &&
jest --maxWorkers=1 ./build/e2e/web.test.js &&
jest --maxWorkers=1 ./build/e2e/angular-package.test.js &&
jest --maxWorkers=1 ./build/e2e/react-package.test.js &&
jest --maxWorkers=1 ./build/e2e/ngrx.test.js
PUBLISHED_VERSION=9999.0.0 npm_config_registry=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 "./build/e2e/(storybook|upgrade-module|web|angular-package|react-package|ngrx).test.js"

View File

@ -1,12 +1,10 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
mkdir -p tmp/nx
export SELECTED_CLI=$1
jest --maxWorkers=1 ./build/e2e/ng-add.test.js &&
jest --maxWorkers=1 ./build/e2e/node.test.js &&
jest --maxWorkers=1 ./build/e2e/react.test.js
PUBLISHED_VERSION=9999.0.0 npm_config_registry=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 "./build/e2e/(ng-add|node|react).test.js"

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp/nx/proj/node_modules/@nrwl
rm -rf tmp/angular/proj/node_modules/@nrwl
@ -8,9 +8,9 @@ cp -r node_modules/@nrwl tmp/nx/proj/node_modules/@nrwl
cp -r node_modules/@nrwl tmp/angular/proj/node_modules/@nrwl
if [ -n "$1" ]; then
jest --maxWorkers=1 ./build/e2e/$1.test.js
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 ./build/e2e/$1.test.js
else
jest --maxWorkers=1 ./build/e2e
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 ./build/e2e
fi

View File

@ -1,6 +1,5 @@
#!/usr/bin/env bash
./scripts/link.sh
./scripts/link.sh 9999.0.0
rm -rf tmp
mkdir -p tmp/angular
@ -11,10 +10,10 @@ if [ -n "$1" ]; then
COMMAND_FILE="./build/e2e/commands/$1.test.js"
if [ -f "$TEST_FILE" ]; then
jest --maxWorkers=1 $TEST_FILE
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 $TEST_FILE
else
jest --maxWorkers=1 $COMMAND_FILE
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 $COMMAND_FILE
fi
else
jest --maxWorkers=1 ./build/e2e/*.test.js
PUBLISHED_VERSION=9999.0.0 NPM_CONFIG_REGISTRY=http://localhost:4872/ jest -c "./build/e2e/jest-config.js" --maxWorkers=1 ./build/e2e/*.test.js
fi

View File

@ -5,7 +5,7 @@ if [ "$1" = "fast" ]; then
fi
if [ "$1" != "fast" ]; then
./scripts/package.sh --local
./scripts/package.sh $1
fi
rm -rf node_modules/@nrwl

View File

@ -9,7 +9,6 @@ LOCALBUILD=$3
PACKAGE_SOURCE=build/packages
NPM_DEST=build/npm
ORIG_DIRECTORY=`pwd`
NPM_REGISTRY=`npm config get registry` # for local releases
# We are running inside of a child_process, so we need to reauth
npm adduser

View File

@ -4692,10 +4692,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.5.tgz#e19436e7f8e9b4601005d73673b6dc4784ffcc2f"
integrity sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==
"@types/node@10.0.1":
version "10.0.1"
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.0.1.tgz#9095e8b9b10d1de6d49a939b2f65c2872a47afd9"
integrity sha512-HKTs07TC1RJRBd9z0Kf/cy37j2HCbUfcVKS6Xm9orZVcLqZ1JXWe/JTDLw6AwxmLOxV45fDpOMPXyqXU3TfOPQ==
"@types/node@12.12.38":
version "12.12.38"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.38.tgz#58841a382f231ad005dbb935c36d44aa1118a26b"
integrity sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"