This commit is contained in:
Rizky 2024-03-21 08:41:33 +07:00
parent 1662c83592
commit a8849248ed
6 changed files with 72 additions and 144 deletions

View File

@ -67,12 +67,12 @@ export const SyncActions = {
bin: Uint8Array bin: Uint8Array
) => ({}) as { diff: Uint8Array; sv: Uint8Array } | void, ) => ({}) as { diff: Uint8Array; sv: Uint8Array } | void,
diff_local: async ( diff_local: async (
mode: "page" | "comp" | "site" | "code", mode: "page" | "comp" | "site" ,
id: string, id: string,
bin: Uint8Array bin: Uint8Array
) => {}, ) => {},
sv_remote: async ( sv_remote: async (
mode: "page" | "comp" | "site" | "code", mode: "page" | "comp" | "site" ,
id: string, id: string,
sv: Uint8Array, sv: Uint8Array,
diff: Uint8Array diff: Uint8Array

View File

@ -15,10 +15,7 @@ export const yjs_sv_remote: SAction["yjs"]["sv_remote"] = async function (
return; return;
} }
let doc = null; let doc = null;
if (mode !== "code") doc = docs[mode][id].doc; doc = docs[mode][id].doc;
else {
doc = docs.code[id].build.site;
}
const diff_local = Y.encodeStateAsUpdate(doc as any, await gunzipAsync(sv)); const diff_local = Y.encodeStateAsUpdate(doc as any, await gunzipAsync(sv));
Y.applyUpdate(doc as any, await gunzipAsync(diff), "local"); Y.applyUpdate(doc as any, await gunzipAsync(diff), "local");
return { diff: await gzipAsync(diff_local) }; return { diff: await gzipAsync(diff_local) };

View File

@ -2,11 +2,20 @@ import globalExternals from "@fal-works/esbuild-plugin-global-externals";
import { style } from "@hyrious/esbuild-plugin-style"; import { style } from "@hyrious/esbuild-plugin-style";
import { context } from "esbuild"; import { context } from "esbuild";
import { dirAsync, existsAsync, removeAsync, writeAsync } from "fs-jetpack"; import { dirAsync, existsAsync, removeAsync, writeAsync } from "fs-jetpack";
import { DCode } from "../../../../../web/src/utils/types/root";
import { readDirectoryRecursively } from "../../../../api/site-export";
import { docs } from "../../entity/docs";
import { code } from "./util-code";
import { server } from "./server-main"; import { server } from "./server-main";
import { code } from "./util-code";
import { user } from "../../entity/user";
import { conns } from "../../entity/conn";
import { SyncType } from "../../type";
import { Packr } from "msgpackr";
import { ServerWebSocket } from "bun";
import { WSData } from "../../../../../../pkgs/core/server/create";
const packr = new Packr({ structuredClone: true });
const sendWS = (ws: ServerWebSocket<WSData>, msg: any) => {
ws.sendBinary(packr.pack(msg));
};
export const codeBuild = async (id_site: any) => { export const codeBuild = async (id_site: any) => {
const src_path = code.path(id_site, "site", "src"); const src_path = code.path(id_site, "site", "src");
@ -185,14 +194,21 @@ if (typeof global.server_hook === "function") {
"site" "site"
); );
} }
const cdoc = docs.code[id_site];
if (cdoc) { const client_ids = new Set<string>();
const doc = cdoc.build["site"]; user.active.findAll({ site_id: id_site }).forEach((e) => {
const build_dir = code.path(id_site, "site", "build"); client_ids.add(e.client_id);
if (doc) { });
codeApplyChanges(build_dir, doc);
client_ids.forEach((client_id) => {
const ws = conns.get(client_id)?.ws;
if (ws) {
sendWS(ws, {
type: SyncType.Event,
event: "code_changes",
});
} }
} });
}); });
}, },
}, },
@ -223,27 +239,27 @@ if (typeof global.server_hook === "function") {
} }
}; };
const codeApplyChanges = (path: string, doc: DCode) => { // const codeApplyChanges = (path: string, doc: DCode) => {
const map = doc.getMap("map"); // const map = doc.getMap("map");
const files = map.get("files"); // const files = map.get("files");
const dirs = readDirectoryRecursively(path); // const dirs = readDirectoryRecursively(path);
doc.transact(() => { // doc.transact(() => {
files?.forEach((v, k) => { // files?.forEach((v, k) => {
if (!dirs[k]) { // if (!dirs[k]) {
files?.delete(k); // files?.delete(k);
} // }
}); // });
for (const [k, v] of Object.entries(dirs)) { // for (const [k, v] of Object.entries(dirs)) {
if (files) { // if (files) {
files.set(k, v); // files.set(k, v);
} // }
} // }
}); // });
return doc; // return doc;
}; // };
const codeError = async ( const codeError = async (
id_site: string, id_site: string,

View File

@ -1,15 +1,5 @@
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 { codeBuild } from "./build-code";
import { CodeMode, code } from "./util-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) => { export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
await code await code
@ -21,100 +11,5 @@ export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
) )
.await(); .await();
let dcode = docs.code[id_site]; await codeBuild(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);
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);
const client_ids = new Set<string>();
user.active.findAll({ site_id: id_site }).forEach((e) => {
client_ids.add(e.client_id);
});
client_ids.forEach((client_id) => {
const ws = conns.get(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") {
snapshot.update({
id: id_site,
type: "code",
build,
});
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;
}; };

View File

@ -182,14 +182,33 @@ export const edInitSync = (p: PG) => {
} }
p.render(); p.render();
}, },
async code_changes() {
const w = window as any;
const url = `/prod/${
p.site.id
}/_prasi/code/index.js?ts=${Date.now()}`;
const fn = new Function(
"callback",
`import("${url}").then(callback)`
);
await new Promise<void>((resolve) => {
fn((exports: any) => {
for (const [k, v] of Object.entries(exports)) {
w[k] = v;
}
resolve();
});
});
await treeRebuild(p);
p.render();
},
async remote_svlocal(data) { async remote_svlocal(data) {
let doc = null as any; let doc = null as any;
if (data.type === "page" && p.page.cur.id === data.id) { if (data.type === "page" && p.page.cur.id === data.id) {
doc = p.page.doc as Y.Doc; doc = p.page.doc as Y.Doc;
} else if (data.type === "comp" && p.comp.list[data.id]) { } else if (data.type === "comp" && p.comp.list[data.id]) {
doc = p.comp.list[data.id].doc; doc = p.comp.list[data.id].doc;
} else if (data.type === "code") {
doc = p.code.site.doc;
} }
if (doc && p.sync) { if (doc && p.sync) {

View File

@ -79,7 +79,7 @@ export const clientStartSync = async (arg: {
events: { events: {
editor_start: (arg: UserConf) => void; editor_start: (arg: UserConf) => void;
remote_svlocal: (arg: { remote_svlocal: (arg: {
type: "page" | "comp" | "code"; type: "page" | "comp";
id: string; id: string;
sv_local: Uint8Array; sv_local: Uint8Array;
}) => void; }) => void;
@ -91,6 +91,7 @@ export const clientStartSync = async (arg: {
} }
> >
) => void; ) => void;
code_changes: () => void;
disconnected: () => { reconnect: boolean }; disconnected: () => { reconnect: boolean };
opened: () => void; opened: () => void;
shakehand: (client_id: string) => void; shakehand: (client_id: string) => void;