1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2023-03-17 09:48:45 +02:00
parent 88023e1f70
commit be79c4d044
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
6 changed files with 132 additions and 95 deletions

View File

@ -2,5 +2,6 @@
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="ES6PreferShortImport" enabled="true" level="INFORMATION" enabled_by_default="true" /> <inspection_tool class="ES6PreferShortImport" enabled="true" level="INFORMATION" enabled_by_default="true" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile> </profile>
</component> </component>

20
package-lock.json generated
View File

@ -34595,7 +34595,11 @@
"@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application": "^6.5.0-alpha.0",
"@k8slens/application-for-electron-main": "^6.5.0-alpha.0", "@k8slens/application-for-electron-main": "^6.5.0-alpha.0",
"@k8slens/legacy-extensions": "^1.0.0-alpha.0", "@k8slens/legacy-extensions": "^1.0.0-alpha.0",
"@k8slens/messaging": "^1.0.0-alpha.1",
"@k8slens/messaging-for-main": "^1.0.0-alpha.1",
"@k8slens/messaging-for-renderer": "^1.0.0-alpha.1",
"@k8slens/run-many": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1",
"@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1",
"@types/byline": "^4.2.33", "@types/byline": "^4.2.33",
@ -36661,7 +36665,11 @@
"@k8slens/generate-tray-icons": "^6.5.0-alpha.1", "@k8slens/generate-tray-icons": "^6.5.0-alpha.1",
"@k8slens/legacy-extension-example": "^1.0.0-alpha.1", "@k8slens/legacy-extension-example": "^1.0.0-alpha.1",
"@k8slens/legacy-extensions": "^1.0.0-alpha.1", "@k8slens/legacy-extensions": "^1.0.0-alpha.1",
"@k8slens/messaging": "^1.0.0-alpha.1",
"@k8slens/messaging-for-main": "^1.0.0-alpha.1",
"@k8slens/messaging-for-renderer": "^1.0.0-alpha.1",
"@k8slens/run-many": "^1.0.0-alpha.1", "@k8slens/run-many": "^1.0.0-alpha.1",
"@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/test-utils": "^1.0.0-alpha.1", "@k8slens/test-utils": "^1.0.0-alpha.1",
"@k8slens/utilities": "^1.0.0-alpha.1", "@k8slens/utilities": "^1.0.0-alpha.1",
"@ogre-tools/fp": "^15.1.2", "@ogre-tools/fp": "^15.1.2",
@ -37231,6 +37239,7 @@
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@async-fn/jest": "^1.6.4", "@async-fn/jest": "^1.6.4",
"@k8slens/eslint-config": "^6.5.0-alpha.1",
"type-fest": "^2.14.0" "type-fest": "^2.14.0"
}, },
"peerDependencies": { "peerDependencies": {
@ -37249,6 +37258,9 @@
"name": "@k8slens/messaging-for-main", "name": "@k8slens/messaging-for-main",
"version": "1.0.0-alpha.1", "version": "1.0.0-alpha.1",
"license": "MIT", "license": "MIT",
"devDependencies": {
"@k8slens/eslint-config": "^6.5.0-alpha.1"
},
"peerDependencies": { "peerDependencies": {
"@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application": "^6.5.0-alpha.0",
"@k8slens/feature-core": "^6.5.0-alpha.0", "@k8slens/feature-core": "^6.5.0-alpha.0",
@ -37263,6 +37275,9 @@
"name": "@k8slens/messaging-for-renderer", "name": "@k8slens/messaging-for-renderer",
"version": "1.0.0-alpha.1", "version": "1.0.0-alpha.1",
"license": "MIT", "license": "MIT",
"devDependencies": {
"@k8slens/eslint-config": "^6.5.0-alpha.1"
},
"peerDependencies": { "peerDependencies": {
"@k8slens/application": "^6.5.0-alpha.0", "@k8slens/application": "^6.5.0-alpha.0",
"@k8slens/messaging": "^1.0.0-alpha.1", "@k8slens/messaging": "^1.0.0-alpha.1",
@ -37288,7 +37303,10 @@
"packages/utility-features/startable-stoppable": { "packages/utility-features/startable-stoppable": {
"name": "@k8slens/startable-stoppable", "name": "@k8slens/startable-stoppable",
"version": "1.0.0-alpha.1", "version": "1.0.0-alpha.1",
"license": "MIT" "license": "MIT",
"devDependencies": {
"@k8slens/eslint-config": "^6.5.0-alpha.1"
}
}, },
"packages/utility-features/test-utils": { "packages/utility-features/test-utils": {
"name": "@k8slens/test-utils", "name": "@k8slens/test-utils",

View File

@ -0,0 +1,65 @@
import { reaction } from "mobx";
import type { MessageChannel } from "../message/message-channel-listener-injection-token";
import { getMessageChannelListenerInjectable } from "../message/message-channel-listener-injection-token";
import { sendMessageToChannelInjectionToken } from "../message/message-to-channel-injection-token.no-coverage";
import type { JsonPrimitive } from "type-fest";
import { computedChannelObserverInjectionToken } from "./computed-channel.injectable";
export type JsonifiableObject = { [Key in string]?: Jsonifiable } | { toJSON: () => Jsonifiable };
export type JsonifiableArray = readonly Jsonifiable[];
export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray;
export type ComputedChannelAdminMessage = {
channelId: string;
status: "became-observed" | "became-unobserved";
};
export const computedChannelAdministrationChannel: MessageChannel<ComputedChannelAdminMessage> = {
id: "computed-channel-administration-channel",
};
export const computedChannelAdministrationListenerInjectable = getMessageChannelListenerInjectable({
id: "computed-channel-administration",
getHandler: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
const disposersByChannelId = new Map<string, () => void>();
return (message) => {
if (message.status === "became-observed") {
const result = di
.injectMany(computedChannelObserverInjectionToken)
.find((channelObserver) => channelObserver.channel.id === message.channelId);
if (result === undefined) {
return;
}
const disposer = reaction(
() => result.observer.get(),
(observed) =>
sendMessageToChannel(
{
id: message.channelId,
},
observed,
),
{
fireImmediately: true,
},
);
disposersByChannelId.set(message.channelId, disposer);
} else {
const disposer = disposersByChannelId.get(message.channelId);
disposer?.();
}
};
},
channel: computedChannelAdministrationChannel,
});

View File

@ -7,18 +7,14 @@ import {
observable, observable,
onBecomeObserved, onBecomeObserved,
onBecomeUnobserved, onBecomeUnobserved,
reaction,
runInAction, runInAction,
} from "mobx"; } from "mobx";
import type { MessageChannel } from "../message/message-channel-listener-injection-token"; import type { MessageChannel } from "../message/message-channel-listener-injection-token";
import { getMessageChannelListenerInjectable } from "../message/message-channel-listener-injection-token"; import { getMessageChannelListenerInjectable } from "../message/message-channel-listener-injection-token";
import { sendMessageToChannelInjectionToken } from "../message/message-to-channel-injection-token.no-coverage"; import { sendMessageToChannelInjectionToken } from "../message/message-to-channel-injection-token.no-coverage";
import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
import { pipeline } from "@ogre-tools/fp";
import { filter, groupBy, map, nth, toPairs } from "lodash/fp";
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
import type { JsonPrimitive } from "type-fest"; import type { JsonPrimitive } from "type-fest";
import { computedChannelAdministrationChannel } from "./computed-channel-administration-channel.injectable";
export type JsonifiableObject = { [Key in string]?: Jsonifiable } | { toJSON: () => Jsonifiable }; export type JsonifiableObject = { [Key in string]?: Jsonifiable } | { toJSON: () => Jsonifiable };
export type JsonifiableArray = readonly Jsonifiable[]; export type JsonifiableArray = readonly Jsonifiable[];
@ -37,10 +33,6 @@ export type ChannelObserver<T extends Jsonifiable> = {
channel: MessageChannel<T>; channel: MessageChannel<T>;
observer: IComputedValue<T>; observer: IComputedValue<T>;
}; };
export type ComputedChannelAdminMessage = {
channelId: string;
status: "became-observed" | "became-unobserved";
};
export const computedChannelObserverInjectionToken = getInjectionToken< export const computedChannelObserverInjectionToken = getInjectionToken<
ChannelObserver<Jsonifiable> ChannelObserver<Jsonifiable>
@ -48,10 +40,6 @@ export const computedChannelObserverInjectionToken = getInjectionToken<
id: "computed-channel-observer", id: "computed-channel-observer",
}); });
export const computedChannelAdministrationChannel: MessageChannel<ComputedChannelAdminMessage> = {
id: "computed-channel-administration-channel",
};
const computedChannelInjectable = getInjectable({ const computedChannelInjectable = getInjectable({
id: "computed-channel", id: "computed-channel",
@ -119,83 +107,4 @@ const computedChannelInjectable = getInjectable({
injectionToken: computedChannelInjectionToken, injectionToken: computedChannelInjectionToken,
}); });
export const duplicateChannelObserverGuardInjectable = getInjectable({
id: "duplicate-channel-observer-guard",
instantiate: (di) => {
const computedInjectMany = di.inject(computedInjectManyInjectable);
return {
run: () => {
reaction(
() => computedInjectMany(computedChannelObserverInjectionToken).get(),
(observers) => {
const duplicateObserverChannelIds = pipeline(
observers,
groupBy((observer) => observer.channel.id),
toPairs,
filter(([, channelObservers]) => channelObservers.length > 1),
map(nth(0)),
);
if (duplicateObserverChannelIds.length) {
throw new Error(
`Tried to register duplicate channel observer for channels "${duplicateObserverChannelIds.join(
'", "',
)}"`,
);
}
},
);
},
};
},
injectionToken: onLoadOfApplicationInjectionToken,
});
export const computedChannelAdministrationListenerInjectable = getMessageChannelListenerInjectable({
id: "computed-channel-administration",
getHandler: (di) => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
const disposersByChannelId = new Map<string, () => void>();
return (message) => {
if (message.status === "became-observed") {
const result = di
.injectMany(computedChannelObserverInjectionToken)
.find((channelObserver) => channelObserver.channel.id === message.channelId);
if (result === undefined) {
return;
}
const disposer = reaction(
() => result.observer.get(),
(observed) =>
sendMessageToChannel(
{
id: message.channelId,
},
observed,
),
{
fireImmediately: true,
},
);
disposersByChannelId.set(message.channelId, disposer);
} else {
const disposer = disposersByChannelId.get(message.channelId);
disposer?.();
}
};
},
channel: computedChannelAdministrationChannel,
});
export default computedChannelInjectable; export default computedChannelInjectable;

View File

@ -20,13 +20,15 @@ import { registerMobX } from "@ogre-tools/injectable-extension-for-mobx";
import { registerFeature } from "@k8slens/feature-core"; import { registerFeature } from "@k8slens/feature-core";
import { messagingFeatureForUnitTesting } from "../../unit-testing"; import { messagingFeatureForUnitTesting } from "../../unit-testing";
import { import {
computedChannelAdministrationChannel,
ComputedChannelAdminMessage,
computedChannelInjectionToken, computedChannelInjectionToken,
computedChannelObserverInjectionToken, computedChannelObserverInjectionToken,
} from "./computed-channel.injectable"; } from "./computed-channel.injectable";
import { runWithThrownMobxReactions, renderFor } from "@k8slens/test-utils"; import { runWithThrownMobxReactions, renderFor } from "@k8slens/test-utils";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import {
computedChannelAdministrationChannel,
ComputedChannelAdminMessage,
} from "./computed-channel-administration-channel.injectable";
const testChannel: MessageChannel<string> = { id: "some-channel-id" }; const testChannel: MessageChannel<string> = { id: "some-channel-id" };
const testChannel2: MessageChannel<string> = { id: "some-other-channel-id" }; const testChannel2: MessageChannel<string> = { id: "some-other-channel-id" };

View File

@ -0,0 +1,42 @@
import { onLoadOfApplicationInjectionToken } from "@k8slens/application";
import { pipeline } from "@ogre-tools/fp";
import { getInjectable } from "@ogre-tools/injectable";
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
import { filter, groupBy, nth, map, toPairs } from "lodash/fp";
import { reaction } from "mobx";
import { computedChannelObserverInjectionToken } from "./computed-channel.injectable";
export const duplicateChannelObserverGuardInjectable = getInjectable({
id: "duplicate-channel-observer-guard",
instantiate: (di) => {
const computedInjectMany = di.inject(computedInjectManyInjectable);
return {
run: () => {
reaction(
() => computedInjectMany(computedChannelObserverInjectionToken).get(),
(observers) => {
const duplicateObserverChannelIds = pipeline(
observers,
groupBy((observer) => observer.channel.id),
toPairs,
filter(([, channelObservers]) => channelObservers.length > 1),
map(nth(0)),
);
if (duplicateObserverChannelIds.length) {
throw new Error(
`Tried to register duplicate channel observer for channels "${duplicateObserverChannelIds.join(
'", "',
)}"`,
);
}
},
);
},
};
},
injectionToken: onLoadOfApplicationInjectionToken,
});