port some more files from app/ to ts

This commit is contained in:
Labhansh Agrawal 2020-01-02 20:14:11 +05:30 committed by Benjamin Staneck
parent 9485b3297e
commit 624cd1e6c8
10 changed files with 138 additions and 96 deletions

View file

@ -6,9 +6,32 @@ import win from './config/windows';
import {cfgPath, cfgDir} from './config/paths';
import {getColorMap} from './utils/colors';
const watchers = [];
let cfg = {};
let _watcher;
const watchers: any[] = [];
let cfg: Record<string, any> = {};
let _watcher: fs.FSWatcher;
export const getDeprecatedCSS = (config: Record<string, any>) => {
const deprecated: string[] = [];
const deprecatedCSS = ['x-screen', 'x-row', 'cursor-node', '::selection'];
deprecatedCSS.forEach(css => {
if ((config.css && config.css.includes(css)) || (config.termCSS && config.termCSS.includes(css))) {
deprecated.push(css);
}
});
return deprecated;
};
const checkDeprecatedConfig = () => {
if (!cfg.config) {
return;
}
const deprecated = getDeprecatedCSS(cfg.config);
if (deprecated.length === 0) {
return;
}
const deprecatedStr = deprecated.join(', ');
notify('Configuration warning', `Your configuration uses some deprecated CSS classes (${deprecatedStr})`);
};
const _watch = () => {
if (_watcher) {
@ -36,11 +59,10 @@ const _watch = () => {
} else if (curr.mtime.getTime() !== prev.mtime.getTime()) {
onChange();
}
});
}) as any;
return;
}
// macOS/Linux
setWatcher();
function setWatcher() {
try {
_watcher = fs.watch(cfgPath, eventType => {
@ -61,9 +83,10 @@ const _watch = () => {
console.error('error watching config', error);
});
}
setWatcher();
};
export const subscribe = fn => {
export const subscribe = (fn: Function) => {
watchers.push(fn);
return () => {
watchers.splice(watchers.indexOf(fn), 1);
@ -83,7 +106,7 @@ export const openConfig = () => {
return _openConfig();
};
export const getPlugins = () => {
export const getPlugins = (): {plugins: string[]; localPlugins: string[]} => {
return {
plugins: cfg.plugins,
localPlugins: cfg.localPlugins
@ -104,40 +127,16 @@ export const getWin = win.get;
export const winRecord = win.recordState;
export const windowDefaults = win.defaults;
const getDeprecatedCSS = config => {
const deprecated = [];
const deprecatedCSS = ['x-screen', 'x-row', 'cursor-node', '::selection'];
deprecatedCSS.forEach(css => {
if ((config.css && config.css.includes(css)) || (config.termCSS && config.termCSS.includes(css))) {
deprecated.push(css);
}
});
return deprecated;
};
export {getDeprecatedCSS};
const checkDeprecatedConfig = () => {
if (!cfg.config) {
return;
}
const deprecated = getDeprecatedCSS(cfg.config);
if (deprecated.length === 0) {
return;
}
const deprecatedStr = deprecated.join(', ');
notify('Configuration warning', `Your configuration uses some deprecated CSS classes (${deprecatedStr})`);
};
export const fixConfigDefaults = decoratedConfig => {
const defaultConfig = getDefaultConfig().config;
export const fixConfigDefaults = (decoratedConfig: any) => {
const defaultConfig = getDefaultConfig()?.config;
decoratedConfig.colors = getColorMap(decoratedConfig.colors) || {};
// We must have default colors for xterm css.
decoratedConfig.colors = Object.assign({}, defaultConfig.colors, decoratedConfig.colors);
return decoratedConfig;
};
export const htermConfigTranslate = config => {
const cssReplacements = {
export const htermConfigTranslate = (config: Record<string, any>) => {
const cssReplacements: Record<string, string> = {
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
'.cursor-node([ {.[])': '.terminal-cursor$1',
'::selection([ {.[])': '.terminal .xterm-selection div$1',

View file

@ -1,3 +1,8 @@
declare module 'git-describe' {
export function gitDescribe(...args: any[]): void;
}
declare module 'default-shell' {
const val: string;
export default val;
}

View file

@ -1,12 +1,13 @@
import ms from 'ms';
import fetch from 'electron-fetch';
import {version} from './package';
import {version} from './package.json';
import {BrowserWindow} from 'electron';
const NEWS_URL = 'https://hyper-news.now.sh';
export default function fetchNotifications(win) {
export default function fetchNotifications(win: BrowserWindow) {
const {rpc} = win;
const retry = err => {
const retry = (err?: any) => {
setTimeout(() => fetchNotifications(win), ms('30m'));
if (err) {
//eslint-disable-next-line no-console

View file

@ -2,14 +2,28 @@ import {resolve} from 'path';
import {app, BrowserWindow} from 'electron';
import isDev from 'electron-is-dev';
let win;
let win: BrowserWindow;
// the hack of all hacks
// electron doesn't have a built in notification thing,
// so we launch a window on which we can use the
// HTML5 `Notification` API :'(
let buffer = [];
let buffer: string[][] = [];
function notify(title: string, body = '', details: any = {}) {
//eslint-disable-next-line no-console
console.log(`[Notification] ${title}: ${body}`);
if (details.error) {
//eslint-disable-next-line no-console
console.error(details.error);
}
if (win) {
win.webContents.send('notification', {title, body});
} else {
buffer.push([title, body]);
}
}
app.on('ready', () => {
const win_ = new BrowserWindow({
@ -25,22 +39,8 @@ app.on('ready', () => {
buffer.forEach(([title, body]) => {
notify(title, body);
});
buffer = null;
buffer = [];
});
});
function notify(title, body, details = {}) {
//eslint-disable-next-line no-console
console.log(`[Notification] ${title}: ${body}`);
if (details.error) {
//eslint-disable-next-line no-console
console.error(details.error);
}
if (win) {
win.webContents.send('notification', {title, body});
} else {
buffer.push([title, body]);
}
}
export default notify;

View file

@ -1,4 +1,5 @@
import {app, dialog} from 'electron';
/* eslint-disable @typescript-eslint/no-use-before-define */
import {app, dialog, BrowserWindow, App} from 'electron';
import {resolve, basename} from 'path';
import {writeFileSync} from 'fs';
import Config from 'electron-store';
@ -26,11 +27,11 @@ let paths = getPaths();
let id = getId(plugins);
let modules = requirePlugins();
function getId(plugins_) {
function getId(plugins_: any) {
return JSON.stringify(plugins_);
}
const watchers = [];
const watchers: Function[] = [];
// we listen on configuration updates to trigger
// plugin installation
@ -50,9 +51,10 @@ config.subscribe(() => {
// so plugins can `require` them without needing their own version
// https://github.com/zeit/hyper/issues/619
function patchModuleLoad() {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const Module = require('module');
const originalLoad = Module._load;
Module._load = function _load(modulePath) {
Module._load = function _load(modulePath: string) {
// PLEASE NOTE: Code changes here, also need to be changed in
// lib/utils/plugins.js
switch (modulePath) {
@ -72,6 +74,7 @@ function patchModuleLoad() {
case 'hyper/decorate':
return Object;
default:
// eslint-disable-next-line prefer-rest-params
return originalLoad.apply(this, arguments);
}
};
@ -95,7 +98,7 @@ function updatePlugins({force = false} = {}) {
updating = true;
syncPackageJSON();
const id_ = id;
install(err => {
install((err: any) => {
updating = false;
if (err) {
@ -185,7 +188,10 @@ if (cache.get('hyper.plugins') !== id || process.env.HYPER_FORCE_UPDATE) {
const baseConfig = config.getConfig();
if (baseConfig['autoUpdatePlugins']) {
// otherwise update plugins every 5 hours
setInterval(updatePlugins, ms(baseConfig['autoUpdatePlugins'] === true ? '5h' : baseConfig['autoUpdatePlugins']));
setInterval(
updatePlugins,
ms(baseConfig['autoUpdatePlugins'] === true ? '5h' : (baseConfig['autoUpdatePlugins'] as string))
);
}
})();
@ -210,15 +216,15 @@ function syncPackageJSON() {
}
}
function alert(message) {
function alert(message: string) {
dialog.showMessageBox({
message,
buttons: ['Ok']
});
}
function toDependencies(plugins_) {
const obj = {};
function toDependencies(plugins_: {plugins: string[]}) {
const obj: Record<string, string> = {};
plugins_.plugins.forEach(plugin => {
const regex = /.(@|#)/;
const match = regex.exec(plugin);
@ -237,7 +243,7 @@ function toDependencies(plugins_) {
return obj;
}
export const subscribe = fn => {
export const subscribe = (fn: Function) => {
watchers.push(fn);
return () => {
watchers.splice(watchers.indexOf(fn), 1);
@ -263,11 +269,11 @@ export const getBasePaths = () => {
return {path, localPath};
};
function requirePlugins() {
function requirePlugins(): any[] {
const {plugins: plugins_, localPlugins} = paths;
const load = path_ => {
let mod;
const load = (path_: string) => {
let mod: any;
try {
mod = require(path_);
const exposed = mod && Object.keys(mod).some(key => availableExtensions.has(key));
@ -304,7 +310,7 @@ function requirePlugins() {
.filter(v => Boolean(v));
}
export const onApp = app_ => {
export const onApp = (app_: App) => {
modules.forEach(plugin => {
if (plugin.onApp) {
try {
@ -318,7 +324,7 @@ export const onApp = app_ => {
});
};
export const onWindowClass = win => {
export const onWindowClass = (win: BrowserWindow) => {
modules.forEach(plugin => {
if (plugin.onWindowClass) {
try {
@ -332,7 +338,7 @@ export const onWindowClass = win => {
});
};
export const onWindow = win => {
export const onWindow = (win: BrowserWindow) => {
modules.forEach(plugin => {
if (plugin.onWindow) {
try {
@ -348,7 +354,7 @@ export const onWindow = win => {
// decorates the base entity by calling plugin[key]
// for all the available plugins
function decorateEntity(base, key, type) {
function decorateEntity(base: any, key: string, type: 'object' | 'function') {
let decorated = base;
modules.forEach(plugin => {
if (plugin[key]) {
@ -370,16 +376,16 @@ function decorateEntity(base, key, type) {
return decorated;
}
function decorateObject(base, key) {
function decorateObject(base: any, key: string) {
return decorateEntity(base, key, 'object');
}
function decorateClass(base, key) {
function decorateClass(base: any, key: string) {
return decorateEntity(base, key, 'function');
}
export const getDeprecatedConfig = () => {
const deprecated = {};
const deprecated: Record<string, any> = {};
const baseConfig = config.getConfig();
modules.forEach(plugin => {
if (!plugin.decorateConfig) {
@ -404,11 +410,11 @@ export const getDeprecatedConfig = () => {
return deprecated;
};
export const decorateMenu = tpl => {
export const decorateMenu = (tpl: any) => {
return decorateObject(tpl, 'decorateMenu');
};
export const getDecoratedEnv = baseEnv => {
export const getDecoratedEnv = (baseEnv: Record<string, string>) => {
return decorateObject(baseEnv, 'decorateEnv');
};
@ -427,19 +433,19 @@ export const getDecoratedKeymaps = () => {
return decoratedKeymaps;
};
export const getDecoratedBrowserOptions = defaults => {
export const getDecoratedBrowserOptions = <T>(defaults: T): T => {
return decorateObject(defaults, 'decorateBrowserOptions');
};
export const decorateWindowClass = defaults => {
export const decorateWindowClass = <T>(defaults: T): T => {
return decorateObject(defaults, 'decorateWindowClass');
};
export const decorateSessionOptions = defaults => {
export const decorateSessionOptions = <T>(defaults: T): T => {
return decorateObject(defaults, 'decorateSessionOptions');
};
export const decorateSessionClass = Session => {
export const decorateSessionClass = <T>(Session: T): T => {
return decorateClass(Session, 'decorateSessionClass');
};

View file

@ -2,15 +2,16 @@ import {EventEmitter} from 'events';
import {StringDecoder} from 'string_decoder';
import defaultShell from 'default-shell';
import {getDecoratedEnv} from './plugins';
import {productName, version} from './package';
import {productName, version} from './package.json';
import * as config from './config';
import {IPty, IWindowsPtyForkOptions, spawn as npSpawn} from 'node-pty';
const createNodePtyError = () =>
new Error(
'`node-pty` failed to load. Typically this means that it was built incorrectly. Please check the `readme.md` to more info.'
);
let spawn;
let spawn: typeof npSpawn;
try {
spawn = require('node-pty').spawn;
} catch (err) {
@ -33,7 +34,11 @@ const BATCH_MAX_SIZE = 200 * 1024;
// with the window ID which is then stripped on the renderer process and this
// overhead is reduced with batching.
class DataBatcher extends EventEmitter {
constructor(uid) {
uid: string;
decoder: StringDecoder;
data!: string;
timeout!: NodeJS.Timeout | null;
constructor(uid: string) {
super();
this.uid = uid;
this.decoder = new StringDecoder('utf8');
@ -46,7 +51,7 @@ class DataBatcher extends EventEmitter {
this.timeout = null;
}
write(chunk) {
write(chunk: Buffer) {
if (this.data.length + chunk.length >= BATCH_MAX_SIZE) {
// We've reached the max batch size. Flush it and start another one
if (this.timeout) {
@ -72,8 +77,20 @@ class DataBatcher extends EventEmitter {
}
}
interface SessionOptions {
uid: string;
rows: number;
cols: number;
cwd: string;
shell: string;
shellArgs: string[];
}
export default class Session extends EventEmitter {
constructor(options) {
pty: IPty | null;
batcher: DataBatcher | null;
shell: string | null;
ended: boolean;
constructor(options: SessionOptions) {
super();
this.pty = null;
this.batcher = null;
@ -82,8 +99,9 @@ export default class Session extends EventEmitter {
this.init(options);
}
init({uid, rows, cols: columns, cwd, shell, shellArgs}) {
const osLocale = require('os-locale');
init({uid, rows, cols: columns, cwd, shell, shellArgs}: SessionOptions) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const osLocale = require('os-locale') as typeof import('os-locale');
const baseEnv = Object.assign(
{},
process.env,
@ -106,7 +124,7 @@ export default class Session extends EventEmitter {
const defaultShellArgs = ['--login'];
const options = {
const options: IWindowsPtyForkOptions = {
cols: columns,
rows,
cwd,
@ -133,7 +151,7 @@ export default class Session extends EventEmitter {
if (this.ended) {
return;
}
this.batcher.write(chunk);
this.batcher?.write(chunk as any);
});
this.batcher.on('flush', data => {
@ -154,7 +172,7 @@ export default class Session extends EventEmitter {
this.destroy();
}
write(data) {
write(data: string) {
if (this.pty) {
this.pty.write(data);
} else {
@ -163,7 +181,7 @@ export default class Session extends EventEmitter {
}
}
resize({cols, rows}) {
resize({cols, rows}: {cols: number; rows: number}) {
if (this.pty) {
try {
this.pty.resize(cols, rows);

View file

@ -8,7 +8,7 @@ const regParts = [
{name: 'Icon', value: `${appPath}`}
];
function addValues(hyperKey, commandKey, callback) {
function addValues(hyperKey: Registry.Registry, commandKey: Registry.Registry, callback: Function) {
hyperKey.set(regParts[1].name, Registry.REG_SZ, regParts[1].value, error => {
if (error) {
//eslint-disable-next-line no-console
@ -30,7 +30,7 @@ function addValues(hyperKey, commandKey, callback) {
});
}
export const add = callback => {
export const add = (callback: Function) => {
const hyperKey = new Registry({hive: 'HKCU', key: regKey});
const commandKey = new Registry({
hive: 'HKCU',
@ -78,7 +78,7 @@ export const add = callback => {
});
};
export const remove = callback => {
export const remove = (callback: Function) => {
new Registry({hive: 'HKCU', key: regKey}).destroy(err => {
if (err) {
//eslint-disable-next-line no-console

View file

@ -111,7 +111,7 @@ export function newWindow(
}
});
function createSession(extraOptions = {}) {
function createSession(extraOptions: any = {}) {
const uid = uuid.v4();
// remove the rows and cols, the wrong value of them will break layout when init create

View file

@ -67,6 +67,7 @@
"@babel/preset-react": "7.7.4",
"@babel/preset-typescript": "7.7.7",
"@types/args": "3.0.0",
"@types/async-retry": "1.4.1",
"@types/color": "3.0.0",
"@types/columnify": "^1.5.0",
"@types/electron-devtools-installer": "2.2.0",

View file

@ -596,6 +596,13 @@
resolved "https://registry.yarnpkg.com/@types/args/-/args-3.0.0.tgz#2fd21cfbdaf5e1ed110bd239de42a82330d6ecf6"
integrity sha512-2A817ZtVj1/nD44MV0/U/R6xe3GM2n1WDdni4ioCuLjay6dE0bLJd5RafHC/ddqwXL1xa2RQUdJhsGZKyr3vpA==
"@types/async-retry@1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@types/async-retry/-/async-retry-1.4.1.tgz#3b136a707b7a850f4947a727eb0f7b473b601992"
integrity sha512-hDI5Ttk9SUmDLcD/Yl2VuWQRGYZjJ7aaJFeRlomUOz/iTKSE7yA55SwY87QwjiZgwhMlVAKoT1rl08UyQoheag==
dependencies:
"@types/retry" "*"
"@types/cacheable-request@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976"
@ -773,6 +780,11 @@
dependencies:
"@types/node" "*"
"@types/retry@*":
version "0.12.0"
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
"@types/seamless-immutable@7.1.11":
version "7.1.11"
resolved "https://registry.yarnpkg.com/@types/seamless-immutable/-/seamless-immutable-7.1.11.tgz#89250c3e2587a44c2a051f5798e6f29f0e91bbc9"