check point

This commit is contained in:
Rizky 2024-05-04 09:23:49 +07:00
parent 3f780647b2
commit e3a199b45b
11 changed files with 219 additions and 111 deletions

19
app/srv/api/rebuild.ts Normal file
View File

@ -0,0 +1,19 @@
import { apiContext } from "service-srv";
import { code } from "../ws/sync/code/code";
import { initFrontEnd } from "../ws/sync/code/parts/init/frontend";
import { initServer } from "../ws/sync/code/parts/init/server";
export const _ = {
url: "/rebuild/:id_site",
async api(id_site: string) {
const { req, res } = apiContext(this);
const { frontend, server, typings } = code.internal;
const root = `/code/${id_site}/site/src`;
delete frontend[id_site];
delete server[id_site];
await initFrontEnd(root, id_site);
await initServer(root, id_site);
return "ok";
},
};

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,9 @@
"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

@ -26,6 +26,7 @@ export const code_action: SAction["code"]["action"] = async function (
const cs = code_startup.process[arg.site_id]; const cs = code_startup.process[arg.site_id];
if (!cs) { if (!cs) {
try {
const pkg_file = Bun.file( const pkg_file = Bun.file(
code.path(arg.site_id, "site", "src", "package.json") code.path(arg.site_id, "site", "src", "package.json")
); );
@ -34,7 +35,7 @@ export const code_action: SAction["code"]["action"] = async function (
if (!pkg_json.scripts || !pkg_json.scripts.startup) { if (!pkg_json.scripts || !pkg_json.scripts.startup) {
return { type, status: "disabled" }; return { type, status: "disabled" };
} }
} catch (e) {}
return { type, status: "stopped" }; return { type, status: "stopped" };
} }

View File

@ -1,7 +1,7 @@
import { dir } from "dir"; import { dir } from "dir";
import { initFrontEnd } from "./parts/init/frontend"; import { initFrontEnd } from "./parts/init/frontend";
import { initServer } from "./parts/init/server"; import { initServer } from "./parts/init/server";
import { initTypings } from "./parts/init/typings"; import { buildTypes } from "./parts/init/typings";
import { codeInternal } from "./parts/internal"; import { codeInternal } from "./parts/internal";
import { ensureLib } from "./utlis/ensure-lib"; import { ensureLib } from "./utlis/ensure-lib";
import { ensureFiles } from "./utlis/ensure-files"; import { ensureFiles } from "./utlis/ensure-files";
@ -10,16 +10,13 @@ export const code = {
internal: codeInternal, internal: codeInternal,
async init(id_site: string, note: string) { async init(id_site: string, note: string) {
const { frontend, server, typings } = this.internal; const { frontend, server, typings } = this.internal;
if (true || !frontend[id_site] || !server[id_site] || !typings[id_site]) {
const root = `/code/${id_site}/site/src`; const root = `/code/${id_site}/site/src`;
if (!frontend[id_site]) await initFrontEnd(root, id_site); await initFrontEnd(root, id_site);
if (!server[id_site]) await initServer(root, id_site); await initServer(root, id_site);
if (!typings[id_site]) await initTypings(root, id_site);
await ensureLib(root, id_site); await ensureLib(root, id_site);
await ensureFiles(root, id_site); await ensureFiles(root, id_site);
}
}, },
path( path(
id_site: string, id_site: string,

View File

@ -3,16 +3,29 @@ import style from "@hyrious/esbuild-plugin-style";
import { dir } from "dir"; import { dir } from "dir";
import { context } from "esbuild"; import { context } from "esbuild";
import { removeAsync } from "fs-jetpack"; import { removeAsync } from "fs-jetpack";
import isEqual from "lodash.isequal";
import { code } from "../../code"; import { code } from "../../code";
import { buildTypes } from "./typings";
const npm_list = {} as Record<string, Set<string>>;
export const initFrontEnd = async (root: string, id_site: string) => { export const initFrontEnd = async (root: string, id_site: string) => {
let existing = code.internal.frontend[id_site]; let existing = code.internal.frontend[id_site];
if (!existing) { if (existing) {
try {
await existing.dispose();
delete code.internal.frontend[id_site];
} catch (e) {}
}
try {
await isInstalling(id_site);
const build_path = dir.data(`code/${id_site}/site/build`); const build_path = dir.data(`code/${id_site}/site/build`);
await removeAsync(build_path); await removeAsync(build_path);
existing = await context({ const existing = await context({
absWorkingDir: root, absWorkingDir: dir.data(root),
entryPoints: ["index.tsx"], entryPoints: ["index.tsx"],
outdir: build_path, outdir: build_path,
format: "esm", format: "esm",
@ -22,6 +35,7 @@ export const initFrontEnd = async (root: string, id_site: string) => {
splitting: true, splitting: true,
logLevel: "silent", logLevel: "silent",
sourcemap: true, sourcemap: true,
metafile: true,
plugins: [ plugins: [
style(), style(),
globalExternals({ globalExternals({
@ -37,36 +51,112 @@ export const initFrontEnd = async (root: string, id_site: string) => {
{ {
name: "prasi", name: "prasi",
setup(setup) { setup(setup) {
try {
setup.onEnd(async (res) => { setup.onEnd(async (res) => {
if (!npm_list[id_site]) npm_list[id_site] = new Set<string>();
const imports = new Set<string>();
if (!(await isInstalling(id_site)))
await codeError(id_site, "");
if (res.errors.length > 0) {
for (const err of res.errors) {
if (
err.notes?.[0].text.startsWith("You can mark the path ")
) {
let im = err.notes?.[0].text.split('"')[1];
if (!im.startsWith("@")) {
im = im.split("/").shift() || "";
}
imports.add(im);
}
}
}
if (res.metafile) {
for (const [_, file] of Object.entries(
res.metafile?.inputs || {}
)) {
for (const im of file.imports) {
if (im.kind === "import-statement" && im.external) {
if (
!im.path.startsWith(".") &&
!im.path.startsWith("@/")
)
imports.add(im.path);
}
}
}
}
if (!isEqual(imports, npm_list[id_site])) {
await codeError(
id_site,
"Installing dependencies:\n " + [...imports].join("\n ")
);
npm_list[id_site] = imports;
let proc = Bun.spawn(
[`npm`, `install`, "--silent", ...imports],
{
stdio: ["inherit", "pipe", "pipe"],
cwd: dir.data(root),
}
);
async function print(generator: any, prefix: any) {
for await (let value of generator) {
console.log(`${prefix} ${value}`);
await codeError(id_site, `${prefix} ${value}`);
}
}
print(proc.stdout, "stdout:");
print(proc.stderr, "stderr:");
await proc.exited;
await codeError(id_site, "");
try {
await code.internal.frontend[id_site].rebuild();
} catch (e) {}
return;
}
if (res.errors.length > 0) { if (res.errors.length > 0) {
await codeError( await codeError(
id_site, id_site,
res.errors.map((e) => e.text).join("\n\n"), res.errors.map((e) => e.text).join("\n\n")
"site"
); );
} else {
buildTypes(root, id_site);
} }
}); });
} catch (e) {
console.log("ERROR");
}
}, },
}, },
], ],
}); });
code.internal.frontend[id_site] = existing; code.internal.frontend[id_site] = existing;
existing.watch() await existing.watch();
} catch (e) {
delete code.internal.frontend[id_site];
console.log("front end error", e);
} }
await code.internal.frontend[id_site].rebuild()
}; };
const codeError = async ( const codeError = async (id_site: string, error: string) => {
id_site: string, const path = code.path(id_site, "site", "src", "index.log");
error: string,
mode: "server" | "site"
) => {
const path = code.path(
id_site,
"site",
"src",
mode === "server" ? "server.log" : "index.log"
);
await Bun.write(path, error); await Bun.write(path, error);
}; };
const isInstalling = async (id_site: string) => {
const path = code.path(id_site, "site", "src", "index.log");
const file = Bun.file(path);
try {
const text = await file.text();
if (text.startsWith("Installing dependencies")) return true;
} catch (e) {}
return false;
};

View File

@ -1,5 +1,5 @@
import { code } from "../../code"; import { code } from "../../code";
export const initTypings = async (root_dir: string, id_site: string) => { export const buildTypes = async (root: string, id_site: string) => {
code.internal.typings[id_site] = true as any; // console.log(root);
}; };

View File

@ -14,6 +14,7 @@ export const ensureFiles = async (path: string, id_site: string) => {
cwd: dir.path(tdir), cwd: dir.path(tdir),
}); });
try {
for await (const t of templates) { for await (const t of templates) {
const f = t.replaceAll("_", "."); const f = t.replaceAll("_", ".");
const to = dir.data(path + `/${f}`); const to = dir.data(path + `/${f}`);
@ -24,4 +25,7 @@ export const ensureFiles = async (path: string, id_site: string) => {
await copyAsync(from, to); await copyAsync(from, to);
} }
} }
} catch (e) {
console.log("error ensure file", e);
}
}; };

View File

@ -53,11 +53,15 @@ const serverMain = () => ({
); );
} else { } else {
const file = await Bun.file(server_src_path).text(); const file = await Bun.file(server_src_path).text();
if (file.length === 0) {
const log_path = code.path(site_id, "site", "src", "server.log"); const log_path = code.path(site_id, "site", "src", "server.log");
if (file.length === 0) {
await Bun.write(Bun.file(log_path), "server.ts is empty"); await Bun.write(Bun.file(log_path), "server.ts is empty");
} else { } else {
throw new Error("server.ts does not return server object"); await Bun.write(
Bun.file(log_path),
"server.ts does not return server object"
);
} }
} }
} catch (e: any) { } catch (e: any) {

View File

@ -14,15 +14,6 @@ type PRELOAD_ARGS = Parameters<PRELOAD>[0];
const w = window as any; const w = window as any;
if (!w.prasi_error_handler) {
w.prasi_error_handler = true;
window.addEventListener("error", (errorEvent) => {
const { lineno, colno } = errorEvent;
console.log(`Error thrown at: ${lineno}:${colno}`);
errorEvent.preventDefault();
});
}
export const Vi: FC<{ export const Vi: FC<{
meta: Record<string, IMeta>; meta: Record<string, IMeta>;
mode: "mobile" | "desktop"; mode: "mobile" | "desktop";

BIN
bun.lockb

Binary file not shown.