mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-16 05:38:41 -09:00
port some more files from app/ to ts
This commit is contained in:
parent
9485b3297e
commit
624cd1e6c8
10 changed files with 138 additions and 96 deletions
|
|
@ -6,9 +6,32 @@ import win from './config/windows';
|
||||||
import {cfgPath, cfgDir} from './config/paths';
|
import {cfgPath, cfgDir} from './config/paths';
|
||||||
import {getColorMap} from './utils/colors';
|
import {getColorMap} from './utils/colors';
|
||||||
|
|
||||||
const watchers = [];
|
const watchers: any[] = [];
|
||||||
let cfg = {};
|
let cfg: Record<string, any> = {};
|
||||||
let _watcher;
|
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 = () => {
|
const _watch = () => {
|
||||||
if (_watcher) {
|
if (_watcher) {
|
||||||
|
|
@ -36,11 +59,10 @@ const _watch = () => {
|
||||||
} else if (curr.mtime.getTime() !== prev.mtime.getTime()) {
|
} else if (curr.mtime.getTime() !== prev.mtime.getTime()) {
|
||||||
onChange();
|
onChange();
|
||||||
}
|
}
|
||||||
});
|
}) as any;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// macOS/Linux
|
// macOS/Linux
|
||||||
setWatcher();
|
|
||||||
function setWatcher() {
|
function setWatcher() {
|
||||||
try {
|
try {
|
||||||
_watcher = fs.watch(cfgPath, eventType => {
|
_watcher = fs.watch(cfgPath, eventType => {
|
||||||
|
|
@ -61,9 +83,10 @@ const _watch = () => {
|
||||||
console.error('error watching config', error);
|
console.error('error watching config', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
setWatcher();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const subscribe = fn => {
|
export const subscribe = (fn: Function) => {
|
||||||
watchers.push(fn);
|
watchers.push(fn);
|
||||||
return () => {
|
return () => {
|
||||||
watchers.splice(watchers.indexOf(fn), 1);
|
watchers.splice(watchers.indexOf(fn), 1);
|
||||||
|
|
@ -83,7 +106,7 @@ export const openConfig = () => {
|
||||||
return _openConfig();
|
return _openConfig();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPlugins = () => {
|
export const getPlugins = (): {plugins: string[]; localPlugins: string[]} => {
|
||||||
return {
|
return {
|
||||||
plugins: cfg.plugins,
|
plugins: cfg.plugins,
|
||||||
localPlugins: cfg.localPlugins
|
localPlugins: cfg.localPlugins
|
||||||
|
|
@ -104,40 +127,16 @@ export const getWin = win.get;
|
||||||
export const winRecord = win.recordState;
|
export const winRecord = win.recordState;
|
||||||
export const windowDefaults = win.defaults;
|
export const windowDefaults = win.defaults;
|
||||||
|
|
||||||
const getDeprecatedCSS = config => {
|
export const fixConfigDefaults = (decoratedConfig: any) => {
|
||||||
const deprecated = [];
|
const defaultConfig = getDefaultConfig()?.config;
|
||||||
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;
|
|
||||||
decoratedConfig.colors = getColorMap(decoratedConfig.colors) || {};
|
decoratedConfig.colors = getColorMap(decoratedConfig.colors) || {};
|
||||||
// We must have default colors for xterm css.
|
// We must have default colors for xterm css.
|
||||||
decoratedConfig.colors = Object.assign({}, defaultConfig.colors, decoratedConfig.colors);
|
decoratedConfig.colors = Object.assign({}, defaultConfig.colors, decoratedConfig.colors);
|
||||||
return decoratedConfig;
|
return decoratedConfig;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const htermConfigTranslate = config => {
|
export const htermConfigTranslate = (config: Record<string, any>) => {
|
||||||
const cssReplacements = {
|
const cssReplacements: Record<string, string> = {
|
||||||
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
|
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
|
||||||
'.cursor-node([ {.[])': '.terminal-cursor$1',
|
'.cursor-node([ {.[])': '.terminal-cursor$1',
|
||||||
'::selection([ {.[])': '.terminal .xterm-selection div$1',
|
'::selection([ {.[])': '.terminal .xterm-selection div$1',
|
||||||
5
app/ext-modules.d.ts
vendored
5
app/ext-modules.d.ts
vendored
|
|
@ -1,3 +1,8 @@
|
||||||
declare module 'git-describe' {
|
declare module 'git-describe' {
|
||||||
export function gitDescribe(...args: any[]): void;
|
export function gitDescribe(...args: any[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module 'default-shell' {
|
||||||
|
const val: string;
|
||||||
|
export default val;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
import fetch from 'electron-fetch';
|
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';
|
const NEWS_URL = 'https://hyper-news.now.sh';
|
||||||
|
|
||||||
export default function fetchNotifications(win) {
|
export default function fetchNotifications(win: BrowserWindow) {
|
||||||
const {rpc} = win;
|
const {rpc} = win;
|
||||||
const retry = err => {
|
const retry = (err?: any) => {
|
||||||
setTimeout(() => fetchNotifications(win), ms('30m'));
|
setTimeout(() => fetchNotifications(win), ms('30m'));
|
||||||
if (err) {
|
if (err) {
|
||||||
//eslint-disable-next-line no-console
|
//eslint-disable-next-line no-console
|
||||||
|
|
@ -2,14 +2,28 @@ import {resolve} from 'path';
|
||||||
import {app, BrowserWindow} from 'electron';
|
import {app, BrowserWindow} from 'electron';
|
||||||
import isDev from 'electron-is-dev';
|
import isDev from 'electron-is-dev';
|
||||||
|
|
||||||
let win;
|
let win: BrowserWindow;
|
||||||
|
|
||||||
// the hack of all hacks
|
// the hack of all hacks
|
||||||
// electron doesn't have a built in notification thing,
|
// electron doesn't have a built in notification thing,
|
||||||
// so we launch a window on which we can use the
|
// so we launch a window on which we can use the
|
||||||
// HTML5 `Notification` API :'(
|
// 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', () => {
|
app.on('ready', () => {
|
||||||
const win_ = new BrowserWindow({
|
const win_ = new BrowserWindow({
|
||||||
|
|
@ -25,22 +39,8 @@ app.on('ready', () => {
|
||||||
buffer.forEach(([title, body]) => {
|
buffer.forEach(([title, body]) => {
|
||||||
notify(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;
|
export default notify;
|
||||||
|
|
@ -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 {resolve, basename} from 'path';
|
||||||
import {writeFileSync} from 'fs';
|
import {writeFileSync} from 'fs';
|
||||||
import Config from 'electron-store';
|
import Config from 'electron-store';
|
||||||
|
|
@ -26,11 +27,11 @@ let paths = getPaths();
|
||||||
let id = getId(plugins);
|
let id = getId(plugins);
|
||||||
let modules = requirePlugins();
|
let modules = requirePlugins();
|
||||||
|
|
||||||
function getId(plugins_) {
|
function getId(plugins_: any) {
|
||||||
return JSON.stringify(plugins_);
|
return JSON.stringify(plugins_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchers = [];
|
const watchers: Function[] = [];
|
||||||
|
|
||||||
// we listen on configuration updates to trigger
|
// we listen on configuration updates to trigger
|
||||||
// plugin installation
|
// plugin installation
|
||||||
|
|
@ -50,9 +51,10 @@ config.subscribe(() => {
|
||||||
// so plugins can `require` them without needing their own version
|
// so plugins can `require` them without needing their own version
|
||||||
// https://github.com/zeit/hyper/issues/619
|
// https://github.com/zeit/hyper/issues/619
|
||||||
function patchModuleLoad() {
|
function patchModuleLoad() {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const Module = require('module');
|
const Module = require('module');
|
||||||
const originalLoad = Module._load;
|
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
|
// PLEASE NOTE: Code changes here, also need to be changed in
|
||||||
// lib/utils/plugins.js
|
// lib/utils/plugins.js
|
||||||
switch (modulePath) {
|
switch (modulePath) {
|
||||||
|
|
@ -72,6 +74,7 @@ function patchModuleLoad() {
|
||||||
case 'hyper/decorate':
|
case 'hyper/decorate':
|
||||||
return Object;
|
return Object;
|
||||||
default:
|
default:
|
||||||
|
// eslint-disable-next-line prefer-rest-params
|
||||||
return originalLoad.apply(this, arguments);
|
return originalLoad.apply(this, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -95,7 +98,7 @@ function updatePlugins({force = false} = {}) {
|
||||||
updating = true;
|
updating = true;
|
||||||
syncPackageJSON();
|
syncPackageJSON();
|
||||||
const id_ = id;
|
const id_ = id;
|
||||||
install(err => {
|
install((err: any) => {
|
||||||
updating = false;
|
updating = false;
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
@ -185,7 +188,10 @@ if (cache.get('hyper.plugins') !== id || process.env.HYPER_FORCE_UPDATE) {
|
||||||
const baseConfig = config.getConfig();
|
const baseConfig = config.getConfig();
|
||||||
if (baseConfig['autoUpdatePlugins']) {
|
if (baseConfig['autoUpdatePlugins']) {
|
||||||
// otherwise update plugins every 5 hours
|
// 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({
|
dialog.showMessageBox({
|
||||||
message,
|
message,
|
||||||
buttons: ['Ok']
|
buttons: ['Ok']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDependencies(plugins_) {
|
function toDependencies(plugins_: {plugins: string[]}) {
|
||||||
const obj = {};
|
const obj: Record<string, string> = {};
|
||||||
plugins_.plugins.forEach(plugin => {
|
plugins_.plugins.forEach(plugin => {
|
||||||
const regex = /.(@|#)/;
|
const regex = /.(@|#)/;
|
||||||
const match = regex.exec(plugin);
|
const match = regex.exec(plugin);
|
||||||
|
|
@ -237,7 +243,7 @@ function toDependencies(plugins_) {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const subscribe = fn => {
|
export const subscribe = (fn: Function) => {
|
||||||
watchers.push(fn);
|
watchers.push(fn);
|
||||||
return () => {
|
return () => {
|
||||||
watchers.splice(watchers.indexOf(fn), 1);
|
watchers.splice(watchers.indexOf(fn), 1);
|
||||||
|
|
@ -263,11 +269,11 @@ export const getBasePaths = () => {
|
||||||
return {path, localPath};
|
return {path, localPath};
|
||||||
};
|
};
|
||||||
|
|
||||||
function requirePlugins() {
|
function requirePlugins(): any[] {
|
||||||
const {plugins: plugins_, localPlugins} = paths;
|
const {plugins: plugins_, localPlugins} = paths;
|
||||||
|
|
||||||
const load = path_ => {
|
const load = (path_: string) => {
|
||||||
let mod;
|
let mod: any;
|
||||||
try {
|
try {
|
||||||
mod = require(path_);
|
mod = require(path_);
|
||||||
const exposed = mod && Object.keys(mod).some(key => availableExtensions.has(key));
|
const exposed = mod && Object.keys(mod).some(key => availableExtensions.has(key));
|
||||||
|
|
@ -304,7 +310,7 @@ function requirePlugins() {
|
||||||
.filter(v => Boolean(v));
|
.filter(v => Boolean(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
export const onApp = app_ => {
|
export const onApp = (app_: App) => {
|
||||||
modules.forEach(plugin => {
|
modules.forEach(plugin => {
|
||||||
if (plugin.onApp) {
|
if (plugin.onApp) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -318,7 +324,7 @@ export const onApp = app_ => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const onWindowClass = win => {
|
export const onWindowClass = (win: BrowserWindow) => {
|
||||||
modules.forEach(plugin => {
|
modules.forEach(plugin => {
|
||||||
if (plugin.onWindowClass) {
|
if (plugin.onWindowClass) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -332,7 +338,7 @@ export const onWindowClass = win => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const onWindow = win => {
|
export const onWindow = (win: BrowserWindow) => {
|
||||||
modules.forEach(plugin => {
|
modules.forEach(plugin => {
|
||||||
if (plugin.onWindow) {
|
if (plugin.onWindow) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -348,7 +354,7 @@ export const onWindow = win => {
|
||||||
|
|
||||||
// decorates the base entity by calling plugin[key]
|
// decorates the base entity by calling plugin[key]
|
||||||
// for all the available plugins
|
// for all the available plugins
|
||||||
function decorateEntity(base, key, type) {
|
function decorateEntity(base: any, key: string, type: 'object' | 'function') {
|
||||||
let decorated = base;
|
let decorated = base;
|
||||||
modules.forEach(plugin => {
|
modules.forEach(plugin => {
|
||||||
if (plugin[key]) {
|
if (plugin[key]) {
|
||||||
|
|
@ -370,16 +376,16 @@ function decorateEntity(base, key, type) {
|
||||||
return decorated;
|
return decorated;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decorateObject(base, key) {
|
function decorateObject(base: any, key: string) {
|
||||||
return decorateEntity(base, key, 'object');
|
return decorateEntity(base, key, 'object');
|
||||||
}
|
}
|
||||||
|
|
||||||
function decorateClass(base, key) {
|
function decorateClass(base: any, key: string) {
|
||||||
return decorateEntity(base, key, 'function');
|
return decorateEntity(base, key, 'function');
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDeprecatedConfig = () => {
|
export const getDeprecatedConfig = () => {
|
||||||
const deprecated = {};
|
const deprecated: Record<string, any> = {};
|
||||||
const baseConfig = config.getConfig();
|
const baseConfig = config.getConfig();
|
||||||
modules.forEach(plugin => {
|
modules.forEach(plugin => {
|
||||||
if (!plugin.decorateConfig) {
|
if (!plugin.decorateConfig) {
|
||||||
|
|
@ -404,11 +410,11 @@ export const getDeprecatedConfig = () => {
|
||||||
return deprecated;
|
return deprecated;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decorateMenu = tpl => {
|
export const decorateMenu = (tpl: any) => {
|
||||||
return decorateObject(tpl, 'decorateMenu');
|
return decorateObject(tpl, 'decorateMenu');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDecoratedEnv = baseEnv => {
|
export const getDecoratedEnv = (baseEnv: Record<string, string>) => {
|
||||||
return decorateObject(baseEnv, 'decorateEnv');
|
return decorateObject(baseEnv, 'decorateEnv');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -427,19 +433,19 @@ export const getDecoratedKeymaps = () => {
|
||||||
return decoratedKeymaps;
|
return decoratedKeymaps;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDecoratedBrowserOptions = defaults => {
|
export const getDecoratedBrowserOptions = <T>(defaults: T): T => {
|
||||||
return decorateObject(defaults, 'decorateBrowserOptions');
|
return decorateObject(defaults, 'decorateBrowserOptions');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decorateWindowClass = defaults => {
|
export const decorateWindowClass = <T>(defaults: T): T => {
|
||||||
return decorateObject(defaults, 'decorateWindowClass');
|
return decorateObject(defaults, 'decorateWindowClass');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decorateSessionOptions = defaults => {
|
export const decorateSessionOptions = <T>(defaults: T): T => {
|
||||||
return decorateObject(defaults, 'decorateSessionOptions');
|
return decorateObject(defaults, 'decorateSessionOptions');
|
||||||
};
|
};
|
||||||
|
|
||||||
export const decorateSessionClass = Session => {
|
export const decorateSessionClass = <T>(Session: T): T => {
|
||||||
return decorateClass(Session, 'decorateSessionClass');
|
return decorateClass(Session, 'decorateSessionClass');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2,15 +2,16 @@ import {EventEmitter} from 'events';
|
||||||
import {StringDecoder} from 'string_decoder';
|
import {StringDecoder} from 'string_decoder';
|
||||||
import defaultShell from 'default-shell';
|
import defaultShell from 'default-shell';
|
||||||
import {getDecoratedEnv} from './plugins';
|
import {getDecoratedEnv} from './plugins';
|
||||||
import {productName, version} from './package';
|
import {productName, version} from './package.json';
|
||||||
import * as config from './config';
|
import * as config from './config';
|
||||||
|
import {IPty, IWindowsPtyForkOptions, spawn as npSpawn} from 'node-pty';
|
||||||
|
|
||||||
const createNodePtyError = () =>
|
const createNodePtyError = () =>
|
||||||
new Error(
|
new Error(
|
||||||
'`node-pty` failed to load. Typically this means that it was built incorrectly. Please check the `readme.md` to more info.'
|
'`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 {
|
try {
|
||||||
spawn = require('node-pty').spawn;
|
spawn = require('node-pty').spawn;
|
||||||
} catch (err) {
|
} 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
|
// with the window ID which is then stripped on the renderer process and this
|
||||||
// overhead is reduced with batching.
|
// overhead is reduced with batching.
|
||||||
class DataBatcher extends EventEmitter {
|
class DataBatcher extends EventEmitter {
|
||||||
constructor(uid) {
|
uid: string;
|
||||||
|
decoder: StringDecoder;
|
||||||
|
data!: string;
|
||||||
|
timeout!: NodeJS.Timeout | null;
|
||||||
|
constructor(uid: string) {
|
||||||
super();
|
super();
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
this.decoder = new StringDecoder('utf8');
|
this.decoder = new StringDecoder('utf8');
|
||||||
|
|
@ -46,7 +51,7 @@ class DataBatcher extends EventEmitter {
|
||||||
this.timeout = null;
|
this.timeout = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
write(chunk) {
|
write(chunk: Buffer) {
|
||||||
if (this.data.length + chunk.length >= BATCH_MAX_SIZE) {
|
if (this.data.length + chunk.length >= BATCH_MAX_SIZE) {
|
||||||
// We've reached the max batch size. Flush it and start another one
|
// We've reached the max batch size. Flush it and start another one
|
||||||
if (this.timeout) {
|
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 {
|
export default class Session extends EventEmitter {
|
||||||
constructor(options) {
|
pty: IPty | null;
|
||||||
|
batcher: DataBatcher | null;
|
||||||
|
shell: string | null;
|
||||||
|
ended: boolean;
|
||||||
|
constructor(options: SessionOptions) {
|
||||||
super();
|
super();
|
||||||
this.pty = null;
|
this.pty = null;
|
||||||
this.batcher = null;
|
this.batcher = null;
|
||||||
|
|
@ -82,8 +99,9 @@ export default class Session extends EventEmitter {
|
||||||
this.init(options);
|
this.init(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
init({uid, rows, cols: columns, cwd, shell, shellArgs}) {
|
init({uid, rows, cols: columns, cwd, shell, shellArgs}: SessionOptions) {
|
||||||
const osLocale = require('os-locale');
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const osLocale = require('os-locale') as typeof import('os-locale');
|
||||||
const baseEnv = Object.assign(
|
const baseEnv = Object.assign(
|
||||||
{},
|
{},
|
||||||
process.env,
|
process.env,
|
||||||
|
|
@ -106,7 +124,7 @@ export default class Session extends EventEmitter {
|
||||||
|
|
||||||
const defaultShellArgs = ['--login'];
|
const defaultShellArgs = ['--login'];
|
||||||
|
|
||||||
const options = {
|
const options: IWindowsPtyForkOptions = {
|
||||||
cols: columns,
|
cols: columns,
|
||||||
rows,
|
rows,
|
||||||
cwd,
|
cwd,
|
||||||
|
|
@ -133,7 +151,7 @@ export default class Session extends EventEmitter {
|
||||||
if (this.ended) {
|
if (this.ended) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.batcher.write(chunk);
|
this.batcher?.write(chunk as any);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.batcher.on('flush', data => {
|
this.batcher.on('flush', data => {
|
||||||
|
|
@ -154,7 +172,7 @@ export default class Session extends EventEmitter {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
write(data) {
|
write(data: string) {
|
||||||
if (this.pty) {
|
if (this.pty) {
|
||||||
this.pty.write(data);
|
this.pty.write(data);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -163,7 +181,7 @@ export default class Session extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resize({cols, rows}) {
|
resize({cols, rows}: {cols: number; rows: number}) {
|
||||||
if (this.pty) {
|
if (this.pty) {
|
||||||
try {
|
try {
|
||||||
this.pty.resize(cols, rows);
|
this.pty.resize(cols, rows);
|
||||||
|
|
@ -8,7 +8,7 @@ const regParts = [
|
||||||
{name: 'Icon', value: `${appPath}`}
|
{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 => {
|
hyperKey.set(regParts[1].name, Registry.REG_SZ, regParts[1].value, error => {
|
||||||
if (error) {
|
if (error) {
|
||||||
//eslint-disable-next-line no-console
|
//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 hyperKey = new Registry({hive: 'HKCU', key: regKey});
|
||||||
const commandKey = new Registry({
|
const commandKey = new Registry({
|
||||||
hive: 'HKCU',
|
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 => {
|
new Registry({hive: 'HKCU', key: regKey}).destroy(err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
//eslint-disable-next-line no-console
|
//eslint-disable-next-line no-console
|
||||||
|
|
@ -111,7 +111,7 @@ export function newWindow(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function createSession(extraOptions = {}) {
|
function createSession(extraOptions: any = {}) {
|
||||||
const uid = uuid.v4();
|
const uid = uuid.v4();
|
||||||
|
|
||||||
// remove the rows and cols, the wrong value of them will break layout when init create
|
// remove the rows and cols, the wrong value of them will break layout when init create
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
"@babel/preset-react": "7.7.4",
|
"@babel/preset-react": "7.7.4",
|
||||||
"@babel/preset-typescript": "7.7.7",
|
"@babel/preset-typescript": "7.7.7",
|
||||||
"@types/args": "3.0.0",
|
"@types/args": "3.0.0",
|
||||||
|
"@types/async-retry": "1.4.1",
|
||||||
"@types/color": "3.0.0",
|
"@types/color": "3.0.0",
|
||||||
"@types/columnify": "^1.5.0",
|
"@types/columnify": "^1.5.0",
|
||||||
"@types/electron-devtools-installer": "2.2.0",
|
"@types/electron-devtools-installer": "2.2.0",
|
||||||
|
|
|
||||||
12
yarn.lock
12
yarn.lock
|
|
@ -596,6 +596,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/args/-/args-3.0.0.tgz#2fd21cfbdaf5e1ed110bd239de42a82330d6ecf6"
|
resolved "https://registry.yarnpkg.com/@types/args/-/args-3.0.0.tgz#2fd21cfbdaf5e1ed110bd239de42a82330d6ecf6"
|
||||||
integrity sha512-2A817ZtVj1/nD44MV0/U/R6xe3GM2n1WDdni4ioCuLjay6dE0bLJd5RafHC/ddqwXL1xa2RQUdJhsGZKyr3vpA==
|
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":
|
"@types/cacheable-request@^6.0.1":
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976"
|
resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976"
|
||||||
|
|
@ -773,6 +780,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@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":
|
"@types/seamless-immutable@7.1.11":
|
||||||
version "7.1.11"
|
version "7.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/seamless-immutable/-/seamless-immutable-7.1.11.tgz#89250c3e2587a44c2a051f5798e6f29f0e91bbc9"
|
resolved "https://registry.yarnpkg.com/@types/seamless-immutable/-/seamless-immutable-7.1.11.tgz#89250c3e2587a44c2a051f5798e6f29f0e91bbc9"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue