feat: add native module realtime transport
CI / verify (pull_request) Successful in 37s
CI / infrastructure-smoke (pull_request) Successful in 13s
CI / migration-smoke (pull_request) Successful in 1m7s

This commit is contained in:
ekklesia
2026-08-23 18:47:18 -05:00
parent fcc531a39c
commit fc6c8045c4
53 changed files with 3959 additions and 108 deletions
@@ -17,7 +17,16 @@ export default defineModuleUi({
container.textContent = describePrincipal(context.principal);
void context.api.request("records");
void context.permissions.has("example.records.read");
const subscription = context.realtime.subscribe<{ readonly count: number }>("record-count", {
onSnapshot(state, sequence) {
container.textContent = `${state.count}:${sequence}`;
},
onStatus(status) {
container.setAttribute("data-realtime", status);
},
});
return () => {
subscription.close();
container.textContent = "";
};
},
@@ -6,6 +6,7 @@ import {
type ModuleUiApiClient,
type ModuleUiDefinition,
type ModuleUiHostContext,
type ModuleUiRealtimeClient,
parseModuleUiDefinition,
parseModuleUiExport,
} from "../src/index.js";
@@ -19,6 +20,10 @@ function validDefinition(): ModuleUiDefinition {
* contract, and this package deliberately does not take a DOM dependency to obtain one. */
const noop = (): void => undefined;
const noopRealtime: ModuleUiRealtimeClient = Object.freeze({
subscribe: () => Object.freeze({ close: noop }),
});
function fakeContainer(): Element & { textContent: string } {
return { textContent: "" } as unknown as Element & { textContent: string };
}
@@ -131,6 +136,7 @@ describe("the same module UI artifact hosted by two different hosts", () => {
api,
principal: { kind: "anonymous" },
permissions: { has: () => canPublish },
realtime: noopRealtime,
},
};
}
@@ -154,6 +160,7 @@ describe("the same module UI artifact hosted by two different hosts", () => {
api,
principal: { kind: "anonymous" },
permissions: { has: () => canPublish },
realtime: noopRealtime,
},
};
}