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"