wip fix
This commit is contained in:
parent
3923747602
commit
922e7f5d37
File diff suppressed because one or more lines are too long
|
|
@ -8,7 +8,7 @@ glb.ws_hook = {
|
||||||
server.ws("ping", ws, data);
|
server.ws("ping", ws, data);
|
||||||
},
|
},
|
||||||
pong(ws, data) {
|
pong(ws, data) {
|
||||||
server.ws("pong", ws, data);
|
server.ws("pong", ws, data);
|
||||||
},
|
},
|
||||||
drain(ws) {
|
drain(ws) {
|
||||||
server.ws("drain", ws);
|
server.ws("drain", ws);
|
||||||
|
|
@ -31,7 +31,12 @@ glb.server_hook = async (arg) => {
|
||||||
const site_id = arr[2];
|
const site_id = arr[2];
|
||||||
|
|
||||||
if (arr.length >= 3 && validate(site_id)) {
|
if (arr.length >= 3 && validate(site_id)) {
|
||||||
return await server.http(site_id, arg);
|
const res = await server.http(site_id, arg);
|
||||||
|
if (res instanceof Response) {
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return new Response("403: Please see server.log", { status: 403 });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,8 @@ declare global {
|
||||||
index: { head: string[]; body: string[]; render: () => string };
|
index: { head: string[]; body: string[]; render: () => string };
|
||||||
}) => Promise<Response>;
|
}) => Promise<Response>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function createServer(arg: PrasiServer): PrasiServer;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,13 @@ export const codeBuild = async (id_site: any) => {
|
||||||
`\
|
`\
|
||||||
import type {} from "./typings/global";
|
import type {} from "./typings/global";
|
||||||
|
|
||||||
export const server: PrasiServer = {
|
export const server = createServer({
|
||||||
async http({ req, handle, mode, url, index, server }) {
|
async http({ req, handle, mode, url, index, server }) {
|
||||||
return await handle(req);
|
return await handle(req);
|
||||||
},
|
},
|
||||||
};
|
db,
|
||||||
|
api
|
||||||
|
});
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
const bun_types = Bun.spawn({
|
const bun_types = Bun.spawn({
|
||||||
|
|
@ -62,14 +64,53 @@ typeof global.server_hook === "function"
|
||||||
? { ...global.console }
|
? { ...global.console }
|
||||||
: global.console;
|
: global.console;
|
||||||
|
|
||||||
const db = {};
|
let db = new Proxy({}, {
|
||||||
const api = {};
|
get(_, key) {
|
||||||
|
if (key === '___site_id') {
|
||||||
|
return (site_id) => { _.site_id = site_id }
|
||||||
|
}
|
||||||
|
if (_.site_id) {
|
||||||
|
const runtime = global.server_runtime[_.site_id];
|
||||||
|
if (runtime && runtime.db) {
|
||||||
|
return runtime.db[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let api = {};
|
||||||
if (typeof global.server_hook === "function") {
|
if (typeof global.server_hook === "function") {
|
||||||
const log = global.console.log;
|
const log = global.console.log;
|
||||||
console.log = function (...arg) {
|
console.log = function (...arg) {
|
||||||
const out = "${code.path(id_site, "site", "src", "server.log")}";
|
const out = "${code.path(id_site, "site", "src", "server.log")}";
|
||||||
_fs.appendFile(out, arg.join(" ") + "\\n");
|
_fs.appendFile(out, arg.map((e)=>{
|
||||||
|
const ancestors = [];
|
||||||
|
if (typeof e === 'object') return JSON.stringify(e, (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(value)) {
|
||||||
|
return "[circular]";
|
||||||
|
}
|
||||||
|
ancestors.push(value);
|
||||||
|
|
||||||
|
if (val.constructor && val.constructor.name){
|
||||||
|
return '[class] ' + val.constructor.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}, 2);
|
||||||
|
return e;
|
||||||
|
}).join(" ") + "\\n");
|
||||||
}.bind(console);
|
}.bind(console);
|
||||||
|
} else {
|
||||||
|
db = global.db;
|
||||||
|
api = global.api;
|
||||||
}`,
|
}`,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { g } from "utils/global";
|
||||||
|
import { dbProxy } from "../../../../../web/src/base/load/db/db-proxy";
|
||||||
|
|
||||||
|
if (!g.createServer) {
|
||||||
|
g.server_runtime = {};
|
||||||
|
g.createServer = (arg) => {
|
||||||
|
return async (site_id: string) => {
|
||||||
|
if (!g.server_runtime[site_id]) {
|
||||||
|
const site = await _db.site.findFirst({
|
||||||
|
where: {
|
||||||
|
id: site_id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
config: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (site?.config && (site.config as any).api_url) {
|
||||||
|
try {
|
||||||
|
new URL((site.config as any).api_url);
|
||||||
|
g.server_runtime[site_id] = {
|
||||||
|
db: dbProxy((site.config as any).api_url),
|
||||||
|
api: null as any,
|
||||||
|
};
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtime = g.server_runtime[site_id];
|
||||||
|
if (runtime) {
|
||||||
|
const db = runtime.db as any;
|
||||||
|
if (
|
||||||
|
!!db._ &&
|
||||||
|
typeof db._._ === "function" &&
|
||||||
|
!!arg.db &&
|
||||||
|
typeof arg.db.___site_id === "function"
|
||||||
|
) {
|
||||||
|
arg.db.___site_id(site_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,8 @@ import { WSData } from "../../../../../../pkgs/core/server/create";
|
||||||
import { codeBuild } from "./build-code";
|
import { codeBuild } from "./build-code";
|
||||||
import { prodIndex } from "../../../../util/prod-index";
|
import { prodIndex } from "../../../../util/prod-index";
|
||||||
|
|
||||||
|
import "./server-create";
|
||||||
|
|
||||||
const serverMain = () => ({
|
const serverMain = () => ({
|
||||||
handler: {} as Record<string, PrasiServer>,
|
handler: {} as Record<string, PrasiServer>,
|
||||||
init_timeout: null as any,
|
init_timeout: null as any,
|
||||||
|
|
@ -27,7 +29,7 @@ const serverMain = () => ({
|
||||||
},
|
},
|
||||||
init(site_id: string) {
|
init(site_id: string) {
|
||||||
clearTimeout(this.init_timeout);
|
clearTimeout(this.init_timeout);
|
||||||
this.init_timeout = setTimeout(() => {
|
this.init_timeout = setTimeout(async () => {
|
||||||
try {
|
try {
|
||||||
const server_src_path = code.path(
|
const server_src_path = code.path(
|
||||||
site_id,
|
site_id,
|
||||||
|
|
@ -38,7 +40,13 @@ const serverMain = () => ({
|
||||||
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 && svr.server) {
|
if (svr && svr.server) {
|
||||||
this.handler[site_id] = svr.server;
|
if (typeof svr.server === "function") {
|
||||||
|
this.handler[site_id] = await svr.server(site_id);
|
||||||
|
} else {
|
||||||
|
this.handler[site_id] = svr.server;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handler[site_id].site_id = site_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bun.write(
|
Bun.write(
|
||||||
|
|
@ -46,7 +54,7 @@ const serverMain = () => ({
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to init server ${site_id}`);
|
console.log(`Failed to init server ${site_id}`, e);
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
},
|
},
|
||||||
|
|
@ -67,6 +75,8 @@ const serverMain = () => ({
|
||||||
}
|
}
|
||||||
const handler = this.handler[site_id];
|
const handler = this.handler[site_id];
|
||||||
if (handler) {
|
if (handler) {
|
||||||
|
if (!handler.site_id) handler.site_id = site_id;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
handler.ws &&
|
handler.ws &&
|
||||||
|
|
@ -108,6 +118,7 @@ const serverMain = () => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
type PrasiServer = {
|
type PrasiServer = {
|
||||||
|
site_id?: string;
|
||||||
ws?: WebSocketHandler<{ url: string }>;
|
ws?: WebSocketHandler<{ url: string }>;
|
||||||
http: (arg: {
|
http: (arg: {
|
||||||
url: { raw: URL; pathname: string };
|
url: { raw: URL; pathname: string };
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import hash_sum from "hash-sum";
|
||||||
import { fetchViaProxy } from "../proxy";
|
import { fetchViaProxy } from "../proxy";
|
||||||
|
|
||||||
export const dbProxy = (dburl: string) => {
|
export const dbProxy = (dburl: string) => {
|
||||||
|
const name = "";
|
||||||
return new Proxy(
|
return new Proxy(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
|
@ -50,12 +51,12 @@ export const dbProxy = (dburl: string) => {
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
get(_, action: string) {
|
get(_, action: string) {
|
||||||
return (...params: any[]) => {
|
return async (...params: any[]) => {
|
||||||
if (table === "query") {
|
if (table === "query") {
|
||||||
table = action;
|
table = action;
|
||||||
action = "query";
|
action = "query";
|
||||||
}
|
}
|
||||||
return fetchSendDb(
|
return await fetchSendDb(
|
||||||
{
|
{
|
||||||
name,
|
name,
|
||||||
action,
|
action,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(BigInt.prototype as any).toJSON = function (): string {
|
(BigInt.prototype as any).toJSON = function (): string {
|
||||||
return `BigInt::` + this.toString();
|
return `BigInt::` + this.toString();
|
||||||
};
|
};
|
||||||
let w = window as any;
|
let w = (typeof window !== "undefined" ? window : null) as any;
|
||||||
|
|
||||||
export const fetchViaProxy = async (
|
export const fetchViaProxy = async (
|
||||||
url: string,
|
url: string,
|
||||||
|
|
@ -14,24 +14,25 @@ export const fetchViaProxy = async (
|
||||||
let isFile = false;
|
let isFile = false;
|
||||||
|
|
||||||
const formatSingle = async (data: any) => {
|
const formatSingle = async (data: any) => {
|
||||||
if (!(data instanceof w.FormData || data instanceof w.File)) {
|
if (w !== null) {
|
||||||
headers["content-type"] = "application/json";
|
if (!(data instanceof w.FormData || data instanceof w.File)) {
|
||||||
} else {
|
headers["content-type"] = "application/json";
|
||||||
if (data instanceof w.File) {
|
} else {
|
||||||
isFile = true;
|
if (data instanceof w.File) {
|
||||||
let ab = await new Promise<ArrayBuffer | undefined>((resolve) => {
|
isFile = true;
|
||||||
const reader = new FileReader();
|
let ab = await new Promise<ArrayBuffer | undefined>((resolve) => {
|
||||||
reader.addEventListener("load", (e) => {
|
const reader = new FileReader();
|
||||||
resolve(e.target?.result as ArrayBuffer);
|
reader.addEventListener("load", (e) => {
|
||||||
|
resolve(e.target?.result as ArrayBuffer);
|
||||||
|
});
|
||||||
|
reader.readAsArrayBuffer(data);
|
||||||
});
|
});
|
||||||
reader.readAsArrayBuffer(data);
|
if (ab) {
|
||||||
});
|
data = new File([ab], data.name);
|
||||||
if (ab) {
|
}
|
||||||
data = new File([ab], data.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -44,11 +45,92 @@ export const fetchViaProxy = async (
|
||||||
body = JSON.stringify(body);
|
body = JSON.stringify(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cur = new URL(location.href);
|
|
||||||
const base = new URL(url);
|
const base = new URL(url);
|
||||||
if (cur.host === base.host) {
|
|
||||||
|
if (w !== null) {
|
||||||
|
const cur = new URL(location.href);
|
||||||
|
|
||||||
|
if (cur.host === base.host) {
|
||||||
|
const res = await fetch(
|
||||||
|
base.pathname,
|
||||||
|
data
|
||||||
|
? {
|
||||||
|
method: "POST",
|
||||||
|
body,
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
const raw = await res.text();
|
||||||
|
try {
|
||||||
|
return JSON.parse(raw);
|
||||||
|
} catch (e) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
data instanceof File ||
|
||||||
|
(Array.isArray(data) && data[0] instanceof File)
|
||||||
|
) {
|
||||||
|
const target = new URL(url);
|
||||||
|
_headers["content-type"] = "multipart/form-data";
|
||||||
|
if (data instanceof File) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", data);
|
||||||
|
const res = await fetch(target.pathname, {
|
||||||
|
body: formData,
|
||||||
|
method: "POST",
|
||||||
|
headers: _headers,
|
||||||
|
});
|
||||||
|
return await res.text();
|
||||||
|
} else {
|
||||||
|
const formData = new FormData();
|
||||||
|
let idx = 1;
|
||||||
|
for (const file of data) {
|
||||||
|
formData.append("file-" + idx++, file);
|
||||||
|
}
|
||||||
|
const res = await fetch(target.pathname, {
|
||||||
|
body: formData,
|
||||||
|
method: "POST",
|
||||||
|
headers: _headers,
|
||||||
|
});
|
||||||
|
return await res.text();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const res = await fetch(`${w.basehost ? w.basehost : ""}/_proxy`, {
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify([
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
body,
|
||||||
|
headers,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
headers: { "content-type": "application/json" },
|
||||||
|
});
|
||||||
|
|
||||||
|
let text = "";
|
||||||
|
try {
|
||||||
|
text = await res.text();
|
||||||
|
return JSON.parse(text);
|
||||||
|
} catch (e) {
|
||||||
|
let formatted_body = null;
|
||||||
|
try {
|
||||||
|
formatted_body = JSON.stringify(JSON.parse(body), null, 2);
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
`\n\n⚡ Failed to JSON.parse fetch result of ${url}:\n\n${JSON.stringify(
|
||||||
|
text
|
||||||
|
)} \n\nwith params:\n${formatted_body}`
|
||||||
|
);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
base.pathname,
|
base,
|
||||||
data
|
data
|
||||||
? {
|
? {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
|
@ -63,65 +145,5 @@ export const fetchViaProxy = async (
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
data instanceof File ||
|
|
||||||
(Array.isArray(data) && data[0] instanceof File)
|
|
||||||
) {
|
|
||||||
const target = new URL(url);
|
|
||||||
_headers["content-type"] = "multipart/form-data";
|
|
||||||
if (data instanceof File) {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("file", data);
|
|
||||||
const res = await fetch(target.pathname, {
|
|
||||||
body: formData,
|
|
||||||
method: "POST",
|
|
||||||
headers: _headers,
|
|
||||||
});
|
|
||||||
return await res.text();
|
|
||||||
} else {
|
|
||||||
const formData = new FormData();
|
|
||||||
let idx = 1;
|
|
||||||
for (const file of data) {
|
|
||||||
formData.append("file-" + idx++, file);
|
|
||||||
}
|
|
||||||
const res = await fetch(target.pathname, {
|
|
||||||
body: formData,
|
|
||||||
method: "POST",
|
|
||||||
headers: _headers,
|
|
||||||
});
|
|
||||||
return await res.text();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const res = await fetch(`${w.basehost ? w.basehost : ""}/_proxy`, {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify([
|
|
||||||
{
|
|
||||||
url,
|
|
||||||
body,
|
|
||||||
headers,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
headers: { "content-type": "application/json" },
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = "";
|
|
||||||
try {
|
|
||||||
text = await res.text();
|
|
||||||
return JSON.parse(text);
|
|
||||||
} catch (e) {
|
|
||||||
let formatted_body = null;
|
|
||||||
try {
|
|
||||||
formatted_body = JSON.stringify(JSON.parse(body), null, 2);
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
console.warn(
|
|
||||||
`\n\n⚡ Failed to JSON.parse fetch result of ${url}:\n\n${JSON.stringify(
|
|
||||||
text
|
|
||||||
)} \n\nwith params:\n${formatted_body}`
|
|
||||||
);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,6 @@ declare global {;
|
||||||
|
|
||||||
${baseTypings}
|
${baseTypings}
|
||||||
|
|
||||||
const moko: {nama: string};
|
|
||||||
${propText.join("\n")}
|
${propText.join("\n")}
|
||||||
|
|
||||||
${iftext(
|
${iftext(
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ import { syncronize } from "y-pojo";
|
||||||
import type * as Y from "yjs";
|
import type * as Y from "yjs";
|
||||||
import { PrismaClient } from "../../../app/db/db";
|
import { PrismaClient } from "../../../app/db/db";
|
||||||
import { WSData } from "../server/create";
|
import { WSData } from "../server/create";
|
||||||
|
import {
|
||||||
|
ApiProxy,
|
||||||
|
apiProxy,
|
||||||
|
} from "../../../app/web/src/base/load/api/api-proxy";
|
||||||
|
import { dbProxy } from "../../../app/web/src/base/load/db/db-proxy";
|
||||||
|
|
||||||
type SingleRoute = {
|
type SingleRoute = {
|
||||||
url: string;
|
url: string;
|
||||||
|
|
@ -22,6 +27,16 @@ export const g = global as unknown as {
|
||||||
handle: (req: Request) => Promise<Response | undefined>;
|
handle: (req: Request) => Promise<Response | undefined>;
|
||||||
wsHandler: Record<string, WebSocketHandler<WSData>>;
|
wsHandler: Record<string, WebSocketHandler<WSData>>;
|
||||||
}) => Promise<Response | undefined>;
|
}) => Promise<Response | undefined>;
|
||||||
|
server_runtime: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
api: ReturnType<typeof apiProxy>;
|
||||||
|
db: ReturnType<typeof dbProxy>;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
createServer: (
|
||||||
|
arg: PrasiServer & { api: any; db: any }
|
||||||
|
) => (site_id: string) => Promise<PrasiServer & { api: any; db: any }>;
|
||||||
ws_hook?: WebSocketHandler<WSData>;
|
ws_hook?: WebSocketHandler<WSData>;
|
||||||
_db: PrismaClient;
|
_db: PrismaClient;
|
||||||
dburl: string;
|
dburl: string;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue