feat: allow ignoring dependent packages in case a irrelevant file was changed

close #3021
PR #3035
This commit is contained in:
Idan Attias
2020-12-22 14:59:10 +02:00
committed by GitHub
parent 8aeb30c56e
commit a8656b42fa
14 changed files with 235 additions and 52 deletions

View File

@@ -0,0 +1,7 @@
---
"@pnpm/filter-workspace-packages": minor
"pnpm": minor
"@pnpm/config": minor
---
Filter files matching this filter from the git changed file list when running the test command

View File

@@ -121,6 +121,8 @@ export interface Config {
registries: Registries
ignoreWorkspaceRootCheck: boolean
workspaceRoot: boolean
testPattern?: string[]
}
export interface ConfigWithDeprecatedSettings extends Config {

View File

@@ -91,6 +91,7 @@ export const types = Object.assign({
'workspace-concurrency': Number,
'workspace-packages': [String, Array],
'workspace-root': Boolean,
'test-pattern': String,
}, npmTypes.types)
export type CliOptions = Record<string, unknown> & { dir?: string }

View File

@@ -583,3 +583,31 @@ test('local prefix search stops on pnpm-workspace.yaml', async () => {
expect(config.dir).toEqual(workspaceDir)
})
test('respects test-pattern', async () => {
{
const { config } = await getConfig({
cliOptions: {},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
})
expect(config.testPattern).toBeUndefined()
}
{
const workspaceDir = path.join(__dirname, 'using-test-pattern')
process.chdir(workspaceDir)
const { config } = await getConfig({
cliOptions: {},
packageManager: {
name: 'pnpm',
version: '1.0.0',
},
workspaceDir,
})
expect(config.testPattern).toEqual(['*.spec.js', '*.spec.ts'])
}
})

View File

@@ -0,0 +1,2 @@
test-pattern[]=*.spec.js
test-pattern[]=*.spec.ts

View File

@@ -35,6 +35,7 @@
"execa": "^4.1.0",
"find-up": "^5.0.0",
"is-subdir": "^1.1.1",
"micromatch": "^4.0.2",
"pkgs-graph": "workspace:5.2.0",
"ramda": "^0.27.1"
},
@@ -42,6 +43,7 @@
"@pnpm/filter-workspace-packages": "link:",
"@types/is-ci": "^2.0.0",
"@types/is-windows": "^1.0.0",
"@types/micromatch": "^4.0.1",
"@types/ramda": "^0.27.34",
"@types/touch": "^3.1.1",
"is-ci": "^2.0.0",

View File

@@ -1,27 +1,37 @@
import PnpmError from '@pnpm/error'
import * as micromatch from 'micromatch'
import path = require('path')
import execa = require('execa')
import findUp = require('find-up')
import isSubdir = require('is-subdir')
export default async function changedSince (packageDirs: string[], commit: string, opts: { workspaceDir: string }): Promise<string[]> {
type ChangeType = 'source' | 'test'
interface ChangedDir { dir: string, changeType: ChangeType }
export default async function changedSince (packageDirs: string[], commit: string, opts: { workspaceDir: string, testPattern?: string[] }): Promise<[string[], string[]]> {
const repoRoot = path.resolve(await findUp('.git', { cwd: opts.workspaceDir, type: 'directory' }) ?? opts.workspaceDir, '..')
let changedDirs = Array.from(
await getChangedDirsSinceCommit(commit, opts.workspaceDir)
).map(changedDir => path.join(repoRoot, changedDir))
const changedPkgs = []
const changedDirs = (await getChangedDirsSinceCommit(commit, opts.workspaceDir, opts.testPattern ?? []))
.map(changedDir => ({ ...changedDir, dir: path.join(repoRoot, changedDir.dir) }))
let changedSourceDirs = changedDirs.filter(changedDir => changedDir.changeType === 'source')
const changedPkgs: string[] = []
for (const packageDir of packageDirs.sort((pkgDir1, pkgDir2) => pkgDir2.length - pkgDir1.length)) {
if (
changedDirs.some(changedDir => isSubdir(packageDir, changedDir))
changedSourceDirs.some(changedDir => isSubdir(packageDir, changedDir.dir))
) {
changedDirs = changedDirs.filter((changedDir) => !isSubdir(packageDir, changedDir))
changedSourceDirs = changedSourceDirs.filter((changedDir) => !isSubdir(packageDir, changedDir.dir))
changedPkgs.push(packageDir)
}
}
return changedPkgs
const ignoreDependentForPkgs = changedDirs.filter(changedDir => changedDir.changeType === 'test')
.filter(changedDir => changedPkgs.find(pkg => changedDir.dir.startsWith(pkg)))
.map(changedDir => changedDir.dir)
return [changedPkgs, ignoreDependentForPkgs]
}
async function getChangedDirsSinceCommit (commit: string, workingDir: string) {
async function getChangedDirsSinceCommit (commit: string, workingDir: string, testPattern: string[]): Promise<ChangedDir[]> {
let diff!: string
try {
diff = (
@@ -36,15 +46,24 @@ async function getChangedDirsSinceCommit (commit: string, workingDir: string) {
} catch (err) {
throw new PnpmError('FILTER_CHANGED', `Filtering by changed packages failed. ${err.stderr as string}`)
}
const changedDirs = new Set<string>()
const changedDirs = new Set<ChangedDir>()
const dirsMatchingFilter = new Set<ChangedDir>()
if (!diff) {
return changedDirs
return []
}
const changedFiles = diff.split('\n')
for (const changedFile of changedFiles) {
changedDirs.add(path.dirname(changedFile))
const dirName = path.dirname(changedFile)
changedDirs.add({ dir: dirName, changeType: 'source' })
if (testPattern.some(pattern => micromatch.isMatch(changedFile, pattern))) {
dirsMatchingFilter.add({ dir: dirName, changeType: 'test' })
}
}
return changedDirs
return [...Array.from(changedDirs), ...Array.from(dirsMatchingFilter)]
}

View File

@@ -42,6 +42,7 @@ export async function filterPackages<T> (
linkWorkspacePackages?: boolean
prefix: string
workspaceDir: string
testPattern?: string[]
}
): Promise<{
selectedProjectsGraph: PackageGraph<T>
@@ -59,6 +60,7 @@ export function filterPkgsBySelectorObjects<T> (
opts: {
linkWorkspacePackages?: boolean
workspaceDir: string
testPattern?: string[]
}
): Promise<{
selectedProjectsGraph: PackageGraph<T>
@@ -68,6 +70,7 @@ export function filterPkgsBySelectorObjects<T> (
if (packageSelectors?.length) {
return filterGraph(graph, packageSelectors, {
workspaceDir: opts.workspaceDir,
testPattern: opts.testPattern,
})
} else {
return Promise.resolve({ selectedProjectsGraph: graph, unmatchedFilters: [] })
@@ -79,6 +82,7 @@ export default async function filterGraph<T> (
packageSelectors: PackageSelector[],
opts: {
workspaceDir: string
testPattern?: string[]
}
): Promise<{
selectedProjectsGraph: PackageGraph<T>
@@ -106,6 +110,7 @@ async function _filterGraph<T> (
pkgGraph: PackageGraph<T>,
opts: {
workspaceDir: string
testPattern?: string[]
},
packageSelectors: PackageSelector[]
): Promise<{
@@ -121,9 +126,10 @@ async function _filterGraph<T> (
let reversedGraph: Graph | undefined
for (const selector of packageSelectors) {
let entryPackages: string[] | null = null
let ignoreDependentForPkgs: string[] = []
if (selector.diff) {
entryPackages = await getChangedPkgs(Object.keys(pkgGraph),
selector.diff, { workspaceDir: selector.parentDir ?? opts.workspaceDir })
[entryPackages, ignoreDependentForPkgs] = await getChangedPkgs(Object.keys(pkgGraph),
selector.diff, { workspaceDir: selector.parentDir ?? opts.workspaceDir, testPattern: opts.testPattern })
} else if (selector.parentDir) {
entryPackages = matchPackagesByPath(pkgGraph, selector.parentDir)
}
@@ -155,7 +161,7 @@ async function _filterGraph<T> (
if (!reversedGraph) {
reversedGraph = reverseGraph(graph)
}
pickSubgraph(reversedGraph, entryPackages, walkedDependents, { includeRoot: !selector.excludeSelf })
pickSubgraph(reversedGraph, entryPackages, walkedDependents, { includeRoot: !selector.excludeSelf, finalNodes: ignoreDependentForPkgs })
}
if (selector.includeDependencies && selector.includeDependents) {
@@ -217,6 +223,7 @@ function pickSubgraph (
walked: Set<string>,
opts: {
includeRoot: boolean
finalNodes?: string[]
}
) {
for (const nextNodeId of nextNodeIds) {
@@ -225,7 +232,11 @@ function pickSubgraph (
walked.add(nextNodeId)
}
if (graph[nextNodeId]) pickSubgraph(graph, graph[nextNodeId], walked, { includeRoot: true })
if (opts.finalNodes?.includes(nextNodeId)) {
continue
}
if (graph[nextNodeId]) pickSubgraph(graph, graph[nextNodeId], walked, { includeRoot: true, finalNodes: opts.finalNodes })
}
}
}

View File

@@ -219,12 +219,16 @@ test('select changed packages', async () => {
const pkg1Dir = path.join(workspaceDir, 'package-1')
await mkdir(pkg1Dir)
await touch(path.join(pkg1Dir, 'file.js'))
await touch(path.join(pkg1Dir, 'file1.js'))
const pkg2Dir = path.join(workspaceDir, 'package-2')
await mkdir(pkg2Dir)
await touch(path.join(pkg2Dir, 'file.js'))
await touch(path.join(pkg2Dir, 'file2.js'))
const pkg3Dir = path.join(workspaceDir, 'package-3')
await mkdir(pkg3Dir)
await execa('git', ['add', '.'], { cwd: workspaceDir })
await execa('git', ['commit', '--allow-empty-message', '-m', '', '--no-gpg-sign'], { cwd: workspaceDir })
@@ -262,6 +266,16 @@ test('select changed packages', async () => {
},
},
},
[pkg3Dir]: {
dependencies: [pkg2Dir],
package: {
dir: pkg3Dir,
manifest: {
name: 'package-3',
version: '0.0.0',
},
},
},
[pkg20Dir]: {
dependencies: [],
package: {
@@ -297,6 +311,14 @@ test('select changed packages', async () => {
expect(Object.keys(selectedProjectsGraph)).toStrictEqual([pkg2Dir])
}
{
const { selectedProjectsGraph } = await filterWorkspacePackages(pkgsGraph, [{
diff: 'HEAD~1',
includeDependents: true,
}], { workspaceDir, testPattern: ['*/file2.js'] })
expect(Object.keys(selectedProjectsGraph)).toStrictEqual([pkg1Dir, pkg2Dir])
}
})
test('selection should fail when diffing to a branch that does not exist', async () => {

View File

@@ -75,7 +75,7 @@ test('pnpm recursive test', async () => {
expect(outputs2).toStrictEqual(['project-1', 'project-3'])
})
test('`pnpm recursive test` does not fail if none of the packaegs has a test command', async () => {
test('`pnpm recursive test` does not fail if none of the packages has a test command', async () => {
preparePackages([
{
name: 'project-1',

View File

@@ -102,6 +102,7 @@
"split-cmd": "^1.0.1",
"strip-ansi": "^6.0.0",
"symlink-dir": "^4.1.0",
"tempy": "^1.0.0",
"tree-kill": "^1.2.2",
"which": "^2.0.2",
"write-json-file": "^4.3.0",

View File

@@ -175,6 +175,7 @@ export default async function run (inputArgv: string[]) {
linkWorkspacePackages: !!config.linkWorkspacePackages,
prefix: process.cwd(),
workspaceDir: wsDir,
testPattern: cmd === 'test' ? config.testPattern : undefined,
})
config.selectedProjectsGraph = filterResults.selectedProjectsGraph
if (R.isEmpty(config.selectedProjectsGraph)) {

View File

@@ -11,10 +11,12 @@ import { fromDir as readPackageJsonFromDir } from '@pnpm/read-package-json'
import readYamlFile from 'read-yaml-file'
import { execPnpm, execPnpmSync, execPnpxSync } from '../utils'
import path = require('path')
import execa = require('execa')
import rimraf = require('@zkochan/rimraf')
import fs = require('mz/fs')
import exists = require('path-exists')
import symlink = require('symlink-dir')
import tempy = require('tempy')
import writeYamlFile = require('write-yaml-file')
test('no projects matched the filters', async () => {
@@ -267,6 +269,75 @@ test('topological order of packages with self-dependencies in monorepo is correc
expect(outputs2).toStrictEqual(['project-2', 'project-3', 'project-1'])
})
test('test-pattern is respected by the test script', async () => {
const remote = tempy.directory()
preparePackages([
{
name: 'project-1',
version: '1.0.0',
dependencies: { 'project-2': '1.0.0', 'project-3': '1.0.0' },
devDependencies: { 'json-append': '1' },
scripts: {
test: 'node -e "process.stdout.write(\'project-1\')" | json-append ../output.json',
},
},
{
name: 'project-2',
version: '1.0.0',
dependencies: {},
devDependencies: { 'json-append': '1' },
scripts: {
test: 'node -e "process.stdout.write(\'project-2\')" | json-append ../output.json',
},
},
{
name: 'project-3',
version: '1.0.0',
dependencies: { 'project-2': '1.0.0' },
devDependencies: { 'json-append': '1' },
scripts: {
test: 'node -e "process.stdout.write(\'project-3\')" | json-append ../output.json',
},
},
{
name: 'project-4',
version: '1.0.0',
dependencies: {},
devDependencies: { 'json-append': '1' },
scripts: {
test: 'node -e "process.stdout.write(\'project-4\')" | json-append ../output.json',
},
},
])
await execa('git', ['init'])
await execa('git', ['config', 'user.email', 'x@y.z'])
await execa('git', ['config', 'user.name', 'xyz'])
await execa('git', ['init', '--bare'], { cwd: remote })
await execa('git', ['add', '*'])
await execa('git', ['commit', '-m', 'init', '--no-gpg-sign'])
await execa('git', ['remote', 'add', 'origin', remote])
await execa('git', ['push', '-u', 'origin', 'master'])
await fs.writeFile('project-2/file.js', '')
await fs.writeFile('project-4/different-pattern.js', '')
await fs.writeFile('.npmrc', 'test-pattern[]=*/file.js', 'utf8')
await writeYamlFile('pnpm-workspace.yaml', { packages: ['**', '!store/**'] })
await execa('git', ['add', '.'])
await execa('git', ['commit', '--allow-empty-message', '-m', '', '--no-gpg-sign'])
process.chdir('project-1')
await execPnpm(['install'])
await execPnpm(['recursive', 'test', '--filter', '...[origin/master]'])
const { default: output } = await import(path.resolve('..', 'output.json'))
expect(output.sort()).toStrictEqual(['project-2', 'project-4'])
})
test('do not get confused by filtered dependencies when searching for dependents in monorepo', async () => {
/*
In this test case, we are filtering for 'project-2' and its dependents with

80
pnpm-lock.yaml generated
View File

@@ -494,12 +494,14 @@ importers:
execa: 4.1.0
find-up: 5.0.0
is-subdir: 1.1.1
micromatch: 4.0.2
pkgs-graph: 'link:../pkgs-graph'
ramda: 0.27.1
devDependencies:
'@pnpm/filter-workspace-packages': 'link:'
'@types/is-ci': 2.0.0
'@types/is-windows': 1.0.0
'@types/micromatch': 4.0.1
'@types/ramda': 0.27.34
'@types/touch': 3.1.1
is-ci: 2.0.0
@@ -513,6 +515,7 @@ importers:
'@pnpm/matcher': 'workspace:1.0.3'
'@types/is-ci': ^2.0.0
'@types/is-windows': ^1.0.0
'@types/micromatch': ^4.0.1
'@types/ramda': ^0.27.34
'@types/touch': ^3.1.1
execa: ^4.1.0
@@ -520,6 +523,7 @@ importers:
is-ci: ^2.0.0
is-subdir: ^1.1.1
is-windows: ^1.0.2
micromatch: ^4.0.2
pkgs-graph: 'workspace:5.2.0'
ramda: ^0.27.1
tempy: ^1.0.0
@@ -2258,6 +2262,7 @@ importers:
split-cmd: 1.0.1
strip-ansi: 6.0.0
symlink-dir: 4.1.0
tempy: 1.0.0
tree-kill: 1.2.2
which: 2.0.2
write-json-file: 4.3.0
@@ -2347,6 +2352,7 @@ importers:
split-cmd: ^1.0.1
strip-ansi: ^6.0.0
symlink-dir: ^4.1.0
tempy: ^1.0.0
tree-kill: ^1.2.2
update-notifier: ^5.0.1
which: ^2.0.2
@@ -3971,7 +3977,7 @@ packages:
engines:
node: '>= 8'
resolution:
integrity: sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==
integrity: sha1-Olgr21OATGum0UZXnEblITDPSjs=
/@nodelib/fs.stat/1.1.3:
dev: true
engines:
@@ -3982,15 +3988,15 @@ packages:
engines:
node: '>= 8'
resolution:
integrity: sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==
integrity: sha1-NNxfTKu8cg9OYPdadH5+zWwXW9M=
/@nodelib/fs.walk/1.2.4:
dependencies:
'@nodelib/fs.scandir': 2.1.3
fastq: 1.9.0
fastq: 1.10.0
engines:
node: '>= 8'
resolution:
integrity: sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==
integrity: sha1-ARuSAqcKY2bkNspcBlhEUoqwSXY=
/@pnpm/colorize-semver-diff/1.0.1:
dependencies:
chalk: 4.1.0
@@ -4171,6 +4177,10 @@ packages:
dev: true
resolution:
integrity: sha512-kSjgDMZONiIfSH1Nxcr5JIRMwUetDki63FSQfpTCz8ogF3Ulqm8+mr5f78dUYs6vMiB6gBusQqfQmBvHZj/lwg==
/@types/braces/3.0.0:
dev: true
resolution:
integrity: sha1-faHA1E/xx+tmCjbsB46mG6frQss=
/@types/byline/4.2.32:
dependencies:
'@types/node': 14.14.14
@@ -4288,6 +4298,12 @@ packages:
dev: true
resolution:
integrity: sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w==
/@types/micromatch/4.0.1:
dependencies:
'@types/braces': 3.0.0
dev: true
resolution:
integrity: sha1-k4FEndZZ/Dgj/SpBkM6syYUIO8c=
/@types/minimatch/3.0.3:
resolution:
integrity: sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
@@ -5387,7 +5403,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
integrity: sha1-t5hCCtvrHego2ErNii4j0+/oXo0=
/array-uniq/1.0.3:
dev: true
engines:
@@ -5663,7 +5679,7 @@ packages:
balanced-match: 1.0.0
concat-map: 0.0.1
resolution:
integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
integrity: sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=
/braces/2.3.2:
dependencies:
arr-flatten: 1.1.0
@@ -5687,7 +5703,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
integrity: sha1-NFThpGLujVmeI23zNs2epPiv4Qc=
/breakword/1.0.5:
dependencies:
wcwidth: 1.0.1
@@ -6752,7 +6768,7 @@ packages:
engines:
node: '>=10'
resolution:
integrity: sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==
integrity: sha1-C0DQMyzqdD8WFPgYvk/rcXcUyVI=
/delay/4.4.0:
engines:
node: '>=6'
@@ -6845,7 +6861,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
integrity: sha1-Vtv3PZkqSpO6FYT0U0Bj/S5BcX8=
/dir-is-case-sensitive/1.0.2:
dependencies:
graceful-fs: 4.2.4
@@ -7582,7 +7598,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==
integrity: sha1-0grvv5lXk4Pn88xmUpFYybmFVNM=
/fast-json-stable-stringify/2.1.0:
resolution:
integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
@@ -7593,11 +7609,11 @@ packages:
/fast-safe-stringify/1.1.13:
resolution:
integrity: sha1-oB6c2cnkkXFcmKdaQtXwu9EH/3Y=
/fastq/1.9.0:
/fastq/1.10.0:
dependencies:
reusify: 1.0.4
resolution:
integrity: sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==
integrity: sha1-dNvvzK3pZJMs31AEc+8wJxnGUrs=
/fb-watchman/2.0.1:
dependencies:
bser: 2.1.1
@@ -7650,7 +7666,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
integrity: sha1-GRmmp8df44ssfHflGYU12prN2kA=
/finalhandler/1.1.2:
dependencies:
debug: 2.6.9
@@ -8072,7 +8088,7 @@ packages:
engines:
node: '>= 6'
resolution:
integrity: sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
integrity: sha1-tsHvQXxOVmPqSY8cRa+saRa7wik=
/glob-stream/6.1.0:
dependencies:
extend: 3.0.2
@@ -8154,7 +8170,7 @@ packages:
engines:
node: '>=10'
resolution:
integrity: sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==
integrity: sha1-mivxB6Bo8//qvEmtcCx57ejP01c=
/globby/9.2.0:
dependencies:
'@types/glob': 7.1.3
@@ -8486,7 +8502,7 @@ packages:
engines:
node: '>= 4'
resolution:
integrity: sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
integrity: sha1-8VCotQo0KJsz4i9YiavU2AFvDlc=
/immediate/3.2.3:
dev: true
resolution:
@@ -8783,7 +8799,7 @@ packages:
engines:
node: '>=0.10.0'
resolution:
integrity: sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
integrity: sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw=
/is-gzip/1.0.0:
dev: false
engines:
@@ -8842,7 +8858,7 @@ packages:
engines:
node: '>=0.12.0'
resolution:
integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
integrity: sha1-dTU0W4lnNNX4DE0GxQlVUnoU8Ss=
/is-obj/2.0.0:
engines:
node: '>=8'
@@ -8856,7 +8872,7 @@ packages:
engines:
node: '>=6'
resolution:
integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==
integrity: sha1-Z9Q7gmZKe1GR/ZEZEn6zAASKn9s=
/is-path-inside/3.0.2:
engines:
node: '>=8'
@@ -10372,7 +10388,7 @@ packages:
engines:
node: '>= 8'
resolution:
integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
integrity: sha1-Q2iJL4hekHRVpv19xVwMnUBJkK4=
/methods/1.1.2:
dev: true
engines:
@@ -10406,7 +10422,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
integrity: sha1-T8sJmb+fvC/L3SEvbWKbmlbDklk=
/mime-db/1.44.0:
engines:
node: '>= 0.6'
@@ -10466,7 +10482,7 @@ packages:
dependencies:
brace-expansion: 1.1.11
resolution:
integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
integrity: sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=
/minimist-options/4.1.0:
dependencies:
arrify: 1.0.1
@@ -11177,7 +11193,7 @@ packages:
engines:
node: '>=10'
resolution:
integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
integrity: sha1-uy+Vpe2i7BaOySdOBqdHw+KQTSs=
/p-memoize/4.0.1:
dependencies:
mem: 6.1.1
@@ -11417,7 +11433,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
integrity: sha1-hO0BwKe6OAr+CdkKjBgNzZ0DBDs=
/peek-stream/1.1.3:
dependencies:
buffer-from: 1.1.1
@@ -11433,7 +11449,7 @@ packages:
engines:
node: '>=8.6'
resolution:
integrity: sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
integrity: sha1-IfMz6ba46v8CRo9RRupAbTRfTa0=
/pidtree/0.3.1:
dev: true
engines:
@@ -12373,7 +12389,7 @@ packages:
iojs: '>=1.0.0'
node: '>=0.10.0'
resolution:
integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
integrity: sha1-kNo4Kx4SbvwCFG6QhFqI2xKSXXY=
/right-pad/1.0.1:
dev: false
engines:
@@ -12439,7 +12455,7 @@ packages:
integrity: sha512-2hIL01Osd6FWsQVhVGqJ7drNikmTaUg2A/VBR98+LuhQ1jV1Xlh43BQH4gJiNaOzfHJTasD0pw5YviIfdVVY4g==
/run-parallel/1.1.10:
resolution:
integrity: sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==
integrity: sha1-YKUbKug2Y2yBN33xbLEHNRvNE+8=
/rx-lite/3.1.2:
dev: true
resolution:
@@ -12722,7 +12738,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
integrity: sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ=
/slice-ansi/2.1.0:
dependencies:
ansi-styles: 3.2.1
@@ -13274,7 +13290,7 @@ packages:
engines:
node: '>=8'
resolution:
integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==
integrity: sha1-vekrBb3+sVFugEycAK1FF38xMh4=
/tempy/0.6.0:
dependencies:
is-stream: 2.0.0
@@ -13296,7 +13312,7 @@ packages:
engines:
node: '>=10'
resolution:
integrity: sha512-eLXG5B1G0mRPHmgH2WydPl5v4jH35qEn3y/rA/aahKhIa91Pn119SsU7n7v/433gtT9ONzC8ISvNHIh2JSTm0w==
integrity: sha1-TxkrPuMyiiaE0OP8XEkUJTlaq2U=
/term-size/1.2.0:
dependencies:
execa: 0.7.0
@@ -13449,7 +13465,7 @@ packages:
engines:
node: '>=8.0'
resolution:
integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
integrity: sha1-FkjESq58jZiKMmAY7XL1tN0DkuQ=
/to-regex/3.0.2:
dependencies:
define-property: 2.0.2
@@ -13705,7 +13721,7 @@ packages:
engines:
node: '>=10'
resolution:
integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==
integrity: sha1-MkC4kaeLDerpENvrhlU+VSoUiGA=
/type-fest/0.18.1:
dev: true
engines: