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",
"y-pojo": "^0.0.8",
"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": {
"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];
if (!cs) {
try {
const pkg_file = Bun.file(
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) {
return { type, status: "disabled" };
}
} catch (e) {}
return { type, status: "stopped" };
}

View File

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

View File

@ -3,16 +3,29 @@ import style from "@hyrious/esbuild-plugin-style";
import { dir } from "dir";
import { context } from "esbuild";
import { removeAsync } from "fs-jetpack";
import isEqual from "lodash.isequal";
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) => {
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`);
await removeAsync(build_path);
existing = await context({
absWorkingDir: root,
const existing = await context({
absWorkingDir: dir.data(root),
entryPoints: ["index.tsx"],
outdir: build_path,
format: "esm",
@ -22,6 +35,7 @@ export const initFrontEnd = async (root: string, id_site: string) => {
splitting: true,
logLevel: "silent",
sourcemap: true,
metafile: true,
plugins: [
style(),
globalExternals({
@ -37,36 +51,112 @@ export const initFrontEnd = async (root: string, id_site: string) => {
{
name: "prasi",
setup(setup) {
try {
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) {
await codeError(
id_site,
res.errors.map((e) => e.text).join("\n\n"),
"site"
res.errors.map((e) => e.text).join("\n\n")
);
} else {
buildTypes(root, id_site);
}
});
} catch (e) {
console.log("ERROR");
}
},
},
],
});
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 (
id_site: string,
error: string,
mode: "server" | "site"
) => {
const path = code.path(
id_site,
"site",
"src",
mode === "server" ? "server.log" : "index.log"
);
const codeError = async (id_site: string, error: string) => {
const path = code.path(id_site, "site", "src", "index.log");
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";
export const initTypings = async (root_dir: string, id_site: string) => {
code.internal.typings[id_site] = true as any;
export const buildTypes = async (root: string, id_site: string) => {
// console.log(root);
};

View File

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

View File

@ -53,11 +53,15 @@ const serverMain = () => ({
);
} else {
const file = await Bun.file(server_src_path).text();
if (file.length === 0) {
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");
} 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) {

View File

@ -14,15 +14,6 @@ type PRELOAD_ARGS = Parameters<PRELOAD>[0];
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<{
meta: Record<string, IMeta>;
mode: "mobile" | "desktop";

BIN
bun.lockb

Binary file not shown.