From 493438e2d2f6a9c11d5260a3119b1ea1923eea98 Mon Sep 17 00:00:00 2001 From: mrmeku Date: Mon, 11 Nov 2019 17:39:28 -0700 Subject: [PATCH] fix(error-handling): Give more feedback for common errors Place feedback in output channel rather than debug console Telemetry for invalid angular.json parsing / node_modules caching Error messaging for angular.json missing Error message for node_modules missing --- angular.json | 2 +- .../src/app/ng-task/ng-task-provider.ts | 35 +-- apps/vscode/src/app/output-channel.ts | 10 + apps/vscode/src/main.ts | 210 +++++++++++------- apps/vscode/src/package.json | 2 +- libs/server/src/index.ts | 2 + libs/server/src/lib/utils/utils.ts | 36 +-- package.json | 1 + tools/gen-build-files.ts | 89 ++++++++ yarn.lock | 80 ++++++- 10 files changed, 352 insertions(+), 115 deletions(-) create mode 100644 apps/vscode/src/app/output-channel.ts create mode 100644 tools/gen-build-files.ts diff --git a/angular.json b/angular.json index f793af3b49..747d34d019 100644 --- a/angular.json +++ b/angular.json @@ -23,7 +23,7 @@ { "glob": "README.md", "input": "./", - "output": "/assets/" + "output": "/" }, { "glob": "**/*", diff --git a/apps/vscode/src/app/ng-task/ng-task-provider.ts b/apps/vscode/src/app/ng-task/ng-task-provider.ts index d2b0273ce9..25b6598817 100644 --- a/apps/vscode/src/app/ng-task/ng-task-provider.ts +++ b/apps/vscode/src/app/ng-task/ng-task-provider.ts @@ -1,23 +1,24 @@ -import { readJsonFile } from '@angular-console/server'; +import { readAndParseJson } from '@angular-console/server'; +import { existsSync } from 'fs'; +import { join } from 'path'; import { ProviderResult, Task, + TaskExecution, TaskProvider, - window, tasks, - TaskExecution + window } from 'vscode'; -import * as path from 'path'; +import { getTelemetry } from '../telemetry'; import { NgTask } from './ng-task'; import { AngularJson, + NamedProject, NgTaskDefinition, ProjectDef, - NamedProject, Projects } from './ng-task-definition'; -import { getTelemetry } from '../telemetry'; export class NgTaskProvider implements TaskProvider { private workspacePath?: string; @@ -70,6 +71,16 @@ export class NgTaskProvider implements TaskProvider { } executeTask(definition: NgTaskDefinition) { + if ( + !this.workspacePath || + !existsSync(join(this.workspacePath, 'node_modules')) + ) { + window.showErrorMessage( + 'Could not execute task since node_modules directory is missing. Run npm install.' + ); + return; + } + const isDryRun = definition.flags.includes('--dry-run'); if (isDryRun && this.currentDryRun) { this.deferredDryRun = definition; @@ -94,14 +105,12 @@ export class NgTaskProvider implements TaskProvider { } try { - const { projects } = readJsonFile('angular.json', this.workspacePath) - .json as AngularJson; + const { projects } = readAndParseJson( + join(this.workspacePath, 'angular.json') + ).json as AngularJson; return projects; - } catch { - window.showErrorMessage( - 'Your angular.json file is invalid (see debug console)' - ); + } catch (e) { return {}; } } @@ -118,7 +127,7 @@ export class NgTaskProvider implements TaskProvider { if (!this.workspacePath) return null; const entry = this.getProjectEntries().find(([_, def]) => - selectedPath.startsWith(path.join(this.workspacePath!, def.root)) + selectedPath.startsWith(join(this.workspacePath!, def.root)) ); return entry ? { name: entry[0], ...entry[1] } : null; diff --git a/apps/vscode/src/app/output-channel.ts b/apps/vscode/src/app/output-channel.ts new file mode 100644 index 0000000000..49d0bd6066 --- /dev/null +++ b/apps/vscode/src/app/output-channel.ts @@ -0,0 +1,10 @@ +import { OutputChannel, window } from 'vscode'; + +let _channel: OutputChannel; + +export function getOutputChannel(): OutputChannel { + if (!_channel) { + _channel = window.createOutputChannel('Angular Console'); + } + return _channel; +} diff --git a/apps/vscode/src/main.ts b/apps/vscode/src/main.ts index c0d3b2aed0..1829a7f993 100644 --- a/apps/vscode/src/main.ts +++ b/apps/vscode/src/main.ts @@ -1,6 +1,10 @@ -import { cacheJsonFiles, EXTENSIONS } from '@angular-console/server'; +import { + cacheJsonFiles, + EXTENSIONS, + readAndParseJson +} from '@angular-console/server'; import { stream } from 'fast-glob'; -import { existsSync, readFileSync } from 'fs'; +import { existsSync } from 'fs'; import { dirname, join, parse } from 'path'; import { commands, @@ -16,6 +20,7 @@ import { AngularJsonTreeItem } from './app/angular-json-tree/angular-json-tree-i import { AngularJsonTreeProvider } from './app/angular-json-tree/angular-json-tree-provider'; import { registerNgTaskCommands } from './app/ng-task/ng-task-commands'; import { NgTaskProvider } from './app/ng-task/ng-task-provider'; +import { getTelemetry, initTelemetry } from './app/telemetry'; import { VSCodeStorage } from './app/vscode-storage'; import { revealWebViewPanel } from './app/webview'; import { WorkspaceTreeItem } from './app/workspace-tree/workspace-tree-item'; @@ -23,7 +28,7 @@ import { LOCATE_YOUR_WORKSPACE, WorkspaceTreeProvider } from './app/workspace-tree/workspace-tree-provider'; -import { initTelemetry } from './app/telemetry'; +import { getOutputChannel } from './app/output-channel'; let workspaceTreeView: TreeView; let angularJsonTreeView: TreeView; @@ -35,81 +40,100 @@ let ngTaskProvider: NgTaskProvider; let context: ExtensionContext; export function activate(c: ExtensionContext) { - context = c; - currentWorkspaceTreeProvider = WorkspaceTreeProvider.create({ - extensionPath: context.extensionPath - }); - const store = VSCodeStorage.fromContext(context); - initTelemetry(context, store); - - ngTaskProvider = new NgTaskProvider(); - tasks.registerTaskProvider('ng', ngTaskProvider); - - registerNgTaskCommands(context, ngTaskProvider); - - workspaceTreeView = window.createTreeView('angularConsole', { - treeDataProvider: currentWorkspaceTreeProvider - }) as TreeView; - context.subscriptions.push(workspaceTreeView); - - angularJsonTreeProvider = new AngularJsonTreeProvider( - context, - ngTaskProvider - ); - - angularJsonTreeView = window.createTreeView('angularConsoleJson', { - treeDataProvider: angularJsonTreeProvider - }) as TreeView; - context.subscriptions.push(angularJsonTreeView); - - context.subscriptions.push( - commands.registerCommand( - 'angularConsole.revealWebViewPanel', - async (workspaceTreeItem: WorkspaceTreeItem) => { - switch (workspaceTreeItem.route) { - case 'Add': - const extensions = Object.entries(EXTENSIONS).map( - ([label, description]): QuickPickItem => ({ - label, - description - }) + try { + context = c; + currentWorkspaceTreeProvider = WorkspaceTreeProvider.create({ + extensionPath: context.extensionPath + }); + const store = VSCodeStorage.fromContext(context); + initTelemetry(context, store); + + ngTaskProvider = new NgTaskProvider(); + tasks.registerTaskProvider('ng', ngTaskProvider); + + registerNgTaskCommands(context, ngTaskProvider); + + workspaceTreeView = window.createTreeView('angularConsole', { + treeDataProvider: currentWorkspaceTreeProvider + }) as TreeView; + context.subscriptions.push(workspaceTreeView); + + angularJsonTreeProvider = new AngularJsonTreeProvider( + context, + ngTaskProvider + ); + + angularJsonTreeView = window.createTreeView('angularConsoleJson', { + treeDataProvider: angularJsonTreeProvider + }) as TreeView; + context.subscriptions.push(angularJsonTreeView); + + context.subscriptions.push( + commands.registerCommand( + 'angularConsole.revealWebViewPanel', + async (workspaceTreeItem: WorkspaceTreeItem) => { + if ( + !existsSync(join(workspaceTreeItem.workspacePath, 'node_modules')) + ) { + window.showErrorMessage( + 'Angular Console requires your workspace have a node_modules directory. Run npm install.' ); - window.showQuickPick(extensions).then(selection => { - if (!selection) { - return; - } - - ngTaskProvider.executeTask({ - command: 'add', - positional: selection.label, - flags: [] + return; + } + switch (workspaceTreeItem.route) { + case 'Add': + const extensions = Object.entries(EXTENSIONS).map( + ([label, description]): QuickPickItem => ({ + label, + description + }) + ); + window.showQuickPick(extensions).then(selection => { + if (!selection) { + return; + } + + ngTaskProvider.executeTask({ + command: 'add', + positional: selection.label, + flags: [] + }); }); - }); + } + + revealWebViewPanel({ + workspaceTreeItem, + context, + ngTaskProvider, + workspaceTreeView + }); } + ) + ); + context.subscriptions.push( + commands.registerCommand( + LOCATE_YOUR_WORKSPACE.command!.command, + async () => { + return await locateAngularWorkspace(); + } + ) + ); - revealWebViewPanel({ - workspaceTreeItem, - context, - ngTaskProvider, - workspaceTreeView - }); - } - ) - ); - context.subscriptions.push( - commands.registerCommand( - LOCATE_YOUR_WORKSPACE.command!.command, - async () => { - return await locateAngularWorkspace(); - } - ) - ); + const vscodeWorkspacePath = + workspace.workspaceFolders && workspace.workspaceFolders[0].uri.fsPath; - const vscodeWorkspacePath = - workspace.workspaceFolders && workspace.workspaceFolders[0].uri.fsPath; + if (vscodeWorkspacePath) { + scanForWorkspace(vscodeWorkspacePath); + } + } catch (e) { + window.showErrorMessage( + 'Angular Console encountered an error when activating (see output panel)' + ); - if (vscodeWorkspacePath) { - scanForWorkspace(vscodeWorkspacePath); + getOutputChannel().appendLine( + 'Angular Console encountered an error when activating' + ); + getOutputChannel().appendLine(JSON.stringify(e)); } } @@ -161,18 +185,24 @@ function scanForWorkspace(vscodeWorkspacePath: string) { async function setAngularWorkspace(workspacePath: string) { try { - JSON.parse(readFileSync(join(workspacePath, 'angular.json')).toString()); + readAndParseJson(join(workspacePath, 'angular.json')); } catch (e) { - console.error('Invalid angular JSON', e); window.showErrorMessage( - 'Your angular.json file is invalid (see debug console)' + 'Invalid angular.json (see output panel for details)' ); - commands.executeCommand('setContext', 'isAngularWorkspace', false); - return; + getOutputChannel().appendLine( + 'Invalid angular JSON: ' + join(workspacePath, 'angular.json') + ); + + const stringifiedError = e.toString ? e.toString() : JSON.stringify(e); + getOutputChannel().appendLine(stringifiedError); + getTelemetry().exceptionOccured(stringifiedError); } - cacheJsonFiles(workspacePath); - setInterval(() => cacheJsonFiles(workspacePath), 60000); + setTimeout(() => { + cacheWorkspaceNodeModulesJsons(workspacePath); + }, 0); + setInterval(() => cacheWorkspaceNodeModulesJsons(workspacePath), 60000); commands.executeCommand('setContext', 'isAngularWorkspace', true); @@ -182,3 +212,25 @@ async function setAngularWorkspace(workspacePath: string) { } export async function deactivate() {} + +function cacheWorkspaceNodeModulesJsons(workspacePath: string) { + if (!existsSync(join(workspacePath, 'node_modules'))) { + getOutputChannel().appendLine( + 'Tried to cache node_modules but directory was not present. Run npm install' + ); + return; + } + + try { + cacheJsonFiles(workspacePath); + } catch (e) { + window.showErrorMessage( + 'Angular Console encountered an error when scanning node_modules' + ); + getOutputChannel().appendLine('Error parsing node_modules '); + + const stringifiedError = e.toString ? e.toString() : JSON.stringify(e); + getOutputChannel().appendLine(stringifiedError); + getTelemetry().exceptionOccured(stringifiedError); + } +} diff --git a/apps/vscode/src/package.json b/apps/vscode/src/package.json index ef42c1df1d..199279c253 100644 --- a/apps/vscode/src/package.json +++ b/apps/vscode/src/package.json @@ -5,7 +5,7 @@ "version": "9.0.0", "repository": { "type": "git", - "url": "https://github.com/nrwl/angular-console" + "url": "https://github.com/nrwl/angular-console.git" }, "author": { "name": "Narwhal Technologies Inc", diff --git a/libs/server/src/index.ts b/libs/server/src/index.ts index 19913531df..fa720aba87 100644 --- a/libs/server/src/index.ts +++ b/libs/server/src/index.ts @@ -1,3 +1,5 @@ +export { readAndParseJson } from './lib/utils/utils'; + export { findClosestNg } from './lib/utils/utils'; export { cacheJsonFiles } from './lib/utils/utils'; diff --git a/libs/server/src/lib/utils/utils.ts b/libs/server/src/lib/utils/utils.ts index a02f94ce3d..dc2e4afddd 100644 --- a/libs/server/src/lib/utils/utils.ts +++ b/libs/server/src/lib/utils/utils.ts @@ -3,7 +3,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'fs'; import { platform } from 'os'; import * as path from 'path'; -const stripJsonComments = require('strip-json-comments'); // tslint:disable-line +import * as stripJsonComments from 'strip-json-comments'; export interface SchematicDefaults { [name: string]: string; @@ -88,6 +88,10 @@ export function findClosestNg(dir: string): string { export function listOfUnnestedNpmPackages(nodeModulesDir: string): string[] { const res: string[] = []; + if (!existsSync(nodeModulesDir)) { + return res; + } + readdirSync(nodeModulesDir).forEach(npmPackageOrScope => { if (npmPackageOrScope.startsWith('@')) { readdirSync(path.join(nodeModulesDir, npmPackageOrScope)).forEach(p => { @@ -124,22 +128,18 @@ export function listFiles(dirName: string): string[] { } export function cacheJsonFiles(basedir: string) { - try { - const nodeModulesDir = path.join(basedir, 'node_modules'); - const packages = listOfUnnestedNpmPackages(nodeModulesDir); - - const res: any = {}; - packages.forEach(p => { - const filePath = path.join(nodeModulesDir, p, 'package.json'); - if (!fileExistsSync(filePath)) return; - res[filePath] = readAndParseJson( - path.join(nodeModulesDir, p, 'package.json') - ); - }); - return res; - } catch (e) { - return {}; - } + const nodeModulesDir = path.join(basedir, 'node_modules'); + const packages = listOfUnnestedNpmPackages(nodeModulesDir); + + const res: any = {}; + packages.forEach(p => { + const filePath = path.join(nodeModulesDir, p, 'package.json'); + if (!fileExistsSync(filePath)) return; + res[filePath] = readAndParseJson( + path.join(nodeModulesDir, p, 'package.json') + ); + }); + return res; } export function directoryExists(filePath: string): boolean { @@ -158,7 +158,7 @@ export function fileExistsSync(filePath: string): boolean { } } -function readAndParseJson(fullFilePath: string): any { +export function readAndParseJson(fullFilePath: string): any { return JSON.parse(stripJsonComments(readFileSync(fullFilePath).toString())); } diff --git a/package.json b/package.json index 98a58e3808..8932b983ca 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "codelyzer": "5.1.0", "cypress": "3.4.0", "fast-glob": "3.0.4", + "husky": "^3.0.9", "jest": "24.1.0", "jest-preset-angular": "7.0.0", "nps": "5.9.3", diff --git a/tools/gen-build-files.ts b/tools/gen-build-files.ts new file mode 100644 index 0000000000..6589890ca1 --- /dev/null +++ b/tools/gen-build-files.ts @@ -0,0 +1,89 @@ +import { readFileSync } from 'fs'; +import * as stripJsonComments from 'strip-json-comments'; +import { join } from 'path'; + +export enum ProjectType { + app = 'app', + e2e = 'e2e', + lib = 'lib' +} + +export function readJsonFile(path: string): T { + return JSON.parse(stripJsonComments(readFileSync(path, 'utf-8'))); +} + +export type ProjectNode = { + name: string; + root: string; + type: ProjectType; + architect: { [k: string]: any }; + implicitDependencies: string[]; +}; + +export function getProjectNodes(workspaceJson: any): ProjectNode[] { + const workspaceJsonProjects = Object.keys(workspaceJson.projects); + + return workspaceJsonProjects.map(key => { + const p = workspaceJson.projects[key]; + + const projectType = + p.projectType === 'application' + ? key.endsWith('-e2e') + ? ProjectType.e2e + : ProjectType.app + : ProjectType.lib; + + let implicitDependencies: string[] = []; + if (projectType === ProjectType.e2e) { + implicitDependencies = [key.replace(/-e2e$/, '')]; + } + + return { + name: key, + root: p.root, + type: projectType, + architect: p.architect || {}, + implicitDependencies + }; + }); +} + +export function readWorkspaceJson(): any { + return readJsonFile(join(__dirname, '..', 'angular.json')); +} + +export function generateGraph( + args: { file?: string; filter?: string[]; exclude?: string[] }, + affectedProjects: string[] +): void { + const workspaceJson = readWorkspaceJson(); + const projects: ProjectNode[] = getProjectNodes(workspaceJson); + const deps = readDependencies(nxJson.npmScope, projects); +} + +export function filterProjects(deps, projects, filter, exclude) { + const filteredProjects = projects.filter(p => { + const filtered = + filter && filter.length > 0 + ? filter.find( + f => hasPath(deps, f, p.name, []) || hasPath(deps, p.name, f, []) + ) + : true; + return !exclude + ? filtered + : exclude && exclude.indexOf(p.name) === -1 && filtered; + }); + + return filteredProjects; +} + +export function hasPath(deps, target, node, visited) { + if (target === node) return true; + + for (let d of deps[node]) { + if (visited.indexOf(d.projectName) > -1) continue; + if (hasPath(deps, target, d.projectName, [...visited, d.projectName])) + return true; + } + return false; +} diff --git a/yarn.lock b/yarn.lock index 2c5fb2503c..af892dfdbc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1565,6 +1565,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.7.tgz#01e4ea724d9e3bd50d90c11fd5980ba317d8fa11" integrity sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + "@types/shelljs@^0.8.2": version "0.8.6" resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.6.tgz#45193a51df99e0f00513c39a2152832399783221" @@ -3379,7 +3384,7 @@ cosmiconfig@4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" -cosmiconfig@^5.0.0, cosmiconfig@^5.2.0: +cosmiconfig@^5.0.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== @@ -5442,6 +5447,23 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +husky@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.9.tgz#a2c3e9829bfd6b4957509a9500d2eef5dbfc8044" + integrity sha512-Yolhupm7le2/MqC1VYLk/cNmYxsSsqKkTyBhzQHhPK1jFnC89mmmNVuGtLNabjDI6Aj8UNIr0KpRNuBkiC4+sg== + dependencies: + chalk "^2.4.2" + ci-info "^2.0.0" + cosmiconfig "^5.2.1" + execa "^1.0.0" + get-stdin "^7.0.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" + please-upgrade-node "^3.2.0" + read-pkg "^5.2.0" + run-node "^1.0.0" + slash "^3.0.0" + iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -6873,6 +6895,11 @@ license-webpack-plugin@^1.4.0: dependencies: ejs "^2.5.7" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + linkify-it@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" @@ -7782,7 +7809,7 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -8100,6 +8127,11 @@ open@6.4.0: dependencies: is-wsl "^1.1.0" +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + opn-cli@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/opn-cli/-/opn-cli-3.1.0.tgz#f819ae6cae0b411bd0149b8560fe6c88adad20f8" @@ -8395,6 +8427,16 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" + integrity sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + lines-and-columns "^1.1.6" + parse-semver@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/parse-semver/-/parse-semver-1.1.1.tgz#9a4afd6df063dc4826f93fba4a99cf223f666cb8" @@ -8583,13 +8625,20 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" +please-upgrade-node@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" + integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== + dependencies: + semver-compare "^1.0.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -9129,6 +9178,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + read@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" @@ -9590,6 +9649,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" + integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== + run-parallel@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" @@ -9736,6 +9800,11 @@ selfsigned@^1.10.4, selfsigned@^1.10.7, selfsigned@^1.9.1: dependencies: node-forge "0.9.0" +semver-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" + integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= + semver-dsl@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/semver-dsl/-/semver-dsl-1.0.1.tgz#d3678de5555e8a61f629eed025366ae5f27340a0" @@ -11083,6 +11152,11 @@ type-fest@^0.5.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.5.2.tgz#d6ef42a0356c6cd45f49485c3b6281fc148e48a2" integrity sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"