feat: adopt shared wasm wire schemas; resurrect collab e2e bundle (ysync 0008 A)
- standalone wasm/collab/types.ts: the CollabItem/CollabDelta data shapes now
come from MIT @pcbjam/shared (collab-wire zod schemas) via re-export; the
RUNTIME adapter interface (CollabBridge) stays here. emptyDelta/isEmptyDelta
alias the shared helpers — reconciler untouched.
- tests/collab/browser-entry.ts: fix the import path stale since the repo
restructure (web/apps/frontend → web/standalone) — the collab bundle had been
silently unbuildable; its opts type now tracks startCollab's real signature.
- tests/kicad/*-collab.spec.ts: update KicadCollab.start calls from the
pre-ysync-0004 { channel, settleMs } API to { provider: { kind:
"broadcastchannel", settleMs }, room } — the drift the broken bundle hid.
Verified: pl_editor 2/2, eeschema 2 passed, pcbnew 7 passed (skips pre-existing);
shared 47 unit tests; both typechecks clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c98e88c33b
commit
b69ba09ebd
7 changed files with 28 additions and 26 deletions
|
|
@ -16,11 +16,12 @@ import {
|
||||||
function start(
|
function start(
|
||||||
mod: CollabModule,
|
mod: CollabModule,
|
||||||
win: CollabWindow,
|
win: CollabWindow,
|
||||||
opts: { channel: string; settleMs?: number },
|
// Same opts as startCollab itself (ysync 0004: { provider, room }).
|
||||||
|
opts: Parameters<typeof startCollab>[2],
|
||||||
): ReturnType<typeof startCollab> {
|
): ReturnType<typeof startCollab> {
|
||||||
return startCollab(mod, win, {
|
return startCollab(mod, win, {
|
||||||
provider: { kind: "broadcastchannel", settleMs: opts.settleMs },
|
provider: { kind: "broadcastchannel", settleMs: opts.settleMs },
|
||||||
room: opts.channel,
|
room: opts.room,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ test.describe("eeschema collab bridge — two tabs (BroadcastChannel)", () => {
|
||||||
KicadCollab: { start: (m: unknown, win: unknown, o: unknown) => Promise<unknown> };
|
KicadCollab: { start: (m: unknown, win: unknown, o: unknown) => Promise<unknown> };
|
||||||
Module: unknown;
|
Module: unknown;
|
||||||
};
|
};
|
||||||
await w.KicadCollab.start(w.Module, window, { channel: ch, settleMs: 500 });
|
await w.KicadCollab.start(w.Module, window, { provider: { kind: "broadcastchannel", settleMs: 500 }, room: ch });
|
||||||
}, channel);
|
}, channel);
|
||||||
await startCollab(tabA);
|
await startCollab(tabA);
|
||||||
await startCollab(tabB);
|
await startCollab(tabB);
|
||||||
|
|
|
||||||
|
|
@ -414,7 +414,7 @@ test.describe("pcbnew collab bridge — two tabs (BroadcastChannel)", () => {
|
||||||
KicadCollab: { start: (m: unknown, win: unknown, o: unknown) => Promise<unknown> };
|
KicadCollab: { start: (m: unknown, win: unknown, o: unknown) => Promise<unknown> };
|
||||||
Module: unknown;
|
Module: unknown;
|
||||||
};
|
};
|
||||||
await w.KicadCollab.start(w.Module, window, { channel: ch, settleMs: 500 });
|
await w.KicadCollab.start(w.Module, window, { provider: { kind: "broadcastchannel", settleMs: 500 }, room: ch });
|
||||||
}, channel);
|
}, channel);
|
||||||
await startCollab(tabA);
|
await startCollab(tabA);
|
||||||
await startCollab(tabB);
|
await startCollab(tabB);
|
||||||
|
|
|
||||||
|
|
@ -195,7 +195,7 @@ test.describe("pl_editor collab bridge — two tabs (BroadcastChannel)", () => {
|
||||||
Module: unknown;
|
Module: unknown;
|
||||||
__collab?: unknown;
|
__collab?: unknown;
|
||||||
};
|
};
|
||||||
w.__collab = await w.KicadCollab.start(w.Module, window, { channel: ch, settleMs: 500 });
|
w.__collab = await w.KicadCollab.start(w.Module, window, { provider: { kind: "broadcastchannel", settleMs: 500 }, room: ch });
|
||||||
}, channel);
|
}, channel);
|
||||||
await startCollab(tabA);
|
await startCollab(tabA);
|
||||||
await startCollab(tabB);
|
await startCollab(tabB);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 011962c0992c5c30eba5487033f0c3609712dd28
|
Subproject commit 26d2d7951ba6a9574ff5149fb1a29a2a69d9176c
|
||||||
3
web/pnpm-lock.yaml
generated
3
web/pnpm-lock.yaml
generated
|
|
@ -45,6 +45,9 @@ importers:
|
||||||
'@ts-rest/core':
|
'@ts-rest/core':
|
||||||
specifier: ^3.52.1
|
specifier: ^3.52.1
|
||||||
version: 3.52.1(@types/node@22.19.19)(zod@3.25.76)
|
version: 3.52.1(@types/node@22.19.19)(zod@3.25.76)
|
||||||
|
yjs:
|
||||||
|
specifier: ^13.6.18
|
||||||
|
version: 13.6.31
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.24.1
|
specifier: ^3.24.1
|
||||||
version: 3.25.76
|
version: 3.25.76
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
// Wire contract shared with the C++ bridge (wasm/bindings/pl_editor_embind.cpp).
|
// Wire contract shared with the C++ bridge (wasm/bindings/*_embind.cpp).
|
||||||
// Schema-agnostic by design: an item is just { id, type, …arbitrary fields }. The
|
//
|
||||||
// reconciler hardcodes no field names — it diffs values keyed by field name.
|
// The data shapes (CollabItem / CollabDelta) and their zod schemas now live in
|
||||||
|
// MIT `@pcbjam/shared` (collab-wire.ts, ysync 0008) so any consumer — this GPL
|
||||||
|
// editor, tests, a backend — can validate the wasm from-to JSON against one
|
||||||
|
// source of truth. This module re-exports them under the established local names
|
||||||
|
// and keeps the RUNTIME adapter interface (CollabBridge), which is about how this
|
||||||
|
// app talks to a live wasm Module, not about the data.
|
||||||
|
|
||||||
export type CollabItem = {
|
import {
|
||||||
id: string;
|
emptyCollabDelta,
|
||||||
type: string;
|
isEmptyCollabDelta,
|
||||||
[field: string]: unknown;
|
type CollabDelta,
|
||||||
};
|
type CollabItem,
|
||||||
|
} from "@pcbjam/shared";
|
||||||
|
|
||||||
export type CollabDelta = {
|
export { collabDeltaSchema, collabItemSchema, parseCollabDelta } from "@pcbjam/shared";
|
||||||
added: CollabItem[];
|
export type { CollabDelta, CollabItem };
|
||||||
changed: CollabItem[];
|
|
||||||
removed: string[]; // uuids
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The two C++ bridge entry points + the emit hook, abstracted so the reconciler is
|
* The two C++ bridge entry points + the emit hook, abstracted so the reconciler is
|
||||||
|
|
@ -27,10 +30,5 @@ export interface CollabBridge {
|
||||||
onDelta(cb: (deltaJson: string) => void): void;
|
onDelta(cb: (deltaJson: string) => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function emptyDelta(): CollabDelta {
|
export const emptyDelta = emptyCollabDelta;
|
||||||
return { added: [], changed: [], removed: [] };
|
export const isEmptyDelta = isEmptyCollabDelta;
|
||||||
}
|
|
||||||
|
|
||||||
export function isEmptyDelta(d: CollabDelta): boolean {
|
|
||||||
return d.added.length === 0 && d.changed.length === 0 && d.removed.length === 0;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue