import { QxReject } from "@quixos/camino-replica-core"; import { createRegistry } from "./gen/qx.js"; export const registry = createRegistry({ enroll: async ({ input, ports }) => { if (!/^[a-f0-9-]{36}$/.test(input.nonce) || input.label.length > 100) throw new QxReject("INVALID_DISPLAY_ENROLLMENT"); const enrolled = await ports.enrolled.resolve(); for (const previous of enrolled) { if ((await ports.existing["nonce.get"]({ receiver: previous.target, input: null })) === input.nonce) return previous.target; } if (enrolled.length >= 128) throw new QxReject("DISPLAY_ENROLLMENT_LIMIT"); const target = await ports.target.create( { nonce: input.nonce, initial: { label: input.label, generation: 0, presentation: null, observed: null } }, { key: "display" }, ); const ref = { ...target, expectation: { kind: "interface" as const, id: "interface:org.quixos.web-studio.display-target@1" as const }, }; await ports.enrolled.connect(ref, { key: "display" }); return ref; }, assign: async ({ input, ports }) => { if (input && !(await ports.subject["canPresent.call"]({ receiver: input.subject, input: input.presentation }))) throw new QxReject("INVALID_PRESENTATION"); const state = await ports.data.get(); if (state.generation === 4294967295) throw new QxReject("DISPLAY_GENERATION_EXHAUSTED"); const generation = state.generation + 1; for (const previous of await ports.selected.resolve()) await ports.selected.disconnect(previous.entry); if (input) await ports.selected.connect(input.subject, { key: "subject" }); for (const previous of await ports.mount.resolve()) await ports.mount.disconnect(previous.entry); if (input?.presentationMount) await ports.mount.connect(input.presentationMount, { key: "presentationMount" }); await ports.data.set({ ...state, generation, presentation: input?.presentation ?? null, observed: null }); return generation; }, acknowledge: async ({ input, ports }) => { if (!["mounted", "failed", "empty"].includes(input.status) || input.error.length > 2000) throw new QxReject("INVALID_DISPLAY_REPORT"); const state = await ports.data.get(); if (input.generation !== state.generation || (state.observed && input.sequence <= state.observed.sequence)) return false; if ((state.presentation === null) !== (input.status === "empty")) throw new QxReject("INVALID_DISPLAY_REPORT"); await ports.data.set({ ...state, observed: input }); return true; }, });