wip fix
This commit is contained in:
parent
43745f20df
commit
972fbd6ffd
|
|
@ -1,7 +1,7 @@
|
|||
import { dir } from "dir";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { g } from "utils/global";
|
||||
import { code } from "../ws/sync/editor/code/util";
|
||||
import { code } from "../ws/sync/editor/code/util-code";
|
||||
|
||||
export const _ = {
|
||||
url: "/nova-load/:mode/:id/**",
|
||||
|
|
|
|||
|
|
@ -65,12 +65,12 @@ export const SyncActions = {
|
|||
bin: Uint8Array
|
||||
) => ({}) as { diff: Uint8Array; sv: Uint8Array } | void,
|
||||
diff_local: async (
|
||||
mode: "page" | "comp" | "site",
|
||||
mode: "page" | "comp" | "site" | "code",
|
||||
id: string,
|
||||
bin: Uint8Array
|
||||
) => {},
|
||||
sv_remote: async (
|
||||
mode: "page" | "comp" | "site",
|
||||
mode: "page" | "comp" | "site" | "code",
|
||||
id: string,
|
||||
sv: Uint8Array,
|
||||
diff: Uint8Array
|
||||
|
|
@ -84,7 +84,13 @@ export const SyncActions = {
|
|||
load: async (id: string, type: "src" | "build") =>
|
||||
({}) as {
|
||||
id: string;
|
||||
snapshot: null | Uint8Array;
|
||||
snapshot: null | Record<
|
||||
string,
|
||||
{
|
||||
id_doc: number;
|
||||
bin: Uint8Array;
|
||||
}
|
||||
>;
|
||||
},
|
||||
edit: async (
|
||||
arg:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { SAction } from "../actions";
|
||||
import { getCode, prepDCode } from "../editor/code/prep-code";
|
||||
import { prepCodeSnapshot } from "../editor/code/prep-code";
|
||||
import { SyncConnection } from "../type";
|
||||
|
||||
export const code_load: SAction["code"]["load"] = async function (
|
||||
|
|
@ -7,13 +7,9 @@ export const code_load: SAction["code"]["load"] = async function (
|
|||
site_id,
|
||||
type
|
||||
) {
|
||||
const code = await getCode(site_id, "site");
|
||||
|
||||
if (code) {
|
||||
const prep = await prepDCode(site_id);
|
||||
if (prep) {
|
||||
return { id: site_id, snapshot: prep.bin[type] };
|
||||
}
|
||||
const snap = await prepCodeSnapshot(site_id, "site");
|
||||
if (snap && snap.type === "code") {
|
||||
return { id: site_id, snapshot: snap.build };
|
||||
}
|
||||
|
||||
return { id: site_id, snapshot: null };
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { ESite } from "../../../../web/src/nova/ed/logic/ed-global";
|
|||
import { SAction } from "../actions";
|
||||
import { prepCodeSnapshot } from "../editor/code/prep-code";
|
||||
import { SyncConnection } from "../type";
|
||||
import { gzipAsync } from "../entity/zlib";
|
||||
|
||||
export const site_load: SAction["site"]["load"] = async function (
|
||||
this: SyncConnection,
|
||||
|
|
@ -27,7 +28,13 @@ export const site_load: SAction["site"]["load"] = async function (
|
|||
select: { id: true },
|
||||
});
|
||||
|
||||
await prepCodeSnapshot(site_id, "site");
|
||||
const snap = await prepCodeSnapshot(site_id, "site");
|
||||
const compressed: any = {};
|
||||
if (snap) {
|
||||
for (const [key, value] of Object.entries(snap.build)) {
|
||||
compressed[key] = { bin: await gzipAsync(value.bin) };
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: site.id,
|
||||
|
|
@ -38,7 +45,10 @@ export const site_load: SAction["site"]["load"] = async function (
|
|||
responsive: site.responsive as ESite["responsive"],
|
||||
js_compiled: site.js_compiled || "",
|
||||
layout: { id: layout?.id || "", snapshot: null, meta: undefined },
|
||||
code: { snapshot: null, mode: site.code_mode as "old" | "vsc" },
|
||||
code: {
|
||||
snapshot: compressed,
|
||||
mode: site.code_mode as "old" | "vsc",
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ export const yjs_sv_remote: SAction["yjs"]["sv_remote"] = async function (
|
|||
console.log(`sv_remote not found`, mode, id);
|
||||
return;
|
||||
}
|
||||
const doc = docs[mode][id].doc;
|
||||
let doc = null;
|
||||
if (mode !== "code") doc = docs[mode][id].doc;
|
||||
else {
|
||||
doc = docs.code[id].build.site;
|
||||
}
|
||||
const diff_local = Y.encodeStateAsUpdate(doc as any, await gunzipAsync(sv));
|
||||
Y.applyUpdate(doc as any, await gunzipAsync(diff), "local");
|
||||
return { diff: await gzipAsync(diff_local) };
|
||||
|
|
|
|||
|
|
@ -1,50 +1,78 @@
|
|||
import { build, context } from "esbuild";
|
||||
import { Code } from "./watcher";
|
||||
import { g } from "utils/global";
|
||||
import { dir } from "dir";
|
||||
import globalExternals from "@fal-works/esbuild-plugin-global-externals";
|
||||
import { style } from "@hyrious/esbuild-plugin-style";
|
||||
import { sendWS } from "../../sync-handler";
|
||||
import { SyncType } from "../../type";
|
||||
import { gzipAsync } from "../../entity/zlib";
|
||||
import { ServerWebSocket } from "bun";
|
||||
import { WSData } from "../../../../../../pkgs/core/server/create";
|
||||
import { dir } from "dir";
|
||||
import { context } from "esbuild";
|
||||
import { existsAsync, dirAsync, removeAsync, writeAsync } from "fs-jetpack";
|
||||
import { CodeMode, code } from "./util-code";
|
||||
import { user } from "../../entity/user";
|
||||
import { conns } from "../../entity/conn";
|
||||
import { CodeMode, code } from "./util";
|
||||
import { docs } from "../../entity/docs";
|
||||
import { DCode } from "../../../../../web/src/utils/types/root";
|
||||
import { readDirectoryRecursively } from "../../../../api/site-export";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
export const codeBuild = async (id_site: any, mode: CodeMode) => {
|
||||
const src_path = code.path(id_site, mode, "src");
|
||||
if (!(await existsAsync(src_path))) return;
|
||||
const build_path = code.path(id_site, mode, "build");
|
||||
const build_file = dir.path(`${build_path}/index.js`);
|
||||
|
||||
await removeAsync(build_path);
|
||||
await dirAsync(build_path);
|
||||
const build_file = `${build_path}/index.js`;
|
||||
await writeAsync(build_file, "");
|
||||
|
||||
if (!code.esbuild[id_site]) {
|
||||
code.esbuild[id_site] = { site: null, ssr: null };
|
||||
}
|
||||
|
||||
code.esbuild[id_site][mode] = await context({
|
||||
absWorkingDir: src_path,
|
||||
entryPoints: ["index.tsx"],
|
||||
bundle: true,
|
||||
outfile: build_file,
|
||||
minify: true,
|
||||
treeShaking: true,
|
||||
sourcemap: true,
|
||||
plugins: [
|
||||
style(),
|
||||
globalExternals({
|
||||
react: {
|
||||
varName: "window.React",
|
||||
type: "cjs",
|
||||
if (!code.esbuild[id_site][mode]) {
|
||||
code.esbuild[id_site][mode] = await context({
|
||||
absWorkingDir: src_path,
|
||||
entryPoints: ["index.tsx"],
|
||||
bundle: true,
|
||||
outfile: build_file,
|
||||
minify: true,
|
||||
treeShaking: true,
|
||||
format: "cjs",
|
||||
sourcemap: true,
|
||||
plugins: [
|
||||
style(),
|
||||
globalExternals({
|
||||
react: {
|
||||
varName: "window.React",
|
||||
type: "cjs",
|
||||
},
|
||||
"react-dom": {
|
||||
varName: "window.ReactDOM",
|
||||
type: "cjs",
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "prasi",
|
||||
setup(setup) {
|
||||
setup.onEnd((res) => {
|
||||
const cdoc = docs.code[id_site];
|
||||
if (cdoc) {
|
||||
const doc = cdoc.build[mode];
|
||||
const build_dir = code.path(id_site, mode, "build");
|
||||
|
||||
if (doc) {
|
||||
codeApplyChanges(build_dir, doc);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
"react-dom": {
|
||||
varName: "window.ReactDOM",
|
||||
type: "cjs",
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
],
|
||||
});
|
||||
const esbuild = code.esbuild[id_site][mode];
|
||||
esbuild?.watch();
|
||||
}
|
||||
const esbuild = code.esbuild[id_site][mode];
|
||||
if (esbuild) {
|
||||
try {
|
||||
await esbuild.rebuild();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const out = Bun.file(build_file);
|
||||
const src = (await out.text()).replace(
|
||||
|
|
@ -53,3 +81,25 @@ export const codeBuild = async (id_site: any, mode: CodeMode) => {
|
|||
);
|
||||
await Bun.write(out, src);
|
||||
};
|
||||
|
||||
const codeApplyChanges = (path: string, doc: DCode) => {
|
||||
const map = doc.getMap("map");
|
||||
|
||||
const files = map.get("files");
|
||||
|
||||
const dirs = readDirectoryRecursively(path);
|
||||
doc.transact(() => {
|
||||
files?.forEach((v, k) => {
|
||||
if (!dirs[k]) {
|
||||
files?.delete(k);
|
||||
}
|
||||
});
|
||||
for (const [k, v] of Object.entries(dirs)) {
|
||||
if (files) {
|
||||
files.set(k, v);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return doc;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import { spawn } from "bun";
|
||||
import { sendWS } from "../../sync-handler";
|
||||
import { SyncType } from "../../type";
|
||||
import { Code } from "./watcher";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
export const codePkgInstall = async (id_site: string, mode: string) => {
|
||||
try {
|
||||
const proc = spawn({
|
||||
cmd: ["bun", "i"],
|
||||
cwd: Code.path(code.id_site, code.id),
|
||||
stderr: "pipe",
|
||||
stdout: "pipe",
|
||||
});
|
||||
|
||||
const broadcast = (content: string) => {
|
||||
activity.site
|
||||
.room(code.id_site)
|
||||
.findAll({ site_js: code.name })
|
||||
.forEach((item, ws) => {
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "code",
|
||||
data: {
|
||||
name: code.name,
|
||||
id: code.id,
|
||||
content,
|
||||
},
|
||||
});
|
||||
});
|
||||
};
|
||||
(async () => {
|
||||
for await (const chunk of proc.stdout) {
|
||||
broadcast(decoder.decode(chunk));
|
||||
}
|
||||
})();
|
||||
(async () => {
|
||||
for await (const chunk of proc.stderr) {
|
||||
broadcast(decoder.decode(chunk));
|
||||
}
|
||||
})();
|
||||
await proc.exited;
|
||||
|
||||
activity.site
|
||||
.room(code.id_site)
|
||||
.findAll({ site_js: code.name })
|
||||
.forEach((item, ws) => {
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "code",
|
||||
data: {
|
||||
name: code.name,
|
||||
id: code.id,
|
||||
event: "code-done",
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch (e: any) {
|
||||
activity.site
|
||||
.room(code.id_site)
|
||||
.findAll({ site_js: code.name })
|
||||
.forEach((item, ws) => {
|
||||
sendWS(ws, {
|
||||
type: SyncType.Event,
|
||||
event: "code",
|
||||
data: {
|
||||
name: code.name,
|
||||
id: code.id,
|
||||
event: "code-done",
|
||||
content: `ERROR: ${e.message}`,
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,11 +1,15 @@
|
|||
import { existsAsync } from "fs-jetpack";
|
||||
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";
|
||||
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
|
||||
|
|
@ -17,23 +21,47 @@ export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
|
|||
)
|
||||
.await();
|
||||
|
||||
let doc = docs.code[id_site];
|
||||
let dcode = docs.code[id_site];
|
||||
if (!docs.code[id_site]) {
|
||||
docs.code[id_site] = {
|
||||
id: id_site,
|
||||
build: {},
|
||||
};
|
||||
doc = docs.code[id_site];
|
||||
dcode = docs.code[id_site];
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
if (!doc.build[mode]) {
|
||||
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 (!(await existsAsync(build_dir))) {
|
||||
await codeBuild(id_site, mode);
|
||||
if (snap && 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 },
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
doc.build[mode] = codeLoad(id_site, build_dir);
|
||||
}
|
||||
|
||||
const build: Record<
|
||||
|
|
@ -43,9 +71,10 @@ export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
|
|||
bin: Uint8Array;
|
||||
}
|
||||
> = {};
|
||||
for (const [k, v] of Object.entries(doc.build)) {
|
||||
|
||||
for (const [k, v] of Object.entries(dcode.build)) {
|
||||
const bin = Y.encodeStateAsUpdate(v as Doc);
|
||||
build[k] = { bin, id_doc: v.clientID };
|
||||
build[k] = { bin: bin, id_doc: v.clientID };
|
||||
}
|
||||
|
||||
let snap = await snapshot.getOrCreate({
|
||||
|
|
@ -54,7 +83,9 @@ export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
|
|||
build,
|
||||
});
|
||||
|
||||
return snap;
|
||||
if (snap.type === "code") {
|
||||
return snap;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -66,7 +97,7 @@ const codeLoad = (id: string, path: string) => {
|
|||
|
||||
const dirs = readDirectoryRecursively(path);
|
||||
for (const [k, v] of Object.entries(dirs)) {
|
||||
files.set(k, new Y.Text(v));
|
||||
files.set(k, v);
|
||||
}
|
||||
|
||||
doc.transact(() => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
import { dir } from "dir";
|
||||
import { g } from "utils/global";
|
||||
import { dirAsync, writeAsync } from "fs-jetpack";
|
||||
import { dirname } from "path";
|
||||
import { BuildContext } from "esbuild";
|
||||
import { dirAsync, existsAsync, writeAsync } from "fs-jetpack";
|
||||
import { dirname } from "path";
|
||||
import { g } from "utils/global";
|
||||
|
||||
export type CodeMode = "site" | "ssr";
|
||||
export const code = {
|
||||
path(id_site: string, mode: CodeMode, type: "src" | "build", path?: string) {
|
||||
return dir.path(`${g.datadir}/code/${id_site}/${mode}/${type}`);
|
||||
let file_path = "";
|
||||
if (path) {
|
||||
file_path = path[0] === "/" ? path : `/${path}`;
|
||||
}
|
||||
return dir.path(`${g.datadir}/code/${id_site}/${mode}/${type}${file_path}`);
|
||||
},
|
||||
esbuild: {} as Record<string, Record<CodeMode, null | BuildContext>>,
|
||||
prep(id_site: string, mode: CodeMode) {
|
||||
|
|
@ -17,15 +21,21 @@ export const code = {
|
|||
});
|
||||
const promises: Promise<void>[] = [];
|
||||
return {
|
||||
path(type: "src" | "build", path?: string) {
|
||||
return dir.path(`${g.datadir}/code/${id_site}/${mode}/${type}`);
|
||||
path(type: "src" | "build", path: string) {
|
||||
return dir.path(
|
||||
`${g.datadir}/code/${id_site}/${mode}/${type}${
|
||||
path[0] === "/" ? path : `/${path}`
|
||||
}`
|
||||
);
|
||||
},
|
||||
new_file(path: string, content: string) {
|
||||
promises.push(
|
||||
new Promise(async (done) => {
|
||||
const full_path = this.path("src", path);
|
||||
await dirAsync(dirname(full_path));
|
||||
await writeAsync(full_path, content);
|
||||
if (!(await existsAsync(full_path))) {
|
||||
await dirAsync(dirname(full_path));
|
||||
await writeAsync(full_path, content);
|
||||
}
|
||||
done();
|
||||
})
|
||||
);
|
||||
|
|
@ -85,8 +85,9 @@ export const snapshot = {
|
|||
async getOrCreate(data: DocSnapshot) {
|
||||
const id = `${data.type}-${data.id}`;
|
||||
let res = this.db.get(id);
|
||||
if (!res) {
|
||||
await this.db.put(id, structuredClone(emptySnapshot as DocSnapshot));
|
||||
|
||||
if (!res || !res.id) {
|
||||
await this.db.put(id, structuredClone(data as DocSnapshot));
|
||||
res = this.db.get(id);
|
||||
}
|
||||
return res as DocSnapshot;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { SAction } from "../../../../../srv/ws/sync/actions";
|
|||
import { parseJs } from "../../../../../srv/ws/sync/editor/parser/parse-js";
|
||||
import { clientStartSync } from "../../../utils/sync/ws-client";
|
||||
import { IItem } from "../../../utils/types/item";
|
||||
import { DComp, DPage } from "../../../utils/types/root";
|
||||
import { DCode, DComp, DPage } from "../../../utils/types/root";
|
||||
import { GenMetaP, IMeta as LogicMeta } from "../../vi/utils/types";
|
||||
|
||||
export type IMeta = LogicMeta;
|
||||
|
|
@ -24,7 +24,15 @@ export const EmptySite = {
|
|||
meta: undefined as void | Record<string, IMeta>,
|
||||
},
|
||||
code: {
|
||||
snapshot: null as null | Uint8Array,
|
||||
snapshot: {} as
|
||||
| undefined
|
||||
| Record<
|
||||
string,
|
||||
{
|
||||
id_doc: number;
|
||||
bin: Uint8Array;
|
||||
}
|
||||
>,
|
||||
mode: "old" as "old" | "vsc",
|
||||
},
|
||||
};
|
||||
|
|
@ -183,7 +191,8 @@ export const EDGlobal = {
|
|||
>,
|
||||
group: {} as Record<string, Awaited<ReturnType<SAction["comp"]["group"]>>>,
|
||||
},
|
||||
global_prop: [] as string[],
|
||||
code: {} as Record<string, { doc: null | DCode }>,
|
||||
global_prop: [] as string[],
|
||||
ui: {
|
||||
zoom: localStorage.zoom || "100%",
|
||||
should_render: false,
|
||||
|
|
@ -211,7 +220,6 @@ export const EDGlobal = {
|
|||
code: {
|
||||
init: false,
|
||||
open: false,
|
||||
id: "",
|
||||
name: "site",
|
||||
log: "",
|
||||
loading: false,
|
||||
|
|
|
|||
|
|
@ -1,57 +1,59 @@
|
|||
import { viLoadLegacy } from "../../vi/load/load-legacy";
|
||||
import { viLoadSnapshot } from "../../vi/load/load-snapshot";
|
||||
import { ESite, PG } from "./ed-global";
|
||||
import { reloadPage } from "./ed-route";
|
||||
|
||||
export const loadSite = async (p: PG, site: ESite, note: string) => {
|
||||
const old_layout_id = p.site.layout.id;
|
||||
const layout_changed = p.site.layout.id !== site.layout.id;
|
||||
p.site = site;
|
||||
const old_layout_id = p.site.layout.id;
|
||||
const layout_changed = p.site.layout.id !== site.layout.id;
|
||||
p.site = site;
|
||||
|
||||
p.mode = "desktop";
|
||||
if (p.site.responsive === "mobile-only") {
|
||||
p.mode = "mobile";
|
||||
} else if (p.site.responsive === "desktop-only") {
|
||||
p.mode = "desktop";
|
||||
}
|
||||
p.mode = "desktop";
|
||||
if (p.site.responsive === "mobile-only") {
|
||||
p.mode = "mobile";
|
||||
} else if (p.site.responsive === "desktop-only") {
|
||||
p.mode = "desktop";
|
||||
}
|
||||
|
||||
if (layout_changed) {
|
||||
const old_layout = p.page.list[old_layout_id];
|
||||
if (layout_changed) {
|
||||
const old_layout = p.page.list[old_layout_id];
|
||||
|
||||
if (old_layout && old_layout.on_update) {
|
||||
old_layout.doc.off("update", old_layout.on_update);
|
||||
}
|
||||
if (old_layout && old_layout.on_update) {
|
||||
old_layout.doc.off("update", old_layout.on_update);
|
||||
}
|
||||
|
||||
if (!p.script.db && !p.script.api) {
|
||||
if (p.site.code.mode === "old") {
|
||||
await viLoadLegacy({
|
||||
site: {
|
||||
api_url: p.site.config.api_url,
|
||||
id: p.site.id,
|
||||
api: {
|
||||
get() {
|
||||
return p.script.api;
|
||||
},
|
||||
set(val) {
|
||||
p.script.api = val;
|
||||
},
|
||||
},
|
||||
db: {
|
||||
get() {
|
||||
return p.script.db;
|
||||
},
|
||||
set(val) {
|
||||
p.script.db = val;
|
||||
},
|
||||
},
|
||||
},
|
||||
render: () => {},
|
||||
});
|
||||
} else {
|
||||
}
|
||||
}
|
||||
if (!p.script.db && !p.script.api) {
|
||||
if (p.site.code.mode === "old") {
|
||||
await viLoadLegacy({
|
||||
site: {
|
||||
api_url: p.site.config.api_url,
|
||||
id: p.site.id,
|
||||
api: {
|
||||
get() {
|
||||
return p.script.api;
|
||||
},
|
||||
set(val) {
|
||||
p.script.api = val;
|
||||
},
|
||||
},
|
||||
db: {
|
||||
get() {
|
||||
return p.script.db;
|
||||
},
|
||||
set(val) {
|
||||
p.script.db = val;
|
||||
},
|
||||
},
|
||||
},
|
||||
render: () => {},
|
||||
});
|
||||
} else {
|
||||
await viLoadSnapshot(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (site.layout.id) {
|
||||
await reloadPage(p, site.layout.id, "load-layout");
|
||||
}
|
||||
}
|
||||
if (site.layout.id) {
|
||||
await reloadPage(p, site.layout.id, "load-layout");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -64,47 +64,11 @@ export const edInitSync = (p: PG) => {
|
|||
site_id: params.site_id,
|
||||
page_id: params.page_id,
|
||||
events: {
|
||||
code(arg) {
|
||||
p.ui.popup.code.error = false;
|
||||
|
||||
if (arg.event === "code-loading") {
|
||||
p.ui.popup.code.log = "";
|
||||
p.ui.popup.code.loading = true;
|
||||
p.render();
|
||||
} else if (arg.event === "code-done") {
|
||||
if (typeof arg.content === "string") {
|
||||
if (arg.content !== "OK") {
|
||||
p.ui.popup.code.error = true;
|
||||
}
|
||||
|
||||
p.ui.popup.code.log += arg.content;
|
||||
}
|
||||
p.ui.popup.code.loading = false;
|
||||
|
||||
if (arg.src) {
|
||||
const w = window as any;
|
||||
const module = evalCJS(decoder.decode(decompress(arg.src)));
|
||||
p.global_prop = Object.keys(module);
|
||||
if (typeof module === "object") {
|
||||
for (const [k, v] of Object.entries(module)) {
|
||||
w[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
p.render();
|
||||
} else {
|
||||
if (typeof arg.content === "string")
|
||||
p.ui.popup.code.log += arg.content;
|
||||
p.render();
|
||||
}
|
||||
},
|
||||
activity(arg) {},
|
||||
opened() {
|
||||
if (w.offline) {
|
||||
console.log("reconnected!");
|
||||
w.offline = false;
|
||||
p.ui.syncing = true;
|
||||
p.sync.activity("site", { type: "join", id: params.site_id });
|
||||
p.render();
|
||||
} else {
|
||||
w.offline = false;
|
||||
|
|
@ -158,6 +122,8 @@ export const edInitSync = (p: PG) => {
|
|||
doc = p.page.doc as Y.Doc;
|
||||
} else if (data.type === "comp" && p.comp.list[data.id]) {
|
||||
doc = p.comp.list[data.id].doc;
|
||||
} else if (data.type === "code") {
|
||||
doc = p.code.site.doc;
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
|
|
@ -179,7 +145,7 @@ export const edInitSync = (p: PG) => {
|
|||
Y.applyUpdate(doc, decompress(res.diff), "sv_remote");
|
||||
if (data.type === "page") {
|
||||
await treeRebuild(p, { note: "sv_remote" });
|
||||
} else {
|
||||
} else if (data.type === "comp") {
|
||||
const updated = await updateComponentMeta(p, doc, data.id);
|
||||
if (updated) {
|
||||
p.comp.list[data.id].meta = updated.meta;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ import { Popover } from "../../../../../utils/ui/popover";
|
|||
import { Tooltip } from "../../../../../utils/ui/tooltip";
|
||||
import { EDGlobal } from "../../../logic/ed-global";
|
||||
import {
|
||||
iconChevronDown,
|
||||
iconLoading,
|
||||
iconLog,
|
||||
iconNewTab,
|
||||
iconTrash
|
||||
iconChevronDown,
|
||||
iconLoading,
|
||||
iconLog,
|
||||
iconNewTab,
|
||||
iconTrash,
|
||||
} from "./icons";
|
||||
import { CodeNameItem, CodeNameList, codeName } from "./name-list";
|
||||
|
||||
|
|
@ -116,7 +116,6 @@ const CodeBody = () => {
|
|||
onPick={async (e) => {
|
||||
local.namePicker = false;
|
||||
p.ui.popup.code.name = e.name;
|
||||
p.ui.popup.code.id = "";
|
||||
p.render();
|
||||
}}
|
||||
/>
|
||||
|
|
@ -142,41 +141,6 @@ const CodeBody = () => {
|
|||
></div>
|
||||
</Popover>
|
||||
|
||||
{p.ui.popup.code.name !== "site" &&
|
||||
p.ui.popup.code.name !== "SSR" && (
|
||||
<>
|
||||
<Tooltip
|
||||
content={"Delete Code Module"}
|
||||
className="flex items-center border-l relative hover:bg-red-50 cursor-pointer px-2 transition-all text-red-500"
|
||||
placement="bottom"
|
||||
onClick={async () => {
|
||||
if (
|
||||
prompt(
|
||||
"Are you sure want to delete this code?\ntype 'yes' to confirm:"
|
||||
) === "yes"
|
||||
) {
|
||||
await db.code.delete({
|
||||
where: { id: p.ui.popup.code.id },
|
||||
});
|
||||
|
||||
codeName.list = codeName.list.filter(
|
||||
(e) => e.id !== p.ui.popup.code.id
|
||||
);
|
||||
|
||||
p.ui.popup.code.name = codeName.list[0].name;
|
||||
p.ui.popup.code.id = codeName.list[0].id;
|
||||
p.render();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: iconTrash,
|
||||
}}
|
||||
></div>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
<Tooltip
|
||||
content="STDOUT Log"
|
||||
delay={0}
|
||||
|
|
@ -211,9 +175,7 @@ const CodeBody = () => {
|
|||
placement="bottom"
|
||||
className={cx("flex items-stretch relative")}
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`${vscode_url}folder=/site/code/${p.site.id}/${p.ui.popup.code.id}`
|
||||
);
|
||||
window.open(`${vscode_url}folder=/site/${p.site.id}/site/src`);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
|
|
@ -271,13 +233,13 @@ const CodeBody = () => {
|
|||
|
||||
{code_mode === "vsc" ? (
|
||||
<div className="flex flex-1 relative">
|
||||
{!p.ui.popup.code.open || !p.ui.popup.code.id ? (
|
||||
{!p.ui.popup.code.open ? (
|
||||
<Loading backdrop={false} />
|
||||
) : (
|
||||
<>
|
||||
<iframe
|
||||
className="flex flex-1 absolute inset-0 w-full h-full z-10"
|
||||
src={`${vscode_url}folder=/site/code/${p.site.id}/${p.ui.popup.code.id}`}
|
||||
src={`${vscode_url}folder=/site/${p.site.id}/site/src`}
|
||||
></iframe>
|
||||
<div className="flex flex-1 absolute inset-0 z-0 items-center justify-center">
|
||||
Loading VSCode...
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
import { decompress } from "wasm-gzip";
|
||||
import { loadApiProxyDef } from "../../../base/load/api/api-proxy-def";
|
||||
import { PG } from "../../ed/logic/ed-global";
|
||||
import { evalCJS } from "../../ed/logic/ed-sync";
|
||||
import { treeRebuild } from "../../ed/logic/tree/build";
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
export const viLoadSnapshot = async (p: PG) => {
|
||||
let api_url = p.site.config.api_url;
|
||||
|
||||
try {
|
||||
const apiURL = new URL(api_url);
|
||||
if (api_url && apiURL.hostname) {
|
||||
try {
|
||||
await loadApiProxyDef(api_url, true);
|
||||
} catch (e) {
|
||||
console.warn("Failed to load API:", api_url);
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (p.site.code.snapshot) {
|
||||
for (const [name, build] of Object.entries(p.site.code.snapshot)) {
|
||||
const doc = new Y.Doc();
|
||||
Y.applyUpdate(doc, decompress(build.bin));
|
||||
|
||||
p.code[name] = { doc: doc as any };
|
||||
const code = p.code[name].doc;
|
||||
if (code) {
|
||||
const src = code.getMap("map").get("files")?.get("index.js");
|
||||
applyEnv(p, src);
|
||||
treeRebuild(p);
|
||||
p.render();
|
||||
code.on("update", (e, origin) => {
|
||||
const src = code.getMap("map").get("files")?.get("index.js");
|
||||
applyEnv(p, src);
|
||||
treeRebuild(p);
|
||||
p.render();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const applyEnv = (p: PG, src?: string) => {
|
||||
if (src) {
|
||||
const w = window as any;
|
||||
const module = evalCJS(src);
|
||||
p.global_prop = Object.keys(module);
|
||||
if (typeof module === "object") {
|
||||
for (const [k, v] of Object.entries(module)) {
|
||||
w[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -77,28 +77,9 @@ export const clientStartSync = async (arg: {
|
|||
site_id?: string;
|
||||
page_id?: string;
|
||||
events: {
|
||||
code: (arg: {
|
||||
name: string;
|
||||
id: string;
|
||||
event: "code-loading" | "code-done";
|
||||
content?: string;
|
||||
src?: Uint8Array;
|
||||
}) => void;
|
||||
activity: (arg: {
|
||||
activity: string;
|
||||
room_id: string;
|
||||
clients: {
|
||||
user: {
|
||||
client_id: string;
|
||||
user_id: string;
|
||||
username: string;
|
||||
};
|
||||
data: any;
|
||||
}[];
|
||||
}) => void;
|
||||
editor_start: (arg: UserConf) => void;
|
||||
remote_svlocal: (arg: {
|
||||
type: "page" | "comp";
|
||||
type: "page" | "comp" | "code";
|
||||
id: string;
|
||||
sv_local: Uint8Array;
|
||||
}) => void;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,6 @@ export type DComp = TypedDoc<{
|
|||
export type DCode = TypedDoc<{
|
||||
map: TypedMap<{
|
||||
id: string;
|
||||
files: TypedMap<Record<string, Y.Text>>;
|
||||
files: TypedMap<Record<string, string>>;
|
||||
}>;
|
||||
}>;
|
||||
|
|
|
|||
Loading…
Reference in New Issue