diff --git a/.circleci/config.yml b/.circleci/config.yml index 882d6e4..6baf59f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,7 +42,4 @@ workflows: version: 2 test: jobs: - - test: - filters: - branches: - only: develop + - test diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..e8e7d69 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +flow-custom-typedefs/*.js \ No newline at end of file diff --git a/.flowconfig b/.flowconfig index f2d95fd..945b564 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,11 +1,12 @@ [ignore] .*/node_modules/polished/.* -./__tests__ +./__tests__/**.js [include] [libs] flow-typed +flow-custom-typedefs [lints] diff --git a/app/components/button.js b/app/components/button.js index d867613..f3291cf 100644 --- a/app/components/button.js +++ b/app/components/button.js @@ -76,6 +76,7 @@ type Props = { icon?: string | null, className?: string, isLoading?: boolean, + id?: string, }; export const Button = ({ @@ -123,4 +124,5 @@ Button.defaultProps = { disabled: false, className: '', isLoading: false, + id: '', }; diff --git a/app/components/column.js b/app/components/column.js index 7f80ede..44b0e0a 100644 --- a/app/components/column.js +++ b/app/components/column.js @@ -1,8 +1,7 @@ // @flow -import React from 'react'; +import React, { type Node, type ElementProps } from 'react'; import styled from 'styled-components'; -import type { Node, ElementProps } from 'react'; const Flex = styled.div` display: flex; @@ -22,7 +21,7 @@ type Props = { }; export const ColumnComponent = ({ children, ...props }: Props) => ( - {React.Children.map(children, ch => ch)} + {React.Children.map(children, (ch: Node) => ch)} ); ColumnComponent.defaultProps = { diff --git a/app/components/confirm-dialog.js b/app/components/confirm-dialog.js index d8543d0..3ac980c 100644 --- a/app/components/confirm-dialog.js +++ b/app/components/confirm-dialog.js @@ -80,7 +80,7 @@ export const ConfirmDialogComponent = ({ closeOnEsc={false} > {toggle => ( - + diff --git a/app/components/dropdown.js b/app/components/dropdown.js index c90ff91..bc10e1b 100644 --- a/app/components/dropdown.js +++ b/app/components/dropdown.js @@ -13,10 +13,9 @@ import truncateAddress from '../utils/truncateAddress'; /* eslint-disable max-len */ const MenuWrapper = styled.div` - background-image: ${props => `linear-gradient(to right, ${darken( - 0.05, - props.theme.colors.activeItem, - )}, ${props.theme.colors.activeItem})`}; + background-image: ${props => `linear-gradient(to right, ${darken(0.05, props.theme.colors.activeItem)}, ${ + props.theme.colors.activeItem + })`}; border-radius: ${props => props.theme.boxBorderRadius}; margin-left: -10px; max-width: 400px; @@ -56,7 +55,7 @@ const MenuItem = styled.button` const OptionItem = styled(MenuItem)` &:hover { - background-color: #F9D114; + background-color: #f9d114; } `; @@ -100,9 +99,7 @@ export class DropdownComponent extends Component { } = this.props; const body = [ - this.setState(() => ({ isOpen: false }))} - > + this.setState(() => ({ isOpen: false }))}> {label && ( @@ -126,10 +123,7 @@ export class DropdownComponent extends Component { tipSize={7} body={body} > - {renderTrigger( - () => this.setState(state => ({ isOpen: !state.isOpen })), - isOpen, - )} + {renderTrigger(() => this.setState(state => ({ isOpen: !state.isOpen })), isOpen)} ); } diff --git a/app/components/sidebar.js b/app/components/sidebar.js index 5ca69e1..d85e73d 100644 --- a/app/components/sidebar.js +++ b/app/components/sidebar.js @@ -1,5 +1,5 @@ // @flow - +/* eslint-disable max-len */ import React from 'react'; import styled from 'styled-components'; import type { Location, RouterHistory } from 'react-router-dom'; diff --git a/app/components/text.js b/app/components/text.js index 21ab22a..ec182ce 100644 --- a/app/components/text.js +++ b/app/components/text.js @@ -16,7 +16,7 @@ const Text = styled.p` text-align: ${props => props.align}; `; -type Props = { +export type Props = { ...ElementProps<'p'>, value: string, isBold?: boolean, diff --git a/app/containers/dashboard.js b/app/containers/dashboard.js index 2316756..56e8df0 100644 --- a/app/containers/dashboard.js +++ b/app/containers/dashboard.js @@ -5,6 +5,7 @@ import eres from 'eres'; import flow from 'lodash.flow'; import groupBy from 'lodash.groupby'; import dateFns from 'date-fns'; +import { BigNumber } from 'bignumber.js'; import { DashboardView } from '../views/dashboard'; import rpc from '../../services/api'; import store from '../../config/electron-store'; @@ -33,28 +34,16 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ getSummary: async () => { dispatch(loadWalletSummary()); - const [err, walletSummary] = await eres(rpc.z_gettotalbalance()); - - if (err) return dispatch(loadWalletSummaryError({ error: err.message })); - - const [zAddressesErr, zAddresses] = await eres(rpc.z_listaddresses()); - - const [tAddressesErr, transparentAddresses] = await eres( - rpc.getaddressesbyaccount(''), - ); - - // eslint-disable-next-line - if (zAddressesErr || tAddressesErr) return dispatch( - loadWalletSummaryError({ - error: zAddressesErr?.message || tAddressesErr?.message, - }), - ); - + const [walletErr, walletSummary] = await eres(rpc.z_gettotalbalance()); + const [zAddressesErr, zAddresses = []] = await eres(rpc.z_listaddresses()); + const [tAddressesErr, tAddresses = []] = await eres(rpc.getaddressesbyaccount('')); const [transactionsErr, transactions] = await eres(rpc.listtransactions()); - if (transactionsErr) { + if (walletErr || zAddressesErr || tAddressesErr || transactionsErr) { return dispatch( - loadWalletSummaryError({ error: transactionsErr.message }), + loadWalletSummaryError({ + error: 'Something went wrong!', + }), ); } @@ -75,21 +64,15 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ ])(transactions); if (!zAddresses.length) { - const [getNewZAddressErr, newZAddress] = await eres( - rpc.z_getnewaddress(), - ); + const [, newZAddress] = await eres(rpc.z_getnewaddress()); - if (!getNewZAddressErr && newZAddress) { - zAddresses.push(newZAddress); - } + if (newZAddress) zAddresses.push(newZAddress); } - if (!transparentAddresses.length) { - const [getNewAddressErr, newAddress] = await eres(rpc.getnewaddress('')); + if (!tAddresses.length) { + const [, newTAddress] = await eres(rpc.getnewaddress('')); - if (!getNewAddressErr && newAddress) { - transparentAddresses.push(newAddress); - } + if (newTAddress) tAddresses.push(newTAddress); } dispatch( @@ -97,9 +80,9 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ transparent: walletSummary.transparent, total: walletSummary.total, shielded: walletSummary.private, - addresses: [...zAddresses, ...transparentAddresses], + addresses: [...zAddresses, ...tAddresses], transactions: formattedTransactions, - zecPrice: store.get('ZEC_DOLLAR_PRICE'), + zecPrice: new BigNumber(store.get('ZEC_DOLLAR_PRICE')).toNumber(), }), ); }, diff --git a/app/containers/send.js b/app/containers/send.js index 9fe767c..30b7bf5 100644 --- a/app/containers/send.js +++ b/app/containers/send.js @@ -48,6 +48,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ }: SendTransactionInput) => { dispatch(sendTransaction()); + // $FlowFixMe const [sendErr, operationId] = await eres( rpc.z_sendmany( from, @@ -136,7 +137,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ }, loadZECPrice: () => dispatch( loadZECPrice({ - value: store.get('ZEC_DOLLAR_PRICE'), + value: Number(store.get('ZEC_DOLLAR_PRICE')), }), ), }); diff --git a/app/containers/transactions.js b/app/containers/transactions.js index fc24fb8..77270ae 100644 --- a/app/containers/transactions.js +++ b/app/containers/transactions.js @@ -31,14 +31,10 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ getTransactions: async () => { dispatch(loadTransactions()); - const [transactionsErr, transactions = []] = await eres( - rpc.listtransactions(), - ); + const [transactionsErr, transactions = []] = await eres(rpc.listtransactions()); if (transactionsErr) { - return dispatch( - loadTransactionsError({ error: transactionsErr.message }), - ); + return dispatch(loadTransactionsError({ error: transactionsErr.message })); } const formattedTransactions = flow([ @@ -60,7 +56,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({ dispatch( loadTransactionsSuccess({ list: formattedTransactions, - zecPrice: store.get('ZEC_DOLLAR_PRICE'), + zecPrice: new BigNumber(store.get('ZEC_DOLLAR_PRICE')).toNumber(), }), ); }, diff --git a/app/index.js b/app/index.js index ec64a6d..a09b9cf 100644 --- a/app/index.js +++ b/app/index.js @@ -1,7 +1,10 @@ +// @flow + import React from 'react'; import ReactDOM from 'react-dom'; import App from './app'; const el = document.getElementById('root'); -ReactDOM.render(, el); + +if (el) ReactDOM.render(, el); diff --git a/app/redux/modules/wallet.js b/app/redux/modules/wallet.js index a7d3879..d0a9e94 100644 --- a/app/redux/modules/wallet.js +++ b/app/redux/modules/wallet.js @@ -8,7 +8,7 @@ export const LOAD_WALLET_SUMMARY_SUCCESS = 'LOAD_WALLET_SUMMARY_SUCCESS'; export const LOAD_WALLET_SUMMARY_ERROR = 'LOAD_WALLET_SUMMARY_ERROR'; // Actions Creators -export const loadWalletSummary = () => ({ +export const loadWalletSummary: () => Action = () => ({ type: LOAD_WALLET_SUMMARY, payload: {}, }); diff --git a/app/types/redux.js b/app/types/redux.js index 84151d4..47e2357 100644 --- a/app/types/redux.js +++ b/app/types/redux.js @@ -4,4 +4,4 @@ type State = {||}; export type Action = { type: $Subtype, payload: Object }; export type GetState = () => State; -export type Dispatch = (action: Action) => any; +export type Dispatch = (action: Action) => void; diff --git a/app/views/settings.js b/app/views/settings.js index 4cf93f4..ea663c8 100644 --- a/app/views/settings.js +++ b/app/views/settings.js @@ -170,6 +170,7 @@ export class SettingsView extends PureComponent { )}.dat`; electron.remote.dialog.showSaveDialog( + undefined, { defaultPath: backupFileName }, async (pathToSave) => { if (!pathToSave) return; @@ -182,19 +183,13 @@ export class SettingsView extends PureComponent { /* eslint-disable no-alert */ if (cannotAccess) { - alert( - "Couldn't backup the wallet.dat file. You need to back it up manually.", - ); + alert("Couldn't backup the wallet.dat file. You need to back it up manually."); } - const [error] = await eres( - promisify(fs.copyFile)(walletDatPath, pathToSave), - ); + const [error] = await eres(promisify(fs.copyFile)(walletDatPath, pathToSave)); if (error) { - alert( - "Couldn't backup the wallet.dat file. You need to back it up manually.", - ); + alert("Couldn't backup the wallet.dat file. You need to back it up manually."); } }, ); @@ -307,16 +302,12 @@ export class SettingsView extends PureComponent { this.setState({ importedPrivateKeys: value }) - } + onChange={value => this.setState({ importedPrivateKeys: value })} inputType='textarea' rows={10} /> {successImportPrivateKeys && ( - + )} {error && } diff --git a/config/daemon/fetch-windows-params.js b/config/daemon/fetch-windows-params.js index dfba7d9..21cade5 100644 --- a/config/daemon/fetch-windows-params.js +++ b/config/daemon/fetch-windows-params.js @@ -71,9 +71,7 @@ const downloadFile = ({ file, pathToSave }): Promise<*> => new Promise((resolve, log(`SHA256 validation for file ${file.name} succeeded!`); resolve(file.name); } else { - reject( - new Error(`SHA256 validation failed for file: ${file.name}`), - ); + reject(new Error(`SHA256 validation failed for file: ${file.name}`)); } }); }) @@ -84,9 +82,7 @@ const downloadFile = ({ file, pathToSave }): Promise<*> => new Promise((resolve, let missingDownloadParam = false; export default (): Promise<*> => new Promise((resolve, reject) => { - const firstRunProcess = cp.spawn( - path.join(getBinariesPath(), 'win', 'first-run.bat'), - ); + const firstRunProcess = cp.spawn(path.join(getBinariesPath(), 'win', 'first-run.bat')); firstRunProcess.stdout.on('data', data => log(data.toString())); firstRunProcess.stderr.on('data', data => reject(data.toString())); @@ -95,12 +91,7 @@ export default (): Promise<*> => new Promise((resolve, reject) => { await Promise.all( FILES.map(async (file) => { - const pathToSave = path.join( - app.getPath('userData'), - '..', - 'ZcashParams', - file.name, - ); + const pathToSave = path.join(app.getPath('userData'), '..', 'ZcashParams', file.name); const [cannotAccess] = await eres( util.promisify(fs.access)(pathToSave, fs.constants.F_OK), @@ -115,11 +106,7 @@ export default (): Promise<*> => new Promise((resolve, reject) => { if (isValid) { log(`${file.name} already is in ${pathToSave}...`); } else { - log( - `File: ${ - file.name - } failed in the SHASUM validation, downloading again...`, - ); + log(`File: ${file.name} failed in the SHASUM validation, downloading again...`); queue.add(() => { // eslint-disable-next-line max-len downloadFile({ file, pathToSave }).then(() => log(`Download ${file.name} finished!`)); diff --git a/config/electron.js b/config/electron.js index 899ca95..4b50b24 100644 --- a/config/electron.js +++ b/config/electron.js @@ -5,11 +5,9 @@ import dotenv from 'dotenv'; import path from 'path'; /* eslint-disable import/no-extraneous-dependencies */ -import { app, BrowserWindow } from 'electron'; +import { app, BrowserWindow, typeof BrowserWindow as BrowserWindowType } from 'electron'; import { autoUpdater } from 'electron-updater'; import isDev from 'electron-is-dev'; -/* eslint-enable import/no-extraneous-dependencies */ -import type { BrowserWindow as BrowserWindowType } from 'electron'; import eres from 'eres'; import { registerDebugShortcut } from '../utils/debug-shortcut'; import runDaemon from './daemon/zcashd-child-process'; @@ -26,10 +24,12 @@ let zcashDaemon; const showStatus = (text) => { if (text === 'Update downloaded') updateAvailable = true; - mainWindow.webContents.send('update', { - updateAvailable, - updateInfo: text, - }); + if (mainWindow) { + mainWindow.webContents.send('update', { + updateAvailable, + updateInfo: text, + }); + } }; const createWindow = () => { @@ -42,9 +42,9 @@ const createWindow = () => { autoUpdater.on('download-progress', progress => showStatus( /* eslint-disable-next-line max-len */ - `Download speed: ${progress.bytesPerSecond} - Downloaded ${ - progress.percent - }% (${progress.transferred}/${progress.total})`, + `Download speed: ${progress.bytesPerSecond} - Downloaded ${progress.percent}% (${ + progress.transferred + }/${progress.total})`, )); autoUpdater.on('update-downloaded', () => { updateAvailable = true; @@ -64,16 +64,14 @@ const createWindow = () => { }); getZecPrice().then((obj) => { - store.set('ZEC_DOLLAR_PRICE', obj.USD); + store.set('ZEC_DOLLAR_PRICE', String(obj.USD)); }); mainWindow.setVisibleOnAllWorkspaces(true); registerDebugShortcut(app, mainWindow); mainWindow.loadURL( - isDev - ? 'http://0.0.0.0:8080/' - : `file://${path.join(__dirname, '../build/index.html')}`, + isDev ? 'http://0.0.0.0:8080/' : `file://${path.join(__dirname, '../build/index.html')}`, ); exports.app = app; diff --git a/config/main.js b/config/main.js index 3219cba..efa1f66 100644 --- a/config/main.js +++ b/config/main.js @@ -1,3 +1,5 @@ +// @flow + const path = require('path'); const appRoot = path.join(__dirname, '..'); diff --git a/coverage.json b/coverage.json new file mode 100644 index 0000000..7841daa --- /dev/null +++ b/coverage.json @@ -0,0 +1,8 @@ +{ + "concurrentFiles": 1, + "globExcludePatterns": ["node_modules/**", "dist/*.js"], + "flowCommandPath": "./node_modules/.bin/flow", + "globIncludePatterns": ["app/**/*.js", "config/**/*.js", "services/**/*.js", "utils/**/*.js"], + "threshold": 70, + "reportTypes": ["html"] +} diff --git a/flow-custom-typedefs/electron-store.js b/flow-custom-typedefs/electron-store.js new file mode 100644 index 0000000..aa2a7c0 --- /dev/null +++ b/flow-custom-typedefs/electron-store.js @@ -0,0 +1,24 @@ +declare module 'electron-store' { + declare class ElectronStore { + constructor({ + defaults?: Object, + name?: string, + cwd?: string, + encryptionKey?: string | Buffer, + fileExtension?: string, + }): ElectronStore; + + set(key: string, value: string): void; + set(payload: Object): void; + get(key: string): string; + has(key: string): boolean; + delete(key: string): void; + clear(): void; + size: number; + store: Object; + path: string; + openInEditor(): void; + } + + declare export default typeof ElectronStore; +} diff --git a/flow-custom-typedefs/electron.js b/flow-custom-typedefs/electron.js new file mode 100644 index 0000000..1edc609 --- /dev/null +++ b/flow-custom-typedefs/electron.js @@ -0,0 +1,959 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the license found in the LICENSE file in + * the root directory of this source tree. + * + * @flow + */ + +// The properties on this module depend on whether the importer is the main +// process or a renderer process. +declare module 'electron' { + // Main process: + declare var app: electron$app; + declare var autoUpdater: electron$autoUpdater; + // $FlowFixMe + declare var BrowserWindow: typeof electron$BrowserWindow; + declare var contentTracing: electron$contentTracing; + declare var dialog: electron$dialog; + declare var globalShortcut: electron$globalShortcut; + declare var ipcMain: electron$IpcMain; + // $FlowFixMe + declare var Menu: typeof electron$Menu; + // $FlowFixMe + declare var MenuItem: typeof electron$MenuItem; + declare var powerMonitor: electron$powerMonitor; + declare var powerSaveBlocker: electron$powerSaveBlocker; + declare var protocol: electron$protocol; + declare var session: electron$session; + declare var electron$Tray: typeof electron$Tray; + declare var webContents: electron$webContents; + + // Renderer process: + declare var desktopCapturer: electron$desktopCapturer; + declare var ipcRenderer: electron$IpcRenderer; + declare var remote: electron$remote; + declare var webFrame: electron$webFrame; + + // Both: + declare var clipboard: electron$clipboard; + declare var crashReporter: electron$crashReporter; + declare var nativeImage: electron$nativeImage; + declare var screen: electron$Screen; + declare var shell: electron$shell; + + declare type electron$BrowserWindow = electron$BrowserWindow; + declare type electron$Menu = electron$Menu; + declare type electron$MenuItem = electron$MenuItem; + declare type electron$NativeImage = electron$NativeImage; + declare type electron$Screen = electron$Screen; + declare type electron$WebContents = electron$WebContents; +} + +// very common struct +type electron$rect = { + x: number, + y: number, + width: number, + height: number, +}; + +//------------------------------------------------------------------------------ +// Custom DOM Elements +//------------------------------------------------------------------------------ + +/** + * https://github.com/electron/electron/blob/master/docs/api/file-object.md + */ + +// HTML5 File API but with a `path` attribute added. + +/** + * https://github.com/electron/electron/blob/master/docs/api/web-view-tag.md + */ + +declare class WebviewElement extends HTMLElement { + src: string; + nodeintegration: boolean; + disablewebsecurity: boolean; + + executeJavaScript(code: string, userGesture: ?boolean): void; + getTitle(): string; + // This used to be `getUrl`, but the old version was dropped in the electron bundled with Atom + // 1.12, and the new version exists at least in Atom 1.10.2 onward. + getURL(): string; + // Not sure when this was introduced + stop?: () => void; + insertCSS(code: string): void; + send(channel: string, ...args: Array): void; + openDevTools(): void; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/window-open.md + */ + +// window.open + +//------------------------------------------------------------------------------ +// Modules for the Main Process +//------------------------------------------------------------------------------ + +/** + * https://github.com/electron/electron/blob/master/docs/api/app.md + */ + +type electron$app = { + quit(): void, + exit(exitCode?: number): void, + relaunch(options?: { args?: Array, execPath?: string }): void, + isReady(): boolean, + focus(): void, + getAppPath(): string, + getPath(name: string): string, + setPath(name: string, path: string): void, + getVersion(): string, + getName(): string, + setName(name: string): void, + getLocale(): string, + makeSingleInstance(callback: (argv: Array, workingDirectory: string) => void): boolean, + releaseSingleInstance(): void, + disableHardwareAcceleration(): void, + on(event: string, callback: () => any): void, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/auto-updater.md + */ + +type electron$autoUpdater = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/browser-window.md + */ + +type electron$BrowserWindowOptions = { + width?: number, + height?: number, + x?: number, + y?: number, + useContentSize?: boolean, + center?: boolean, + minWidth?: number, + minHeight?: number, + maxWidth?: number, + maxHeight?: number, + resizable?: boolean, + movable?: boolean, + minimizable?: boolean, + maximizable?: boolean, + closable?: boolean, + focusable?: boolean, + alwaysOnTop?: boolean, + fullscreen?: boolean, + fullscreenable?: boolean, + skipTaskbar?: boolean, + kiosk?: boolean, + title?: string, + icon?: electron$NativeImage, + show?: boolean, + frame?: boolean, + parent?: electron$BrowserWindow, + modal?: boolean, + acceptFirstMouse?: boolean, + disableAutoHideCursor?: boolean, + autoHideMenuBar?: boolean, + enableLargerThanScreen?: boolean, + backgroundColor?: string, + hasShadow?: boolean, + darkTheme?: boolean, + transparent?: boolean, + type?: + | 'desktop' + | 'dock' + | 'toolbar' + | 'splash' + | 'notification' + /* macOS */ + | 'desktop' + | 'textured' + /* Windows */ + | 'toolbar', + titleBarStyle?: 'default' | 'hidden' | 'hidden-inset', + thickFrame?: boolean, + webPreferences?: electron$BrowserWindowWebPreferences, +}; + +type electron$BrowserWindowWebPreferences = { + nodeIntegration?: boolean, + preload?: string, + session?: electron$session, + partition?: string, + zoomFactor?: number, + javascript?: boolean, + webSecurity?: boolean, + allowDisplayingInsecureContent?: boolean, + allowRunningInsecureContent?: boolean, + images?: boolean, + textAreasAreResizable?: boolean, + webgl?: boolean, + webaudio?: boolean, + plugins?: boolean, + experimentalFeatures?: boolean, + experimentalCanvasFeatures?: boolean, + scrollBounce?: boolean, + blinkFeatures?: string, + disableBlinkFeatures?: string, + defaultFontFamily?: { + standard?: string, + serif?: string, + sansSerif?: string, + monospace?: string, + }, + defaultFontSize?: number, + defaultMonospaceFontSize?: number, + minimumFontSize?: number, + defaultEncoding?: string, + backgroundThrottling?: boolean, + offscreen?: boolean, +}; + +type electron$BrowserWindowEvents = + | 'page-title-updated' + | 'close' + | 'closed' + | 'unresponsive' + | 'responsive' + | 'blur' + | 'focus' + | 'show' + | 'hide' + | 'ready-to-show' + | 'maximize' + | 'unmaximize' + | 'minimize' + | 'restore' + | 'resize' + | 'move' + | 'moved' + | 'enter-full-screen' + | 'leave-full-screen' + | 'enter-html-full-screen' + | 'leave-html-full-screen' + | 'context-menu' + | 'app-command' // Windows + | 'scroll-touch-begin' // macOS + | 'scroll-touch-end' // macOS + | 'swipe'; // macOS + +type electron$BrowserWindowListener = ( + event: electron$BrowserWindowEvents, + callback: (event: Object, ...args: Array) => void, +) => electron$BrowserWindow; + +declare class electron$BrowserWindow { + constructor(options: electron$BrowserWindowOptions): void; + on: electron$BrowserWindowListener; + once: electron$BrowserWindowListener; + removeAllListeners(event?: electron$BrowserWindowEvents): electron$BrowserWindow; + removeListener(event?: electron$BrowserWindowEvents, callback: Function): electron$BrowserWindow; + send(channel: string, ...args: Array): void; + + static getAllWindows(): Array; + static getFocusedWindow(): ?electron$BrowserWindow; + static fromWebContents(webContents: electron$WebContents): ?electron$BrowserWindow; + static fromId(id: number): ?electron$BrowserWindow; + static addDevToolsExtension(path: string): void; + static removeDevToolsExtension(name: string): void; + static getDevToolsExtensions(): { [name: string]: { [name: string]: string } }; + + webContents: electron$WebContents; + id: number; + destroy(): void; + close(): void; + focus(): void; + blur(): void; + isFocused(): boolean; + show(): void; + showInactive(): void; + hide(): void; + isVisible(): boolean; + isModal(): boolean; + maximize(): void; + unmaximize(): void; + isMaximized(): boolean; + minimize(): void; + restore(): void; + isMinimized(): boolean; + setFullScreen(flag: boolean): void; + isFullScreen(): boolean; + setAspectRatio(aspectRatio: number, extraSize?: { width: number, height: number }): void; // macOS + setBounds(options: electron$rect, /* macOS */ animate?: boolean): void; + getBounds(): electron$rect; + setSize(width: number, height: number, /* macOS */ animate?: boolean): void; + getSize(): [number, number]; + setContentSize(width: number, height: number, /* macOS */ animate?: boolean): void; + getContentSize(): [number, number]; + setMinimumSize(width: number, height: number): void; + getMinimumSize(): [number, number]; + setMaximumSize(width: number, height: number): void; + getMaximumSize(): [number, number]; + setResizable(resizable: boolean): void; + isResizable(): boolean; + setMovable(movable: boolean): void; // macOS Windows + isMovable(): boolean; // macOS Windows + setMinimizable(minimizable: boolean): void; // macOS Windows + isMinimizable(): boolean; // macOS Windows + setMaximizable(maximizable: boolean): void; // macOS Windows + isMaximizable(): boolean; // macOS Windows + setFullScreenable(fullscreenable: boolean): void; + isFullScreenable(): boolean; + setClosable(closable: boolean): void; // macOS Windows + isClosable(): boolean; // macOS Windows + setAlwaysOnTop(flag: boolean): void; + isAlwaysOnTop(): boolean; + center(): void; + setPosition(x: number, y: number, /* macOS */ animate?: boolean): void; + getPosition(): [number, number]; + setTitle(title: string): void; + getTitle(): string; + setSheetOffset(offsetY: number, offsetX?: number): void; // macOS + flashFrame(flag: boolean): void; + setSkipTaskbar(skip: boolean): void; + setKiosk(flag: boolean): void; + isKiosk(): boolean; + getNativeWindowHandle(): Buffer; + hookWindowMessage(message: number, callback: Function): void; // Windows + isWindowMessageHooked(message: number): boolean; // Windows + unhookWindowMessage(message: number): void; // Windows + unhookAllWindowMessages(): void; // Windows + setRepresentedFilename(filename: string): void; // macOS + getRepresentedFilename(): string; // macOS + setDocumentEdited(edited: boolean): void; // macOS + isDocumentEdited(): boolean; // macOS + focusOnWebView(): void; + blurWebView(): void; + capturePage(rect: electron$rect, callback: (image: electron$NativeImage) => void): void; + capturePage(callback: (image: electron$NativeImage) => void): void; + loadURL( + url: string, + options?: { httpReferrer?: string, userAgent?: string, extraHeaders?: string }, + ): void; + reload(): void; + setMenu(menu: ?electron$Menu): void; // Linux Windows + setProgressBar(progress: number): void; + setOverlayIcon(overlay: electron$NativeImage, description: string): void; // Windows + setHasShadow(hasShadow: boolean): void; // macOS + hasShadow(): boolean; // macOS + setThumbarButtons( + buttons: Array<{ + icon: electron$NativeImage, + click: Function, + tooltip?: string, + flags?: Array< + 'enabled' | 'disabled' | 'dismissonclick' | 'nobackground' | 'hidden' | 'noninteractive', + >, + }>, + ): void; // Windows + setThumbnailClip(region: electron$rect): void; // Windows + showDefinitionForSelection(): void; // macOS + setIcon(icon: electron$NativeImage): void; // Windows Linux + setAutoHideMenuBar(hide: boolean): void; + isMenuBarAutoHide(): boolean; + setMenuBarVisibility(visible: boolean): void; + isMenuBarVisible(): boolean; + setVisibleOnAllWorkspaces(visible: boolean): void; + isVisibleOnAllWorkspaces(): boolean; + setIgnoreMouseEvents(ignore: boolean): void; + setContentProtection(enable: boolean): void; // macOS Windows + setFocusable(focusable: boolean): void; // Windows + setParentWindow(parent: electron$BrowserWindow): void; // Linux macOS + getParentWindow(): ?electron$BrowserWindow; + getChildWindows(): Array; + + // Atom sets this during window setup (see: src/main-process/atom-window.coffee). + loadSettings?: Object; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/content-tracing.md + */ + +type electron$contentTracing = { + startRecording( + options: { categoryFilter: string, traceOptions: string }, + callback: () => mixed, + ): boolean, + + stopRecording(resultFilePath: ?string, callback: (resultFilePath: string) => mixed): void, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/dialog.md + */ + +type electron$dialog = { + showOpenDialog( + browserWindow?: electron$BrowserWindow, + options: electron$dialogOpenOptions, + callback?: Function, + ): Array, + showSaveDialog( + browserWindow?: electron$BrowserWindow, + options: electron$dialogSaveOptions, + callback?: Function, + ): string, + showMessageBox( + browserWindow?: electron$BrowserWindow, + options: electron$dialogMessageBoxOptions, + callback?: Function, + ): number, + showErrorBox(title: string, content: string): void, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/dialog.md + * See `dialog.showOpenDialog()` + */ + +type electron$dialogOpenOptions = { + title?: string, + defaultPath?: string, + buttonLabel?: string, + filters?: Array, + properties?: Array, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/dialog.md + * See `dialog.showSaveDialog()` + */ + +type electron$dialogSaveOptions = { + title?: string, + defaultPath?: string, + buttonLabel?: string, + filters?: Array, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/dialog.md + * See `dialog.showMessageBox()` + */ + +type electron$dialogMessageBoxOptions = { + type?: string, + buttons?: Array, + defaultId?: number, + title?: string, + message?: string, + detail?: string, + icon?: electron$NativeImage, + cancelId?: number, + noLink?: boolean, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/global-shortcut.md + */ + +type electron$globalShortcut = { + register: (string, () => void) => boolean, + isRegistered: string => boolean, + unregister: string => void, + unregisterAll: () => void, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/ipc-main.md + */ + +declare class electron$IpcMain {} + +/** + * https://github.com/electron/electron/blob/master/docs/api/menu.md + */ + +declare class electron$Menu { + static setApplicationMenu(menu: electron$Menu): void; + static getApplicationMenu(): ?electron$Menu; + static sendActionToFirstResponder(action: string): void; + static buildFromTemplate(templates: Array): electron$Menu; + popup( + browserWindow: electron$BrowserWindow, + x?: number, + y?: number, + positioningItem?: number, + ): void; + popup(x?: number, y?: number, positioningItem?: number): void; + append(menuItem: electron$MenuItem): void; + insert(pos: number, menuItem: electron$MenuItem): void; + items: Array; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/menu-item.md + */ + +type electron$MenuItemOptions = { + click?: ( + menuItem: electron$MenuItem, + browserWindow: electron$BrowserWindow, + event: Object, + ) => void, + role?: + | 'undo' + | 'redo' + | 'cut' + | 'copy' + | 'paste' + | 'pasteandmatchstyle' + | 'selectall' + | 'delete' + | 'minimize' + | 'close' + | 'quit' + | 'togglefullscreen' + // macOS-only + | 'about' + | 'hide' + | 'hideothers' + | 'unhide' + | 'front' + | 'zoom' + | 'window' + | 'help' + | 'services', + type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio', + label?: string, + sublabel?: string, + accelerator?: string, + icon?: electron$NativeImage, + enabled?: boolean, + visible?: boolean, + checked?: boolean, + submenu?: electron$MenuItem | electron$MenuItemOptions, + id?: string, + position?: string, +}; + +declare class electron$MenuItem { + constructor(options: electron$MenuItemOptions): void; + enabled: boolean; + visible: boolean; + checked: boolean; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/power-monitor.md + */ + +type electron$powerMonitor = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/power-save-blocker.md + */ + +type electron$powerSaveBlocker = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/protocol.md + */ + +type electron$protocol = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/session.md + */ + +type electron$session = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/system-preferences.md + */ + +type electron$systemPreferences = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/tray.md + */ + +declare class electron$Tray {} + +/** + * https://github.com/electron/electron/blob/master/docs/api/web-contents.md + */ + +type electron$InputEventModifiers = Array< + | 'shift' + | 'control' + | 'alt' + | 'meta' + | 'isKeypad' + | 'isAutoRepeat' + | 'leftButtonDown' + | 'middleButtonDown' + | 'rightButtonDown' + | 'capsLock' + | 'numLock' + | 'left' + | 'right', +>; + +declare class electron$WebContents extends events$EventEmitter { + loadURL( + url: string, + options?: { httpReferrer?: string, userAgent?: string, extraHeaders?: string }, + ): void; + downloadURL(url: string): void; + getURL(): string; + getTitle(): string; + isDestroyed(): boolean; + isFocused(): boolean; + isLoading(): boolean; + isLoadingMainFrame(): boolean; + isWaitingForResponse(): boolean; + stop(): void; + reload(): void; + reloadIgnoringCache(): void; + canGoBack(): boolean; + canGoForward(): boolean; + canGoToOffset(offset: number): boolean; + clearHistory(): void; + goBack(): void; + goForward(): void; + goToIndex(index: number): void; + goToOffset(index: number): void; + isCrashed(): boolean; + setUserAgent(userAgent: string): void; + getUserAgent(): string; + insertCSS(css: string): void; + // Keep `result` as mixed (and not any) to make this unsafe function less so. + executeJavaScript(code: string, callback: (result: mixed) => void): void; + executeJavaScript(code: string, userGesture?: boolean, callback?: (result: mixed) => void): void; + setAudioMuted(muted: boolean): void; + isAudioMuted(): boolean; + setZoomFactor(factor: number): void; + getZoomFactor(callback: (factor: number) => void): void; + setZoomLevel(level: number): void; + getZoomLevel(callback: (level: number) => void): void; + setZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; + setVisualZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; + setLayoutZoomLevelLimits(minimumLevel: number, maximumLevel: number): void; + undo(): void; + redo(): void; + cut(): void; + copy(): void; + copyImageAt(x: number, y: number): void; + paste(): void; + pasteAndMatchStyle(): void; + delete(): void; + selectAll(): void; + unselect(): void; + replace(text: string): void; + replaceMisspelling(text: string): void; + insertText(text: string): void; + inserfindInPagetText( + text: string, + options?: { + forward?: boolean, + findNext?: boolean, + matchCase?: boolean, + wordStart?: boolean, + medialCapitalAsWordStart?: boolean, + }, + ): void; + stopFindInPage(action: 'clearSelection' | 'keepSelection' | 'activateSelection'): void; + capturePage(rect: electron$rect, callback: (image: electron$NativeImage) => void): void; + capturePage(callback: (image: electron$NativeImage) => void): void; + hasServiceWorker(callback: (result: boolean) => void): void; + unregisterServiceWorker(callback: (result: boolean) => void): void; + print(options?: { silent?: boolean, printBackground?: boolean }): void; + printToPDF( + options: { + marginsType: number, + pageSize: string, + pageSize: string, + printBackground: boolean, + printSelectionOnly: boolean, + landscape: boolean, + }, + callback: (err: ?mixed, data: ?Buffer) => void, + ): void; + addWorkSpace(path: string): void; + removeWorkSpace(path: string): void; + openDevTools(options?: { mode: 'right' | 'bottom' | 'undocked' | 'detach' }): void; + closeDevTools(): void; + isDevToolsOpened(): boolean; + isDevToolsFocused(): boolean; + toggleDevTools(): void; + inspectElement(x: number, y: number): void; + inspectServiceWorker(): void; + send(channel: string, ...args: Array): void; + enableDeviceEmulation(parameters: { + screenPosition?: 'desktop' | 'mobile', + screenSize: { width: number, height: number }, + viewPosition?: { x: number, y: number }, + deviceScaleFactor?: number, + viewSize?: { width: number, height: number }, + fitToView?: boolean, + offset?: { x: number, y: number }, + scale?: number, + }): void; + disableDeviceEmulation(): void; + sendInputEvent( + event: + | { + type: 'keyDown' | 'keyUp' | 'char', + modifiers?: electron$InputEventModifiers, + keyCode: string, + } + | { + type: 'mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu', + modifiers?: electron$InputEventModifiers, + x: number, + y: number, + button: 'left' | 'middle' | 'right', + globalX: number, + globalY: number, + movementX: number, + movementY: number, + clickCount: number, + } + | { + type: 'mouseWheel', + modifiers?: electron$InputEventModifiers, + x: number, + y: number, + button: 'left' | 'middle' | 'right', + globalX: number, + globalY: number, + movementX: number, + movementY: number, + clickCount: number, + deltaX: number, + deltaY: number, + wheelTicksX: number, + wheelTicksY: number, + accelerationRatioX: number, + accelerationRatioY: number, + hasPreciseScrollingDeltas: boolean, + canScroll: boolean, + }, + ): void; + beginFrameSubscription(callback: (frameBuffer: Buffer, dirtyRect: electron$rect) => void): void; + beginFrameSubscription( + onlyDirty?: boolean, + callback: (frameBuffer: Buffer, dirtyRect: electron$rect) => void, + ): void; + endFrameSubscription(): void; + startDrag(item: { file: string, icon: electron$NativeImage }): void; + savePage( + fullPath: string, + saveType: 'HTMLOnly' | 'HTMLComplete' | 'MHTML', + callback: (error: ?mixed) => void, + ): void; + showDefinitionForSelection(): void; + isOffscreen(): boolean; + startPainting(): void; + stopPainting(): void; + isPainting(): boolean; + setFrameRate(fps: number): void; + getFrameRate(): ?number; + + id: number; + session: electron$session; + hostWebContents: ?electron$WebContents; + devToolsWebContents: ?electron$WebContents; + debugger: ?electron$Debugger; +} + +declare class electron$Debugger extends events$EventEmitter { + attach(protocolVersion?: string): void; + isAttached(): boolean; + detach(): void; + sendCommand(method: string, callback?: (error: ?mixed, result: ?mixed) => void): void; + sendCommand( + method: string, + commandParams?: Object, + callback?: (error: ?mixed, result: ?mixed) => void, + ): void; +} + +type electron$webContents = { + getAllWebContents(): Array, + getFocusedWebContents: ?electron$WebContents, + fromId(id: number): ?electron$WebContents, +}; + +//------------------------------------------------------------------------------ +// Modules for the Renderer Process (Web Page) +//------------------------------------------------------------------------------ + +/** + * https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md + */ + +type electron$desktopCapturer = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/ipc-renderer.md + */ + +declare class electron$IpcRenderer { + on(channel: string, callback: (...args: Array) => void): electron$IpcRenderer; + once(channel: string, callback: (...args: Array) => void): electron$IpcRenderer; + removeListener(channel: string, callback: (...args: Array) => void): electron$IpcRenderer; + removeAllListeners(channel?: string): electron$IpcRenderer; + send(channel: string, ...args: Array): void; + sendSync(channel: string, ...args: Array): void; + sendToHost(channel: string, ...args: Array): void; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/remote.md + */ + +type electron$remote = { + // main process built-in modules: + app: electron$app, + autoUpdater: electron$autoUpdater, + BrowserWindow: typeof electron$BrowserWindow, + contentTracing: electron$contentTracing, + dialog: electron$dialog, + globalShortcut: electron$globalShortcut, + ipcMain: electron$IpcMain, + Menu: typeof electron$Menu, + MenuItem: typeof electron$MenuItem, + powerMonitor: electron$powerMonitor, + powerSaveBlocker: electron$powerSaveBlocker, + protocol: electron$protocol, + session: electron$session, + electron$Tray: typeof electron$Tray, + webContents: electron$webContents, + // methods: + require(module: string): any, + getCurrentWindow(): electron$BrowserWindow, + getCurrentWebContents(): electron$WebContents, + getGlobal(name: string): ?mixed, + process: typeof process, +}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/web-frame.md + */ + +type electron$webFrame = { + registerURLSchemeAsBypassingCSP(scheme: string): void, +}; + +//------------------------------------------------------------------------------ +// Modules for Both Processes +//------------------------------------------------------------------------------ + +/** + * https://github.com/electron/electron/blob/master/docs/api/clipboard.md + */ + +type electron$clipboard = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/crash-reporter.md + */ + +type electron$crashReporter = {}; + +/** + * https://github.com/electron/electron/blob/master/docs/api/native-image.md + */ + +type electron$nativeImage = { + createEmpty(): electron$NativeImage, + createFromPath(path: string): electron$NativeImage, + createFromBuffer(buffer: Buffer, scaleFactor?: number): electron$NativeImage, + createFromDataURL(dataURL: string): electron$NativeImage, +}; + +declare class electron$NativeImage { + toPNG(): Uint8Array; + toJPEG(quality: number): Uint8Array; + toBitmap(): Uint8Array; + toDataURL(): string; + getNativeHandle(): Uint8Array; + isEmpty(): boolean; + getSize(): { width: number, height: number }; + setTemplateImage(option: boolean): void; + isTemplateImage(): boolean; + // Deprecated, but Atom is behind - so keep them around. + toPng(): Uint8Array; + toJpeg(quality: number): Uint8Array; + toDataUrl(): string; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/screen.md + */ + +type electron$Display = { + id: number, + rotation: 0 | 90 | 180 | 270, + scaleFactor: number, + touchSupport: 'available' | 'unavailable' | 'unknown', + bounds: electron$rect, + size: { height: number, width: number }, + workArea: electron$rect, + workAreaSize: { height: number, width: number }, +}; + +type electron$DisplayEvents = 'display-added' | 'display-removed' | 'display-metrics-changed'; + +type electron$ScreenListener = ( + event: electron$DisplayEvents, + callback: ( + event: Object, + display: electron$Display, + changedMetrics?: Array<'bounds' | 'workArea' | 'scaleFactor' | 'rotation'>, + ) => void, +) => electron$Screen; + +declare class electron$Screen { + on: electron$ScreenListener; + once: electron$ScreenListener; + removeAllListeners(event?: electron$DisplayEvents): electron$Screen; + removeListener(event?: electron$DisplayEvents, callback: Function): electron$Screen; + getCursorScreenPoint(): { x: number, y: number }; + getPrimaryDisplay(): electron$Display; + getAllDisplays(): Array; + getDisplayNearestPoint(point: { x: number, y: number }): electron$Display; + getDisplayMatching(rect: electron$rect): electron$Display; +} + +/** + * https://github.com/electron/electron/blob/master/docs/api/shell.md + */ + +type electron$shell = { + showItemInFolder(fullPath: string): void, + openItem(fullPath: string): void, + openExternal(url: string, options?: { activate: boolean }): void, + moveItemToTrash(fullPath: string): boolean, + beep(): void, + // Windows-only + writeShortcutLink( + shortcutPath: string, + operation?: 'create' | 'update' | 'replace', + options?: { + target: string, + cwd?: string, + args?: string, + description?: string, + icon?: string, + iconIndex?: number, + appUserModelId?: string, + }, + ): void, + // Windows-only + readShortcutLink(shortcutPath: string): void, +}; diff --git a/flow-custom-typedefs/eres.js b/flow-custom-typedefs/eres.js new file mode 100644 index 0000000..0ac2361 --- /dev/null +++ b/flow-custom-typedefs/eres.js @@ -0,0 +1,3 @@ +declare module 'eres' { + declare module.exports: (Promise) => Promise<[?Error, T]>; +} diff --git a/flow-custom-typedefs/lodash.flow.js b/flow-custom-typedefs/lodash.flow.js new file mode 100644 index 0000000..9a8bda4 --- /dev/null +++ b/flow-custom-typedefs/lodash.flow.js @@ -0,0 +1,3 @@ +declare module 'lodash.flow' { + declare module.exports: $ComposeReverse & ((funcs?: Array) => Function); +} diff --git a/flow-custom-typedefs/lodash.groupby.js b/flow-custom-typedefs/lodash.groupby.js new file mode 100644 index 0000000..e39fbe9 --- /dev/null +++ b/flow-custom-typedefs/lodash.groupby.js @@ -0,0 +1,15 @@ +declare module 'lodash.groupby' { + declare type _ValueOnlyIteratee = (value: T) => mixed; + declare type ValueOnlyIteratee = _ValueOnlyIteratee | string; + + declare type GroupBy = ( + array: $ReadOnlyArray, + iteratee?: ?ValueOnlyIteratee, + ) => { [key: V]: Array } & ((array: void | null, iteratee?: ?ValueOnlyIteratee) => {}) & + (( + object: T, + iteratee?: ValueOnlyIteratee, + ) => { [key: V]: Array }); + + declare export default GroupBy; +} diff --git a/flow-custom-typedefs/styled-components.js b/flow-custom-typedefs/styled-components.js new file mode 100644 index 0000000..9336b7e --- /dev/null +++ b/flow-custom-typedefs/styled-components.js @@ -0,0 +1,419 @@ +// @flow + +declare module 'styled-components' { + declare export type Interpolation = + | ((executionContext: P) => string) + | CSSRules + | KeyFrames + | string + | number; + + declare export type CSSRules = Interpolation[]; + + // This is not exported on purpose, since it's an implementation detail + declare type TaggedTemplateLiteral = ( + strings: string[], + ...interpolations: Interpolation[] + ) => R; + + declare export type CSSConstructor = TaggedTemplateLiteral; + declare export type KeyFramesConstructor = TaggedTemplateLiteral; + declare export type CreateGlobalStyleConstructor = TaggedTemplateLiteral>; + + declare interface Tag { + styleTag: HTMLStyleElement | null; + getIds(): string[]; + hasNameForId(id: string, name: string): boolean; + insertMarker(id: string): T; + insertRules(id: string, cssRules: string[], name: ?string): void; + removeRules(id: string): void; + css(): string; + toHTML(additionalAttrs: ?string): string; + toElement(): React$Element<*>; + clone(): Tag; + sealed: boolean; + } + + // The `any`/weak types in here all come from `styled-components` directly, since those definitions were just copied over + declare export class StyleSheet { + static get master(): StyleSheet; + static get instance(): StyleSheet; + static reset(forceServer?: boolean): void; + + id: number; + forceServer: boolean; + target: ?HTMLElement; + tagMap: { [string]: Tag }; // eslint-disable-line flowtype/no-weak-types + deferred: { [string]: string[] | void }; + rehydratedNames: { [string]: boolean }; + ignoreRehydratedNames: { [string]: boolean }; + tags: Tag[]; // eslint-disable-line flowtype/no-weak-types + importRuleTag: Tag; // eslint-disable-line flowtype/no-weak-types + capacity: number; + clones: StyleSheet[]; + + constructor(?HTMLElement): this; + rehydrate(): this; + clone(): StyleSheet; + sealAllTags(): void; + makeTag(tag: ?Tag): Tag; // eslint-disable-line flowtype/no-weak-types + getImportRuleTag(): Tag; // eslint-disable-line flowtype/no-weak-types + getTagForId(id: string): Tag; // eslint-disable-line flowtype/no-weak-types + hasId(id: string): boolean; + hasNameForId(id: string, name: string): boolean; + deferredInject(id: string, cssRules: string[]): void; + inject(id: string, cssRules: string[], name?: string): void; + remove(id: string): void; + toHtml(): string; + toReactElements(): React$ElementType[]; + } + + declare export class KeyFrames { + id: string; + name: string; + rules: string[]; + + constructor(name: string, rules: string[]): this; + inject(StyleSheet): void; + toString(): string; + getName(): string; + } + + // I think any is appropriate here? + // eslint-disable-next-line flowtype/no-weak-types + declare export type Theme = { +[string]: any }; + + declare export var css: CSSConstructor; + declare export var keyframes: KeyFramesConstructor; + declare export var createGlobalStyle: CreateGlobalStyleConstructor; + declare export var ThemeProvider: React$ComponentType<{ + children?: ?React$Node, + theme: Theme | (Theme => Theme), + }>; + + // This is a bit hard to read. Not sure how to make it more readable. I think adding line-breaks makes it worse. + declare type InjectedProps = { theme: Theme | void }; + declare export function withTheme>( + WrappedComponent: Component, + ): React$ComponentType<$Diff>, InjectedProps>>; + + // @HACK This is a cheat to hide that the underlying type is "just a string" + // once we know of a better way, we should be able to update this accordingly. + // I don't think there _is_ a good way, currently. + // @NOTE Also not too sure about the naming of this... + declare export type StyledElementType = T; + declare export type StyledComponentType = { + [[call]]: TaggedTemplateLiteral, + +attrs: ( + attributes: A | ((props: React$ElementConfig) => A), + ) => TaggedTemplateLiteral, A>>>, + }; + + declare type StyledComponentList = { + a: StyledComponentType>, + abbr: StyledComponentType>, + address: StyledComponentType>, + area: StyledComponentType>, + article: StyledComponentType>, + aside: StyledComponentType>, + audio: StyledComponentType>, + b: StyledComponentType>, + base: StyledComponentType>, + bdi: StyledComponentType>, + bdo: StyledComponentType>, + big: StyledComponentType>, + blockquote: StyledComponentType>, + body: StyledComponentType>, + br: StyledComponentType>, + button: StyledComponentType>, + canvas: StyledComponentType>, + caption: StyledComponentType>, + cite: StyledComponentType>, + code: StyledComponentType>, + col: StyledComponentType>, + colgroup: StyledComponentType>, + data: StyledComponentType>, + datalist: StyledComponentType>, + dd: StyledComponentType>, + del: StyledComponentType>, + details: StyledComponentType>, + dfn: StyledComponentType>, + dialog: StyledComponentType>, + div: StyledComponentType>, + dl: StyledComponentType>, + dt: StyledComponentType>, + em: StyledComponentType>, + embed: StyledComponentType>, + fieldset: StyledComponentType>, + figcaption: StyledComponentType>, + figure: StyledComponentType>, + footer: StyledComponentType>, + form: StyledComponentType>, + h1: StyledComponentType>, + h2: StyledComponentType>, + h3: StyledComponentType>, + h4: StyledComponentType>, + h5: StyledComponentType>, + h6: StyledComponentType>, + head: StyledComponentType>, + header: StyledComponentType>, + hgroup: StyledComponentType>, + hr: StyledComponentType>, + html: StyledComponentType>, + i: StyledComponentType>, + iframe: StyledComponentType>, + img: StyledComponentType>, + input: StyledComponentType>, + ins: StyledComponentType>, + kbd: StyledComponentType>, + keygen: StyledComponentType>, + label: StyledComponentType>, + legend: StyledComponentType>, + li: StyledComponentType>, + link: StyledComponentType>, + main: StyledComponentType>, + map: StyledComponentType>, + mark: StyledComponentType>, + menu: StyledComponentType>, + menuitem: StyledComponentType>, + meta: StyledComponentType>, + meter: StyledComponentType>, + nav: StyledComponentType>, + noscript: StyledComponentType>, + object: StyledComponentType>, + ol: StyledComponentType>, + optgroup: StyledComponentType>, + option: StyledComponentType>, + output: StyledComponentType>, + p: StyledComponentType>, + param: StyledComponentType>, + picture: StyledComponentType>, + pre: StyledComponentType>, + progress: StyledComponentType>, + q: StyledComponentType>, + rp: StyledComponentType>, + rt: StyledComponentType>, + ruby: StyledComponentType>, + s: StyledComponentType>, + samp: StyledComponentType>, + script: StyledComponentType>, + section: StyledComponentType>, + select: StyledComponentType>, + small: StyledComponentType>, + source: StyledComponentType>, + span: StyledComponentType>, + strong: StyledComponentType>, + style: StyledComponentType>, + sub: StyledComponentType>, + summary: StyledComponentType>, + sup: StyledComponentType>, + table: StyledComponentType>, + tbody: StyledComponentType>, + td: StyledComponentType>, + textarea: StyledComponentType>, + tfoot: StyledComponentType>, + th: StyledComponentType>, + thead: StyledComponentType>, + time: StyledComponentType>, + title: StyledComponentType>, + tr: StyledComponentType>, + track: StyledComponentType>, + u: StyledComponentType>, + ul: StyledComponentType>, + var: StyledComponentType>, + video: StyledComponentType>, + wbr: StyledComponentType>, + + // SVG + circle: StyledComponentType>, + clipPath: StyledComponentType>, + defs: StyledComponentType>, + ellipse: StyledComponentType>, + g: StyledComponentType>, + image: StyledComponentType>, + line: StyledComponentType>, + linearGradient: StyledComponentType>, + mask: StyledComponentType>, + path: StyledComponentType>, + pattern: StyledComponentType>, + polygon: StyledComponentType>, + polyline: StyledComponentType>, + radialGradient: StyledComponentType>, + rect: StyledComponentType>, + stop: StyledComponentType>, + svg: StyledComponentType>, + text: StyledComponentType>, + tspan: StyledComponentType>, + }; + + declare export default StyledComponentList & { + [[call]]: (S) => $ElementType, + [[call]]: >(C) => StyledComponentType, + }; +} + +declare module 'styled-components/native' { + declare export type Interpolation = + | ((executionContext: P) => string) + | CSSRules + | KeyFrames + | string + | number; + + declare export type CSSRules = Interpolation[]; + + // This is not exported on purpose, since it's an implementation detail + declare type TaggedTemplateLiteral = ( + strings: string[], + ...interpolations: Interpolation[] + ) => R; + + declare export type CSSConstructor = TaggedTemplateLiteral; + declare export type KeyFramesConstructor = TaggedTemplateLiteral; + declare export type CreateGlobalStyleConstructor = TaggedTemplateLiteral>; + + declare interface Tag { + styleTag: HTMLStyleElement | null; + getIds(): string[]; + hasNameForId(id: string, name: string): boolean; + insertMarker(id: string): T; + insertRules(id: string, cssRules: string[], name: ?string): void; + removeRules(id: string): void; + css(): string; + toHTML(additionalAttrs: ?string): string; + toElement(): React$Element<*>; + clone(): Tag; + sealed: boolean; + } + + // The `any`/weak types in here all come from `styled-components` directly, since those definitions were just copied over + declare export class StyleSheet { + static get master(): StyleSheet; + static get instance(): StyleSheet; + static reset(forceServer?: boolean): void; + + id: number; + forceServer: boolean; + target: ?HTMLElement; + tagMap: { [string]: Tag }; // eslint-disable-line flowtype/no-weak-types + deferred: { [string]: string[] | void }; + rehydratedNames: { [string]: boolean }; + ignoreRehydratedNames: { [string]: boolean }; + tags: Tag[]; // eslint-disable-line flowtype/no-weak-types + importRuleTag: Tag; // eslint-disable-line flowtype/no-weak-types + capacity: number; + clones: StyleSheet[]; + + constructor(?HTMLElement): this; + rehydrate(): this; + clone(): StyleSheet; + sealAllTags(): void; + makeTag(tag: ?Tag): Tag; // eslint-disable-line flowtype/no-weak-types + getImportRuleTag(): Tag; // eslint-disable-line flowtype/no-weak-types + getTagForId(id: string): Tag; // eslint-disable-line flowtype/no-weak-types + hasId(id: string): boolean; + hasNameForId(id: string, name: string): boolean; + deferredInject(id: string, cssRules: string[]): void; + inject(id: string, cssRules: string[], name?: string): void; + remove(id: string): void; + toHtml(): string; + toReactElements(): React$ElementType[]; + } + + declare export class KeyFrames { + id: string; + name: string; + rules: string[]; + + constructor(name: string, rules: string[]): this; + inject(StyleSheet): void; + toString(): string; + getName(): string; + } + + // I think any is appropriate here? + // eslint-disable-next-line flowtype/no-weak-types + declare export type Theme = { +[string]: any }; + + declare export var css: CSSConstructor; + declare export var keyframes: KeyFramesConstructor; + declare export var createGlobalStyle: CreateGlobalStyleConstructor; + declare export var ThemeProvider: React$ComponentType<{ + children?: ?React$Node, + theme: Theme | (Theme => Theme), + }>; + + // This is a bit hard to read. Not sure how to make it more readable. I think adding line-breaks makes it worse. + declare type InjectedProps = { theme: Theme | void }; + declare export function withTheme>( + WrappedComponent: Component, + ): React$ComponentType<$Diff>, InjectedProps>>; + + // @HACK This is a cheat to hide that the underlying type is "just a string" + // once we know of a better way, we should be able to update this accordingly. + // I don't think there _is_ a good way, currently. + // @NOTE Also not too sure about the naming of this... + declare export type StyledElementType = T; + declare export type StyledComponentType = { + [[call]]: TaggedTemplateLiteral, + +attrs: ( + attributes: A, + ) => TaggedTemplateLiteral, A>>>, + }; + + declare type StyledComponentList = { + ActivityIndicator: StyledComponentType>, + ActivityIndicatorIOS: StyledComponentType>, + ART: StyledComponentType>, + Button: StyledComponentType>, + DatePickerIOS: StyledComponentType>, + DrawerLayoutAndroid: StyledComponentType>, + Image: StyledComponentType>, + ImageBackground: StyledComponentType>, + ImageEditor: StyledComponentType>, + ImageStore: StyledComponentType>, + KeyboardAvoidingView: StyledComponentType>, + ListView: StyledComponentType>, + MapView: StyledComponentType>, + Modal: StyledComponentType>, + NavigatorIOS: StyledComponentType>, + Picker: StyledComponentType>, + PickerIOS: StyledComponentType>, + ProgressBarAndroid: StyledComponentType>, + ProgressViewIOS: StyledComponentType>, + ScrollView: StyledComponentType>, + SegmentedControlIOS: StyledComponentType>, + Slider: StyledComponentType>, + SliderIOS: StyledComponentType>, + SnapshotViewIOS: StyledComponentType>, + Switch: StyledComponentType>, + RecyclerViewBackedScrollView: StyledComponentType>, + RefreshControl: StyledComponentType>, + SafeAreaView: StyledComponentType>, + StatusBar: StyledComponentType>, + SwipeableListView: StyledComponentType>, + SwitchAndroid: StyledComponentType>, + SwitchIOS: StyledComponentType>, + TabBarIOS: StyledComponentType>, + Text: StyledComponentType>, + TextInput: StyledComponentType>, + ToastAndroid: StyledComponentType>, + ToolbarAndroid: StyledComponentType>, + Touchable: StyledComponentType>, + TouchableHighlight: StyledComponentType>, + TouchableNativeFeedback: StyledComponentType>, + TouchableOpacity: StyledComponentType>, + TouchableWithoutFeedback: StyledComponentType>, + View: StyledComponentType>, + ViewPagerAndroid: StyledComponentType>, + WebView: StyledComponentType>, + FlatList: StyledComponentType>, + SectionList: StyledComponentType>, + VirtualizedList: StyledComponentType>, + }; + + declare export default StyledComponentList & { + [[call]]: (S) => $ElementType, + [[call]]: >(C) => StyledComponentType, + }; +} diff --git a/package.json b/package.json index c6f5025..c4d6451 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build": "rm -rf build && webpack --config config/webpack-prod.config.js --mode production --env.NODE_ENV=production", "lint:precommit": "eslint ./app/", "flow:precommit": "glow", - "flow:coverage": "flow-coverage-report -t html -i 'app/**/*.js' -x 'dist/*.js' --threshold 70", + "flow:coverage": "flow-coverage-report --config ./coverage.json", "flow:report": "yarn flow:coverage && cd ./flow-coverage && open index.html", "electron:dev": "electron -r @babel/register .", "electron:prepare": "yarn icon:build && rm -rf dist && mkdir dist", @@ -66,7 +66,7 @@ "eslint-plugin-react": "^7.12.4", "file-loader": "^2.0.0", "flow-bin": "^0.91.0", - "flow-coverage-report": "^0.6.0", + "flow-coverage-report": "^0.6.1", "flow-typed": "^2.5.1", "glow": "^1.2.2", "html-webpack-plugin": "^3.1.0", diff --git a/services/utils.js b/services/utils.js index cb7f523..216f999 100644 --- a/services/utils.js +++ b/services/utils.js @@ -679,6 +679,7 @@ export type APIMethods = { amount: number, vout: number, fee: number, + category: string, confirmations: number, blockhash: string, blockindex: number, diff --git a/services/zec-price.js b/services/zec-price.js index a5b7a03..71788fa 100644 --- a/services/zec-price.js +++ b/services/zec-price.js @@ -1,5 +1,6 @@ // @flow -// eslint-disable-next-line import/no-extraneous-dependencies +/* eslint-disable import/no-extraneous-dependencies */ +// $FlowFixMe import { net } from 'electron'; type Payload = { diff --git a/utils/debug-shortcut.js b/utils/debug-shortcut.js index 3a75a68..e236a66 100644 --- a/utils/debug-shortcut.js +++ b/utils/debug-shortcut.js @@ -1,9 +1,11 @@ // @flow /* eslint-disable import/no-extraneous-dependencies */ -import { globalShortcut } from 'electron'; +import { globalShortcut, typeof BrowserWindow, typeof app as ElectronApp } from 'electron'; -export const registerDebugShortcut = (app: Object, mainWindow: Object) => globalShortcut.register('CommandOrControl+Option+B', () => { +export const registerDebugShortcut = (app: ElectronApp, mainWindow: BrowserWindow) => globalShortcut.register('CommandOrControl+Option+B', () => { + // $FlowFixMe app.dock.show(); + // $FlowFixMe mainWindow.webContents.openDevTools(); }); diff --git a/yarn.lock b/yarn.lock index 21c59c1..b796c62 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1412,6 +1412,15 @@ vue-template-compiler "^2.0.0-alpha.8" vue-template-es2015-compiler "^1.4.2" +"@rpl/badge-up@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@rpl/badge-up/-/badge-up-2.2.0.tgz#79a5ccf72bdb1777390bb7e4caa08dc42d57dd9a" + integrity sha512-ylcyuw/fttO3gJPF04B257HK5u14xhCnWhN6JuW1Z7236lNj8WU10xxWcPI471tNqqE9ksJ3ApoJigXW8WjDKQ== + dependencies: + css-color-names "~0.0.3" + dot "^1.1.1" + svgo "^1.1.1" + "@sheerun/mutationobserver-shim@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.2.tgz#8013f2af54a2b7d735f71560ff360d3a8176a87b" @@ -2123,14 +2132,6 @@ argparse@^1.0.7, argparse@^1.0.9: dependencies: sprintf-js "~1.0.2" -"argparse@~ 0.1.11": - version "0.1.16" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-0.1.16.tgz#cfd01e0fbba3d6caed049fbd758d40f65196f57c" - integrity sha1-z9AeD7uj1srtBJ+9dY1A9lGW9Xw= - dependencies: - underscore "~1.7.0" - underscore.string "~2.4.0" - args@^2.3.0: version "2.6.1" resolved "https://registry.yarnpkg.com/args/-/args-2.6.1.tgz#b2590ed4168cd31b62444199bdc5166bb1920c2f" @@ -3092,15 +3093,6 @@ babylon@^6.17.0, babylon@^6.18.0: resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== -badge-up@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/badge-up/-/badge-up-2.3.0.tgz#72fff694a32d44aa14031e72889e0fc55b53058b" - integrity sha1-cv/2lKMtRKoUAx5yiJ4PxVtTBYs= - dependencies: - css-color-names "~0.0.3" - dot "~1.0.2" - svgo "~0.4.5" - bail@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.3.tgz#63cfb9ddbac829b02a3128cd53224be78e6c21a3" @@ -4194,13 +4186,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@~0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/coa/-/coa-0.4.1.tgz#baf6f49c7ad9f20c597af39b3fc1e5090fe8838b" - integrity sha1-uvb0nHrZ8gxZevObP8HlCQ/og4s= - dependencies: - q "~0.9.6" - coa@~1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" @@ -4334,11 +4319,6 @@ colors@^1.0.3, colors@^1.1.2: resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" integrity sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ== -colors@~0.6.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" - integrity sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w= - colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" @@ -6029,10 +6009,10 @@ dot-prop@^4.1.0, dot-prop@^4.1.1, dot-prop@^4.2.0: dependencies: is-obj "^1.0.0" -dot@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/dot/-/dot-1.0.3.tgz#f8750bfb6b03c7664eb0e6cb1eb4c66419af9427" - integrity sha1-+HUL+2sDx2ZOsObLHrTGZBmvlCc= +dot@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/dot/-/dot-1.1.2.tgz#c7377019fc4e550798928b2b9afeb66abfa1f2f9" + integrity sha1-xzdwGfxOVQeYkosrmv62ar+h8vk= dotenv-expand@^4.2.0: version "4.2.0" @@ -6743,11 +6723,6 @@ esprima@^4.0.0, esprima@~4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -"esprima@~ 1.0.2": - version "1.0.4" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" - integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0= - esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" @@ -7324,14 +7299,14 @@ flow-bin@^0.91.0: resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.91.0.tgz#f5c89729f74b2ccbd47df6fbfadbdcc89cc1e478" integrity sha512-j+L+xNiUYnZZ27MjVI0y2c9474ZHOvdSQq0Tjwh56mEA7tfxYqp5Dcb6aZSwvs3tGMTjCrZow9aUlZf3OoRyDQ== -flow-coverage-report@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/flow-coverage-report/-/flow-coverage-report-0.6.0.tgz#3bab30921f14ef798d709902048205bd7611ec43" - integrity sha512-Tr94Db/8xXhaaEeO5knE5iGZ/UxzmuVPqb4F2pcOgKv3R6/9kLVprIcORZJnxKPiPvF6f56JAoNx0TdkDCJUxA== +flow-coverage-report@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/flow-coverage-report/-/flow-coverage-report-0.6.1.tgz#b7b3458093dba1aebf48288b251877bb6861fe5b" + integrity sha512-AUMuC4rocbGcyhKG8oINN4qKaJ2aYbhZQlyk5ro9/TcQ1+gdcy/O0OM9iilEmL2uJraHkFpwo9dCfiJbvRwQcA== dependencies: + "@rpl/badge-up" "2.2.0" array.prototype.find "2.0.4" babel-runtime "6.23.0" - badge-up "2.3.0" flow-annotation-check "1.8.1" glob "7.1.1" minimatch "3.0.4" @@ -9875,14 +9850,6 @@ js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.7.0, js-yaml@^3.9.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@~2.1.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-2.1.3.tgz#0ffb5617be55525878063d7a16aee7fdd282e84c" - integrity sha1-D/tWF75VUlh4Bj16Fq7n/dKC6Ew= - dependencies: - argparse "~ 0.1.11" - esprima "~ 1.0.2" - js-yaml@~3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" @@ -13363,11 +13330,6 @@ q@^1.1.2, q@~1.5.0: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -q@~0.9.6: - version "0.9.7" - resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" - integrity sha1-TeLmyzspCIyeTLwDv51C+5bOL3U= - qr.js@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/qr.js/-/qr.js-0.0.0.tgz#cace86386f59a0db8050fa90d9b6b0e88a1e364f" @@ -14829,11 +14791,6 @@ sax@>=0.6.0, sax@^1.1.4, sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== -sax@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" - integrity sha1-VjsZx8HeiS4Jv8Ty/DDjwn8JUrk= - scan-directory@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scan-directory/-/scan-directory-1.0.0.tgz#46b6769dbd893d9bd7490ae9dcc43811a38b7fbb" @@ -15860,17 +15817,6 @@ svgo@^1.0.0, svgo@^1.1.1: unquote "~1.1.1" util.promisify "~1.0.0" -svgo@~0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.4.5.tgz#ba56155fb1733728956c01b405221ee7e789a2a4" - integrity sha1-ulYVX7FzNyiVbAG0BSIe5+eJoqQ= - dependencies: - coa "~0.4.0" - colors "~0.6.0" - js-yaml "~2.1.0" - sax "~0.6.0" - whet.extend "~0.9.9" - swap-case@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-1.1.2.tgz#c39203a4587385fad3c850a0bd1bcafa081974e3" @@ -16466,16 +16412,6 @@ ulid@^2.3.0: resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f" integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw== -underscore.string@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.4.0.tgz#8cdd8fbac4e2d2ea1e7e2e8097c42f442280f85b" - integrity sha1-jN2PusTi0uoefi6Al8QvRCKA+Fs= - -underscore@~1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209" - integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk= - unescape-js@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/unescape-js/-/unescape-js-1.1.1.tgz#a4345e654b857c29fa66469e311ccaf2e93063bd"