checkpoint

This commit is contained in:
Rizky 2024-05-06 17:35:23 +07:00
parent 993951eb89
commit 0c96971a8f
16 changed files with 148 additions and 111 deletions

View File

@ -34,10 +34,13 @@ export const _ = {
if (!(await file.exists())) { if (!(await file.exists())) {
const root = `/code/${site_id}/site/src`; const root = `/code/${site_id}/site/src`;
await initFrontEnd(root, site_id); await initFrontEnd(root, site_id);
return new Response("Code file not found", { status: 403 }); return new Response("", { status: 403 });
} }
const body = Bun.gzipSync(await file.arrayBuffer());
return new Response(file); return new Response(body, {
headers: { "content-type": file.type, "content-encoding": "gzip" },
});
} }
case "route": { case "route": {
const site = await _db.site.findFirst({ const site = await _db.site.findFirst({

View File

@ -11,8 +11,8 @@ export const _ = {
const root = `/code/${id_site}/site/src`; const root = `/code/${id_site}/site/src`;
delete frontend[id_site]; delete frontend[id_site];
delete server[id_site]; delete server[id_site];
await initFrontEnd(root, id_site); await initFrontEnd(root, id_site, true);
await initServer(root, id_site); await initServer(root, id_site, true);
return "ok"; return "ok";
}, },

View File

@ -6,19 +6,20 @@
"@hyrious/esbuild-plugin-style": "^0.3.5", "@hyrious/esbuild-plugin-style": "^0.3.5",
"@node-rs/argon2": "^1.5.2", "@node-rs/argon2": "^1.5.2",
"@paralleldrive/cuid2": "^2.2.2", "@paralleldrive/cuid2": "^2.2.2",
"@types/lodash.isequal": "^4.5.8",
"@types/mime-types": "^2.1.4", "@types/mime-types": "^2.1.4",
"recast": "^0.23.4",
"esbuild": "^0.20.2", "esbuild": "^0.20.2",
"esbuild-clean-plugin": "^1.0.0",
"lmdb": "^2.9.2", "lmdb": "^2.9.2",
"lodash.isequal": "^4.5.0",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"msgpackr": "^1.10.0", "msgpackr": "^1.10.0",
"radix3": "^1.1.0", "radix3": "^1.1.0",
"recast": "^0.23.4",
"uuid": "^9.0.1", "uuid": "^9.0.1",
"y-pojo": "^0.0.8", "y-pojo": "^0.0.8",
"yjs": "^13.6.10", "yjs": "^13.6.10",
"yjs-types": "^0.0.1", "yjs-types": "^0.0.1"
"lodash.isequal": "^4.5.0",
"@types/lodash.isequal": "^4.5.8"
}, },
"devDependencies": { "devDependencies": {
"bun-types": "^1.0.30" "bun-types": "^1.0.30"

View File

@ -1,28 +1,34 @@
import globalExternals from "@fal-works/esbuild-plugin-global-externals"; import globalExternals from "@fal-works/esbuild-plugin-global-externals";
import style from "@hyrious/esbuild-plugin-style"; import style from "@hyrious/esbuild-plugin-style";
import { dir } from "dir"; import { dir } from "dir";
import { BuildOptions, BuildResult, context } from "esbuild"; import { BuildOptions, BuildResult, context, formatMessages } from "esbuild";
import { removeAsync } from "fs-jetpack"; import { cleanPlugin } from "esbuild-clean-plugin";
import isEqual from "lodash.isequal"; import isEqual from "lodash.isequal";
import { appendFile } from "node:fs/promises"; import { appendFile } from "node:fs/promises";
import { code } from "../../code"; import { code } from "../../code";
import { buildTypes } from "./typings"; import { buildTypes } from "./typings";
const decoder = new TextDecoder(); const decoder = new TextDecoder();
export const initFrontEnd = async (root: string, id_site: string) => { export const initFrontEnd = async (
root: string,
id_site: string,
force?: boolean
) => {
let existing = code.internal.frontend[id_site]; let existing = code.internal.frontend[id_site];
if (existing) { if (existing) {
try { if (force) {
await existing.dispose(); try {
delete code.internal.frontend[id_site]; await existing.dispose();
} catch (e) {} delete code.internal.frontend[id_site];
} catch (e) {}
} else {
return;
}
} }
try { try {
await isInstalling(id_site); await isInstalling(id_site);
const out_dir = dir.data(`code/${id_site}/site/build`); const out_dir = dir.data(`code/${id_site}/site/build`);
await removeAsync(out_dir);
const existing = await context({ const existing = await context({
absWorkingDir: dir.data(root), absWorkingDir: dir.data(root),
entryPoints: ["index.tsx"], entryPoints: ["index.tsx"],
@ -36,6 +42,7 @@ export const initFrontEnd = async (root: string, id_site: string) => {
sourcemap: true, sourcemap: true,
metafile: true, metafile: true,
plugins: [ plugins: [
cleanPlugin(),
style(), style(),
globalExternals({ globalExternals({
react: { react: {
@ -58,13 +65,15 @@ export const initFrontEnd = async (root: string, id_site: string) => {
}); });
setup.onEnd(async (res) => { setup.onEnd(async (res) => {
if (res.errors.length > 0) { if (res.errors.length > 0) {
if (!(await installDeps(root, res, id_site))) { await codeError(
await codeError( id_site,
id_site, (await formatMessages(res.errors, { kind: "error" })).join(
res.errors.map((e) => e.text).join("\n\n") "\n\n"
); )
} );
await installDeps(root, res, id_site);
} else { } else {
await codeError(id_site, "");
await buildTypes(root, id_site); await buildTypes(root, id_site);
} }
}); });
@ -135,8 +144,6 @@ const installDeps = async (
const pkgjson = await readPackageJSON(id_site); const pkgjson = await readPackageJSON(id_site);
const imports = new Set<string>(); const imports = new Set<string>();
if (!(await isInstalling(id_site))) await codeError(id_site, "");
if (res.errors.length > 0) { if (res.errors.length > 0) {
for (const err of res.errors) { for (const err of res.errors) {
if (err.notes?.[0].text.startsWith("You can mark the path ")) { if (err.notes?.[0].text.startsWith("You can mark the path ")) {

View File

@ -3,10 +3,18 @@ import { context } from "esbuild";
import { dirAsync, existsAsync, removeAsync, writeAsync } from "fs-jetpack"; import { dirAsync, existsAsync, removeAsync, writeAsync } from "fs-jetpack";
import { code } from "../../code"; import { code } from "../../code";
export const initServer = async (root: string, id_site: string) => { export const initServer = async (
root: string,
id_site: string,
force?: boolean
) => {
const existing = code.internal.server[id_site]; const existing = code.internal.server[id_site];
if (existing) { if (existing) {
await existing.dispose(); if (force) {
await existing.dispose();
} else {
return;
}
} }
const build_path = code.path(id_site, "server", "build"); const build_path = code.path(id_site, "server", "build");
@ -84,4 +92,6 @@ export const initServer = async (root: string, id_site: string) => {
}`, }`,
}, },
}); });
await code.internal.server[id_site].watch();
}; };

View File

@ -9,8 +9,12 @@ import { prodIndex } from "../../../../util/prod-index";
import { code } from "../../code/code"; import { code } from "../../code/code";
import "./server-runtime"; import "./server-runtime";
if (!g.server_main_handler) {
g.server_main_handler = {};
}
const serverMain = () => ({ const serverMain = () => ({
handler: {} as Record<string, PrasiServer>, handler: g.server_main_handler as Record<string, PrasiServer>,
init_timeout: null as any, init_timeout: null as any,
ws(action: keyof WebSocketHandler<WSData>, ...arg: any[]) { ws(action: keyof WebSocketHandler<WSData>, ...arg: any[]) {
const id = arg[0].data.site_id; const id = arg[0].data.site_id;
@ -29,42 +33,45 @@ const serverMain = () => ({
init(site_id: string) { init(site_id: string) {
clearTimeout(this.init_timeout); clearTimeout(this.init_timeout);
this.init_timeout = setTimeout(async () => { this.init_timeout = setTimeout(async () => {
// const server_src_path = code.path(site_id, "server", "build", "index.js"); const server_src_path = code.path(site_id, "server", "build", "index.js");
// try { const file = Bun.file(server_src_path);
// delete require.cache[server_src_path]; if (!this.handler[site_id] && (await file.exists()) && file.length) {
// const svr = require(server_src_path); try {
// if (svr && typeof svr.server === "object") { delete require.cache[server_src_path];
// this.handler[site_id] = svr.server; const svr = require(server_src_path);
// this.handler[site_id].site_id = site_id; if (svr && typeof svr.server === "object") {
// if (typeof svr.server.init === "function") { this.handler[site_id] = svr.server;
// svr.server.init({}); this.handler[site_id].site_id = site_id;
// } if (typeof svr.server.init === "function") {
// Bun.write( svr.server.init({});
// Bun.file(code.path(site_id, "site", "src", "server.log")), }
// "" Bun.write(
// ); Bun.file(code.path(site_id, "site", "src", "server.log")),
// } else { ""
// const file = await Bun.file(server_src_path).text(); );
// const log_path = code.path(site_id, "site", "src", "server.log"); } else {
// if (file.length === 0) { const file = await Bun.file(server_src_path).text();
// await Bun.write(Bun.file(log_path), "server.ts is empty"); const log_path = code.path(site_id, "site", "src", "server.log");
// } else { if (file.length === 0) {
// await Bun.write( await Bun.write(Bun.file(log_path), "server.ts is empty");
// Bun.file(log_path), } else {
// "server.ts does not return server object" await Bun.write(
// ); Bun.file(log_path),
// } "server.ts does not return server object"
// } );
// } catch (e: any) { }
// const file = await Bun.file(server_src_path).text(); }
// const log_path = code.path(site_id, "site", "src", "server.log"); } catch (e: any) {
// if (file.length === 0) { const file = await Bun.file(server_src_path).text();
// await Bun.write(Bun.file(log_path), "server.ts is empty"); const log_path = code.path(site_id, "site", "src", "server.log");
// } else { if (file.length === 0) {
// await Bun.write(Bun.file(log_path), e.message); await Bun.write(Bun.file(log_path), "server.ts is empty");
// console.log(`Failed to init server ${site_id}\n`, log_path); } else {
// } await Bun.write(Bun.file(log_path), e.message);
// } console.log(`Failed to init server ${site_id}\n`, log_path);
}
}
}
}, 10); }, 10);
}, },
async http( async http(

View File

@ -9,7 +9,6 @@
"packagers": { "packagers": {
"*.wasm": "@parcel/packager-wasm" "*.wasm": "@parcel/packager-wasm"
}, },
"transformers": { "transformers": {
"*.wasm": [ "*.wasm": [
"...", "...",

View File

@ -0,0 +1,24 @@
export const loadCode = async (id_site: string, ts?: number) => {
const url = `/prod/${id_site}/_prasi/code/index.js?ts=${ts}`;
const fn = new Function(
"callback",
`
import("${url}")
.catch((e) => console.error("Failed to load site code\\n\\n", e))
.then(callback)`
);
try {
return await new Promise<any>((resolve) => {
try {
fn((exports: any) => {
resolve(exports);
});
} catch (e) {
console.log("Failed to load site code", e);
}
});
} catch (e) {
console.log("Failed to load site code", e);
}
return {};
};

View File

@ -10,6 +10,7 @@ import { reloadPage } from "./ed-route";
import { loadSite } from "./ed-site"; import { loadSite } from "./ed-site";
import { updateComponentMeta } from "./comp/load"; import { updateComponentMeta } from "./comp/load";
import { createRouter, RadixRouter } from "radix3"; import { createRouter, RadixRouter } from "radix3";
import { loadCode } from "./code-loader";
const decoder = new TextDecoder(); const decoder = new TextDecoder();
@ -185,24 +186,10 @@ export const edInitSync = (p: PG) => {
async code_changes({ ts }) { async code_changes({ ts }) {
const w = window as any; const w = window as any;
const url = `/prod/${p.site.id}/_prasi/code/index.js?ts=${ts}`; const exports = await loadCode(p.site.id, ts);
const fn = new Function( for (const [k, v] of Object.entries(exports)) {
"callback", w[k] = v;
`import("${url}").then(callback)` p.site_exports[k] = v;
);
try {
await new Promise<void>((resolve) => {
fn((exports: any) => {
p.site_exports = {};
for (const [k, v] of Object.entries(exports)) {
p.site_exports[k] = v;
w[k] = v;
}
resolve();
});
});
} catch (e) {
console.log("Failed to load site code", e);
} }
await treeRebuild(p); await treeRebuild(p);
p.render(); p.render();

View File

@ -338,7 +338,6 @@ export const EdScriptMonaco: FC<{}> = () => {
} }
} else { } else {
editorLocalValue[active.item_id] = null; editorLocalValue[active.item_id] = null;
const code_result = await p.sync.code.edit({ const code_result = await p.sync.code.edit({
type: "adv", type: "adv",
mode: mode, mode: mode,

View File

@ -6,6 +6,7 @@ import { w } from "../../../utils/types/general";
import { PG } from "../../ed/logic/ed-global"; import { PG } from "../../ed/logic/ed-global";
import { treeRebuild } from "../../ed/logic/tree/build"; import { treeRebuild } from "../../ed/logic/tree/build";
import { simpleHash } from "../utils/simple-hash"; import { simpleHash } from "../utils/simple-hash";
import { loadCode } from "../../ed/logic/code-loader";
const encoder = new TextEncoder(); const encoder = new TextEncoder();
export const viLoadSnapshot = async (p: PG) => { export const viLoadSnapshot = async (p: PG) => {
@ -62,31 +63,5 @@ export const applyEnv = async (p: PG) => {
w.api = apiProxy(p.site.config.api_url); w.api = apiProxy(p.site.config.api_url);
} }
const url = `/prod/${p.site.id}/_prasi/code/index.js?ts=${p.site_tstamp}`; await loadCode(p.site.id, p.site_tstamp);
const fn = new Function(
"callback",
`
try {
return import("${url}")
} catch(e) {
console.log("Failed to load site code", e);
}`
);
await new Promise<void>(async (resolve) => {
try {
const exports = await fn();
if (exports) {
p.site_exports = {};
for (const [k, v] of Object.entries(exports)) {
p.site_exports[k] = v;
w[k] = v;
}
}
resolve();
} catch (e) {
console.log("Failed to load site code", e);
resolve();
}
});
}; };

View File

@ -18,6 +18,30 @@ export const monacoTypings = async (
monaco: Monaco, monaco: Monaco,
prop: { values: Record<string, any>; types: Record<string, string> } prop: { values: Record<string, any>; types: Record<string, string> }
) => { ) => {
register(
monaco,
`
declare module "momo" {
export type MO = "123";
export const MUU = "123";
}
`,
"ts: momo.d.ts"
);
register(
monaco,
`
declare global {
import * as _ from "momo"
const MUU = _.MUU;
}
export {}
`,
"ts: coba.d.ts"
);
if (!map.has(prop.values)) { if (!map.has(prop.values)) {
map.set(prop.values, true); map.set(prop.values, true);
} else { } else {

BIN
bun.lockb

Binary file not shown.

View File

@ -21,6 +21,7 @@ type SingleRoute = {
export const g = global as unknown as { export const g = global as unknown as {
status: "init" | "ready"; status: "init" | "ready";
server_main_handler: any;
server_hook?: (arg: { server_hook?: (arg: {
url: URL; url: URL;
req: Request; req: Request;