From a3fa646eb6b51004ef9e85a32f7be1cf2d0cc2db Mon Sep 17 00:00:00 2001 From: Ward Peeters Date: Tue, 18 Jan 2022 08:47:13 +0100 Subject: [PATCH] feat(gatsby-sharp): create more resilient wrapper around sharp (#34339) * feat(gatsby-sharp): add gatsby-sharp as sharp abstraction * move safe-sharp to gatsby/sharp when available * fix yarn.lock and snapshots because of deps * only require sharp once + typescript fixes * fix fallback safe-sharp * update sharp * fix jest babel resolution * Apply suggestions from code review --- jest-transformer.js | 7 ++ .../src/__tests__/gatsby-node.js | 5 -- .../gatsby-plugin-manifest/src/gatsby-node.js | 10 +-- .../gatsby-plugin-manifest/src/safe-sharp.js | 12 ++- .../src/__tests__/index.js | 3 + .../src/index.js | 5 +- .../src/safe-sharp.js | 13 +++- packages/gatsby-sharp/.babelrc.js | 5 ++ packages/gatsby-sharp/package.json | 41 ++++++++++ packages/gatsby-sharp/src/__tests__/index.ts | 76 +++++++++++++++++++ packages/gatsby-sharp/src/index.ts | 52 +++++++++++++ packages/gatsby-sharp/tsconfig.json | 12 +++ .../gatsby-source-contentful/package.json | 2 +- packages/gatsby/package.json | 4 + packages/gatsby/sharp.d.ts | 3 + packages/gatsby/sharp.js | 3 + yarn.lock | 76 +++++-------------- 17 files changed, 258 insertions(+), 71 deletions(-) create mode 100644 packages/gatsby-sharp/.babelrc.js create mode 100644 packages/gatsby-sharp/package.json create mode 100644 packages/gatsby-sharp/src/__tests__/index.ts create mode 100644 packages/gatsby-sharp/src/index.ts create mode 100644 packages/gatsby-sharp/tsconfig.json create mode 100644 packages/gatsby/sharp.d.ts create mode 100644 packages/gatsby/sharp.js diff --git a/jest-transformer.js b/jest-transformer.js index 02167a152534c..94411b7b1d426 100644 --- a/jest-transformer.js +++ b/jest-transformer.js @@ -2,4 +2,11 @@ const babelJest = require(`babel-jest`) module.exports = babelJest.default.createTransformer({ presets: [`babel-preset-gatsby-package`], + babelrcRoots: [ + // Keep the root as a root + `.`, + + // Also consider monorepo packages "root" and load their .babelrc files. + `./packages/*`, + ], }) diff --git a/packages/gatsby-plugin-manifest/src/__tests__/gatsby-node.js b/packages/gatsby-plugin-manifest/src/__tests__/gatsby-node.js index 8c8412159bd27..b6591d4cec3c4 100644 --- a/packages/gatsby-plugin-manifest/src/__tests__/gatsby-node.js +++ b/packages/gatsby-plugin-manifest/src/__tests__/gatsby-node.js @@ -106,11 +106,6 @@ describe(`Test plugin manifest options`, () => { sharp.mockClear() }) - // the require of gatsby-node performs the invoking - it(`invokes sharp.simd for optimization`, () => { - expect(sharp.simd).toHaveBeenCalledTimes(1) - }) - it(`correctly works with default parameters`, async () => { await onPostBootstrap(apiArgs, { name: `GatsbyJS`, diff --git a/packages/gatsby-plugin-manifest/src/gatsby-node.js b/packages/gatsby-plugin-manifest/src/gatsby-node.js index bed101a18790d..7230197641c03 100644 --- a/packages/gatsby-plugin-manifest/src/gatsby-node.js +++ b/packages/gatsby-plugin-manifest/src/gatsby-node.js @@ -1,17 +1,13 @@ import * as fs from "fs" import * as path from "path" -import sharp from "./safe-sharp" +// TODO(v5): use gatsby/sharp +import getSharpInstance from "./safe-sharp" import { createContentDigest, slash } from "gatsby-core-utils" import { defaultIcons, addDigestToPath, favicons } from "./common" import { doesIconExist } from "./node-helpers" import pluginOptionsSchema from "./pluginOptionsSchema" -sharp.simd(true) - -// force it to be 1 as we only resize one image -sharp.concurrency(1) - async function generateIcon(icon, srcIcon) { const imgPath = path.join(`public`, icon.src) @@ -28,6 +24,7 @@ async function generateIcon(icon, srcIcon) { // Sharp accept density from 1 to 2400 const density = Math.min(2400, Math.max(1, size)) + const sharp = await getSharpInstance() return sharp(srcIcon, { density }) .resize({ width: size, @@ -194,6 +191,7 @@ const makeManifest = async ({ ) } + const sharp = await getSharpInstance() const sharpIcon = sharp(icon) const metadata = await sharpIcon.metadata() diff --git a/packages/gatsby-plugin-manifest/src/safe-sharp.js b/packages/gatsby-plugin-manifest/src/safe-sharp.js index e92a40063c28c..4cc3856d924be 100644 --- a/packages/gatsby-plugin-manifest/src/safe-sharp.js +++ b/packages/gatsby-plugin-manifest/src/safe-sharp.js @@ -157,7 +157,17 @@ try { originalConsoleError(msg, ...args) handleMessage(msg) } - sharp = require(`sharp`) + try { + sharp = require(`gatsby/sharp`) + } catch (e) { + sharp = () => { + const sharp = require(`sharp`) + sharp.simd() + sharp.concurrency(1) + + return Promise.resolve(sharp) + } + } } catch (e) { handleMessage(e.toString()) throw e diff --git a/packages/gatsby-remark-images-contentful/src/__tests__/index.js b/packages/gatsby-remark-images-contentful/src/__tests__/index.js index 028e38a740334..2e36041fef1cf 100644 --- a/packages/gatsby-remark-images-contentful/src/__tests__/index.js +++ b/packages/gatsby-remark-images-contentful/src/__tests__/index.js @@ -30,9 +30,12 @@ jest.mock(`sharp`, () => { const pipeline = { metadata: metadataMock, } + return pipeline } + sharp.simd = jest.fn() + sharp.concurrency = jest.fn() sharp.metadataMock = metadataMock return sharp diff --git a/packages/gatsby-remark-images-contentful/src/index.js b/packages/gatsby-remark-images-contentful/src/index.js index 9a340d193f90a..2e84c1bdfe58d 100644 --- a/packages/gatsby-remark-images-contentful/src/index.js +++ b/packages/gatsby-remark-images-contentful/src/index.js @@ -1,5 +1,6 @@ const { selectAll } = require(`unist-util-select`) -const sharp = require(`./safe-sharp`) +// TODO(v5): use gatsby/sharp +const getSharpInstance = require(`./safe-sharp`) const axios = require(`axios`) const _ = require(`lodash`) const Promise = require(`bluebird`) @@ -62,6 +63,7 @@ module.exports = async ( if (cachedRawHTML) { return cachedRawHTML } + const sharp = await getSharpInstance() const metaReader = sharp() // @todo to increase reliablility, this should use the asset downloading function from gatsby-source-contentful @@ -86,6 +88,7 @@ module.exports = async ( try { metadata = await metaReader.metadata() } catch (error) { + console.log(error) reporter.panic( `The image "${node.url}" (with alt text: "${node.alt}") doesn't appear to be a supported image format.`, error diff --git a/packages/gatsby-remark-images-contentful/src/safe-sharp.js b/packages/gatsby-remark-images-contentful/src/safe-sharp.js index e92a40063c28c..d8e9bb5105733 100644 --- a/packages/gatsby-remark-images-contentful/src/safe-sharp.js +++ b/packages/gatsby-remark-images-contentful/src/safe-sharp.js @@ -157,7 +157,18 @@ try { originalConsoleError(msg, ...args) handleMessage(msg) } - sharp = require(`sharp`) + try { + sharp = require(`gatsby/sharp`) + } catch (e) { + sharp = () => { + const sharp = require(`sharp`) + + sharp.simd() + sharp.concurrency(1) + + return Promise.resolve(sharp) + } + } } catch (e) { handleMessage(e.toString()) throw e diff --git a/packages/gatsby-sharp/.babelrc.js b/packages/gatsby-sharp/.babelrc.js new file mode 100644 index 0000000000000..cad9956015e41 --- /dev/null +++ b/packages/gatsby-sharp/.babelrc.js @@ -0,0 +1,5 @@ +console.log('hi there'); +module.exports = { + "presets": [["babel-preset-gatsby-package"]], + "plugins": ["babel-plugin-replace-ts-export-assignment"] +} diff --git a/packages/gatsby-sharp/package.json b/packages/gatsby-sharp/package.json new file mode 100644 index 0000000000000..bf5d1c3274c27 --- /dev/null +++ b/packages/gatsby-sharp/package.json @@ -0,0 +1,41 @@ +{ + "name": "gatsby-sharp", + "version": "0.0.1-next.0", + "sideEffects": false, + "keywords": [ + "gatsby", + "sharp" + ], + "main": "dist/index.js", + "source": "src/index.ts", + "files": [ + "dist/*" + ], + "types": "dist/index.d.ts", + "homepage": "https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-sharp#readme", + "dependencies": { + "@types/sharp": "^0.29.5", + "sharp": "^0.29.3" + }, + "devDependencies": { + "@babel/cli": "^7.15.5", + "@babel/core": "^7.15.5", + "babel-plugin-replace-ts-export-assignment": "^0.0.2", + "cross-env": "^7.0.3" + }, + "engines": { + "node": ">=14.15.0" + }, + "repository": { + "type": "git", + "url": "https://github.com/gatsbyjs/gatsby.git", + "directory": "packages/gatsby-sharp" + }, + "license": "MIT", + "scripts": { + "build": "babel src --out-file dist/index.js --ignore \"**/__tests__\" --extensions \".ts,.js\"", + "typegen": "tsc --emitDeclarationOnly --declaration --declarationDir dist/", + "prepare": "cross-env NODE_ENV=production npm-run-all -s build typegen", + "watch": "babel -w src --out-file dist/index.js --ignore \"**/__tests__\" --extensions \".ts,.js\"" + } +} diff --git a/packages/gatsby-sharp/src/__tests__/index.ts b/packages/gatsby-sharp/src/__tests__/index.ts new file mode 100644 index 0000000000000..4aeffdb8c8db5 --- /dev/null +++ b/packages/gatsby-sharp/src/__tests__/index.ts @@ -0,0 +1,76 @@ +/** @jest-environment node */ +import { exec } from "child_process" + +jest.mock(`child_process`, () => { + return { + exec: jest.fn(async (command, options, cb) => { + setImmediate(() => { + try { + return cb( + null, + `> sharp@0.29.3 install C:\\Users\\Ward\\projects\\gatsby\\gatsby\\node_modules\\sharp\n`, + `` + ) + } catch (err) { + return cb(true, ``, err.message) + } + }) + }), + } +}) + +function getSharpInstance(): typeof import("../index") { + let getSharpInstance + jest.isolateModules(() => { + getSharpInstance = require(`../index`) + }) + + return getSharpInstance() +} + +describe(`getSharpInstance`, () => { + beforeEach(() => { + exec.mockClear() + }) + + // jest mocking is making this impossible to test + it(`should give you the bare sharp module`, async () => { + const sharpInstance = await getSharpInstance() + + expect(exec).not.toHaveBeenCalled() + expect(sharpInstance).toBeDefined() + expect(sharpInstance.versions).toBeDefined() + }) + + it( + `should rebuild sharp when binaries not found for current arch`, + async () => { + expect.assertions(3) + + let called = false + jest.doMock(`sharp`, () => { + if (!called) { + called = true + throw new Error(`sharp failed to load`) + } + + return jest.requireActual(`sharp`) + }) + + try { + const sharpInstance = await getSharpInstance() + expect(sharpInstance).toBeDefined() + expect(sharpInstance.versions).toBeDefined() + } catch (err) { + // ignore + } + + expect(exec).toHaveBeenCalledWith( + `npm rebuild sharp`, + expect.anything(), + expect.anything() + ) + }, + 60 * 1000 + ) +}) diff --git a/packages/gatsby-sharp/src/index.ts b/packages/gatsby-sharp/src/index.ts new file mode 100644 index 0000000000000..5c1318241b1cb --- /dev/null +++ b/packages/gatsby-sharp/src/index.ts @@ -0,0 +1,52 @@ +const { exec } = require(`child_process`) +const { createRequire } = require(`module`) + +let sharpInstance: typeof import("sharp") + +export = async function getSharpInstance(): Promise { + try { + return importSharp() + } catch (err) { + await rebuildSharp() + + // Try importing again now we have rebuilt sharp + return importSharp() + } +} + +function importSharp(): typeof import("sharp") { + if (!sharpInstance) { + const cleanRequire = createRequire(__filename) + const sharp = cleanRequire(`sharp`) + + sharp.simd(true) + // Concurrency is handled by gatsby + sharp.concurrency(1) + + sharpInstance = sharp + } + + return sharpInstance +} + +function rebuildSharp(): Promise { + return new Promise((resolve, reject) => { + exec( + `npm rebuild sharp`, + { + timeout: 60 * 1000, + }, + (error, stdout, stderr) => { + if (error) { + if (error.killed) { + console.log(`timeout reached`) + } + + return reject(stderr) + } + + return setImmediate(() => resolve(stdout)) + } + ) + }) +} diff --git a/packages/gatsby-sharp/tsconfig.json b/packages/gatsby-sharp/tsconfig.json new file mode 100644 index 0000000000000..68027cd6d44d0 --- /dev/null +++ b/packages/gatsby-sharp/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES5", + "module": "CommonJS" + }, + "exclude": [ + "src/__tests__", + "src/__mocks__", + "dist", + ] +} diff --git a/packages/gatsby-source-contentful/package.json b/packages/gatsby-source-contentful/package.json index 1ee6744f6cb78..30abea1cb0ddb 100644 --- a/packages/gatsby-source-contentful/package.json +++ b/packages/gatsby-source-contentful/package.json @@ -46,7 +46,7 @@ "gatsby": "^4.0.0-next", "gatsby-plugin-image": "^2.0.0-next", "gatsby-plugin-sharp": "^4.0.0-next", - "sharp": "^0.29.0" + "sharp": "^0.29.3" }, "repository": { "type": "git", diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index ec0426e612669..c1847e0aa4ca2 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -170,6 +170,7 @@ "@types/reach__router": "^1.3.5", "@types/react-dom": "^17.0.9", "@types/semver": "^7.3.9", + "@types/sharp": "^0.29.5", "@types/signal-exit": "^3.0.0", "@types/string-similarity": "^4.0.0", "@types/tmp": "^0.2.0", @@ -188,6 +189,9 @@ "zipkin-javascript-opentracing": "^3.0.0", "zipkin-transport-http": "^0.22.0" }, + "optionalDependencies": { + "gatsby-sharp": "^0.0.1-next.0" + }, "engines": { "node": ">=14.15.0" }, diff --git a/packages/gatsby/sharp.d.ts b/packages/gatsby/sharp.d.ts new file mode 100644 index 0000000000000..8453179e2b768 --- /dev/null +++ b/packages/gatsby/sharp.d.ts @@ -0,0 +1,3 @@ +import getSharpInstance from "gatsby-sharp" + +export = getSharpInstance diff --git a/packages/gatsby/sharp.js b/packages/gatsby/sharp.js new file mode 100644 index 0000000000000..ac7150fc03d04 --- /dev/null +++ b/packages/gatsby/sharp.js @@ -0,0 +1,3 @@ +"use strict" + +module.exports = require('gatsby-sharp'); diff --git a/yarn.lock b/yarn.lock index aafb39f3791b7..a2ffb5440c564 100644 --- a/yarn.lock +++ b/yarn.lock @@ -152,10 +152,10 @@ resolved "https://registry.yarnpkg.com/@ascorbic/worker-threads-shim/-/worker-threads-shim-1.0.0.tgz#d003ac1f9aacc9d95d8a0e453bce256d7fa99923" integrity sha512-CEvYpC2w2t7tDWgloPA8ETra79cZzi2IdeM0bluTTkvWcnEdLWYStM12ymq2VRE3OMR8OtmKD4l026dUel1d+w== -"@babel/cli@^7.15.4": - version "7.15.4" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.15.4.tgz#00e21e192b738dec7900c8bb36270e377217c0a4" - integrity sha512-9RhhQ7tgKRcSO/jI3rNLxalLSk30cHqeM8bb+nGOJTyYBDpkoXw/A9QHZ2SYjlslAt4tr90pZQGIEobwWHSIDw== +"@babel/cli@^7.15.4", "@babel/cli@^7.15.5": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.16.7.tgz#4184b5ec6a22106e9dd64bbcaa2eb22675ff595d" + integrity sha512-0iBF+G2Qml0y3mY5dirolyToLSR88a/KB6F2Gm8J/lOnyL8wbEOHak0DHF8gjc9XZGgTDGv/jYXNiapvsYyHTA== dependencies: commander "^4.0.1" convert-source-map "^1.1.0" @@ -165,7 +165,7 @@ slash "^2.0.0" source-map "^0.5.0" optionalDependencies: - "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.2" + "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" "@babel/code-frame@7.10.4": @@ -3321,22 +3321,10 @@ resolved "https://registry.yarnpkg.com/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-2.1.2.tgz#e486bf86c4c29e78601694a26f31c2dec0c08d9b" integrity sha512-KwZGeX2XK7Xj9ksWwei5923QnqIGoEuLlh3O46OW9vc8hQxjzmMTKCgJMVZ5ne5xaWFQYDT2dMpbUhq6hEOhxA== -"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.2": - version "2.1.8-no-fsevents.2" - resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.2.tgz#e324c0a247a5567192dd7180647709d7e2faf94b" - integrity sha512-Fb8WxUFOBQVl+CX4MWet5o7eCc6Pj04rXIwVKZ6h1NnqTo45eOQW6aWyhG25NIODvWFwTDMwBsYxrQ3imxpetg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^5.1.2" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" +"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": + version "2.1.8-no-fsevents.3" + resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" + integrity sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ== "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -5212,13 +5200,6 @@ any-promise@^1.0.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" @@ -5576,10 +5557,6 @@ async-cache@^1.1.0: dependencies: lru-cache "^4.0.0" -async-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" @@ -5904,6 +5881,11 @@ babel-plugin-react-css-modules@^3.4.2: postcss-modules-scope "^1.1.0" postcss-modules-values "^1.3.0" +babel-plugin-replace-ts-export-assignment@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-replace-ts-export-assignment/-/babel-plugin-replace-ts-export-assignment-0.0.2.tgz#927a30ba303fcf271108980a8d4f80a693e1d53f" + integrity sha512-BiTEG2Ro+O1spuheL5nB289y37FFmz0ISE6GjpNCG2JuA/WNcuEHSYw01+vN8quGf208sID3FnZFDwVyqX18YQ== + babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -6067,10 +6049,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -binary-extensions@^1.0.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" - binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" @@ -6204,7 +6182,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" dependencies: @@ -12767,12 +12745,6 @@ is-bigint@^1.0.1: resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -15973,7 +15945,7 @@ micromark@^2.11.3, micromark@~2.11.0, micromark@~2.11.3: debug "^4.0.0" parse-entities "^2.0.0" -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.5: +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.5: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" dependencies: @@ -19503,14 +19475,6 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -19635,9 +19599,9 @@ regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.1: define-properties "^1.1.3" regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== regexpu-core@^1.0.0: version "1.0.0" @@ -24030,7 +23994,7 @@ unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" -upath@^1.1.1, upath@^1.2.0: +upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==