mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Introduce clearer boundry between extensions (#7164)
- Bundled extensions are always enabled, and are always compatible - Have bundled extensions be loaded asyncronously to support typescript dynamic import (which is typed) as opposed to require Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
1 parent
351f9d492f
commit
058494bc73
29 files changed
+440
-550
No files matched your search
@@ -24,7 +24,7 @@ const createExtensionInstanceInjectable = getInjectable({
|
||||
};
|
||||
|
||||
return (ExtensionClass, extension) => {
|
||||
const instance = new ExtensionClass(extension) as LensMainExtension;
|
||||
const instance = new ExtensionClass(extension as any) as LensMainExtension;
|
||||
|
||||
(instance as Writable<LensMainExtension>)[lensExtensionDependencies] = deps;
|
||||
|
||||
|
||||
@@ -10,16 +10,12 @@ import { noop } from "@k8slens/utilities";
|
||||
import type { LensProtocolRouterMain } from "../lens-protocol-router-main/lens-protocol-router-main";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import lensProtocolRouterMainInjectable from "../lens-protocol-router-main/lens-protocol-router-main.injectable";
|
||||
import getConfigurationFileModelInjectable from "../../../common/get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import { LensExtension } from "../../../extensions/lens-extension";
|
||||
import type { ObservableMap } from "mobx";
|
||||
import { runInAction } from "mobx";
|
||||
import extensionInstancesInjectable from "../../../extensions/extension-loader/extension-instances.injectable";
|
||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
||||
import pathExistsSyncInjectable from "../../../common/fs/path-exists-sync.injectable";
|
||||
import pathExistsInjectable from "../../../common/fs/path-exists.injectable";
|
||||
import readJsonSyncInjectable from "../../../common/fs/read-json-sync.injectable";
|
||||
import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable";
|
||||
import type { LensExtensionId } from "@k8slens/legacy-extensions";
|
||||
import type { LensExtensionState } from "../../../features/extensions/enabled/common/state.injectable";
|
||||
import enabledExtensionsStateInjectable from "../../../features/extensions/enabled/common/state.injectable";
|
||||
@@ -39,16 +35,8 @@ describe("protocol router tests", () => {
|
||||
beforeEach(async () => {
|
||||
const di = getDiForUnitTesting();
|
||||
|
||||
di.override(pathExistsInjectable, () => () => { throw new Error("tried call pathExists without override"); });
|
||||
di.override(pathExistsSyncInjectable, () => () => { throw new Error("tried call pathExistsSync without override"); });
|
||||
di.override(readJsonSyncInjectable, () => () => { throw new Error("tried call readJsonSync without override"); });
|
||||
di.override(writeJsonSyncInjectable, () => () => { throw new Error("tried call writeJsonSync without override"); });
|
||||
|
||||
enabledExtensions = di.inject(enabledExtensionsStateInjectable);
|
||||
|
||||
di.permitSideEffects(getConfigurationFileModelInjectable);
|
||||
|
||||
di.override(directoryForUserDataInjectable, () => "some-directory-for-user-data");
|
||||
di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data");
|
||||
|
||||
broadcastMessageMock = jest.fn();
|
||||
di.override(broadcastMessageInjectable, () => broadcastMessageMock);
|
||||
@@ -56,7 +44,9 @@ describe("protocol router tests", () => {
|
||||
extensionInstances = di.inject(extensionInstancesInjectable);
|
||||
lpr = di.inject(lensProtocolRouterMainInjectable);
|
||||
|
||||
lpr.rendererLoaded = true;
|
||||
runInAction(() => {
|
||||
lpr.rendererLoaded.set(true);
|
||||
});
|
||||
});
|
||||
|
||||
it("should broadcast invalid protocol on non-lens URLs", async () => {
|
||||
@@ -69,7 +59,19 @@ describe("protocol router tests", () => {
|
||||
expect(broadcastMessageMock).toBeCalledWith(ProtocolHandlerInvalid, "invalid host", "lens://foobar");
|
||||
});
|
||||
|
||||
it("should not throw when has valid host", async () => {
|
||||
it("should broadcast internal route when called with valid host", async () => {
|
||||
lpr.addInternalHandler("/", noop);
|
||||
|
||||
try {
|
||||
expect(await lpr.route("lens://app")).toBeUndefined();
|
||||
} catch (error) {
|
||||
expect(throwIfDefined(error)).not.toThrow();
|
||||
}
|
||||
|
||||
expect(broadcastMessageMock).toHaveBeenCalledWith(ProtocolHandlerInternal, "lens://app", "matched");
|
||||
});
|
||||
|
||||
it("should broadcast external route when called with valid host", async () => {
|
||||
const extId = uuid.v4();
|
||||
const ext = new LensExtension({
|
||||
id: extId,
|
||||
|
||||
+12
-16
@@ -6,7 +6,7 @@
|
||||
import * as proto from "../../../common/protocol-handler";
|
||||
import URLParse from "url-parse";
|
||||
import type { LensExtension } from "../../../extensions/lens-extension";
|
||||
import { observable, when, makeObservable } from "mobx";
|
||||
import { observable, when } from "mobx";
|
||||
import type { LensProtocolRouterDependencies, RouteAttempt } from "../../../common/protocol-handler";
|
||||
import { ProtocolHandlerInvalid } from "../../../common/protocol-handler";
|
||||
import { disposer, noop } from "@k8slens/utilities";
|
||||
@@ -39,17 +39,15 @@ export interface LensProtocolRouterMainDependencies extends LensProtocolRouterDe
|
||||
}
|
||||
|
||||
export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||
private missingExtensionHandlers: FallbackHandler[] = [];
|
||||
private readonly missingExtensionHandlers: FallbackHandler[] = [];
|
||||
|
||||
// TODO: This is used to solve out-of-place temporal dependency. Remove, and solve otherwise.
|
||||
@observable rendererLoaded = false;
|
||||
readonly rendererLoaded = observable.box(false);
|
||||
|
||||
protected disposers = disposer();
|
||||
protected readonly disposers = disposer();
|
||||
|
||||
constructor(protected readonly dependencies: LensProtocolRouterMainDependencies) {
|
||||
super(dependencies);
|
||||
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
public cleanup() {
|
||||
@@ -118,13 +116,12 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||
protected _routeToInternal(url: URLParse<Record<string, string | undefined>>): RouteAttempt {
|
||||
const rawUrl = url.toString(); // for sending to renderer
|
||||
const attempt = super._routeToInternal(url);
|
||||
const broadcastToRenderer = () => this.dependencies.broadcastMessage(proto.ProtocolHandlerInternal, rawUrl, attempt);
|
||||
|
||||
const sendRoutingToRenderer = () => this.dependencies.broadcastMessage(proto.ProtocolHandlerInternal, rawUrl, attempt);
|
||||
|
||||
if (this.rendererLoaded) {
|
||||
sendRoutingToRenderer();
|
||||
if (this.rendererLoaded.get()) {
|
||||
broadcastToRenderer();
|
||||
} else {
|
||||
this.disposers.push(when(() => this.rendererLoaded, sendRoutingToRenderer));
|
||||
this.disposers.push(when(() => this.rendererLoaded.get(), broadcastToRenderer));
|
||||
}
|
||||
|
||||
return attempt;
|
||||
@@ -141,13 +138,12 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
||||
* argument.
|
||||
*/
|
||||
const attempt = await super._routeToExtension(new URLParse(url.toString(), true));
|
||||
const broadcastToRenderer = () => this.dependencies.broadcastMessage(proto.ProtocolHandlerExtension, rawUrl, attempt);
|
||||
|
||||
const sendRoutingToRenderer = () => this.dependencies.broadcastMessage(proto.ProtocolHandlerExtension, rawUrl, attempt);
|
||||
|
||||
if (this.rendererLoaded) {
|
||||
sendRoutingToRenderer();
|
||||
if (this.rendererLoaded.get()) {
|
||||
broadcastToRenderer();
|
||||
} else {
|
||||
this.disposers.push(when(() => this.rendererLoaded, sendRoutingToRenderer));
|
||||
this.disposers.push(when(() => this.rendererLoaded.get(), broadcastToRenderer));
|
||||
}
|
||||
|
||||
return attempt;
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ const flagRendererAsLoadedInjectable = getInjectable({
|
||||
|
||||
runInAction(() => {
|
||||
// Todo: remove this kludge which enables out-of-place temporal dependency.
|
||||
lensProtocolRouterMain.rendererLoaded = true;
|
||||
lensProtocolRouterMain.rendererLoaded.set(true);
|
||||
});
|
||||
},
|
||||
}),
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ const flagRendererAsNotLoadedInjectable = getInjectable({
|
||||
|
||||
runInAction(() => {
|
||||
// Todo: remove this kludge which enables out-of-place temporal dependency.
|
||||
lensProtocolRouterMain.rendererLoaded = false;
|
||||
lensProtocolRouterMain.rendererLoaded.set(false);
|
||||
});
|
||||
|
||||
return undefined;
|
||||
|
||||
Reference in new issue
Block a user