diff --git a/.vscode/settings.json b/.vscode/settings.json index f5852ab5..041e71a9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,7 @@ { "javascript.validate.enable": false, + "javascript.format.enable": false, "typescript.validate.enable": false, + "typescript.format.enable": false, "editor.formatOnSave": true, - "typescript.format.enable": false } \ No newline at end of file diff --git a/app/components/Avatar/Avatar.js b/app/components/Avatar/Avatar.js index 46b0e594..38cfe682 100644 --- a/app/components/Avatar/Avatar.js +++ b/app/components/Avatar/Avatar.js @@ -3,13 +3,17 @@ import { observable } from "mobx"; import { observer } from "mobx-react"; import * as React from "react"; import styled from "styled-components"; +import User from "models/User"; import placeholder from "./placeholder.png"; -type Props = { +type Props = {| src: string, size: number, icon?: React.Node, -}; + user?: User, + onClick?: () => void, + className?: string, +|}; @observer class Avatar extends React.Component { diff --git a/app/components/Button.js b/app/components/Button.js index 7f434f37..aa15e984 100644 --- a/app/components/Button.js +++ b/app/components/Button.js @@ -108,8 +108,8 @@ export const Inner = styled.span` ${(props) => props.hasIcon && !props.hasText && "padding: 0 4px;"}; `; -export type Props = { - type?: string, +export type Props = {| + type?: "button" | "submit", value?: string, icon?: React.Node, iconColor?: string, @@ -118,9 +118,21 @@ export type Props = { innerRef?: React.ElementRef, disclosure?: boolean, neutral?: boolean, + danger?: boolean, + primary?: boolean, + disabled?: boolean, fullwidth?: boolean, + autoFocus?: boolean, + style?: Object, + as?: React.ComponentType, + to?: string, + onClick?: (event: SyntheticEvent<>) => mixed, borderOnHover?: boolean, -}; + + "data-on"?: string, + "data-event-category"?: string, + "data-event-action"?: string, +|}; function Button({ type = "text", diff --git a/app/components/Checkbox.js b/app/components/Checkbox.js index 1c19a48e..73068677 100644 --- a/app/components/Checkbox.js +++ b/app/components/Checkbox.js @@ -4,15 +4,18 @@ import { VisuallyHidden } from "reakit/VisuallyHidden"; import styled from "styled-components"; import HelpText from "components/HelpText"; -export type Props = { +export type Props = {| checked?: boolean, label?: string, labelHidden?: boolean, className?: string, + name?: string, + disabled?: boolean, + onChange: (event: SyntheticInputEvent) => mixed, note?: string, short?: boolean, small?: boolean, -}; +|}; const LabelText = styled.span` font-weight: 500; diff --git a/app/components/ContextMenu/MenuItem.js b/app/components/ContextMenu/MenuItem.js index 089144ce..c46e25f2 100644 --- a/app/components/ContextMenu/MenuItem.js +++ b/app/components/ContextMenu/MenuItem.js @@ -4,13 +4,16 @@ import * as React from "react"; import { MenuItem as BaseMenuItem } from "reakit/Menu"; import styled from "styled-components"; -type Props = { +type Props = {| onClick?: (SyntheticEvent<>) => void | Promise, children?: React.Node, selected?: boolean, disabled?: boolean, + to?: string, + href?: string, + target?: "_blank", as?: string | React.ComponentType<*>, -}; +|}; const MenuItem = ({ onClick, diff --git a/app/components/DocumentList.js b/app/components/DocumentList.js index d8c8d20b..00ec5945 100644 --- a/app/components/DocumentList.js +++ b/app/components/DocumentList.js @@ -4,10 +4,15 @@ import * as React from "react"; import Document from "models/Document"; import DocumentListItem from "components/DocumentListItem"; -type Props = { +type Props = {| documents: Document[], limit?: number, -}; + showCollection?: boolean, + showPublished?: boolean, + showPin?: boolean, + showDraft?: boolean, + showTemplate?: boolean, +|}; export default function DocumentList({ limit, documents, ...rest }: Props) { const items = limit ? documents.splice(0, limit) : documents; diff --git a/app/components/DocumentMeta.js b/app/components/DocumentMeta.js index 10a94154..07976305 100644 --- a/app/components/DocumentMeta.js +++ b/app/components/DocumentMeta.js @@ -23,14 +23,14 @@ const Modified = styled.span` font-weight: ${(props) => (props.highlight ? "600" : "400")}; `; -type Props = { +type Props = {| showCollection?: boolean, showPublished?: boolean, showLastViewed?: boolean, document: Document, children: React.Node, to?: string, -}; +|}; function DocumentMeta({ showPublished, diff --git a/app/components/Editor.js b/app/components/Editor.js index 82e2dc82..103d8777 100644 --- a/app/components/Editor.js +++ b/app/components/Editor.js @@ -16,14 +16,31 @@ const RichMarkdownEditor = React.lazy(() => import("rich-markdown-editor")); const EMPTY_ARRAY = []; -type Props = { +export type Props = {| id?: string, + value?: string, defaultValue?: string, readOnly?: boolean, grow?: boolean, disableEmbeds?: boolean, ui?: UiStore, -}; + autoFocus?: boolean, + template?: boolean, + placeholder?: string, + scrollTo?: string, + readOnlyWriteCheckboxes?: boolean, + onBlur?: (event: SyntheticEvent<>) => any, + onFocus?: (event: SyntheticEvent<>) => any, + onPublish?: (event: SyntheticEvent<>) => any, + onSave?: ({ done?: boolean, autosave?: boolean, publish?: boolean }) => any, + onCancel?: () => any, + onChange?: (getValue: () => string) => any, + onSearchLink?: (title: string) => any, + onHoverLink?: (event: MouseEvent) => any, + onCreateLink?: (title: string) => Promise, + onImageUploadStart?: () => any, + onImageUploadStop?: () => any, +|}; type PropsWithRef = Props & { forwardedRef: React.Ref, diff --git a/app/components/Image.js b/app/components/Image.js index 13eb4f58..a8bf88a8 100644 --- a/app/components/Image.js +++ b/app/components/Image.js @@ -2,10 +2,13 @@ import * as React from "react"; import { cdnPath } from "utils/urls"; -type Props = { +type Props = {| alt: string, src: string, -}; + title?: string, + width?: number, + height?: number, +|}; export default function Image({ src, alt, ...rest }: Props) { return {alt}; diff --git a/app/components/Input.js b/app/components/Input.js index e12344f2..855f59b4 100644 --- a/app/components/Input.js +++ b/app/components/Input.js @@ -75,8 +75,8 @@ export const LabelText = styled.div` display: inline-block; `; -export type Props = { - type?: string, +export type Props = {| + type?: "text" | "email" | "checkbox" | "search", value?: string, label?: string, className?: string, @@ -85,9 +85,18 @@ export type Props = { short?: boolean, margin?: string | number, icon?: React.Node, + name?: string, + minLength?: number, + maxLength?: number, + autoFocus?: boolean, + autoComplete?: boolean | string, + readOnly?: boolean, + required?: boolean, + placeholder?: string, + onChange?: (ev: SyntheticInputEvent) => mixed, onFocus?: (ev: SyntheticEvent<>) => void, onBlur?: (ev: SyntheticEvent<>) => void, -}; +|}; @observer class Input extends React.Component { diff --git a/app/components/InputRich.js b/app/components/InputRich.js index d9dd68d7..5238537b 100644 --- a/app/components/InputRich.js +++ b/app/components/InputRich.js @@ -8,13 +8,13 @@ import Editor from "components/Editor"; import HelpText from "components/HelpText"; import { LabelText, Outline } from "components/Input"; -type Props = { +type Props = {| label: string, minHeight?: number, maxHeight?: number, readOnly?: boolean, ui: UiStore, -}; +|}; @observer class InputRich extends React.Component { diff --git a/app/components/InputSelect.js b/app/components/InputSelect.js index 8392c06a..2187b968 100644 --- a/app/components/InputSelect.js +++ b/app/components/InputSelect.js @@ -36,6 +36,8 @@ export type Props = { className?: string, labelHidden?: boolean, options: Option[], + onBlur?: () => void, + onFocus?: () => void, }; @observer diff --git a/app/components/Labeled.js b/app/components/Labeled.js index 07905f96..41b57dec 100644 --- a/app/components/Labeled.js +++ b/app/components/Labeled.js @@ -4,10 +4,10 @@ import * as React from "react"; import styled from "styled-components"; import Flex from "components/Flex"; -type Props = { +type Props = {| label: React.Node | string, children: React.Node, -}; +|}; const Labeled = ({ label, children, ...props }: Props) => ( diff --git a/app/components/Mask.js b/app/components/Mask.js index d581ea3b..eeeabe86 100644 --- a/app/components/Mask.js +++ b/app/components/Mask.js @@ -5,10 +5,10 @@ import { randomInteger } from "shared/random"; import { pulsate } from "shared/styles/animations"; import Flex from "components/Flex"; -type Props = { +type Props = {| header?: boolean, height?: number, -}; +|}; class Mask extends React.Component { width: number; @@ -23,7 +23,7 @@ class Mask extends React.Component { } render() { - return ; + return ; } } diff --git a/app/components/Modal.js b/app/components/Modal.js index 8dbf6197..11032040 100644 --- a/app/components/Modal.js +++ b/app/components/Modal.js @@ -13,12 +13,12 @@ import Scrollable from "components/Scrollable"; ReactModal.setAppElement("#root"); -type Props = { +type Props = {| children?: React.Node, isOpen: boolean, title?: string, onRequestClose: () => void, -}; +|}; const GlobalStyles = createGlobalStyle` .ReactModal__Overlay { diff --git a/app/components/PaginatedDocumentList.js b/app/components/PaginatedDocumentList.js index 45884e20..322ce6d4 100644 --- a/app/components/PaginatedDocumentList.js +++ b/app/components/PaginatedDocumentList.js @@ -5,13 +5,18 @@ import Document from "models/Document"; import DocumentListItem from "components/DocumentListItem"; import PaginatedList from "components/PaginatedList"; -type Props = { +type Props = {| documents: Document[], fetch: (options: ?Object) => Promise, options?: Object, heading?: React.Node, empty?: React.Node, -}; + showCollection?: boolean, + showPublished?: boolean, + showPin?: boolean, + showDraft?: boolean, + showTemplate?: boolean, +|}; @observer class PaginatedDocumentList extends React.Component { diff --git a/app/components/Sidebar/components/HeaderBlock.js b/app/components/Sidebar/components/HeaderBlock.js index cea45ac4..ee8e40e4 100644 --- a/app/components/Sidebar/components/HeaderBlock.js +++ b/app/components/Sidebar/components/HeaderBlock.js @@ -5,12 +5,13 @@ import styled from "styled-components"; import Flex from "components/Flex"; import TeamLogo from "components/TeamLogo"; -type Props = { +type Props = {| teamName: string, subheading: React.Node, showDisclosure?: boolean, + onClick: (event: SyntheticEvent<>) => void, logoUrl: string, -}; +|}; const HeaderBlock = React.forwardRef( ({ showDisclosure, teamName, subheading, logoUrl, ...rest }: Props, ref) => ( diff --git a/app/components/Switch.js b/app/components/Switch.js index 03d907ee..aaa08f18 100644 --- a/app/components/Switch.js +++ b/app/components/Switch.js @@ -3,12 +3,15 @@ import * as React from "react"; import styled from "styled-components"; import { LabelText } from "components/Input"; -type Props = { +type Props = {| width?: number, height?: number, label?: string, + checked?: boolean, + disabled?: boolean, + onChange: (event: SyntheticInputEvent) => mixed, id?: string, -}; +|}; function Switch({ width = 38, height = 20, label, ...props }: Props) { const component = ( diff --git a/app/components/Tooltip.js b/app/components/Tooltip.js index ce86b0d0..d9395fde 100644 --- a/app/components/Tooltip.js +++ b/app/components/Tooltip.js @@ -3,14 +3,14 @@ import Tippy from "@tippy.js/react"; import * as React from "react"; import styled from "styled-components"; -type Props = { +type Props = {| tooltip: React.Node, shortcut?: React.Node, placement?: "top" | "bottom" | "left" | "right", children: React.Node, delay?: number, className?: string, -}; +|}; class Tooltip extends React.Component { render() { diff --git a/app/menus/NewDocumentMenu.js b/app/menus/NewDocumentMenu.js index 1de530f3..5bb65b0e 100644 --- a/app/menus/NewDocumentMenu.js +++ b/app/menus/NewDocumentMenu.js @@ -27,7 +27,6 @@ function NewDocumentMenu() { as={Link} to={newDocumentUrl(collections.orderedData[0].id)} icon={} - small > {t("New doc")} diff --git a/app/models/BaseModel.js b/app/models/BaseModel.js index 7ff62515..d8a00286 100644 --- a/app/models/BaseModel.js +++ b/app/models/BaseModel.js @@ -11,7 +11,7 @@ export default class BaseModel { this.store = store; } - save = async (params: ?Object) => { + save = async (params: Object = {}) => { this.isSaving = true; try { diff --git a/app/models/Document.js b/app/models/Document.js index d20ffc0c..bebb34c8 100644 --- a/app/models/Document.js +++ b/app/models/Document.js @@ -142,7 +142,7 @@ export default class Document extends BaseModel { }; @action - updateFromJson = (data) => { + updateFromJson = (data: Object) => { set(this, data); }; @@ -150,7 +150,7 @@ export default class Document extends BaseModel { return this.store.archive(this); }; - restore = (options) => { + restore = (options: { revisionId?: string, collectionId?: string }) => { return this.store.restore(this, options); }; @@ -233,7 +233,7 @@ export default class Document extends BaseModel { }; @action - save = async (options: SaveOptions) => { + save = async (options: SaveOptions = {}) => { if (this.isSaving) return this; const isCreating = !this.id; @@ -246,7 +246,9 @@ export default class Document extends BaseModel { collectionId: this.collectionId, title: this.title, text: this.text, - ...options, + publish: options.publish, + done: options.done, + autosave: options.autosave, }); } @@ -257,7 +259,9 @@ export default class Document extends BaseModel { text: this.text, templateId: this.templateId, lastRevision: options.lastRevision, - ...options, + publish: options.publish, + done: options.done, + autosave: options.autosave, }); } diff --git a/app/scenes/Document/components/Document.js b/app/scenes/Document/components/Document.js index 1f37713a..17b9df97 100644 --- a/app/scenes/Document/components/Document.js +++ b/app/scenes/Document/components/Document.js @@ -61,7 +61,7 @@ type Props = { document: Document, revision: Revision, readOnly: boolean, - onCreateLink: (title: string) => string, + onCreateLink: (title: string) => Promise, onSearchLink: (term: string) => any, theme: Theme, auth: AuthStore, diff --git a/app/scenes/Document/components/Editor.js b/app/scenes/Document/components/Editor.js index 35403ee9..fd47b415 100644 --- a/app/scenes/Document/components/Editor.js +++ b/app/scenes/Document/components/Editor.js @@ -9,24 +9,24 @@ import parseTitle from "shared/utils/parseTitle"; import Document from "models/Document"; import ClickablePadding from "components/ClickablePadding"; import DocumentMetaWithViews from "components/DocumentMetaWithViews"; -import Editor from "components/Editor"; +import Editor, { type Props as EditorProps } from "components/Editor"; import Flex from "components/Flex"; import HoverPreview from "components/HoverPreview"; import Star, { AnimatedStar } from "components/Star"; import { isModKey } from "utils/keyboard"; import { documentHistoryUrl } from "utils/routeHelpers"; -type Props = { +type Props = {| + ...EditorProps, onChangeTitle: (event: SyntheticInputEvent<>) => void, title: string, - defaultValue: string, document: Document, isDraft: boolean, isShare: boolean, - readOnly?: boolean, - onSave: ({ publish?: boolean, done?: boolean, autosave?: boolean }) => mixed, + grow?: boolean, + onSave: ({ done?: boolean, autosave?: boolean, publish?: boolean }) => any, innerRef: { current: any }, -}; +|}; @observer class DocumentEditor extends React.Component { @@ -98,6 +98,7 @@ class DocumentEditor extends React.Component { isShare, readOnly, innerRef, + ...rest } = this.props; const { emoji } = parseTitle(title); @@ -135,12 +136,12 @@ class DocumentEditor extends React.Component { /> {!readOnly && } {this.activeLinkEvent && !isShare && readOnly && ( diff --git a/app/scenes/Document/components/Header.js b/app/scenes/Document/components/Header.js index f3316111..8c39e7e1 100644 --- a/app/scenes/Document/components/Header.js +++ b/app/scenes/Document/components/Header.js @@ -240,7 +240,6 @@ class Header extends React.Component { diff --git a/app/scenes/UserDelete.js b/app/scenes/UserDelete.js index f04c3196..3aa54486 100644 --- a/app/scenes/UserDelete.js +++ b/app/scenes/UserDelete.js @@ -34,10 +34,10 @@ class UserDelete extends React.Component { }; render() { - const { auth, ...rest } = this.props; + const { onRequestClose } = this.props; return ( - +
diff --git a/app/scenes/UserProfile.js b/app/scenes/UserProfile.js index 05b2e7e7..43dc9783 100644 --- a/app/scenes/UserProfile.js +++ b/app/scenes/UserProfile.js @@ -19,11 +19,11 @@ import Subheading from "components/Subheading"; import useCurrentUser from "hooks/useCurrentUser"; import useStores from "hooks/useStores"; -type Props = { +type Props = {| user: User, history: RouterHistory, onRequestClose: () => void, -}; +|}; function UserProfile(props: Props) { const { t } = useTranslation(); diff --git a/app/stores/AuthStore.js b/app/stores/AuthStore.js index 0e3d24b9..95b0e299 100644 --- a/app/stores/AuthStore.js +++ b/app/stores/AuthStore.js @@ -4,6 +4,7 @@ import invariant from "invariant"; import { observable, action, computed, autorun, runInAction } from "mobx"; import { getCookie, setCookie, removeCookie } from "tiny-cookie"; import RootStore from "stores/RootStore"; +import Policy from "models/Policy"; import Team from "models/Team"; import User from "models/User"; import env from "env"; @@ -13,17 +14,17 @@ import { getCookieDomain } from "utils/domains"; const AUTH_STORE = "AUTH_STORE"; const NO_REDIRECT_PATHS = ["/", "/create", "/home"]; -type Service = { +type Service = {| id: string, name: string, authUrl: string, -}; +|}; -type Config = { +type Config = {| name?: string, hostname?: string, services: Service[], -}; +|}; export default class AuthStore { @observable user: ?User; @@ -88,7 +89,7 @@ export default class AuthStore { } } - addPolicies = (policies) => { + addPolicies = (policies: Policy[]) => { if (policies) { policies.forEach((policy) => this.rootStore.policies.add(policy)); } diff --git a/app/stores/DocumentsStore.js b/app/stores/DocumentsStore.js index 1e1c26df..d0b25328 100644 --- a/app/stores/DocumentsStore.js +++ b/app/stores/DocumentsStore.js @@ -174,7 +174,13 @@ export default class DocumentsStore extends BaseStore { return this.drafts().length; } - drafts = (options = {}): Document[] => { + drafts = ( + options: { + ...PaginationParams, + dateFilter?: "day" | "week" | "month" | "year", + collectionId?: string, + } = {} + ): Document[] => { let drafts = filter( orderBy(this.all, "updatedAt", "desc"), (doc) => !doc.publishedAt @@ -185,7 +191,7 @@ export default class DocumentsStore extends BaseStore { drafts, (draft) => new Date(draft.updatedAt) >= - subtractDate(new Date(), options.dateFilter) + subtractDate(new Date(), options.dateFilter || "year") ); } @@ -245,7 +251,7 @@ export default class DocumentsStore extends BaseStore { @action fetchNamedPage = async ( request: string = "list", - options: ?PaginationParams + options: ?Object ): Promise => { this.isFetching = true; @@ -338,10 +344,9 @@ export default class DocumentsStore extends BaseStore { }; @action - searchTitles = async (query: string, options: PaginationParams = {}) => { + searchTitles = async (query: string) => { const res = await client.get("/documents.search_titles", { query, - ...options, }); invariant(res && res.data, "Search response should be available"); @@ -354,7 +359,15 @@ export default class DocumentsStore extends BaseStore { @action search = async ( query: string, - options: PaginationParams = {} + options: { + offset?: number, + limit?: number, + dateFilter?: "day" | "week" | "month" | "year", + includeArchived?: boolean, + includeDrafts?: boolean, + collectionId?: string, + userId?: string, + } ): Promise => { const compactedOptions = omitBy(options, (o) => !o); const res = await client.get("/documents.search", { @@ -601,10 +614,14 @@ export default class DocumentsStore extends BaseStore { }; @action - restore = async (document: Document, options = {}) => { + restore = async ( + document: Document, + options: { revisionId?: string, collectionId?: string } = {} + ) => { const res = await client.post("/documents.restore", { id: document.id, - ...options, + revisionId: options.revisionId, + collectionId: options.collectionId, }); runInAction("Document#restore", () => { invariant(res && res.data, "Data should be available"); diff --git a/app/stores/UiStore.js b/app/stores/UiStore.js index 859022af..f095feeb 100644 --- a/app/stores/UiStore.js +++ b/app/stores/UiStore.js @@ -182,13 +182,15 @@ class UiStore { @action showToast = ( message: string, - options?: { - type?: "warning" | "error" | "info" | "success", + options: { + type: "warning" | "error" | "info" | "success", timeout?: number, action?: { text: string, onClick: () => void, }, + } = { + type: "info", } ) => { if (!message) return; @@ -204,7 +206,14 @@ class UiStore { const id = v4(); const createdAt = new Date().toISOString(); - this.toasts.set(id, { message, createdAt, id, ...options }); + this.toasts.set(id, { + id, + message, + createdAt, + type: options.type, + timeout: options.timeout, + action: options.action, + }); this.lastToastId = id; return id; }; diff --git a/app/types/index.js b/app/types/index.js index 2c1c0849..db040656 100644 --- a/app/types/index.js +++ b/app/types/index.js @@ -11,7 +11,7 @@ export type LocationWithState = Location & { }, }; -export type Toast = { +export type Toast = {| id: string, createdAt: string, message: string, @@ -22,7 +22,7 @@ export type Toast = { text: string, onClick: () => void, }, -}; +|}; export type FetchOptions = { prefetch?: boolean, @@ -31,12 +31,12 @@ export type FetchOptions = { force?: boolean, }; -export type NavigationNode = { +export type NavigationNode = {| id: string, title: string, url: string, children: NavigationNode[], -}; +|}; // Pagination response in an API call export type Pagination = { @@ -46,12 +46,12 @@ export type Pagination = { }; // Pagination request params -export type PaginationParams = { +export type PaginationParams = {| limit?: number, offset?: number, sort?: string, direction?: "ASC" | "DESC", -}; +|}; export type SearchResult = { ranking: number, diff --git a/app/utils/download.js b/app/utils/download.js index 0f7e4365..89a4dcdc 100644 --- a/app/utils/download.js +++ b/app/utils/download.js @@ -110,6 +110,7 @@ export default function download( // $FlowIssue if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL) + // $FlowIssue return navigator.msSaveBlob(blob, fn); } diff --git a/package.json b/package.json index d24defd3..ad191b07 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "start": "node ./build/server/index.js", "dev": "nodemon --exec \"yarn build:server && yarn build:i18n && node build/server/index.js\" -e js --ignore build/ --ignore app/", "lint": "eslint app server shared", - "flow": "flow", "deploy": "git push heroku master", "heroku-postbuild": "yarn build && yarn sequelize:migrate", "sequelize:create-migration": "sequelize migration:create", @@ -192,7 +191,7 @@ "eslint-plugin-react": "^7.20.0", "eslint-plugin-react-hooks": "^4.1.0", "fetch-test-server": "^1.1.0", - "flow-bin": "^0.104.0", + "flow-bin": "^0.124.0", "html-webpack-plugin": "3.2.0", "i18next-parser": "^3.3.0", "jest-cli": "^26.0.0", diff --git a/yarn.lock b/yarn.lock index cde5ece1..cb3a526e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5181,10 +5181,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== -flow-bin@^0.104.0: - version "0.104.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.104.0.tgz#ef5b3600dfd36abe191a87d19f66e481bad2e235" - integrity sha512-EZXRRmf7m7ET5Lcnwm/I/T8G3d427Bq34vmO3qIlRcPIYloGuVoqRCwjaeezLRDntHkdciagAKbhJ+NTbDjnkw== +flow-bin@^0.124.0: + version "0.124.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.124.0.tgz#24b2e55874e1e2041f9247f42473b3db2ef32758" + integrity sha512-KEtDJ7CFUjcuhw6N52FTZshDd1krf1fxpp4APSIrwhVm+IrlcKJ+EMXpeXKM1kKNSZ347dYGh8wEvXQl4pHZEA== flow-typed@^2.6.2: version "2.6.2"