diff --git a/app/auto-updater-linux.ts b/app/auto-updater-linux.ts index da83733a..d6344fdf 100644 --- a/app/auto-updater-linux.ts +++ b/app/auto-updater-linux.ts @@ -21,9 +21,10 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater { this.emit('checking-for-update'); fetch(this.updateURL) - .then((res): any => { + .then((res) => { if (res.status === 204) { - return this.emit('update-not-available'); + this.emit('update-not-available'); + return; } // eslint-disable-next-line @typescript-eslint/camelcase return res.json().then(({name, notes, pub_date}) => { @@ -40,7 +41,7 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater { .catch(this.emitError.bind(this)); } - emitError(error: any) { + emitError(error: string | Error) { if (typeof error === 'string') { error = new Error(error); } diff --git a/app/config.ts b/app/config.ts index ab4a3542..786c9340 100644 --- a/app/config.ts +++ b/app/config.ts @@ -7,7 +7,7 @@ import {cfgPath, cfgDir} from './config/paths'; import {getColorMap} from './utils/colors'; import {parsedConfig, configOptions} from '../lib/config'; -const watchers: any[] = []; +const watchers: Function[] = []; let cfg: parsedConfig = {} as any; let _watcher: fs.FSWatcher; diff --git a/app/notifications.ts b/app/notifications.ts index fa59a8e4..ad7aaabd 100644 --- a/app/notifications.ts +++ b/app/notifications.ts @@ -7,7 +7,7 @@ const NEWS_URL = 'https://hyper-news.now.sh'; export default function fetchNotifications(win: BrowserWindow) { const {rpc} = win; - const retry = (err?: any) => { + const retry = (err?: Error) => { setTimeout(() => fetchNotifications(win), ms('30m')); if (err) { console.error('Notification messages fetch error', err.stack); diff --git a/app/notify.ts b/app/notify.ts index c455fe55..0d1eaa52 100644 --- a/app/notify.ts +++ b/app/notify.ts @@ -1,7 +1,7 @@ import {Notification} from 'electron'; import {icon} from './config/paths'; -export default function notify(title: string, body = '', details: any = {}) { +export default function notify(title: string, body = '', details: {error?: any} = {}) { console.log(`[Notification] ${title}: ${body}`); if (details.error) { console.error(details.error); diff --git a/app/session.ts b/app/session.ts index b376f48b..4af8a5b2 100644 --- a/app/session.ts +++ b/app/session.ts @@ -153,7 +153,7 @@ export default class Session extends EventEmitter { this.batcher?.write(chunk as any); }); - this.batcher.on('flush', (data) => { + this.batcher.on('flush', (data: string) => { this.emit('data', data); }); diff --git a/app/ui/window.ts b/app/ui/window.ts index 175ae748..df5107c0 100644 --- a/app/ui/window.ts +++ b/app/ui/window.ts @@ -149,7 +149,7 @@ export function newWindow( activeUid: options.activeUid }); - session.on('data', (data: any) => { + session.on('data', (data: string) => { rpc.emit('session data', data); }); diff --git a/app/utils/cli-install.ts b/app/utils/cli-install.ts index 88ca8241..e9f20ef4 100644 --- a/app/utils/cli-install.ts +++ b/app/utils/cli-install.ts @@ -86,7 +86,7 @@ const addBinToUserPath = () => { }); }; -const logNotify = (withNotification: boolean, title: string, body: string, details?: any) => { +const logNotify = (withNotification: boolean, title: string, body: string, details?: {error?: any}) => { console.log(title, body, details); withNotification && notify(title, body, details); }; diff --git a/cli/index.ts b/cli/index.ts index 7fc03d53..95620066 100644 --- a/cli/index.ts +++ b/cli/index.ts @@ -1,6 +1,6 @@ // This is a CLI tool, using console is OK /* eslint no-console: 0 */ -import {spawn, exec} from 'child_process'; +import {spawn, exec, SpawnOptions} from 'child_process'; import {isAbsolute, resolve} from 'path'; import {existsSync} from 'fs'; import {version} from '../app/package.json'; @@ -42,7 +42,7 @@ args.command( commandPromise = api .install(pluginName) .then(() => console.log(chalk.green(`${pluginName} installed successfully!`))) - .catch((err: any) => console.error(chalk.red(err))); + .catch((err) => console.error(chalk.red(err))); }, ['i'] ); @@ -202,7 +202,7 @@ const main = (argv: string[]) => { env['ELECTRON_ENABLE_LOGGING'] = '1'; } - const options: any = { + const options: SpawnOptions = { detached: true, env }; @@ -231,8 +231,8 @@ const main = (argv: string[]) => { const child = spawn(process.execPath, args_, options); if (flags.verbose) { - child.stdout.on('data', (data) => console.log(data.toString('utf8'))); - child.stderr.on('data', (data) => console.error(data.toString('utf8'))); + child.stdout?.on('data', (data) => console.log(data.toString('utf8'))); + child.stderr?.on('data', (data) => console.error(data.toString('utf8'))); } if (flags.verbose) { return new Promise((c) => child.once('exit', () => c(null))); @@ -247,7 +247,7 @@ function eventuallyExit(code: number) { main(process.argv) .then(() => eventuallyExit(0)) - .catch((err: any) => { + .catch((err) => { console.error(err.stack ? err.stack : err); eventuallyExit(1); }); diff --git a/lib/actions/sessions.ts b/lib/actions/sessions.ts index 356cfe13..af77f765 100644 --- a/lib/actions/sessions.ts +++ b/lib/actions/sessions.ts @@ -50,7 +50,7 @@ export function requestSession() { }; } -export function addSessionData(uid: string, data: any) { +export function addSessionData(uid: string, data: string) { return (dispatch: HyperDispatch) => { dispatch({ type: SESSION_ADD_DATA, @@ -161,7 +161,7 @@ export function closeSearch(uid?: string, keyEvent?: any) { }; } -export function sendSessionData(uid: string | null, data: any, escaped?: any) { +export function sendSessionData(uid: string | null, data: any, escaped?: boolean | null) { return (dispatch: HyperDispatch, getState: () => HyperState) => { dispatch({ type: SESSION_USER_DATA, diff --git a/lib/actions/ui.ts b/lib/actions/ui.ts index 9838ee7a..02e80366 100644 --- a/lib/actions/ui.ts +++ b/lib/actions/ui.ts @@ -112,16 +112,15 @@ export function windowGeometryUpdated(): HyperActions { // Find all sessions that are below the given // termGroup uid in the hierarchy: -const findChildSessions = (termGroups: any, uid: string): string[] => { +const findChildSessions = (termGroups: HyperState['termGroups']['termGroups'], uid: string): string[] => { const group = termGroups[uid]; if (group.sessionUid) { return [uid]; } - return group.children.reduce( - (total: string[], childUid: string) => total.concat(findChildSessions(termGroups, childUid)), - [] - ); + return group.children + .asMutable() + .reduce((total: string[], childUid: string) => total.concat(findChildSessions(termGroups, childUid)), []); }; // Get the index of the next or previous group, @@ -318,7 +317,7 @@ export function openSSH(url: string) { }; } -export function execCommand(command: string, fn: (...args: any[]) => void, e: any) { +export function execCommand(command: string, fn: (e: any, dispatch: HyperDispatch) => void, e: any) { return (dispatch: HyperDispatch) => dispatch({ type: UI_COMMAND_EXEC, diff --git a/lib/command-registry.ts b/lib/command-registry.ts index 4c8e827d..27b6e513 100644 --- a/lib/command-registry.ts +++ b/lib/command-registry.ts @@ -3,7 +3,7 @@ import {HyperDispatch} from './hyper'; import {closeSearch} from './actions/sessions'; // TODO: Should be updates to new async API https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31 -const {getDecoratedKeymaps} = remote.require('./plugins'); +const {getDecoratedKeymaps} = remote.require('./plugins') as typeof import('../app/plugins'); let commands: Record void> = { 'editor:search-close': (e, dispatch) => { @@ -16,7 +16,7 @@ export const getRegisteredKeys = () => { return Object.keys(keymaps).reduce((result: Record, actionName) => { const commandKeys = keymaps[actionName]; - commandKeys.forEach((shortcut: string) => { + commandKeys.forEach((shortcut) => { result[shortcut] = actionName; }); return result; diff --git a/lib/components/term-group.tsx b/lib/components/term-group.tsx index 65d37b85..312c9a6a 100644 --- a/lib/components/term-group.tsx +++ b/lib/components/term-group.tsx @@ -12,13 +12,13 @@ const SplitPane = decorate(SplitPane_, 'SplitPane'); // eslint-disable-next-line @typescript-eslint/class-name-casing class TermGroup_ extends React.PureComponent { bound: WeakMap<(uid: string, ...args: any[]) => any, Record any>>; - term?: Term_; + term?: Term_ | null; constructor(props: TermGroupProps, context: any) { super(props, context); this.bound = new WeakMap(); } - bind any>( + bind any>( fn: T, thisObj: any, uid: string @@ -52,7 +52,7 @@ class TermGroup_ extends React.PureComponent { ); } - onTermRef = (uid: string, term: Term_) => { + onTermRef = (uid: string, term: Term_ | null) => { this.term = term; this.props.ref_(uid, term); }; diff --git a/lib/components/terms.tsx b/lib/components/terms.tsx index 5ce8daf3..3f497613 100644 --- a/lib/components/terms.tsx +++ b/lib/components/terms.tsx @@ -3,7 +3,7 @@ import {decorate, getTermGroupProps} from '../utils/plugins'; import {registerCommandHandlers} from '../command-registry'; import TermGroup_ from './term-group'; import StyleSheet_ from './style-sheet'; -import {TermsProps} from '../hyper'; +import {TermsProps, HyperDispatch} from '../hyper'; import Term from './term'; import {ObjectTypedKeys} from '../utils/object'; @@ -14,7 +14,7 @@ const isMac = /Mac/.test(navigator.userAgent); export default class Terms extends React.Component { terms: Record; - registerCommands: (cmds: Record void>) => void; + registerCommands: (cmds: Record void>) => void; constructor(props: TermsProps, context: any) { super(props, context); this.terms = {}; @@ -29,7 +29,7 @@ export default class Terms extends React.Component { ); } - onRef = (uid: string, term: Term) => { + onRef = (uid: string, term: Term | null) => { if (term) { this.terms[uid] = term; } diff --git a/lib/containers/hyper.tsx b/lib/containers/hyper.tsx index 3b503e16..ecd4e9cd 100644 --- a/lib/containers/hyper.tsx +++ b/lib/containers/hyper.tsx @@ -10,12 +10,13 @@ import {HeaderContainer} from './header'; import TermsContainer from './terms'; import NotificationsContainer from './notifications'; import {HyperState, HyperProps, HyperDispatch} from '../hyper'; +import Terms from '../components/terms'; const isMac = /Mac/.test(navigator.userAgent); class Hyper extends React.PureComponent { mousetrap!: MousetrapInstance; - terms: any; + terms!: Terms; constructor(props: HyperProps) { super(props); } @@ -35,8 +36,8 @@ class Hyper extends React.PureComponent { } } - handleFocusActive = (uid: string) => { - const term = this.terms.getTermByUid(uid); + handleFocusActive = (uid?: string) => { + const term = uid && this.terms.getTermByUid(uid); if (term) { term.focus(); } @@ -81,7 +82,7 @@ class Hyper extends React.PureComponent { window.rpc.on('term selectAll', this.handleSelectAll); } - onTermsRef = (terms: any) => { + onTermsRef = (terms: Terms) => { this.terms = terms; window.focusActiveTerm = this.handleFocusActive; }; @@ -153,7 +154,7 @@ const mapStateToProps = (state: HyperState) => { const mapDispatchToProps = (dispatch: HyperDispatch) => { return { - execCommand: (command: string, fn: (...args: any[]) => void, e: any) => { + execCommand: (command: string, fn: (e: any, dispatch: HyperDispatch) => void, e: any) => { dispatch(uiActions.execCommand(command, fn, e)); } }; diff --git a/lib/hyper.d.ts b/lib/hyper.d.ts index a494b90f..d503354e 100644 --- a/lib/hyper.d.ts +++ b/lib/hyper.d.ts @@ -1,10 +1,11 @@ import {Immutable} from 'seamless-immutable'; +import Client from './utils/rpc'; declare global { interface Window { __rpcId: string; - rpc: any; - focusActiveTerm: any; + rpc: Client; + focusActiveTerm: (uid?: string) => void; } } @@ -154,6 +155,7 @@ export type hyperPlugin = { mapNotificationsState: any; mapTermsState: any; middleware: Middleware; + onRendererUnload: any; onRendererWindow: any; reduceSessions: ISessionReducer; reduceTermGroups: ITermGroupReducer; @@ -190,11 +192,12 @@ import configureStore from './store/configure-store'; export type HyperThunkDispatch = ThunkDispatch; export type HyperDispatch = ReturnType['dispatch']; +import {ReactChild} from 'react'; type extensionProps = Partial<{ - customChildren: any; - customChildrenBefore: any; + customChildren: ReactChild | ReactChild[]; + customChildrenBefore: ReactChild | ReactChild[]; customCSS: string; - customInnerChildren: any; + customInnerChildren: ReactChild | ReactChild[]; }>; import {HeaderConnectedProps} from './containers/header'; @@ -206,8 +209,9 @@ export type HyperProps = HyperConnectedProps & extensionProps; import {NotificationsConnectedProps} from './containers/notifications'; export type NotificationsProps = NotificationsConnectedProps & extensionProps; +import Terms from './components/terms'; import {TermsConnectedProps} from './containers/terms'; -export type TermsProps = TermsConnectedProps & extensionProps & {ref_: any}; +export type TermsProps = TermsConnectedProps & extensionProps & {ref_: (terms: Terms | null) => void}; export type StyleSheetProps = { backgroundColor: string; @@ -270,7 +274,7 @@ export type TermGroupOwnProps = { cursorAccentColor?: string; fontSmoothing?: string; parentProps: TermsProps; - ref_: (uid: string, term: Term) => void; + ref_: (uid: string, term: Term | null) => void; termGroup: Immutable; terms: Record; } & Pick< @@ -354,7 +358,7 @@ export type TermProps = { onActive: () => void; onContextMenu: (selection: any) => void; onCursorMove?: (cursorFrame: {x: number; y: number; width: number; height: number; col: number; row: number}) => void; - onData: (data: any) => void; + onData: (data: string) => void; onResize: (cols: number, rows: number) => void; onTitle: (title: string) => void; padding: string; @@ -371,6 +375,7 @@ export type TermProps = { url: string | null; webGLRenderer: boolean; webLinksActivationKey: string; -} & extensionProps & {ref_?: any}; + ref_: (uid: string, term: Term | null) => void; +} & extensionProps; export type Assignable = {[k in keyof U]: k extends keyof T ? T[k] : U[k]} & Partial; diff --git a/lib/index.tsx b/lib/index.tsx index a1921fd0..b1f2c3ce 100644 --- a/lib/index.tsx +++ b/lib/index.tsx @@ -76,7 +76,7 @@ rpc.on('session add', (data) => { store_.dispatch(sessionActions.addSession(data)); }); -rpc.on('session data', (d) => { +rpc.on('session data', (d: string) => { // the uid is a uuid v4 so it's 36 chars long const uid = d.slice(0, 36); const data = d.slice(36); diff --git a/lib/reducers/term-groups.ts b/lib/reducers/term-groups.ts index 7e8955ce..e4e24169 100644 --- a/lib/reducers/term-groups.ts +++ b/lib/reducers/term-groups.ts @@ -46,7 +46,7 @@ const setActiveGroup = (state: ImmutableType, action: {uid: string}) }; // Reduce existing sizes to fit a new split: -const insertRebalance = (oldSizes: ImmutableType, index: any) => { +const insertRebalance = (oldSizes: ImmutableType, index: number) => { const newSize = 1 / (oldSizes.length + 1); // We spread out how much each pane should be reduced // with based on their existing size: @@ -167,7 +167,7 @@ const removeGroup = (state: ImmutableType, uid: string) => { // it's safe to remove the group. if (group.parentUid && state.termGroups[group.parentUid]) { const parent = state.termGroups[group.parentUid]; - const newChildren = parent.children.filter((childUid: any) => childUid !== uid); + const newChildren = parent.children.filter((childUid) => childUid !== uid); if (newChildren.length === 1) { // Since we only have one child left, // we can merge the parent and child into one group: @@ -188,7 +188,7 @@ const removeGroup = (state: ImmutableType, uid: string) => { .set('activeSessions', state.activeSessions.without(uid)); }; -const resizeGroup = (state: ImmutableType, uid: any, sizes: number[]) => { +const resizeGroup = (state: ImmutableType, uid: string, sizes: number[]) => { // Make sure none of the sizes fall below MIN_SIZE: if (sizes.find((size) => size < MIN_SIZE)) { return state; diff --git a/lib/utils/notify.ts b/lib/utils/notify.ts index 46855226..bbb246b9 100644 --- a/lib/utils/notify.ts +++ b/lib/utils/notify.ts @@ -1,5 +1,5 @@ /* eslint no-new:0 */ -export default function notify(title: string, body: string, details: Record = {}) { +export default function notify(title: string, body: string, details: {error?: any} = {}) { console.log(`[Notification] ${title}: ${body}`); if (details.error) { console.error(details.error);