import { Doc } from "yjs"; import { DCode } from "../../../../../web/src/utils/types/root"; import { readDirectoryRecursively } from "../../../../api/site-export"; import { docs } from "../../entity/docs"; import { snapshot } from "../../entity/snapshot"; import { gzipAsync } from "../../entity/zlib"; import { codeBuild } from "./build-code"; import { CodeMode, code } from "./util-code"; import { user } from "../../entity/user"; import { SyncType } from "../../type"; import { sendWS } from "../../sync-handler"; import { conns } from "../../entity/conn"; export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => { await code .prep(id_site, mode) .new_file("index.tsx", "export const sample = 'hello_world'") .new_file( "package.json", JSON.stringify({ name: `${mode}-${id_site}`, dependencies: {} }, null, 2) ) .await(); let dcode = docs.code[id_site]; if (!docs.code[id_site]) { docs.code[id_site] = { id: id_site, build: {}, }; dcode = docs.code[id_site]; } if (dcode) { if (!dcode.build[mode]) { const build_dir = code.path(id_site, mode, "build"); await codeBuild(id_site, mode); dcode.build[mode] = codeLoad(id_site, build_dir); const doc = dcode.build[mode] as Doc; if (doc) { doc.on("update", async (e, origin) => { const bin = Y.encodeStateAsUpdate(doc); if (typeof snap !== "undefined" && snap.type === "code") { snap.build[mode].bin = bin; snapshot.update({ id: id_site, type: "code", build: snap.build, }); } const sv_local = await gzipAsync(bin); user.active.findAll({ site_id: id_site }).map((e) => { const ws = conns.get(e.client_id)?.ws; if (ws) { sendWS(ws, { type: SyncType.Event, event: "remote_svlocal", data: { type: "code", sv_local, id: id_site }, }); } }); }); } } const build: Record< string, { id_doc: number; bin: Uint8Array; } > = {}; for (const [k, v] of Object.entries(dcode.build)) { const bin = Y.encodeStateAsUpdate(v as Doc); build[k] = { bin: bin, id_doc: v.clientID }; } let snap = await snapshot.getOrCreate({ type: "code", id: id_site, build, }); if (snap.type === "code") { return snap; } } }; const codeLoad = (id: string, path: string) => { const doc = new Y.Doc() as DCode; const map = doc.getMap("map"); const files = new Y.Map(); const dirs = readDirectoryRecursively(path); for (const [k, v] of Object.entries(dirs)) { files.set(k, v); } doc.transact(() => { map.set("files", files as any); map.set("id", id); }); return doc; };