Extract agnostic and electron-main ways of starting application to separate packages (#7259)

* Introduce an agnostic way to start application is the Feature

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Introduce directory for application-packages

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Remove non agnostic timeslots from agnostic application

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Introduce empty package for electron main specific stuff for Application Feature

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Introduce electron-main specific timeslots

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Update injectable version

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Update README

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Tweak export names to make them easier to import

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Make starting of application synchronous for Electron main

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Tweak versions in package jsons

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Consolidate name of feature file

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

---------

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen authored and GitHub committed 2023-03-06 10:17:24 +02:00
1 parent a917494e9c
commit a9bd5ae7e2
35 files changed
+1841 -1036

No files matched your search

@@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
export type ApplicationInformation = {
name: string;
version: string;
productName: string;
copyright: string;
description: string;
k8sProxyVersion: string,
bundledKubectlVersion: string,
bundledHelmVersion: string,
sentryDsn: string,
contentSecurityPolicy: string,
welcomeRoute: string,
updatingIsEnabled: boolean;
dependencies: Partial<Record<string, string>>;
}
export const applicationInformationToken = getInjectionToken<ApplicationInformation>({
id: "application-information-token",
});
@@ -0,0 +1,17 @@
import { getFeature } from "@k8slens/feature-core";
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
export const applicationFeature = getFeature({
id: "application",
register: (di) => {
autoRegister({
di,
targetModule: module,
getRequireContexts: () => [
require.context("./", true, /\.injectable\.(ts|tsx)$/),
],
});
},
});
@@ -0,0 +1,42 @@
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
import { runManyFor } from "@ogre-tools/injectable-utils";
import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token";
import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token";
import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token";
export type StartApplication = () => Promise<void>;
export const startApplicationInjectionToken =
getInjectionToken<StartApplication>({
id: "start-application-injection-token",
});
const startApplicationInjectable = getInjectable({
id: "start-application",
instantiate: (di): StartApplication => {
const runManyAsync = runManyFor(di)
const beforeApplicationIsLoading = runManyAsync(
beforeApplicationIsLoadingInjectionToken
);
const onLoadOfApplication = runManyAsync(onLoadOfApplicationInjectionToken);
const afterApplicationIsLoaded = runManyAsync(
afterApplicationIsLoadedInjectionToken
);
return async () => {
await beforeApplicationIsLoading();
await onLoadOfApplication();
await afterApplicationIsLoaded();
};
},
injectionToken: startApplicationInjectionToken,
});
export default startApplicationInjectable;
@@ -0,0 +1,82 @@
import {
createContainer,
DiContainer,
getInjectable,
} from "@ogre-tools/injectable";
import { registerFeature } from "@k8slens/feature-core";
import { applicationFeature } from "../feature";
import { startApplicationInjectionToken } from "./start-application.injectable";
import { beforeApplicationIsLoadingInjectionToken } from "./timeslots/before-application-is-loading-injection-token";
import asyncFn, { AsyncFnMock } from "@async-fn/jest";
import { onLoadOfApplicationInjectionToken } from "./timeslots/on-load-of-application-injection-token";
import { afterApplicationIsLoadedInjectionToken } from "./timeslots/after-application-is-loaded-injection-token";
describe("starting-of-application", () => {
let di: DiContainer;
let beforeApplicationIsLoadingMock: AsyncFnMock<() => Promise<void>>;
let onLoadOfApplicationMock: AsyncFnMock<() => Promise<void>>;
let afterApplicationIsLoadedMock: AsyncFnMock<() => Promise<void>>;
beforeEach(() => {
di = createContainer("irrelevant");
registerFeature(di, applicationFeature);
beforeApplicationIsLoadingMock = asyncFn();
onLoadOfApplicationMock = asyncFn();
afterApplicationIsLoadedMock = asyncFn();
const beforeApplicationIsLoadingInjectable = getInjectable({
id: "before-application-is-loading",
instantiate: () => ({ run: beforeApplicationIsLoadingMock }),
injectionToken: beforeApplicationIsLoadingInjectionToken,
});
const onLoadOfApplicationInjectable = getInjectable({
id: "on-load-of-application",
instantiate: () => ({ run: onLoadOfApplicationMock }),
injectionToken: onLoadOfApplicationInjectionToken,
});
const afterApplicationIsLoadedInjectable = getInjectable({
id: "after-application-is-loaded",
instantiate: () => ({ run: afterApplicationIsLoadedMock }),
injectionToken: afterApplicationIsLoadedInjectionToken,
});
di.register(
beforeApplicationIsLoadingInjectable,
onLoadOfApplicationInjectable,
afterApplicationIsLoadedInjectable
);
});
describe("when application is started", () => {
beforeEach(() => {
const startApplication = di.inject(startApplicationInjectionToken);
startApplication();
});
it("calls runnables registered in before application is loading", () => {
expect(beforeApplicationIsLoadingMock).toHaveBeenCalled();
});
describe("when runnables in before application is loading resolve", () => {
beforeEach(async () => {
await beforeApplicationIsLoadingMock.resolve();
});
it("calls runnables registered in on load of application", () => {
expect(onLoadOfApplicationMock).toHaveBeenCalled();
});
it("when runnables in before application is loading resolve, calls runnables registered in after load of application", async () => {
await onLoadOfApplicationMock.resolve();
expect(afterApplicationIsLoadedMock).toHaveBeenCalled();
});
});
});
});
@@ -0,0 +1,7 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type { Runnable } from "@ogre-tools/injectable-utils";
export const afterApplicationIsLoadedInjectionToken =
getInjectionToken<Runnable>({
id: "after-application-is-loaded-injection-token",
});
@@ -0,0 +1,7 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type { Runnable } from "@ogre-tools/injectable-utils";
export const beforeApplicationIsLoadingInjectionToken =
getInjectionToken<Runnable>({
id: "before-application-is-loading-injection-token",
});
@@ -0,0 +1,6 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type { Runnable } from "@ogre-tools/injectable-utils";
export const onLoadOfApplicationInjectionToken = getInjectionToken<Runnable>({
id: "on-load-of-application",
});