wip fix code
This commit is contained in:
parent
34a356ccbd
commit
d6d62c7df0
|
|
@ -1,5 +1,5 @@
|
||||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||||
import { code } from "../ws/sync/editor/code/util-code";
|
import { code } from "../ws/sync/code/code";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/nova-load/:mode/:id_site/**",
|
url: "/nova-load/:mode/:id_site/**",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { apiContext } from "service-srv";
|
import { apiContext } from "service-srv";
|
||||||
import { code } from "../ws/sync/editor/code/util-code";
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { gzipAsync } from "../ws/sync/entity/zlib";
|
import { gzipAsync } from "../ws/sync/entity/zlib";
|
||||||
import { validate } from "uuid";
|
import { validate } from "uuid";
|
||||||
import { dir } from "dir";
|
import { dir } from "dir";
|
||||||
import { existsAsync, readAsync } from "fs-jetpack";
|
import { existsAsync, readAsync } from "fs-jetpack";
|
||||||
|
import { code } from "../ws/sync/code/code";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/prod-zip/:site_id",
|
url: "/prod-zip/:site_id",
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ 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 { code } from "../ws/sync/editor/code/util-code";
|
|
||||||
import { gzipAsync } from "../ws/sync/entity/zlib";
|
import { gzipAsync } from "../ws/sync/entity/zlib";
|
||||||
|
import { code } from "../ws/sync/code/code";
|
||||||
|
|
||||||
export const _ = {
|
export const _ = {
|
||||||
url: "/prod/:site_id/**",
|
url: "/prod/:site_id/**",
|
||||||
|
|
@ -20,6 +20,8 @@ export const _ = {
|
||||||
if (!validate(site_id))
|
if (!validate(site_id))
|
||||||
return new Response("site not found", { status: 403 });
|
return new Response("site not found", { status: 403 });
|
||||||
|
|
||||||
|
code;
|
||||||
|
|
||||||
if (pathname.startsWith("_prasi")) {
|
if (pathname.startsWith("_prasi")) {
|
||||||
const action = pathname.split("/")[1];
|
const action = pathname.split("/")[1];
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -119,7 +119,7 @@ export const SyncActions = {
|
||||||
| { type: "startup-check" }
|
| { type: "startup-check" }
|
||||||
| { type: "startup-run" }
|
| { type: "startup-run" }
|
||||||
| { type: "startup-stop" }
|
| { type: "startup-stop" }
|
||||||
| { type: "push-typings"; body: Uint8Array; hash: number }
|
// | { type: "push-typings"; body: Uint8Array; hash: number }
|
||||||
| { type: "check-typings"; hash: number }
|
| { type: "check-typings"; hash: number }
|
||||||
))
|
))
|
||||||
| { type: "flush-page-cache"; page_id: string }
|
| { type: "flush-page-cache"; page_id: string }
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { Subprocess, spawn } from "bun";
|
import { Subprocess, spawn } from "bun";
|
||||||
import { waitUntil } from "web-utils";
|
import { waitUntil } from "web-utils";
|
||||||
import { SAction } from "../actions";
|
import { SAction } from "../actions";
|
||||||
import { code, codeGlobalTypings } from "../editor/code/util-code";
|
|
||||||
import { docs } from "../entity/docs";
|
import { docs } from "../entity/docs";
|
||||||
import { snapshot } from "../entity/snapshot";
|
import { snapshot } from "../entity/snapshot";
|
||||||
import { SyncConnection } from "../type";
|
import { SyncConnection } from "../type";
|
||||||
|
|
@ -9,6 +8,7 @@ import { dirAsync } from "fs-jetpack";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { gunzipAsync } from "../entity/zlib";
|
import { gunzipAsync } from "../entity/zlib";
|
||||||
import { prismaExtendType } from "../../../../web/src/utils/script/prisma-extend";
|
import { prismaExtendType } from "../../../../web/src/utils/script/prisma-extend";
|
||||||
|
import { code } from "../code/code";
|
||||||
|
|
||||||
const decoder = new TextDecoder();
|
const decoder = new TextDecoder();
|
||||||
const code_startup = {
|
const code_startup = {
|
||||||
|
|
@ -84,41 +84,41 @@ export const code_action: SAction["code"]["action"] = async function (
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
return { type: "check-typings", hash: false };
|
return { type: "check-typings", hash: false };
|
||||||
}
|
}
|
||||||
case "push-typings": {
|
// case "push-typings": {
|
||||||
const dir = code.path(arg.site_id, "site", "src", "typings");
|
// const dir = code.path(arg.site_id, "site", "src", "typings");
|
||||||
await dirAsync(dir);
|
// await dirAsync(dir);
|
||||||
await dirAsync(path.join(dir, "runtime"));
|
// await dirAsync(path.join(dir, "runtime"));
|
||||||
Bun.write(Bun.file(path.join(dir, "hash")), arg.hash.toString());
|
// Bun.write(Bun.file(path.join(dir, "hash")), arg.hash.toString());
|
||||||
const res = JSON.parse(decoder.decode(await gunzipAsync(arg.body)));
|
// const res = JSON.parse(decoder.decode(await gunzipAsync(arg.body)));
|
||||||
await Bun.write(Bun.file(path.join(dir, "api.d.ts")), res.api);
|
// await Bun.write(Bun.file(path.join(dir, "api.d.ts")), res.api);
|
||||||
await Bun.write(
|
// await Bun.write(
|
||||||
Bun.file(path.join(dir, "prisma.d.ts")),
|
// Bun.file(path.join(dir, "prisma.d.ts")),
|
||||||
res.prisma["prisma.d.ts"]
|
// res.prisma["prisma.d.ts"]
|
||||||
);
|
// );
|
||||||
await Bun.write(
|
// await Bun.write(
|
||||||
Bun.file(path.join(dir, "runtime/index.d.ts")),
|
// Bun.file(path.join(dir, "runtime/index.d.ts")),
|
||||||
res.prisma["runtime/index.d.ts"]
|
// res.prisma["runtime/index.d.ts"]
|
||||||
);
|
// );
|
||||||
await Bun.write(
|
// await Bun.write(
|
||||||
Bun.file(path.join(dir, "runtime/library.d.ts")),
|
// Bun.file(path.join(dir, "runtime/library.d.ts")),
|
||||||
res.prisma["runtime/library.d.ts"]
|
// res.prisma["runtime/library.d.ts"]
|
||||||
);
|
// );
|
||||||
await Bun.write(
|
// await Bun.write(
|
||||||
Bun.file(path.join(dir, "global.d.ts")),
|
// Bun.file(path.join(dir, "global.d.ts")),
|
||||||
codeGlobalTypings.replace(
|
// codeGlobalTypings.replace(
|
||||||
`declare global {`,
|
// `declare global {`,
|
||||||
`declare global {
|
// `declare global {
|
||||||
const db: prisma.PrismaClient & ${prismaExtendType};
|
// const db: prisma.PrismaClient & ${prismaExtendType};
|
||||||
`
|
// `
|
||||||
)
|
// )
|
||||||
);
|
// );
|
||||||
|
|
||||||
Bun.spawn({
|
// Bun.spawn({
|
||||||
cmd: ["chmod", "-R", "777", "."],
|
// cmd: ["chmod", "-R", "777", "."],
|
||||||
cwd: code.path(arg.site_id, "site", "src"),
|
// cwd: code.path(arg.site_id, "site", "src"),
|
||||||
});
|
// });
|
||||||
|
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { SAction } from "../actions";
|
import { SAction } from "../actions";
|
||||||
import { prepCodeSnapshot } from "../editor/code/prep-code";
|
|
||||||
import { SyncConnection } from "../type";
|
import { SyncConnection } from "../type";
|
||||||
|
|
||||||
export const code_load: SAction["code"]["load"] = async function (
|
export const code_load: SAction["code"]["load"] = async function (
|
||||||
|
|
@ -7,7 +6,5 @@ export const code_load: SAction["code"]["load"] = async function (
|
||||||
site_id,
|
site_id,
|
||||||
type
|
type
|
||||||
) {
|
) {
|
||||||
const snap = await prepCodeSnapshot(site_id, "site");
|
|
||||||
|
|
||||||
return { id: site_id };
|
return { id: site_id };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { validate } from "uuid";
|
||||||
import { ESite } from "../../../../web/src/nova/ed/logic/ed-global";
|
import { ESite } from "../../../../web/src/nova/ed/logic/ed-global";
|
||||||
import { SAction } from "../actions";
|
import { SAction } from "../actions";
|
||||||
import { SyncConnection } from "../type";
|
import { SyncConnection } from "../type";
|
||||||
import { prepCodeSnapshot } from "../editor/code/prep-code";
|
import { code } from "../code/code";
|
||||||
|
|
||||||
export const site_load: SAction["site"]["load"] = async function (
|
export const site_load: SAction["site"]["load"] = async function (
|
||||||
this: SyncConnection,
|
this: SyncConnection,
|
||||||
|
|
@ -13,6 +13,8 @@ export const site_load: SAction["site"]["load"] = async function (
|
||||||
if (site) {
|
if (site) {
|
||||||
if (this.conf) this.conf.site_id = site.id;
|
if (this.conf) this.conf.site_id = site.id;
|
||||||
|
|
||||||
|
code.init(site.id, "init site_load");
|
||||||
|
|
||||||
const config =
|
const config =
|
||||||
typeof site.config === "object" && site.config
|
typeof site.config === "object" && site.config
|
||||||
? { api_url: (site.config as any).api_url || "" }
|
? { api_url: (site.config as any).api_url || "" }
|
||||||
|
|
@ -43,8 +45,6 @@ export const site_load: SAction["site"]["load"] = async function (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const code = await prepCodeSnapshot(site.id, "site");
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: site.id,
|
id: site.id,
|
||||||
name: site.name,
|
name: site.name,
|
||||||
|
|
@ -58,7 +58,6 @@ export const site_load: SAction["site"]["load"] = async function (
|
||||||
meta: undefined,
|
meta: undefined,
|
||||||
entry: [],
|
entry: [],
|
||||||
},
|
},
|
||||||
code_ts: code.ts,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { dir } from "dir";
|
||||||
|
import { initFrontEnd } from "./parts/init/frontend";
|
||||||
|
import { initServer } from "./parts/init/server";
|
||||||
|
import { initTypings } from "./parts/init/typings";
|
||||||
|
import { codeInternal } from "./parts/internal";
|
||||||
|
import { ensureLib } from "./utlis/ensure-lib";
|
||||||
|
import { ensure } from "./utlis/ensure";
|
||||||
|
|
||||||
|
export const code = {
|
||||||
|
internal: codeInternal,
|
||||||
|
async init(id_site: string, note: string) {
|
||||||
|
const { frontend, server, typings } = this.internal;
|
||||||
|
if (!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 ensureLib(root, id_site);
|
||||||
|
await ensure(`${root}/index.tsx`, ``);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
path(
|
||||||
|
id_site: string,
|
||||||
|
mode: "site" | "server",
|
||||||
|
type: "src" | "build" | "build_cache",
|
||||||
|
path?: string
|
||||||
|
) {
|
||||||
|
let file_path = "";
|
||||||
|
if (path) {
|
||||||
|
file_path = path[0] === "/" ? path : `/${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir.data(`/code/${id_site}/${mode}/${type}${file_path}`);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import { code } from "../../code";
|
||||||
|
|
||||||
|
export const initFrontEnd = async (root: string, id_site: string) => {
|
||||||
|
const existing = code.internal.frontend[id_site];
|
||||||
|
if (existing) {
|
||||||
|
await existing.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
code.internal.frontend[id_site] = true as any;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
import { context } from "esbuild";
|
||||||
|
import { code } from "../../code";
|
||||||
|
import { ensure } from "../../utlis/ensure";
|
||||||
|
import { dir } from "dir";
|
||||||
|
import { dirAsync, removeAsync, existsAsync, writeAsync } from "fs-jetpack";
|
||||||
|
|
||||||
|
export const initServer = async (root: string, id_site: string) => {
|
||||||
|
const existing = code.internal.server[id_site];
|
||||||
|
if (existing) {
|
||||||
|
await existing.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
const build_path = code.path(id_site, "server", "build");
|
||||||
|
await removeAsync(build_path);
|
||||||
|
await dirAsync(build_path);
|
||||||
|
|
||||||
|
const build_file = `${build_path}/index.js`;
|
||||||
|
if (!(await existsAsync(build_file))) {
|
||||||
|
await writeAsync(build_file, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
code.internal.server[id_site] = await context({
|
||||||
|
absWorkingDir: dir.data(root),
|
||||||
|
entryPoints: ["server.ts"],
|
||||||
|
bundle: true,
|
||||||
|
outfile: build_file,
|
||||||
|
platform: "node",
|
||||||
|
treeShaking: true,
|
||||||
|
format: "cjs",
|
||||||
|
logLevel: "silent",
|
||||||
|
banner: {
|
||||||
|
js: `\
|
||||||
|
const _fs = require('node:fs/promises');
|
||||||
|
const console =
|
||||||
|
typeof global.server_hook === "function"
|
||||||
|
? { ...global.console }
|
||||||
|
: global.console;
|
||||||
|
|
||||||
|
let db = new Proxy({}, {
|
||||||
|
get(_, key) {
|
||||||
|
const runtime = global.server_runtime["${id_site}"];
|
||||||
|
if (runtime && runtime.db) {
|
||||||
|
return runtime.db[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let api = {};
|
||||||
|
if (typeof global.server_hook === "function") {
|
||||||
|
const log = global.console.log;
|
||||||
|
console.log = function (...arg) {
|
||||||
|
const out = "${code.path(id_site, "site", "src", "server.log")}";
|
||||||
|
_fs.appendFile(out, arg.map((e)=>{
|
||||||
|
const ancestors = [];
|
||||||
|
if (typeof e === 'object') return JSON.stringify(e, function (key, val) {
|
||||||
|
if (val) {
|
||||||
|
if (typeof val === 'function') {
|
||||||
|
return '[function]';
|
||||||
|
}
|
||||||
|
if (typeof val === 'object') {
|
||||||
|
while (ancestors.length > 0 && ancestors.at(-1) !== this) {
|
||||||
|
ancestors.pop();
|
||||||
|
}
|
||||||
|
if (ancestors.includes(val)) {
|
||||||
|
return "[circular]";
|
||||||
|
}
|
||||||
|
ancestors.push(val);
|
||||||
|
|
||||||
|
if (val.constructor &&
|
||||||
|
!['Object', 'Array'].includes(val.constructor.name)) {
|
||||||
|
if (val.constructor.name === 'Error') {
|
||||||
|
return '[Error] ' + val.message;
|
||||||
|
}
|
||||||
|
return '[Class] ' + val.constructor.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}, 2);
|
||||||
|
return e;
|
||||||
|
}).join(" ") + "\\n");
|
||||||
|
}.bind(console);
|
||||||
|
} else {
|
||||||
|
db = global.db;
|
||||||
|
api = global.api;
|
||||||
|
}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { code } from "../../code";
|
||||||
|
|
||||||
|
export const initTypings = async (root_dir: string, id_site: string) => {
|
||||||
|
code.internal.typings[id_site] = true as any;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import { Subprocess } from "bun";
|
||||||
|
import type { BuildContext } from "esbuild";
|
||||||
|
|
||||||
|
const g = global as unknown as {
|
||||||
|
prasi_code: any;
|
||||||
|
};
|
||||||
|
type SITE_ID = string;
|
||||||
|
|
||||||
|
export const codeInternal = {
|
||||||
|
get server() {
|
||||||
|
if (!g.prasi_code) g.prasi_code = {};
|
||||||
|
if (!g.prasi_code.server) g.prasi_code.server = {};
|
||||||
|
return g.prasi_code.server as Record<SITE_ID, BuildContext>;
|
||||||
|
},
|
||||||
|
get frontend() {
|
||||||
|
if (!g.prasi_code) g.prasi_code = {};
|
||||||
|
if (!g.prasi_code.frontend) g.prasi_code.frontend = {};
|
||||||
|
return g.prasi_code.frontend as Record<SITE_ID, BuildContext>;
|
||||||
|
},
|
||||||
|
get typings() {
|
||||||
|
if (!g.prasi_code) g.prasi_code = {};
|
||||||
|
if (!g.prasi_code.typings) g.prasi_code.typings = {};
|
||||||
|
return g.prasi_code.typings as Record<SITE_ID, Subprocess>;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from "@/data";
|
||||||
|
export * from "@/exports";
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type {} from "./typings/global";
|
||||||
|
|
||||||
|
export const server: PrasiServer = {
|
||||||
|
async http({ req, handle, mode, url, index, server }) {
|
||||||
|
return await handle(req);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./lib/*"],
|
||||||
|
"app/*": ["./app/*"],
|
||||||
|
"server/*": ["./server/*"]
|
||||||
|
},
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"module": "esnext",
|
||||||
|
"target": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"moduleDetection": "force",
|
||||||
|
"declaration": true,
|
||||||
|
"outFile": "types.d.ts",
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"composite": true,
|
||||||
|
"strict": true,
|
||||||
|
"downlevelIteration": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"typeRoots": ["./node_modules/@types", "./lib/types"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
//@ts-ignore
|
||||||
|
import type * as SRVAPI from "gen/srv/api/srv";
|
||||||
|
import { Server, WebSocketHandler } from "bun";
|
||||||
|
import prisma from "./prisma";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
type Api = typeof SRVAPI;
|
||||||
|
type ApiName = keyof Api;
|
||||||
|
const api: { [k in ApiName]: Awaited<Api[k]["handler"]>["_"]["api"] } & {
|
||||||
|
_raw: any;
|
||||||
|
};
|
||||||
|
const db: prisma.PrismaClient & {
|
||||||
|
_batch: {
|
||||||
|
update: (
|
||||||
|
batch: {
|
||||||
|
table: string;
|
||||||
|
data: any;
|
||||||
|
where: any;
|
||||||
|
}[]
|
||||||
|
) => Promise<void>;
|
||||||
|
};
|
||||||
|
_schema: {
|
||||||
|
tables: () => Promise<string[]>;
|
||||||
|
columns: (table: string) => Promise<
|
||||||
|
Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
is_pk: boolean;
|
||||||
|
type: string;
|
||||||
|
optional: boolean;
|
||||||
|
db_type: string;
|
||||||
|
default?: any;
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
rels: (table: string) => Promise<
|
||||||
|
Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
type: "has-many" | "has-one";
|
||||||
|
to: {
|
||||||
|
table: string;
|
||||||
|
fields: string[];
|
||||||
|
};
|
||||||
|
from: {
|
||||||
|
table: string;
|
||||||
|
fields: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type PrasiServer = {
|
||||||
|
ws?: WebSocketHandler<{ url: string }>;
|
||||||
|
http: (arg: {
|
||||||
|
url: { raw: URL; pathname: string };
|
||||||
|
req: Request;
|
||||||
|
server: Server;
|
||||||
|
mode: "dev" | "prod";
|
||||||
|
handle: (req: Request) => Promise<Response>;
|
||||||
|
index: { head: string[]; body: string[]; render: () => string };
|
||||||
|
prasi: { page_id?: string; params?: Record<string, any> };
|
||||||
|
}) => Promise<Response>;
|
||||||
|
init: (arg: { port?: number }) => Promise<void>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { $ } from "bun";
|
||||||
|
import { dir } from "dir";
|
||||||
|
import { exists, dirAsync } from "fs-jetpack";
|
||||||
|
|
||||||
|
export const ensureLib = async (src_dir: string, id_site: string) => {
|
||||||
|
if (!exists(dir.data(src_dir))) {
|
||||||
|
await dirAsync(dir.data(src_dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists(dir.data(`${src_dir}/lib`))) {
|
||||||
|
console.log(`${src_dir}/lib not found.`);
|
||||||
|
const _ = $.cwd(dir.data(src_dir));
|
||||||
|
await _`git clone https://github.com/avolut/prasi-lib lib`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { exists, dirAsync } from "fs-jetpack";
|
||||||
|
import { dirname } from "path";
|
||||||
|
import { dir } from "dir";
|
||||||
|
|
||||||
|
export const ensure = async (path: string, content: string) => {
|
||||||
|
const _path = dir.data(path);
|
||||||
|
const _dir = dirname(_path);
|
||||||
|
if (!exists(_dir)) {
|
||||||
|
await dirAsync(_dir);
|
||||||
|
}
|
||||||
|
if (!exists(_path)) {
|
||||||
|
await Bun.write(_path, content);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,22 +1,7 @@
|
||||||
import globalExternals from "@fal-works/esbuild-plugin-global-externals";
|
|
||||||
import { style } from "@hyrious/esbuild-plugin-style";
|
|
||||||
import { context } from "esbuild";
|
|
||||||
import {
|
|
||||||
dirAsync,
|
|
||||||
existsAsync,
|
|
||||||
removeAsync,
|
|
||||||
writeAsync,
|
|
||||||
moveAsync,
|
|
||||||
} from "fs-jetpack";
|
|
||||||
import { server } from "./server-main";
|
|
||||||
import { code } from "./util-code";
|
|
||||||
import { user } from "../../entity/user";
|
|
||||||
import { conns } from "../../entity/conn";
|
|
||||||
import { SyncType } from "../../type";
|
|
||||||
import { Packr } from "msgpackr";
|
|
||||||
import { ServerWebSocket } from "bun";
|
import { ServerWebSocket } from "bun";
|
||||||
|
import { Packr } from "msgpackr";
|
||||||
import { WSData } from "../../../../../../pkgs/core/server/create";
|
import { WSData } from "../../../../../../pkgs/core/server/create";
|
||||||
import { g } from "utils/global";
|
import { code } from "../../code/code";
|
||||||
|
|
||||||
const packr = new Packr({ structuredClone: true });
|
const packr = new Packr({ structuredClone: true });
|
||||||
|
|
||||||
|
|
@ -25,267 +10,240 @@ const sendWS = (ws: ServerWebSocket<WSData>, msg: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const codeBuild = async (id_site: any) => {
|
export const codeBuild = async (id_site: any) => {
|
||||||
const src_path = code.path(id_site, "site", "src");
|
return;
|
||||||
if (!(await existsAsync(src_path))) return;
|
// const src_path = code.path(id_site, "site", "src");
|
||||||
if (!code.esbuild[id_site]) {
|
// if (!(await existsAsync(src_path))) return;
|
||||||
code.esbuild[id_site] = { site: null, server: null, site_ts: Date.now() };
|
// if (!code.esbuild[id_site]) {
|
||||||
}
|
// code.esbuild[id_site] = { site: null, server: null, site_ts: Date.now() };
|
||||||
|
|
||||||
if (!code.esbuild[id_site].server) {
|
|
||||||
const server_main = code.path(id_site, "site", "src", "server.ts");
|
|
||||||
if (!(await existsAsync(server_main))) {
|
|
||||||
await writeAsync(
|
|
||||||
server_main,
|
|
||||||
`\
|
|
||||||
import type {} from "./typings/global";
|
|
||||||
|
|
||||||
export const server: PrasiServer = {
|
|
||||||
async http({ req, handle, mode, url, index, server }) {
|
|
||||||
return await handle(req);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
`
|
|
||||||
);
|
|
||||||
const bun_types = Bun.spawn({
|
|
||||||
cmd: ["npm", "i", "-D", "@types/bun"],
|
|
||||||
cwd: code.path(id_site, "site", "src"),
|
|
||||||
});
|
|
||||||
await bun_types.exited;
|
|
||||||
}
|
|
||||||
|
|
||||||
const build_path = code.path(id_site, "server", "build");
|
|
||||||
await removeAsync(build_path);
|
|
||||||
await dirAsync(build_path);
|
|
||||||
|
|
||||||
const build_file = `${build_path}/index.js`;
|
|
||||||
if (!(await existsAsync(build_file))) {
|
|
||||||
await writeAsync(build_file, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
code.esbuild[id_site].server = await context({
|
|
||||||
absWorkingDir: src_path,
|
|
||||||
entryPoints: ["server.ts"],
|
|
||||||
bundle: true,
|
|
||||||
outfile: build_file,
|
|
||||||
platform: "node",
|
|
||||||
treeShaking: true,
|
|
||||||
format: "cjs",
|
|
||||||
logLevel: "silent",
|
|
||||||
banner: {
|
|
||||||
js: `\
|
|
||||||
const _fs = require('node:fs/promises');
|
|
||||||
const console =
|
|
||||||
typeof global.server_hook === "function"
|
|
||||||
? { ...global.console }
|
|
||||||
: global.console;
|
|
||||||
|
|
||||||
let db = new Proxy({}, {
|
|
||||||
get(_, key) {
|
|
||||||
const runtime = global.server_runtime["${id_site}"];
|
|
||||||
if (runtime && runtime.db) {
|
|
||||||
return runtime.db[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let api = {};
|
|
||||||
if (typeof global.server_hook === "function") {
|
|
||||||
const log = global.console.log;
|
|
||||||
console.log = function (...arg) {
|
|
||||||
const out = "${code.path(id_site, "site", "src", "server.log")}";
|
|
||||||
_fs.appendFile(out, arg.map((e)=>{
|
|
||||||
const ancestors = [];
|
|
||||||
if (typeof e === 'object') return JSON.stringify(e, function (key, val) {
|
|
||||||
if (val) {
|
|
||||||
if (typeof val === 'function') {
|
|
||||||
return '[function]';
|
|
||||||
}
|
|
||||||
if (typeof val === 'object') {
|
|
||||||
while (ancestors.length > 0 && ancestors.at(-1) !== this) {
|
|
||||||
ancestors.pop();
|
|
||||||
}
|
|
||||||
if (ancestors.includes(val)) {
|
|
||||||
return "[circular]";
|
|
||||||
}
|
|
||||||
ancestors.push(val);
|
|
||||||
|
|
||||||
if (val.constructor &&
|
|
||||||
!['Object', 'Array'].includes(val.constructor.name)) {
|
|
||||||
if (val.constructor.name === 'Error') {
|
|
||||||
return '[Error] ' + val.message;
|
|
||||||
}
|
|
||||||
return '[Class] ' + val.constructor.name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}, 2);
|
|
||||||
return e;
|
|
||||||
}).join(" ") + "\\n");
|
|
||||||
}.bind(console);
|
|
||||||
} else {
|
|
||||||
db = global.db;
|
|
||||||
api = global.api;
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
style(),
|
|
||||||
globalExternals({
|
|
||||||
react: {
|
|
||||||
varName: "window.React",
|
|
||||||
type: "cjs",
|
|
||||||
},
|
|
||||||
"react-dom": {
|
|
||||||
varName: "window.ReactDOM",
|
|
||||||
type: "cjs",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
name: "prasi",
|
|
||||||
setup(setup) {
|
|
||||||
const reinit = () => {
|
|
||||||
setup.onEnd((res) => {
|
|
||||||
if (res.errors.length > 0) {
|
|
||||||
Bun.write(
|
|
||||||
Bun.file(code.path(id_site, "site", "src", "server.log")),
|
|
||||||
JSON.stringify(res.errors, null, 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
server.init(id_site);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
reinit();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const esbuild = code.esbuild[id_site].server;
|
|
||||||
esbuild?.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!code.esbuild[id_site].site) {
|
|
||||||
const build_path = code.path(id_site, "site", "build_cache");
|
|
||||||
await removeAsync(build_path);
|
|
||||||
await dirAsync(build_path);
|
|
||||||
const build_file = `${build_path}/index.js`;
|
|
||||||
await writeAsync(build_file, "");
|
|
||||||
|
|
||||||
const index_path = code.path(id_site, "site", "src", "index.tsx");
|
|
||||||
if (!(await existsAsync(index_path))) {
|
|
||||||
await writeAsync(index_path, 'export const hello = "world"');
|
|
||||||
}
|
|
||||||
|
|
||||||
code.esbuild[id_site].site = await context({
|
|
||||||
absWorkingDir: src_path,
|
|
||||||
entryPoints: ["index.tsx"],
|
|
||||||
bundle: true,
|
|
||||||
outdir: build_path,
|
|
||||||
minify: true,
|
|
||||||
treeShaking: true,
|
|
||||||
format: "esm",
|
|
||||||
splitting: true,
|
|
||||||
logLevel: "silent",
|
|
||||||
sourcemap: true,
|
|
||||||
plugins: [
|
|
||||||
style(),
|
|
||||||
globalExternals({
|
|
||||||
react: {
|
|
||||||
varName: "window.React",
|
|
||||||
type: "cjs",
|
|
||||||
},
|
|
||||||
"react-dom": {
|
|
||||||
varName: "window.ReactDOM",
|
|
||||||
type: "cjs",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
name: "prasi",
|
|
||||||
setup(setup) {
|
|
||||||
setup.onEnd(async (res) => {
|
|
||||||
if (res.errors.length > 0) {
|
|
||||||
await codeError(
|
|
||||||
id_site,
|
|
||||||
res.errors.map((e) => e.text).join("\n\n"),
|
|
||||||
"site"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await removeAsync(code.path(id_site, "site", "build"));
|
|
||||||
await moveAsync(
|
|
||||||
code.path(id_site, "site", "build_cache"),
|
|
||||||
code.path(id_site, "site", "build")
|
|
||||||
);
|
|
||||||
await removeAsync(
|
|
||||||
code.path(id_site, "site", "src", "index.log")
|
|
||||||
);
|
|
||||||
|
|
||||||
code.esbuild[id_site].site_ts = Date.now();
|
|
||||||
const client_ids = new Set<string>();
|
|
||||||
user.active.findAll({ site_id: id_site }).forEach((e) => {
|
|
||||||
client_ids.add(e.client_id);
|
|
||||||
});
|
|
||||||
|
|
||||||
client_ids.forEach((client_id) => {
|
|
||||||
const ws = conns.get(client_id)?.ws;
|
|
||||||
if (ws) {
|
|
||||||
sendWS(ws, {
|
|
||||||
type: SyncType.Event,
|
|
||||||
event: "code_changes",
|
|
||||||
data: { ts: code.esbuild[id_site].site_ts },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
const esbuild = code.esbuild[id_site].site;
|
|
||||||
esbuild?.watch();
|
|
||||||
}
|
|
||||||
for (const _mode of ["site", "server"]) {
|
|
||||||
const mode = _mode as "site" | "server";
|
|
||||||
|
|
||||||
const esbuild = code.esbuild[id_site][mode];
|
|
||||||
if (esbuild) {
|
|
||||||
try {
|
|
||||||
await esbuild.rebuild();
|
|
||||||
} catch (e: any) {
|
|
||||||
await codeError(id_site, e.message, mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// const build_file = code.path(id_site, mode, "build", "index.js");
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// const codeApplyChanges = (path: string, doc: DCode) => {
|
|
||||||
// const map = doc.getMap("map");
|
|
||||||
|
|
||||||
// const files = map.get("files");
|
|
||||||
|
|
||||||
// const dirs = readDirectoryRecursively(path);
|
|
||||||
// doc.transact(() => {
|
|
||||||
// files?.forEach((v, k) => {
|
|
||||||
// if (!dirs[k]) {
|
|
||||||
// files?.delete(k);
|
|
||||||
// }
|
// }
|
||||||
// });
|
|
||||||
// for (const [k, v] of Object.entries(dirs)) {
|
|
||||||
// if (files) {
|
|
||||||
// files.set(k, v);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// return doc;
|
// if (!code.esbuild[id_site].server) {
|
||||||
|
// const server_main = code.path(id_site, "site", "src", "server.ts");
|
||||||
|
// if (!(await existsAsync(server_main))) {
|
||||||
|
// await writeAsync(
|
||||||
|
// server_main,
|
||||||
|
// `\
|
||||||
|
// import type {} from "./typings/global";
|
||||||
|
|
||||||
|
// export const server: PrasiServer = {
|
||||||
|
// async http({ req, handle, mode, url, index, server }) {
|
||||||
|
// return await handle(req);
|
||||||
|
// }
|
||||||
// };
|
// };
|
||||||
|
// `
|
||||||
|
// );
|
||||||
|
// const bun_types = Bun.spawn({
|
||||||
|
// cmd: ["npm", "i", "-D", "@types/bun"],
|
||||||
|
// cwd: code.path(id_site, "site", "src"),
|
||||||
|
// });
|
||||||
|
// await bun_types.exited;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const build_path = code.path(id_site, "server", "build");
|
||||||
|
// await removeAsync(build_path);
|
||||||
|
// await dirAsync(build_path);
|
||||||
|
|
||||||
|
// const build_file = `${build_path}/index.js`;
|
||||||
|
// if (!(await existsAsync(build_file))) {
|
||||||
|
// await writeAsync(build_file, "");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// code.esbuild[id_site].server = await context({
|
||||||
|
// absWorkingDir: src_path,
|
||||||
|
// entryPoints: ["server.ts"],
|
||||||
|
// bundle: true,
|
||||||
|
// outfile: build_file,
|
||||||
|
// platform: "node",
|
||||||
|
// treeShaking: true,
|
||||||
|
// format: "cjs",
|
||||||
|
// logLevel: "silent",
|
||||||
|
// banner: {
|
||||||
|
// js: `\
|
||||||
|
// const _fs = require('node:fs/promises');
|
||||||
|
// const console =
|
||||||
|
// typeof global.server_hook === "function"
|
||||||
|
// ? { ...global.console }
|
||||||
|
// : global.console;
|
||||||
|
|
||||||
|
// let db = new Proxy({}, {
|
||||||
|
// get(_, key) {
|
||||||
|
// const runtime = global.server_runtime["${id_site}"];
|
||||||
|
// if (runtime && runtime.db) {
|
||||||
|
// return runtime.db[key];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// let api = {};
|
||||||
|
// if (typeof global.server_hook === "function") {
|
||||||
|
// const log = global.console.log;
|
||||||
|
// console.log = function (...arg) {
|
||||||
|
// const out = "${code.path(id_site, "site", "src", "server.log")}";
|
||||||
|
// _fs.appendFile(out, arg.map((e)=>{
|
||||||
|
// const ancestors = [];
|
||||||
|
// if (typeof e === 'object') return JSON.stringify(e, function (key, val) {
|
||||||
|
// if (val) {
|
||||||
|
// if (typeof val === 'function') {
|
||||||
|
// return '[function]';
|
||||||
|
// }
|
||||||
|
// if (typeof val === 'object') {
|
||||||
|
// while (ancestors.length > 0 && ancestors.at(-1) !== this) {
|
||||||
|
// ancestors.pop();
|
||||||
|
// }
|
||||||
|
// if (ancestors.includes(val)) {
|
||||||
|
// return "[circular]";
|
||||||
|
// }
|
||||||
|
// ancestors.push(val);
|
||||||
|
|
||||||
|
// if (val.constructor &&
|
||||||
|
// !['Object', 'Array'].includes(val.constructor.name)) {
|
||||||
|
// if (val.constructor.name === 'Error') {
|
||||||
|
// return '[Error] ' + val.message;
|
||||||
|
// }
|
||||||
|
// return '[Class] ' + val.constructor.name;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return val;
|
||||||
|
// }, 2);
|
||||||
|
// return e;
|
||||||
|
// }).join(" ") + "\\n");
|
||||||
|
// }.bind(console);
|
||||||
|
// } else {
|
||||||
|
// db = global.db;
|
||||||
|
// api = global.api;
|
||||||
|
// }`,
|
||||||
|
// },
|
||||||
|
// plugins: [
|
||||||
|
// style(),
|
||||||
|
// globalExternals({
|
||||||
|
// react: {
|
||||||
|
// varName: "window.React",
|
||||||
|
// type: "cjs",
|
||||||
|
// },
|
||||||
|
// "react-dom": {
|
||||||
|
// varName: "window.ReactDOM",
|
||||||
|
// type: "cjs",
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
// {
|
||||||
|
// name: "prasi",
|
||||||
|
// setup(setup) {
|
||||||
|
// const reinit = () => {
|
||||||
|
// setup.onEnd((res) => {
|
||||||
|
// if (res.errors.length > 0) {
|
||||||
|
// Bun.write(
|
||||||
|
// Bun.file(code.path(id_site, "site", "src", "server.log")),
|
||||||
|
// JSON.stringify(res.errors, null, 2)
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// server.init(id_site);
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// reinit();
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const esbuild = code.esbuild[id_site].server;
|
||||||
|
// esbuild?.watch();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!code.esbuild[id_site].site) {
|
||||||
|
// const build_path = code.path(id_site, "site", "build_cache");
|
||||||
|
// await removeAsync(build_path);
|
||||||
|
// await dirAsync(build_path);
|
||||||
|
// const build_file = `${build_path}/index.js`;
|
||||||
|
// await writeAsync(build_file, "");
|
||||||
|
|
||||||
|
// const index_path = code.path(id_site, "site", "src", "index.tsx");
|
||||||
|
// if (!(await existsAsync(index_path))) {
|
||||||
|
// await writeAsync(index_path, 'export const hello = "world"');
|
||||||
|
// }
|
||||||
|
// console.log("running ");
|
||||||
|
|
||||||
|
// code.esbuild[id_site].site = await context({
|
||||||
|
// absWorkingDir: src_path,
|
||||||
|
// entryPoints: ["index.tsx"],
|
||||||
|
// bundle: true,
|
||||||
|
// outdir: build_path,
|
||||||
|
// minify: true,
|
||||||
|
// treeShaking: true,
|
||||||
|
// format: "esm",
|
||||||
|
// splitting: true,
|
||||||
|
// logLevel: "silent",
|
||||||
|
// sourcemap: true,
|
||||||
|
// plugins: [
|
||||||
|
// style(),
|
||||||
|
// globalExternals({
|
||||||
|
// react: {
|
||||||
|
// varName: "window.React",
|
||||||
|
// type: "cjs",
|
||||||
|
// },
|
||||||
|
// "react-dom": {
|
||||||
|
// varName: "window.ReactDOM",
|
||||||
|
// type: "cjs",
|
||||||
|
// },
|
||||||
|
// }),
|
||||||
|
// {
|
||||||
|
// name: "prasi",
|
||||||
|
// setup(setup) {
|
||||||
|
// setup.onEnd(async (res) => {
|
||||||
|
// if (res.errors.length > 0) {
|
||||||
|
// await codeError(
|
||||||
|
// id_site,
|
||||||
|
// res.errors.map((e) => e.text).join("\n\n"),
|
||||||
|
// "site"
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// codeBuildType(id_site);
|
||||||
|
// await removeAsync(code.path(id_site, "site", "build"));
|
||||||
|
// await moveAsync(
|
||||||
|
// code.path(id_site, "site", "build_cache"),
|
||||||
|
// code.path(id_site, "site", "build")
|
||||||
|
// );
|
||||||
|
// await removeAsync(
|
||||||
|
// code.path(id_site, "site", "src", "index.log")
|
||||||
|
// );
|
||||||
|
|
||||||
|
// code.esbuild[id_site].site_ts = Date.now();
|
||||||
|
// const client_ids = new Set<string>();
|
||||||
|
// user.active.findAll({ site_id: id_site }).forEach((e) => {
|
||||||
|
// client_ids.add(e.client_id);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// client_ids.forEach((client_id) => {
|
||||||
|
// const ws = conns.get(client_id)?.ws;
|
||||||
|
// if (ws) {
|
||||||
|
// sendWS(ws, {
|
||||||
|
// type: SyncType.Event,
|
||||||
|
// event: "code_changes",
|
||||||
|
// data: { ts: code.esbuild[id_site].site_ts },
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
// const esbuild = code.esbuild[id_site].site;
|
||||||
|
// esbuild?.watch();
|
||||||
|
// }
|
||||||
|
// for (const _mode of ["site", "server"]) {
|
||||||
|
// const mode = _mode as "site" | "server";
|
||||||
|
|
||||||
|
// const esbuild = code.esbuild[id_site][mode];
|
||||||
|
// if (esbuild) {
|
||||||
|
// try {
|
||||||
|
// await esbuild.rebuild();
|
||||||
|
// } catch (e: any) {
|
||||||
|
// await codeError(id_site, e.message, mode);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
const codeError = async (
|
const codeError = async (
|
||||||
id_site: string,
|
id_site: string,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
import { g } from "utils/global";
|
|
||||||
import { codeBuild } from "./build-code";
|
|
||||||
import { CodeMode, code, codeGlobalTypings } from "./util-code";
|
|
||||||
|
|
||||||
export const prepCodeSnapshot = async (id_site: string, mode: CodeMode) => {
|
|
||||||
await code
|
|
||||||
.prep(id_site, mode)
|
|
||||||
.new_file("index.tsx", "export const sample = 'hello_world'")
|
|
||||||
.new_file(
|
|
||||||
"package.json",
|
|
||||||
JSON.stringify({ name: `${mode}-${id_site}`, dependencies: {} }, null, 2)
|
|
||||||
)
|
|
||||||
.new_file("typings/global.d.ts", codeGlobalTypings)
|
|
||||||
.await();
|
|
||||||
|
|
||||||
await codeBuild(id_site);
|
|
||||||
|
|
||||||
return { ts: code.esbuild[id_site].site_ts };
|
|
||||||
};
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import type { Server, WebSocketHandler, ServerWebSocket } from "bun";
|
import type { Server, WebSocketHandler } from "bun";
|
||||||
import { existsAsync } from "fs-jetpack";
|
import { existsAsync } from "fs-jetpack";
|
||||||
import _fs from "node:fs/promises";
|
import _fs from "node:fs/promises";
|
||||||
import { g } from "utils/global";
|
import { g } from "utils/global";
|
||||||
import { waitUntil } from "web-utils";
|
import { waitUntil } from "web-utils";
|
||||||
import { code } from "./util-code";
|
|
||||||
import { WSData } from "../../../../../../pkgs/core/server/create";
|
import { WSData } from "../../../../../../pkgs/core/server/create";
|
||||||
import { codeBuild } from "./build-code";
|
|
||||||
import { prodIndex } from "../../../../util/prod-index";
|
import { prodIndex } from "../../../../util/prod-index";
|
||||||
|
|
||||||
|
import { code } from "../../code/code";
|
||||||
import "./server-runtime";
|
import "./server-runtime";
|
||||||
|
|
||||||
const serverMain = () => ({
|
const serverMain = () => ({
|
||||||
|
|
@ -61,10 +60,9 @@ const serverMain = () => ({
|
||||||
site_id: string,
|
site_id: string,
|
||||||
arg: Parameters<Exclude<(typeof g)["server_hook"], undefined>>[0]
|
arg: Parameters<Exclude<(typeof g)["server_hook"], undefined>>[0]
|
||||||
) {
|
) {
|
||||||
if (!code.esbuild[site_id]) {
|
if (arg.url.pathname.endsWith("main.js")) {
|
||||||
await codeBuild(site_id);
|
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"))
|
||||||
|
|
@ -130,13 +128,11 @@ type PrasiServer = {
|
||||||
index: { head: string[]; body: string[]; render: () => string };
|
index: { head: string[]; body: string[]; render: () => string };
|
||||||
prasi: { page_id?: string; params?: Record<string, any> };
|
prasi: { page_id?: string; params?: Record<string, any> };
|
||||||
}) => Promise<Response>;
|
}) => Promise<Response>;
|
||||||
init?: () => Promise<void>;
|
init?: (arg: { port?: number }) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const glb = global as unknown as {
|
const glb = global as unknown as {
|
||||||
_server: ReturnType<typeof serverMain>;
|
_server: ReturnType<typeof serverMain>;
|
||||||
};
|
};
|
||||||
if (!glb._server) {
|
|
||||||
glb._server = serverMain();
|
glb._server = serverMain();
|
||||||
}
|
|
||||||
export const server = glb._server;
|
export const server = glb._server;
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { dir } from "dir";
|
||||||
import { BuildContext } from "esbuild";
|
import { BuildContext } from "esbuild";
|
||||||
import { dirAsync, exists, existsAsync, writeAsync } from "fs-jetpack";
|
import { dirAsync, exists, existsAsync, writeAsync } from "fs-jetpack";
|
||||||
import { dirname } from "path";
|
import { dirname } from "path";
|
||||||
|
import { prismaExtendType } from "../../../../../web/src/utils/script/prisma-extend";
|
||||||
|
|
||||||
export type CodeBuild = {
|
export type CodeBuild = {
|
||||||
server: BuildContext | null;
|
server: BuildContext | null;
|
||||||
|
|
@ -11,7 +12,7 @@ export type CodeBuild = {
|
||||||
};
|
};
|
||||||
export type CodeMode = keyof CodeBuild;
|
export type CodeMode = keyof CodeBuild;
|
||||||
|
|
||||||
export const code = {
|
const code = {
|
||||||
path(
|
path(
|
||||||
id_site: string,
|
id_site: string,
|
||||||
mode: CodeMode,
|
mode: CodeMode,
|
||||||
|
|
@ -69,6 +70,8 @@ declare global {
|
||||||
type Api = typeof SRVAPI;
|
type Api = typeof SRVAPI;
|
||||||
type ApiName = keyof Api;
|
type ApiName = keyof Api;
|
||||||
const api: { [k in ApiName]: Awaited<Api[k]["handler"]>["_"]["api"] } & { _raw: any };
|
const api: { [k in ApiName]: Awaited<Api[k]["handler"]>["_"]["api"] } & { _raw: any };
|
||||||
|
const db: prisma.PrismaClient & ${prismaExtendType};
|
||||||
|
|
||||||
|
|
||||||
type PrasiServer = {
|
type PrasiServer = {
|
||||||
ws?: WebSocketHandler<{ url: string }>;
|
ws?: WebSocketHandler<{ url: string }>;
|
||||||
|
|
@ -81,7 +84,7 @@ declare global {
|
||||||
index: { head: string[]; body: string[]; render: () => string };
|
index: { head: string[]; body: string[]; render: () => string };
|
||||||
prasi: { page_id?: string; params?: Record<string, any> };
|
prasi: { page_id?: string; params?: Record<string, any> };
|
||||||
}) => Promise<Response>;
|
}) => Promise<Response>;
|
||||||
init: () => Promise<void>;
|
init: (arg: { port?: number }) => Promise<void>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ export const EmptySite = {
|
||||||
meta: undefined as void | Record<string, IMeta>,
|
meta: undefined as void | Record<string, IMeta>,
|
||||||
entry: [] as string[],
|
entry: [] as string[],
|
||||||
},
|
},
|
||||||
code_ts: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ESite = typeof EmptySite;
|
export type ESite = typeof EmptySite;
|
||||||
|
|
@ -150,6 +149,7 @@ export const EDGlobal = {
|
||||||
sync: null as null | Awaited<ReturnType<typeof clientStartSync>>,
|
sync: null as null | Awaited<ReturnType<typeof clientStartSync>>,
|
||||||
sync_assigned: false,
|
sync_assigned: false,
|
||||||
site: deepClone(EmptySite),
|
site: deepClone(EmptySite),
|
||||||
|
site_tstamp: Date.now(),
|
||||||
site_exports: {} as Record<string, any>,
|
site_exports: {} as Record<string, any>,
|
||||||
site_dts: "",
|
site_dts: "",
|
||||||
script: {
|
script: {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ 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.code_ts}`;
|
const url = `/prod/${p.site.id}/_prasi/code/index.js?ts=${p.site_tstamp}`;
|
||||||
const fn = new Function("callback", `import("${url}").then(callback)`);
|
const fn = new Function("callback", `import("${url}").then(callback)`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ export const createViLocal = (
|
||||||
const [_, set] = useState({});
|
const [_, set] = useState({});
|
||||||
const local = ref.current;
|
const local = ref.current;
|
||||||
local.render = () => {
|
local.render = () => {
|
||||||
if ((window as any).prasiContext?.render) {
|
if ((window as any).prasiContext.render) {
|
||||||
(window as any).prasiContext?.render();
|
(window as any).prasiContext.render();
|
||||||
} else {
|
} else {
|
||||||
set({});
|
set({});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun run ./pkgs/core/index.ts dev",
|
"dev": "bun run --hot ./pkgs/core/index.ts dev",
|
||||||
"clean": "rm -rf data/lmdb && rm -rf app/static && rm -rf app/web/.parcel-cache",
|
"clean": "rm -rf data/lmdb && rm -rf app/static && rm -rf app/web/.parcel-cache",
|
||||||
"build": "bun run --silent ./pkgs/core/build.ts",
|
"build": "bun run --silent ./pkgs/core/build.ts",
|
||||||
"build-site": "bun run --silent ./pkgs/core/build-site.ts",
|
"build-site": "bun run --silent ./pkgs/core/build-site.ts",
|
||||||
|
|
@ -19,9 +19,6 @@
|
||||||
"app/*",
|
"app/*",
|
||||||
"pkgs/*"
|
"pkgs/*"
|
||||||
],
|
],
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.0.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brotli-wasm": "^2.0.1",
|
"brotli-wasm": "^2.0.1",
|
||||||
"fdir": "^6.1.0",
|
"fdir": "^6.1.0",
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
"pino-pretty": "^10.2.3",
|
"pino-pretty": "^10.2.3",
|
||||||
"radash": "^11.0.0",
|
"radash": "^11.0.0",
|
||||||
"radix3": "^1.1.0",
|
"radix3": "^1.1.0",
|
||||||
"typescript": "^5.2.2",
|
|
||||||
"unzipper": "^0.10.14"
|
"unzipper": "^0.10.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue