This commit is contained in:
Rizky 2024-01-23 14:29:18 +07:00
parent b0e30ed9fd
commit 43745f20df
8 changed files with 105 additions and 195 deletions

View File

@ -1,15 +1,14 @@
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";
export const _ = {
url: "/nova-load/:mode/:id/**",
async api(mode: "site" | "ssr", id_site: string) {
const { req, res } = apiContext(this);
const file = Bun.file(
dir.path(`${g.datadir}/site/build/${id_site}-${mode}/${req.params["*"]}`)
);
const file = Bun.file(code.path(id_site, mode, "build", req.params["*"]));
if (await file.exists()) {
return new Response(file as any);
}

View File

@ -1,7 +1,7 @@
import { validate } from "uuid";
import { ESite } from "../../../../web/src/nova/ed/logic/ed-global";
import { SAction } from "../actions";
import { prepCode } from "../editor/code/prep-code";
import { prepCodeSnapshot } from "../editor/code/prep-code";
import { SyncConnection } from "../type";
export const site_load: SAction["site"]["load"] = async function (
@ -27,7 +27,7 @@ export const site_load: SAction["site"]["load"] = async function (
select: { id: true },
});
await prepCode(site_id, "site");
await prepCodeSnapshot(site_id, "site");
return {
id: site.id,

View File

@ -0,0 +1,55 @@
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 { user } from "../../entity/user";
import { conns } from "../../entity/conn";
import { CodeMode, code } from "./util";
const encoder = new TextEncoder();
export const codeBuild = async (id_site: any, mode: CodeMode) => {
const src_path = code.path(id_site, mode, "src");
const build_path = code.path(id_site, mode, "build");
const build_file = dir.path(`${build_path}/index.js`);
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",
},
"react-dom": {
varName: "window.ReactDOM",
type: "cjs",
},
}),
],
});
const out = Bun.file(build_file);
const src = (await out.text()).replace(
"//# sourceMappingURL=index.js.map",
`//# sourceMappingURL=/nova-load/code/${id_site}/${mode}/index.js.map`
);
await Bun.write(out, src);
};

View File

@ -1,147 +0,0 @@
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 { user } from "../../entity/user";
import { conns } from "../../entity/conn";
const encoder = new TextEncoder();
export const codeBuild = async (id_site: any, mode: string) => {
// try {
// const id_code = code.id;
// const outfile = dir.path(`${g.datadir}/site/build/${id_code}/index.js`);
// if (!Code.build.ctx[id_code]) {
// Code.build.ctx[id_code] = await context({
// absWorkingDir: dir.path(
// `${g.datadir}/site/code/${code.id_site}/${id_code}`
// ),
// entryPoints: ["index.tsx"],
// bundle: true,
// format: "cjs",
// outfile,
// minify: true,
// treeShaking: true,
// sourcemap: true,
// plugins: [
// style(),
// globalExternals({
// react: {
// varName: "window.React",
// type: "cjs",
// },
// "react-dom": {
// varName: "window.ReactDOM",
// type: "cjs",
// },
// }),
// ],
// });
// }
// 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-loading",
// },
// });
// });
// const out = Bun.file(outfile);
// const src = (await out.text()).replace(
// "//# sourceMappingURL=index.js.map",
// `//# sourceMappingURL=/nova-load/code/${id_code}/index.js.map`
// );
// Bun.write(out, src);
// const srcgz = await gzipAsync(encoder.encode(src));
// user.active.findAll({ site_id: code.id_site }).map((e) => {
// const ws = conns.get(e.client_id)?.ws;
// if (ws) {
// sendWS(ws, {
// type: SyncType.Event,
// event: "code",
// data: {
// name: "site",
// id: id_code,
// event: "code-done",
// src: srcgz,
// content: "OK",
// },
// });
// }
// });
// } catch (e: any) {
// console.error(e);
// 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}`,
// },
// });
// });
// }
};
// export const broadcastCode = async (
// id_site: string,
// mode: string,
// ws?: ServerWebSocket<WSData>
// ) => {
// const outfile = dir.path(
// `${g.datadir}/site/build/${id_site}-${mode}/index.js`
// );
// const out = Bun.file(outfile);
// if (out) {
// const src = await out.text();
// const srcgz = await gzipAsync(encoder.encode(src));
// if (ws) {
// sendWS(ws, {
// type: SyncType.Event,
// event: "code",
// data: {
// name: "site",
// event: "code-done",
// src: srcgz,
// content: "OK",
// },
// });
// } else {
// 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: "code",
// data: {
// name: "site",
// event: "code-done",
// src: srcgz,
// content: "OK",
// },
// });
// }
// });
// }
// }
// };

View File

@ -1,72 +1,64 @@
import { dir } from "dir";
import { existsAsync } from "fs-jetpack";
import { g } from "utils/global";
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 { codeBuild } from "./build-code";
import { CodeMode, code } from "./util";
export const prepCode = async (id_site: string, mode: CodeMode) => {
export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
await code
.prep(id_site, mode)
.new_file("index.ts", "export const sample = 'hello_world'")
.new_file("index.tsx", "export const sample = 'hello_world'")
.new_file(
"package.json",
JSON.stringify({ name: `${mode}-${id_site}`, dependencies: {} }, null, 2)
)
.await();
};
export const prepDCode = async (id_site: string) => {
let exists = false;
let doc = docs.code[id_site];
if (!docs.code[id_site]) {
const path = {
src: dir.path(`${g.datadir}/site/code/${id_site}-site`),
build: dir.path(`${g.datadir}/site/build/${id_site}-site`),
docs.code[id_site] = {
id: id_site,
build: {},
};
if ((await existsAsync(path.src)) && (await existsAsync(path.build))) {
docs.code[id_site] = {
id: id_site,
build: loadFolderAsDCode(id_site, path.build),
};
exists = true;
}
doc = docs.code[id_site];
}
if (exists) {
const chmod = Bun.spawn({
cmd: ["chmod", "-R", "777", "."],
cwd: dir.path(`${g.datadir}/site`),
});
if (doc) {
if (!doc.build[mode]) {
const build_dir = code.path(id_site, mode, "build");
await chmod.exited;
if (!(await existsAsync(build_dir))) {
await codeBuild(id_site, mode);
}
doc.build[mode] = codeLoad(id_site, build_dir);
}
const build_bin = Y.encodeStateAsUpdate(docs.code[id_site].build as Doc);
const build: Record<
string,
{
id_doc: number;
bin: Uint8Array;
}
> = {};
for (const [k, v] of Object.entries(doc.build)) {
const bin = Y.encodeStateAsUpdate(v as Doc);
build[k] = { bin, id_doc: v.clientID };
}
let snap = await snapshot.getOrCreate({
type: "site",
type: "code",
id: id_site,
name: "",
build: {
bin: build_bin,
id_doc: docs.code[id_site].build.clientID,
},
build,
});
if (snap && snap.type === "site") {
return {
bin: {
build: snap.build.bin,
},
};
}
return snap;
}
};
const loadFolderAsDCode = (id: string, path: string) => {
const codeLoad = (id: string, path: string) => {
const doc = new Y.Doc() as DCode;
const map = doc.getMap("map");

View File

@ -2,13 +2,19 @@ import { dir } from "dir";
import { g } from "utils/global";
import { dirAsync, writeAsync } from "fs-jetpack";
import { dirname } from "path";
import { BuildContext } from "esbuild";
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}`);
},
esbuild: {} as Record<string, Record<CodeMode, null | BuildContext>>,
prep(id_site: string, mode: CodeMode) {
Bun.spawn({
cmd: ["chmod", "-R", "777", "."],
cwd: dir.path(`${g.datadir}/site`),
});
const promises: Promise<void>[] = [];
return {
path(type: "src" | "build", path?: string) {

View File

@ -1,5 +1,3 @@
import { TypedDoc, TypedMap } from "yjs-types";
import { MItem } from "../../../../web/src/utils/types/item";
import { DCode, DComp, DPage } from "../../../../web/src/utils/types/root";
export const docs = {
@ -27,5 +25,5 @@ export const docs = {
um: Y.UndoManager;
}
>,
code: {} as Record<string, { id: string; build: DCode }>,
code: {} as Record<string, { id: string; build: Record<string, DCode> }>,
};

View File

@ -33,19 +33,26 @@ type SiteSnapshot = {
type: "site";
id: string;
name: string;
build: { bin: Uint8Array; id_doc: number };
};
type CodeSnapshot = {
type: "code";
id: string;
build: Record<string, { id_doc: number; bin: Uint8Array }>;
};
type DocSnapshotMap = {
page: PageSnapshot;
comp: CompSnapshot;
site: SiteSnapshot;
code: CodeSnapshot;
"": EmptySnapshot;
};
export type DocSnapshot =
| PageSnapshot
| SiteSnapshot
| CompSnapshot
| CodeSnapshot
| EmptySnapshot;
const emptySnapshot: DocSnapshot = {