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:
committed by
Facebook GitHub Bot
parent
ecfdeb2276
commit
9324bef8cc
@@ -20,18 +20,15 @@
|
||||
"algoliasearch": "^4.0.0",
|
||||
"async-mutex": "^0.1.3",
|
||||
"axios": "^0.19.2",
|
||||
"decompress": "^4.2.0",
|
||||
"decompress-targz": "^4.1.1",
|
||||
"decompress-unzip": "^4.0.1",
|
||||
"deep-equal": "^2.0.1",
|
||||
"emotion": "^10.0.23",
|
||||
"expand-tilde": "^2.0.2",
|
||||
"flipper-doctor": "0.45.0",
|
||||
"flipper-plugin-lib": "0.45.0",
|
||||
"fs-extra": "^8.0.1",
|
||||
"immer": "^6.0.0",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"invariant": "^2.2.2",
|
||||
"live-plugin-manager": "^0.14.0",
|
||||
"lodash": "^4.17.15",
|
||||
"npm-api": "^1.0.0",
|
||||
"open": "^7.0.0",
|
||||
|
||||
@@ -44,8 +44,8 @@ import {
|
||||
provideSearchIndex,
|
||||
findPluginUpdates as _findPluginUpdates,
|
||||
UpdateResult,
|
||||
installPluginFromNpm,
|
||||
} from '../../utils/pluginManager';
|
||||
import {installPluginFromNpm} from 'flipper-plugin-lib';
|
||||
import {State as AppState} from '../../reducers';
|
||||
import {connect} from 'react-redux';
|
||||
import {Dispatch, Action} from 'redux';
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import styled from '@emotion/styled';
|
||||
import {default as FileSelector} from '../../ui/components/FileSelector';
|
||||
import React, {useState} from 'react';
|
||||
import {installPluginFromFile} from '../../utils/pluginManager';
|
||||
import {installPluginFromFile} from 'flipper-plugin-lib';
|
||||
|
||||
const CenteredGlyph = styled(Glyph)({
|
||||
margin: 'auto',
|
||||
|
||||
@@ -9,123 +9,17 @@
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import {promisify} from 'util';
|
||||
import {homedir} from 'os';
|
||||
import {PluginMap, PluginDefinition} from '../reducers/pluginManager';
|
||||
import {PluginManager as PM} from 'live-plugin-manager';
|
||||
import {default as algoliasearch, SearchIndex} from 'algoliasearch';
|
||||
import NpmApi, {Package} from 'npm-api';
|
||||
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_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
|
||||
|
||||
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.
|
||||
export function provideSearchIndex(): SearchIndex {
|
||||
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY);
|
||||
|
||||
@@ -9,7 +9,12 @@
|
||||
"license": "MIT",
|
||||
"bugs": "https://github.com/facebook/flipper/issues",
|
||||
"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": {
|
||||
"@types/fs-extra": "^8.1.0",
|
||||
|
||||
@@ -9,3 +9,4 @@
|
||||
|
||||
export {default as PluginDetails} from './PluginDetails';
|
||||
export {default as getPluginDetails} from './getPluginDetails';
|
||||
export * from './pluginInstaller';
|
||||
|
||||
120
desktop/plugin-lib/src/pluginInstaller.tsx
Normal file
120
desktop/plugin-lib/src/pluginInstaller.tsx
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1704,7 +1704,7 @@
|
||||
widest-line "^2.0.1"
|
||||
wrap-ansi "^4.0.0"
|
||||
|
||||
"@oclif/plugin-help@^3":
|
||||
"@oclif/plugin-help@^3", "@oclif/plugin-help@^3.0.0":
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-3.0.1.tgz#21919bc6bef58eb045b80312dbb1d671ee7bba51"
|
||||
integrity sha512-Q1OITeUBkkydPf6r5qX75KgE9capr1mNrfHtfD7gkVXmqoTndrbc++z4KfAYNf5nhTCY7N9l52sjbF6BrSGu9w==
|
||||
@@ -1719,21 +1719,6 @@
|
||||
widest-line "^2.0.1"
|
||||
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":
|
||||
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"
|
||||
@@ -1939,7 +1924,7 @@
|
||||
dependencies:
|
||||
"@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"
|
||||
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.0.tgz#1114834b53c3914806cd03b3304b37b3bd221a4d"
|
||||
integrity sha512-UoOfVEzAUpeSPmjm7h1uk5MH6KZma2z2O7a75onTGjnNvAvMVrPzPL/vBbT65iIGHWj6rokwfmYcmxmlSf2uwg==
|
||||
@@ -2070,10 +2055,10 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node-fetch@^2.5.4":
|
||||
version "2.5.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.5.tgz#cd264e20a81f4600a6c52864d38e7fef72485e92"
|
||||
integrity sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==
|
||||
"@types/node-fetch@^2.5.6":
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c"
|
||||
integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^3.0.0"
|
||||
@@ -2279,10 +2264,12 @@
|
||||
"@types/node" "*"
|
||||
"@types/rsocket-flowable" "*"
|
||||
|
||||
"@types/semver@^6.2.0":
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.2.1.tgz#a236185670a7860f1597cf73bea2e16d001461ba"
|
||||
integrity sha512-+beqKQOh9PYxuHvijhVl+tIHvT6tuwOrE9m14zd+MT2A38KoKZhh7pYJ0SNleLtwDsiIxHDsIk9bv01oOxvSvA==
|
||||
"@types/semver@^7.1.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.2.0.tgz#0d72066965e910531e1db4621c15d0ca36b8d83b"
|
||||
integrity sha512-TbB0A8ACUWZt3Y6bQPstW9QNbhNeebdgLX4T/ZfkrswAfUzRiXrgd9seol+X379Wa589Pu4UEx9Uok0D4RjRCQ==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.13.3"
|
||||
@@ -3673,11 +3660,16 @@ chardet@^0.7.0:
|
||||
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
|
||||
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
|
||||
|
||||
chownr@^1.1.1, chownr@^1.1.3:
|
||||
chownr@^1.1.1:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||
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:
|
||||
version "0.2.0"
|
||||
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"
|
||||
yauzl "^2.4.2"
|
||||
|
||||
decompress@^4.2.0:
|
||||
decompress@^4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118"
|
||||
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"
|
||||
integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=
|
||||
|
||||
live-plugin-manager@^0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.0.tgz#234f5623e6d5768a8191fe9be009e1ec0fd7a2d8"
|
||||
integrity sha512-wYf65O93USi8Oz2elo/TtFfq3+yYt7iz08RC3whSnlhKuobPBI2te7qzYJMmGBe3aKheamfqrN92LaPMdCAUfw==
|
||||
live-plugin-manager@^0.14.1:
|
||||
version "0.14.1"
|
||||
resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.1.tgz#34b6bb8f3d2062ec2557c857ca028fea9dc2b6db"
|
||||
integrity sha512-bRFh5xn1PEYrwxoOhQ4k8gsh8eh4cRMbXmV/YefV4Xs2E6wuXLF+e51gsXjyim7DquEWsiFuoKK+RSQ387PuHA==
|
||||
dependencies:
|
||||
"@types/debug" "^4.1.5"
|
||||
"@types/fs-extra" "^8.0.1"
|
||||
"@types/fs-extra" "^8.1.0"
|
||||
"@types/lockfile" "^1.0.1"
|
||||
"@types/node-fetch" "^2.5.4"
|
||||
"@types/semver" "^6.2.0"
|
||||
"@types/node-fetch" "^2.5.6"
|
||||
"@types/semver" "^7.1.0"
|
||||
"@types/tar" "^4.0.3"
|
||||
"@types/url-join" "4.0.0"
|
||||
debug "^4.1.1"
|
||||
fs-extra "^8.1.0"
|
||||
fs-extra "^9.0.0"
|
||||
lockfile "^1.0.4"
|
||||
node-fetch "^2.6.0"
|
||||
semver "^6.3.0"
|
||||
tar "^5.0.5"
|
||||
semver "^7.3.2"
|
||||
tar "^6.0.1"
|
||||
url-join "^4.0.1"
|
||||
|
||||
load-json-file@^1.0.0:
|
||||
@@ -8953,7 +8945,7 @@ mixin-deep@^1.2.0:
|
||||
for-in "^1.0.2"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
@@ -11959,16 +11951,16 @@ tar@^4:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tar@^5.0.5:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-5.0.5.tgz#03fcdb7105bc8ea3ce6c86642b9c942495b04f93"
|
||||
integrity sha512-MNIgJddrV2TkuwChwcSNds/5E9VijOiw7kAc1y5hTNJoLDSuIyid2QtLYiCYNnICebpuvjhPQZsXwUL0O3l7OQ==
|
||||
tar@^6.0.1:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
|
||||
integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==
|
||||
dependencies:
|
||||
chownr "^1.1.3"
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.0"
|
||||
mkdirp "^0.5.0"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
temp-file@^3.3.6:
|
||||
|
||||
Reference in New Issue
Block a user