add config types

This commit is contained in:
Labhansh Agrawal 2020-04-27 19:02:08 +05:30 committed by Benjamin Staneck
parent b099bb1218
commit 6debd1e7f2
11 changed files with 147 additions and 58 deletions

View file

@ -5,12 +5,13 @@ import _openConfig from './config/open';
import win from './config/windows';
import {cfgPath, cfgDir} from './config/paths';
import {getColorMap} from './utils/colors';
import {parsedConfig, configOptions} from '../lib/config';
const watchers: any[] = [];
let cfg: Record<string, any> = {};
let cfg: parsedConfig = {} as any;
let _watcher: fs.FSWatcher;
export const getDeprecatedCSS = (config: Record<string, any>) => {
export const getDeprecatedCSS = (config: configOptions) => {
const deprecated: string[] = [];
const deprecatedCSS = ['x-screen', 'x-row', 'cursor-node', '::selection'];
deprecatedCSS.forEach((css) => {
@ -124,15 +125,15 @@ export const getWin = win.get;
export const winRecord = win.recordState;
export const windowDefaults = win.defaults;
export const fixConfigDefaults = (decoratedConfig: any) => {
const defaultConfig = getDefaultConfig()?.config;
export const fixConfigDefaults = (decoratedConfig: configOptions) => {
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);
decoratedConfig.colors = {...defaultConfig.colors, ...decoratedConfig.colors};
return decoratedConfig;
};
export const htermConfigTranslate = (config: Record<string, any>) => {
export const htermConfigTranslate = (config: configOptions) => {
const cssReplacements: Record<string, string> = {
'x-screen x-row([ {.[])': '.xterm-rows > div$1',
'.cursor-node([ {.[])': '.terminal-cursor$1',

View file

@ -3,8 +3,9 @@ import {sync as mkdirpSync} from 'mkdirp';
import {defaultCfg, cfgPath, legacyCfgPath, plugs, defaultPlatformKeyPath} from './paths';
import {_init, _extractDefault} from './init';
import notify from '../notify';
import {rawConfig} from '../../lib/config';
let defaultConfig: Record<string, any> | undefined;
let defaultConfig: rawConfig;
const _write = (path: string, data: any) => {
// This method will take text formatted as Unix line endings and transform it
@ -92,41 +93,46 @@ const _importConf = () => {
console.error(err);
}
let defaultCfgRaw = '';
try {
const defaultCfgRaw = readFileSync(defaultCfg, 'utf8');
const _defaultCfg = _extractDefault(defaultCfgRaw);
// Importing platform specific keymap
try {
const content = readFileSync(defaultPlatformKeyPath(), 'utf8');
const mapping = JSON.parse(content) as Record<string, string | string[]>;
_defaultCfg.keymaps = mapping;
} catch (err) {
console.error(err);
}
// Import user config
try {
const userCfg = readFileSync(cfgPath, 'utf8');
return {userCfg, defaultCfg: _defaultCfg};
} catch (err) {
_write(cfgPath, defaultCfgRaw);
return {userCfg: defaultCfgRaw, defaultCfg: _defaultCfg};
}
defaultCfgRaw = readFileSync(defaultCfg, 'utf8');
} catch (err) {
console.log(err);
}
const _defaultCfg = _extractDefault(defaultCfgRaw) as rawConfig;
// Importing platform specific keymap
let content = '{}';
try {
content = readFileSync(defaultPlatformKeyPath(), 'utf8');
} catch (err) {
console.error(err);
}
const mapping = JSON.parse(content) as Record<string, string | string[]>;
_defaultCfg.keymaps = mapping;
// Import user config
let userCfg: string;
try {
userCfg = readFileSync(cfgPath, 'utf8');
} catch (err) {
_write(cfgPath, defaultCfgRaw);
userCfg = defaultCfgRaw;
}
return {userCfg, defaultCfg: _defaultCfg};
};
export const _import = () => {
const imported = _importConf();
defaultConfig = imported?.defaultCfg;
defaultConfig = imported.defaultCfg;
const result = _init(imported!);
return result;
};
export const getDefaultConfig = () => {
if (!defaultConfig) {
defaultConfig = _importConf()?.defaultCfg;
defaultConfig = _importConf().defaultCfg;
}
return defaultConfig;
};

View file

@ -1,6 +1,7 @@
import vm from 'vm';
import notify from '../notify';
import mapKeys from '../utils/map-keys';
import {parsedConfig, rawConfig, configOptions} from '../../lib/config';
const _extract = (script?: vm.Script): Record<string, any> => {
const module: Record<string, any> = {};
@ -24,22 +25,24 @@ const _extractDefault = (cfg: string) => {
};
// init config
const _init = (cfg: {userCfg: string; defaultCfg: Record<string, any>}) => {
const _init = (cfg: {userCfg: string; defaultCfg: rawConfig}): parsedConfig => {
const script = _syntaxValidation(cfg.userCfg);
if (script) {
const _cfg = _extract(script);
if (!_cfg.config) {
notify('Error reading configuration: `config` key is missing');
return cfg.defaultCfg;
}
const _cfg = script && (_extract(script) as rawConfig);
return {
config: (() => {
if (_cfg?.config) {
return _cfg.config;
} else {
notify('Error reading configuration: `config` key is missing');
return cfg.defaultCfg.config || ({} as configOptions);
}
})(),
// Merging platform specific keymaps with user defined keymaps
_cfg.keymaps = mapKeys(Object.assign({}, cfg.defaultCfg.keymaps, _cfg.keymaps));
keymaps: mapKeys({...cfg.defaultCfg.keymaps, ..._cfg?.keymaps}),
// Ignore undefined values in plugin and localPlugins array Issue #1862
_cfg.plugins = (_cfg.plugins && _cfg.plugins.filter(Boolean)) || [];
_cfg.localPlugins = (_cfg.localPlugins && _cfg.localPlugins.filter(Boolean)) || [];
return _cfg;
}
return cfg.defaultCfg;
plugins: (_cfg?.plugins && _cfg.plugins.filter(Boolean)) || [],
localPlugins: (_cfg?.localPlugins && _cfg.localPlugins.filter(Boolean)) || []
};
};
export {_init, _extractDefault};

View file

@ -13,6 +13,7 @@ import {availableExtensions} from './plugins/extensions';
import {install} from './plugins/install';
import {plugs} from './config/paths';
import mapKeys from './utils/map-keys';
import {configOptions} from '../lib/config';
// local storage
const cache = new Config();
@ -187,10 +188,7 @@ 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'] as string))
);
setInterval(updatePlugins, ms(baseConfig['autoUpdatePlugins'] === true ? '5h' : baseConfig['autoUpdatePlugins']));
}
})();
@ -372,7 +370,7 @@ function decorateEntity(base: any, key: string, type: 'object' | 'function') {
return decorated;
}
function decorateObject(base: any, key: string) {
function decorateObject<T>(base: T, key: string): T {
return decorateEntity(base, key, 'object');
}
@ -381,14 +379,14 @@ function decorateClass(base: any, key: string) {
}
export const getDeprecatedConfig = () => {
const deprecated: Record<string, any> = {};
const deprecated: Record<string, {css: string[]}> = {};
const baseConfig = config.getConfig();
modules.forEach((plugin) => {
if (!plugin.decorateConfig) {
return;
}
// We need to clone config in case of plugin modifies config directly.
let configTmp;
let configTmp: configOptions;
try {
configTmp = plugin.decorateConfig(JSON.parse(JSON.stringify(baseConfig)));
} catch (e) {

View file

@ -1,14 +1,15 @@
import {CONFIG_LOAD, CONFIG_RELOAD} from '../constants/config';
import {HyperActions} from '../hyper';
import {configOptions} from '../config';
export function loadConfig(config: any): HyperActions {
export function loadConfig(config: configOptions): HyperActions {
return {
type: CONFIG_LOAD,
config
};
}
export function reloadConfig(config: any): HyperActions {
export function reloadConfig(config: configOptions): HyperActions {
const now = Date.now();
return {
type: CONFIG_RELOAD,

77
lib/config.d.ts vendored Normal file
View file

@ -0,0 +1,77 @@
import {FontWeight} from 'xterm';
export type configOptions = {
autoUpdatePlugins: boolean | string;
backgroundColor: string;
bell: string;
bellSound: string | null;
bellSoundURL: string | null;
borderColor: string;
colors: {
black: string;
blue: string;
cyan: string;
green: string;
lightBlack: string;
lightBlue: string;
lightCyan: string;
lightGreen: string;
lightMagenta: string;
lightRed: string;
lightWhite: string;
lightYellow: string;
magenta: string;
red: string;
white: string;
yellow: string;
};
copyOnSelect: boolean;
css: string;
cursorAccentColor: string;
cursorBlink: boolean;
cursorColor: string;
cursorShape: 'BEAM' | 'UNDERLINE' | 'BLOCK';
defaultSSHApp: boolean;
disableLigatures: boolean;
env: Record<string, string>;
fontFamily: string;
fontSize: number;
fontWeight: FontWeight;
fontWeightBold: FontWeight;
foregroundColor: string;
letterSpacing: number;
lineHeight: number;
macOptionSelectionMode: string;
modifierKeys: {
altIsMeta: boolean;
cmdIsMeta: boolean;
};
padding: string;
quickEdit: boolean;
scrollback: number;
selectionColor: string;
shell: string;
shellArgs: string[];
showHamburgerMenu: boolean | '';
showWindowControls: string;
termCSS: string;
uiFontFamily: string;
updateChannel: 'stable' | 'canary';
useConpty: boolean;
webGLRenderer: boolean;
windowSize: [number, number];
};
export type rawConfig = {
config?: configOptions;
plugins?: string[];
localPlugins?: string[];
keymaps?: Record<string, string | string[]>;
};
export type parsedConfig = {
config: configOptions;
plugins: string[];
localPlugins: string[];
keymaps: Record<string, string[]>;
};

View file

@ -1,15 +1,17 @@
import {configOptions} from '../config';
export const CONFIG_LOAD = 'CONFIG_LOAD';
export const CONFIG_RELOAD = 'CONFIG_RELOAD';
export interface ConfigLoadAction {
type: typeof CONFIG_LOAD;
config: any;
config: configOptions;
now?: number;
}
export interface ConfigReloadAction {
type: typeof CONFIG_RELOAD;
config: any;
config: configOptions;
now: number;
}

2
lib/hyper.d.ts vendored
View file

@ -96,7 +96,7 @@ export type uiState = {
rows: number | null;
scrollback: number;
selectionColor: string;
showHamburgerMenu: string;
showHamburgerMenu: boolean | '';
showWindowControls: string;
termCSS: string;
uiFontFamily: string;

View file

@ -17,6 +17,7 @@ import {addNotificationMessage} from './actions/notifications';
import {loadConfig, reloadConfig} from './actions/config';
import HyperContainer from './containers/hyper';
import configureStore from './store/configure-store';
import {configOptions} from './config';
// On Linux, the default zoom was somehow changed with Electron 3 (or maybe 2).
// Setting zoom factor to 1.2 brings back the normal default size
@ -31,8 +32,8 @@ Object.defineProperty(window, 'rpc', {get: () => rpc});
Object.defineProperty(window, 'config', {get: () => config});
Object.defineProperty(window, 'plugins', {get: () => plugins});
const fetchFileData = (configData: any) => {
const configInfo = Object.assign({}, configData, {bellSound: null});
const fetchFileData = (configData: configOptions) => {
const configInfo: configOptions = {...configData, bellSound: null};
if (!configInfo.bell || configInfo.bell.toUpperCase() !== 'SOUND' || !configInfo.bellSoundURL) {
store_.dispatch(reloadConfig(configInfo));
return;

View file

@ -238,7 +238,7 @@ const reducer = (state = initial, action: HyperActions) => {
ret.modifierKeys = config.modifierKeys;
}
if (allowedHamburgerMenuValues.has(config.showHamburgerMenu)) {
if (allowedHamburgerMenuValues.has(config.showHamburgerMenu as any)) {
ret.showHamburgerMenu = config.showHamburgerMenu;
}

View file

@ -363,10 +363,10 @@ const loadModules = () => {
})
.filter((mod: any) => Boolean(mod));
const deprecatedPlugins: Record<string, any> = plugins.getDeprecatedConfig();
const deprecatedPlugins = plugins.getDeprecatedConfig();
Object.keys(deprecatedPlugins).forEach((name) => {
const {css} = deprecatedPlugins[name];
if (css) {
if (css.length > 0) {
console.warn(`Warning: "${name}" plugin uses some deprecated CSS classes (${css.join(', ')}).`);
}
});