This commit is contained in:
Rizky 2023-10-19 07:06:29 +00:00
parent b1682f5ab9
commit 86c8f16aee
26 changed files with 398 additions and 177 deletions

View File

@ -1,4 +1,3 @@
import { compress } from "lz-string";
import { syncronize } from "y-pojo"; import { syncronize } from "y-pojo";
import * as Y from "yjs"; import * as Y from "yjs";
import { MPage } from "../../web/src/utils/types/general"; import { MPage } from "../../web/src/utils/types/general";
@ -18,9 +17,7 @@ export const _ = {
syncronize(root as any, rawPage); syncronize(root as any, rawPage);
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true }); const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true });
const broadcast = () => { const broadcast = () => {
const sv_local = compress( const sv_local = Y.encodeStateVector(ydoc as any).toString();
Y.encodeStateVector(ydoc as any).toString()
);
const broadcast: WS_MSG_SV_LOCAL = { const broadcast: WS_MSG_SV_LOCAL = {
type: "sv_local", type: "sv_local",
sv_local, sv_local,
@ -40,7 +37,7 @@ export const _ = {
eg.edit.page[page_id].ws.forEach((w) => { eg.edit.page[page_id].ws.forEach((w) => {
const sent: WS_MSG_SET_PAGE = { const sent: WS_MSG_SET_PAGE = {
type: "set_page", type: "set_page",
changes: compress(Y.encodeStateAsUpdate(ydoc as any).toString()), changes: Y.encodeStateAsUpdate(ydoc as any).toString(),
}; };
w.send(JSON.stringify(sent)); w.send(JSON.stringify(sent));
}); });

View File

@ -13,7 +13,7 @@ export const _ = {
const { req, res } = apiContext(this); const { req, res } = apiContext(this);
if (!cache.md5) { if (!cache.md5) {
const content = await readAsync(dir.path("srv/site.zip"), "buffer"); const content = await readAsync(dir.path("app/srv/site.zip"), "buffer");
if (content) { if (content) {
cache.md5 = createHash("md5").update(content).digest("hex"); cache.md5 = createHash("md5").update(content).digest("hex");

View File

@ -24,36 +24,36 @@ export const _ = {
} }
} }
const site = await db.site.findFirst({ // const site = await db.site.findFirst({
where: { id: site_id }, // where: { id: site_id },
select: { js: true }, // select: { js: true },
}); // });
if (site && site.js) { // if (site && site.js) {
const options = { // const options = {
emitDeclarationOnly: true, // emitDeclarationOnly: true,
declaration: true, // declaration: true,
}; // };
let dtsrc = ""; // let dtsrc = "";
const host = ts.createCompilerHost(options); // const host = ts.createCompilerHost(options);
host.writeFile = (fileName, contents) => (dtsrc = contents); // host.writeFile = (fileName, contents) => (dtsrc = contents);
host.readFile = () => // host.readFile = () =>
(site.js || "") + "\n\nexport const ______: string;"; // (site.js || "") + "\n\nexport const ______: string;";
const program = ts.createProgram(["sitedts"], options, host); // const program = ts.createProgram(["sitedts"], options, host);
program.emit(); // program.emit();
const etag = createHash("md5").update(dtsrc).digest("hex"); // const etag = createHash("md5").update(dtsrc).digest("hex");
if (!sent) res.setHeader("etag", etag); // if (!sent) res.setHeader("etag", etag);
dts[site_id] = { etag, dts: dtsrc }; // dts[site_id] = { etag, dts: dtsrc };
if (sent) { // if (sent) {
return ""; // return "";
} // }
return dtsrc; // return dtsrc;
} // }
res.setHeader("etag", "empty"); res.setHeader("etag", "empty");
return ""; return "";

View File

@ -7,9 +7,7 @@
"@node-rs/argon2": "^1.5.2", "@node-rs/argon2": "^1.5.2",
"@paralleldrive/cuid2": "^2.2.2", "@paralleldrive/cuid2": "^2.2.2",
"@types/mime-types": "^2.1.2", "@types/mime-types": "^2.1.2",
"brotli-wasm": "^2.0.1",
"esbuild": "^0.19.4", "esbuild": "^0.19.4",
"lz-string": "^1.5.0",
"mime-types": "^2.1.35", "mime-types": "^2.1.35",
"radix3": "^1.1.0" "radix3": "^1.1.0"
} }

BIN
app/srv/site.zip Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
app/srv/site/site.js Normal file
View File

@ -0,0 +1,2 @@
import{a as E,b as r,c as L,d as h,g as d,j as u,k as y,l as m,m as i}from"./chunk-DH54TKQS.js";var g=E(c=>{"use strict";var f=h();c.createRoot=f.createRoot,c.hydrateRoot=f.hydrateRoot;var b});var w=r(L()),R=r(g());var C=`/_web/${window.id_site}`,a={site:null,pages:[],api:null},_={async site(n,e){let t=await p("/site?prod=1");return a.site=t.site,a.pages=t.pages,a.api=t.api,i.serverurl=t.site.config.api_url,i.apiurl=t.site.config.api_url,i.prasiApi={[t.site.config.api_url]:{apiEntry:t.api}},t.site},async comp(n,e){let t=await p(`/comp/${e}`);return n.comps.all[e]=t,t},npm(n,e,t){return e==="site"?`/_web/${a.site.id}/npm-site/site.js`:`/_web/${a.site.id}/npm-page/${t}/page.js`},async page(n,e){let t=a.pages.find(o=>o.id===e);return t&&!t.content_tree?await p(`/page/${e}`):null},async pages(n,e){return a.pages}},p=async n=>{let t=await(await fetch(`${C}${n}`)).text();return JSON.parse(t)};var s=r(u()),l=window;l.prasiContext={global:{},render(){}};var x=({url:n,Live:e})=>{let[t,o]=(0,w.useState)({});l.prasiContext.render=()=>{o({})};let v=d.Provider;return(0,s.jsx)(v,{value:l.prasiContext,children:(0,s.jsx)(e,{domain:n.host,pathname:location.pathname,loader:_})})};(async()=>{let n=document.getElementById("root");if(n){let e=(0,R.createRoot)(n),t=new URL(location.href);await m(!1),y();let{Live:o}=await import("./live-4QMOJQZB.js");e.render((0,s.jsx)(x,{url:t,Live:o})),document.body.classList.contains("opacity-0")&&document.body.classList.remove("opacity-0")}})();
//# sourceMappingURL=site.js.map

View File

@ -1,17 +1,13 @@
import { Websocket } from "hyper-express";
import { decompress } from "lz-string";
import * as Y from "yjs"; import * as Y from "yjs";
import { eg } from "../edit-global"; import { eg } from "../edit-global";
export const diffLocal = (ws: Websocket, msg: any) => { export const diffLocal = (ws: any, msg: any) => {
return new Promise<void>((resolve) => { return new Promise<void>((resolve) => {
const diff_local = Uint8Array.from( const diff_local = Uint8Array.from(
decompress(msg.diff_local) msg.diff_local.split(",").map((x: any) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
let doc = null as unknown as Y.Doc; let doc = null as unknown as Y.Doc;
let wss: Set<Websocket> = null as any; let wss: Set<any> = null as any;
let um: Y.UndoManager = null as any; let um: Y.UndoManager = null as any;
if (msg.mode === "page") { if (msg.mode === "page") {
doc = eg.edit.page[msg.id].doc as any; doc = eg.edit.page[msg.id].doc as any;

View File

@ -1,15 +1,14 @@
import { ServerWebSocket } from "bun"; import { ServerWebSocket } from "bun";
import { compress } from "lz-string"; import { validate } from "uuid";
import { syncronize } from "y-pojo"; import { syncronize } from "y-pojo";
import * as Y from "yjs"; import * as Y from "yjs";
import { WSData } from "../../../../../pkgs/core/server/create"; import { WSData } from "../../../../../pkgs/core/server/create";
import { SingleComp, eg } from "../edit-global";
import { import {
WS_MSG_GET_COMP, WS_MSG_GET_COMP,
WS_MSG_SET_COMP, WS_MSG_SET_COMP,
WS_MSG_SV_LOCAL, WS_MSG_SV_LOCAL,
} from "../../../../web/src/utils/types/ws"; } from "../../../../web/src/utils/types/ws";
import { validate } from "uuid"; import { SingleComp, eg } from "../edit-global";
export const getComp = async ( export const getComp = async (
ws: ServerWebSocket<WSData>, ws: ServerWebSocket<WSData>,
msg: WS_MSG_GET_COMP msg: WS_MSG_GET_COMP
@ -52,7 +51,7 @@ export const getComp = async (
const ws = new Set<ServerWebSocket<WSData>>(); const ws = new Set<ServerWebSocket<WSData>>();
const um = new Y.UndoManager(map, { ignoreRemoteMapChanges: true }); const um = new Y.UndoManager(map, { ignoreRemoteMapChanges: true });
const broadcast = () => { const broadcast = () => {
const sv_local = compress(Y.encodeStateVector(ydoc as any).toString()); const sv_local = Y.encodeStateVector(ydoc as any).toString();
const broadcast: WS_MSG_SV_LOCAL = { const broadcast: WS_MSG_SV_LOCAL = {
type: "sv_local", type: "sv_local",
sv_local, sv_local,
@ -79,7 +78,7 @@ export const getComp = async (
const sent: WS_MSG_SET_COMP = { const sent: WS_MSG_SET_COMP = {
type: "set_comp", type: "set_comp",
comp_id: comp_id, comp_id: comp_id,
changes: compress(Y.encodeStateAsUpdate(comp.doc as any).toString()), changes: Y.encodeStateAsUpdate(comp.doc as any).toString(),
}; };
ws.send(JSON.stringify(sent)); ws.send(JSON.stringify(sent));
} }

View File

@ -1,5 +1,4 @@
import { ServerWebSocket } from "bun"; import { ServerWebSocket } from "bun";
import { compress } from "lz-string";
import { validate } from "uuid"; import { validate } from "uuid";
import { syncronize } from "y-pojo"; import { syncronize } from "y-pojo";
import * as Y from "yjs"; import * as Y from "yjs";
@ -29,7 +28,7 @@ export const getPage = async (
const ws = new Set<ServerWebSocket<WSData>>(); const ws = new Set<ServerWebSocket<WSData>>();
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true }); const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true });
const broadcast = () => { const broadcast = () => {
const sv_local = compress(Y.encodeStateVector(ydoc as any).toString()); const sv_local = Y.encodeStateVector(ydoc as any).toString();
const broadcast: WS_MSG_SV_LOCAL = { const broadcast: WS_MSG_SV_LOCAL = {
type: "sv_local", type: "sv_local",
sv_local, sv_local,
@ -55,7 +54,7 @@ export const getPage = async (
page.ws.add(ws); page.ws.add(ws);
const sent: WS_MSG_SET_PAGE = { const sent: WS_MSG_SET_PAGE = {
type: "set_page", type: "set_page",
changes: compress(Y.encodeStateAsUpdate(page.doc as any).toString()), changes: Y.encodeStateAsUpdate(page.doc as any).toString(),
}; };
ws.send(JSON.stringify(sent)); ws.send(JSON.stringify(sent));
}; };

View File

@ -1,19 +1,15 @@
import { Websocket } from "hyper-express";
import { compress, decompress } from "lz-string";
import * as Y from "yjs"; import * as Y from "yjs";
import { import {
WS_MSG_SVDIFF_REMOTE, WS_MSG_SVDIFF_REMOTE,
WS_MSG_SV_LOCAL, WS_MSG_SV_LOCAL,
} from "../../../web/src/utils/types/ws"; } from "../../../../web/src/utils/types/ws";
import { eg } from "../edit-global"; import { eg } from "../edit-global";
import { getComp } from "./get-comp"; import { getComp } from "./get-comp";
import { getPage } from "./get-page"; import { getPage } from "./get-page";
export const svLocal = async (ws: Websocket, msg: WS_MSG_SV_LOCAL) => { export const svLocal = async (ws: any, msg: WS_MSG_SV_LOCAL) => {
const changes = Uint8Array.from( const changes = Uint8Array.from(
decompress(msg.sv_local) (msg.sv_local || '').split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
let doc = null as any; let doc = null as any;
if (msg.mode === "page") { if (msg.mode === "page") {
@ -37,8 +33,8 @@ export const svLocal = async (ws: Websocket, msg: WS_MSG_SV_LOCAL) => {
const sv_remote = Y.encodeStateVector(doc); const sv_remote = Y.encodeStateVector(doc);
const sendmsg: WS_MSG_SVDIFF_REMOTE = { const sendmsg: WS_MSG_SVDIFF_REMOTE = {
diff_remote: compress(diff_remote.toString()), diff_remote: diff_remote.toString(),
sv_remote: compress(sv_remote.toString()), sv_remote: sv_remote.toString(),
id: msg.id, id: msg.id,
mode: msg.mode, mode: msg.mode,
type: "svd_remote", type: "svd_remote",

View File

@ -1,25 +1,16 @@
import { Websocket } from "hyper-express";
import { compress, decompress } from "lz-string";
import * as Y from "yjs"; import * as Y from "yjs";
import { import {
WS_MSG_DIFF_LOCAL, WS_MSG_DIFF_LOCAL,
WS_MSG_SVDIFF_REMOTE, WS_MSG_SVDIFF_REMOTE,
} from "../../../web/src/utils/types/ws"; } from "../../../../web/src/utils/types/ws";
import { eg } from "../edit-global"; import { eg } from "../edit-global";
export const svdiffRemote = async ( export const svdiffRemote = async (ws: any, msg: WS_MSG_SVDIFF_REMOTE) => {
ws: Websocket,
msg: WS_MSG_SVDIFF_REMOTE
) => {
const sv_remote = Uint8Array.from( const sv_remote = Uint8Array.from(
decompress(msg.sv_remote) msg.sv_remote.split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
const diff_remote = Uint8Array.from( const diff_remote = Uint8Array.from(
decompress(msg.diff_remote) msg.diff_remote.split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
let doc = null as any; let doc = null as any;
@ -39,7 +30,7 @@ export const svdiffRemote = async (
type: "diff_local", type: "diff_local",
mode: msg.mode, mode: msg.mode,
id: msg.id, id: msg.id,
diff_local: compress(diff_local.toString()), diff_local: diff_local.toString(),
}; };
ws.send(JSON.stringify(sendmsg)); ws.send(JSON.stringify(sendmsg));
} }

View File

@ -1,7 +1,5 @@
import { createId } from "@paralleldrive/cuid2"; import { createId } from "@paralleldrive/cuid2";
import brotliPromise from "brotli-wasm";
import { WebSocketHandler } from "bun"; import { WebSocketHandler } from "bun";
import { decompress } from "lz-string";
import { WSData } from "../../../pkgs/core/server/create"; import { WSData } from "../../../pkgs/core/server/create";
import { WS_MSG } from "../../web/src/utils/types/ws"; import { WS_MSG } from "../../web/src/utils/types/ws";
import { diffLocal } from "./edit/action/diff-local"; import { diffLocal } from "./edit/action/diff-local";
@ -22,7 +20,6 @@ const site = {
saveTimeout: null as any, saveTimeout: null as any,
}; };
const brotli = await brotliPromise;
export const wsHandler: Record<string, WebSocketHandler<WSData>> = { export const wsHandler: Record<string, WebSocketHandler<WSData>> = {
"/edit": { "/edit": {
open(ws) { open(ws) {
@ -44,7 +41,7 @@ export const wsHandler: Record<string, WebSocketHandler<WSData>> = {
case "site-js": case "site-js":
clearTimeout(site.saveTimeout); clearTimeout(site.saveTimeout);
site.saveTimeout = setTimeout(async () => { site.saveTimeout = setTimeout(async () => {
const js = JSON.parse(decompress(msg.src)); const js = JSON.parse(msg.src);
await db.site.update({ await db.site.update({
where: { where: {
id: msg.id_site, id: msg.id_site,

View File

@ -15,7 +15,6 @@
"@parcel/service-worker": "^2.10.0", "@parcel/service-worker": "^2.10.0",
"@swc/wasm-web": "1.3.94-nightly-20231014.1", "@swc/wasm-web": "1.3.94-nightly-20231014.1",
"algoliasearch": "^4.20.0", "algoliasearch": "^4.20.0",
"brotli-dec-wasm": "^2.0.1",
"date-fns": "^2.30.0", "date-fns": "^2.30.0",
"dbgen": "workspace:*", "dbgen": "workspace:*",
"downshift": "^8.2.2", "downshift": "^8.2.2",
@ -37,7 +36,6 @@
"lodash.trim": "4.5.1", "lodash.trim": "4.5.1",
"lodash.uniq": "^4.5.0", "lodash.uniq": "^4.5.0",
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"lz-string": "1.5.0",
"monaco-jsx-syntax-highlight-v2": "^1.2.2", "monaco-jsx-syntax-highlight-v2": "^1.2.2",
"polywasm": "^0.1.4", "polywasm": "^0.1.4",
"prettier": "3.0.3", "prettier": "3.0.3",

View File

@ -1,7 +1,6 @@
import { PG } from "./global"; import { PG } from "./global";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import { compress, decompress } from "lz-string";
import * as Y from "yjs"; import * as Y from "yjs";
import { CompDoc } from "../../../base/global/content-editor"; import { CompDoc } from "../../../base/global/content-editor";
import { MPage } from "../../../utils/types/general"; import { MPage } from "../../../utils/types/general";
@ -15,7 +14,6 @@ import {
WS_MSG_SV_LOCAL, WS_MSG_SV_LOCAL,
} from "../../../utils/types/ws"; } from "../../../utils/types/ws";
import { scanComponent } from "./comp"; import { scanComponent } from "./comp";
import { execSiteJS } from "./init";
import { rebuildTree } from "./tree-logic"; import { rebuildTree } from "./tree-logic";
const timeout = { const timeout = {
@ -134,9 +132,7 @@ export const editorWS = async (p: PG) => {
type: "sv_local", type: "sv_local",
mode: "page", mode: "page",
id, id,
sv_local: compress( sv_local: Y.encodeStateVector(doc as any).toString(),
Y.encodeStateVector(doc as any).toString()
),
}; };
wsend(p, JSON.stringify(sendmsg)); wsend(p, JSON.stringify(sendmsg));
} }
@ -207,9 +203,9 @@ export const editorWS = async (p: PG) => {
type: "sv_local", type: "sv_local",
mode: "comp", mode: "comp",
id, id,
sv_local: compress( sv_local: Y.encodeStateVector(
Y.encodeStateVector(doc as any).toString() doc as any
), ).toString(),
}; };
wsend(p, JSON.stringify(sendmsg)); wsend(p, JSON.stringify(sendmsg));
} }
@ -259,11 +255,7 @@ export const editorWS = async (p: PG) => {
}; };
const extract = (str: string) => { const extract = (str: string) => {
return Uint8Array.from( return Uint8Array.from(str.split(",").map((x) => parseInt(x, 10)));
decompress(str)
.split(",")
.map((x) => parseInt(x, 10))
);
}; };
const svLocal = async (arg: { const svLocal = async (arg: {
@ -287,8 +279,8 @@ const svLocal = async (arg: {
const sv_remote = Y.encodeStateVector(doc); const sv_remote = Y.encodeStateVector(doc);
const sendmsg: any = { const sendmsg: any = {
diff_remote: compress(diff_remote.toString()), diff_remote: diff_remote.toString(),
sv_remote: compress(sv_remote.toString()), sv_remote: sv_remote.toString(),
id: id, id: id,
mode: mode, mode: mode,
type: type, type: type,
@ -304,14 +296,10 @@ const svdRemote = async (arg: {
const { bin, msg, p } = arg; const { bin, msg, p } = arg;
const { id, mode, type } = msg; const { id, mode, type } = msg;
const sv_remote = Uint8Array.from( const sv_remote = Uint8Array.from(
decompress(msg.sv_remote) msg.sv_remote.split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
const diff_remote = Uint8Array.from( const diff_remote = Uint8Array.from(
decompress(msg.diff_remote) msg.diff_remote.split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
const sendDoc = async (doc: any) => { const sendDoc = async (doc: any) => {
@ -321,7 +309,7 @@ const svdRemote = async (arg: {
type: "diff_local", type: "diff_local",
mode: msg.mode, mode: msg.mode,
id: msg.id, id: msg.id,
diff_local: compress(diff_local.toString()), diff_local: diff_local.toString(),
}; };
await wsend(p, JSON.stringify(sendmsg)); await wsend(p, JSON.stringify(sendmsg));
}; };
@ -354,9 +342,7 @@ export const wsend = async (local: PG, payload: string) => {
const setPage = async (msg: WS_MSG_SET_PAGE) => { const setPage = async (msg: WS_MSG_SET_PAGE) => {
const page = Uint8Array.from( const page = Uint8Array.from(
decompress(msg.changes) msg.changes.split(",").map((x) => parseInt(x, 10))
.split(",")
.map((x) => parseInt(x, 10))
); );
const doc = new Y.Doc(); const doc = new Y.Doc();

View File

@ -1,4 +1,3 @@
import { compress } from "lz-string";
import { useEffect } from "react"; import { useEffect } from "react";
import { useGlobal, useLocal } from "web-utils"; import { useGlobal, useLocal } from "web-utils";
import { w } from "../../../../../utils/types/general"; import { w } from "../../../../../utils/types/general";
@ -85,7 +84,7 @@ export const ToolbarCenter = () => {
JSON.stringify({ JSON.stringify({
type: "site-js", type: "site-js",
id_site: p.site.id, id_site: p.site.id,
src: compress(JSON.stringify({ src, compiled })), src: JSON.stringify({ src, compiled }),
}) })
); );
}} }}

View File

@ -5,7 +5,7 @@ const base = `/_web/${(window as any).id_site}`;
const cache = { site: null as any, pages: [] as any, api: null }; const cache = { site: null as any, pages: [] as any, api: null };
export const SiteLoader: Loader = { export const siteLoader: Loader = {
async site(p, id) { async site(p, id) {
const res = (await load(`/site?prod=1`)) as { const res = (await load(`/site?prod=1`)) as {
site: any; site: any;

BIN
bun.lockb

Binary file not shown.

View File

@ -5,7 +5,6 @@ export const _ = {
url: "/_api_frm", url: "/_api_frm",
async api() { async api() {
const { req, res } = apiContext(this); const { req, res } = apiContext(this);
let allowUrl = req.headers.get("origin") || req.headers.get("referer"); let allowUrl = req.headers.get("origin") || req.headers.get("referer");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT"); res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT");

View File

@ -9,6 +9,7 @@ export const _ = {
try { try {
const result = await execQuery(req.params, db); const result = await execQuery(req.params, db);
res.send(result); res.send(result);
} catch (e: any) { } catch (e: any) {
res.sendStatus(500); res.sendStatus(500);
res.send(e.message); res.send(e.message);

View File

@ -1,52 +1,103 @@
import { spawn } from "bun"; import { spawn } from "bun";
import { dir } from "dir"; import { dir } from "dir";
import { statSync } from "fs"; import { Plugin, context } from "esbuild";
import { listAsync, removeAsync, writeAsync } from "fs-jetpack"; import { $ } from "execa";
import brotliPromise from "brotli-wasm"; import { removeAsync, writeAsync } from "fs-jetpack";
const brotli = await brotliPromise;
await removeAsync(dir.path("app/static")); // await removeAsync(dir.path("app/static"));
await removeAsync(dir.path("app/web/.parcel-cache")); // await removeAsync(dir.path("app/web/.parcel-cache"));
await removeAsync(dir.path("app/static")); // await removeAsync(dir.path("app/static"));
const args = [ // const args = [
"node", // "node",
dir.path("node_modules/.bin/parcel"), // dir.path("node_modules/.bin/parcel"),
"build", // "build",
"./src/index.tsx", // "./src/index.tsx",
// "--no-optimize", // // "--no-optimize",
"--no-scope-hoist", // "--no-scope-hoist",
"--dist-dir", // "--dist-dir",
dir.path(`app/static`), // dir.path(`app/static`),
]; // ];
const parcel = spawn({ // const parcel = spawn({
cmd: args, // cmd: args,
cwd: dir.path("app/web"), // cwd: dir.path("app/web"),
stdio: ["ignore", "inherit", "inherit"], // stdio: ["ignore", "inherit", "inherit"],
}); // });
await parcel.exited; // await parcel.exited;
listAsync(dir.path("app/static")).then(async (files) => { // listAsync(dir.path("app/static")).then(async (files) => {
if (files) { // if (files) {
await removeAsync(dir.path("app/static-br")); // await removeAsync(dir.path("app/static-br"));
await Promise.all( // await Promise.all(
files // files
.filter((e) => statSync(dir.path(`app/static/${e}`)).isFile()) // .filter((e) => statSync(dir.path(`app/static/${e}`)).isFile())
.map(async (file) => { // .map(async (file) => {
const br = brotli.compress( // const br = brotli.compress(
new Uint8Array( // new Uint8Array(
await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer() // await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer()
) // )
); // );
if (br) { // if (br) {
console.log(`Compressing ${file}`); // console.log(`Compressing ${file}`);
// await writeAsync(
// dir.path(`app/static-br/${file}`),
// Buffer.from(br)
// );
// }
// })
// );
// }
// });
const buildSite = async () => {
await removeAsync(dir.path("app/srv/site"));
const onEndPlugin: Plugin = {
name: "on-end",
setup(build) {
build.onEnd(async (result) => {
console.log("Compressing deploy");
await removeAsync(dir.path("app/srv/site.zip"));
await $({ cwd: dir.path("app/srv") })`zip -r site.zip site`;
process.exit(0);
});
},
};
console.log("Building deploy");
const ctx = await context({
bundle: true,
absWorkingDir: dir.path(""),
entryPoints: [dir.path("app/web/src/render/site/site.tsx")],
outdir: dir.path("app/srv/site"),
splitting: true,
format: "esm",
jsx: "transform",
minify: true,
sourcemap: true,
logLevel: "error",
plugins: [onEndPlugin],
define: {
"process.env.NODE_ENV": `"production"`,
},
});
await ctx.rebuild();
await writeAsync( await writeAsync(
dir.path(`app/static-br/${file}`), dir.path("app/srv/site/index.html"),
Buffer.from(br) `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<link rel="stylesheet" href="https://prasi.app/index.css">
</head>
<body class="flex-col flex-1 w-full min-h-screen flex opacity-0">
<div id="root"></div>
<script src="/site.js" type="module"></script>
</body>
</html>`
); );
} };
}) await buildSite();
);
}
});

View File

@ -6,7 +6,7 @@
"@swc/core": "^1.3.91", "@swc/core": "^1.3.91",
"@types/mime": "^3.0.2", "@types/mime": "^3.0.2",
"@types/unzipper": "^0.10.7", "@types/unzipper": "^0.10.7",
"brotli-wasm": "^2.0.1", "esbuild": "^0.19.5",
"execa": "^8.0.1", "execa": "^8.0.1",
"fs-jetpack": "^5.1.0", "fs-jetpack": "^5.1.0",
"lmdb": "^2.8.5", "lmdb": "^2.8.5",

View File

@ -11,8 +11,7 @@ export const cache = {
string, string,
{ {
type: string; type: string;
content: ReadableStream<Uint8Array>; content: ArrayBuffer;
br?: ReadableStream<Uint8Array>;
} }
>, >,
}; };
@ -30,6 +29,7 @@ export const createServer = async () => {
port: g.port, port: g.port,
websocket: { websocket: {
maxPayloadLength: 9999999, maxPayloadLength: 9999999,
closeOnBackpressureLimit: true,
close(ws, code, reason) { close(ws, code, reason) {
const pathname = ws.data.url.pathname; const pathname = ws.data.url.pathname;
if (wsHandler[pathname]) { if (wsHandler[pathname]) {
@ -99,7 +99,7 @@ export const createServer = async () => {
if (!cache.static[url.pathname]) { if (!cache.static[url.pathname]) {
cache.static[url.pathname] = { cache.static[url.pathname] = {
type: lookup(url.pathname) || "text/plain", type: lookup(url.pathname) || "text/plain",
content: file.stream(), content: await file.arrayBuffer(),
}; };
} }
const found = cache.static[url.pathname]; const found = cache.static[url.pathname];
@ -115,6 +115,7 @@ export const createServer = async () => {
return new Response(Bun.file(dir.path(`${webPath}/index.html`)) as any); return new Response(Bun.file(dir.path(`${webPath}/index.html`)) as any);
} catch (e) { } catch (e) {
g.log.error(e); g.log.error(e);
return new Response("Loading..."); return new Response("Loading...");
} }
}, },

View File

@ -19,6 +19,16 @@ export const ${name} = {
await Bun.write(dir.path(`app/srv/exports.ts`), out.join(`\n`)); await Bun.write(dir.path(`app/srv/exports.ts`), out.join(`\n`));
const targetFile = dir.path("app/srv/exports.d.ts"); const targetFile = dir.path("app/srv/exports.d.ts");
const args = [
dir.path("node_modules/.bin/tsc"),
dir.path("app/srv/exports.ts"),
"--declaration",
"--emitDeclarationOnly",
"--outFile",
targetFile,
];
if (g.mode === "dev") {
const tsc = spawn( const tsc = spawn(
[ [
dir.path("node_modules/.bin/tsc"), dir.path("node_modules/.bin/tsc"),
@ -32,8 +42,8 @@ export const ${name} = {
cwd: dir.path(`node_modules/.bin`), cwd: dir.path(`node_modules/.bin`),
} }
); );
await tsc.exited; await tsc.exited;
}
let res = await readAsync(targetFile); let res = await readAsync(targetFile);
if (res) { if (res) {

View File

@ -1,13 +1,8 @@
import { spawn } from "bun"; import { spawn } from "bun";
import { dirAsync, inspectTreeAsync, writeAsync } from "fs-jetpack"; import { dirAsync } from "fs-jetpack";
import { InspectTreeResult } from "fs-jetpack/types";
import { cache } from "../server/create";
import { dir } from "./dir"; import { dir } from "./dir";
import { g } from "./global"; import { g } from "./global";
import { lookup } from "mime-types";
import brotliPromise from "brotli-wasm";
const brotli = await brotliPromise;
const decoder = new TextDecoder(); const decoder = new TextDecoder();
export const parcelBuild = async () => { export const parcelBuild = async () => {