diff --git a/package.json b/package.json
index c5fb2deca..b41f2bd94 100644
--- a/package.json
+++ b/package.json
@@ -64,6 +64,7 @@
"@jest-runner/electron": "^2.0.2",
"@testing-library/react": "^9.3.0",
"@types/algoliasearch": "^3.30.19",
+ "@types/decompress": "4.2.3",
"@types/deep-equal": "^1.0.1",
"@types/expand-tilde": "^2.0.0",
"@types/fb-watchman": "^2.0.0",
@@ -133,6 +134,8 @@
"codemirror": "^5.25.0",
"cross-env": "^7.0.0",
"dashify": "^2.0.0",
+ "decompress": "^4.2.0",
+ "decompress-targz": "^4.1.1",
"deep-equal": "^2.0.1",
"detect-port": "^1.1.1",
"electron-devtools-installer": "^2.2.0",
diff --git a/src/chrome/plugin-manager/PluginInstaller.tsx b/src/chrome/plugin-manager/PluginInstaller.tsx
index 755f8cd64..427ca9801 100644
--- a/src/chrome/plugin-manager/PluginInstaller.tsx
+++ b/src/chrome/plugin-manager/PluginInstaller.tsx
@@ -25,7 +25,6 @@ import {
LoadingIndicator,
Tooltip,
} from 'flipper';
-import {default as FileSelector} from '../../ui/components/FileSelector';
import React, {useCallback, useState, useMemo, useEffect} from 'react';
import {List} from 'immutable';
import {SearchIndex} from 'algoliasearch';
@@ -42,14 +41,15 @@ import {
import {
PLUGIN_DIR,
readInstalledPlugins,
- providePluginManager,
provideSearchIndex,
findPluginUpdates as _findPluginUpdates,
UpdateResult,
+ installPluginFromNpm,
} from '../../utils/pluginManager';
import {State as AppState} from '../../reducers';
import {connect} from 'react-redux';
import {Dispatch, Action} from 'redux';
+import PluginPackageInstaller from './PluginPackageInstaller';
const TAG = 'PluginInstaller';
@@ -145,15 +145,18 @@ export function annotatePluginsWithUpdates(
const PluginInstaller = function props(props: Props) {
const [restartRequired, setRestartRequired] = useState(false);
const [query, setQuery] = useState('');
- const [_localPackagePath, setLocalPackagePath] = useState('');
- const [isLocalPackagePathValid, setIsLocalPackagePathValud] = useState(false);
+
+ const onInstall = useCallback(async () => {
+ props.refreshInstalledPlugins();
+ setRestartRequired(true);
+ }, []);
+
const rows = useNPMSearch(
- setRestartRequired,
query,
setQuery,
props.searchIndexFactory,
props.installedPlugins,
- props.refreshInstalledPlugins,
+ onInstall,
props.findPluginUpdates,
);
const restartApp = useCallback(() => {
@@ -190,26 +193,7 @@ const PluginInstaller = function props(props: Props) {
rows={rows}
/>
-
- {
- setLocalPackagePath(e.path);
- setIsLocalPackagePathValud(e.isValid);
- }}
- />
-
-
+
>
);
};
@@ -267,35 +251,8 @@ function InstallButton(props: {
props.name,
);
setAction({kind: 'Waiting'});
- await fs.ensureDir(PLUGIN_DIR);
- // create empty watchman config (required by metro's file watcher)
- await fs.writeFile(path.join(PLUGIN_DIR, '.watchmanconfig'), '{}');
- // Clean up existing destination files.
- await fs.remove(path.join(PLUGIN_DIR, props.name));
-
- const pluginManager = providePluginManager();
- // install the plugin and all it's dependencies into node_modules
- pluginManager.options.pluginsPath = path.join(
- PLUGIN_DIR,
- props.name,
- 'node_modules',
- );
- await pluginManager.install(props.name);
-
- // move the plugin itself out of the node_modules folder
- const pluginDir = path.join(
- PLUGIN_DIR,
- props.name,
- 'node_modules',
- props.name,
- );
- const pluginFiles = await fs.readdir(pluginDir);
- await Promise.all(
- pluginFiles.map(f =>
- fs.move(path.join(pluginDir, f), path.join(pluginDir, '..', '..', f)),
- ),
- );
+ await installPluginFromNpm(props.name);
props.onInstall();
setAction({kind: 'Remove'});
@@ -376,12 +333,11 @@ function InstallButton(props: {
}
function useNPMSearch(
- setRestartRequired: (restart: boolean) => void,
query: string,
setQuery: (query: string) => void,
searchClientFactory: () => SearchIndex,
installedPlugins: Map,
- refreshInstalledPlugins: () => void,
+ onInstall: () => Promise,
findPluginUpdates: (
currentPlugins: PluginMap,
) => Promise<[string, UpdateResult][]>,
@@ -392,11 +348,6 @@ function useNPMSearch(
reportUsage(`${TAG}:open`);
}, []);
- const onInstall = useCallback(async () => {
- refreshInstalledPlugins();
- setRestartRequired(true);
- }, []);
-
const createRow = useCallback(
(h: UpdatablePluginDefinition) => ({
key: h.name,
diff --git a/src/chrome/plugin-manager/PluginPackageInstaller.tsx b/src/chrome/plugin-manager/PluginPackageInstaller.tsx
new file mode 100644
index 000000000..37fa2eded
--- /dev/null
+++ b/src/chrome/plugin-manager/PluginPackageInstaller.tsx
@@ -0,0 +1,110 @@
+/**
+ * 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 {
+ Toolbar,
+ Button,
+ FlexRow,
+ Tooltip,
+ Glyph,
+ colors,
+ LoadingIndicator,
+} from 'flipper';
+import styled from '@emotion/styled';
+import {default as FileSelector} from '../../ui/components/FileSelector';
+import React, {useState} from 'react';
+import {installPluginFromFile} from '../../utils/pluginManager';
+
+const CenteredGlyph = styled(Glyph)({
+ margin: 'auto',
+ marginLeft: 2,
+});
+
+const Spinner = styled(LoadingIndicator)({
+ margin: 'auto',
+ marginLeft: 16,
+});
+
+const ButtonContainer = styled(FlexRow)({
+ width: 76,
+});
+
+const ErrorGlyphContainer = styled(FlexRow)({
+ width: 20,
+});
+
+export default function PluginPackageInstaller({
+ onInstall,
+}: {
+ onInstall: () => Promise;
+}) {
+ const [path, setPath] = useState('');
+ const [isPathValid, setIsPathValid] = useState(false);
+ const [error, setError] = useState();
+ const [inProgress, setInProgress] = useState(false);
+ const onClick = async () => {
+ setError(undefined);
+ setInProgress(true);
+ try {
+ await installPluginFromFile(path);
+ await onInstall();
+ } catch (e) {
+ setError(e);
+ console.error(e);
+ } finally {
+ setInProgress(false);
+ }
+ };
+ const button = inProgress ? (
+
+ ) : (
+
+ );
+ return (
+
+ {
+ setPath(e.path);
+ setIsPathValid(e.isValid);
+ setError(undefined);
+ }}
+ />
+
+
+ {button}
+
+ {error && (
+
+
+
+ )}
+
+
+
+
+ );
+}
diff --git a/src/ui/components/FileSelector.tsx b/src/ui/components/FileSelector.tsx
index 1e6298fb2..409e150d1 100644
--- a/src/ui/components/FileSelector.tsx
+++ b/src/ui/components/FileSelector.tsx
@@ -9,7 +9,6 @@
import React, {useState} from 'react';
import FlexRow from './FlexRow';
-import FlexColumn from './FlexColumn';
import Glyph from './Glyph';
import Input from './Input';
import electron from 'electron';
@@ -17,15 +16,20 @@ import styled from '@emotion/styled';
import {colors} from './colors';
import Electron from 'electron';
import fs from 'fs';
+import {Tooltip} from '..';
const CenteredGlyph = styled(Glyph)({
- flexGrow: 0,
margin: 'auto',
- marginLeft: 10,
+ marginLeft: 4,
});
const Container = styled(FlexRow)({
width: '100%',
+ marginRight: 4,
+});
+
+const GlyphContainer = styled(FlexRow)({
+ width: 20,
});
const FileInputBox = styled(Input)<{isValid: boolean}>(({isValid}) => ({
@@ -49,7 +53,7 @@ export interface Props {
}
const defaultProps: Props = {
- onPathChanged: () => {},
+ onPathChanged: _ => {},
placeholderText: '',
defaultPath: '/',
showHiddenFiles: false,
@@ -97,7 +101,7 @@ export default function FileSelector({
onChange(e.target.value);
}}
/>
-
electron.remote.dialog
.showOpenDialog(options)
@@ -112,14 +116,18 @@ export default function FileSelector({
variant="outline"
title="Open file selection dialog"
/>
-
- {isValid ? null : (
-
- )}
+
+
+ {isValid ? null : (
+
+
+
+ )}
+
);
}
diff --git a/src/utils/pluginManager.tsx b/src/utils/pluginManager.tsx
index 4dc82725d..fa96b6cbe 100644
--- a/src/utils/pluginManager.tsx
+++ b/src/utils/pluginManager.tsx
@@ -15,10 +15,15 @@ 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 tmp from 'tmp';
const ALGOLIA_APPLICATION_ID = 'OFCNCOG2CU';
const ALGOLIA_API_KEY = 'f54e21fa3a2a0160595bb058179bfb1e';
+export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
+
// TODO(T57014856): The use should be constrained to just this module when the
// refactor is done.
export function providePluginManager(): PM {
@@ -27,13 +32,77 @@ export function providePluginManager(): PM {
});
}
+async function installPlugin(
+ name: string,
+ installFn: (pluginManager: PM) => Promise,
+) {
+ 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);
+
+ const pluginManager = providePluginManager();
+ // install the plugin and all it's dependencies into node_modules
+ pluginManager.options.pluginsPath = path.join(destinationDir, 'node_modules');
+ await installFn(pluginManager);
+
+ // move the plugin itself out of the node_modules folder
+ const pluginDir = path.join(PLUGIN_DIR, name, 'node_modules', name);
+ const pluginFiles = await fs.readdir(pluginDir);
+ await Promise.all(
+ pluginFiles.map(f =>
+ fs.move(path.join(pluginDir, f), path.join(pluginDir, '..', '..', f)),
+ ),
+ );
+}
+
+export async function installPluginFromNpm(name: string) {
+ await installPlugin(name, pluginManager =>
+ pluginManager.install(name).then(() => {}),
+ );
+}
+
+export async function installPluginFromFile(packagePath: string) {
+ const tmpDir = tmp.dirSync().name;
+ try {
+ const files = await decompress(packagePath, tmpDir, {
+ plugins: [decompressTargz()],
+ });
+ if (!files.length) {
+ throw new Error('The package is not in tar.gz format or is empty');
+ }
+ const packageDir = path.join(tmpDir, 'package');
+ if (!(await fs.pathExists(packageDir))) {
+ throw new Error(
+ 'Package format is invalid: directory "package" not found',
+ );
+ }
+ const packageJsonPath = path.join(packageDir, 'package.json');
+ if (!(await fs.pathExists(packageJsonPath))) {
+ throw new Error(
+ 'Package format is invalid: file "package/package.json" not found',
+ );
+ }
+ const packageJson = await fs.readJSON(packageJsonPath);
+ const name = packageJson.name as string;
+ await installPlugin(name, pluginManager =>
+ pluginManager.installFromPath(packageDir).then(() => {}),
+ );
+ } finally {
+ if (fs.existsSync(tmpDir)) {
+ fs.removeSync(tmpDir);
+ }
+ }
+}
+
// TODO(T57014856): This should be private, too.
export function provideSearchIndex(): SearchIndex {
const client = algoliasearch(ALGOLIA_APPLICATION_ID, ALGOLIA_API_KEY);
return client.initIndex('npm-search');
}
-export const PLUGIN_DIR = path.join(homedir(), '.flipper', 'thirdparty');
export async function readInstalledPlugins(): Promise {
const pluginDirExists = await fs.pathExists(PLUGIN_DIR);
diff --git a/types/decompress-targz.d.tsx b/types/decompress-targz.d.tsx
new file mode 100644
index 000000000..8b6c20977
--- /dev/null
+++ b/types/decompress-targz.d.tsx
@@ -0,0 +1,12 @@
+/**
+ * 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
+ */
+
+declare module 'decompress-targz' {
+ export default function(): any;
+}
diff --git a/types/live-plugin-manager.d.tsx b/types/live-plugin-manager.d.tsx
index 10f7618e9..af8181684 100644
--- a/types/live-plugin-manager.d.tsx
+++ b/types/live-plugin-manager.d.tsx
@@ -13,6 +13,13 @@ export declare class PluginManager {
name: string,
version?: string,
): Promise;
+ installFromPath(
+ location: string,
+ options?: {
+ force: boolean;
+ },
+ ): Promise;
+
readonly options: LivePluginManager.PluginManagerOptions;
}
diff --git a/yarn.lock b/yarn.lock
index 92f8fc24c..1786d3380 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1296,6 +1296,13 @@
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd"
integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==
+"@types/decompress@4.2.3":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/@types/decompress/-/decompress-4.2.3.tgz#98eed48af80001038aa05690b2094915f296fe65"
+ integrity sha512-W24e3Ycz1UZPgr1ZEDHlK4XnvOr+CpJH3qNsFeqXwwlW/9END9gxn3oJSsp7gYdiQxrXUHwUUd3xuzVz37MrZQ==
+ dependencies:
+ "@types/node" "*"
+
"@types/deep-equal@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
@@ -2316,6 +2323,14 @@ better-assert@~1.0.0:
dependencies:
callsite "1.0.0"
+bl@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
+ integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
+ dependencies:
+ readable-stream "^2.3.5"
+ safe-buffer "^5.1.1"
+
blob@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
@@ -2459,11 +2474,29 @@ bser@^2.0.0:
dependencies:
node-int64 "^0.4.0"
+buffer-alloc-unsafe@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
+ integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
+
+buffer-alloc@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
+ integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
+ dependencies:
+ buffer-alloc-unsafe "^1.1.0"
+ buffer-fill "^1.0.0"
+
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
+buffer-fill@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
+ integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
+
buffer-from@1.x, buffer-from@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
@@ -2825,6 +2858,13 @@ commander@^2.11.0, commander@^2.3.0, commander@~2.20.3:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+commander@~2.8.1:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4"
+ integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=
+ dependencies:
+ graceful-readlink ">= 1.0.0"
+
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -3146,6 +3186,59 @@ decompress-response@^3.3.0:
dependencies:
mimic-response "^1.0.0"
+decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1"
+ integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==
+ dependencies:
+ file-type "^5.2.0"
+ is-stream "^1.1.0"
+ tar-stream "^1.5.2"
+
+decompress-tarbz2@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b"
+ integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==
+ dependencies:
+ decompress-tar "^4.1.0"
+ file-type "^6.1.0"
+ is-stream "^1.1.0"
+ seek-bzip "^1.0.5"
+ unbzip2-stream "^1.0.9"
+
+decompress-targz@^4.0.0, decompress-targz@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee"
+ integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==
+ dependencies:
+ decompress-tar "^4.1.1"
+ file-type "^5.2.0"
+ is-stream "^1.1.0"
+
+decompress-unzip@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69"
+ integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k=
+ dependencies:
+ file-type "^3.8.0"
+ get-stream "^2.2.0"
+ pify "^2.3.0"
+ yauzl "^2.4.2"
+
+decompress@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d"
+ integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50=
+ dependencies:
+ decompress-tar "^4.0.0"
+ decompress-tarbz2 "^4.0.0"
+ decompress-targz "^4.0.0"
+ decompress-unzip "^4.0.1"
+ graceful-fs "^4.1.10"
+ make-dir "^1.0.0"
+ pify "^2.3.0"
+ strip-dirs "^2.0.0"
+
deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.1.tgz#fc12bbd6850e93212f21344748682ccc5a8813cf"
@@ -3492,7 +3585,7 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
-end-of-stream@^1.1.0:
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@@ -4182,6 +4275,13 @@ fd-slicer@~1.0.1:
dependencies:
pend "~1.2.0"
+fd-slicer@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+ integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=
+ dependencies:
+ pend "~1.2.0"
+
figures@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec"
@@ -4196,6 +4296,21 @@ file-entry-cache@^5.0.1:
dependencies:
flat-cache "^2.0.1"
+file-type@^3.8.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
+ integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
+
+file-type@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6"
+ integrity sha1-LdvqfHP/42No365J3DOMBYwritY=
+
+file-type@^6.1.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919"
+ integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==
+
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
@@ -4354,6 +4469,11 @@ from2@^2.3.0:
inherits "^2.0.1"
readable-stream "^2.0.0"
+fs-constants@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+ integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
+
fs-extra@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@@ -4447,6 +4567,14 @@ get-params@^0.1.2:
resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe"
integrity sha1-uuDfq6WIoMYNeDTA2Nwv9g7u8v4=
+get-stream@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de"
+ integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4=
+ dependencies:
+ object-assign "^4.0.1"
+ pinkie-promise "^2.0.0"
+
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
@@ -4608,11 +4736,21 @@ got@^9.6.0:
to-readable-stream "^1.0.0"
url-parse-lax "^3.0.0"
+graceful-fs@^4.1.10:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423"
+ integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==
+
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.2.tgz#6f0952605d0140c1cfdb138ed005775b92d67b02"
integrity sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==
+"graceful-readlink@>= 1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
+ integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=
+
graphql@^14.0.0:
version "14.5.8"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.8.tgz#504f3d3114cb9a0a3f359bbbcf38d9e5bf6a6b3c"
@@ -5162,6 +5300,11 @@ is-map@^2.0.0:
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1"
integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==
+is-natural-number@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8"
+ integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg=
+
is-npm@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
@@ -6708,7 +6851,7 @@ oauth-sign@~0.9.0:
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
-object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -7178,7 +7321,7 @@ picomatch@^2.0.5:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5"
integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==
-pify@^2.0.0:
+pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
@@ -7193,6 +7336,18 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+pinkie-promise@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
+ dependencies:
+ pinkie "^2.0.0"
+
+pinkie@^2.0.0:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+
pirates@^4.0.0, pirates@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
@@ -7667,6 +7822,19 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6, readable
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
+readable-stream@^2.3.0, readable-stream@^2.3.5:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
realpath-native@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
@@ -8137,7 +8305,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@^5.0.1, safe-buffer@^5.1.2:
+safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2:
version "5.2.0"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519"
integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==
@@ -8206,6 +8374,13 @@ scheduler@^0.18.0:
loose-envify "^1.1.0"
object-assign "^4.1.1"
+seek-bzip@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc"
+ integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=
+ dependencies:
+ commander "~2.8.1"
+
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
@@ -8736,6 +8911,13 @@ strip-bom@^3.0.0:
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
+strip-dirs@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
+ integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==
+ dependencies:
+ is-natural-number "^4.0.1"
+
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
@@ -8804,6 +8986,19 @@ table@^5.2.3:
slice-ansi "^2.1.0"
string-width "^3.0.0"
+tar-stream@^1.5.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
+ integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
+ dependencies:
+ bl "^1.0.0"
+ buffer-alloc "^1.2.0"
+ end-of-stream "^1.0.0"
+ fs-constants "^1.0.0"
+ readable-stream "^2.3.0"
+ to-buffer "^1.1.1"
+ xtend "^4.0.0"
+
tar@^4:
version "4.4.13"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
@@ -8877,7 +9072,7 @@ throttleit@^1.0.0:
resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=
-through@2, "through@>=2.2.7 <3", through@^2.3.6:
+through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
@@ -8909,6 +9104,11 @@ to-array@0.1.4:
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
+to-buffer@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
+ integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
+
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -9116,6 +9316,14 @@ uid2@0.0.3:
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=
+unbzip2-stream@^1.0.9:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a"
+ integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg==
+ dependencies:
+ buffer "^5.2.1"
+ through "^2.3.8"
+
unherit@^1.0.4:
version "1.1.2"
resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.2.tgz#14f1f397253ee4ec95cec167762e77df83678449"
@@ -9663,7 +9871,7 @@ xmlhttprequest-ssl@~1.5.4:
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
-xtend@^4.0.1:
+xtend@^4.0.0, xtend@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
@@ -9782,6 +9990,14 @@ yauzl@2.4.1:
dependencies:
fd-slicer "~1.0.1"
+yauzl@^2.4.2:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+ integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=
+ dependencies:
+ buffer-crc32 "~0.2.3"
+ fd-slicer "~1.1.0"
+
yazl@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/yazl/-/yazl-2.5.1.tgz#a3d65d3dd659a5b0937850e8609f22fffa2b5c35"