checkpoint
This commit is contained in:
parent
0c96971a8f
commit
2af0e9932e
|
|
@ -132,15 +132,6 @@ model site {
|
||||||
page_folder page_folder[]
|
page_folder page_folder[]
|
||||||
org org? @relation(fields: [id_org], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "site_id_organization_fkey")
|
org org? @relation(fields: [id_org], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "site_id_organization_fkey")
|
||||||
user user @relation(fields: [id_user], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
user user @relation(fields: [id_user], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
||||||
site_query site_query[]
|
|
||||||
}
|
|
||||||
|
|
||||||
model site_query {
|
|
||||||
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
|
||||||
id_site String? @db.Uuid
|
|
||||||
name String?
|
|
||||||
query String?
|
|
||||||
site site? @relation(fields: [id_site], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "site")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model site_use_comp {
|
model site_use_comp {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,54 @@
|
||||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||||
|
|
||||||
|
const g = global as unknown as {
|
||||||
|
_font_cache: Record<string, { body: any; headers: any }>;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!g._font_cache) {
|
||||||
|
g._font_cache = {};
|
||||||
|
}
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/_font/**",
|
url: "/_font/**",
|
||||||
async api() {
|
async api() {
|
||||||
const { req } = apiContext(this);
|
const { req } = apiContext(this);
|
||||||
const pathname = req.url.split("/_font").pop();
|
const pathname = req.url.split("/_font").pop() || "";
|
||||||
const f = await fetch(`https://api.fonts.coollabs.io${pathname}`);
|
const cache = g._font_cache[pathname];
|
||||||
const body = await f.arrayBuffer();
|
if (cache) {
|
||||||
const res = new Response(body);
|
if (req.headers.get("accept-encoding")?.includes("gzip")) {
|
||||||
|
return new Response(Bun.gzipSync(cache.body), {
|
||||||
|
headers: {
|
||||||
|
"content-type": cache.headers["content-type"],
|
||||||
|
"content-encoding": "gzip",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return new Response(cache.body, {
|
||||||
|
headers: {
|
||||||
|
"content-type": cache.headers["content-type"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let f: Response = null as any;
|
||||||
|
if (pathname?.startsWith("/s/")) {
|
||||||
|
f = await fetch(`https://fonts.gstatic.com${pathname}`);
|
||||||
|
} else {
|
||||||
|
f = await fetch(`https://fonts.googleapis.com${pathname}`);
|
||||||
|
}
|
||||||
|
if (f) {
|
||||||
|
const body = await f.text();
|
||||||
|
g._font_cache[pathname] = { body, headers: {} };
|
||||||
|
f.headers.forEach((v, k) => {
|
||||||
|
g._font_cache[pathname].headers[k] = v;
|
||||||
|
});
|
||||||
|
|
||||||
res.headers.set("content-type", f.headers.get("content-type") || "");
|
const res = new Response(
|
||||||
return res;
|
body.replaceAll("https://fonts.gstatic.com", "/_font")
|
||||||
|
);
|
||||||
|
|
||||||
|
res.headers.set("content-type", f.headers.get("content-type") || "");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
|
import { parseFile } from "@swc/core";
|
||||||
import { dir } from "dir";
|
import { dir } from "dir";
|
||||||
import { apiContext } from "service-srv";
|
import { apiContext } from "service-srv";
|
||||||
import { validate } from "uuid";
|
import { validate } from "uuid";
|
||||||
import { prodIndex } from "../util/prod-index";
|
import { prodIndex } from "../util/prod-index";
|
||||||
import { gzipAsync } from "../ws/sync/entity/zlib";
|
|
||||||
import { code } from "../ws/sync/code/code";
|
import { code } from "../ws/sync/code/code";
|
||||||
import { initFrontEnd } from "../ws/sync/code/parts/init/frontend";
|
import { initFrontEnd } from "../ws/sync/code/parts/init/frontend";
|
||||||
|
import { gzipAsync } from "../ws/sync/entity/zlib";
|
||||||
|
import { visit } from "woodpile";
|
||||||
|
import { parseTypeDef } from "../util/parse-type-def";
|
||||||
|
import { Glob, build } from "bun";
|
||||||
|
import { removeAsync } from "fs-jetpack";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/prod/:site_id/**",
|
url: "/prod/:site_id/**",
|
||||||
|
|
@ -25,16 +30,85 @@ export const _ = {
|
||||||
const action = pathname.split("/")[1];
|
const action = pathname.split("/")[1];
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "code": {
|
case "type_def": {
|
||||||
const arr = pathname.split("/").slice(2);
|
const path = dir.data(`/code/${site_id}/site/typings.d.ts`);
|
||||||
const codepath = arr.join("/");
|
const file = Bun.file(path);
|
||||||
const build_path = code.path(site_id, "site", "build", codepath);
|
if (await file.exists()) {
|
||||||
|
const glob = new Glob("type_def*");
|
||||||
|
for await (const item of glob.scan(
|
||||||
|
dir.data(`/code/${site_id}/site`)
|
||||||
|
)) {
|
||||||
|
const stamp = parseInt(item.split(".")[1]);
|
||||||
|
if (file.lastModified !== stamp) {
|
||||||
|
await removeAsync(dir.data(`/code/${site_id}/site/${item}`));
|
||||||
|
} else {
|
||||||
|
return new Response(
|
||||||
|
Bun.gzipSync(
|
||||||
|
await Bun.file(
|
||||||
|
dir.data(`/code/${site_id}/site/${item}`)
|
||||||
|
).arrayBuffer()
|
||||||
|
),
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"content-encoding": "gzip",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = JSON.stringify(await parseTypeDef(path));
|
||||||
|
await Bun.write(
|
||||||
|
dir.data(
|
||||||
|
`/code/${site_id}/site/type_def.${file.lastModified}.json`
|
||||||
|
),
|
||||||
|
res
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Response(Bun.gzipSync(res), {
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
"content-encoding": "gzip",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new Response("{}", {
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case "typings.d.ts": {
|
||||||
|
const build_path = dir.data(`/code/${site_id}/site/typings.d.ts`);
|
||||||
const file = Bun.file(build_path);
|
const file = Bun.file(build_path);
|
||||||
|
|
||||||
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("", { status: 403 });
|
}
|
||||||
|
const body = Bun.gzipSync(await file.arrayBuffer());
|
||||||
|
|
||||||
|
return new Response(body, {
|
||||||
|
headers: { "content-type": file.type, "content-encoding": "gzip" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
case "code": {
|
||||||
|
const arr = pathname.split("/").slice(2);
|
||||||
|
const codepath = arr.join("/");
|
||||||
|
const build_path = code.path(site_id, "site", "build", codepath);
|
||||||
|
let file = Bun.file(build_path);
|
||||||
|
|
||||||
|
if (!(await file.exists())) {
|
||||||
|
const root = `/code/${site_id}/site/src`;
|
||||||
|
await initFrontEnd(root, site_id, true);
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
const ival = setInterval(async () => {
|
||||||
|
file = Bun.file(build_path);
|
||||||
|
if (await file.exists()) {
|
||||||
|
clearInterval(ival);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const body = Bun.gzipSync(await file.arrayBuffer());
|
const body = Bun.gzipSync(await file.arrayBuffer());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { apiContext } from "service-srv";
|
||||||
import { code } from "../ws/sync/code/code";
|
import { code } from "../ws/sync/code/code";
|
||||||
import { initFrontEnd } from "../ws/sync/code/parts/init/frontend";
|
import { initFrontEnd } from "../ws/sync/code/parts/init/frontend";
|
||||||
import { initServer } from "../ws/sync/code/parts/init/server";
|
import { initServer } from "../ws/sync/code/parts/init/server";
|
||||||
|
import { initTypings } from "../ws/sync/code/parts/init/typings";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/rebuild/:id_site",
|
url: "/rebuild/:id_site",
|
||||||
|
|
@ -13,6 +14,7 @@ export const _ = {
|
||||||
delete server[id_site];
|
delete server[id_site];
|
||||||
await initFrontEnd(root, id_site, true);
|
await initFrontEnd(root, id_site, true);
|
||||||
await initServer(root, id_site, true);
|
await initServer(root, id_site, true);
|
||||||
|
await initTypings(root, id_site, true);
|
||||||
|
|
||||||
return "ok";
|
return "ok";
|
||||||
},
|
},
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -34,10 +34,13 @@ glb.server_hook = async (arg) => {
|
||||||
if (arr.length >= 3 && validate(site_id)) {
|
if (arr.length >= 3 && validate(site_id)) {
|
||||||
try {
|
try {
|
||||||
if (!g.server_runtime[site_id]) {
|
if (!g.server_runtime[site_id]) {
|
||||||
await g.createServerRuntime(site_id);
|
if (g.server_runtime[site_id] !== null) {
|
||||||
|
await g.createServerRuntime(site_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await server.http(site_id, arg);
|
const res = await server.http(site_id, arg);
|
||||||
|
|
||||||
if (res instanceof Response) {
|
if (res instanceof Response) {
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
import { parseFile, TsModuleDeclaration } from "@swc/core";
|
||||||
|
import { visit } from "woodpile";
|
||||||
|
|
||||||
|
type SingleExport = {
|
||||||
|
type: "all" | "named" | "default";
|
||||||
|
kind: "const" | "type";
|
||||||
|
val: string;
|
||||||
|
};
|
||||||
|
export const parseTypeDef = async (path: string) => {
|
||||||
|
const ast = await parseFile(path, { syntax: "typescript" });
|
||||||
|
|
||||||
|
const exports = {} as Record<string, SingleExport[]>;
|
||||||
|
|
||||||
|
visit(ast, {
|
||||||
|
visitWithPath: {
|
||||||
|
visitDecl(node, path) {
|
||||||
|
const t = node as TsModuleDeclaration;
|
||||||
|
if (t.type === "TsModuleDeclaration") {
|
||||||
|
if (t.body) {
|
||||||
|
exports[t.id.value] = [];
|
||||||
|
|
||||||
|
if (Array.isArray(t.body.body)) {
|
||||||
|
for (const body of t.body.body) {
|
||||||
|
if (body.type === "ExportAllDeclaration") {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "all",
|
||||||
|
kind: "const",
|
||||||
|
val: body.source.value,
|
||||||
|
});
|
||||||
|
} else if (body.type === "ExportDeclaration") {
|
||||||
|
if (body.declaration.type === "FunctionDeclaration") {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "named",
|
||||||
|
kind: "const",
|
||||||
|
val: body.declaration.identifier.value,
|
||||||
|
});
|
||||||
|
} else if (body.declaration.type === "VariableDeclaration") {
|
||||||
|
for (const dec of body.declaration.declarations) {
|
||||||
|
if (dec.type === "VariableDeclarator") {
|
||||||
|
const id = dec.id as unknown as Map<string, any>;
|
||||||
|
if (id.get("type") === "Identifier") {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "named",
|
||||||
|
kind: "const",
|
||||||
|
val: id.get("value"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
body.declaration.type === "TsTypeAliasDeclaration"
|
||||||
|
) {
|
||||||
|
if (body.declaration.id.type === "Identifier") {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "named",
|
||||||
|
kind: "type",
|
||||||
|
val: body.declaration.id.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (body.type === "ExportNamedDeclaration") {
|
||||||
|
for (const s of body.specifiers) {
|
||||||
|
if (s.type === "ExportSpecifier") {
|
||||||
|
if (s.exported) {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "named",
|
||||||
|
kind: "const",
|
||||||
|
val: s.exported.value,
|
||||||
|
});
|
||||||
|
} else if (s.orig) {
|
||||||
|
exports[t.id.value].push({
|
||||||
|
type: "named",
|
||||||
|
kind: "const",
|
||||||
|
val: s.orig.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = {} as Record<string, "const" | "type">;
|
||||||
|
const traverse = (items: SingleExport[]) => {
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.type === "all") {
|
||||||
|
const found = exports[item.val];
|
||||||
|
traverse(found);
|
||||||
|
} else {
|
||||||
|
result[item.val] = item.kind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
traverse(exports.index);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
@ -4,6 +4,7 @@ import { initServer } from "./parts/init/server";
|
||||||
import { codeInternal } from "./parts/internal";
|
import { codeInternal } from "./parts/internal";
|
||||||
import { ensureFiles } from "./utlis/ensure-files";
|
import { ensureFiles } from "./utlis/ensure-files";
|
||||||
import { ensureLib } from "./utlis/ensure-lib";
|
import { ensureLib } from "./utlis/ensure-lib";
|
||||||
|
import { initTypings } from "./parts/init/typings";
|
||||||
|
|
||||||
export const code = {
|
export const code = {
|
||||||
internal: codeInternal,
|
internal: codeInternal,
|
||||||
|
|
@ -15,6 +16,7 @@ export const code = {
|
||||||
|
|
||||||
await initFrontEnd(root, id_site);
|
await initFrontEnd(root, id_site);
|
||||||
await initServer(root, id_site);
|
await initServer(root, id_site);
|
||||||
|
await initTypings(root, id_site);
|
||||||
},
|
},
|
||||||
path(
|
path(
|
||||||
id_site: string,
|
id_site: string,
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ 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";
|
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
export const initFrontEnd = async (
|
export const initFrontEnd = async (
|
||||||
root: string,
|
root: string,
|
||||||
|
|
@ -74,7 +74,6 @@ export const initFrontEnd = async (
|
||||||
await installDeps(root, res, id_site);
|
await installDeps(root, res, id_site);
|
||||||
} else {
|
} else {
|
||||||
await codeError(id_site, "");
|
await codeError(id_site, "");
|
||||||
await buildTypes(root, id_site);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,32 @@
|
||||||
|
import { dir } from "dir";
|
||||||
import { code } from "../../code";
|
import { code } from "../../code";
|
||||||
|
|
||||||
export const buildTypes = async (root: string, id_site: string) => {
|
export const initTypings = async (
|
||||||
// console.log(root);
|
root: string,
|
||||||
|
id_site: string,
|
||||||
|
force?: boolean
|
||||||
|
) => {
|
||||||
|
let existing = code.internal.typings[id_site];
|
||||||
|
if (existing) {
|
||||||
|
if (force) {
|
||||||
|
existing.kill();
|
||||||
|
await existing.exited;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
code.internal.typings[id_site] = Bun.spawn({
|
||||||
|
cmd: [
|
||||||
|
...`tsc --watch --moduleResolution node --emitDeclarationOnly --outFile ../typings.d.ts --declaration --noEmit false`.split(
|
||||||
|
" "
|
||||||
|
),
|
||||||
|
],
|
||||||
|
cwd: dir.data(`/code/${id_site}/site/src`),
|
||||||
|
stdio: ["ignore", "ignore", "ignore"],
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ if (!g.server_main_handler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverMain = () => ({
|
const serverMain = () => ({
|
||||||
handler: g.server_main_handler as Record<string, PrasiServer>,
|
handler: g.server_main_handler as Record<string, null | 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;
|
||||||
if (this.handler[id]) {
|
if (this.handler[id]) {
|
||||||
const handler = this.handler[id].ws;
|
const handler = this.handler[id]?.ws;
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
const fn = handler[action] as any;
|
const fn = handler[action] as any;
|
||||||
|
|
@ -30,49 +30,47 @@ const serverMain = () => ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
init(site_id: string) {
|
async init(site_id: string) {
|
||||||
clearTimeout(this.init_timeout);
|
this.handler[site_id] = null;
|
||||||
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");
|
const file = Bun.file(server_src_path);
|
||||||
const file = Bun.file(server_src_path);
|
if (!this.handler[site_id] && (await file.exists()) && file.length) {
|
||||||
if (!this.handler[site_id] && (await file.exists()) && file.length) {
|
try {
|
||||||
try {
|
delete require.cache[server_src_path];
|
||||||
delete require.cache[server_src_path];
|
const svr = require(server_src_path);
|
||||||
const svr = require(server_src_path);
|
if (svr && typeof svr.server === "object") {
|
||||||
if (svr && typeof svr.server === "object") {
|
this.handler[site_id] = svr.server;
|
||||||
this.handler[site_id] = svr.server;
|
svr.server.site_id = site_id;
|
||||||
this.handler[site_id].site_id = site_id;
|
if (typeof svr.server.init === "function") {
|
||||||
if (typeof svr.server.init === "function") {
|
svr.server.init({});
|
||||||
svr.server.init({});
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
if (file.length === 0) {
|
|
||||||
await Bun.write(Bun.file(log_path), "server.ts is empty");
|
|
||||||
} else {
|
|
||||||
await Bun.write(
|
|
||||||
Bun.file(log_path),
|
|
||||||
"server.ts does not return server object"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
Bun.write(
|
||||||
|
Bun.file(code.path(site_id, "site", "src", "server.log")),
|
||||||
|
""
|
||||||
|
);
|
||||||
|
} else {
|
||||||
const file = await Bun.file(server_src_path).text();
|
const file = await Bun.file(server_src_path).text();
|
||||||
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) {
|
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 {
|
||||||
await Bun.write(Bun.file(log_path), e.message);
|
await Bun.write(
|
||||||
console.log(`Failed to init server ${site_id}\n`, log_path);
|
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");
|
||||||
|
if (file.length === 0) {
|
||||||
|
await Bun.write(Bun.file(log_path), "server.ts is empty");
|
||||||
|
} else {
|
||||||
|
await Bun.write(Bun.file(log_path), e.message);
|
||||||
|
console.log(`Failed to init server ${site_id}\n`, log_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 10);
|
}
|
||||||
},
|
},
|
||||||
async http(
|
async http(
|
||||||
site_id: string,
|
site_id: string,
|
||||||
|
|
@ -81,14 +79,15 @@ const serverMain = () => ({
|
||||||
if (arg.url.pathname.endsWith("main.js")) {
|
if (arg.url.pathname.endsWith("main.js")) {
|
||||||
code.init(site_id, "init http");
|
code.init(site_id, "init http");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.handler[site_id] === "undefined") {
|
if (typeof this.handler[site_id] === "undefined") {
|
||||||
if (
|
if (
|
||||||
await existsAsync(code.path(site_id, "server", "build", "index.js"))
|
await existsAsync(code.path(site_id, "server", "build", "index.js"))
|
||||||
) {
|
) {
|
||||||
this.init(site_id);
|
await this.init(site_id);
|
||||||
await waitUntil(200);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = this.handler[site_id];
|
const handler = this.handler[site_id];
|
||||||
|
|
||||||
if (handler) {
|
if (handler) {
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@ if (!g.createServerRuntime) {
|
||||||
db: dbProxy((site.config as any).api_url),
|
db: dbProxy((site.config as any).api_url),
|
||||||
api: null as any,
|
api: null as any,
|
||||||
};
|
};
|
||||||
} catch (e) { }
|
} catch (e) {
|
||||||
|
g.server_runtime[site_id] = null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.server_runtime[site_id] = { db: null as any, api: null }
|
g.server_runtime[site_id] = { db: null as any, api: null };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,12 @@
|
||||||
content="width=device-width, initial-scale=1.0, user-scalable=1.0, minimum-scale=1.0, maximum-scale=1.0">
|
content="width=device-width, initial-scale=1.0, user-scalable=1.0, minimum-scale=1.0, maximum-scale=1.0">
|
||||||
<title>Prasi: App Builder</title>
|
<title>Prasi: App Builder</title>
|
||||||
<link rel="stylesheet" href="/index.css">
|
<link rel="stylesheet" href="/index.css">
|
||||||
<script>window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
<style>
|
||||||
|
@import url('/_font/css2?family=Source+Sans+3:wght@400;600&display=swap');
|
||||||
|
@import url('/_font/css2?family=JetBrains+Mono&display=swap');
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
||||||
isDisabled: true,
|
isDisabled: true,
|
||||||
_renderers: {}
|
_renderers: {}
|
||||||
};</script>
|
};</script>
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,46 @@
|
||||||
@import url('https://prasi.avolut.com/_font/css2?family=Source+Sans+3:wght@400;600&display=swap');
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
@import url('https://prasi.avolut.com/_font/css2?family=JetBrains+Mono&display=swap');
|
html,
|
||||||
|
body,
|
||||||
|
#root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
overscroll-behavior-y: none;
|
||||||
|
}
|
||||||
|
|
||||||
@tailwind base;
|
body {
|
||||||
@tailwind components;
|
font-family: "Source Sans 3", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||||
@tailwind utilities;
|
}
|
||||||
|
|
||||||
html,
|
.JsxText {
|
||||||
body,
|
color: #5c6773;
|
||||||
#root {
|
}
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex: 1;
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
overscroll-behavior-y: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
.JsxSelfClosingElement,
|
||||||
font-family: "Source Sans 3", system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
.JsxOpeningElement,
|
||||||
}
|
.JsxClosingElement,
|
||||||
|
.tagName-of-JsxOpeningElement,
|
||||||
|
.tagName-of-JsxClosingElement,
|
||||||
|
.tagName-of-JsxSelfClosingElement {
|
||||||
|
color: #41a6d9;
|
||||||
|
}
|
||||||
|
|
||||||
.JsxText {
|
.name-of-JsxAttribute {
|
||||||
color: #5c6773;
|
color: #f08c36;
|
||||||
}
|
}
|
||||||
|
|
||||||
.JsxSelfClosingElement,
|
.name-of-PropertyAssignment {
|
||||||
.JsxOpeningElement,
|
color: #86b300;
|
||||||
.JsxClosingElement,
|
}
|
||||||
.tagName-of-JsxOpeningElement,
|
|
||||||
.tagName-of-JsxClosingElement,
|
|
||||||
.tagName-of-JsxSelfClosingElement {
|
|
||||||
color: #41a6d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name-of-JsxAttribute {
|
.name-of-PropertyAccessExpression {
|
||||||
color: #f08c36;
|
color: #f08c36;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-of-PropertyAssignment {
|
|
||||||
color: #86b300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name-of-PropertyAccessExpression {
|
|
||||||
color: #f08c36;
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { useGlobal } from "web-utils";
|
import { useGlobal } from "web-utils";
|
||||||
|
import { jscript } from "../../utils/script/jscript";
|
||||||
import { Loading } from "../../utils/ui/loading";
|
import { Loading } from "../../utils/ui/loading";
|
||||||
import { EdLeft } from "./ed-left";
|
import { EdLeft } from "./ed-left";
|
||||||
import { EdMid } from "./ed-mid";
|
import { EdMid } from "./ed-mid";
|
||||||
|
|
@ -8,6 +9,7 @@ import { edInit } from "./logic/ed-init";
|
||||||
import { edRoute } from "./logic/ed-route";
|
import { edRoute } from "./logic/ed-route";
|
||||||
import { edUndoManager } from "./logic/ed-undo";
|
import { edUndoManager } from "./logic/ed-undo";
|
||||||
import { EdMain } from "./panel/main/main";
|
import { EdMain } from "./panel/main/main";
|
||||||
|
import { EdPageHistoryMain } from "./panel/main/main-history";
|
||||||
import { EdPane } from "./panel/main/pane-resize";
|
import { EdPane } from "./panel/main/pane-resize";
|
||||||
import { EdPopApi } from "./panel/popup/api/api-server";
|
import { EdPopApi } from "./panel/popup/api/api-server";
|
||||||
import { EdPopCode } from "./panel/popup/code/code";
|
import { EdPopCode } from "./panel/popup/code/code";
|
||||||
|
|
@ -16,9 +18,6 @@ import { EdPopComp } from "./panel/popup/comp/comp-popup";
|
||||||
import { EdPopPage } from "./panel/popup/page/page-popup";
|
import { EdPopPage } from "./panel/popup/page/page-popup";
|
||||||
import { EdPopScript } from "./panel/popup/script/pop-script";
|
import { EdPopScript } from "./panel/popup/script/pop-script";
|
||||||
import { EdPopSite } from "./panel/popup/site/site-popup";
|
import { EdPopSite } from "./panel/popup/site/site-popup";
|
||||||
import { EdPageHistoryMain } from "./panel/main/main-history";
|
|
||||||
import { jscript } from "../../utils/script/jscript";
|
|
||||||
import { useEffect } from "react";
|
|
||||||
|
|
||||||
export const EdBase = () => {
|
export const EdBase = () => {
|
||||||
const p = useGlobal(EDGlobal, "EDITOR");
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
export const loadCode = async (id_site: string, ts?: number) => {
|
import { PG } from "./ed-global";
|
||||||
|
|
||||||
|
export const loadCode = async (p: PG, ts?: number) => {
|
||||||
|
const id_site = p.site.id;
|
||||||
const url = `/prod/${id_site}/_prasi/code/index.js?ts=${ts}`;
|
const url = `/prod/${id_site}/_prasi/code/index.js?ts=${ts}`;
|
||||||
const fn = new Function(
|
const fn = new Function(
|
||||||
"callback",
|
"callback",
|
||||||
|
|
@ -8,9 +11,24 @@ import("${url}")
|
||||||
.then(callback)`
|
.then(callback)`
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
|
fetch(`/prod/${id_site}/_prasi/typings.d.ts`)
|
||||||
|
.catch(() => {})
|
||||||
|
.then(async (res) => {
|
||||||
|
if (res) {
|
||||||
|
p.site_dts = await res.text();
|
||||||
|
p.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return await new Promise<any>((resolve) => {
|
return await new Promise<any>((resolve) => {
|
||||||
try {
|
try {
|
||||||
fn((exports: any) => {
|
fn((exports: any) => {
|
||||||
|
const w = window as any;
|
||||||
|
|
||||||
|
for (const [k, v] of Object.entries(exports)) {
|
||||||
|
w[k] = v;
|
||||||
|
p.site_exports[k] = v;
|
||||||
|
}
|
||||||
resolve(exports);
|
resolve(exports);
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -20,5 +38,6 @@ import("${url}")
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Failed to load site code", e);
|
console.log("Failed to load site code", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ import { ESite, PG } from "./ed-global";
|
||||||
export const loadSite = async (p: PG, site: ESite, note: string) => {
|
export const loadSite = async (p: PG, site: ESite, note: string) => {
|
||||||
p.site = site;
|
p.site = site;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!p.script.db && !p.script.api) {
|
if (!p.script.db && !p.script.api) {
|
||||||
if (!location.pathname.startsWith("/ed/")) {
|
if (!location.pathname.startsWith("/ed/")) {
|
||||||
await viLoadLegacy({
|
await viLoadLegacy({
|
||||||
|
|
|
||||||
|
|
@ -184,13 +184,7 @@ export const edInitSync = (p: PG) => {
|
||||||
p.render();
|
p.render();
|
||||||
},
|
},
|
||||||
async code_changes({ ts }) {
|
async code_changes({ ts }) {
|
||||||
const w = window as any;
|
await loadCode(p, ts);
|
||||||
|
|
||||||
const exports = await loadCode(p.site.id, ts);
|
|
||||||
for (const [k, v] of Object.entries(exports)) {
|
|
||||||
w[k] = v;
|
|
||||||
p.site_exports[k] = v;
|
|
||||||
}
|
|
||||||
await treeRebuild(p);
|
await treeRebuild(p);
|
||||||
p.render();
|
p.render();
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,6 @@ export const EdScriptMonaco: FC<{}> = () => {
|
||||||
if (p.ui.popup.script.mode === "js") {
|
if (p.ui.popup.script.mode === "js") {
|
||||||
const w = window as any;
|
const w = window as any;
|
||||||
const types: any = {};
|
const types: any = {};
|
||||||
const values: any = {};
|
|
||||||
for (const prop_name of p.global_prop) {
|
for (const prop_name of p.global_prop) {
|
||||||
if (prop_name === "_types") continue;
|
if (prop_name === "_types") continue;
|
||||||
types[prop_name] = "any";
|
types[prop_name] = "any";
|
||||||
|
|
@ -110,10 +109,6 @@ export const EdScriptMonaco: FC<{}> = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [k, v] of Object.entries(p.site_exports)) {
|
|
||||||
values[k] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
let component = { id: "", props: {} as Record<string, FNCompDef> };
|
let component = { id: "", props: {} as Record<string, FNCompDef> };
|
||||||
if (meta?.item.component?.id && meta.item.component.props) {
|
if (meta?.item.component?.id && meta.item.component.props) {
|
||||||
component.id = meta.item.component.id;
|
component.id = meta.item.component.id;
|
||||||
|
|
@ -185,6 +180,7 @@ export const EdScriptMonaco: FC<{}> = () => {
|
||||||
await monacoTypings(
|
await monacoTypings(
|
||||||
{
|
{
|
||||||
site_dts: p.site_dts,
|
site_dts: p.site_dts,
|
||||||
|
site_exports: p.site_exports,
|
||||||
script: {
|
script: {
|
||||||
siteTypes: p.script.site_types,
|
siteTypes: p.script.site_types,
|
||||||
},
|
},
|
||||||
|
|
@ -193,7 +189,7 @@ export const EdScriptMonaco: FC<{}> = () => {
|
||||||
monaco,
|
monaco,
|
||||||
{
|
{
|
||||||
types,
|
types,
|
||||||
values,
|
values: {},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await jsMount(editor, monaco, p);
|
await jsMount(editor, monaco, p);
|
||||||
|
|
|
||||||
|
|
@ -17,30 +17,6 @@ export const viLoadSnapshot = async (p: PG) => {
|
||||||
if (api_url && apiURL.hostname) {
|
if (api_url && apiURL.hostname) {
|
||||||
await loadApiProxyDef(api_url, true);
|
await loadApiProxyDef(api_url, true);
|
||||||
|
|
||||||
// const api = w.prasiApi[api_url];
|
|
||||||
// if (api && api.apiTypes && api.prismaTypes) {
|
|
||||||
// const zip = JSON.stringify({
|
|
||||||
// api: api.apiTypes,
|
|
||||||
// prisma: api.prismaTypes,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// const hash = simpleHash(zip);
|
|
||||||
// const res = await p.sync?.code.action({
|
|
||||||
// type: "check-typings",
|
|
||||||
// site_id: p.site.id,
|
|
||||||
// hash,
|
|
||||||
// });
|
|
||||||
// if (res?.type === "check-typings" && !res.hash) {
|
|
||||||
// const body = Buffer.from(compress(encoder.encode(zip)));
|
|
||||||
// p.sync?.code.action({
|
|
||||||
// type: "push-typings",
|
|
||||||
// site_id: p.site.id,
|
|
||||||
// body,
|
|
||||||
// hash,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!p.script.db) p.script.db = dbProxy(api_url);
|
if (!p.script.db) p.script.db = dbProxy(api_url);
|
||||||
if (!p.script.api) p.script.api = apiProxy(api_url);
|
if (!p.script.api) p.script.api = apiProxy(api_url);
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +24,6 @@ export const viLoadSnapshot = async (p: PG) => {
|
||||||
if (e && !e.message.toLowerCase().includes("invalid url")) {
|
if (e && !e.message.toLowerCase().includes("invalid url")) {
|
||||||
console.warn("Failed to load API [Snapshot]:", api_url);
|
console.warn("Failed to load API [Snapshot]:", api_url);
|
||||||
} else {
|
} else {
|
||||||
// console.error(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,5 +38,5 @@ export const applyEnv = async (p: PG) => {
|
||||||
w.api = apiProxy(p.site.config.api_url);
|
w.api = apiProxy(p.site.config.api_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
await loadCode(p.site.id, p.site_tstamp);
|
await loadCode(p, p.site_tstamp);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export const cssFont = (
|
||||||
if (glbFont.loadedFonts.indexOf(font.family) < 0) {
|
if (glbFont.loadedFonts.indexOf(font.family) < 0) {
|
||||||
glbFont.loadedFonts.push(font.family);
|
glbFont.loadedFonts.push(font.family);
|
||||||
const doc = document;
|
const doc = document;
|
||||||
const _href = `https://prasi.avolut.com/_font/css2?family=${fontName}${weight}`;
|
const _href = `/_font/css2?family=${fontName}${weight}`;
|
||||||
if (!doc.querySelector(`link[href="${_href}]`)) {
|
if (!doc.querySelector(`link[href="${_href}]`)) {
|
||||||
const link = doc.createElement("link");
|
const link = doc.createElement("link");
|
||||||
link.type = "text/css";
|
link.type = "text/css";
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import type { OnMount } from "@monaco-editor/react";
|
import type { OnMount } from "@monaco-editor/react";
|
||||||
import { w } from "../types/general";
|
import { w } from "../types/general";
|
||||||
|
import { prismaExtendType } from "./prisma-extend";
|
||||||
import { baseTypings } from "./types/base";
|
import { baseTypings } from "./types/base";
|
||||||
import { extractProp } from "./types/prop";
|
import { extractProp } from "./types/prop";
|
||||||
import { prismaExtendType } from "./prisma-extend";
|
|
||||||
import { propPopover } from "../../nova/ed/panel/side/prop-master/prop-form";
|
|
||||||
export type MonacoEditor = Parameters<OnMount>[0];
|
export type MonacoEditor = Parameters<OnMount>[0];
|
||||||
type Monaco = Parameters<OnMount>[1];
|
type Monaco = Parameters<OnMount>[1];
|
||||||
|
|
||||||
|
|
@ -13,34 +12,33 @@ export const monacoTypings = async (
|
||||||
p: {
|
p: {
|
||||||
site_dts: string;
|
site_dts: string;
|
||||||
site: { api_url: string };
|
site: { api_url: string };
|
||||||
|
site_exports: Record<string, any>;
|
||||||
script: { siteTypes: Record<string, string> };
|
script: { siteTypes: Record<string, string> };
|
||||||
},
|
},
|
||||||
monaco: Monaco,
|
monaco: Monaco,
|
||||||
prop: { values: Record<string, any>; types: Record<string, string> }
|
prop: { values: Record<string, any>; types: Record<string, string> }
|
||||||
) => {
|
) => {
|
||||||
register(
|
if (p.site_dts) {
|
||||||
monaco,
|
register(monaco, p.site_dts, "ts: site.d.ts");
|
||||||
`
|
register(
|
||||||
declare module "momo" {
|
monaco,
|
||||||
export type MO = "123";
|
`
|
||||||
export const MUU = "123";
|
declare global {
|
||||||
}
|
import * as _ from "index"
|
||||||
`,
|
type MOKA = _.MOKA;
|
||||||
"ts: momo.d.ts"
|
|
||||||
);
|
${Object.keys(p.site_exports)
|
||||||
|
.map((v) => {
|
||||||
register(
|
return `
|
||||||
monaco,
|
const ${v} = _.${v};`;
|
||||||
`
|
})
|
||||||
declare global {
|
.join("\n")}
|
||||||
import * as _ from "momo"
|
}
|
||||||
const MUU = _.MUU;
|
export {}
|
||||||
}
|
`,
|
||||||
export {}
|
"ts: active_global.d.ts"
|
||||||
`,
|
);
|
||||||
"ts: coba.d.ts"
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
if (!map.has(prop.values)) {
|
if (!map.has(prop.values)) {
|
||||||
map.set(prop.values, true);
|
map.set(prop.values, true);
|
||||||
|
|
@ -107,10 +105,6 @@ declare module "ts:prisma" {
|
||||||
"https://cdn.jsdelivr.net/npm/@types/react@18.2.0/jsx-runtime.d.ts"
|
"https://cdn.jsdelivr.net/npm/@types/react@18.2.0/jsx-runtime.d.ts"
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
filePath: "site.d.ts",
|
|
||||||
content: p.site_dts.replaceAll("export declare const", "declare const"),
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const propText = extractProp({
|
const propText = extractProp({
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@surfy/multipart-parser": "^1.0.2",
|
"@surfy/multipart-parser": "^1.0.2",
|
||||||
"@swc/core": "^1.3.95",
|
"@swc/core": "^1.4.17",
|
||||||
|
"woodpile": "^0.0.5",
|
||||||
"@types/mime": "^3.0.3",
|
"@types/mime": "^3.0.3",
|
||||||
"@types/unzipper": "^0.10.8",
|
"@types/unzipper": "^0.10.8",
|
||||||
"esbuild": "^0.20.2",
|
"esbuild": "^0.20.2",
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ export const cache = {
|
||||||
|
|
||||||
export type WSData = { url: URL };
|
export type WSData = { url: URL };
|
||||||
|
|
||||||
export const createServer = async () => {
|
export const createServer = async () => {
|
||||||
await serveAPI.init();
|
await serveAPI.init();
|
||||||
await serveStatic.init();
|
await serveStatic.init();
|
||||||
const { wsHandler } = await import("../../../app/srv/ws/handler");
|
const { wsHandler } = await import("../../../app/srv/ws/handler");
|
||||||
|
|
||||||
|
|
@ -28,6 +28,7 @@ export const createServer = async () => {
|
||||||
async fetch(req, server) {
|
async fetch(req, server) {
|
||||||
const url = new URL(req.url) as URL;
|
const url = new URL(req.url) as URL;
|
||||||
const prasi = {};
|
const prasi = {};
|
||||||
|
|
||||||
const handle = async (req: Request) => {
|
const handle = async (req: Request) => {
|
||||||
if (wsHandler[url.pathname]) {
|
if (wsHandler[url.pathname]) {
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,25 @@ const web = {
|
||||||
else return "static";
|
else return "static";
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!g.static_cache) {
|
||||||
|
g.static_cache = {};
|
||||||
|
}
|
||||||
|
|
||||||
const cache = {
|
const cache = {
|
||||||
static: {} as Record<
|
static: g.static_cache as Record<
|
||||||
string,
|
string,
|
||||||
{ type: string; content: any; compression: "" | "br" }
|
{ type: string; content: any; compression: "" | "br" }
|
||||||
>,
|
>,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const serveStatic: any = {
|
export const serveStatic = {
|
||||||
async init() {
|
async init() {
|
||||||
|
if (g.mode === "dev") {
|
||||||
|
for (const k of Object.keys(cache.static)) {
|
||||||
|
delete cache.static[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
await this.walk();
|
await this.walk();
|
||||||
if (g.mode === "dev") {
|
if (g.mode === "dev") {
|
||||||
watch(dir.path(`app/static`), async (_, filename) => {
|
watch(dir.path(`app/static`), async (_, filename) => {
|
||||||
|
|
@ -42,7 +52,7 @@ export const serveStatic: any = {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
cache.static = {}
|
cache.static = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -89,11 +99,12 @@ export const serveStatic: any = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g.mode === 'dev' && url.pathname.endsWith('.js')) {
|
if (g.mode === "dev" && url.pathname.endsWith(".js")) {
|
||||||
await this.walk();
|
await this.walk();
|
||||||
}
|
}
|
||||||
|
|
||||||
file = cache.static["/index.html"];
|
file = cache.static["/index.html"];
|
||||||
|
|
||||||
if (file) {
|
if (file) {
|
||||||
return new Response(file.content, {
|
return new Response(file.content, {
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ export const g = global as unknown as {
|
||||||
}) => Promise<Response | undefined>;
|
}) => Promise<Response | undefined>;
|
||||||
server_runtime: Record<
|
server_runtime: Record<
|
||||||
string,
|
string,
|
||||||
{
|
null | {
|
||||||
api: ReturnType<typeof apiProxy>;
|
api: ReturnType<typeof apiProxy>;
|
||||||
db: ReturnType<typeof dbProxy>;
|
db: ReturnType<typeof dbProxy>;
|
||||||
}
|
}
|
||||||
|
|
@ -56,4 +56,5 @@ export const g = global as unknown as {
|
||||||
apiPrepared: boolean;
|
apiPrepared: boolean;
|
||||||
Y: typeof Y;
|
Y: typeof Y;
|
||||||
syncronize: typeof syncronize;
|
syncronize: typeof syncronize;
|
||||||
|
static_cache: any;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue