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( - <> - -
-
- Network Failed -
-
- - ); - } + 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( - <> - -
-
- Updating App... -
-
- - ); - - 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( + <> + +
+
+ Network Failed +
+
+ , + ); + } + + if (e.data.type === "activated") { + if (e.data.shouldRefresh && sw) { + react.root.render( + <> + +
+
+ Updating App... +
+
+ , + ); + + 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 || ""; };