From 119e91b4b29fe432e7261a13e303b4d0ff16fa8b Mon Sep 17 00:00:00 2001 From: Janne Savolainen Date: Fri, 31 Mar 2023 14:35:51 +0300 Subject: [PATCH] Revert "Remove requirement for JSON of messages (#7426)" This reverts commit 132c51018bc4227df4a935a8f89aa1b4ff83910d. --- .../messaging/computed-channel/index.ts | 3 +++ ...annel-administration-channel.injectable.ts | 6 +++++ .../computed-channel.injectable.ts | 26 ++++++++++++++++--- .../computed-channel.test.tsx | 16 ++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/packages/technical-features/messaging/computed-channel/index.ts b/packages/technical-features/messaging/computed-channel/index.ts index dd72ecf71b..4516e0b9a6 100644 --- a/packages/technical-features/messaging/computed-channel/index.ts +++ b/packages/technical-features/messaging/computed-channel/index.ts @@ -6,4 +6,7 @@ export { export type { ChannelObserver, ComputedChannelFactory, + JsonifiableObject, + JsonifiableArray, + Jsonifiable, } from "./src/computed-channel/computed-channel.injectable"; diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts index da8dd4110a..b0fdb3c59f 100644 --- a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel-administration-channel.injectable.ts @@ -1,9 +1,15 @@ import { reaction } from "mobx"; + import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +import type { JsonPrimitive } from "type-fest"; import { computedChannelObserverInjectionToken } from "./computed-channel.injectable"; import { getMessageChannel } from "@k8slens/messaging"; +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"; diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts index b652a0c795..03f5a16aab 100644 --- a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.injectable.ts @@ -1,6 +1,7 @@ import { getInjectable, getInjectionToken } from "@ogre-tools/injectable"; import { + _getGlobalState, computed, IComputedValue, observable, @@ -12,8 +13,13 @@ import { import type { MessageChannel } from "@k8slens/messaging"; import { getMessageChannelListenerInjectable } from "@k8slens/messaging"; import { sendMessageToChannelInjectionToken } from "@k8slens/messaging"; +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 JsonifiableArray = readonly Jsonifiable[]; +export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray; + export type ComputedChannelFactory = ( channel: MessageChannel, pendingValue: T, @@ -23,12 +29,14 @@ export const computedChannelInjectionToken = getInjectionToken = { +export type ChannelObserver = { channel: MessageChannel; observer: IComputedValue; }; -export const computedChannelObserverInjectionToken = getInjectionToken>({ +export const computedChannelObserverInjectionToken = getInjectionToken< + ChannelObserver +>({ id: "computed-channel-observer", }); @@ -41,7 +49,19 @@ const computedChannelInjectable = getInjectable({ return ((channel, pendingValue) => { const observableValue = observable.box(pendingValue); - const computedValue = computed(() => observableValue.get()); + const computedValue = computed(() => { + const { trackingDerivation } = _getGlobalState(); + + const contextIsReactive = !!trackingDerivation; + + if (!contextIsReactive) { + throw new Error( + `Tried to access value of computed channel "${channel.id}" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.`, + ); + } + + return observableValue.get(); + }); const valueReceiverInjectable = getMessageChannelListenerInjectable({ id: `computed-channel-value-receiver-for-${channel.id}`, diff --git a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx index 6bea2ca76d..3ee58db25b 100644 --- a/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx +++ b/packages/technical-features/messaging/computed-channel/src/computed-channel/computed-channel.test.tsx @@ -292,6 +292,14 @@ const TestComponent = observer(({ someComputed }: { someComputed: IComputedValue }); }); + it("when accessing the computed value outside of reactive context, throws", () => { + expect(() => { + computedTestChannel.get(); + }).toThrow( + 'Tried to access value of computed channel "some-channel-id" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.', + ); + }); + it("no value gets listened in di-1 anymore", () => { expect(latestValueMessage).toBeUndefined(); }); @@ -373,6 +381,14 @@ const TestComponent = observer(({ someComputed }: { someComputed: IComputedValue }); }); }); + + it("when accessing the computed value outside of reactive context, throws", () => { + expect(() => { + computedTestChannel.get(); + }).toThrow( + 'Tried to access value of computed channel "some-channel-id" outside of reactive context. This is not possible, as the value is acquired asynchronously sometime *after* being observed. Not respecting that, the value could be stale.', + ); + }); }); it("given observation of unrelated computed channel is stopped, observation of other computed channel still works", async () => {