diff --git a/app/web/.gitignore b/app/web/.gitignore
index dfcdde16..0ca55df2 100644
--- a/app/web/.gitignore
+++ b/app/web/.gitignore
@@ -179,3 +179,5 @@ app/web/.parcel-cache
app/static
.data
.data/*
+
+timestamp.ts
\ No newline at end of file
diff --git a/app/web/src/index.tsx b/app/web/src/index.tsx
index 73d3e288..571e6cc2 100644
--- a/app/web/src/index.tsx
+++ b/app/web/src/index.tsx
@@ -10,36 +10,36 @@ import { sworkerAddCache, sworkerRegister } from "./sworker-boot";
import { w } from "./utils/types/general";
const start = async () => {
- const base = `${location.protocol}//${location.host}`;
- let react = {
- root: null as null | ReactRoot,
- };
- w.mobile = registerMobile();
+ const base = `${location.protocol}//${location.host}`;
+ let react = {
+ root: null as null | ReactRoot,
+ };
+ w.mobile = registerMobile();
- const cur = new URL(location.href);
- const base_url = `${cur.protocol}//${cur.host}`;
- w.db = dbProxy(base_url);
+ const cur = new URL(location.href);
+ const base_url = `${cur.protocol}//${cur.host}`;
+ w.db = dbProxy(base_url);
- try {
- await loadApiProxyDef(base_url, false);
- w.api = apiProxy(base_url);
- } catch (e) {
- console.warn("Failed to load API:", base_url);
- }
+ try {
+ await loadApiProxyDef(base_url, false);
+ w.api = apiProxy(base_url);
+ } catch (e) {
+ console.warn("Failed to load API:", base_url);
+ }
- w.serverurl = base;
+ w.serverurl = base;
- sworkerRegister(react);
- defineReact();
- await defineWindow(false);
- sworkerAddCache(base);
+ sworkerRegister(react);
+ defineReact();
+ await defineWindow(false);
+ sworkerAddCache(base);
- const el = document.getElementById("root");
+ const el = document.getElementById("root");
- if (el) {
- react.root = createRoot(el);
- react.root.render();
- }
+ if (el) {
+ react.root = createRoot(el);
+ react.root.render();
+ }
};
start();
diff --git a/app/web/src/sworker-boot.tsx b/app/web/src/sworker-boot.tsx
index f35c5eec..6d0d28dc 100644
--- a/app/web/src/sworker-boot.tsx
+++ b/app/web/src/sworker-boot.tsx
@@ -2,176 +2,235 @@ 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";
+import { version } from "../timestamp";
+
+const state = {
+ updating: false,
+};
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();
- };
- setTimeout(click, 5000);
- react.root.render(
- <>
-
-
- >
- );
- }
+ 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();
- if (e.data.type === "activated") {
- if (e.data.shouldRefresh && sw) {
- react.root.render(
- <>
-
-
- >
- );
-
- 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();
- };
- setTimeout(click, 5000);
- react.root.render(
- <>
-
-
+
+
{
+ swc.postMessage({
+ type: "force-update",
+ });
+ if (react.root)
+ react.root.render(
+ <>
+
+
-
- Prasi Updated{" "}
- {e.data.version}
-
-
- >
- );
- }
- }
- }
- }
- });
- } else {
- navigator.serviceWorker.getRegistrations().then(function (registrations) {
- for (let registration of registrations) {
- registration.unregister();
- }
- });
- }
- }
+ "flex justify-center",
+ )}
+ >
+
+ Updating App...
+
+
+ >,
+ );
+ }}
+ >
+
+ New Version Available. Click to Update
+
+
+ >,
+ );
+ }
+
+ 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();
+ };
+ setTimeout(click, 5000);
+ react.root.render(
+ <>
+
+
+ >,
+ );
+ }
+
+ if (e.data.type === "activated") {
+ if (e.data.shouldRefresh && sw) {
+ react.root.render(
+ <>
+
+
+ >,
+ );
+
+ 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();
+ };
+ setTimeout(click, 5000);
+ react.root.render(
+ <>
+
+
+
+ Prasi Updated{" "}
+ {e.data.version}
+
+
+ >,
+ );
+ }
+ }
+ }
+ }
+ });
+ } 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}`);
- }
- }
+ 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,
- })
- );
+ 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,
- });
- }
- }
- }
- }
+ swc.postMessage({
+ type: "define-route",
+ routes,
+ });
+ }
+ }
+ }
+ }
};
diff --git a/app/web/src/sworker.ts b/app/web/src/sworker.ts
index 20caffdb..79725b95 100644
--- a/app/web/src/sworker.ts
+++ b/app/web/src/sworker.ts
@@ -1,95 +1,110 @@
-import { manifest, version } from "@parcel/service-worker";
+import { manifest } from "@parcel/service-worker";
import { RadixRouter, createRouter } from "radix3";
+import { version } from "../timestamp";
+
const g = {
- router: null as null | RadixRouter,
- offline: false,
- broadcast(msg: any) {
- // @ts-ignore
- const c: Clients = self.clients;
- c.matchAll({ includeUncontrolled: true }).then((clients) => {
- clients.forEach((client) => {
- client.postMessage(msg);
- });
- });
- },
+ router: null as null | RadixRouter,
+ offline: false,
+ broadcast(msg: any) {
+ // @ts-ignore
+ const c: Clients = self.clients;
+ c.matchAll({ includeUncontrolled: true }).then((clients) => {
+ clients.forEach((client) => {
+ client.postMessage(msg);
+ });
+ });
+ },
};
async function install() {
- const cache = await caches.open(version);
- await cache.addAll(manifest);
- g.broadcast({ type: "installed" });
+ const cache = await caches.open(version);
+ await cache.addAll(manifest);
+ g.broadcast({ type: "installed" });
}
addEventListener("install", (e) => (e as ExtendableEvent).waitUntil(install()));
async function activate() {
- let shouldRefresh = false;
- if (!g.offline) {
- const keys = await caches.keys();
- await Promise.all(
- keys.map(async (key) => {
- if (key !== version) {
- await caches.delete(key);
- shouldRefresh = true;
- }
- })
- );
+ let shouldRefresh = false;
+ if (!g.offline) {
+ const keys = await caches.keys();
+ await Promise.all(
+ keys.map(async (key) => {
+ if (key !== version) {
+ await caches.delete(key);
+ shouldRefresh = true;
+ }
+ }),
+ );
- g.broadcast({ type: "activated", shouldRefresh, version });
- }
+ g.broadcast({ type: "activated", shouldRefresh, version });
+ }
}
addEventListener("activate", (e) =>
- (e as ExtendableEvent).waitUntil(activate())
+ (e as ExtendableEvent).waitUntil(activate()),
);
addEventListener("fetch", async (evt) => {
- const e = evt as FetchEvent;
+ const e = evt as FetchEvent;
- const url = new URL(e.request.url);
+ const url = new URL(e.request.url);
- if (g.router) {
- const found = g.router.lookup(url.pathname);
- if (found) {
- return;
- }
- }
+ if (g.router) {
+ const found = g.router.lookup(url.pathname);
+ if (found) {
+ return;
+ }
+ }
- e.respondWith(
- (async () => {
- const r = await caches.match(e.request);
- if (r) {
- return r;
- }
+ e.respondWith(
+ (async () => {
+ const r = await caches.match(e.request);
+ if (r) {
+ return r;
+ }
- try {
- g.offline = false;
- return await fetch(e.request);
- } catch (e) {
- g.offline = true;
- g.broadcast({ type: "offline" });
- return new Response();
- }
- })()
- );
+ try {
+ g.offline = false;
+ return await fetch(e.request);
+ } catch (e) {
+ g.offline = true;
+ g.broadcast({ type: "offline" });
+ return new Response();
+ }
+ })(),
+ );
});
addEventListener("message", async (e) => {
- const type = e.data.type;
- const cache = await caches.open(version);
+ const type = e.data.type;
+ const cache = await caches.open(version);
- switch (type) {
- case "add-cache":
- {
- const cached = await cache.match(e.data.url);
- if (!cached) {
- await cache.add(e.data.url);
- }
- }
- break;
- case "define-route":
- g.router = createRouter({ strictTrailingSlash: false });
- for (const route of e.data.routes) {
- g.router.insert(route.url, route);
- }
- await activate();
- break;
- }
+ switch (type) {
+ case "add-cache":
+ {
+ const cached = await cache.match(e.data.url);
+ if (!cached) {
+ await cache.add(e.data.url);
+ }
+ }
+ break;
+ case "define-route":
+ g.router = createRouter({ strictTrailingSlash: false });
+ for (const route of e.data.routes) {
+ g.router.insert(route.url, route);
+ }
+ await activate();
+ break;
+ case "force-update":
+ {
+ const keys = await caches.keys();
+ await Promise.all(
+ keys.map(async (key) => {
+ if (key !== version) {
+ await caches.delete(key);
+ }
+ }),
+ );
+ await install();
+ }
+ break;
+ }
});
diff --git a/app/web/src/utils/ui/is-localhost.ts b/app/web/src/utils/ui/is-localhost.ts
index 46d30717..b7e20d21 100644
--- a/app/web/src/utils/ui/is-localhost.ts
+++ b/app/web/src/utils/ui/is-localhost.ts
@@ -3,7 +3,7 @@ export const isLocalhost = () => {
"localhost",
"127.0.0.1",
"192.168",
- "trycloudflare.com",
+ // "trycloudflare.com",
"ngrok",
].find((e) => location.hostname.includes(e));
};
diff --git a/pkgs/core/build.ts b/pkgs/core/build.ts
index 352cca6e..b92cc87e 100644
--- a/pkgs/core/build.ts
+++ b/pkgs/core/build.ts
@@ -1,103 +1,101 @@
+import { createId } from "@paralleldrive/cuid2";
import brotliPromise from "brotli-wasm";
import { spawn } from "bun";
import { dir } from "dir";
import { fdir } from "fdir";
-import { statSync } from "fs";
-import {
- copyAsync,
- existsAsync,
- listAsync,
- removeAsync,
- writeAsync,
-} from "fs-jetpack";
+import { existsAsync, listAsync, removeAsync, writeAsync } from "fs-jetpack";
const brotli = await brotliPromise;
await removeAsync(dir.path("app/web/.parcel-cache"));
await removeAsync(dir.path("app/static"));
+await writeAsync(
+ dir.path("app/web/timestamp.ts"),
+ `export const version = "${createId().substring(0, 7)}";`,
+);
+
const args = [
- "node",
- dir.path("node_modules/.bin/parcel"),
- "build",
- "./src/index.tsx",
- // "--no-optimize",
- "--no-scope-hoist",
- "--dist-dir",
- dir.path(`app/static`),
+ "node",
+ dir.path("node_modules/.bin/parcel"),
+ "build",
+ "./src/index.tsx",
+ // "--no-optimize",
+ "--no-scope-hoist",
+ "--dist-dir",
+ dir.path(`app/static`),
];
const parcel = spawn({
- cmd: args,
- cwd: dir.path("app/web"),
- stdio: ["ignore", "inherit", "inherit"],
+ cmd: args,
+ cwd: dir.path("app/web"),
+ stdio: ["ignore", "inherit", "inherit"],
});
await parcel.exited;
const public_br = dir.path("app/web/public-br");
if (!(await existsAsync(public_br))) {
- const api = new fdir().withRelativePaths().crawl(dir.path("app/web/public"));
- const files = api.sync();
- if (files) {
- await Promise.all(
- files.map(async (file) => {
- const br = brotli.compress(
- new Uint8Array(
- await Bun.file(dir.path(`app/web/public/${file}`)).arrayBuffer()
- ),
- { quality: 11 }
- );
- if (br) {
- console.log(`Compressing [public] ${file}`);
- await writeAsync(
- dir.path(`app/web/public-br/${file}`),
- Buffer.from(br)
- );
- }
- })
- );
- }
+ const api = new fdir().withRelativePaths().crawl(dir.path("app/web/public"));
+ const files = api.sync();
+ if (files) {
+ await Promise.all(
+ files.map(async (file) => {
+ const br = brotli.compress(
+ new Uint8Array(
+ await Bun.file(dir.path(`app/web/public/${file}`)).arrayBuffer(),
+ ),
+ { quality: 11 },
+ );
+ if (br) {
+ console.log(`Compressing [public] ${file}`);
+ await writeAsync(
+ dir.path(`app/web/public-br/${file}`),
+ Buffer.from(br),
+ );
+ }
+ }),
+ );
+ }
}
const static_br = dir.path("app/static-br");
await removeAsync(static_br);
const files = await listAsync(dir.path("app/static"));
if (files) {
- await Promise.all(
- files
- .filter((file) => statSync(dir.path(`app/static/${file}`)).isFile())
- .map(async (file) => {
- if (!(await Bun.file(dir.path(`app/static-br/${file}`)).exists())) {
- const br = brotli.compress(
- new Uint8Array(
- await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer()
- ),
- { quality: 11 }
- );
- if (br) {
- console.log(`Compressing [static] ${file}`);
- await writeAsync(
- dir.path(`app/static-br/${file}`),
- Buffer.from(br)
- );
- }
- }
- })
- );
-
- const pub = await listAsync(dir.path("app/web/public-br"));
- if (pub) {
- await Promise.all(
- pub.map(async (file) => {
- if (await existsAsync(`app/static-br/${file}`)) {
- await removeAsync(`app/static-br/${file}`);
- }
- await copyAsync(
- dir.path(`app/web/public-br/${file}`),
- dir.path(`app/static-br/${file}`)
- );
- })
- );
- }
+ // await Promise.all(
+ // files
+ // .filter((file) => statSync(dir.path(`app/static/${file}`)).isFile())
+ // .map(async (file) => {
+ // if (!(await Bun.file(dir.path(`app/static-br/${file}`)).exists())) {
+ // const br = brotli.compress(
+ // new Uint8Array(
+ // await Bun.file(dir.path(`app/static/${file}`)).arrayBuffer(),
+ // ),
+ // { quality: 11 },
+ // );
+ // if (br) {
+ // console.log(`Compressing [static] ${file}`);
+ // await writeAsync(
+ // dir.path(`app/static-br/${file}`),
+ // Buffer.from(br),
+ // );
+ // }
+ // }
+ // }),
+ // );
+ // const pub = await listAsync(dir.path("app/web/public-br"));
+ // if (pub) {
+ // await Promise.all(
+ // pub.map(async (file) => {
+ // if (await existsAsync(`app/static-br/${file}`)) {
+ // await removeAsync(`app/static-br/${file}`);
+ // }
+ // await copyAsync(
+ // dir.path(`app/web/public-br/${file}`),
+ // dir.path(`app/static-br/${file}`),
+ // );
+ // }),
+ // );
+ // }
}
await import("./build-site");
diff --git a/pkgs/core/index.ts b/pkgs/core/index.ts
index 9f24f5d8..045e8784 100644
--- a/pkgs/core/index.ts
+++ b/pkgs/core/index.ts
@@ -9,58 +9,66 @@ import { syncActionDefinition } from "utils/sync-def";
import { user } from "../../app/srv/ws/sync/entity/user";
import { snapshot } from "../../app/srv/ws/sync/entity/snapshot";
import { initSrv } from "../../app/srv/init";
+import { createId } from "@paralleldrive/cuid2";
import { prepareApiRoutes } from "./server/api/api-scan";
+import { writeAsync } from "fs-jetpack";
+import { dir } from "dir";
g.status = "init";
+await writeAsync(
+ dir.path("app/web/timestamp.ts"),
+ `export const version = "${createId().substring(0, 7)}";`,
+);
+
if (!g.Y) {
- g.Y = await import("yjs");
- g.syncronize = (await import("y-pojo")).syncronize;
+ g.Y = await import("yjs");
+ g.syncronize = (await import("y-pojo")).syncronize;
- await createLogger();
- g.api = {};
- g.mode = process.argv.includes("dev") ? "dev" : "prod";
- g.datadir = g.mode == "prod" ? "../data" : "data";
- g.port = parseInt(process.env.PORT || "4550");
+ await createLogger();
+ g.api = {};
+ g.mode = process.argv.includes("dev") ? "dev" : "prod";
+ g.datadir = g.mode == "prod" ? "../data" : "data";
+ g.port = parseInt(process.env.PORT || "4550");
- g.log.info(g.mode === "dev" ? "DEVELOPMENT" : "PRODUCTION");
- if (g.mode === "dev") {
- await startDevWatcher();
- }
+ g.log.info(g.mode === "dev" ? "DEVELOPMENT" : "PRODUCTION");
+ if (g.mode === "dev") {
+ await startDevWatcher();
+ }
- /** init lmdb */
- user.conf.init();
- snapshot.init();
+ /** init lmdb */
+ user.conf.init();
+ snapshot.init();
}
const db = g.db;
if (!db) {
- await preparePrisma();
- await ensureNotRunning();
- const db = g.db;
- if (db) {
- db.$connect()
- .catch((e: any) => {
- g.log.error(`[DB ERROR]\n${e.message}`);
- })
- .then(() => {
- g.log.info("Database connected");
- });
- }
+ await preparePrisma();
+ await ensureNotRunning();
+ const db = g.db;
+ if (db) {
+ db.$connect()
+ .catch((e: any) => {
+ g.log.error(`[DB ERROR]\n${e.message}`);
+ })
+ .then(() => {
+ g.log.info("Database connected");
+ });
+ }
}
if (!g.apiPrepared) {
- await initSrv();
- await syncActionDefinition();
- g.log.info("WS Action defined");
- await prepareApiRoutes();
- await prepareAPITypes();
- g.log.info("API Prepared");
- g.apiPrepared = true;
+ await initSrv();
+ await syncActionDefinition();
+ g.log.info("WS Action defined");
+ await prepareApiRoutes();
+ await prepareAPITypes();
+ g.log.info("API Prepared");
+ g.apiPrepared = true;
}
if (!g.parcel) {
- await parcelBuild();
+ await parcelBuild();
}
const { createServer } = await import("./server/create");
diff --git a/pkgs/core/server/serve-static.ts b/pkgs/core/server/serve-static.ts
index 42eca787..4c5f2618 100644
--- a/pkgs/core/server/serve-static.ts
+++ b/pkgs/core/server/serve-static.ts
@@ -1,5 +1,5 @@
import { dir } from "dir";
-import { inspectTreeAsync } from "fs-jetpack";
+import { exists, inspectTreeAsync } from "fs-jetpack";
import { InspectTreeResult } from "fs-jetpack/types";
import { join } from "path";
import { watch } from "fs";
@@ -8,83 +8,88 @@ import mime from "mime";
import { g } from "utils/global";
const web = {
- get path() {
- if (g.mode === "dev") return "static";
- return "static-br";
- },
+ brExists: null as null | boolean,
+ get path() {
+ if (g.mode === "dev") return "static";
+ if (this.brExists === null) {
+ this.brExists = !!exists(dir.path("app/static-br"));
+ }
+ if (this.brExists) return "static-br";
+ else return "static";
+ },
};
const cache = {
- static: {} as Record<
- string,
- { type: string; content: any; compression: "" | "br" }
- >,
+ static: {} as Record<
+ string,
+ { type: string; content: any; compression: "" | "br" }
+ >,
};
export const serveStatic = {
- init: async () => {
- const list = await inspectTreeAsync(dir.path(`app/${web.path}`));
- const walk = async (
- list: InspectTreeResult,
- parent?: InspectTreeResult[]
- ) => {
- if (list.type === "dir") {
- for (const item of list.children) {
- await walk(item, [...(parent || []), list]);
- }
- } else {
- const path = join(...(parent || []).map((e) => e.name), list.name);
- const file = Bun.file(dir.path(`app/${path}`));
- if (await file.exists()) {
- cache.static[path.substring(web.path.length)] = {
- type: mime.getType(path) || "application/octet-stream",
- compression: g.mode === "prod" ? "br" : "",
- content: await file.arrayBuffer(),
- };
- }
- }
- };
- if (list) {
- await walk(list);
- }
+ init: async () => {
+ const list = await inspectTreeAsync(dir.path(`app/${web.path}`));
+ const walk = async (
+ list: InspectTreeResult,
+ parent?: InspectTreeResult[],
+ ) => {
+ if (list.type === "dir") {
+ for (const item of list.children) {
+ await walk(item, [...(parent || []), list]);
+ }
+ } else {
+ const path = join(...(parent || []).map((e) => e.name), list.name);
+ const file = Bun.file(dir.path(`app/${path}`));
+ if (await file.exists()) {
+ cache.static[path.substring(web.path.length)] = {
+ type: mime.getType(path) || "application/octet-stream",
+ compression: g.mode === "prod" ? "br" : "",
+ content: await file.arrayBuffer(),
+ };
+ }
+ }
+ };
+ if (list) {
+ await walk(list);
+ }
- if (g.mode === "dev") {
- watch(dir.path(`app/static`), async (_, filename) => {
- if (filename) {
- const path = join("static", filename);
- const file = Bun.file(dir.path(`app/${path}`));
- if (await file.exists()) {
- cache.static[`/${filename}`] = {
- type: mime.getType(path) || "application/octet-stream",
- compression: g.mode === "prod" ? "br" : "",
- content: await file.arrayBuffer(),
- };
- }
- }
- });
- }
- },
- exists: (url: URL) => {
- return !!cache.static[url.pathname];
- },
- serve: (url: URL) => {
- let file = cache.static[url.pathname];
- if (file) {
- return new Response(file.content, {
- headers: {
- ...{ "content-type": file.type },
- ...(file.compression ? { "content-encoding": file.compression } : {}),
- },
- });
- }
+ if (g.mode === "dev") {
+ watch(dir.path(`app/static`), async (_, filename) => {
+ if (filename) {
+ const path = join("static", filename);
+ const file = Bun.file(dir.path(`app/${path}`));
+ if (await file.exists()) {
+ cache.static[`/${filename}`] = {
+ type: mime.getType(path) || "application/octet-stream",
+ compression: g.mode === "prod" ? "br" : "",
+ content: await file.arrayBuffer(),
+ };
+ }
+ }
+ });
+ }
+ },
+ exists: (url: URL) => {
+ return !!cache.static[url.pathname];
+ },
+ serve: (url: URL) => {
+ let file = cache.static[url.pathname];
+ if (file) {
+ return new Response(file.content, {
+ headers: {
+ ...{ "content-type": file.type },
+ ...(file.compression ? { "content-encoding": file.compression } : {}),
+ },
+ });
+ }
- file = cache.static["/index.html"];
- if (file) {
- return new Response(file.content, {
- headers: {
- ...{ "content-type": file.type },
- ...(file.compression ? { "content-encoding": file.compression } : {}),
- },
- });
- }
- },
+ file = cache.static["/index.html"];
+ if (file) {
+ return new Response(file.content, {
+ headers: {
+ ...{ "content-type": file.type },
+ ...(file.compression ? { "content-encoding": file.compression } : {}),
+ },
+ });
+ }
+ },
};
diff --git a/pkgs/core/utils/prisma.ts b/pkgs/core/utils/prisma.ts
index c22130ed..0da6327a 100644
--- a/pkgs/core/utils/prisma.ts
+++ b/pkgs/core/utils/prisma.ts
@@ -1,22 +1,22 @@
import { $ } from "execa";
-import { existsAsync } from "fs-jetpack";
+import { exists, existsAsync } from "fs-jetpack";
import { dir } from "./dir";
import { g } from "./global";
export const preparePrisma = async () => {
- if (
- (await existsAsync(dir.path("app/db/.env"))) ||
- process.env.DATABASE_URL
- ) {
- if (g.mode === "prod") {
- g.log.info("Prisma: db pull & generate");
- await $({ cwd: dir.path(`app/db`) })`bun prisma db pull`;
- await $({ cwd: dir.path(`app/db`) })`bun prisma generate`;
- }
-
- const { PrismaClient } = await import("../../../app/db/db");
- g.db = new PrismaClient();
- }
+ if (
+ (await existsAsync(dir.path("app/db/.env"))) ||
+ process.env.DATABASE_URL
+ ) {
+ if (g.mode === "prod" && exists(dir.path("app/static-br"))) {
+ g.log.info("Prisma: db pull & generate");
+ await $({ cwd: dir.path(`app/db`) })`bun prisma db pull`;
+ await $({ cwd: dir.path(`app/db`) })`bun prisma generate`;
+ }
- g.dburl = process.env.DATABASE_URL || "";
+ const { PrismaClient } = await import("../../../app/db/db");
+ g.db = new PrismaClient();
+ }
+
+ g.dburl = process.env.DATABASE_URL || "";
};