From 2fddcf1a780eb95e772891f13cb99672304bd110 Mon Sep 17 00:00:00 2001 From: Rizky Date: Fri, 20 Oct 2023 11:20:01 +0700 Subject: [PATCH] fix --- app/srv/ws/sync/actions-def.ts | 26 +++ app/srv/ws/sync/actions.ts | 22 +++ app/srv/ws/sync/sync-handler.ts | 36 ++-- app/srv/ws/sync/type.ts | 23 --- app/web/package.json | 5 +- app/web/src/base/page/ned.tsx | 29 +++ app/web/src/base/pages.ts | 4 + app/web/src/index.tsx | 147 ++++++++++++--- app/web/src/render/editor/logic/global.ts | 2 + .../panel/script/monaco/monaco-el-history.tsx | 4 +- app/web/src/sworker.ts | 41 +++-- app/web/src/utils/script/init-api.ts | 8 +- app/web/src/utils/sync/client.ts | 167 ++++++++++-------- app/web/src/utils/sync/idb.ts | 5 + app/web/src/utils/types/general.ts | 1 + bun.lockb | Bin 291568 -> 244328 bytes pkgs/core/build.ts | 2 +- pkgs/core/index.ts | 14 +- pkgs/core/utils/sync-def.ts | 31 ++++ 19 files changed, 392 insertions(+), 175 deletions(-) create mode 100644 app/srv/ws/sync/actions-def.ts create mode 100644 app/srv/ws/sync/actions.ts delete mode 100644 app/srv/ws/sync/type.ts create mode 100644 app/web/src/base/page/ned.tsx create mode 100644 app/web/src/utils/sync/idb.ts create mode 100644 pkgs/core/utils/sync-def.ts diff --git a/app/srv/ws/sync/actions-def.ts b/app/srv/ws/sync/actions-def.ts new file mode 100644 index 00000000..7df0a90e --- /dev/null +++ b/app/srv/ws/sync/actions-def.ts @@ -0,0 +1,26 @@ +export const SyncActionDefinition = { + "site": { + "all": "0", + "group": "1", + "load": "2" + }, + "comp": { + "all": "3", + "group": "4", + "doc": "5" + }, + "page": { + "all": "6", + "load": "7" + } +}; +export const SyncActionPaths = { + "0": "site.all", + "1": "site.group", + "2": "site.load", + "3": "comp.all", + "4": "comp.group", + "5": "comp.doc", + "6": "page.all", + "7": "page.load" +}; \ No newline at end of file diff --git a/app/srv/ws/sync/actions.ts b/app/srv/ws/sync/actions.ts new file mode 100644 index 00000000..446f555f --- /dev/null +++ b/app/srv/ws/sync/actions.ts @@ -0,0 +1,22 @@ +import { component, site, page } from "dbgen"; + +export const SyncActions = { + site: { + all: () => + ({}) as Promise< + Record + >, + group: () => ({}) as Promise>, + load: (id: string) => ({}) as Promise, + }, + comp: { + all: () => ({}) as Record>, + group: () => ({}) as Record, + doc: (id: string) => ({}) as Uint8Array, + }, + page: { + all: (id_site: string) => + ({}) as Record>, + load: (id: string) => ({}) as Uint8Array, + }, +}; diff --git a/app/srv/ws/sync/sync-handler.ts b/app/srv/ws/sync/sync-handler.ts index cb71bca7..fb662832 100644 --- a/app/srv/ws/sync/sync-handler.ts +++ b/app/srv/ws/sync/sync-handler.ts @@ -1,13 +1,13 @@ -import { ServerWebSocket, WebSocketHandler } from "bun"; -import { WSData } from "../../../../pkgs/core/server/create"; -import { Packr } from "msgpackr"; import { createId } from "@paralleldrive/cuid2"; -import { MSG_TO_SERVER } from "./type"; +import { ServerWebSocket, WebSocketHandler } from "bun"; +import { Packr } from "msgpackr"; +import { WSData } from "../../../../pkgs/core/server/create"; const packr = new Packr({ structuredClone: true }); const conns = new Map< string, { + user_id: string; ws: ServerWebSocket; msg: { pending: Record>; @@ -18,21 +18,31 @@ const conns = new Map< const wconns = new WeakMap, string>(); export const syncHandler: WebSocketHandler = { open(ws) { - const id = createId(); - conns.set(id, { ws, msg: { pending: {}, resolve: {} } }); - wconns.set(ws, id); - ws.sendBinary(packr.pack({ type: "identify", id })); + const client_id = createId(); + conns.set(client_id, { + user_id: "", + ws, + msg: { pending: {}, resolve: {} }, + }); + wconns.set(ws, client_id); + ws.sendBinary(packr.pack({ type: "client_id", client_id })); + }, + close(ws, code, reason) { + const conn_id = wconns.get(ws); + if (conn_id) { + conns.delete(conn_id); + wconns.delete(ws); + } }, message(ws, raw) { const conn_id = wconns.get(ws); if (conn_id) { const conn = conns.get(conn_id); if (conn) { - const msg = packr.unpack(Buffer.from(raw)) as MSG_TO_SERVER & { - msg_client_id: string; - }; - - switch (msg.action) { + const msg = packr.unpack(Buffer.from(raw)); + if (msg.type === "user_id") { + const { user_id } = msg; + conn.user_id = user_id; } } } diff --git a/app/srv/ws/sync/type.ts b/app/srv/ws/sync/type.ts deleted file mode 100644 index 6f2f9adb..00000000 --- a/app/srv/ws/sync/type.ts +++ /dev/null @@ -1,23 +0,0 @@ -export enum DType { - Site, - Comp, - Page, -} - -export enum ServerAction { - Load, -} - -export type MSG_TO_SERVER = { - action: ServerAction.Load; - type: DType; - id: string; -}; - -export enum ClientAction { - Identify, -} -export type MSG_TO_CLIENT = { - action: ClientAction.Identify; - id: string; -}; diff --git a/app/web/package.json b/app/web/package.json index dcdb37c7..b8ae8980 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -13,13 +13,14 @@ "@paralleldrive/cuid2": "2.2.2", "@parcel/packager-wasm": "^2.10.0", "@parcel/service-worker": "^2.10.0", - "msgpackr": "^1.9.9", + "@qiwi/deep-proxy": "^2.0.3", "@swc/wasm-web": "1.3.94-nightly-20231014.1", "algoliasearch": "^4.20.0", "date-fns": "^2.30.0", "dbgen": "workspace:*", "downshift": "^8.2.2", "esbuild-wasm": "^0.19.4", + "hash-wasm": "^4.10.0", "idb-keyval": "^6.2.1", "js-base64": "^3.7.5", "lodash.capitalize": "^4.2.1", @@ -38,6 +39,7 @@ "lodash.uniq": "^4.5.0", "lodash.uniqby": "^4.7.0", "monaco-jsx-syntax-highlight-v2": "^1.2.2", + "msgpackr": "^1.9.9", "polywasm": "^0.1.4", "prettier": "3.0.3", "prop-types": "^15.8.1", @@ -50,6 +52,7 @@ "react-is": "^18.2.0", "react-use-error-boundary": "^3.0.0", "react-virtuoso": "^4.6.1", + "safe-stable-stringify": "^2.4.3", "svgo": "^3.0.2", "textdiff-create": "^1.1.9", "tinycolor2": "^1.6.0", diff --git a/app/web/src/base/page/ned.tsx b/app/web/src/base/page/ned.tsx new file mode 100644 index 00000000..e907ac5d --- /dev/null +++ b/app/web/src/base/page/ned.tsx @@ -0,0 +1,29 @@ +import { page, useGlobal } from "web-utils"; +import { EditorGlobal } from "../../render/editor/logic/global"; +import { Loading } from "../../utils/ui/loading"; +import { clientStartSync } from "../../utils/sync/client"; + +export default page({ + url: "/ned/:site_id/:page_id", + component: ({}) => { + const p = useGlobal(EditorGlobal, "EDITOR"); + + const session = JSON.parse( + localStorage.getItem("prasi-session") || "null" + ) as { data: { user: { id: string } } }; + if (!session) { + navigate("/login"); + return ; + } + + if (!p.sync) { + // p.sync = clientStartSync({ + // user_id: session.data.user.id, + // }); + + return ; + } + + return
; + }, +}); diff --git a/app/web/src/base/pages.ts b/app/web/src/base/pages.ts index 40113090..14a81af7 100644 --- a/app/web/src/base/pages.ts +++ b/app/web/src/base/pages.ts @@ -26,3 +26,7 @@ export const live = { url: "/live/:domain/**", page: () => import("./page/live"), }; +export const ned = { + url: "/ned/:site_id/:page_id", + page: () => import("./page/ned"), +}; diff --git a/app/web/src/index.tsx b/app/web/src/index.tsx index 8217d661..b2fec886 100644 --- a/app/web/src/index.tsx +++ b/app/web/src/index.tsx @@ -1,4 +1,4 @@ -import { createRoot } from "react-dom/client"; +import { Root as ReactRoot, createRoot } from "react-dom/client"; import { defineReact, defineWindow } from "web-utils"; import { Root } from "./base/root"; import "./index.css"; @@ -6,35 +6,107 @@ import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api"; import { w } from "./utils/types/general"; const start = async () => { + const base = `${location.protocol}//${location.host}`; + let react = { + root: null as null | ReactRoot, + }; if (!["localhost", "127.0.0.1"].includes(location.hostname)) { const sw = await registerServiceWorker(); navigator.serviceWorker.addEventListener("message", (e) => { - if (e.data.type === "activated") { - if (e.data.shouldRefresh && sw) { - sw.unregister().then(() => { - window.location.reload(); - }); - } - } - if (e.data.type === "ready") { - const sw = navigator.serviceWorker.controller; - - if (sw) { - const routes = Object.entries(w.prasiApi[base].apiEntry).map( - ([k, v]: any) => ({ - url: v.url, - name: k, - }) + 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: Offline Mode +
+
+ ); + } - sw.postMessage({ - type: "add-cache", - url: location.href, - }); - sw.postMessage({ - type: "define-route", - routes, - }); + 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( + <> + +
+
+ App Updated, Ready to use offline +
+
+ + ); + } + } } } }); @@ -48,15 +120,36 @@ const start = async () => { defineReact(); await defineWindow(false); - const base = `${location.protocol}//${location.host}`; w.serverurl = base; await reloadDBAPI(base, "prod"); + + const swc = navigator.serviceWorker.controller; + if (swc) { + swc.postMessage({ + type: "add-cache", + url: location.href, + }); + 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); const el = document.getElementById("root"); if (el) { - createRoot(el).render(); + react.root = createRoot(el); + react.root.render(); } }; diff --git a/app/web/src/render/editor/logic/global.ts b/app/web/src/render/editor/logic/global.ts index dce6caf1..6b028a4e 100644 --- a/app/web/src/render/editor/logic/global.ts +++ b/app/web/src/render/editor/logic/global.ts @@ -9,6 +9,7 @@ import { IRoot } from "../../../utils/types/root"; import { LSite } from "../../live/logic/global"; import { ISection } from "../../../utils/types/section"; import { IText } from "../../../utils/types/text"; +import { clientStartSync } from "../../../utils/sync/client"; export type WithRequired = T & { [P in K]-?: T[P] }; export type NodeMeta = { meta: ItemMeta; idx: number }; @@ -40,6 +41,7 @@ export type ItemMeta = { export const EditorGlobal = { /** ui */ mode: "" as "desktop" | "mobile", + sync: null as unknown as ReturnType, status: "init" as | "init" | "loading" diff --git a/app/web/src/render/editor/panel/script/monaco/monaco-el-history.tsx b/app/web/src/render/editor/panel/script/monaco/monaco-el-history.tsx index c9b2e67d..80236a9a 100644 --- a/app/web/src/render/editor/panel/script/monaco/monaco-el-history.tsx +++ b/app/web/src/render/editor/panel/script/monaco/monaco-el-history.tsx @@ -1,7 +1,7 @@ -import { UseStore, del, getMany, keys } from "idb-keyval"; +import { UseStore, getMany, keys } from "idb-keyval"; import { useGlobal, useLocal } from "web-utils"; -import { EditorGlobal } from "../../../logic/global"; import { Tooltip } from "../../../../../utils/ui/tooltip"; +import { EditorGlobal } from "../../../logic/global"; export const MonacoElHistory = ({ store, diff --git a/app/web/src/sworker.ts b/app/web/src/sworker.ts index 6ce91091..20caffdb 100644 --- a/app/web/src/sworker.ts +++ b/app/web/src/sworker.ts @@ -2,6 +2,7 @@ import { manifest, version } from "@parcel/service-worker"; import { RadixRouter, createRouter } from "radix3"; const g = { router: null as null | RadixRouter, + offline: false, broadcast(msg: any) { // @ts-ignore const c: Clients = self.clients; @@ -22,17 +23,19 @@ addEventListener("install", (e) => (e as ExtendableEvent).waitUntil(install())); async function activate() { let shouldRefresh = false; - const keys = await caches.keys(); - await Promise.all( - keys.map(async (key) => { - if (key !== version) { - await caches.delete(key); - shouldRefresh = true; - } - }) - ); + 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 }); + g.broadcast({ type: "activated", shouldRefresh, version }); + } } addEventListener("activate", (e) => (e as ExtendableEvent).waitUntil(activate()) @@ -56,19 +59,29 @@ addEventListener("fetch", async (evt) => { if (r) { return r; } - return fetch(e.request); + + try { + g.offline = false; + return await fetch(e.request); + } catch (e) { + g.offline = true; + g.broadcast({ type: "offline" }); + return new Response(); + } })() ); }); -g.broadcast({ type: "ready" }); addEventListener("message", async (e) => { const type = e.data.type; const cache = await caches.open(version); switch (type) { case "add-cache": - if (!(await cache.match(e.data.url))) { - await cache.add(e.data.url); + { + const cached = await cache.match(e.data.url); + if (!cached) { + await cache.add(e.data.url); + } } break; case "define-route": diff --git a/app/web/src/utils/script/init-api.ts b/app/web/src/utils/script/init-api.ts index 4b90c124..70d4c2e7 100644 --- a/app/web/src/utils/script/init-api.ts +++ b/app/web/src/utils/script/init-api.ts @@ -64,7 +64,6 @@ export const initApi = async (config: any, mode: "dev" | "prod" = "dev") => { if (url) { if (!w.prasiApi[url]) { try { - await reloadDBAPI(url, mode); } catch (e) {} } @@ -137,12 +136,7 @@ export const reloadDBAPI = async ( const found = await get(url, cache); if (found) { w.prasiApi[url] = JSON.parse(found); - forceReload().catch(() => { - if (url === prasiBase) { - console.error("Failed to load prasi. Reloading..."); - setTimeout(() => location.reload(), 3000); - } - }); + forceReload(); } else { await forceReload(); } diff --git a/app/web/src/utils/sync/client.ts b/app/web/src/utils/sync/client.ts index 784cc459..5db15d66 100644 --- a/app/web/src/utils/sync/client.ts +++ b/app/web/src/utils/sync/client.ts @@ -1,91 +1,106 @@ +import { DeepProxy } from "@qiwi/deep-proxy"; +import { xxhash32 } from "hash-wasm"; +import { UseStore, get } from "idb-keyval"; import { Packr } from "msgpackr"; -import { - ClientAction, - MSG_TO_CLIENT, - MSG_TO_SERVER, - ServerAction, -} from "../../../../srv/ws/sync/type"; -import { SyncSite } from "./site"; -import { createId } from "@paralleldrive/cuid2"; +import { stringify } from "safe-stable-stringify"; +import { SyncActions } from "../../../../srv/ws/sync/actions"; +import { SyncActionDefinition } from "../../../../srv/ws/sync/actions-def"; +import { initIDB } from "./idb"; const packr = new Packr({ structuredClone: true }); +const conf = { + ws: null as null | WebSocket, + client_id: "", + idb: null as null | UseStore, +}; -export class SyncClient { - private id = ""; - private ws: WebSocket; - private wsPending?: Promise; - public connected = false; - public loaded = { - site: new Map(), +type User = { + id: string; + name: string; +}; + +export const clientStartSync = async (arg: { + user_id: string; + events: { + site_open: (arg: { site_id: string; user: User }) => void; }; - - public site = { - load: async (id: string) => { - this.loaded.site.set(id, new SyncSite(this, id)); - }, - }; - - public _internal = { - msg: { - pending: {} as Record>, - resolve: {} as Record void>, - }, - send: async (msg: MSG_TO_SERVER) => { - const { resolve, pending } = this._internal.msg; - const msg_client_id = createId(); - pending[msg_client_id] = new Promise((done) => { - resolve[msg_client_id] = done; - }); - - if (this.wsPending) { - await this.wsPending; +}) => { + const { user_id, events } = arg; + conf.idb = initIDB(user_id); + await connect(user_id); + const path: any[] = []; + return new DeepProxy( + SyncActionDefinition, + ({ trapName, value, key, DEFAULT, PROXY }) => { + if (trapName === "set") { + throw new TypeError("target is immutable"); } - this.ws.send(packr.pack({ ...msg, msg_client_id: createId() })); - }, - }; + path.push(key); + if (typeof value === "string") { + if (path[0] === "then") path.shift(); + return (...args: any[]) => + new Promise((resolve) => { + operation({ + path: path.join("."), + resolve, + args, + }); + }); + } - constructor(ws: WebSocket) { - this.ws = ws; - } + if (trapName === "get") { + if (typeof value === "object" && value !== null) { + return PROXY; + } + } - private static instance = null as SyncClient | null; - static connect() { - if (SyncClient.instance) return SyncClient.instance; + return DEFAULT; + } + ) as unknown as typeof SyncActions; +}; - const url = new URL(location.href); - url.pathname = "/sync"; - url.protocol = url.protocol === "http:" ? "ws:" : "wss:"; +const connect = (user_id: string) => { + return new Promise((resolve) => { + if (!conf.ws) { + const url = new URL(location.href); + url.pathname = "/sync"; + url.protocol = url.protocol === "http:" ? "ws:" : "wss:"; - const ws = new WebSocket(url.toString()); - const client = new SyncClient(ws); - SyncClient.instance = client; - let promise = { - resolve: null as null | (() => void), - }; - client.wsPending = new Promise((resolve) => { - promise.resolve = resolve; - }); - ws.onopen = () => { - promise.resolve?.(); - }; - - ws.onmessage = async (e) => { - const raw = e.data as Blob; - const msg = packr.unpack( - Buffer.from(await raw.arrayBuffer()) - ) as MSG_TO_CLIENT & { - msg_server_id: string; + const ws = new WebSocket(url.toString()); + conf.ws = ws; + ws.onopen = () => { + ws.send(packr.pack({ type: "user_id", user_id })); }; - if (!client.id) { - if (msg.action === ClientAction.Identify) { - client.id = msg.id; - client.connected = true; + ws.onmessage = async (e) => { + const raw = e.data as Blob; + const msg = packr.unpack(Buffer.from(await raw.arrayBuffer())); + if (msg.type === "client_id") { + conf.client_id = msg.client_id; + resolve(ws); } - } else { - } - }; + }; + } + }); +}; - return client; +const operation = async (arg: { + path: string; + resolve: (value: any) => void; + args: any[]; +}) => { + const ws = conf.ws; + const idb = conf.idb; + if (idb) { + const sargs = stringify(arg.args); + const hargs = await xxhash32(`${arg.path}-${sargs}`); + + if (ws && ws.readyState === ws.OPEN) { + // online + } else { + // offline + const cache = await get(hargs, idb); + console.log(cache); + } } -} +}; diff --git a/app/web/src/utils/sync/idb.ts b/app/web/src/utils/sync/idb.ts new file mode 100644 index 00000000..1e0758c9 --- /dev/null +++ b/app/web/src/utils/sync/idb.ts @@ -0,0 +1,5 @@ +import { createStore } from "idb-keyval"; +export const initIDB = (user_id: string) => { + const store = createStore(`prasi-user-${user_id}`, "default"); + return store; +}; diff --git a/app/web/src/utils/types/general.ts b/app/web/src/utils/types/general.ts index efdd1eb8..73c2ee48 100644 --- a/app/web/src/utils/types/general.ts +++ b/app/web/src/utils/types/general.ts @@ -33,6 +33,7 @@ export const w = window as unknown as { serverurl: string; api: any; db: any; + offline: boolean; }; export type Page = { diff --git a/bun.lockb b/bun.lockb index b599983e1c2129a9a2d9943a014d1485c9892df2..5958f7e1889b6fd2c3e91f5b6ac28b46b888be73 100755 GIT binary patch delta 43966 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

C=e9Tz~-1T%%J`lBiRs3Y?e}47=oXCQX&uRsWk# zRr?Pr+w3NDlj{_cRFQTx8l79CXo~a{I_6a;!b*N(vDK#_k$#jZ!enmMd9(GcCe>6F zeHwLICN+>b*Df*KAzXrjaX}-4jEP3ApjI*Wq$D!0pPa-0Hri*U$=s~Pu?)@HQH_3t zyAv#;rOe4(xIqP`5Ww)De(5CiOOVA5Pe=OboGe^=TXk zG8lzRY~9%(=X9j}|N; z!1wP8;w@cJ#gLG%yOaLP1#ZbM=f`?k%Utn}Aemv6;)55${}|HjJ%?3=#4TvhYlSE* z&bPL@xdB{V1id?uNo&ZQZHs0R@QcD2C%C=Evir)Mm8f8__gkM)doKK85;6u{f;sXE_yQ&i4AMAf+G0#7<34Yp)>-HI#+={o5KO`!@qs<<0j( z*Ak_oS`lt0%f)h{$53AKe^m)dQ(rAnQ}RIe-a>5iib91#Qm=Z&nV~cto(ckt|my#M2RT z0@yq?Nr~YvhLcm1X~?p8&W1ZGi~FN9sO$^=_K&dLYN+--Cf54J8Mug#{8 zlT~S>Yay`p+Dp#g)TKsL_f|$LlH;)^C86PB`I8O)ekK21TrXXmHOiLRm7zPCP{m8I zv^p}kvivPfkoYT8{Nmhdm(U4j2?{?a@Pl8=P{EJKi!BDq>>Nacc#2+9K8_v?m&VOp zxIGJQQB{*Oz#php(ry;O)dtD!!n>Db)ywL2edzjAT~;OR-+LCMF1d~2Jy?Dj=Wnv& zfBoC4+Ni@7O`=i_cv2Q_NtNCubK@iuc0E_-R60*&j7>A38?u#|{Z84#(mT@x@n@hy oyklu^l|YD6iDIL6$?96+HXMJe54ZpLJ7RcxQc{jS9X#Xz0YJO5_5c6? diff --git a/pkgs/core/build.ts b/pkgs/core/build.ts index ed96fd76..d1708ebf 100644 --- a/pkgs/core/build.ts +++ b/pkgs/core/build.ts @@ -2,7 +2,7 @@ import { spawn } from "bun"; import { dir } from "dir"; import { Plugin, context } from "esbuild"; import { $ } from "execa"; -import { removeAsync, writeAsync } from "fs-jetpack"; +import { listAsync, removeAsync, writeAsync } from "fs-jetpack"; await removeAsync(dir.path("app/web/.parcel-cache")); await removeAsync(dir.path("app/static")); diff --git a/pkgs/core/index.ts b/pkgs/core/index.ts index 0509bb60..5af17d15 100644 --- a/pkgs/core/index.ts +++ b/pkgs/core/index.ts @@ -8,6 +8,7 @@ import { ensureNotRunning } from "./utils/ensure"; import { g } from "./utils/global"; import { createLogger } from "./utils/logger"; import { preparePrisma } from "./utils/prisma"; +import { syncActionDefinition } from "utils/sync-def"; g.status = "init"; @@ -17,7 +18,6 @@ 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(); @@ -31,19 +31,11 @@ if (g.db) { g.log.error(`[DB ERROR]\n${e.message}`); }); } - - + +await syncActionDefinition(); await parcelBuild(); - await generateAPIFrm(); await prepareApiRoutes(); - -// Bun.serve({ -// port: g.port, -// async fetch(req, server) { -// return new Response("test. sabar. ya...."); -// }, -// }); await createServer(); await prepareAPITypes(); diff --git a/pkgs/core/utils/sync-def.ts b/pkgs/core/utils/sync-def.ts new file mode 100644 index 00000000..68fcdc20 --- /dev/null +++ b/pkgs/core/utils/sync-def.ts @@ -0,0 +1,31 @@ +import { dir } from "dir"; +import { SyncActions } from "../../../app/srv/ws/sync/actions"; +import { writeAsync } from "fs-jetpack"; + +export const syncActionDefinition = async () => { + const def: any = {}; + let idx = 0; + + const paths = {} as Record; + const walk = (act: any, d: any, parentPaths: string[]) => { + for (const [k, v] of Object.entries(act)) { + d[k] = typeof v === "function" ? idx++ + "" : {}; + + if (typeof d[k] === "string") { + paths[d[k]] = [...parentPaths, k].join("."); + } + + if (typeof d[k] === "object") { + walk(v, d[k], [...parentPaths, k]); + } + } + }; + walk(SyncActions, def, []); + + await writeAsync( + dir.path("app/srv/ws/sync/actions-def.ts"), + `\ +export const SyncActionDefinition = ${JSON.stringify(def, null, 2)}; +export const SyncActionPaths = ${JSON.stringify(paths, null, 2)}; ` + ); +};