From 181c5230201659a90af55212deb8b75c93482d94 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Wed, 18 Sep 2019 20:56:59 +0200 Subject: [PATCH] strict null checks --- .eslintrc.yml | 1 + app/src/entry.ts | 2 +- app/src/plugins.ts | 4 +- terminus-community-color-schemes/package.json | 2 +- terminus-core/package.json | 2 +- terminus-core/src/api/tabRecovery.ts | 2 +- .../src/api/toolbarButtonProvider.ts | 2 +- .../src/components/appRoot.component.ts | 4 +- .../src/components/baseTab.component.ts | 10 ++--- .../src/components/splitTab.component.ts | 44 ++++++++++++------- .../components/splitTabSpanner.component.ts | 8 ++-- .../src/components/tabHeader.component.ts | 4 +- .../components/windowControls.component.ts | 4 +- terminus-core/src/services/app.service.ts | 10 ++--- terminus-core/src/services/config.service.ts | 4 +- terminus-core/src/services/hostApp.service.ts | 2 +- terminus-core/src/services/hotkeys.service.ts | 4 +- terminus-core/src/services/hotkeys.util.ts | 2 +- .../src/services/shellIntegration.service.ts | 2 +- .../src/services/tabRecovery.service.ts | 2 +- terminus-core/src/services/tabs.service.ts | 2 +- terminus-core/src/services/themes.service.ts | 12 ++--- .../src/services/touchbar.service.ts | 10 +++-- terminus-core/src/tabContextMenu.ts | 4 +- terminus-plugin-manager/package.json | 3 +- .../pluginsSettingsTab.component.pug | 14 +++--- .../pluginsSettingsTab.component.ts | 13 +++--- terminus-plugin-manager/src/index.ts | 2 - terminus-settings/package.json | 9 ++-- .../components/hotkeyInputModal.component.ts | 6 +-- .../src/components/settingsTab.component.pug | 37 ++++++++-------- terminus-settings/src/index.ts | 2 - terminus-settings/src/recoveryProvider.ts | 2 +- terminus-settings/yarn.lock | 6 +-- terminus-ssh/package.json | 2 +- terminus-ssh/src/api.ts | 6 +-- .../editConnectionModal.component.ts | 15 +++++-- .../src/components/sshModal.component.ts | 8 ++-- .../components/sshSettingsTab.component.ts | 8 ++-- terminus-ssh/src/recoveryProvider.ts | 2 +- .../src/services/passwordStorage.service.ts | 2 +- terminus-ssh/src/services/ssh.service.ts | 24 +++++----- terminus-terminal/package.json | 2 +- .../src/api/baseTerminalTab.component.ts | 2 +- terminus-terminal/src/buttonProvider.ts | 2 +- terminus-terminal/src/colorSchemes.ts | 2 +- .../appearanceSettingsTab.component.ts | 4 +- .../components/shellSettingsTab.component.ts | 5 ++- .../terminalSettingsTab.component.ts | 2 +- .../src/components/terminalTab.component.ts | 2 +- terminus-terminal/src/frontends/hterm.ts | 6 +-- .../src/frontends/htermFrontend.ts | 2 +- .../src/frontends/xtermFrontend.ts | 6 +-- terminus-terminal/src/index.ts | 2 +- terminus-terminal/src/pathDrop.ts | 2 +- terminus-terminal/src/recoveryProvider.ts | 2 +- .../src/services/dockMenu.service.ts | 2 +- .../src/services/sessions.service.ts | 16 +++---- .../src/services/terminal.service.ts | 4 +- .../src/services/terminalFrontend.service.ts | 2 +- terminus-terminal/src/shells/linuxDefault.ts | 2 +- tsconfig.json | 1 + 62 files changed, 202 insertions(+), 170 deletions(-) diff --git a/.eslintrc.yml b/.eslintrc.yml index 5ce21888..a684a72a 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -92,3 +92,4 @@ rules: - error - single - allowTemplateLiterals: true + '@typescript-eslint/no-non-null-assertion': off diff --git a/app/src/entry.ts b/app/src/entry.ts index b3313e16..46244755 100644 --- a/app/src/entry.ts +++ b/app/src/entry.ts @@ -19,7 +19,7 @@ location.hash = '' ;(process as any).enablePromiseAPI = true if (process.platform === 'win32' && !('HOME' in process.env)) { - process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH + process.env.HOME = `${process.env.HOMEDRIVE}${process.env.HOMEPATH}` } if (isDev) { diff --git a/app/src/plugins.ts b/app/src/plugins.ts index dc7c1ce0..b17a9cac 100644 --- a/app/src/plugins.ts +++ b/app/src/plugins.ts @@ -156,7 +156,9 @@ export async function findPlugins (): Promise { } } - (window as any).installedPlugins = foundPlugins + foundPlugins.sort((a, b) => a.name > b.name ? 1 : -1) + + ;(window as any).installedPlugins = foundPlugins return foundPlugins } diff --git a/terminus-community-color-schemes/package.json b/terminus-community-color-schemes/package.json index 29ad5fd4..ebd5f0a6 100644 --- a/terminus-community-color-schemes/package.json +++ b/terminus-community-color-schemes/package.json @@ -1,6 +1,6 @@ { "name": "terminus-community-color-schemes", - "version": "1.0.83-nightly.0", + "version": "1.0.92-nightly.0", "description": "Community color schemes for Terminus", "keywords": [ "terminus-builtin-plugin" diff --git a/terminus-core/package.json b/terminus-core/package.json index 87b897fa..e5e29f13 100644 --- a/terminus-core/package.json +++ b/terminus-core/package.json @@ -1,6 +1,6 @@ { "name": "terminus-core", - "version": "1.0.83-nightly.4", + "version": "1.0.92-nightly.0", "description": "Terminus core", "keywords": [ "terminus-builtin-plugin" diff --git a/terminus-core/src/api/tabRecovery.ts b/terminus-core/src/api/tabRecovery.ts index 63e7ec82..b1d1268f 100644 --- a/terminus-core/src/api/tabRecovery.ts +++ b/terminus-core/src/api/tabRecovery.ts @@ -34,5 +34,5 @@ export abstract class TabRecoveryProvider { * @returns [[RecoveredTab]] descriptor containing tab type and component inputs * or `null` if this token is from a different tab type or is not supported */ - abstract async recover (recoveryToken: any): Promise + abstract async recover (recoveryToken: any): Promise } diff --git a/terminus-core/src/api/toolbarButtonProvider.ts b/terminus-core/src/api/toolbarButtonProvider.ts index b2fa9f85..a30b9987 100644 --- a/terminus-core/src/api/toolbarButtonProvider.ts +++ b/terminus-core/src/api/toolbarButtonProvider.ts @@ -5,7 +5,7 @@ export interface ToolbarButton { /** * Raw SVG icon code */ - icon: string + icon?: string title: string diff --git a/terminus-core/src/components/appRoot.component.ts b/terminus-core/src/components/appRoot.component.ts index ebef17cd..3aa03de3 100644 --- a/terminus-core/src/components/appRoot.component.ts +++ b/terminus-core/src/components/appRoot.component.ts @@ -144,7 +144,7 @@ export class AppRootComponent { config.changed$.subscribe(() => this.updateVibrancy()) this.updateVibrancy() - let lastProgress = null + let lastProgress: number|null = null this.app.tabOpened$.subscribe(tab => { this.unsortedTabs.push(tab) tab.progress$.subscribe(progress => { @@ -258,7 +258,7 @@ export class AppRootComponent { buttons = buttons.concat(provider.provide()) }) return buttons - .filter(button => button.weight > 0 === aboveZero) + .filter(button => (button.weight || 0) > 0 === aboveZero) .sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0)) } diff --git a/terminus-core/src/components/baseTab.component.ts b/terminus-core/src/components/baseTab.component.ts index 8b4eb942..62e8cba1 100644 --- a/terminus-core/src/components/baseTab.component.ts +++ b/terminus-core/src/components/baseTab.component.ts @@ -36,7 +36,7 @@ export abstract class BaseTabComponent { /** * CSS color override for the tab's header */ - color: string = null + color: string|null = null protected hasFocus = false @@ -50,14 +50,14 @@ export abstract class BaseTabComponent { private titleChange = new Subject() private focused = new Subject() private blurred = new Subject() - private progress = new Subject() + private progress = new Subject() private activity = new Subject() private destroyed = new Subject() get focused$ (): Observable { return this.focused } get blurred$ (): Observable { return this.blurred } get titleChange$ (): Observable { return this.titleChange } - get progress$ (): Observable { return this.progress } + get progress$ (): Observable { return this.progress } get activity$ (): Observable { return this.activity } get destroyed$ (): Observable { return this.destroyed } get recoveryStateChangedHint$ (): Observable { return this.recoveryStateChangedHint } @@ -83,7 +83,7 @@ export abstract class BaseTabComponent { * * @param {type} progress: value between 0 and 1, or `null` to remove */ - setProgress (progress: number) { + setProgress (progress: number|null) { this.progress.next(progress) if (progress) { if (this.progressClearTimeout) { @@ -125,7 +125,7 @@ export abstract class BaseTabComponent { /** * Override this to enable task completion notifications for the tab */ - async getCurrentProcess (): Promise { + async getCurrentProcess (): Promise { return null } diff --git a/terminus-core/src/components/splitTab.component.ts b/terminus-core/src/components/splitTab.component.ts index 71582de2..be571971 100644 --- a/terminus-core/src/components/splitTab.component.ts +++ b/terminus-core/src/components/splitTab.component.ts @@ -33,8 +33,8 @@ export class SplitContainer { /** * @return Flat list of all tabs inside this container */ - getAllTabs () { - let r = [] + getAllTabs (): BaseTabComponent[] { + let r: BaseTabComponent[] = [] for (const child of this.children) { if (child instanceof SplitContainer) { r = r.concat(child.getAllTabs()) @@ -94,7 +94,7 @@ export class SplitContainer { } async serialize () { - const children = [] + const children: any[] = [] for (const child of this.children) { if (child instanceof SplitContainer) { children.push(await child.serialize()) @@ -292,9 +292,9 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes /** * Inserts a new `tab` to the `side` of the `relative` tab */ - addTab (tab: BaseTabComponent, relative: BaseTabComponent, side: SplitDirection) { - let target = this.getParentOf(relative) || this.root - let insertIndex = target.children.indexOf(relative) + addTab (tab: BaseTabComponent, relative: BaseTabComponent|null, side: SplitDirection) { + let target = (relative ? this.getParentOf(relative) : null) || this.root + let insertIndex = relative ? target.children.indexOf(relative) : -1 if ( target.orientation === 'v' && ['l', 'r'].includes(side) || @@ -302,7 +302,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes ) { const newContainer = new SplitContainer() newContainer.orientation = target.orientation === 'v' ? 'h' : 'v' - newContainer.children = [relative] + newContainer.children = relative ? [relative] : [] newContainer.ratios = [1] target.children[insertIndex] = newContainer target = newContainer @@ -333,6 +333,9 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes removeTab (tab: BaseTabComponent) { const parent = this.getParentOf(tab) + if (!parent) { + return + } const index = parent.children.indexOf(tab) parent.ratios.splice(index, 1) parent.children.splice(index, 1) @@ -356,11 +359,18 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes navigate (dir: SplitDirection) { let rel: BaseTabComponent | SplitContainer = this.focusedTab let parent = this.getParentOf(rel) + if (!parent) { + return + } + const orientation = ['l', 'r'].includes(dir) ? 'h' : 'v' while (parent !== this.root && parent.orientation !== orientation) { rel = parent parent = this.getParentOf(rel) + if (!parent) { + return + } } if (parent.orientation !== orientation) { @@ -381,13 +391,15 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes async splitTab (tab: BaseTabComponent, dir: SplitDirection) { const newTab = await this.tabsService.duplicate(tab) - this.addTab(newTab, tab, dir) + if (newTab) { + this.addTab(newTab, tab, dir) + } } /** * @returns the immediate parent of `tab` */ - getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer { + getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer|null { root = root || this.root for (const child of root.children) { if (child instanceof SplitContainer) { @@ -414,8 +426,8 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes } /** @hidden */ - async getCurrentProcess (): Promise { - return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) + async getCurrentProcess (): Promise { + return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x) || null } /** @hidden */ @@ -443,8 +455,10 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes private detachTabView (tab: BaseTabComponent) { const ref = this.viewRefs.get(tab) - this.viewRefs.delete(tab) - this.viewContainer.remove(this.viewContainer.indexOf(ref)) + if (ref) { + this.viewRefs.delete(tab) + this.viewContainer.remove(this.viewContainer.indexOf(ref)) + } } private layout () { @@ -471,7 +485,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes if (child instanceof SplitContainer) { this.layoutInternal(child, childX, childY, childW, childH) } else { - const element = this.viewRefs.get(child).rootNodes[0] + const element = this.viewRefs.get(child)!.rootNodes[0] element.style.position = 'absolute' element.style.left = `${childX}%` element.style.top = `${childY}%` @@ -518,7 +532,7 @@ export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDes /** @hidden */ @Injectable() export class SplitTabRecoveryProvider extends TabRecoveryProvider { - async recover (recoveryToken: any): Promise { + async recover (recoveryToken: any): Promise { if (recoveryToken && recoveryToken.type === 'app:split-tab') { return { type: SplitTabComponent, diff --git a/terminus-core/src/components/splitTabSpanner.component.ts b/terminus-core/src/components/splitTabSpanner.component.ts index af53be27..8319acfe 100644 --- a/terminus-core/src/components/splitTabSpanner.component.ts +++ b/terminus-core/src/components/splitTabSpanner.component.ts @@ -67,13 +67,13 @@ export class SplitTabSpannerComponent { this.container.x, this.container.y + this.container.h * this.container.getOffsetRatio(this.index), this.container.w, - null + 0 ) } else { this.setDimensions( this.container.x + this.container.w * this.container.getOffsetRatio(this.index), this.container.y, - null, + 0, this.container.h ) } @@ -82,7 +82,7 @@ export class SplitTabSpannerComponent { private setDimensions (x: number, y: number, w: number, h: number) { this.cssLeft = `${x}%` this.cssTop = `${y}%` - this.cssWidth = w ? `${w}%` : null - this.cssHeight = h ? `${h}%` : null + this.cssWidth = w ? `${w}%` : 'initial' + this.cssHeight = h ? `${h}%` : 'initial' } } diff --git a/terminus-core/src/components/tabHeader.component.ts b/terminus-core/src/components/tabHeader.component.ts index 62fd40bc..e418d406 100644 --- a/terminus-core/src/components/tabHeader.component.ts +++ b/terminus-core/src/components/tabHeader.component.ts @@ -25,7 +25,7 @@ export class TabHeaderComponent { @Input() @HostBinding('class.active') active: boolean @Input() @HostBinding('class.has-activity') hasActivity: boolean @Input() tab: BaseTabComponent - @Input() progress: number + @Input() progress: number|null @ViewChild('handle') handle: ElementRef private constructor ( @@ -83,7 +83,7 @@ export class TabHeaderComponent { this.app.closeTab(this.tab, true) } if ($event.which === 3) { - event.preventDefault() + $event.preventDefault() const contextMenu = this.electron.remote.Menu.buildFromTemplate(await this.buildContextMenu()) diff --git a/terminus-core/src/components/windowControls.component.ts b/terminus-core/src/components/windowControls.component.ts index e99d58ed..48875ffd 100644 --- a/terminus-core/src/components/windowControls.component.ts +++ b/terminus-core/src/components/windowControls.component.ts @@ -12,6 +12,8 @@ export class WindowControlsComponent { constructor (public hostApp: HostAppService, public app: AppService) { } async closeWindow () { - await this.app.closeAllTabs() && this.hostApp.closeWindow() + if (await this.app.closeAllTabs()) { + this.hostApp.closeWindow() + } } } diff --git a/terminus-core/src/services/app.service.ts b/terminus-core/src/services/app.service.ts index 4ad4d3e3..7e6ea370 100644 --- a/terminus-core/src/services/app.service.ts +++ b/terminus-core/src/services/app.service.ts @@ -25,14 +25,14 @@ class CompletionObserver { async tick () { if (!await this.tab.getCurrentProcess()) { - this.done.next(null) + this.done.next() this.stop() } } stop () { clearInterval(this.interval) - this.destroyed.next(null) + this.destroyed.next() this.destroyed.complete() this.done.complete() } @@ -144,7 +144,7 @@ export class AppService { if (this.tabs.includes(this._activeTab)) { this.lastTabIndex = this.tabs.indexOf(this._activeTab) } else { - this.lastTabIndex = null + this.lastTabIndex = 0 } if (this._activeTab) { this._activeTab.clearActivity() @@ -229,7 +229,7 @@ export class AppService { /** @hidden */ emitReady () { - this.ready.next(null) + this.ready.next() this.ready.complete() this.hostApp.emitReady() } @@ -246,7 +246,7 @@ export class AppService { }) this.completionObservers.set(tab, observer) } - return this.completionObservers.get(tab).done$ + return this.completionObservers.get(tab)!.done$ } stopObservingTabCompletion (tab: BaseTabComponent) { diff --git a/terminus-core/src/services/config.service.ts b/terminus-core/src/services/config.service.ts index f74b55fb..013dcff4 100644 --- a/terminus-core/src/services/config.service.ts +++ b/terminus-core/src/services/config.service.ts @@ -95,7 +95,7 @@ export class ConfigService { private changed = new Subject() private _store: any private defaults: any - private servicesCache: { [id: string]: Function[] } = null + private servicesCache: { [id: string]: Function[] }|null = null get changed$ (): Observable { return this.changed } @@ -170,7 +170,7 @@ export class ConfigService { * * @typeparam T Base provider type */ - enabledServices (services: T[]): T[] { + enabledServices (services: T[]): T[] { if (!this.servicesCache) { this.servicesCache = {} const ngModule = window['rootModule'].ngInjectorDef diff --git a/terminus-core/src/services/hostApp.service.ts b/terminus-core/src/services/hostApp.service.ts index 6ccdd997..218bc2af 100644 --- a/terminus-core/src/services/hostApp.service.ts +++ b/terminus-core/src/services/hostApp.service.ts @@ -215,7 +215,7 @@ export class HostAppService { setVibrancy (enable: boolean, type: string) { document.body.classList.toggle('vibrant', enable) if (this.platform === Platform.macOS) { - this.getWindow().setVibrancy(enable ? 'dark' : null) + this.getWindow().setVibrancy(enable ? 'dark' : null as any) // electron issue 20269 } if (this.platform === Platform.Windows) { this.electron.ipcRenderer.send('window-set-vibrancy', enable, type) diff --git a/terminus-core/src/services/hotkeys.service.ts b/terminus-core/src/services/hotkeys.service.ts index b2e7120c..aa757882 100644 --- a/terminus-core/src/services/hotkeys.service.ts +++ b/terminus-core/src/services/hotkeys.service.ts @@ -93,7 +93,7 @@ export class HotkeysService { return stringifyKeySequence(this.currentKeystrokes.map(x => x.event)) } - getCurrentFullyMatchedHotkey (): string { + getCurrentFullyMatchedHotkey (): string|null { const currentStrokes = this.getCurrentKeystrokes() const config = this.getHotkeysConfig() for (const id in config) { @@ -116,7 +116,7 @@ export class HotkeysService { getCurrentPartiallyMatchedHotkeys (): PartialHotkeyMatch[] { const currentStrokes = this.getCurrentKeystrokes() const config = this.getHotkeysConfig() - const result = [] + const result: PartialHotkeyMatch[] = [] for (const id in config) { for (const sequence of config[id]) { for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) { diff --git a/terminus-core/src/services/hotkeys.util.ts b/terminus-core/src/services/hotkeys.util.ts index ca121244..72d4ecf6 100644 --- a/terminus-core/src/services/hotkeys.util.ts +++ b/terminus-core/src/services/hotkeys.util.ts @@ -15,7 +15,7 @@ export function stringifyKeySequence (events: KeyboardEvent[]): string[] { events = events.slice() while (events.length > 0) { - const event = events.shift() + const event = events.shift()! if ((event as any).event === 'keydown') { const itemKeys: string[] = [] if (event.ctrlKey) { diff --git a/terminus-core/src/services/shellIntegration.service.ts b/terminus-core/src/services/shellIntegration.service.ts index 2078c626..0c85362d 100644 --- a/terminus-core/src/services/shellIntegration.service.ts +++ b/terminus-core/src/services/shellIntegration.service.ts @@ -37,7 +37,7 @@ export class ShellIntegrationService { 'extras', 'automator-workflows', ) - this.automatorWorkflowsDestination = path.join(process.env.HOME, 'Library', 'Services') + this.automatorWorkflowsDestination = path.join(process.env.HOME as string, 'Library', 'Services') } this.updatePaths() } diff --git a/terminus-core/src/services/tabRecovery.service.ts b/terminus-core/src/services/tabRecovery.service.ts index 47fdcf7e..4a7b21c0 100644 --- a/terminus-core/src/services/tabRecovery.service.ts +++ b/terminus-core/src/services/tabRecovery.service.ts @@ -27,7 +27,7 @@ export class TabRecoveryService { ) } - async recoverTab (token: any): Promise { + async recoverTab (token: any): Promise { for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) { try { const tab = await provider.recover(token) diff --git a/terminus-core/src/services/tabs.service.ts b/terminus-core/src/services/tabs.service.ts index 90e752e6..992dafe8 100644 --- a/terminus-core/src/services/tabs.service.ts +++ b/terminus-core/src/services/tabs.service.ts @@ -29,7 +29,7 @@ export class TabsService { /** * Duplicates an existing tab instance (using the tab recovery system) */ - async duplicate (tab: BaseTabComponent): Promise { + async duplicate (tab: BaseTabComponent): Promise { const token = await tab.getRecoveryToken() if (!token) { return null diff --git a/terminus-core/src/services/themes.service.ts b/terminus-core/src/services/themes.service.ts index 24edea10..1a5ee765 100644 --- a/terminus-core/src/services/themes.service.ts +++ b/terminus-core/src/services/themes.service.ts @@ -4,7 +4,7 @@ import { Theme } from '../api/theme' @Injectable({ providedIn: 'root' }) export class ThemesService { - private styleElement: HTMLElement = null + private styleElement: HTMLElement|null = null /** @hidden */ constructor ( @@ -17,22 +17,22 @@ export class ThemesService { }) } - findTheme (name: string): Theme { - return this.config.enabledServices(this.themes).find(x => x.name === name) + findTheme (name: string): Theme|null { + return this.config.enabledServices(this.themes).find(x => x.name === name) || null } findCurrentTheme (): Theme { - return this.findTheme(this.config.store.appearance.theme) || this.findTheme('Standard') + return this.findTheme(this.config.store.appearance.theme) || this.findTheme('Standard')! } applyTheme (theme: Theme): void { if (!this.styleElement) { this.styleElement = document.createElement('style') this.styleElement.setAttribute('id', 'theme') - document.querySelector('head').appendChild(this.styleElement) + document.querySelector('head')!.appendChild(this.styleElement) } this.styleElement.textContent = theme.css - document.querySelector('style#custom-css').innerHTML = this.config.store.appearance.css + document.querySelector('style#custom-css')!.innerHTML = this.config.store.appearance.css } private applyCurrentTheme (): void { diff --git a/terminus-core/src/services/touchbar.service.ts b/terminus-core/src/services/touchbar.service.ts index 10261200..f96c8e71 100644 --- a/terminus-core/src/services/touchbar.service.ts +++ b/terminus-core/src/services/touchbar.service.ts @@ -42,7 +42,7 @@ export class TouchbarService { const showIcon = this.app.activeTab !== tab && hasActivity const segment = this.tabSegments[app.tabs.indexOf(tab)] if (segment) { - segment.icon = showIcon ? activityIcon : null + segment.icon = showIcon ? activityIcon : undefined } }) }) @@ -83,7 +83,9 @@ export class TouchbarService { segments: buttons.map(button => this.getButton(button)), mode: 'buttons', change: (selectedIndex) => this.zone.run(() => { - buttons[selectedIndex].click() + if (buttons[selectedIndex].click) { + buttons[selectedIndex].click!() + } }), }) @@ -100,8 +102,8 @@ export class TouchbarService { private getButton (button: ToolbarButton): Electron.SegmentedControlSegment { return { - label: button.touchBarNSImage ? null : this.shortenTitle(button.touchBarTitle || button.title), - icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : null, + label: button.touchBarNSImage ? undefined : this.shortenTitle(button.touchBarTitle || button.title), + icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : undefined, // click: () => this.zone.run(() => button.click()), } } diff --git a/terminus-core/src/tabContextMenu.ts b/terminus-core/src/tabContextMenu.ts index f8894ee7..9708a198 100644 --- a/terminus-core/src/tabContextMenu.ts +++ b/terminus-core/src/tabContextMenu.ts @@ -78,7 +78,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider { return [ { label: 'Rename', - click: () => this.zone.run(() => tabHeader.showRenameTabModal()), + click: () => this.zone.run(() => tabHeader && tabHeader.showRenameTabModal()), }, { label: 'Duplicate', @@ -86,7 +86,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider { }, { label: 'Color', - sublabel: COLORS.find(x => x.value === tab.color).name, + sublabel: COLORS.find(x => x.value === tab.color)!.name, submenu: COLORS.map(color => ({ label: color.name, type: 'radio', diff --git a/terminus-plugin-manager/package.json b/terminus-plugin-manager/package.json index d71c6467..b57ad508 100644 --- a/terminus-plugin-manager/package.json +++ b/terminus-plugin-manager/package.json @@ -1,6 +1,6 @@ { "name": "terminus-plugin-manager", - "version": "1.0.83-nightly.0", + "version": "1.0.92-nightly.0", "description": "Terminus' plugin manager", "keywords": [ "terminus-builtin-plugin" @@ -20,7 +20,6 @@ "@types/semver": "^6.0.0", "axios": "^0.19.0", "mz": "^2.6.0", - "ngx-pipes": "^1.6.1", "semver": "^6.1.0" }, "peerDependencies": { diff --git a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug index de6378a8..6dcd1a69 100644 --- a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug +++ b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug @@ -8,9 +8,9 @@ button.btn.btn-outline-info.btn-sm.ml-auto((click)='openPluginsFolder()') i.fas.fa-folder span Plugins folder - + .list-group.list-group-flush.mt-2 - .list-group-item.d-flex.align-items-center(*ngFor='let plugin of pluginManager.installedPlugins|orderBy:"name"') + .list-group-item.d-flex.align-items-center(*ngFor='let plugin of pluginManager.installedPlugins') .mr-auto.d-flex.flex-column div strong {{plugin.name}} @@ -33,15 +33,15 @@ (click)='enablePlugin(plugin)' ) i.fas.fa-fw.fa-play - + button.btn.btn-secondary.ml-2( *ngIf='!config.store.pluginBlacklist.includes(plugin.name)', (click)='disablePlugin(plugin)' ) i.fas.fa-fw.fa-pause - + button.btn.btn-danger.ml-2( - (click)='uninstallPlugin(plugin)', + (click)='uninstallPlugin(plugin)', *ngIf='!plugin.isBuiltin', [disabled]='busy[plugin.name] != undefined' ) @@ -65,7 +65,7 @@ div .list-group.list-group-flush.mb-4(*ngIf='availablePlugins$') - ng-container(*ngFor='let plugin of (availablePlugins$|async|orderBy:"name")') + ng-container(*ngFor='let plugin of (availablePlugins$|async)') .list-group-item.d-flex.align-items-center(*ngIf='!isAlreadyInstalled(plugin)') button.btn.btn-primary.mr-3( (click)='installPlugin(plugin)', @@ -73,7 +73,7 @@ div ) i.fas.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing') i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing') - + div((click)='showPluginInfo(plugin)') div strong {{plugin.name}} diff --git a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts index a80ddffb..041544eb 100644 --- a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts +++ b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts @@ -1,5 +1,5 @@ import { BehaviorSubject, Observable } from 'rxjs' -import { debounceTime, distinctUntilChanged, first, tap, flatMap } from 'rxjs/operators' +import { debounceTime, distinctUntilChanged, first, tap, flatMap, map } from 'rxjs/operators' import * as semver from 'semver' import { Component, Input } from '@angular/core' @@ -18,7 +18,7 @@ export class PluginsSettingsTabComponent { @Input() availablePlugins$: Observable @Input() availablePluginsQuery$ = new BehaviorSubject('') @Input() availablePluginsReady = false - @Input() knownUpgrades: {[id: string]: PluginInfo} = {} + @Input() knownUpgrades: {[id: string]: PluginInfo|null} = {} @Input() busy: {[id: string]: BusyState} = {} @Input() erroredPlugin: string @Input() errorMessage: string @@ -43,9 +43,12 @@ export class PluginsSettingsTabComponent { })) }) ) - this.availablePlugins$.pipe(first()).subscribe(available => { + this.availablePlugins$.pipe(first(), map((plugins: PluginInfo[]) => { + plugins.sort((a, b) => a.name > b.name ? 1 : -1) + return plugins + })).subscribe(available => { for (const plugin of this.pluginManager.installedPlugins) { - this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version)) + this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version)) || null } }) } @@ -91,7 +94,7 @@ export class PluginsSettingsTabComponent { } async upgradePlugin (plugin: PluginInfo): Promise { - return this.installPlugin(this.knownUpgrades[plugin.name]) + return this.installPlugin(this.knownUpgrades[plugin.name]!) } showPluginInfo (plugin: PluginInfo) { diff --git a/terminus-plugin-manager/src/index.ts b/terminus-plugin-manager/src/index.ts index 14da0428..fb49c226 100644 --- a/terminus-plugin-manager/src/index.ts +++ b/terminus-plugin-manager/src/index.ts @@ -1,7 +1,6 @@ import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' -import { NgPipesModule } from 'ngx-pipes' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { SettingsTabProvider } from 'terminus-settings' @@ -15,7 +14,6 @@ import { PluginsSettingsTabProvider } from './settings' BrowserModule, FormsModule, NgbModule, - NgPipesModule, ], providers: [ { provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true }, diff --git a/terminus-settings/package.json b/terminus-settings/package.json index 10a3c72c..21bcc942 100644 --- a/terminus-settings/package.json +++ b/terminus-settings/package.json @@ -1,6 +1,6 @@ { "name": "terminus-settings", - "version": "1.0.83-nightly.4", + "version": "1.0.92-nightly.0", "description": "Terminus terminal settings page", "keywords": [ "terminus-builtin-plugin" @@ -17,8 +17,7 @@ "author": "Eugene Pankov", "license": "MIT", "devDependencies": { - "@types/deep-equal": "1.0.1", - "ngx-pipes": "^1.6.1" + "@types/deep-equal": "1.0.1" }, "peerDependencies": { "@angular/common": "^7", @@ -26,7 +25,7 @@ "@angular/forms": "^7", "@angular/platform-browser": "^7", "@ng-bootstrap/ng-bootstrap": "^1", - "terminus-core": "*", - "rxjs": "^5" + "rxjs": "^5", + "terminus-core": "*" } } diff --git a/terminus-settings/src/components/hotkeyInputModal.component.ts b/terminus-settings/src/components/hotkeyInputModal.component.ts index b5ee061d..abd10174 100644 --- a/terminus-settings/src/components/hotkeyInputModal.component.ts +++ b/terminus-settings/src/components/hotkeyInputModal.component.ts @@ -41,8 +41,8 @@ export class HotkeyInputModalComponent { @Input() timeoutProgress = 0 private keySubscription: Subscription - private lastKeyEvent: number - private keyTimeoutInterval: number = null + private lastKeyEvent: number|null = null + private keyTimeoutInterval: number|null = null constructor ( private modalInstance: NgbActiveModal, @@ -78,7 +78,7 @@ export class HotkeyInputModalComponent { this.keySubscription.unsubscribe() this.hotkeys.clearCurrentKeystrokes() this.hotkeys.enable() - clearInterval(this.keyTimeoutInterval) + clearInterval(this.keyTimeoutInterval!) } close () { diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug index 06e0f3ca..238edcec 100644 --- a/terminus-settings/src/components/settingsTab.component.pug +++ b/terminus-settings/src/components/settingsTab.component.pug @@ -8,14 +8,14 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') ng-template(ngbTabContent) .d-flex.align-items-center.mb-4 h1.terminus-title.mb-2.mr-2 Terminus - sup α - + sup α + .text-muted.mr-auto {{homeBase.appVersion}} - + button.btn.btn-secondary.mr-3((click)='homeBase.openGitHub()') i.fab.fa-github span GitHub - + button.btn.btn-secondary((click)='homeBase.reportBug()') i.fas.fa-bug span Report a problem @@ -57,7 +57,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') .title(*ngIf='hostApp.platform === Platform.Windows') Acrylic background .title(*ngIf='hostApp.platform === Platform.macOS') Vibrancy .description Gives the window a blurred transparent background - + toggle( [(ngModel)]='config.store.appearance.vibrancy', (ngModelChange)='config.save()' @@ -85,7 +85,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') [value]='"fluent"' ) | Fluent - + .form-line .header .title Transparency @@ -256,27 +256,28 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') | Hotkeys ng-template(ngbTabContent) h3.mb-3 Hotkeys - + .input-group.mb-4 .input-group-prepend .input-group-text i.fas.fa-fw.fa-search input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter') - + .form-group table.hotkeys-table tr th Name th ID th Hotkey - tr(*ngFor='let hotkey of hotkeyDescriptions|filterBy:["name"]:hotkeyFilter') - td {{hotkey.name}} - td {{hotkey.id}} - td.pr-5 - multi-hotkey-input( - [model]='getHotkey(hotkey.id)', - (modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()' - ) + ng-container(*ngFor='let hotkey of hotkeyDescriptions') + tr(*ngIf='!hotkeyFilter || hotkey.name.toLowerCase().includes(hotkeyFilter.toLowerCase())') + td {{hotkey.name}} + td {{hotkey.id}} + td.pr-5 + multi-hotkey-input( + [model]='getHotkey(hotkey.id)', + (modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()' + ) ngb-tab(*ngFor='let provider of settingsProviders', [id]='provider.id') ng-template(ngbTabTitle) @@ -285,7 +286,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') ng-template(ngbTabContent) settings-tab-body([provider]='provider') - + ngb-tab(id='config-file') ng-template(ngbTabTitle) i.fas.fa-fw.fa-code.mr-2 @@ -303,7 +304,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab') textarea.form-control.h-100( [(ngModel)]='configDefaults', readonly - ) + ) .mt-2.mb-2.d-flex button.btn.btn-primary((click)='saveConfigFile()', *ngIf='isConfigFileValid()') i.fas.fa-check.mr-2 diff --git a/terminus-settings/src/index.ts b/terminus-settings/src/index.ts index 7708b149..29445bae 100644 --- a/terminus-settings/src/index.ts +++ b/terminus-settings/src/index.ts @@ -2,7 +2,6 @@ import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { FormsModule } from '@angular/forms' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' -import { NgPipesModule } from 'ngx-pipes' import TerminusCorePlugin, { ToolbarButtonProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider } from 'terminus-core' @@ -22,7 +21,6 @@ import { SettingsConfigProvider } from './config' BrowserModule, FormsModule, NgbModule, - NgPipesModule, TerminusCorePlugin, ], providers: [ diff --git a/terminus-settings/src/recoveryProvider.ts b/terminus-settings/src/recoveryProvider.ts index 7ae40eb7..90fdbb5a 100644 --- a/terminus-settings/src/recoveryProvider.ts +++ b/terminus-settings/src/recoveryProvider.ts @@ -6,7 +6,7 @@ import { SettingsTabComponent } from './components/settingsTab.component' /** @hidden */ @Injectable() export class RecoveryProvider extends TabRecoveryProvider { - async recover (recoveryToken: any): Promise { + async recover (recoveryToken: any): Promise { if (recoveryToken && recoveryToken.type === 'app:settings') { return { type: SettingsTabComponent } } diff --git a/terminus-settings/yarn.lock b/terminus-settings/yarn.lock index 5e4f03cb..79cc4bce 100644 --- a/terminus-settings/yarn.lock +++ b/terminus-settings/yarn.lock @@ -8,6 +8,6 @@ integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg== ngx-pipes@^1.6.1: - version "1.6.6" - resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.6.tgz#32bb80906c220f1e84d5cce7d6dae002cffead4b" - integrity sha512-mRV0xOZDd6/Jlvti4W0pDepZRIHLHd3kZ6ZzdqyGCU0dxbKVWWLTR1jlNlxN1ruMk8eO0Y8lNh6a1bEW7dJP1w== + version "1.7.0" + resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.7.0.tgz#70e166dc2f59a8b96f69dfbf75b58186c189037b" + integrity sha512-ZTJc0/a+e+8v7pP+tb301So5UlxVOoUEZZtJHMjuvHO/CADqfgF+sOAdq1dZMf2RnJ2QTuxbZ8wf34w3T/f8AA== diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json index b50c3d7c..a82d5a73 100644 --- a/terminus-ssh/package.json +++ b/terminus-ssh/package.json @@ -1,6 +1,6 @@ { "name": "terminus-ssh", - "version": "1.0.83-nightly.0", + "version": "1.0.92-nightly.0", "description": "SSH connection manager for Terminus", "keywords": [ "terminus-builtin-plugin" diff --git a/terminus-ssh/src/api.ts b/terminus-ssh/src/api.ts index ead3db4a..959b1483 100644 --- a/terminus-ssh/src/api.ts +++ b/terminus-ssh/src/api.ts @@ -1,7 +1,7 @@ import { BaseSession } from 'terminus-terminal' export interface LoginScript { - expect?: string + expect: string send: string isRegex?: boolean optional?: boolean @@ -15,7 +15,7 @@ export enum SSHAlgorithmType { } export interface SSHConnection { - name?: string + name: string host: string port: number user: string @@ -122,7 +122,7 @@ export class SSHSession extends BaseSession { this.kill('TERM') } - async getWorkingDirectory (): Promise { + async getWorkingDirectory (): Promise { return null } diff --git a/terminus-ssh/src/components/editConnectionModal.component.ts b/terminus-ssh/src/components/editConnectionModal.component.ts index 42fe8e48..92ce237b 100644 --- a/terminus-ssh/src/components/editConnectionModal.component.ts +++ b/terminus-ssh/src/components/editConnectionModal.component.ts @@ -85,7 +85,7 @@ export class EditConnectionModalComponent { title: 'Select private key', } ).then(result => { - if (!result.filePaths) { + if (result.filePaths) { this.connection.privateKey = result.filePaths[0] } }) @@ -93,7 +93,7 @@ export class EditConnectionModalComponent { save () { for (const k of Object.values(SSHAlgorithmType)) { - this.connection.algorithms[k] = Object.entries(this.algorithms[k]) + this.connection.algorithms![k] = Object.entries(this.algorithms[k]) .filter(([_k, v]) => !!v) .map(([k, _v]) => k) } @@ -105,6 +105,9 @@ export class EditConnectionModalComponent { } moveScriptUp (script: LoginScript) { + if (!this.connection.scripts) { + this.connection.scripts = [] + } const index = this.connection.scripts.indexOf(script) if (index > 0) { this.connection.scripts.splice(index, 1) @@ -113,6 +116,9 @@ export class EditConnectionModalComponent { } moveScriptDown (script: LoginScript) { + if (!this.connection.scripts) { + this.connection.scripts = [] + } const index = this.connection.scripts.indexOf(script) if (index >= 0 && index < this.connection.scripts.length - 1) { this.connection.scripts.splice(index, 1) @@ -121,7 +127,7 @@ export class EditConnectionModalComponent { } async deleteScript (script: LoginScript) { - if ((await this.electron.showMessageBox( + if (this.connection.scripts && (await this.electron.showMessageBox( this.hostApp.getWindow(), { type: 'warning', @@ -136,6 +142,9 @@ export class EditConnectionModalComponent { } addScript () { + if (!this.connection.scripts) { + this.connection.scripts = [] + } this.connection.scripts.push({ expect: '', send: '' }) } } diff --git a/terminus-ssh/src/components/sshModal.component.ts b/terminus-ssh/src/components/sshModal.component.ts index ea8958fc..242c45b0 100644 --- a/terminus-ssh/src/components/sshModal.component.ts +++ b/terminus-ssh/src/components/sshModal.component.ts @@ -15,7 +15,7 @@ export class SSHModalComponent { connections: SSHConnection[] childFolders: SSHConnectionGroup[] quickTarget: string - lastConnection: SSHConnection + lastConnection: SSHConnection|null = null childGroups: SSHConnectionGroup[] groupCollapsed: {[id: string]: boolean} = {} @@ -91,14 +91,14 @@ export class SSHModalComponent { } for (const connection of connections) { - connection.group = connection.group || null + connection.group = connection.group || undefined let group = this.childGroups.find(x => x.name === connection.group) if (!group) { group = { - name: connection.group, + name: connection.group!, connections: [], } - this.childGroups.push(group) + this.childGroups.push(group!) } group.connections.push(connection) } diff --git a/terminus-ssh/src/components/sshSettingsTab.component.ts b/terminus-ssh/src/components/sshSettingsTab.component.ts index e9d6c6f9..19ca22e4 100644 --- a/terminus-ssh/src/components/sshSettingsTab.component.ts +++ b/terminus-ssh/src/components/sshSettingsTab.component.ts @@ -97,7 +97,7 @@ export class SSHSettingsTabComponent { } )).response === 1) { for (const connection of this.connections.filter(x => x.group === group.name)) { - connection.group = null + connection.group = undefined } this.config.save() this.refresh() @@ -109,14 +109,14 @@ export class SSHSettingsTabComponent { this.childGroups = [] for (const connection of this.connections) { - connection.group = connection.group || null + connection.group = connection.group || undefined let group = this.childGroups.find(x => x.name === connection.group) if (!group) { group = { - name: connection.group, + name: connection.group!, connections: [], } - this.childGroups.push(group) + this.childGroups.push(group!) } group.connections.push(connection) } diff --git a/terminus-ssh/src/recoveryProvider.ts b/terminus-ssh/src/recoveryProvider.ts index 4dc82d11..b59ac9d2 100644 --- a/terminus-ssh/src/recoveryProvider.ts +++ b/terminus-ssh/src/recoveryProvider.ts @@ -6,7 +6,7 @@ import { SSHTabComponent } from './components/sshTab.component' /** @hidden */ @Injectable() export class RecoveryProvider extends TabRecoveryProvider { - async recover (recoveryToken: any): Promise { + async recover (recoveryToken: any): Promise { if (recoveryToken && recoveryToken.type === 'app:ssh-tab') { return { type: SSHTabComponent, diff --git a/terminus-ssh/src/services/passwordStorage.service.ts b/terminus-ssh/src/services/passwordStorage.service.ts index fa5d9dd8..3c57b24e 100644 --- a/terminus-ssh/src/services/passwordStorage.service.ts +++ b/terminus-ssh/src/services/passwordStorage.service.ts @@ -12,7 +12,7 @@ export class PasswordStorageService { await keytar.deletePassword(`ssh@${connection.host}`, connection.user) } - async loadPassword (connection: SSHConnection): Promise { + async loadPassword (connection: SSHConnection): Promise { return keytar.getPassword(`ssh@${connection.host}`, connection.user) } } diff --git a/terminus-ssh/src/services/ssh.service.ts b/terminus-ssh/src/services/ssh.service.ts index fe98d56f..98760a29 100644 --- a/terminus-ssh/src/services/ssh.service.ts +++ b/terminus-ssh/src/services/ssh.service.ts @@ -38,9 +38,9 @@ export class SSHService { ) as SSHTabComponent) } - async connectSession (session: SSHSession, logCallback?: (s: string) => void): Promise { - let privateKey: string = null - let privateKeyPassphrase: string = null + async connectSession (session: SSHSession, logCallback?: (s: any) => void): Promise { + let privateKey: string|null = null + let privateKeyPassphrase: string|null = null let privateKeyPath = session.connection.privateKey if (!logCallback) { @@ -48,12 +48,12 @@ export class SSHService { } const log = (s: any) => { - logCallback(s) + logCallback!(s) this.logger.info(s) } if (!privateKeyPath) { - const userKeyPath = path.join(process.env.HOME, '.ssh', 'id_rsa') + const userKeyPath = path.join(process.env.HOME as string, '.ssh', 'id_rsa') if (await fs.exists(userKeyPath)) { log(`Using user's default private key: ${userKeyPath}`) privateKeyPath = userKeyPath @@ -92,7 +92,7 @@ export class SSHService { const ssh = new Client() let connected = false - let savedPassword: string = null + let savedPassword: string|null = null await new Promise(async (resolve, reject) => { ssh.on('ready', () => { connected = true @@ -116,7 +116,7 @@ export class SSHService { ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => { log(`Keyboard-interactive auth requested: ${name}`) this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang) - const results = [] + const results: string[] = [] for (const prompt of prompts) { const modal = this.ngbModal.open(PromptModalComponent) modal.componentInstance.prompt = prompt.prompt @@ -135,7 +135,7 @@ export class SSHService { log('Banner: \n' + banner) }) - let agent: string = null + let agent: string|null = null if (this.hostApp.platform === Platform.Windows) { const pageantRunning = new Promise(resolve => { windowsProcessTreeNative.getProcessList(list => { // eslint-disable-line block-scoped-var @@ -146,7 +146,7 @@ export class SSHService { agent = 'pageant' } } else { - agent = process.env.SSH_AUTH_SOCK + agent = process.env.SSH_AUTH_SOCK as string } try { @@ -155,10 +155,10 @@ export class SSHService { port: session.connection.port || 22, username: session.connection.user, password: session.connection.privateKey ? undefined : '', - privateKey, - passphrase: privateKeyPassphrase, + privateKey: privateKey || undefined, + passphrase: privateKeyPassphrase || undefined, tryKeyboard: true, - agent, + agent: agent || undefined, agentForward: !!agent, keepaliveInterval: session.connection.keepaliveInterval, keepaliveCountMax: session.connection.keepaliveCountMax, diff --git a/terminus-terminal/package.json b/terminus-terminal/package.json index f0bcbe3b..d5cee50c 100644 --- a/terminus-terminal/package.json +++ b/terminus-terminal/package.json @@ -1,6 +1,6 @@ { "name": "terminus-terminal", - "version": "1.0.83-nightly.4", + "version": "1.0.92-nightly.0", "description": "Terminus' terminal emulation core", "keywords": [ "terminus-builtin-plugin" diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts index ab22708b..dea2b9bc 100644 --- a/terminus-terminal/src/api/baseTerminalTab.component.ts +++ b/terminus-terminal/src/api/baseTerminalTab.component.ts @@ -43,7 +43,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit @ViewChild('content') content /** @hidden */ - @HostBinding('style.background-color') backgroundColor: string + @HostBinding('style.background-color') backgroundColor: string|null = null /** @hidden */ @HostBinding('class.top-padded') topPadded: boolean diff --git a/terminus-terminal/src/buttonProvider.ts b/terminus-terminal/src/buttonProvider.ts index f9733e4e..13132d3a 100644 --- a/terminus-terminal/src/buttonProvider.ts +++ b/terminus-terminal/src/buttonProvider.ts @@ -18,7 +18,7 @@ export class ButtonProvider extends ToolbarButtonProvider { for (const arg of argv.slice(1).concat([electron.remote.process.argv0])) { if (await fs.exists(arg)) { if ((await fs.stat(arg)).isDirectory()) { - this.terminal.openTab(null, arg) + this.terminal.openTab(undefined, arg) } } } diff --git a/terminus-terminal/src/colorSchemes.ts b/terminus-terminal/src/colorSchemes.ts index 44d5b212..cc7fbe0a 100644 --- a/terminus-terminal/src/colorSchemes.ts +++ b/terminus-terminal/src/colorSchemes.ts @@ -8,7 +8,7 @@ import { TerminalColorScheme } from './api/interfaces' @Injectable() export class HyperColorSchemes extends TerminalColorSchemeProvider { async getSchemes (): Promise { - const pluginsPath = path.join(process.env.HOME, '.hyper_plugins', 'node_modules') + const pluginsPath = path.join(process.env.HOME as string, '.hyper_plugins', 'node_modules') if (!await fs.exists(pluginsPath)) { return [] } diff --git a/terminus-terminal/src/components/appearanceSettingsTab.component.ts b/terminus-terminal/src/components/appearanceSettingsTab.component.ts index 664c40c2..94eff4d1 100644 --- a/terminus-terminal/src/components/appearanceSettingsTab.component.ts +++ b/terminus-terminal/src/components/appearanceSettingsTab.component.ts @@ -19,7 +19,7 @@ export class AppearanceSettingsTabComponent { fonts: string[] = [] colorSchemes: TerminalColorScheme[] = [] equalComparator = deepEqual - editingColorScheme: TerminalColorScheme + editingColorScheme: TerminalColorScheme|null = null schemeChanged = false constructor ( @@ -68,7 +68,7 @@ export class AppearanceSettingsTabComponent { saveScheme () { let schemes = this.config.store.terminal.customColorSchemes - schemes = schemes.filter(x => x !== this.editingColorScheme && x.name !== this.editingColorScheme.name) + schemes = schemes.filter(x => x !== this.editingColorScheme && x.name !== this.editingColorScheme!.name) schemes.push(this.editingColorScheme) this.config.store.terminal.customColorSchemes = schemes this.config.save() diff --git a/terminus-terminal/src/components/shellSettingsTab.component.ts b/terminus-terminal/src/components/shellSettingsTab.component.ts index e6b810eb..cc6ccb3d 100644 --- a/terminus-terminal/src/components/shellSettingsTab.component.ts +++ b/terminus-terminal/src/components/shellSettingsTab.component.ts @@ -52,6 +52,9 @@ export class ShellSettingsTabComponent { pickWorkingDirectory () { const shell = this.shells.find(x => x.id === this.config.store.terminal.shell) + if (!shell) { + return + } const paths = this.electron.dialog.showOpenDialog( this.hostApp.getWindow(), { @@ -66,7 +69,7 @@ export class ShellSettingsTabComponent { newProfile (shell: Shell) { const profile: Profile = { - name: shell.name, + name: shell.name || '', sessionOptions: this.terminalService.optionsFromShell(shell), } this.config.store.terminal.profiles = [profile, ...this.config.store.terminal.profiles] diff --git a/terminus-terminal/src/components/terminalSettingsTab.component.ts b/terminus-terminal/src/components/terminalSettingsTab.component.ts index 85454a25..ed57fb6d 100644 --- a/terminus-terminal/src/components/terminalSettingsTab.component.ts +++ b/terminus-terminal/src/components/terminalSettingsTab.component.ts @@ -16,7 +16,7 @@ export class TerminalSettingsTabComponent { openWSLVolumeMixer () { this.electron.shell.openItem('sndvol.exe') this.terminal.openTab({ - name: null, + name: '', sessionOptions: { command: 'wsl.exe', args: ['tput', 'bel'], diff --git a/terminus-terminal/src/components/terminalTab.component.ts b/terminus-terminal/src/components/terminalTab.component.ts index 669420d4..8c4e46b3 100644 --- a/terminus-terminal/src/components/terminalTab.component.ts +++ b/terminus-terminal/src/components/terminalTab.component.ts @@ -68,7 +68,7 @@ export class TerminalTabComponent extends BaseTerminalTabComponent { } } - async getCurrentProcess (): Promise { + async getCurrentProcess (): Promise { const children = await this.session.getChildProcesses() if (!children.length) { return null diff --git a/terminus-terminal/src/frontends/hterm.ts b/terminus-terminal/src/frontends/hterm.ts index 43d5649c..a72b9f09 100644 --- a/terminus-terminal/src/frontends/hterm.ts +++ b/terminus-terminal/src/frontends/hterm.ts @@ -78,11 +78,11 @@ hterm.hterm.VT.CSI[' q'] = function (parseState) { } hterm.hterm.VT.OSC['4'] = function (parseState) { - const args = parseState.args[0].split(';') + const args: string[] = parseState.args[0].split(';') const pairCount = args.length / 2 const colorPalette = this.terminal.getTextAttributes().colorPalette - const responseArray = [] + const responseArray: string[] = [] for (let pairNumber = 0; pairNumber < pairCount; ++pairNumber) { const colorIndex = parseInt(args[pairNumber * 2]) @@ -95,7 +95,7 @@ hterm.hterm.VT.OSC['4'] = function (parseState) { if (colorValue === '?') { colorValue = hterm.lib.colors.rgbToX11(colorPalette[colorIndex]) if (colorValue) { - responseArray.push(colorIndex + ';' + colorValue) + responseArray.push(colorIndex.toString() + ';' + colorValue) } continue } diff --git a/terminus-terminal/src/frontends/htermFrontend.ts b/terminus-terminal/src/frontends/htermFrontend.ts index a5503683..a4d8b2dd 100644 --- a/terminus-terminal/src/frontends/htermFrontend.ts +++ b/terminus-terminal/src/frontends/htermFrontend.ts @@ -186,7 +186,7 @@ export class HTermFrontend extends Frontend { this.io.onTerminalResize = (columns, rows) => { this.resize.next({ columns, rows }) } - this.ready.next(null) + this.ready.next() this.ready.complete() this.term.scrollPort_.document_.addEventListener('dragOver', event => { diff --git a/terminus-terminal/src/frontends/xtermFrontend.ts b/terminus-terminal/src/frontends/xtermFrontend.ts index 5ef29753..29cc5cca 100644 --- a/terminus-terminal/src/frontends/xtermFrontend.ts +++ b/terminus-terminal/src/frontends/xtermFrontend.ts @@ -120,7 +120,7 @@ export class XTermFrontend extends Frontend { this.xterm.loadAddon(new WebglAddon()) } - this.ready.next(null) + this.ready.next() this.ready.complete() this.xterm.loadAddon(this.search) @@ -250,7 +250,7 @@ export class XTermFrontend extends Frontend { let html = `
` const selection = this.xterm.getSelectionPosition() if (!selection) { - return null + return '' } if (selection.startRow === selection.endRow) { html += this.getLineAsHTML(selection.startRow, selection.startColumn, selection.endColumn) @@ -278,7 +278,7 @@ export class XTermFrontend extends Frontend { private getLineAsHTML (y: number, start: number, end: number): string { let html = '
' - let lastStyle = null + let lastStyle: string|null = null const line = (this.xterm.buffer.getLine(y) as any)._line const cell = new CellData() for (let i = start; i < end; i++) { diff --git a/terminus-terminal/src/index.ts b/terminus-terminal/src/index.ts index c7c3d51e..1d8af8ff 100644 --- a/terminus-terminal/src/index.ts +++ b/terminus-terminal/src/index.ts @@ -188,7 +188,7 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/ hostApp.cliOpenDirectory$.subscribe(async directory => { if (await fs.exists(directory)) { if ((await fs.stat(directory)).isDirectory()) { - terminal.openTab(null, directory) + terminal.openTab(undefined, directory) hostApp.bringToFront() } } diff --git a/terminus-terminal/src/pathDrop.ts b/terminus-terminal/src/pathDrop.ts index e3405edb..19a19cf6 100644 --- a/terminus-terminal/src/pathDrop.ts +++ b/terminus-terminal/src/pathDrop.ts @@ -15,7 +15,7 @@ export class PathDropDecorator extends TerminalDecorator { event.preventDefault() }), terminal.frontend.drop$.subscribe(event => { - for (const file of event.dataTransfer.files as any) { + for (const file of event.dataTransfer!.files as any) { this.injectPath(terminal, file.path) } event.preventDefault() diff --git a/terminus-terminal/src/recoveryProvider.ts b/terminus-terminal/src/recoveryProvider.ts index a9a061b1..ebe4170c 100644 --- a/terminus-terminal/src/recoveryProvider.ts +++ b/terminus-terminal/src/recoveryProvider.ts @@ -6,7 +6,7 @@ import { TerminalTabComponent } from './components/terminalTab.component' /** @hidden */ @Injectable() export class RecoveryProvider extends TabRecoveryProvider { - async recover (recoveryToken: any): Promise { + async recover (recoveryToken: any): Promise { if (recoveryToken && recoveryToken.type === 'app:terminal-tab') { return { type: TerminalTabComponent, diff --git a/terminus-terminal/src/services/dockMenu.service.ts b/terminus-terminal/src/services/dockMenu.service.ts index 312b2d90..38b26374 100644 --- a/terminus-terminal/src/services/dockMenu.service.ts +++ b/terminus-terminal/src/services/dockMenu.service.ts @@ -30,7 +30,7 @@ export class DockMenuService { iconPath: process.execPath, iconIndex: 0, })), - }] : null) + }] : null as any) } if (this.hostApp.platform === Platform.macOS) { this.electron.app.dock.setMenu(this.electron.Menu.buildFromTemplate( diff --git a/terminus-terminal/src/services/sessions.service.ts b/terminus-terminal/src/services/sessions.service.ts index d088cd08..c200e726 100644 --- a/terminus-terminal/src/services/sessions.service.ts +++ b/terminus-terminal/src/services/sessions.service.ts @@ -62,7 +62,7 @@ export abstract class BaseSession { releaseInitialDataBuffer () { this.initialDataBufferReleased = true this.output.next(this.initialDataBuffer) - this.initialDataBuffer = null + this.initialDataBuffer = '' } async destroy (): Promise { @@ -81,14 +81,14 @@ export abstract class BaseSession { abstract kill (signal?: string): void abstract async getChildProcesses (): Promise abstract async gracefullyKillProcess (): Promise - abstract async getWorkingDirectory (): Promise + abstract async getWorkingDirectory (): Promise } /** @hidden */ export class Session extends BaseSession { private pty: any private pauseAfterExit = false - private guessedCWD: string + private guessedCWD: string|null = null private reportedCWD: string constructor (private config: ConfigService) { @@ -96,7 +96,7 @@ export class Session extends BaseSession { } start (options: SessionOptions) { - this.name = options.name + this.name = options.name || '' const env = { ...process.env, @@ -122,7 +122,7 @@ export class Session extends BaseSession { if (!fs.existsSync(cwd)) { console.warn('Ignoring non-existent CWD:', cwd) - cwd = null + cwd = undefined } this.pty = nodePTY.spawn(options.command, options.args || [], { @@ -135,7 +135,7 @@ export class Session extends BaseSession { experimentalUseConpty: (isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY ? 1 : false) as any, }) - this.guessedCWD = cwd + this.guessedCWD = cwd || null this.truePID = this.pty['pid'] @@ -174,7 +174,7 @@ export class Session extends BaseSession { } }) - this.pauseAfterExit = options.pauseAfterExit + this.pauseAfterExit = options.pauseAfterExit || false } processOSC1337 (data: string) { @@ -270,7 +270,7 @@ export class Session extends BaseSession { } } - async getWorkingDirectory (): Promise { + async getWorkingDirectory (): Promise { if (this.reportedCWD) { return this.reportedCWD } diff --git a/terminus-terminal/src/services/terminal.service.ts b/terminus-terminal/src/services/terminal.service.ts index 9d156005..4dc08d67 100644 --- a/terminus-terminal/src/services/terminal.service.ts +++ b/terminus-terminal/src/services/terminal.service.ts @@ -51,7 +51,7 @@ export class TerminalService { * Launches a new terminal with a specific shell and CWD * @param pause Wait for a keypress when the shell exits */ - async openTab (profile?: Profile, cwd?: string, pause?: boolean): Promise { + async openTab (profile?: Profile, cwd?: string|null, pause?: boolean): Promise { if (!profile) { const profiles = await this.getProfiles(true) profile = profiles.find(x => slug(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0] @@ -85,7 +85,7 @@ export class TerminalService { const sessionOptions = { ...profile.sessionOptions, pauseAfterExit: pause, - cwd, + cwd: cwd || undefined, } return this.openTabWithOptions(sessionOptions) diff --git a/terminus-terminal/src/services/terminalFrontend.service.ts b/terminus-terminal/src/services/terminalFrontend.service.ts index 046995a0..748b1a6e 100644 --- a/terminus-terminal/src/services/terminalFrontend.service.ts +++ b/terminus-terminal/src/services/terminalFrontend.service.ts @@ -34,6 +34,6 @@ export class TerminalFrontendService { this.getFrontend(), ) } - return this.containers.get(session) + return this.containers.get(session)! } } diff --git a/terminus-terminal/src/shells/linuxDefault.ts b/terminus-terminal/src/shells/linuxDefault.ts index 903db827..988a2826 100644 --- a/terminus-terminal/src/shells/linuxDefault.ts +++ b/terminus-terminal/src/shells/linuxDefault.ts @@ -23,7 +23,7 @@ export class LinuxDefaultShellProvider extends ShellProvider { return [] } const line = (await fs.readFile('/etc/passwd', { encoding: 'utf-8' })) - .split('\n').find(x => x.startsWith(process.env.LOGNAME + ':')) + .split('\n').find(x => x.startsWith(`${process.env.LOGNAME}:`)) if (!line) { this.logger.warn('Could not detect user shell') return [{ diff --git a/tsconfig.json b/tsconfig.json index c5e25d85..92bce4f8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ "esModuleInterop": true, "allowSyntheticDefaultImports": true, "importHelpers": true, + "strictNullChecks": true, "lib": [ "dom", "es5", -- GitLab