mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Try and fix exit code issue
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
1e6c859539
commit
f63d10d003
20
package-lock.json
generated
20
package-lock.json
generated
@ -10241,6 +10241,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
|
||||
"integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw=="
|
||||
},
|
||||
"node_modules/@types/stoppable": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stoppable/-/stoppable-1.1.1.tgz",
|
||||
"integrity": "sha512-b8N+fCADRIYYrGZOcmOR8ZNBOqhktWTB/bMUl5LvGtT201QKJZOOH5UsFyI3qtteM6ZAJbJqZoBcLqqxKIwjhw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/tar": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-6.1.4.tgz",
|
||||
@ -34430,6 +34439,15 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stoppable": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz",
|
||||
"integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==",
|
||||
"engines": {
|
||||
"node": ">=4",
|
||||
"npm": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-buffers": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stream-buffers/-/stream-buffers-3.0.2.tgz",
|
||||
@ -38200,6 +38218,7 @@
|
||||
"rfc6902": "^5.0.1",
|
||||
"selfsigned": "^2.1.1",
|
||||
"semver": "^7.3.8",
|
||||
"stoppable": "^1.1.0",
|
||||
"tar": "^6.1.13",
|
||||
"tcp-port-used": "^1.0.2",
|
||||
"tempy": "1.0.1",
|
||||
@ -38260,6 +38279,7 @@
|
||||
"@types/react-window": "^1.8.5",
|
||||
"@types/readable-stream": "^2.3.13",
|
||||
"@types/semver": "^7.3.13",
|
||||
"@types/stoppable": "^1.1.1",
|
||||
"@types/tar": "^6.1.4",
|
||||
"@types/tcp-port-used": "^1.0.1",
|
||||
"@types/triple-beam": "^1.3.2",
|
||||
|
||||
@ -167,6 +167,7 @@
|
||||
"rfc6902": "^5.0.1",
|
||||
"selfsigned": "^2.1.1",
|
||||
"semver": "^7.3.8",
|
||||
"stoppable": "^1.1.0",
|
||||
"tar": "^6.1.13",
|
||||
"tcp-port-used": "^1.0.2",
|
||||
"tempy": "1.0.1",
|
||||
@ -227,6 +228,7 @@
|
||||
"@types/react-window": "^1.8.5",
|
||||
"@types/readable-stream": "^2.3.13",
|
||||
"@types/semver": "^7.3.13",
|
||||
"@types/stoppable": "^1.1.1",
|
||||
"@types/tar": "^6.1.4",
|
||||
"@types/tcp-port-used": "^1.0.1",
|
||||
"@types/triple-beam": "^1.3.2",
|
||||
|
||||
@ -10,13 +10,48 @@ const loggerInjectable = getInjectable({
|
||||
id: "logger",
|
||||
instantiate: (di): Logger => {
|
||||
const baseLogger = di.inject(winstonLoggerInjectable);
|
||||
let closed = false;
|
||||
|
||||
baseLogger.once("close", () => {
|
||||
closed = true;
|
||||
});
|
||||
|
||||
return {
|
||||
debug: (message, ...data) => baseLogger.debug(message, ...data),
|
||||
info: (message, ...data) => baseLogger.info(message, ...data),
|
||||
warn: (message, ...data) => baseLogger.warn(message, ...data),
|
||||
error: (message, ...data) => baseLogger.error(message, ...data),
|
||||
silly: (message, ...data) => baseLogger.silly(message, ...data),
|
||||
debug: (message, ...data) => {
|
||||
if (closed) {
|
||||
console.debug(message, ...data);
|
||||
} else {
|
||||
baseLogger.debug(message, ...data);
|
||||
}
|
||||
},
|
||||
info: (message, ...data) => {
|
||||
if (closed) {
|
||||
console.info(message, ...data);
|
||||
} else {
|
||||
baseLogger.info(message, ...data);
|
||||
}
|
||||
},
|
||||
warn: (message, ...data) => {
|
||||
if (closed) {
|
||||
console.warn(message, ...data);
|
||||
} else {
|
||||
baseLogger.warn(message, ...data);
|
||||
}
|
||||
},
|
||||
error: (message, ...data) => {
|
||||
if (closed) {
|
||||
console.error(message, ...data);
|
||||
} else {
|
||||
baseLogger.error(message, ...data);
|
||||
}
|
||||
},
|
||||
silly: (message, ...data) => {
|
||||
if (closed) {
|
||||
// DO nothing
|
||||
} else {
|
||||
baseLogger.silly(message, ...data);
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -8,11 +8,10 @@ import { loggerTransportInjectionToken } from "./logger/transports";
|
||||
|
||||
const winstonLoggerInjectable = getInjectable({
|
||||
id: "winston-logger",
|
||||
instantiate: (di) =>
|
||||
createLogger({
|
||||
format: format.combine(format.splat(), format.simple()),
|
||||
transports: di.injectMany(loggerTransportInjectionToken),
|
||||
}),
|
||||
instantiate: (di) => createLogger({
|
||||
format: format.combine(format.splat(), format.simple()),
|
||||
transports: di.injectMany(loggerTransportInjectionToken),
|
||||
}),
|
||||
});
|
||||
|
||||
export default winstonLoggerInjectable;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
|
||||
import { ipcRenderer } from "electron";
|
||||
import { EventEmitter } from "events";
|
||||
import { makeObservable, observable, reaction, when } from "mobx";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { broadcastMessage, ipcMainHandle, ipcRendererOn } from "../../common/ipc";
|
||||
import { toJS } from "../../common/utils";
|
||||
import { isErrnoException } from "@k8slens/utilities";
|
||||
@ -31,6 +31,7 @@ import type { GetRelativePath } from "../../common/path/get-relative-path.inject
|
||||
import type { RemovePath } from "../../common/fs/remove.injectable";
|
||||
import type TypedEventEmitter from "typed-emitter";
|
||||
import type { IsExtensionEnabled } from "../../features/extensions/enabled/common/is-enabled.injectable";
|
||||
import assert from "assert";
|
||||
|
||||
interface Dependencies {
|
||||
readonly extensionLoader: ExtensionLoader;
|
||||
@ -101,10 +102,6 @@ export class ExtensionDiscovery {
|
||||
// True if extensions have been loaded from the disk after app startup
|
||||
@observable isLoaded = false;
|
||||
|
||||
get whenLoaded() {
|
||||
return when(() => this.isLoaded);
|
||||
}
|
||||
|
||||
public readonly events: TypedEventEmitter<ExtensionDiscoveryEvents> = new EventEmitter();
|
||||
|
||||
constructor(protected readonly dependencies: Dependencies) {
|
||||
@ -157,11 +154,10 @@ export class ExtensionDiscovery {
|
||||
* Watches for added/removed local extensions.
|
||||
* Dependencies are installed automatically after an extension folder is copied.
|
||||
*/
|
||||
async watchExtensions(): Promise<void> {
|
||||
this.dependencies.logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`);
|
||||
watchExtensions() {
|
||||
assert(this.isLoaded, "This function can only be called after a call to 'load' has resolved");
|
||||
|
||||
// Wait until .load() has been called and has been resolved
|
||||
await this.whenLoaded;
|
||||
this.dependencies.logger.info(`${logModule} watching extension add/remove in ${this.localFolderPath}`);
|
||||
|
||||
this.dependencies.watch(this.localFolderPath, {
|
||||
// For adding and removing symlinks to work, the depth has to be 1.
|
||||
|
||||
@ -69,10 +69,6 @@ export class ExtensionLoader {
|
||||
|
||||
@observable isLoaded = false;
|
||||
|
||||
get whenLoaded() {
|
||||
return when(() => this.isLoaded);
|
||||
}
|
||||
|
||||
constructor(protected readonly dependencies: Dependencies) {
|
||||
makeObservable(this);
|
||||
|
||||
@ -138,10 +134,9 @@ export class ExtensionLoader {
|
||||
await this.initMain();
|
||||
} else {
|
||||
await this.initRenderer();
|
||||
await when(() => this.isLoaded);
|
||||
}
|
||||
|
||||
await Promise.all([this.whenLoaded]);
|
||||
|
||||
// broadcasting extensions between main/renderer processes
|
||||
reaction(() => this.toJSON(), () => this.broadcastExtensions(), {
|
||||
fireImmediately: true,
|
||||
|
||||
@ -4,28 +4,23 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import applicationMenuItemInjectionToken from "../../application-menu-item-injection-token";
|
||||
import stopServicesAndExitAppInjectable from "../../../../../../main/stop-services-and-exit-app.injectable";
|
||||
import quitAppExplicitlyInjectable from "../../../../../../main/stop-services-and-exit-app.injectable";
|
||||
import isMacInjectable from "../../../../../../common/vars/is-mac.injectable";
|
||||
|
||||
const quitApplicationMenuItemInjectable = getInjectable({
|
||||
id: "quit-application-menu-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const stopServicesAndExitApp = di.inject(stopServicesAndExitAppInjectable);
|
||||
const isMac = di.inject(isMacInjectable);
|
||||
|
||||
return {
|
||||
kind: "clickable-menu-item" as const,
|
||||
id: "quit",
|
||||
label: "Quit",
|
||||
|
||||
parentId: isMac ? "mac" : "file",
|
||||
orderNumber: isMac ? 140 : 70,
|
||||
keyboardShortcut: isMac ? "Cmd+Q" : "Alt+F4",
|
||||
|
||||
onClick: () => {
|
||||
stopServicesAndExitApp();
|
||||
},
|
||||
onClick: di.inject(quitAppExplicitlyInjectable),
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@ -14,8 +14,6 @@ const stopApplicationMenuInjectable = getInjectable({
|
||||
const applicationMenu = di.inject(applicationMenuReactivityInjectable);
|
||||
|
||||
applicationMenu.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -16,8 +16,6 @@ const stopCheckingForUpdatesInjectable = getInjectable({
|
||||
if (periodicalCheckForUpdates.started) {
|
||||
periodicalCheckForUpdates.stop();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -14,8 +14,6 @@ const stopWatchingIfUpdateShouldHappenOnQuitInjectable = getInjectable({
|
||||
const watchIfUpdateShouldHappenOnQuit = di.inject(watchIfUpdateShouldHappenOnQuitInjectable);
|
||||
|
||||
watchIfUpdateShouldHappenOnQuit.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -5,21 +5,23 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import extensionInjectable from "../../../../extensions/extension-loader/extension/extension.injectable";
|
||||
import extensionsInjectable from "../../../../extensions/extensions.injectable";
|
||||
import { beforeQuitOfBackEndInjectionToken } from "../../../../main/start-main-application/runnable-tokens/phases";
|
||||
|
||||
const stopAllExtensionsInjectable = getInjectable({
|
||||
id: "stop-all-extensions",
|
||||
instantiate: (di) => {
|
||||
const extensionInstances = di.inject(extensionsInjectable);
|
||||
instantiate: (di) => ({
|
||||
run: async () => {
|
||||
const instances = di.inject(extensionsInjectable).get();
|
||||
|
||||
return async () => {
|
||||
for (const instance of extensionInstances.get()) {
|
||||
for (const instance of instances) {
|
||||
const extension = di.inject(extensionInjectable, instance);
|
||||
|
||||
await instance.disable();
|
||||
extension.deregister();
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopAllExtensionsInjectable;
|
||||
|
||||
@ -26,7 +26,7 @@ const ipcFileLoggerInjectable = getInjectable({
|
||||
() => createIpcFileTransport(fileId),
|
||||
);
|
||||
|
||||
transport?.log?.(entry, () => {});
|
||||
transport.log?.(entry, () => {});
|
||||
}
|
||||
|
||||
function close(fileId: string) {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../../../main/start-main-application/runnable-tokens/phases";
|
||||
import ipcFileLoggerInjectable from "./ipc-file-logger.injectable";
|
||||
|
||||
const stopIpcLoggingInjectable = getInjectable({
|
||||
@ -21,7 +21,7 @@ const stopIpcLoggingInjectable = getInjectable({
|
||||
};
|
||||
},
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopIpcLoggingInjectable;
|
||||
|
||||
@ -6,16 +6,16 @@
|
||||
import type { ApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||
import type { ClusterManager } from "../../main/cluster/manager";
|
||||
import exitAppInjectable from "../../main/electron-app/features/exit-app.injectable";
|
||||
import quitAppInjectable from "../../main/electron-app/features/exit-app.injectable";
|
||||
import clusterManagerInjectable from "../../main/cluster/manager.injectable";
|
||||
import stopServicesAndExitAppInjectable from "../../main/stop-services-and-exit-app.injectable";
|
||||
import quitAppExplicitlyInjectable from "../../main/stop-services-and-exit-app.injectable";
|
||||
import { testUsingFakeTime, advanceFakeTime } from "../../test-utils/use-fake-time";
|
||||
|
||||
describe("quitting the app using application menu", () => {
|
||||
describe("given application has started", () => {
|
||||
let builder: ApplicationBuilder;
|
||||
let clusterManagerStub: ClusterManager;
|
||||
let exitAppMock: jest.Mock;
|
||||
let quitAppMock: jest.Mock;
|
||||
|
||||
beforeEach(async () => {
|
||||
testUsingFakeTime("2015-10-21T07:28:00Z");
|
||||
@ -23,13 +23,13 @@ describe("quitting the app using application menu", () => {
|
||||
builder = getApplicationBuilder();
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.unoverride(stopServicesAndExitAppInjectable);
|
||||
mainDi.unoverride(quitAppExplicitlyInjectable);
|
||||
|
||||
clusterManagerStub = { stop: jest.fn() } as unknown as ClusterManager;
|
||||
mainDi.override(clusterManagerInjectable, () => clusterManagerStub);
|
||||
|
||||
exitAppMock = jest.fn();
|
||||
mainDi.override(exitAppInjectable, () => exitAppMock);
|
||||
quitAppMock = jest.fn();
|
||||
mainDi.override(quitAppInjectable, () => quitAppMock);
|
||||
});
|
||||
|
||||
await builder.render();
|
||||
@ -52,14 +52,10 @@ describe("quitting the app using application menu", () => {
|
||||
expect(windows).toEqual([]);
|
||||
});
|
||||
|
||||
it("disconnects all clusters", () => {
|
||||
expect(clusterManagerStub.stop).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("after insufficient time passes, does not terminate application yet", () => {
|
||||
advanceFakeTime(999);
|
||||
|
||||
expect(exitAppMock).not.toHaveBeenCalled();
|
||||
expect(quitAppMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("after sufficient time passes", () => {
|
||||
@ -68,7 +64,7 @@ describe("quitting the app using application menu", () => {
|
||||
});
|
||||
|
||||
it("terminates application", () => {
|
||||
expect(exitAppMock).toHaveBeenCalled();
|
||||
expect(quitAppMock).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,8 +13,6 @@ const stopValidatingWeblinksInjectable = getInjectable({
|
||||
const weblinkVerificationStartableStoppable = di.inject(weblinkVerificationStartableStoppableInjectable);
|
||||
|
||||
weblinkVerificationStartableStoppable.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import catalogSyncToRendererInjectable from "./catalog-sync-to-renderer.injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../start-main-application/runnable-tokens/phases";
|
||||
|
||||
const stopCatalogSyncInjectable = getInjectable({
|
||||
id: "stop-catalog-sync",
|
||||
@ -21,7 +21,7 @@ const stopCatalogSyncInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopCatalogSyncInjectable;
|
||||
|
||||
@ -226,14 +226,6 @@ export class ClusterManager {
|
||||
)),
|
||||
);
|
||||
};
|
||||
|
||||
stop() {
|
||||
for (const cluster of this.dependencies.clusters.get()) {
|
||||
this.dependencies
|
||||
.getClusterConnection(cluster)
|
||||
.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function catalogEntityFromCluster(cluster: Cluster) {
|
||||
|
||||
@ -5,14 +5,14 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
|
||||
const exitAppInjectable = getInjectable({
|
||||
id: "exit-app",
|
||||
const quitAppInjectable = getInjectable({
|
||||
id: "quit-app",
|
||||
|
||||
instantiate: (di) => () => {
|
||||
const app = di.inject(electronAppInjectable);
|
||||
|
||||
app.exit(0);
|
||||
app.quit();
|
||||
},
|
||||
});
|
||||
|
||||
export default exitAppInjectable;
|
||||
export default quitAppInjectable;
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
const isAutoUpdatingInjectable = getInjectable({
|
||||
id: "is-auto-updating",
|
||||
instantiate: () => {
|
||||
let value = false;
|
||||
|
||||
return {
|
||||
get: () => value,
|
||||
set: (newValue: boolean) => {
|
||||
value = newValue;
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default isAutoUpdatingInjectable;
|
||||
@ -14,8 +14,6 @@ const cleanUpDeepLinkingInjectable = getInjectable({
|
||||
const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable);
|
||||
|
||||
lensProtocolRouterMain.cleanup();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../../../start-main-application/runnable-tokens/phases";
|
||||
import electronAppInjectable from "../../electron-app.injectable";
|
||||
import { isEmpty } from "lodash/fp";
|
||||
import getVisibleWindowsInjectable from "../../../start-main-application/lens-window/get-visible-windows.injectable";
|
||||
@ -25,7 +25,7 @@ const hideDockForLastClosedWindowInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default hideDockForLastClosedWindowInjectable;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main";
|
||||
import requestSingleInstanceLockInjectable from "../features/request-single-instance-lock.injectable";
|
||||
import exitAppInjectable from "../features/exit-app.injectable";
|
||||
import quitAppInjectable from "../features/exit-app.injectable";
|
||||
|
||||
const enforceSingleApplicationInstanceInjectable = getInjectable({
|
||||
id: "enforce-single-application-instance",
|
||||
@ -13,10 +13,10 @@ const enforceSingleApplicationInstanceInjectable = getInjectable({
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const requestSingleInstanceLock = di.inject(requestSingleInstanceLockInjectable);
|
||||
const exitApp = di.inject(exitAppInjectable);
|
||||
const quitApp = di.inject(quitAppInjectable);
|
||||
|
||||
if (!requestSingleInstanceLock()) {
|
||||
exitApp();
|
||||
quitApp();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import powerMonitorInjectable from "../features/power-monitor.injectable";
|
||||
import exitAppInjectable from "../features/exit-app.injectable";
|
||||
import quitAppInjectable from "../features/exit-app.injectable";
|
||||
import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
|
||||
|
||||
const setupDeviceShutdownInjectable = getInjectable({
|
||||
@ -13,9 +13,9 @@ const setupDeviceShutdownInjectable = getInjectable({
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const powerMonitor = di.inject(powerMonitorInjectable);
|
||||
const exitApp = di.inject(exitAppInjectable);
|
||||
const quitApp = di.inject(quitAppInjectable);
|
||||
|
||||
powerMonitor.on("shutdown", exitApp);
|
||||
powerMonitor.on("shutdown", quitApp);
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main";
|
||||
import { beforeQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken, beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/phases";
|
||||
import electronAppInjectable from "../electron-app.injectable";
|
||||
import isIntegrationTestingInjectable from "../../../common/vars/is-integration-testing.injectable";
|
||||
import autoUpdaterInjectable from "../features/auto-updater.injectable";
|
||||
import { runManySyncFor, runManyFor } from "@k8slens/run-many";
|
||||
import quitAppInjectable from "../features/exit-app.injectable";
|
||||
|
||||
const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({
|
||||
id: "setup-closing-of-application",
|
||||
@ -17,54 +17,51 @@ const setupRunnablesBeforeClosingOfApplicationInjectable = getInjectable({
|
||||
run: () => {
|
||||
const runManySync = runManySyncFor(di);
|
||||
const runMany = runManyFor(di);
|
||||
const runRunnablesBeforeQuitOfFrontEnd = runManySync(beforeQuitOfFrontEndInjectionToken);
|
||||
const runRunnablesAfterQuitOfFrontEnd = runManySync(afterQuitOfFrontEndInjectionToken);
|
||||
const runRunnablesBeforeQuitOfBackEnd = runMany(beforeQuitOfBackEndInjectionToken);
|
||||
const app = di.inject(electronAppInjectable);
|
||||
const isIntegrationTesting = di.inject(isIntegrationTestingInjectable);
|
||||
const autoUpdater = di.inject(autoUpdaterInjectable);
|
||||
let isAutoUpdating = false;
|
||||
const quitApp = di.inject(quitAppInjectable);
|
||||
|
||||
autoUpdater.on("before-quit-for-update", () => {
|
||||
isAutoUpdating = true;
|
||||
let isAsyncQuitting = false;
|
||||
|
||||
const doAsyncQuit = () => {
|
||||
if (isAsyncQuitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
isAsyncQuitting = true;
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
console.log("before runRunnablesBeforeQuitOfBackEnd");
|
||||
await runRunnablesBeforeQuitOfBackEnd();
|
||||
console.log("after runRunnablesBeforeQuitOfBackEnd");
|
||||
app.exit(0);
|
||||
} catch (error) {
|
||||
console.error("A beforeQuitOfBackEnd failed!!!!", error);
|
||||
app.exit(1);
|
||||
}
|
||||
})();
|
||||
};
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
console.log(`app.on("window-all-closed")`);
|
||||
runRunnablesAfterQuitOfFrontEnd();
|
||||
|
||||
if (isIntegrationTesting) {
|
||||
quitApp();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("will-quit", () => {
|
||||
runRunnablesBeforeQuitOfFrontEnd();
|
||||
app.on("will-quit", (event) => {
|
||||
console.log(`app.on("will-quit")`);
|
||||
event.preventDefault();
|
||||
doAsyncQuit();
|
||||
});
|
||||
|
||||
let isAsyncQuitting = false;
|
||||
|
||||
const doAsyncQuit = (event: Electron.Event, exitCode = 0) => {
|
||||
if (isAsyncQuitting) {
|
||||
return;
|
||||
}
|
||||
|
||||
isAsyncQuitting = true;
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
await runRunnablesBeforeQuitOfBackEnd();
|
||||
} catch (error) {
|
||||
console.error("A beforeQuitOfBackEnd failed!!!!", error);
|
||||
exitCode = 1;
|
||||
}
|
||||
|
||||
app.exit(exitCode);
|
||||
})();
|
||||
};
|
||||
|
||||
app.on("will-quit", (event) => {
|
||||
runRunnablesBeforeQuitOfFrontEnd();
|
||||
event.preventDefault();
|
||||
|
||||
if (isIntegrationTesting || isAutoUpdating) {
|
||||
doAsyncQuit(event);
|
||||
}
|
||||
});
|
||||
|
||||
app.on("quit", (event, exitCode) => {
|
||||
event.preventDefault();
|
||||
doAsyncQuit(event, exitCode);
|
||||
});
|
||||
app.on("quit", () => {
|
||||
console.log(`app.on("quit")`);
|
||||
});
|
||||
|
||||
return undefined;
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { beforeElectronIsReadyInjectionToken } from "@k8slens/application-for-electron-main";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import autoUpdaterInjectable from "../features/auto-updater.injectable";
|
||||
import isAutoUpdatingInjectable from "../features/is-auto-updating.injectable";
|
||||
|
||||
const setupTrackingAutoUpdatingInjectable = getInjectable({
|
||||
id: "setup-tracking-auto-updating",
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const isAutoUpdating = di.inject(isAutoUpdatingInjectable);
|
||||
const autoUpdater = di.inject(autoUpdaterInjectable);
|
||||
|
||||
autoUpdater.on("before-quit-for-update", () => {
|
||||
isAutoUpdating.set(true);
|
||||
});
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeElectronIsReadyInjectionToken,
|
||||
});
|
||||
|
||||
export default setupTrackingAutoUpdatingInjectable;
|
||||
@ -18,6 +18,7 @@ import type { EmitAppEvent } from "../../common/app-event-bus/emit-event.injecta
|
||||
import type { Logger } from "../../common/logger";
|
||||
import type { SelfSignedCert } from "selfsigned";
|
||||
import type { KubeAuthProxyServer } from "../cluster/kube-auth-proxy-server.injectable";
|
||||
import stoppable from "stoppable";
|
||||
|
||||
export type GetClusterForRequest = (req: http.IncomingMessage) => Cluster | undefined;
|
||||
export type ServerIncomingMessage = SetRequired<http.IncomingMessage, "url" | "method">;
|
||||
@ -65,14 +66,14 @@ const disallowedPorts = new Set([
|
||||
]);
|
||||
|
||||
export class LensProxy {
|
||||
protected proxyServer: https.Server;
|
||||
protected proxyServer: https.Server & stoppable.WithStop;
|
||||
protected closed = false;
|
||||
protected retryCounters = new Map<string, number>();
|
||||
|
||||
constructor(private readonly dependencies: Dependencies) {
|
||||
this.configureProxy(dependencies.proxy);
|
||||
|
||||
this.proxyServer = https.createServer(
|
||||
this.proxyServer = stoppable(https.createServer(
|
||||
{
|
||||
key: dependencies.certificate.private,
|
||||
cert: dependencies.certificate.cert,
|
||||
@ -80,7 +81,7 @@ export class LensProxy {
|
||||
(req, res) => {
|
||||
this.handleRequest(req as ServerIncomingMessage, res);
|
||||
},
|
||||
);
|
||||
), 500);
|
||||
|
||||
this.proxyServer
|
||||
.on("upgrade", (req: ServerIncomingMessage, socket: net.Socket, head: Buffer) => {
|
||||
@ -175,7 +176,7 @@ export class LensProxy {
|
||||
this.dependencies.logger.info("[LENS-PROXY]: Closing server");
|
||||
|
||||
return new Promise<void>((resolve) => {
|
||||
this.proxyServer.close(() => resolve());
|
||||
this.proxyServer.stop(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { loggerTransportInjectionToken } from "../../common/logger/transports";
|
||||
import winstonLoggerInjectable from "../../common/winston-logger.injectable";
|
||||
import { beforeQuitOfBackEndInjectionToken } from "../start-main-application/runnable-tokens/phases";
|
||||
|
||||
const closeLoggerOnQuitInjectable = getInjectable({
|
||||
id: "close-file-transport-on-quit",
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const transports = di.injectMany(loggerTransportInjectionToken);
|
||||
const winstonLogger = di.inject(winstonLoggerInjectable);
|
||||
|
||||
winstonLogger.close();
|
||||
|
||||
for (const transport of transports) {
|
||||
transport.close?.();
|
||||
}
|
||||
},
|
||||
}),
|
||||
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||
});
|
||||
|
||||
export default closeLoggerOnQuitInjectable;
|
||||
@ -13,10 +13,6 @@ const fileLoggerTransportInjectable = getInjectable({
|
||||
handleExceptions: false,
|
||||
level: "debug",
|
||||
filename: "lens.log",
|
||||
/**
|
||||
* SAFTEY: the `ipcMain` check above should mean that this is only
|
||||
* called in the main process
|
||||
*/
|
||||
dirname: di.inject(directoryForLogsInjectable),
|
||||
maxsize: 1024 * 1024,
|
||||
maxFiles: 16,
|
||||
|
||||
@ -6,7 +6,6 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import loggerInjectable from "../../../../common/logger.injectable";
|
||||
import applicationWindowStateInjectable from "./application-window-state.injectable";
|
||||
import { BrowserWindow } from "electron";
|
||||
import type { ElectronWindow } from "./create-lens-window.injectable";
|
||||
import type { RequireExactlyOne } from "type-fest";
|
||||
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
|
||||
import getAbsolutePathInjectable from "../../../../common/path/get-absolute-path.injectable";
|
||||
@ -15,6 +14,7 @@ import isLinuxInjectable from "../../../../common/vars/is-linux.injectable";
|
||||
import pathExistsSyncInjectable from "../../../../common/fs/path-exists-sync.injectable";
|
||||
import { applicationInformationToken } from "@k8slens/application";
|
||||
import sessionCertificateVerifierInjectable from "./session-certificate-verifier.injectable";
|
||||
import type { ClusterFrameInfo } from "../../../../common/cluster-frames.injectable";
|
||||
|
||||
export type ElectronWindowTitleBarStyle = "hiddenInset" | "hidden" | "default" | "customButtonsOnHover";
|
||||
|
||||
@ -43,6 +43,21 @@ export interface ElectronWindowConfiguration {
|
||||
onDomReady?: () => void;
|
||||
}
|
||||
|
||||
export interface ElectronWindow {
|
||||
show: () => void;
|
||||
close: () => void;
|
||||
send: (args: SendToViewArgs) => void;
|
||||
loadFile: (filePath: string) => Promise<void>;
|
||||
loadUrl: (url: string) => Promise<void>;
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: unknown;
|
||||
}
|
||||
|
||||
export type CreateElectronWindow = (config: ElectronWindowConfiguration) => ElectronWindow;
|
||||
|
||||
const createElectronWindowInjectable = getInjectable({
|
||||
@ -158,7 +173,6 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
await browserWindow.loadFile(filePath);
|
||||
},
|
||||
|
||||
loadUrl: async (url) => {
|
||||
logger.info(
|
||||
`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from url: ${url}...`,
|
||||
@ -166,7 +180,6 @@ const createElectronWindowInjectable = getInjectable({
|
||||
|
||||
await browserWindow.loadURL(url);
|
||||
},
|
||||
|
||||
show: () => browserWindow.show(),
|
||||
close: () => browserWindow.close(),
|
||||
send: ({ channel, data, frameInfo }) => {
|
||||
|
||||
@ -3,24 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ContentSource, ElectronWindowTitleBarStyle } from "./create-electron-window.injectable";
|
||||
import type { ContentSource, ElectronWindow, ElectronWindowTitleBarStyle, SendToViewArgs } from "./create-electron-window.injectable";
|
||||
import createElectronWindowInjectable from "./create-electron-window.injectable";
|
||||
import type { ClusterFrameInfo } from "../../../../common/cluster-frames.injectable";
|
||||
|
||||
export interface ElectronWindow {
|
||||
show: () => void;
|
||||
close: () => void;
|
||||
send: (args: SendToViewArgs) => void;
|
||||
loadFile: (filePath: string) => Promise<void>;
|
||||
loadUrl: (url: string) => Promise<void>;
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
export interface SendToViewArgs {
|
||||
channel: string;
|
||||
frameInfo?: ClusterFrameInfo;
|
||||
data?: unknown;
|
||||
}
|
||||
|
||||
export interface LensWindow {
|
||||
id: string;
|
||||
@ -91,6 +75,7 @@ const createLensWindowInjectable = getInjectable({
|
||||
if (!browserWindow) {
|
||||
windowIsStarting = true;
|
||||
|
||||
console.log("BEFORE createElectronWindow");
|
||||
browserWindow = createElectronWindow({
|
||||
...configuration,
|
||||
onClose: () => {
|
||||
@ -104,11 +89,14 @@ const createLensWindowInjectable = getInjectable({
|
||||
url: urlForContent,
|
||||
} = configuration.getContentSource();
|
||||
|
||||
console.log("BEFORE configuration.beforeOpen?.()");
|
||||
const beforeOpen = configuration.beforeOpen?.();
|
||||
|
||||
if (filePathForContent) {
|
||||
console.log("BEFORE browserWindow.loadFile");
|
||||
await browserWindow.loadFile(filePathForContent);
|
||||
} else if (urlForContent) {
|
||||
console.log("BEFORE browserWindow.loadUrl");
|
||||
await browserWindow.loadUrl(urlForContent);
|
||||
}
|
||||
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { Runnable, RunnableSync } from "@k8slens/run-many";
|
||||
|
||||
export const beforeQuitOfFrontEndInjectionToken = getInjectionToken<RunnableSync>({
|
||||
id: "before-quit-of-front-end",
|
||||
export const afterQuitOfFrontEndInjectionToken = getInjectionToken<RunnableSync>({
|
||||
id: "after-quit-of-front-end",
|
||||
});
|
||||
|
||||
export const beforeQuitOfBackEndInjectionToken = getInjectionToken<Runnable>({
|
||||
|
||||
@ -26,8 +26,6 @@ const cleanUpShellSessionsInjectable = getInjectable({
|
||||
}
|
||||
|
||||
shellSessionProcesses.clear();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import emitAppEventInjectable from "../../../common/app-event-bus/emit-event.injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases";
|
||||
|
||||
const emitCloseToEventBusInjectable = getInjectable({
|
||||
id: "emit-close-to-event-bus",
|
||||
@ -19,7 +19,7 @@ const emitCloseToEventBusInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default emitCloseToEventBusInjectable;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { runInAction } from "mobx";
|
||||
import lensProtocolRouterMainInjectable from "../../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../../runnable-tokens/phases";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../../runnable-tokens/phases";
|
||||
|
||||
const flagRendererAsNotLoadedInjectable = getInjectable({
|
||||
id: "stop-deep-linking",
|
||||
@ -23,7 +23,7 @@ const flagRendererAsNotLoadedInjectable = getInjectable({
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default flagRendererAsNotLoadedInjectable;
|
||||
|
||||
@ -14,8 +14,6 @@ const stopKubeConfigSyncInjectable = getInjectable({
|
||||
const kubeConfigSyncManager = di.inject(kubeconfigSyncManagerInjectable);
|
||||
|
||||
kubeConfigSyncManager.stopSync();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import exitAppInjectable from "../../electron-app/features/exit-app.injectable";
|
||||
import quitAppInjectable from "../../electron-app/features/exit-app.injectable";
|
||||
import lensProxyInjectable from "../../lens-proxy/lens-proxy.injectable";
|
||||
import loggerInjectable from "../../../common/logger.injectable";
|
||||
import lensProxyPortInjectable from "../../lens-proxy/lens-proxy-port.injectable";
|
||||
@ -22,7 +22,7 @@ const setupLensProxyInjectable = getInjectable({
|
||||
instantiate: (di) => ({
|
||||
run: async () => {
|
||||
const lensProxy = di.inject(lensProxyInjectable);
|
||||
const exitApp = di.inject(exitAppInjectable);
|
||||
const quitApp = di.inject(quitAppInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||
const isWindows = di.inject(isWindowsInjectable);
|
||||
@ -37,7 +37,7 @@ const setupLensProxyInjectable = getInjectable({
|
||||
} catch (error: any) {
|
||||
showErrorPopup("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`);
|
||||
|
||||
return exitApp();
|
||||
return quitApp();
|
||||
}
|
||||
|
||||
// test proxy connection
|
||||
@ -54,7 +54,7 @@ const setupLensProxyInjectable = getInjectable({
|
||||
if (buildVersion.get() !== versionFromProxy) {
|
||||
logger.error("Proxy server responded with invalid response");
|
||||
|
||||
return exitApp();
|
||||
return quitApp();
|
||||
}
|
||||
|
||||
logger.info("⚡ LensProxy connection OK");
|
||||
@ -73,7 +73,7 @@ const setupLensProxyInjectable = getInjectable({
|
||||
|
||||
showErrorPopup("Lens Proxy Error", message.join("\n\n"));
|
||||
|
||||
return exitApp();
|
||||
return quitApp();
|
||||
}
|
||||
},
|
||||
runAfter: initializeBuildVersionInjectable,
|
||||
|
||||
@ -3,23 +3,26 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import clusterManagerInjectable from "../../cluster/manager.injectable";
|
||||
import { beforeQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases";
|
||||
import clustersInjectable from "../../../features/cluster/storage/common/clusters.injectable";
|
||||
import clusterConnectionInjectable from "../../cluster/cluster-connection.injectable";
|
||||
import { afterQuitOfFrontEndInjectionToken } from "../runnable-tokens/phases";
|
||||
|
||||
const stopClusterManagerInjectable = getInjectable({
|
||||
id: "stop-cluster-manager",
|
||||
|
||||
instantiate: (di) => ({
|
||||
run: () => {
|
||||
const clusterManager = di.inject(clusterManagerInjectable);
|
||||
const clusters = di.inject(clustersInjectable);
|
||||
|
||||
clusterManager.stop();
|
||||
for (const cluster of clusters.get()) {
|
||||
di.inject(clusterConnectionInjectable, cluster).disconnect();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
injectionToken: beforeQuitOfFrontEndInjectionToken,
|
||||
injectionToken: afterQuitOfFrontEndInjectionToken,
|
||||
});
|
||||
|
||||
export default stopClusterManagerInjectable;
|
||||
|
||||
@ -3,33 +3,24 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import exitAppInjectable from "./electron-app/features/exit-app.injectable";
|
||||
import clusterManagerInjectable from "./cluster/manager.injectable";
|
||||
import quitAppInjectable from "./electron-app/features/exit-app.injectable";
|
||||
import loggerInjectable from "../common/logger.injectable";
|
||||
import closeAllWindowsInjectable from "./start-main-application/lens-window/hide-all-windows/close-all-windows.injectable";
|
||||
import emitAppEventInjectable from "../common/app-event-bus/emit-event.injectable";
|
||||
import stopAllExtensionsInjectable from "../features/extensions/stopping/main/stop-all.injectable";
|
||||
|
||||
const stopServicesAndExitAppInjectable = getInjectable({
|
||||
id: "stop-services-and-exit-app",
|
||||
const quitAppExplicitlyInjectable = getInjectable({
|
||||
id: "quit-app-explicitly",
|
||||
|
||||
instantiate: (di) => {
|
||||
const exitApp = di.inject(exitAppInjectable);
|
||||
const clusterManager = di.inject(clusterManagerInjectable);
|
||||
const quitApp = di.inject(quitAppInjectable);
|
||||
const logger = di.inject(loggerInjectable);
|
||||
const closeAllWindows = di.inject(closeAllWindowsInjectable);
|
||||
const emitAppEvent = di.inject(emitAppEventInjectable);
|
||||
const stopAllExtensions = di.inject(stopAllExtensionsInjectable);
|
||||
|
||||
return async () => {
|
||||
return () => {
|
||||
emitAppEvent({ name: "service", action: "close" });
|
||||
closeAllWindows();
|
||||
clusterManager.stop();
|
||||
await stopAllExtensions();
|
||||
logger.info("SERVICE:QUIT");
|
||||
setTimeout(exitApp, 1000);
|
||||
quitApp();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default stopServicesAndExitAppInjectable;
|
||||
export default quitAppExplicitlyInjectable;
|
||||
|
||||
@ -14,8 +14,6 @@ const stopSyncingThemeFromOperatingSystemInjectable = getInjectable({
|
||||
const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable);
|
||||
|
||||
syncTheme.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -15,8 +15,6 @@ const stopTrayInjectable = getInjectable({
|
||||
const electronTray = di.inject(electronTrayInjectable);
|
||||
|
||||
electronTray.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
runAfter: stopReactiveTrayMenuItemsInjectable,
|
||||
}),
|
||||
|
||||
@ -14,8 +14,6 @@ const stopReactiveTrayMenuIconInjectable = getInjectable({
|
||||
const reactiveTrayMenuIcon = di.inject(reactiveTrayMenuIconInjectable);
|
||||
|
||||
reactiveTrayMenuIcon.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -14,8 +14,6 @@ const stopReactiveTrayMenuItemsInjectable = getInjectable({
|
||||
const reactiveTrayMenuItems = di.inject(reactiveTrayMenuItemsInjectable);
|
||||
|
||||
reactiveTrayMenuItems.stop();
|
||||
|
||||
return undefined;
|
||||
},
|
||||
}),
|
||||
|
||||
|
||||
@ -5,37 +5,20 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { trayMenuItemInjectionToken } from "../tray-menu-item-injection-token";
|
||||
import { computed } from "mobx";
|
||||
import stopServicesAndExitAppInjectable from "../../../stop-services-and-exit-app.injectable";
|
||||
import { withErrorSuppression } from "../../../../common/utils/with-error-suppression/with-error-suppression";
|
||||
import { pipeline } from "@ogre-tools/fp";
|
||||
import withErrorLoggingInjectable from "../../../../common/utils/with-error-logging/with-error-logging.injectable";
|
||||
import quitAppExplicitlyInjectable from "../../../stop-services-and-exit-app.injectable";
|
||||
|
||||
const quitAppTrayItemInjectable = getInjectable({
|
||||
id: "quit-app-tray-item",
|
||||
|
||||
instantiate: (di) => {
|
||||
const stopServicesAndExitApp = di.inject(stopServicesAndExitAppInjectable);
|
||||
const withErrorLoggingFor = di.inject(withErrorLoggingInjectable);
|
||||
|
||||
return {
|
||||
id: "quit-app",
|
||||
parentId: null,
|
||||
orderNumber: 150,
|
||||
label: computed(() => "Quit App"),
|
||||
enabled: computed(() => true),
|
||||
visible: computed(() => true),
|
||||
|
||||
click: pipeline(
|
||||
stopServicesAndExitApp,
|
||||
|
||||
withErrorLoggingFor(() => "[TRAY]: Quitting application failed."),
|
||||
|
||||
// TODO: Find out how to improve typing so that instead of
|
||||
// x => withErrorSuppression(x) there could only be withErrorSuppression
|
||||
(x) => withErrorSuppression(x),
|
||||
),
|
||||
};
|
||||
},
|
||||
instantiate: (di) => ({
|
||||
id: "quit-app",
|
||||
parentId: null,
|
||||
orderNumber: 150,
|
||||
label: computed(() => "Quit App"),
|
||||
enabled: computed(() => true),
|
||||
visible: computed(() => true),
|
||||
click: di.inject(quitAppExplicitlyInjectable),
|
||||
}),
|
||||
|
||||
injectionToken: trayMenuItemInjectionToken,
|
||||
});
|
||||
|
||||
@ -44,7 +44,7 @@ class DynamicBarrier {
|
||||
}
|
||||
}
|
||||
|
||||
const executeRunnableWith = <Param>(param: Param) => {
|
||||
const executeRunnableWith = <Param>(tokenId: string, param: Param) => {
|
||||
const barrier = new DynamicBarrier();
|
||||
|
||||
return async (runnable: RunnableWithId<Param>): Promise<void> => {
|
||||
@ -52,7 +52,9 @@ const executeRunnableWith = <Param>(param: Param) => {
|
||||
await barrier.blockOn(parentRunnable.id);
|
||||
}
|
||||
|
||||
console.log(`^^^ "${tokenId}" @ "${runnable.id}"`)
|
||||
await runnable.run(param);
|
||||
console.log(`--- "${tokenId}" @ "${runnable.id}"`)
|
||||
barrier.setFinished(runnable.id);
|
||||
};
|
||||
};
|
||||
@ -61,7 +63,7 @@ export function runManyFor(di: DiContainerForInjection): RunMany {
|
||||
const convertToWithId = convertToWithIdWith(di);
|
||||
|
||||
return <Param>(injectionToken: InjectionToken<Runnable<Param>, void>) => async (param: Param) => {
|
||||
const executeRunnable = executeRunnableWith(param);
|
||||
const executeRunnable = executeRunnableWith(injectionToken.id, param);
|
||||
const allRunnables = di.injectManyWithMeta(injectionToken).map(x => convertToWithId(x));
|
||||
|
||||
verifyRunnablesAreDAG(injectionToken.id, allRunnables);
|
||||
|
||||
@ -12,6 +12,13 @@ export interface Runnable<T = void> {
|
||||
id?: never;
|
||||
run: Run<T>;
|
||||
readonly runAfter?: SingleOrMany<Injectable<Runnable<T>, Runnable<T>, void>>;
|
||||
/**
|
||||
* Allows for specifying an black box ordering so that some runnables can be run at the end of the phase in
|
||||
* a sorted order but after all other ones
|
||||
*
|
||||
* NOTE: Must be exclusively set to `runAfter`
|
||||
*/
|
||||
readonly afterOrderNumber?: number;
|
||||
}
|
||||
|
||||
export interface RunnableWithId<T> {
|
||||
@ -20,6 +27,12 @@ export interface RunnableWithId<T> {
|
||||
readonly runAfter: RunnableWithId<T>[];
|
||||
}
|
||||
|
||||
export interface AfterRunnableWithId<T> {
|
||||
run: Run<T>;
|
||||
readonly id: string;
|
||||
readonly runAfter: number;
|
||||
}
|
||||
|
||||
export interface RunnableSync<T = void> {
|
||||
id?: never;
|
||||
run: RunSync<T>;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user