wip check point
This commit is contained in:
parent
8cffe6fa69
commit
6ddbd121cb
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../../pkgs/core/server/api/api-ctx";
|
||||
import argon from "@node-rs/argon2";
|
||||
import { session } from "utils/session";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../../pkgs/core/server/api/api-ctx";
|
||||
import { session } from "utils/session";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../../pkgs/core/server/api/api-ctx";
|
||||
import { user } from "dbgen";
|
||||
import { session } from "utils/session";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { dirAsync } from "fs-jetpack";
|
||||
import trim from "lodash.trim";
|
||||
import { dirname } from "path";
|
||||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { g } from "utils/global";
|
||||
import { baseTypings } from "../../web/src/utils/script/types/base";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
|
||||
export const _ = {
|
||||
url: "/_web/comp/:id",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
|
||||
export const _ = {
|
||||
url: "/_font/**",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { g } from "utils/global";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
export const _ = {
|
||||
url: "/local-ip",
|
||||
async api() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { dir } from "dir";
|
||||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { g } from "utils/global";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { buildNpm } from "../util/build-npm";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { dir } from "dir";
|
||||
import { stat } from "fs/promises";
|
||||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { g } from "utils/global";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import crypto from "crypto";
|
|||
import { dir } from "dir";
|
||||
import { readAsync } from "fs-jetpack";
|
||||
import mime from "mime-types";
|
||||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { glb } from "../global";
|
||||
import { g } from "utils/global";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
|
||||
export const _ = {
|
||||
url: "/_web/page/:id",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import { session } from "utils/session";
|
||||
import { user } from "dbgen";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createHash } from "crypto";
|
||||
import { dir } from "dir";
|
||||
import { readAsync } from "fs-jetpack";
|
||||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
const cache = {
|
||||
md5: "",
|
||||
content: null as any,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
import ts from "typescript";
|
||||
import { createHash } from "crypto";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "service-srv";
|
||||
import { apiContext } from "../../../pkgs/core/server/api/api-ctx";
|
||||
|
||||
import { dir } from "dir";
|
||||
import fs from "fs";
|
||||
|
|
|
|||
|
|
@ -7,6 +7,19 @@ import { Loading } from "../../utils/ui/loading";
|
|||
export default page({
|
||||
url: "/ed/:site_id/:page_id",
|
||||
component: ({}) => {
|
||||
console.log("momoka");
|
||||
setTimeout(() => {
|
||||
(async () => {
|
||||
console.log(
|
||||
await fetch("/moka", {
|
||||
method: "POST",
|
||||
body: "{}",
|
||||
})
|
||||
);
|
||||
})();
|
||||
}, 2000);
|
||||
return <>uwuw</>;
|
||||
|
||||
const p = useGlobal(EDGlobal, "EDITOR");
|
||||
|
||||
const w = window as any;
|
||||
|
|
|
|||
|
|
@ -2,197 +2,30 @@ import { Root as ReactRoot, createRoot } from "react-dom/client";
|
|||
import { defineReact, defineWindow } from "web-utils";
|
||||
import { Root } from "./base/root";
|
||||
import "./index.css";
|
||||
import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api";
|
||||
import { w } from "./utils/types/general";
|
||||
import { registerMobile } from "./render/live/logic/mobile";
|
||||
import { isLocalhost } from "./utils/ui/is-localhost";
|
||||
import { reloadDBAPI } from "./utils/script/init-api";
|
||||
import { w } from "./utils/types/general";
|
||||
import { sworkerAddCache, sworkerRegister } from "./sworker-boot";
|
||||
|
||||
const start = async () => {
|
||||
const base = `${location.protocol}//${location.host}`;
|
||||
let react = {
|
||||
root: null as null | ReactRoot,
|
||||
};
|
||||
(window as any).mobile = registerMobile();
|
||||
|
||||
if (navigator.serviceWorker) {
|
||||
if (!isLocalhost()) {
|
||||
const sw = await registerServiceWorker();
|
||||
const cacheCurrentPage = () => {
|
||||
const swController = navigator.serviceWorker.controller;
|
||||
if (swController) {
|
||||
[location.href, "", "/", "/ed", "/ed/_/_", "/login"].forEach(
|
||||
(url) => {
|
||||
swController.postMessage({
|
||||
type: "add-cache",
|
||||
url: url,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
cacheCurrentPage();
|
||||
navigator.serviceWorker.addEventListener("message", (e) => {
|
||||
cacheCurrentPage();
|
||||
if (react.root) {
|
||||
if (e.data.type === "offline") {
|
||||
w.offline = true;
|
||||
const click = () => {
|
||||
if (react.root) react.root.render(<Root />);
|
||||
};
|
||||
setTimeout(click, 5000);
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center cursor-pointer"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="bg-orange-500 text-white px-4 py-2 rounded-full text-sm"
|
||||
onClick={click}
|
||||
>
|
||||
Network Failed
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (e.data.type === "activated") {
|
||||
if (e.data.shouldRefresh && sw) {
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center"
|
||||
)}
|
||||
>
|
||||
<div className="bg-blue-400 text-white px-4 py-2 rounded-full text-sm">
|
||||
Updating App...
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
sw.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
} else {
|
||||
const localVersion = localStorage.getItem("prasi-version");
|
||||
if (localVersion !== e.data.version) {
|
||||
localStorage.setItem("prasi-version", e.data.version);
|
||||
const click = () => {
|
||||
if (react.root) react.root.render(<Root />);
|
||||
};
|
||||
setTimeout(click, 5000);
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center cursor-pointer"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="bg-green-600 text-white px-4 py-2 rounded-full text-sm"
|
||||
onClick={click}
|
||||
>
|
||||
Prasi Updated{" "}
|
||||
<span className="opacity-50">{e.data.version}</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
navigator.serviceWorker.getRegistrations().then(function (registrations) {
|
||||
for (let registration of registrations) {
|
||||
registration.unregister();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
w.mobile = registerMobile();
|
||||
|
||||
// sworkerRegister(react);
|
||||
defineReact();
|
||||
await defineWindow(false);
|
||||
w.serverurl = base;
|
||||
await reloadDBAPI(base, "prod");
|
||||
|
||||
if (navigator.serviceWorker) {
|
||||
const swc = navigator.serviceWorker.controller;
|
||||
if (swc) {
|
||||
[location.href, "", "/", "/ed", "/ed/_/_", "/login"].forEach((url) => {
|
||||
swc.postMessage({
|
||||
type: "add-cache",
|
||||
url: url,
|
||||
});
|
||||
});
|
||||
if (w.prasiApi && w.prasiApi[base] && w.prasiApi[base].apiEntry) {
|
||||
const routes = Object.entries(w.prasiApi[base].apiEntry).map(
|
||||
([k, v]: any) => ({
|
||||
url: v.url,
|
||||
name: k,
|
||||
})
|
||||
);
|
||||
|
||||
swc.postMessage({
|
||||
type: "define-route",
|
||||
routes,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
w.api = createAPI(base);
|
||||
w.db = createDB(base);
|
||||
// await reloadDBAPI(base, "prod");
|
||||
// sworkerAddCache(base);
|
||||
|
||||
const el = document.getElementById("root");
|
||||
|
||||
if (el) {
|
||||
react.root = createRoot(el);
|
||||
react.root.render(<Root />);
|
||||
}
|
||||
};
|
||||
|
||||
const registerServiceWorker = async () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
try {
|
||||
return await navigator.serviceWorker.register(
|
||||
new URL("./sworker.ts", import.meta.url),
|
||||
{
|
||||
type: "module",
|
||||
scope: "/",
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`Registration failed with ${error}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
start();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import init from "wasm-gzip";
|
|||
import { jscript } from "../../../utils/script/jscript";
|
||||
import { dbClient } from "../../vi/load/db/client-db";
|
||||
import { PG } from "./ed-global";
|
||||
import { fetchViaProxy } from "../../vi/load/proxy";
|
||||
|
||||
let w = window as unknown as { db: ReturnType<typeof dbClient> };
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ export const EdScriptSnippet: FC<{}> = ({}) => {
|
|||
font-size: 12px;
|
||||
`)}
|
||||
onClick={() => {
|
||||
console.log(p.script.do_edit);
|
||||
p.script.do_edit(
|
||||
`\
|
||||
<div {...props}>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,177 @@
|
|||
import { Root as ReactRoot } from "react-dom/client";
|
||||
import { Root } from "./base/root";
|
||||
import { w } from "./utils/types/general";
|
||||
import { isLocalhost } from "./utils/ui/is-localhost";
|
||||
|
||||
export const sworkerRegister = async (react: { root: null | ReactRoot }) => {
|
||||
if (navigator.serviceWorker) {
|
||||
if (!isLocalhost()) {
|
||||
const sw = await registerServiceWorker();
|
||||
const cacheCurrentPage = () => {
|
||||
const swController = navigator.serviceWorker.controller;
|
||||
if (swController) {
|
||||
[location.href, "", "/", "/ed", "/ed/_/_", "/login"].forEach(
|
||||
(url) => {
|
||||
swController.postMessage({
|
||||
type: "add-cache",
|
||||
url: url,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
cacheCurrentPage();
|
||||
navigator.serviceWorker.addEventListener("message", (e) => {
|
||||
cacheCurrentPage();
|
||||
if (react.root) {
|
||||
if (e.data.type === "offline") {
|
||||
w.offline = true;
|
||||
const click = () => {
|
||||
if (react.root) react.root.render(<Root />);
|
||||
};
|
||||
setTimeout(click, 5000);
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center cursor-pointer"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="bg-orange-500 text-white px-4 py-2 rounded-full text-sm"
|
||||
onClick={click}
|
||||
>
|
||||
Network Failed
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (e.data.type === "activated") {
|
||||
if (e.data.shouldRefresh && sw) {
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center"
|
||||
)}
|
||||
>
|
||||
<div className="bg-blue-400 text-white px-4 py-2 rounded-full text-sm">
|
||||
Updating App...
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
sw.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
} else {
|
||||
const localVersion = localStorage.getItem("prasi-version");
|
||||
if (localVersion !== e.data.version) {
|
||||
localStorage.setItem("prasi-version", e.data.version);
|
||||
const click = () => {
|
||||
if (react.root) react.root.render(<Root />);
|
||||
};
|
||||
setTimeout(click, 5000);
|
||||
react.root.render(
|
||||
<>
|
||||
<Root />
|
||||
<div
|
||||
className={cx(
|
||||
css`
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 999;
|
||||
`,
|
||||
"flex justify-center cursor-pointer"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="bg-green-600 text-white px-4 py-2 rounded-full text-sm"
|
||||
onClick={click}
|
||||
>
|
||||
Prasi Updated{" "}
|
||||
<span className="opacity-50">{e.data.version}</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
navigator.serviceWorker.getRegistrations().then(function (registrations) {
|
||||
for (let registration of registrations) {
|
||||
registration.unregister();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const registerServiceWorker = async () => {
|
||||
if ("serviceWorker" in navigator) {
|
||||
try {
|
||||
return await navigator.serviceWorker.register(
|
||||
new URL("./sworker.ts", import.meta.url),
|
||||
{
|
||||
type: "module",
|
||||
scope: "/",
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(`Registration failed with ${error}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const sworkerAddCache = (base: string) => {
|
||||
if (navigator.serviceWorker) {
|
||||
if (!isLocalhost()) {
|
||||
const swc = navigator.serviceWorker.controller;
|
||||
if (swc) {
|
||||
[location.href, "", "/", "/ed", "/ed/_/_", "/login"].forEach((url) => {
|
||||
swc.postMessage({
|
||||
type: "add-cache",
|
||||
url: url,
|
||||
});
|
||||
});
|
||||
if (w.prasiApi && w.prasiApi[base] && w.prasiApi[base].apiEntry) {
|
||||
const routes = Object.entries(w.prasiApi[base].apiEntry).map(
|
||||
([k, v]: any) => ({
|
||||
url: v.url,
|
||||
name: k,
|
||||
})
|
||||
);
|
||||
|
||||
swc.postMessage({
|
||||
type: "define-route",
|
||||
routes,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -27,6 +27,7 @@ export const w = window as unknown as {
|
|||
prasiApi: Record<string, PrasiAPI>;
|
||||
loadedFonts: string[];
|
||||
prasiApiDbPull: boolean;
|
||||
mobile?: any;
|
||||
params: any;
|
||||
editorGlbDefault: string;
|
||||
ts: number;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "../server/api-ctx";
|
||||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { g } from "../utils/global";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { apiContext } from "../server/api-ctx";
|
||||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { DBArg, execQuery } from "../utils/query";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { g } from "utils/global";
|
||||
import { apiContext } from "../server/api-ctx";
|
||||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { dir } from "../utils/dir";
|
||||
|
||||
export const _ = {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { readAsync } from "fs-jetpack";
|
||||
import { apiContext } from "../server/api-ctx";
|
||||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { g } from "../utils/global";
|
||||
import { dir } from "../utils/dir";
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import mp from "@surfy/multipart-parser";
|
|||
|
||||
import { writeAsync } from "fs-jetpack";
|
||||
import { g } from "utils/global";
|
||||
import { apiContext } from "../server/api-ctx";
|
||||
import { apiContext } from "../server/api/api-ctx";
|
||||
import { dir } from "../utils/dir";
|
||||
export const _ = {
|
||||
url: "/_upload",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import { parcelBuild } from "utils/parcel";
|
||||
import { generateAPIFrm } from "./server/api-frm";
|
||||
import { prepareApiRoutes } from "./server/api-scan";
|
||||
import { prepareAPITypes } from "./server/prep-api-ts";
|
||||
import { prepareAPITypes } from "./server/api/prep-api-ts";
|
||||
import { startDevWatcher } from "./utils/dev-watcher";
|
||||
import { ensureNotRunning } from "./utils/ensure";
|
||||
import { g } from "./utils/global";
|
||||
|
|
@ -55,14 +53,11 @@ if (!g.apiPrepared) {
|
|||
await syncActionDefinition();
|
||||
g.log.info("WS Action defined");
|
||||
|
||||
await generateAPIFrm();
|
||||
await prepareAPITypes();
|
||||
g.log.info("API Prepared");
|
||||
g.apiPrepared = true;
|
||||
}
|
||||
|
||||
await prepareApiRoutes();
|
||||
|
||||
if (!g.parcel) {
|
||||
await parcelBuild();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
import { transform } from "@swc/core";
|
||||
import { g } from "../utils/global";
|
||||
import { createHash } from "crypto";
|
||||
|
||||
export const generateAPIFrm = async () => {
|
||||
const res = await transform(
|
||||
`
|
||||
(BigInt.prototype).toJSON = function () {
|
||||
return "BigInt::" + this.toString();
|
||||
};
|
||||
|
||||
const replacer = (key, value) => {
|
||||
if (typeof value === "string" && value.startsWith('BigInt::')) {
|
||||
return BigInt(value.substr(8));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
window.addEventListener('message', (e) => {
|
||||
const msg = e.data;
|
||||
const init = Object.assign({}, msg.init)
|
||||
|
||||
let input = msg.input;
|
||||
let url = msg.input;
|
||||
if (typeof msg.input === 'string') {
|
||||
if (!input.startsWith('http')) {
|
||||
url = new URL(\`\$\{location.origin\}\$\{input\}\`)
|
||||
} else {
|
||||
url = new URL(input)
|
||||
}
|
||||
}
|
||||
|
||||
if (init && init.body && typeof init.body === 'object') {
|
||||
if (Array.isArray(init.body)) {
|
||||
const body = new FormData();
|
||||
body.append("file", init.body[0]);
|
||||
init.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fetch(url.pathname, init)
|
||||
.then(async (res) => {
|
||||
if (res) {
|
||||
const body = await res.text();
|
||||
if (res.ok) {
|
||||
try {
|
||||
parent.postMessage({result: JSON.parse(body, replacer), id: msg.id }, '*')
|
||||
} catch(e) {
|
||||
parent.postMessage({result: body, id: msg.id }, '*')
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
parent.postMessage({error: JSON.parse(body, replacer), id: msg.id }, '*')
|
||||
} catch(e) {
|
||||
parent.postMessage({error: body, id: msg.id }, '*')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
parent.postMessage('initialized', '*')`,
|
||||
{ minify: true }
|
||||
);
|
||||
|
||||
g.frm = {
|
||||
js: res.code,
|
||||
etag: createHash("md5").update(res.code).digest("hex"),
|
||||
};
|
||||
};
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { file } from "bun";
|
||||
import { inspectAsync, listAsync } from "fs-jetpack";
|
||||
import { join } from "path";
|
||||
import { dir } from "../utils/dir";
|
||||
import { g } from "../utils/global";
|
||||
import { dir } from "../../utils/dir";
|
||||
import { g } from "../../utils/global";
|
||||
import { parseArgs } from "./parse-args";
|
||||
|
||||
export const prepareApiRoutes = async () => {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { spawn, spawnSync } from "bun";
|
||||
import { spawn } from "bun";
|
||||
import { existsAsync, readAsync } from "fs-jetpack";
|
||||
import { dir } from "../utils/dir";
|
||||
import { g } from "../utils/global";
|
||||
import { dir } from "../../utils/dir";
|
||||
import { g } from "../../utils/global";
|
||||
|
||||
export const prepareAPITypes = async () => {
|
||||
const out: string[] = [];
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
import { WebSocketHandler } from "bun";
|
||||
import { lookup } from "mime-types";
|
||||
import { createRouter } from "radix3";
|
||||
import { dir } from "../utils/dir";
|
||||
import { g } from "../utils/global";
|
||||
import { serveWS } from "./serve-ws";
|
||||
import { serveStatic } from "./serve-static";
|
||||
import { serveAPI } from "./serve-api";
|
||||
|
||||
export const cache = {
|
||||
|
|
@ -19,127 +18,24 @@ export const cache = {
|
|||
export type WSData = { url: URL };
|
||||
|
||||
export const createServer = async () => {
|
||||
g.router = createRouter({ strictTrailingSlash: false });
|
||||
await serveAPI.init();
|
||||
await serveStatic.init();
|
||||
|
||||
for (const route of Object.values(g.api)) {
|
||||
g.router.insert(route.url.replace(/\*/gi, "**"), route);
|
||||
}
|
||||
|
||||
const { wsHandler } = await import("../../../app/srv/ws/handler");
|
||||
g.server = Bun.serve({
|
||||
port: g.port,
|
||||
websocket: {
|
||||
maxPayloadLength: 9999999,
|
||||
closeOnBackpressureLimit: true,
|
||||
drain(ws) {
|
||||
// console.log("Backpressure relieved...");
|
||||
},
|
||||
close(ws, code, reason) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const close = wsHandler[pathname].close;
|
||||
if (close) {
|
||||
close(ws, code, reason);
|
||||
}
|
||||
}
|
||||
},
|
||||
message(ws, message) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const msg = wsHandler[pathname].message;
|
||||
if (msg) {
|
||||
msg(ws, message);
|
||||
}
|
||||
}
|
||||
},
|
||||
open(ws) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const open = wsHandler[pathname].open;
|
||||
if (open) {
|
||||
open(ws);
|
||||
}
|
||||
}
|
||||
},
|
||||
} as WebSocketHandler<WSData>,
|
||||
maxRequestBodySize: 9999999,
|
||||
development: true,
|
||||
websocket: await serveWS(),
|
||||
async fetch(req, server) {
|
||||
const url = new URL(req.url);
|
||||
|
||||
const response = async () => {
|
||||
if (wsHandler[url.pathname]) {
|
||||
if (
|
||||
server.upgrade(req, {
|
||||
data: {
|
||||
url: new URL(req.url),
|
||||
},
|
||||
})
|
||||
) {
|
||||
return;
|
||||
}
|
||||
return new Response("Upgrade failed :(", { status: 500 });
|
||||
}
|
||||
if (serveStatic.exists(url)) {
|
||||
return serveStatic.serve(url);
|
||||
}
|
||||
|
||||
try {
|
||||
const api = await serveAPI(url, req);
|
||||
if (api) {
|
||||
return api;
|
||||
}
|
||||
} catch (e) {
|
||||
g.log.error(e);
|
||||
}
|
||||
await serveAPI.serve(url, req);
|
||||
|
||||
const webPath = "app/static";
|
||||
try {
|
||||
const found = cache.static[url.pathname];
|
||||
|
||||
if (found && g.mode === "prod") {
|
||||
return responseCached(req, found);
|
||||
}
|
||||
|
||||
const file = Bun.file(dir.path(`${webPath}${url.pathname}`));
|
||||
if (
|
||||
(await file.exists()) &&
|
||||
file.type !== "application/octet-stream" // is not directory
|
||||
) {
|
||||
if (g.mode === "dev") {
|
||||
return new Response(file);
|
||||
}
|
||||
|
||||
if (!cache.static[url.pathname]) {
|
||||
cache.static[url.pathname] = {
|
||||
type: lookup(url.pathname) || "text/plain",
|
||||
content: await file.arrayBuffer(),
|
||||
};
|
||||
}
|
||||
|
||||
const filebr = Bun.file(dir.path(`${webPath}-br${url.pathname}`));
|
||||
if (
|
||||
(await filebr.exists()) &&
|
||||
filebr.type !== "application/octet-stream" // is not directory
|
||||
) {
|
||||
cache.static[url.pathname].br = await filebr.arrayBuffer();
|
||||
}
|
||||
|
||||
const found = cache.static[url.pathname];
|
||||
if (found) {
|
||||
return responseCached(req, found);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
g.log.error(e);
|
||||
}
|
||||
|
||||
try {
|
||||
return new Response(
|
||||
Bun.file(dir.path(`${webPath}/index.html`)) as any
|
||||
);
|
||||
} catch (e) {
|
||||
g.log.error(e);
|
||||
return new Response("Loading...");
|
||||
}
|
||||
};
|
||||
const res = await response();
|
||||
return res;
|
||||
return serveStatic.serve(url);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -149,16 +45,3 @@ export const createServer = async () => {
|
|||
g.log.info(`Started at port: ${g.server.port}`);
|
||||
}
|
||||
};
|
||||
|
||||
const responseCached = (req: Request, found: (typeof cache.static)[string]) => {
|
||||
if (req.headers.get("accept-encoding")?.includes("br") && found.br) {
|
||||
const res = new Response(found.br);
|
||||
res.headers.set("content-type", found.type);
|
||||
res.headers.set("content-encoding", "br");
|
||||
return res;
|
||||
}
|
||||
const res = new Response(found.content);
|
||||
res.headers.set("content-type", found.type);
|
||||
|
||||
return res;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,105 @@
|
|||
import { createResponse } from "./api-ctx";
|
||||
import { g } from "../utils/global";
|
||||
import { createRouter } from "radix3";
|
||||
import { g } from "utils/global";
|
||||
import { createResponse } from "./api/api-ctx";
|
||||
import { prepareApiRoutes } from "./api/api-scan";
|
||||
|
||||
export const serveAPI = {
|
||||
init: async () => {
|
||||
g.router = createRouter({ strictTrailingSlash: false });
|
||||
for (const route of Object.values(g.api)) {
|
||||
g.router.insert(route.url.replace(/\*/gi, "**"), route);
|
||||
}
|
||||
await prepareApiRoutes();
|
||||
},
|
||||
serve: async (url: URL, req: Request) => {
|
||||
let found = g.router.lookup(url.pathname);
|
||||
if (!found?.url) {
|
||||
if (!url.pathname.endsWith("/")) {
|
||||
found = g.router.lookup(url.pathname + "/");
|
||||
}
|
||||
|
||||
if (!found?.url) {
|
||||
found = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
const params = { ...found.params };
|
||||
|
||||
let args = found.args.map((e) => {
|
||||
return params[e];
|
||||
});
|
||||
|
||||
if (req.method !== "GET") {
|
||||
if (
|
||||
!req.headers.get("content-type")?.startsWith("multipart/form-data")
|
||||
) {
|
||||
try {
|
||||
const text = await req.text();
|
||||
const json = JSON.parse(text, replacer);
|
||||
|
||||
if (typeof json === "object") {
|
||||
if (Array.isArray(json)) {
|
||||
args = json;
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
const val = json[i];
|
||||
if (found.args[i]) {
|
||||
params[found.args[i]] = val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [k, v] of Object.entries(json)) {
|
||||
params[k] = v;
|
||||
}
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
const idx = found.args.findIndex((arg) => arg === k);
|
||||
if (idx >= 0) {
|
||||
args[idx] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const current = {
|
||||
req,
|
||||
res: new Response(),
|
||||
...found,
|
||||
params,
|
||||
};
|
||||
|
||||
const finalResponse = await current.fn(...args);
|
||||
|
||||
if (finalResponse instanceof Response) {
|
||||
return finalResponse;
|
||||
}
|
||||
|
||||
if (finalResponse) {
|
||||
return createResponse(current.res, finalResponse);
|
||||
}
|
||||
if (
|
||||
(current.res as any)._status &&
|
||||
(current.res as any)._status !== current.res.status
|
||||
) {
|
||||
const res = new Response(current.res.body, {
|
||||
status: (current.res as any)._status,
|
||||
});
|
||||
|
||||
current.res.headers.forEach((v, k) => {
|
||||
res.headers.set(k, v);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return current.res;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const replacer = (key: string, value: string) => {
|
||||
if (typeof value === "string" && value.startsWith("BigInt::")) {
|
||||
|
|
@ -7,90 +107,3 @@ const replacer = (key: string, value: string) => {
|
|||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
export const serveAPI = async (url: URL, req: Request) => {
|
||||
let found = g.router.lookup(url.pathname);
|
||||
if (!found?.url) {
|
||||
if (!url.pathname.endsWith("/")) {
|
||||
found = g.router.lookup(url.pathname + "/");
|
||||
}
|
||||
|
||||
if (!found?.url) {
|
||||
found = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
const params = { ...found.params };
|
||||
|
||||
let args = found.args.map((e) => {
|
||||
return params[e];
|
||||
});
|
||||
|
||||
if (req.method !== "GET") {
|
||||
if (!req.headers.get("content-type")?.startsWith("multipart/form-data")) {
|
||||
try {
|
||||
const text = await req.text();
|
||||
const json = JSON.parse(text, replacer);
|
||||
|
||||
if (typeof json === "object") {
|
||||
if (Array.isArray(json)) {
|
||||
args = json;
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
const val = json[i];
|
||||
if (found.args[i]) {
|
||||
params[found.args[i]] = val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [k, v] of Object.entries(json)) {
|
||||
params[k] = v;
|
||||
}
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
const idx = found.args.findIndex((arg) => arg === k);
|
||||
if (idx >= 0) {
|
||||
args[idx] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
g.log.error({ pathname: url.pathname, error: e });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const current = {
|
||||
req,
|
||||
res: new Response(),
|
||||
...found,
|
||||
params,
|
||||
};
|
||||
|
||||
const finalResponse = await current.fn(...args);
|
||||
|
||||
if (finalResponse instanceof Response) {
|
||||
return finalResponse;
|
||||
}
|
||||
|
||||
if (finalResponse) {
|
||||
return createResponse(current.res, finalResponse);
|
||||
}
|
||||
if (
|
||||
(current.res as any)._status &&
|
||||
(current.res as any)._status !== current.res.status
|
||||
) {
|
||||
const res = new Response(current.res.body, {
|
||||
status: (current.res as any)._status,
|
||||
});
|
||||
|
||||
current.res.headers.forEach((v, k) => {
|
||||
res.headers.set(k, v);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return current.res;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
import { dir } from "dir";
|
||||
import { inspectTreeAsync } from "fs-jetpack";
|
||||
import { InspectTreeResult } from "fs-jetpack/types";
|
||||
import { join } from "path";
|
||||
import mime from "mime";
|
||||
|
||||
const webPath = "app/static";
|
||||
const cache = {
|
||||
static: {} as Record<string, { type: string; content: any }>,
|
||||
};
|
||||
|
||||
export const serveStatic = {
|
||||
init: async () => {
|
||||
const list = await inspectTreeAsync(dir.path(`${webPath}`));
|
||||
const walk = async (
|
||||
list: InspectTreeResult,
|
||||
parent?: InspectTreeResult[]
|
||||
) => {
|
||||
for (const item of list.children) {
|
||||
if (item.type === "file") {
|
||||
const path = join(
|
||||
...(parent || [{ name: "static" }]).map((e) => e.name),
|
||||
item.name
|
||||
);
|
||||
const file = await Bun.file(dir.path(`app/${path}`));
|
||||
if (await file.exists()) {
|
||||
cache.static[path.substring("static".length)] = {
|
||||
type: mime.getType(path) || "application/octet-stream",
|
||||
content: await file.arrayBuffer(),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
await walk(item, parent ? [...parent, list] : [list]);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (list) {
|
||||
await walk(list);
|
||||
}
|
||||
},
|
||||
exists: (url: URL) => {
|
||||
return !!cache.static[url.pathname];
|
||||
},
|
||||
serve: (url: URL) => {
|
||||
const file = cache.static[url.pathname];
|
||||
if (file) {
|
||||
return new Response(file.content, {
|
||||
headers: { "content-type": file.type },
|
||||
});
|
||||
}
|
||||
|
||||
const index = cache.static["/index.html"];
|
||||
if (index) {
|
||||
return new Response(index.content, {
|
||||
headers: { "content-type": index.type },
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { WebSocketHandler } from "bun";
|
||||
import { WSData } from "./create";
|
||||
|
||||
export const serveWS: () => Promise<WebSocketHandler<WSData>> = async () => {
|
||||
const { wsHandler } = await import("../../../app/srv/ws/handler");
|
||||
|
||||
return {
|
||||
maxPayloadLength: 9999999,
|
||||
closeOnBackpressureLimit: true,
|
||||
drain(ws) {
|
||||
// console.log("Backpressure relieved...");
|
||||
},
|
||||
close(ws, code, reason) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const close = wsHandler[pathname].close;
|
||||
if (close) {
|
||||
close(ws, code, reason);
|
||||
}
|
||||
}
|
||||
},
|
||||
message(ws, message) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const msg = wsHandler[pathname].message;
|
||||
if (msg) {
|
||||
msg(ws, message);
|
||||
}
|
||||
}
|
||||
},
|
||||
open(ws) {
|
||||
const pathname = ws.data.url.pathname;
|
||||
if (wsHandler[pathname]) {
|
||||
const open = wsHandler[pathname].open;
|
||||
if (open) {
|
||||
open(ws);
|
||||
}
|
||||
}
|
||||
},
|
||||
} as WebSocketHandler<WSData>;
|
||||
};
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
"./node_modules/.prisma/client/index.d.ts"
|
||||
],
|
||||
"service-srv": [
|
||||
"./pkgs/core/server/api-ctx.ts"
|
||||
"./pkgs/core/server/api/api-ctx.ts"
|
||||
],
|
||||
"utils/*": [
|
||||
"./pkgs/core/utils/*"
|
||||
|
|
|
|||
Loading…
Reference in New Issue