Skip to content

Commit 70a2da3

Browse files
committed
improve default mocking for waveobjs
1 parent ab95a25 commit 70a2da3

3 files changed

Lines changed: 88 additions & 19 deletions

File tree

frontend/app/waveenv/waveenv.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ export type WaveEnv = {
6565
getSettingsKeyAtom: SettingsKeyAtomFnType;
6666
getBlockMetaKeyAtom: BlockMetaKeyAtomFnType;
6767
getConnConfigKeyAtom: ConnConfigKeyAtomFnType;
68+
69+
// the mock fields are only usable in the preview server (may be be null or throw errors in production)
70+
mockSetWaveObj: (oref: string, obj: WaveObj) => void;
6871
mockTabModel?: TabModel;
6972
};
7073

frontend/app/waveenv/waveenvimpl.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ export function makeWaveEnvImpl(): WaveEnv {
4141
},
4242
getBlockMetaKeyAtom,
4343
getConnConfigKeyAtom,
44+
mockSetWaveObj: (_oref: string, _obj: WaveObj) => {
45+
throw new Error("mockSetWaveObj is only available in the preview server");
46+
},
4447
};
4548
}

frontend/preview/mock/mockwaveenv.ts

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,28 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import { makeDefaultConnStatus } from "@/app/store/global";
5+
import { globalStore } from "@/app/store/jotaiStore";
56
import { TabModel } from "@/app/store/tab-model";
7+
import { handleWaveEvent } from "@/app/store/wps";
68
import { RpcApiType } from "@/app/store/wshclientapi";
79
import { WaveEnv } from "@/app/waveenv/waveenv";
810
import { PlatformMacOS, PlatformWindows } from "@/util/platformutil";
911
import { Atom, atom, PrimitiveAtom } from "jotai";
1012
import { DefaultFullConfig } from "./defaultconfig";
1113
import { previewElectronApi } from "./preview-electron-api";
1214

15+
// What works "out of the box" in the mock environment (no MockEnv overrides needed):
16+
//
17+
// RPC calls (handled in makeMockRpc):
18+
// - rpc.EventPublishCommand -- dispatches to handleWaveEvent(); works when the subscriber
19+
// is purely FE-based (registered via WPS on the frontend)
20+
// - rpc.GetMetaCommand -- reads .meta from the mock WOS atom for the given oref
21+
// - rpc.SetMetaCommand -- writes .meta to the mock WOS atom (null values delete keys)
22+
// - rpc.UpdateTabNameCommand -- updates .name on the Tab WaveObj in the mock WOS
23+
//
24+
// Any other RPC call falls through to a console.log and resolves null.
25+
// Override specific calls via MockEnv.rpc (keys are the Command method names, e.g. "GetMetaCommand").
26+
1327
type RpcOverrides = {
1428
[K in keyof RpcApiType as K extends `${string}Command` ? K : never]?: (...args: any[]) => any;
1529
};
@@ -113,8 +127,47 @@ function makeMockGlobalAtoms(
113127
return { ...defaults, ...atomOverrides };
114128
}
115129

116-
export function makeMockRpc(overrides?: RpcOverrides): RpcApiType {
130+
type MockWosFns = {
131+
getWaveObjectAtom: <T extends WaveObj>(oref: string) => PrimitiveAtom<T>;
132+
mockSetWaveObj: (oref: string, obj: WaveObj) => void;
133+
};
134+
135+
export function makeMockRpc(overrides: RpcOverrides, wos: MockWosFns): RpcApiType {
117136
const dispatchMap = new Map<string, (...args: any[]) => any>();
137+
dispatchMap.set("eventpublish", (_client, data: WaveEvent) => {
138+
console.log("[mock eventpublish]", data);
139+
handleWaveEvent(data);
140+
return Promise.resolve(null);
141+
});
142+
dispatchMap.set("getmeta", (_client, data: CommandGetMetaData) => {
143+
const objAtom = wos.getWaveObjectAtom(data.oref);
144+
const current = globalStore.get(objAtom) as WaveObj & { meta?: MetaType };
145+
return Promise.resolve(current?.meta ?? {});
146+
});
147+
dispatchMap.set("setmeta", (_client, data: CommandSetMetaData) => {
148+
const objAtom = wos.getWaveObjectAtom(data.oref);
149+
const current = globalStore.get(objAtom) as WaveObj & { meta?: MetaType };
150+
const updatedMeta = { ...(current?.meta ?? {}) };
151+
for (const [key, value] of Object.entries(data.meta)) {
152+
if (value === null) {
153+
delete updatedMeta[key];
154+
} else {
155+
(updatedMeta as any)[key] = value;
156+
}
157+
}
158+
const updated = { ...current, meta: updatedMeta };
159+
wos.mockSetWaveObj(data.oref, updated);
160+
return Promise.resolve(null);
161+
});
162+
dispatchMap.set("updatetabname", (_client, data: { args: [string, string] }) => {
163+
const [tabId, newName] = data.args;
164+
const tabORef = "tab:" + tabId;
165+
const objAtom = wos.getWaveObjectAtom(tabORef);
166+
const current = globalStore.get(objAtom) as Tab;
167+
const updated = { ...current, name: newName };
168+
wos.mockSetWaveObj(tabORef, updated);
169+
return Promise.resolve(null);
170+
});
118171
if (overrides) {
119172
for (const key of Object.keys(overrides) as (keyof RpcOverrides)[]) {
120173
const cmdName = key.slice(0, -"Command".length).toLowerCase();
@@ -154,7 +207,8 @@ export function makeMockWaveEnv(mockEnv?: MockEnv): MockWaveEnv {
154207
const overrides: MockEnv = mockEnv ?? {};
155208
const platform = overrides.platform ?? PlatformMacOS;
156209
const connStatusAtomCache = new Map<string, PrimitiveAtom<ConnStatus>>();
157-
const waveObjectAtomCache = new Map<string, Atom<any>>();
210+
const waveObjectValueAtomCache = new Map<string, PrimitiveAtom<any>>();
211+
const waveObjectDerivedAtomCache = new Map<string, Atom<any>>();
158212
const blockMetaKeyAtomCache = new Map<string, Atom<any>>();
159213
const connConfigKeyAtomCache = new Map<string, Atom<any>>();
160214
const atoms = makeMockGlobalAtoms(overrides.settings, overrides.atoms, overrides.tabId);
@@ -165,14 +219,29 @@ export function makeMockWaveEnv(mockEnv?: MockEnv): MockWaveEnv {
165219
}
166220
return "user@localhost";
167221
});
222+
const mockWosFns: MockWosFns = {
223+
getWaveObjectAtom: <T extends WaveObj>(oref: string) => {
224+
if (!waveObjectValueAtomCache.has(oref)) {
225+
const obj = (overrides.mockWaveObjs?.[oref] ?? null) as T;
226+
waveObjectValueAtomCache.set(oref, atom(obj) as PrimitiveAtom<T>);
227+
}
228+
return waveObjectValueAtomCache.get(oref) as PrimitiveAtom<T>;
229+
},
230+
mockSetWaveObj: (oref: string, obj: WaveObj) => {
231+
if (!waveObjectValueAtomCache.has(oref)) {
232+
waveObjectValueAtomCache.set(oref, atom(null as WaveObj));
233+
}
234+
globalStore.set(waveObjectValueAtomCache.get(oref), obj);
235+
},
236+
};
168237
const env = {
169238
mockEnv: overrides,
170239
electron: {
171240
...previewElectronApi,
172241
getPlatform: () => platform,
173242
...overrides.electron,
174243
},
175-
rpc: makeMockRpc(overrides.rpc),
244+
rpc: makeMockRpc(overrides.rpc, mockWosFns),
176245
atoms,
177246
getSettingsKeyAtom: makeMockSettingsKeyAtom(atoms.settingsAtom, overrides.settings),
178247
platform,
@@ -201,36 +270,30 @@ export function makeMockWaveEnv(mockEnv?: MockEnv): MockWaveEnv {
201270
return connStatusAtomCache.get(conn);
202271
},
203272
wos: {
204-
getWaveObjectAtom: <T extends WaveObj>(oref: string) => {
205-
const cacheKey = oref + ":value";
206-
if (!waveObjectAtomCache.has(cacheKey)) {
207-
const obj = (overrides.mockWaveObjs?.[oref] ?? null) as T;
208-
waveObjectAtomCache.set(cacheKey, atom(obj));
209-
}
210-
return waveObjectAtomCache.get(cacheKey) as PrimitiveAtom<T>;
211-
},
273+
getWaveObjectAtom: mockWosFns.getWaveObjectAtom,
212274
getWaveObjectLoadingAtom: (oref: string) => {
213275
const cacheKey = oref + ":loading";
214-
if (!waveObjectAtomCache.has(cacheKey)) {
215-
waveObjectAtomCache.set(cacheKey, atom(false));
276+
if (!waveObjectDerivedAtomCache.has(cacheKey)) {
277+
waveObjectDerivedAtomCache.set(cacheKey, atom(false));
216278
}
217-
return waveObjectAtomCache.get(cacheKey) as Atom<boolean>;
279+
return waveObjectDerivedAtomCache.get(cacheKey) as Atom<boolean>;
218280
},
219281
isWaveObjectNullAtom: (oref: string) => {
220282
const cacheKey = oref + ":isnull";
221-
if (!waveObjectAtomCache.has(cacheKey)) {
222-
waveObjectAtomCache.set(
283+
if (!waveObjectDerivedAtomCache.has(cacheKey)) {
284+
waveObjectDerivedAtomCache.set(
223285
cacheKey,
224286
atom((get) => get(env.wos.getWaveObjectAtom(oref)) == null)
225287
);
226288
}
227-
return waveObjectAtomCache.get(cacheKey) as Atom<boolean>;
289+
return waveObjectDerivedAtomCache.get(cacheKey) as Atom<boolean>;
228290
},
229291
useWaveObjectValue: <T extends WaveObj>(oref: string): [T, boolean] => {
230-
const obj = (overrides.mockWaveObjs?.[oref] ?? null) as T;
231-
return [obj, false];
292+
const objAtom = env.wos.getWaveObjectAtom<T>(oref);
293+
return [globalStore.get(objAtom), false];
232294
},
233295
},
296+
mockSetWaveObj: mockWosFns.mockSetWaveObj,
234297
getBlockMetaKeyAtom: <T extends keyof MetaType>(blockId: string, key: T) => {
235298
const cacheKey = blockId + "#meta-" + key;
236299
if (!blockMetaKeyAtomCache.has(cacheKey)) {

0 commit comments

Comments
 (0)