From 361f03e5a9071d6c529245a8f2c2be6140c0a230 Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Tue, 18 Jul 2017 21:48:28 -0700 Subject: [PATCH] Flow types on wrapper.js --- README.md | 17 ++ app/models/o-auth-2-token.js | 47 ++++-- app/models/request.js | 3 +- app/models/response.js | 15 +- app/models/settings.js | 36 +++- app/network/network.js | 60 +++---- app/ui/components/request-pane.js | 10 +- app/ui/components/response-pane.js | 5 +- app/ui/components/wrapper.js | 259 ++++++++++++++++------------- flow-typed/classnames.js | 3 + flow-typed/insomnia-importers.js | 9 + 11 files changed, 278 insertions(+), 186 deletions(-) create mode 100644 flow-typed/classnames.js create mode 100644 flow-typed/insomnia-importers.js diff --git a/README.md b/README.md index 4a70203d0..d1e15ed66 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,9 @@ common text editors. Read more and download plugins at [editorconfig.org](http:/ Development on Insomnia can be done on Mac, Windows, or Linux as long as you have [NodeJS 7.4](https://nodejs.org) and [Git](https://git-scm.com/). +
+Initial Dev Setup + ```bash # Install dependencies and build addons for Electron npm install @@ -45,6 +48,20 @@ npm run dev npm test ``` +
+ +
+Editor Requirements + +You can use any editor you'd like, but make sure to have support/plugins for +the following tools: + +- [ESLint](http://eslint.org/) – For catching syntax problems and common errors +- [JSX Syntax](https://facebook.github.io/react/docs/jsx-in-depth.html) – For React components +- [Flow](https://flow.org/) – For type annotations + +
+ ## License [GNU AGPLv3](LICENSE) © [Insomnia](https://insomnia.rest) diff --git a/app/models/o-auth-2-token.js b/app/models/o-auth-2-token.js index d4e53370c..b76b33574 100644 --- a/app/models/o-auth-2-token.js +++ b/app/models/o-auth-2-token.js @@ -1,58 +1,73 @@ +// @flow +import type {BaseModel} from './index'; + import * as db from '../common/database'; +type BaseOAuth2Token = { + refreshToken: string, + accessToken: string, + expiresAt: number | null, // Should be Date.now() if valid + + // Error handling + error: string, + errorDescription: string, + errorUri: string +}; + +export type OAuth2Token = BaseModel & BaseOAuth2Token; + export const name = 'OAuth 2.0 Token'; export const type = 'OAuth2Token'; export const prefix = 'oa2'; export const canDuplicate = false; -export function init () { +export function init (): BaseOAuth2Token { return { - parentId: null, - refreshToken: null, - accessToken: null, + refreshToken: '', + accessToken: '', expiresAt: null, // Should be Date.now() if valid // Error handling - error: null, - errorDescription: null, - errorUri: null + error: '', + errorDescription: '', + errorUri: '' }; } -export function migrate (doc) { +export function migrate (doc: T): T { return doc; } -export function create (patch = {}) { +export function create (patch: Object = {}): Promise { if (!patch.parentId) { - throw new Error('New OAuth2Token missing `parentId`', patch); + throw new Error(`New OAuth2Token missing \`parentId\` ${JSON.stringify(patch)}`); } return db.docCreate(type, patch); } -export function update (token, patch) { +export function update (token: OAuth2Token, patch: Object): Promise { return db.docUpdate(token, patch); } -export function remove (token) { +export function remove (token: OAuth2Token): Promise { return db.remove(token); } -export function getByParentId (parentId) { +export function getByParentId (parentId: string): Promise { return db.getWhere(type, {parentId}); } -export async function getOrCreateByParentId (parentId, patch = {}) { +export async function getOrCreateByParentId (parentId: string): Promise { let token = await db.getWhere(type, {parentId}); if (!token) { - token = await create({parentId}, patch); + token = await create({parentId}); } return token; } -export function all () { +export function all (): Promise> { return db.all(type); } diff --git a/app/models/request.js b/app/models/request.js index 06f812fb5..b6bd8ed7c 100644 --- a/app/models/request.js +++ b/app/models/request.js @@ -50,7 +50,6 @@ type BaseRequest = { headers: Array, authentication: RequestAuthentication, metaSortKey: number, - bodyPath: string, // Settings settingStoreCookies: boolean, @@ -61,7 +60,7 @@ type BaseRequest = { export type Request = BaseModel & BaseRequest; -export function init () { +export function init (): BaseRequest { return { url: '', name: 'New Request', diff --git a/app/models/response.js b/app/models/response.js index 21e3138bf..1e8dce504 100644 --- a/app/models/response.js +++ b/app/models/response.js @@ -1,5 +1,7 @@ // @flow -import type {Request} from './request'; +import type {BaseModel} from './index'; +import * as models from './index'; + import fs from 'fs'; import crypto from 'crypto'; import path from 'path'; @@ -7,7 +9,6 @@ import mkdirp from 'mkdirp'; import * as electron from 'electron'; import {MAX_RESPONSES} from '../common/constants'; import * as db from '../common/database'; -import * as models from './index'; import {compress, decompress} from '../common/misc'; export const name = 'Response'; @@ -25,7 +26,7 @@ export type ResponseTimelineEntry = { value: string } -export type Response = { +type BaseResponse = { statusCode: number, statusMessage: string, contentType: string, @@ -43,7 +44,9 @@ export type Response = { settingSendCookies: boolean | null }; -export function init (): Response { +export type Response = BaseModel & BaseResponse; + +export function init (): BaseResponse { return { statusCode: 0, statusMessage: '', @@ -81,8 +84,8 @@ export async function removeForRequest (parentId: string) { await db.removeWhere(type, {parentId}); } -export function remove (request: Request) { - return db.remove(request); +export function remove (response: Response) { + return db.remove(response); } export function findRecentForRequest (requestId: string, limit: number) { diff --git a/app/models/settings.js b/app/models/settings.js index f9d6dcb7c..42390ee28 100644 --- a/app/models/settings.js +++ b/app/models/settings.js @@ -1,11 +1,35 @@ +// @flow +import type {BaseModel} from './index'; import * as db from '../common/database'; +type BaseSettings = { + showPasswords: boolean, + useBulkHeaderEditor: boolean, + followRedirects: boolean, + editorFontSize: number, + editorIndentSize: number, + editorLineWrapping: boolean, + editorKeyMap: string, + httpProxy: string, + httpsProxy: string, + noProxy: string, + proxyEnabled: boolean, + timeout: number, + validateSSL: boolean, + forceVerticalLayout: boolean, + autoHideMenuBar: boolean, + theme: string, + disableAnalyticsTracking: boolean +}; + +export type Settings = BaseModel & Settings; + export const name = 'Settings'; export const type = 'Settings'; export const prefix = 'set'; export const canDuplicate = false; -export function init () { +export function init (): BaseSettings { return { showPasswords: false, useBulkHeaderEditor: false, @@ -27,11 +51,11 @@ export function init () { }; } -export function migrate (doc) { +export function migrate (doc: T): T { return doc; } -export async function all () { +export async function all (): Promise> { const settings = await db.all(type); if (settings.length === 0) { return [await getOrCreate()]; @@ -40,15 +64,15 @@ export async function all () { } } -export async function create (patch = {}) { +export async function create (patch: Object = {}): Promise { return db.docCreate(type, patch); } -export async function update (settings, patch) { +export async function update (settings: Settings, patch: Object): Promise { return db.docUpdate(settings, patch); } -export async function getOrCreate (patch = {}) { +export async function getOrCreate (patch: Object = {}): Promise { const results = await db.all(type); if (results.length === 0) { return await create(patch); diff --git a/app/network/network.js b/app/network/network.js index cf1f29413..83af1cd6c 100644 --- a/app/network/network.js +++ b/app/network/network.js @@ -1,8 +1,8 @@ // @flow import type {ResponseTimelineEntry} from '../models/response'; -import type {BaseModel} from '../models/index'; import type {Request, RequestHeader} from '../models/request'; import type {Workspace} from '../models/workspace'; +import type {Settings} from '../models/settings'; import electron from 'electron'; import mkdirp from 'mkdirp'; @@ -37,22 +37,13 @@ type CookieJar = { cookies: Array } -type RenderedRequest = BaseModel & Request & { +type RenderedRequest = Request & { cookies: Array<{name: string, value: string, disabled: boolean}>, cookieJar: CookieJar }; type ResponsePatch = {}; -type Settings = { - _id: string, - followRedirects: boolean, - timeout: number, - httpProxy: string, - httpsProxy: string, - noProxy: string -}; - // Time since user's last keypress to wait before making the request const MAX_DELAY_TIME = 1000; @@ -73,7 +64,10 @@ export function _actuallySend ( return new Promise(async resolve => { let timeline: Array = []; - // Define helper to add base fields when responding + // Initialize the curl handle + const curl = new Curl(); + + /** Helper function to respond with a success */ function respond (patch: ResponsePatch, bodyBuffer: ?Buffer = null): void { const response = Object.assign({ parentId: renderedRequest._id, @@ -85,11 +79,12 @@ export function _actuallySend ( resolve({bodyBuffer, response}); } - function handleError (err, prefix = null) { + /** Helper function to respond with an error */ + function handleError (err: Error): void { respond({ url: renderedRequest.url, parentId: renderedRequest._id, - error: prefix ? `${prefix}: ${err.message}` : err.message, + error: err.message, elapsedTime: 0, statusMessage: 'Error', settingSendCookies: renderedRequest.settingSendCookies, @@ -97,26 +92,21 @@ export function _actuallySend ( }); } - try { - // Initialize the curl handle - const curl = new Curl(); - - // Define helper to setOpt for better error handling - const setOpt = (opt, val, optional = false) => { - const name = Object.keys(Curl.option).find(name => Curl.option[name] === opt); - try { - curl.setOpt(opt, val); - } catch (err) { - if (!optional) { - throw new Error(`${err.message} (${opt} ${name || 'n/a'})`); - } else { - console.warn(`Failed to set optional Curl opt (${opt} ${name || 'n/a'})`); - } + /** Helper function to set Curl options */ + function setOpt (opt: string, val: any, optional: boolean = false) { + const name = Object.keys(Curl.option).find(name => Curl.option[name] === opt); + try { + curl.setOpt(opt, val); + } catch (err) { + if (!optional) { + throw new Error(`${err.message} (${opt} ${name || 'n/a'})`); + } else { + console.warn(`Failed to set optional Curl opt (${opt} ${name || 'n/a'})`); } - }; - - const setOptionalOpt = (opt, val) => setOpt(opt, val, true); + } + } + try { // Setup the cancellation logic cancelRequestFunction = () => { respond({ @@ -133,7 +123,7 @@ export function _actuallySend ( // Set all the basic options setOpt(Curl.option.CUSTOMREQUEST, renderedRequest.method); - setOpt(Curl.option.NOBODY, renderedRequest.method.toLowerCase() === 'head' ? 1 : 0); + setOpt(Curl.option.NOBODY, renderedRequest.method.toUpperCase() === 'HEAD' ? 1 : 0); setOpt(Curl.option.FOLLOWLOCATION, settings.followRedirects); setOpt(Curl.option.TIMEOUT_MS, settings.timeout); // 0 for no timeout setOpt(Curl.option.VERBOSE, true); // True so debug function works @@ -186,7 +176,7 @@ export function _actuallySend ( let lastPercent = 0; // NOTE: This option was added in 7.32.0 so make it optional - setOptionalOpt(Curl.option.XFERINFOFUNCTION, (dltotal, dlnow, ultotal, ulnow) => { + setOpt(Curl.option.XFERINFOFUNCTION, (dltotal, dlnow, ultotal, ulnow) => { if (dltotal === 0) { return 0; } @@ -198,7 +188,7 @@ export function _actuallySend ( } return 0; - }); + }, true); // Set the URL, including the query parameters const qs = querystring.buildFromParams(renderedRequest.parameters); diff --git a/app/ui/components/request-pane.js b/app/ui/components/request-pane.js index d8f409507..7d480ffe4 100644 --- a/app/ui/components/request-pane.js +++ b/app/ui/components/request-pane.js @@ -1,6 +1,7 @@ // @flow import type {Request} from '../../models/request'; import type {Workspace} from '../../models/workspace'; +import type {OAuth2Token} from '../../models/o-auth-2-token'; import React from 'react'; import autobind from 'autobind-decorator'; @@ -55,8 +56,8 @@ type Props = { forceRefreshCounter: number, // Optional - request: Request, - oAuth2Token: Object + request: ?Request, + oAuth2Token: ?OAuth2Token } @autobind @@ -119,6 +120,11 @@ class RequestPane extends React.PureComponent { _handleImportQueryFromUrl () { const {request} = this.props; + if (!request) { + console.warn('Tried to import query when no request active'); + return; + } + let query; try { query = querystring.extractFromUrl(request.url); diff --git a/app/ui/components/response-pane.js b/app/ui/components/response-pane.js index c17741be4..5502e6ba6 100644 --- a/app/ui/components/response-pane.js +++ b/app/ui/components/response-pane.js @@ -1,5 +1,4 @@ // @flow -import type {BaseModel} from '../../models/index'; import type {Request} from '../../models/request'; import type {Response} from '../../models/response'; @@ -51,8 +50,8 @@ class ResponsePane extends PureComponent { responses: Array, // Other - request?: BaseModel & Request, - response?: BaseModel & Response + request: ?Request, + response: ?Response }; _trackTab (name: string) { diff --git a/app/ui/components/wrapper.js b/app/ui/components/wrapper.js index 67bfdc397..e7c421b78 100644 --- a/app/ui/components/wrapper.js +++ b/app/ui/components/wrapper.js @@ -1,4 +1,11 @@ -import React, {PropTypes, PureComponent} from 'react'; +// @flow +import type {Settings} from '../../models/settings'; +import type {Response} from '../../models/response'; +import type {OAuth2Token} from '../../models/o-auth-2-token'; +import type {Workspace} from '../../models/workspace'; +import type {Request, RequestAuthentication, RequestBody, RequestHeader, RequestParameter} from '../../models/request'; + +import React from 'react'; import autobind from 'autobind-decorator'; import classnames from 'classnames'; import {registerModal, showModal} from './modals/index'; @@ -31,12 +38,90 @@ import {updateMimeType} from '../../models/request'; import {trackEvent} from '../../analytics/index'; import * as importers from 'insomnia-importers'; -const rUpdate = models.request.update; +const rUpdate = (request, ...args) => { + if (!request) { + throw new Error('Tried to update null request'); + } + + return models.request.update(request, ...args); +}; + const sUpdate = models.settings.update; +type Props = { + // Helper Functions + handleActivateRequest: Function, + handleSetSidebarFilter: Function, + handleToggleMenuBar: Function, + handleImportFileToWorkspace: Function, + handleImportUriToWorkspace: Function, + handleExportFile: Function, + handleSetActiveWorkspace: Function, + handleSetActiveEnvironment: Function, + handleMoveDoc: Function, + handleCreateRequest: Function, + handleDuplicateRequest: Function, + handleDuplicateRequestGroup: Function, + handleDuplicateWorkspace: Function, + handleCreateRequestGroup: Function, + handleGenerateCodeForActiveRequest: Function, + handleGenerateCode: Function, + handleCopyAsCurl: Function, + handleCreateRequestForWorkspace: Function, + handleSetRequestPaneRef: Function, + handleSetResponsePaneRef: Function, + handleSetResponsePreviewMode: Function, + handleRender: Function, + handleGetRenderContext: Function, + handleSetResponseFilter: Function, + handleSetActiveResponse: Function, + handleSetSidebarRef: Function, + handleStartDragSidebar: Function, + handleResetDragSidebar: Function, + handleStartDragPaneHorizontal: Function, + handleStartDragPaneVertical: Function, + handleResetDragPaneHorizontal: Function, + handleResetDragPaneVertical: Function, + handleSetRequestGroupCollapsed: Function, + handleSendRequestWithEnvironment: Function, + handleSendAndDownloadRequestWithEnvironment: Function, + + // Properties + loadStartTime: number, + isLoading: boolean, + paneWidth: number, + paneHeight: number, + responsePreviewMode: string, + responseFilter: string, + responseFilterHistory: Array, + sidebarWidth: number, + sidebarHidden: boolean, + sidebarFilter: string, + sidebarChildren: Array, + settings: Settings, + workspaces: Array, + workspaceChildren: Array, + environments: Array, + activeRequestResponses: Array, + activeWorkspace: Workspace, + + // Optional + oAuth2Token: ?OAuth2Token, + activeRequest: ?Request, + activeResponse: ?Response, + activeEnvironment: ?Object +}; + +type State = { + forceRefreshKey: number +}; + @autobind -class Wrapper extends PureComponent { - constructor (props) { +class Wrapper extends React.PureComponent { + props: Props; + state: State; + + constructor (props: Props) { super(props); this.state = { forceRefreshKey: Date.now() @@ -44,7 +129,7 @@ class Wrapper extends PureComponent { } // Request updaters - async _handleForceUpdateRequest (patch) { + async _handleForceUpdateRequest (patch: Object): Promise { const newRequest = await rUpdate(this.props.activeRequest, patch); // Give it a second for the app to render first. If we don't wait, it will refresh @@ -54,45 +139,52 @@ class Wrapper extends PureComponent { return newRequest; } - _handleUpdateRequestBody (body) { - rUpdate(this.props.activeRequest, {body}); + _handleUpdateRequestBody (body: RequestBody): Promise { + return rUpdate(this.props.activeRequest, {body}); } - _handleUpdateRequestMethod (method) { - rUpdate(this.props.activeRequest, {method}); + _handleUpdateRequestMethod (method: string): Promise { + return rUpdate(this.props.activeRequest, {method}); } - _handleUpdateRequestParameters (parameters) { - rUpdate(this.props.activeRequest, {parameters}); + _handleUpdateRequestParameters (parameters: Array): Promise { + return rUpdate(this.props.activeRequest, {parameters}); } - _handleUpdateRequestAuthentication (authentication) { - rUpdate(this.props.activeRequest, {authentication}); + _handleUpdateRequestAuthentication (authentication: RequestAuthentication): Promise { + return rUpdate(this.props.activeRequest, {authentication}); } - _handleUpdateRequestHeaders (headers) { - rUpdate(this.props.activeRequest, {headers}); + _handleUpdateRequestHeaders (headers: Array): Promise { + return rUpdate(this.props.activeRequest, {headers}); } - _handleUpdateRequestUrl (url) { - rUpdate(this.props.activeRequest, {url}); + _handleUpdateRequestUrl (url: string): Promise { + return rUpdate(this.props.activeRequest, {url}); } // Special request updaters - async _handleUpdateRequestMimeType (mimeType) { - await updateMimeType(this.props.activeRequest, mimeType); + async _handleUpdateRequestMimeType (mimeType: string): Promise { + if (!this.props.activeRequest) { + console.warn('Tried to update request mime-type when no active request'); + return null; + } + + const newRequest = await updateMimeType(this.props.activeRequest, mimeType); // Force it to update, because other editor components (header editor) // needs to change. Need to wait a delay so the next render can finish setTimeout(this._forceRequestPaneRefresh, 300); + + return newRequest; } - _handleStartDragSidebar (e) { + _handleStartDragSidebar (e: Event): void { e.preventDefault(); this.props.handleStartDragSidebar(); } - async _handleImport (text) { + async _handleImport (text: string): Promise { // Allow user to paste any import file into the url. If it results in // only one item, it will overwrite the current request. try { @@ -121,49 +213,59 @@ class Wrapper extends PureComponent { } // Settings updaters - _handleUpdateSettingsShowPasswords (showPasswords) { - sUpdate(this.props.settings, {showPasswords}); + _handleUpdateSettingsShowPasswords (showPasswords: boolean): Promise { + return sUpdate(this.props.settings, {showPasswords}); } - _handleUpdateSettingsUseBulkHeaderEditor (useBulkHeaderEditor) { - sUpdate(this.props.settings, {useBulkHeaderEditor}); + _handleUpdateSettingsUseBulkHeaderEditor (useBulkHeaderEditor: boolean): Promise { + return sUpdate(this.props.settings, {useBulkHeaderEditor}); } // Other Helpers - _handleImportFile () { + _handleImportFile (): void { this.props.handleImportFileToWorkspace(this.props.activeWorkspace._id); } - _handleImportUri (uri) { + _handleImportUri (uri: string): void { this.props.handleImportUriToWorkspace(this.props.activeWorkspace._id, uri); } - _handleExportWorkspaceToFile () { + _handleExportWorkspaceToFile (): void { this.props.handleExportFile(this.props.activeWorkspace._id); } - _handleSetActiveResponse (responseId) { + _handleSetActiveResponse (responseId: string | null): void { + if (!this.props.activeRequest) { + console.warn('Tried to set active response when request not active'); + return; + } + this.props.handleSetActiveResponse(this.props.activeRequest._id, responseId); } - _handleShowEnvironmentsModal () { + _handleShowEnvironmentsModal (): void { showModal(WorkspaceEnvironmentsEditModal, this.props.activeWorkspace); } - _handleShowCookiesModal () { + _handleShowCookiesModal (): void { showModal(CookiesModal, this.props.activeWorkspace); } - _handleShowRequestSettingsModal () { + _handleShowRequestSettingsModal (): void { showModal(RequestSettingsModal, {request: this.props.activeRequest}); } - _handleDeleteResponses () { + _handleDeleteResponses (): void { + if (!this.props.activeRequest) { + console.warn('Tried to delete responses when request not active'); + return; + } + models.response.removeForRequest(this.props.activeRequest._id); this._handleSetActiveResponse(null); } - async _handleDeleteResponse (response) { + async _handleDeleteResponse (response: Response): Promise { if (response) { await models.response.remove(response); } @@ -174,7 +276,7 @@ class Wrapper extends PureComponent { } } - async _handleRemoveActiveWorkspace () { + async _handleRemoveActiveWorkspace (): Promise { const {workspaces, activeWorkspace} = this.props; if (workspaces.length <= 1) { showModal(AlertModal, { @@ -188,45 +290,36 @@ class Wrapper extends PureComponent { trackEvent('Workspace', 'Delete'); } - models.workspace.remove(activeWorkspace); + await models.workspace.remove(activeWorkspace); } - async _handleDuplicateActiveWorkspace () { - const {activeWorkspace} = this.props; - - trackEvent('Workspace', 'Duplicate'); - - const newWorkspace = await models.workspace.duplicate(activeWorkspace); - await this.props.handleSetActiveWorkspace(newWorkspace._id); - } - - _handleSendRequestWithActiveEnvironment () { + _handleSendRequestWithActiveEnvironment (): void { const {activeRequest, activeEnvironment, handleSendRequestWithEnvironment} = this.props; const activeRequestId = activeRequest ? activeRequest._id : 'n/a'; const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : 'n/a'; handleSendRequestWithEnvironment(activeRequestId, activeEnvironmentId); } - _handleSendAndDownloadRequestWithActiveEnvironment (filename) { + _handleSendAndDownloadRequestWithActiveEnvironment (filename: string): void { const {activeRequest, activeEnvironment, handleSendAndDownloadRequestWithEnvironment} = this.props; const activeRequestId = activeRequest ? activeRequest._id : 'n/a'; const activeEnvironmentId = activeEnvironment ? activeEnvironment._id : 'n/a'; handleSendAndDownloadRequestWithEnvironment(activeRequestId, activeEnvironmentId, filename); } - _handleSetPreviewMode (previewMode) { + _handleSetPreviewMode (previewMode: string): void { const activeRequest = this.props.activeRequest; const activeRequestId = activeRequest ? activeRequest._id : 'n/a'; this.props.handleSetResponsePreviewMode(activeRequestId, previewMode); } - _handleSetResponseFilter (filter) { + _handleSetResponseFilter (filter: string): void { const activeRequest = this.props.activeRequest; const activeRequestId = activeRequest ? activeRequest._id : 'n/a'; this.props.handleSetResponseFilter(activeRequestId, filter); } - _forceRequestPaneRefresh () { + _forceRequestPaneRefresh (): void { this.setState({forceRefreshKey: Date.now()}); } @@ -508,70 +601,4 @@ class Wrapper extends PureComponent { } } -Wrapper.propTypes = { - // Helper Functions - handleActivateRequest: PropTypes.func.isRequired, - handleSetSidebarFilter: PropTypes.func.isRequired, - handleToggleMenuBar: PropTypes.func.isRequired, - handleImportFileToWorkspace: PropTypes.func.isRequired, - handleImportUriToWorkspace: PropTypes.func.isRequired, - handleExportFile: PropTypes.func.isRequired, - handleSetActiveWorkspace: PropTypes.func.isRequired, - handleSetActiveEnvironment: PropTypes.func.isRequired, - handleMoveDoc: PropTypes.func.isRequired, - handleCreateRequest: PropTypes.func.isRequired, - handleDuplicateRequest: PropTypes.func.isRequired, - handleDuplicateRequestGroup: PropTypes.func.isRequired, - handleDuplicateWorkspace: PropTypes.func.isRequired, - handleCreateRequestGroup: PropTypes.func.isRequired, - handleGenerateCodeForActiveRequest: PropTypes.func.isRequired, - handleGenerateCode: PropTypes.func.isRequired, - handleCopyAsCurl: PropTypes.func.isRequired, - handleCreateRequestForWorkspace: PropTypes.func.isRequired, - handleSetRequestPaneRef: PropTypes.func.isRequired, - handleSetResponsePaneRef: PropTypes.func.isRequired, - handleSetResponsePreviewMode: PropTypes.func.isRequired, - handleRender: PropTypes.func.isRequired, - handleGetRenderContext: PropTypes.func.isRequired, - handleSetResponseFilter: PropTypes.func.isRequired, - handleSetActiveResponse: PropTypes.func.isRequired, - handleSetSidebarRef: PropTypes.func.isRequired, - handleStartDragSidebar: PropTypes.func.isRequired, - handleResetDragSidebar: PropTypes.func.isRequired, - handleStartDragPaneHorizontal: PropTypes.func.isRequired, - handleStartDragPaneVertical: PropTypes.func.isRequired, - handleResetDragPaneHorizontal: PropTypes.func.isRequired, - handleResetDragPaneVertical: PropTypes.func.isRequired, - handleSetRequestGroupCollapsed: PropTypes.func.isRequired, - handleSendRequestWithEnvironment: PropTypes.func.isRequired, - handleSendAndDownloadRequestWithEnvironment: PropTypes.func.isRequired, - - // Properties - loadStartTime: PropTypes.number.isRequired, - isLoading: PropTypes.bool.isRequired, - paneWidth: PropTypes.number.isRequired, - paneHeight: PropTypes.number.isRequired, - responsePreviewMode: PropTypes.string.isRequired, - responseFilter: PropTypes.string.isRequired, - responseFilterHistory: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired, - sidebarWidth: PropTypes.number.isRequired, - sidebarHidden: PropTypes.bool.isRequired, - sidebarFilter: PropTypes.string.isRequired, - sidebarChildren: PropTypes.arrayOf(PropTypes.object).isRequired, - settings: PropTypes.object.isRequired, - workspaces: PropTypes.arrayOf(PropTypes.object).isRequired, - workspaceChildren: PropTypes.arrayOf(PropTypes.object).isRequired, - environments: PropTypes.arrayOf(PropTypes.object).isRequired, - activeRequestResponses: PropTypes.arrayOf(PropTypes.object).isRequired, - activeWorkspace: PropTypes.shape({ - _id: PropTypes.string.isRequired - }).isRequired, - - // Optional - oAuth2Token: PropTypes.object, - activeRequest: PropTypes.object, - activeResponse: PropTypes.object, - activeEnvironment: PropTypes.object -}; - export default Wrapper; diff --git a/flow-typed/classnames.js b/flow-typed/classnames.js new file mode 100644 index 000000000..15526ddba --- /dev/null +++ b/flow-typed/classnames.js @@ -0,0 +1,3 @@ +declare module 'classnames' { + declare module.exports: (...args: Array) => Object +} diff --git a/flow-typed/insomnia-importers.js b/flow-typed/insomnia-importers.js new file mode 100644 index 000000000..d05703292 --- /dev/null +++ b/flow-typed/insomnia-importers.js @@ -0,0 +1,9 @@ +declare module 'insomnia-importers' { + declare module.exports: { + convert: (data: string) => { + data: { + resources: Array + } + } + } +}