Moved plugin installation utilities to "plugin-lib" module

Summary: Moved plugin installation utilities to "plugin-lib" module. There are no functional changes in this diff, just refactoring so that plugin installation utils can be re-used by different modules.

Reviewed By: passy

Differential Revision: D21927387

fbshipit-source-id: 340516a544f7cfdcc15d94660dcb74a012054531
This commit is contained in:
Anton Nikolaev
2020-06-08 08:47:29 -07:00
committed by Facebook GitHub Bot
parent ecfdeb2276
commit 9324bef8cc
8 changed files with 166 additions and 157 deletions

View File

@@ -20,18 +20,15 @@
"algoliasearch": "^4.0.0", "algoliasearch": "^4.0.0",
"async-mutex": "^0.1.3", "async-mutex": "^0.1.3",
"axios": "^0.19.2", "axios": "^0.19.2",
"decompress": "^4.2.0",
"decompress-targz": "^4.1.1",
"decompress-unzip": "^4.0.1",
"deep-equal": "^2.0.1", "deep-equal": "^2.0.1",
"emotion": "^10.0.23", "emotion": "^10.0.23",
"expand-tilde": "^2.0.2", "expand-tilde": "^2.0.2",
"flipper-doctor": "0.45.0", "flipper-doctor": "0.45.0",
"flipper-plugin-lib": "0.45.0",
"fs-extra": "^8.0.1", "fs-extra": "^8.0.1",
"immer": "^6.0.0", "immer": "^6.0.0",
"immutable": "^4.0.0-rc.12", "immutable": "^4.0.0-rc.12",
"invariant": "^2.2.2", "invariant": "^2.2.2",
"live-plugin-manager": "^0.14.0",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"npm-api": "^1.0.0", "npm-api": "^1.0.0",
"open": "^7.0.0", "open": "^7.0.0",

View File

@@ -44,8 +44,8 @@ import {
provideSearchIndex, provideSearchIndex,
findPluginUpdates as _findPluginUpdates, findPluginUpdates as _findPluginUpdates,
UpdateResult, UpdateResult,
installPluginFromNpm,
} from '../../utils/pluginManager'; } from '../../utils/pluginManager';
import {installPluginFromNpm} from 'flipper-plugin-lib';
import {State as AppState} from '../../reducers'; import {State as AppState} from '../../reducers';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {Dispatch, Action} from 'redux'; import {Dispatch, Action} from 'redux';

View File

@@ -19,7 +19,7 @@ import {
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import {default as FileSelector} from '../../ui/components/FileSelector'; import {default as FileSelector} from '../../ui/components/FileSelector';
import React, {useState} from 'react'; import React, {useState} from 'react';
import {installPluginFromFile} from '../../utils/pluginManager'; import {installPluginFromFile} from 'flipper-plugin-lib';
const CenteredGlyph = styled(Glyph)({ const CenteredGlyph = styled(Glyph)({
margin: 'auto', margin: 'auto',

View File

@@ -9,123 +9,17 @@
import path from 'path'; import path from 'path';
import fs from 'fs-extra'; import fs from 'fs-extra';
import {promisify} from 'util';
import {homedir} from 'os'; import {homedir} from 'os';
import {PluginMap, PluginDefinition} from '../reducers/pluginManager'; import {PluginMap, PluginDefinition} from '../reducers/pluginManager';
import {PluginManager as PM} from 'live-plugin-manager';
import {default as algoliasearch, SearchIndex} from 'algoliasearch'; import {default as algoliasearch, SearchIndex} from 'algoliasearch';
import NpmApi, {Package} from 'npm-api'; import NpmApi, {Package} from 'npm-api';
import semver from 'semver'; import semver from 'semver';
import decompress from 'decompress';
import decompressTargz from 'decompress-targz';
import decompressUnzip from 'decompress-unzip';
import tmp from 'tmp';
const getTmpDir = promisify(tmp.dir) as () => Promise<string>;
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU'; const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e'; const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty'); export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
function providePluginManager(): PM {
return new PM({
ignoredDependencies: [/^flipper$/, /^react$/, /^react-dom$/, /^@types\//],
});
}
function providePluginManagerNoDependencies(): PM {
return new PM({ignoredDependencies: [/.*/]});
}
async function installPluginFromTempDir(pluginDir: string) {
const packageJSONPath = path.join(pluginDir, 'package.json');
const packageJSON = JSON.parse(
(await fs.readFile(packageJSONPath)).toString(),
);
const name = packageJSON.name;
await fs.ensureDir(PLUGIN_DIR);
// create empty watchman config (required by metro's file watcher)
await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}');
const destinationDir = path.join(PLUGIN_DIR, name);
// Clean up existing destination files.
await fs.remove(destinationDir);
await fs.ensureDir(destinationDir);
const isPreBundled = await fs.pathExists(path.join(pluginDir, 'dist'));
if (!isPreBundled) {
const pluginManager = providePluginManager();
// install the plugin dependencies into node_modules
const nodeModulesDir = path.join(destinationDir, 'node_modules');
pluginManager.options.pluginsPath = nodeModulesDir;
await pluginManager.installFromPath(pluginDir);
// live-plugin-manager also installs plugin itself into the target dir, it's better remove it
await fs.remove(path.join(nodeModulesDir, name));
}
// copying plugin files into the destination folder
const pluginFiles = await fs.readdir(pluginDir);
await Promise.all(
pluginFiles
.filter((f) => f !== 'node_modules')
.map((f) =>
fs.move(path.join(pluginDir, f), path.join(destinationDir, f)),
),
);
}
async function getPluginRootDir(dir: string) {
// npm packages are tar.gz archives containing folder 'package' inside
const packageDir = path.join(dir, 'package');
const isNpmPackage = await fs.pathExists(packageDir);
// vsix packages are zip archives containing folder 'extension' inside
const extensionDir = path.join(dir, 'extension');
const isVsix = await fs.pathExists(extensionDir);
if (!isNpmPackage && !isVsix) {
throw new Error(
'Package format is invalid: directory "package" or "extensions" not found in the archive root',
);
}
return isNpmPackage ? packageDir : extensionDir;
}
export async function installPluginFromNpm(name: string) {
const tmpDir = await getTmpDir();
try {
await fs.ensureDir(tmpDir);
const plugManNoDep = providePluginManagerNoDependencies();
plugManNoDep.options.pluginsPath = tmpDir;
await plugManNoDep.install(name);
const pluginTempDir = path.join(tmpDir, name);
await installPluginFromTempDir(pluginTempDir);
} finally {
if (await fs.pathExists(tmpDir)) {
await fs.remove(tmpDir);
}
}
}
export async function installPluginFromFile(packagePath: string) {
const tmpDir = await getTmpDir();
try {
const files = await decompress(packagePath, tmpDir, {
plugins: [decompressTargz(), decompressUnzip()],
});
if (!files.length) {
throw new Error('The package is not in tar.gz format or is empty');
}
const pluginDir = await getPluginRootDir(tmpDir);
await installPluginFromTempDir(pluginDir);
} finally {
if (await fs.pathExists(tmpDir)) {
await fs.remove(tmpDir);
}
}
}
// TODO(T57014856): This should be private, too. // TODO(T57014856): This should be private, too.
export function provideSearchIndex(): SearchIndex { export function provideSearchIndex(): SearchIndex {
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY); const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY);

View File

@@ -9,7 +9,12 @@
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/facebook/flipper/issues", "bugs": "https://github.com/facebook/flipper/issues",
"dependencies": { "dependencies": {
"fs-extra": "^8.1.0" "decompress": "^4.2.1",
"decompress-targz": "^4.1.1",
"decompress-unzip": "^4.0.1",
"fs-extra": "^8.1.0",
"live-plugin-manager": "^0.14.1",
"tmp": "^0.2.1"
}, },
"devDependencies": { "devDependencies": {
"@types/fs-extra": "^8.1.0", "@types/fs-extra": "^8.1.0",

View File

@@ -9,3 +9,4 @@
export {default as PluginDetails} from './PluginDetails'; export {default as PluginDetails} from './PluginDetails';
export {default as getPluginDetails} from './getPluginDetails'; export {default as getPluginDetails} from './getPluginDetails';
export * from './pluginInstaller';

View File

@@ -0,0 +1,120 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import path from 'path';
import fs from 'fs-extra';
import {promisify} from 'util';
import {homedir} from 'os';
import {PluginManager as PM} from 'live-plugin-manager';
import decompress from 'decompress';
import decompressTargz from 'decompress-targz';
import decompressUnzip from 'decompress-unzip';
import tmp from 'tmp';
const getTmpDir = promisify(tmp.dir) as () => Promise<string>;
export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
function providePluginManager(): PM {
return new PM({
ignoredDependencies: [/^flipper$/, /^react$/, /^react-dom$/, /^@types\//],
});
}
function providePluginManagerNoDependencies(): PM {
return new PM({ignoredDependencies: [/.*/]});
}
async function installPluginFromTempDir(pluginDir: string) {
const packageJSONPath = path.join(pluginDir, 'package.json');
const packageJSON = JSON.parse(
(await fs.readFile(packageJSONPath)).toString(),
);
const name = packageJSON.name;
await fs.ensureDir(PLUGIN_DIR);
// create empty watchman config (required by metro's file watcher)
await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}');
const destinationDir = path.join(PLUGIN_DIR, name);
// Clean up existing destination files.
await fs.remove(destinationDir);
await fs.ensureDir(destinationDir);
const isPreBundled = await fs.pathExists(path.join(pluginDir, 'dist'));
if (!isPreBundled) {
const pluginManager = providePluginManager();
// install the plugin dependencies into node_modules
const nodeModulesDir = path.join(destinationDir, 'node_modules');
pluginManager.options.pluginsPath = nodeModulesDir;
await pluginManager.installFromPath(pluginDir);
// live-plugin-manager also installs plugin itself into the target dir, it's better remove it
await fs.remove(path.join(nodeModulesDir, name));
}
// copying plugin files into the destination folder
const pluginFiles = await fs.readdir(pluginDir);
await Promise.all(
pluginFiles
.filter((f) => f !== 'node_modules')
.map((f) =>
fs.move(path.join(pluginDir, f), path.join(destinationDir, f)),
),
);
}
async function getPluginRootDir(dir: string) {
// npm packages are tar.gz archives containing folder 'package' inside
const packageDir = path.join(dir, 'package');
const isNpmPackage = await fs.pathExists(packageDir);
// vsix packages are zip archives containing folder 'extension' inside
const extensionDir = path.join(dir, 'extension');
const isVsix = await fs.pathExists(extensionDir);
if (!isNpmPackage && !isVsix) {
throw new Error(
'Package format is invalid: directory "package" or "extensions" not found in the archive root',
);
}
return isNpmPackage ? packageDir : extensionDir;
}
export async function installPluginFromNpm(name: string) {
const tmpDir = await getTmpDir();
try {
await fs.ensureDir(tmpDir);
const plugManNoDep = providePluginManagerNoDependencies();
plugManNoDep.options.pluginsPath = tmpDir;
await plugManNoDep.install(name);
const pluginTempDir = path.join(tmpDir, name);
await installPluginFromTempDir(pluginTempDir);
} finally {
if (await fs.pathExists(tmpDir)) {
await fs.remove(tmpDir);
}
}
}
export async function installPluginFromFile(packagePath: string) {
const tmpDir = await getTmpDir();
try {
const files = await decompress(packagePath, tmpDir, {
plugins: [decompressTargz(), decompressUnzip()],
});
if (!files.length) {
throw new Error('The package is not in tar.gz format or is empty');
}
const pluginDir = await getPluginRootDir(tmpDir);
await installPluginFromTempDir(pluginDir);
} finally {
if (await fs.pathExists(tmpDir)) {
await fs.remove(tmpDir);
}
}
}

View File

@@ -1704,7 +1704,7 @@
widest-line "^2.0.1" widest-line "^2.0.1"
wrap-ansi "^4.0.0" wrap-ansi "^4.0.0"
"@oclif/plugin-help@^3": "@oclif/plugin-help@^3", "@oclif/plugin-help@^3.0.0":
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.0.1.tgz#21919bc6bef58eb045b80312dbb1d671ee7bba51" resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.0.1.tgz#21919bc6bef58eb045b80312dbb1d671ee7bba51"
integrity sha512-Q1OITeUBkkydPf6r5qX75KgE9capr1mNrfHtfD7gkVXmqoTndrbc++z4KfAYNf5nhTCY7N9l52sjbF6BrSGu9w== integrity sha512-Q1OITeUBkkydPf6r5qX75KgE9capr1mNrfHtfD7gkVXmqoTndrbc++z4KfAYNf5nhTCY7N9l52sjbF6BrSGu9w==
@@ -1719,21 +1719,6 @@
widest-line "^2.0.1" widest-line "^2.0.1"
wrap-ansi "^4.0.0" wrap-ansi "^4.0.0"
"@oclif/plugin-help@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.0.0.tgz#7d6433d74b0473a43797c6e0468b503470f23b50"
integrity sha512-mrV1O1VXy+ssW0kmIvFYkuEEPYZWKpyqydyHbKa316esAHatsZlrw6cRItf3TuKHTAqeGuXPctPV4mO2e21F9w==
dependencies:
"@oclif/command" "^1.5.20"
"@oclif/config" "^1.15.1"
chalk "^2.4.1"
indent-string "^4.0.0"
lodash.template "^4.4.0"
string-width "^3.0.0"
strip-ansi "^5.0.0"
widest-line "^2.0.1"
wrap-ansi "^4.0.0"
"@oclif/plugin-warn-if-update-available@^1.7.0": "@oclif/plugin-warn-if-update-available@^1.7.0":
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.0.tgz#5a72abe39ce0b831eb4ae81cb64eb4b9f3ea424a" resolved "https://registry.yarnpkg.com/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-1.7.0.tgz#5a72abe39ce0b831eb4ae81cb64eb4b9f3ea424a"
@@ -1939,7 +1924,7 @@
dependencies: dependencies:
"@types/events" "*" "@types/events" "*"
"@types/fs-extra@^8.0.0", "@types/fs-extra@^8.0.1", "@types/fs-extra@^8.1.0": "@types/fs-extra@^8.0.0", "@types/fs-extra@^8.1.0":
version "8.1.0" version "8.1.0"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d" resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d"
integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg== integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==
@@ -2070,10 +2055,10 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/node-fetch@^2.5.4": "@types/node-fetch@^2.5.6":
version "2.5.5" version "2.5.7"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.5.tgz#cd264e20a81f4600a6c52864d38e7fef72485e92" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
integrity sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA== integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
form-data "^3.0.0" form-data "^3.0.0"
@@ -2279,10 +2264,12 @@
"@types/node" "*" "@types/node" "*"
"@types/rsocket-flowable" "*" "@types/rsocket-flowable" "*"
"@types/semver@^6.2.0": "@types/semver@^7.1.0":
version "6.2.1" version "7.2.0"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.1.tgz#a236185670a7860f1597cf73bea2e16d001461ba" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b"
integrity sha512-+beqKQOh9PYxuHvijhVl+tIHvT6tuwOrE9m14zd+MT2A38KoKZhh7pYJ0SNleLtwDsiIxHDsIk9bv01oOxvSvA== integrity sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==
dependencies:
"@types/node" "*"
"@types/serve-static@*": "@types/serve-static@*":
version "1.13.3" version "1.13.3"
@@ -3673,11 +3660,16 @@ chardet@^0.7.0:
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
chownr@^1.1.1, chownr@^1.1.3: chownr@^1.1.1:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
chownr@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
chromium-pickle-js@^0.2.0: chromium-pickle-js@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205" resolved "https://registry.yarnpkg.com/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz#04a106672c18b085ab774d983dfa3ea138f22205"
@@ -4413,7 +4405,7 @@ decompress-unzip@^4.0.1:
pify "^2.3.0" pify "^2.3.0"
yauzl "^2.4.2" yauzl "^2.4.2"
decompress@^4.2.0: decompress@^4.2.1:
version "4.2.1" version "4.2.1"
resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118"
integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==
@@ -8255,24 +8247,24 @@ linked-list@0.1.0:
resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf" resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf"
integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78= integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=
live-plugin-manager@^0.14.0: live-plugin-manager@^0.14.1:
version "0.14.0" version "0.14.1"
resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.0.tgz#234f5623e6d5768a8191fe9be009e1ec0fd7a2d8" resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.1.tgz#34b6bb8f3d2062ec2557c857ca028fea9dc2b6db"
integrity sha512-wYf65O93USi8Oz2elo/TtFfq3+yYt7iz08RC3whSnlhKuobPBI2te7qzYJMmGBe3aKheamfqrN92LaPMdCAUfw== integrity sha512-bRFh5xn1PEYrwxoOhQ4k8gsh8eh4cRMbXmV/YefV4Xs2E6wuXLF+e51gsXjyim7DquEWsiFuoKK+RSQ387PuHA==
dependencies: dependencies:
"@types/debug" "^4.1.5" "@types/debug" "^4.1.5"
"@types/fs-extra" "^8.0.1" "@types/fs-extra" "^8.1.0"
"@types/lockfile" "^1.0.1" "@types/lockfile" "^1.0.1"
"@types/node-fetch" "^2.5.4" "@types/node-fetch" "^2.5.6"
"@types/semver" "^6.2.0" "@types/semver" "^7.1.0"
"@types/tar" "^4.0.3" "@types/tar" "^4.0.3"
"@types/url-join" "4.0.0" "@types/url-join" "4.0.0"
debug "^4.1.1" debug "^4.1.1"
fs-extra "^8.1.0" fs-extra "^9.0.0"
lockfile "^1.0.4" lockfile "^1.0.4"
node-fetch "^2.6.0" node-fetch "^2.6.0"
semver "^6.3.0" semver "^7.3.2"
tar "^5.0.5" tar "^6.0.1"
url-join "^4.0.1" url-join "^4.0.1"
load-json-file@^1.0.0: load-json-file@^1.0.0:
@@ -8953,7 +8945,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2" for-in "^1.0.2"
is-extendable "^1.0.1" is-extendable "^1.0.1"
mkdirp@1.x, mkdirp@^1.0.4: mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@@ -11959,16 +11951,16 @@ tar@^4:
safe-buffer "^5.1.2" safe-buffer "^5.1.2"
yallist "^3.0.3" yallist "^3.0.3"
tar@^5.0.5: tar@^6.0.1:
version "5.0.5" version "6.0.2"
resolved "https://registry.yarnpkg.com/tar/-/tar-5.0.5.tgz#03fcdb7105bc8ea3ce6c86642b9c942495b04f93" resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
integrity sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ== integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==
dependencies: dependencies:
chownr "^1.1.3" chownr "^2.0.0"
fs-minipass "^2.0.0" fs-minipass "^2.0.0"
minipass "^3.0.0" minipass "^3.0.0"
minizlib "^2.1.0" minizlib "^2.1.0"
mkdirp "^0.5.0" mkdirp "^1.0.3"
yallist "^4.0.0" yallist "^4.0.0"
temp-file@^3.3.6: temp-file@^3.3.6: