From ac34579b84bd204fd901790f06af8178ae4c61df Mon Sep 17 00:00:00 2001 From: Rizky Date: Thu, 9 Nov 2023 20:29:32 +0700 Subject: [PATCH] fix watcher --- app/srv/ws/sync/actions.ts | 2 +- app/srv/ws/sync/actions/activity.ts | 8 +- app/srv/ws/sync/editor/code/prep-code.ts | 20 +++++ app/srv/ws/sync/editor/code/watcher.ts | 86 ++++++++++++++++--- app/web/src/index.tsx | 7 +- .../src/render/ed/panel/popup/code/code.tsx | 49 ++++++++--- app/web/src/utils/ui/is-localhost.ts | 5 ++ 7 files changed, 146 insertions(+), 31 deletions(-) create mode 100644 app/web/src/utils/ui/is-localhost.ts diff --git a/app/srv/ws/sync/actions.ts b/app/srv/ws/sync/actions.ts index 40f79a90..42d8cf6b 100644 --- a/app/srv/ws/sync/actions.ts +++ b/app/srv/ws/sync/actions.ts @@ -82,7 +82,7 @@ export const SyncActions = { id: string; } | { type: "code"; id: string; name: string; action: "open" | "close" } - ) => {}, + ) => ({}) as any, client: { info: async (client_ids: string[]) => ({}) as Record, diff --git a/app/srv/ws/sync/actions/activity.ts b/app/srv/ws/sync/actions/activity.ts index ca2d7274..97f56c69 100644 --- a/app/srv/ws/sync/actions/activity.ts +++ b/app/srv/ws/sync/actions/activity.ts @@ -2,7 +2,11 @@ import { SAction } from "../actions"; import { SyncConnection } from "../type"; import { activity as a } from "../entity/activity"; import { prepCode } from "../editor/code/prep-code"; -import { Code, startCodeWatcher, stopCodeWatcher } from "../editor/code/watcher"; +import { + Code, + startCodeWatcher, + stopCodeWatcher, +} from "../editor/code/watcher"; export const activity: SAction["activity"] = async function ( this: SyncConnection, name, @@ -32,5 +36,7 @@ export const activity: SAction["activity"] = async function ( stopCodeWatcher(code.id); } } + + return code.id; } }; diff --git a/app/srv/ws/sync/editor/code/prep-code.ts b/app/srv/ws/sync/editor/code/prep-code.ts index 4171acbe..5664dc27 100644 --- a/app/srv/ws/sync/editor/code/prep-code.ts +++ b/app/srv/ws/sync/editor/code/prep-code.ts @@ -1,7 +1,27 @@ +import { dir } from "dir"; +import { g } from "utils/global"; +import { dirAsync } from "fs-jetpack"; export type DBCode = Exclude>, null>; export const prepCode = async (site_id: string, name: string) => { let code = await getCode(site_id); + + const pkgfile = Bun.file(dir.path(`${g.datadir}/site/code/package.json`)); + if (!(await pkgfile.exists())) { + await dirAsync(dir.path(`${g.datadir}/site/code`)); + await Bun.write( + pkgfile, + JSON.stringify( + { + name: "code", + workspaces: ["./*"], + }, + null, + 2 + ) + ); + } + if (code) return code; let new_code = await db.code.create({ data: { diff --git a/app/srv/ws/sync/editor/code/watcher.ts b/app/srv/ws/sync/editor/code/watcher.ts index 61bf3838..22d1fc7a 100644 --- a/app/srv/ws/sync/editor/code/watcher.ts +++ b/app/srv/ws/sync/editor/code/watcher.ts @@ -7,9 +7,12 @@ import { dirname } from "path"; import { spawn } from "bun"; export const Code = { - watchers: {} as Record>, + watchers: {} as Record< + string, + { id: string; watcher: ReturnType } + >, path: (id: string, p?: string) => { - return dir.path(`${g.datadir}/code/${id}${p ? "/" + p : ""}`); + return dir.path(`${g.datadir}/site/code/${id}${p ? "/" + p : ""}`); }, }; @@ -18,16 +21,25 @@ export const startCodeWatcher = async (code: DBCode) => { return; } + let delay = false; + const indexes = {} as Record; + for (const c of code.code_file) { const path = Code.path(c.id_code, c.path); + indexes[c.path] = c; const file = Bun.file(path); if (!(await file.exists())) { await dirAsync(dirname(path)); await Bun.write(file, c.content); + delay = true; } } + if (delay) { + await new Promise((resolve) => setTimeout(resolve, 1000)); + } + await spawn({ cmd: ["bun", "i"], cwd: Code.path(code.id), @@ -35,18 +47,72 @@ export const startCodeWatcher = async (code: DBCode) => { stdout: "ignore", }).exited; - Code.watchers[code.id] = watch( - Code.path(code.id), - { recursive: true }, - (event, path) => { - console.log(event, path); - } - ); + Code.watchers[code.id] = { + id: code.id, + watcher: watch( + Code.path(code.id), + { recursive: true }, + async (event, path) => { + if (path) { + const file = Bun.file(Code.path(code.id, path)); + + const item = indexes[path]; + + if (event === "change") { + if (item) { + console.log(path, await file.text()); + + await db.code_file.update({ + where: { + path_id_code: { id_code: item.id_code, path: item.path }, + }, + data: { + content: await file.text(), + }, + }); + } + } else { + if (await file.exists()) { + if (!item) { + await new Promise((resolve) => setTimeout(resolve, 500)); + const data = { + id_code: code.id, + path, + content: await file.text(), + }; + await db.code_file.create({ + data, + }); + indexes[path] = data; + } else { + await db.code_file.update({ + where: { + path_id_code: { id_code: item.id_code, path: item.path }, + }, + data: { + content: await file.text(), + }, + }); + } + } else { + if (item) { + await db.code_file.delete({ + where: { + path_id_code: { id_code: item.id_code, path: item.path }, + }, + }); + } + } + } + } + } + ), + }; }; export const stopCodeWatcher = async (id_code: string) => { if (Code.watchers[id_code]) { - Code.watchers[id_code].close(); + Code.watchers[id_code].watcher.close(); delete Code.watchers[id_code]; } }; diff --git a/app/web/src/index.tsx b/app/web/src/index.tsx index 94bb337c..6e8abb9a 100644 --- a/app/web/src/index.tsx +++ b/app/web/src/index.tsx @@ -6,6 +6,7 @@ import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api"; import { w } from "./utils/types/general"; import * as Y from "yjs"; import { registerMobile } from "./render/live/logic/mobile"; +import { isLocalhost } from "./utils/ui/is-localhost"; (window as any).Y = Y; @@ -16,11 +17,7 @@ const start = async () => { }; (window as any).mobile = registerMobile(); - if ( - !["localhost", "127.0.0.1", "trycloudflare.com", "ngrok"].find((e) => - location.hostname.includes(e) - ) - ) { + if (!isLocalhost()) { const sw = await registerServiceWorker(); const cacheCurrentPage = () => { diff --git a/app/web/src/render/ed/panel/popup/code/code.tsx b/app/web/src/render/ed/panel/popup/code/code.tsx index 01efcf52..3773d0d1 100644 --- a/app/web/src/render/ed/panel/popup/code/code.tsx +++ b/app/web/src/render/ed/panel/popup/code/code.tsx @@ -1,29 +1,44 @@ -import { useGlobal } from "web-utils"; +import { useGlobal, useLocal } from "web-utils"; import { EDGlobal } from "../../../logic/ed-global"; import { Modal } from "../../../../../utils/ui/modal"; import { useEffect } from "react"; +import { isLocalhost } from "../../../../../utils/ui/is-localhost"; +import { Loading } from "../../../../../utils/ui/loading"; export const EdPopCode = () => { const p = useGlobal(EDGlobal, "EDITOR"); + const local = useLocal({ id_code: "" }); useEffect(() => { - if (p.ui.popup.code.init) { - p.sync.activity("site", { - action: p.ui.popup.code.open ? "open" : "close", - id: p.site.id, - type: "code", - name: "main", - }); - } - p.ui.popup.code.init = true; + (async () => { + if (p.ui.popup.code.init) { + const id_code = await p.sync.activity("site", { + action: p.ui.popup.code.open ? "open" : "close", + id: p.site.id, + type: "code", + name: "main", + }); + + if (id_code) { + local.id_code = id_code; + local.render(); + } + } + p.ui.popup.code.init = true; + })(); }, [p.ui.popup.code.open]); + const vscode_url = isLocalhost() + ? "http://localhost:3000?" + : "https://code.web.andromedia.co.id?tkn=prasi&"; + return ( { if (!open) { + console.clear(); p.ui.popup.code.open = false; p.render(); } @@ -50,10 +65,16 @@ export const EdPopCode = () => {
Site
- + {!local.id_code ? ( +
+ +
+ ) : ( + + )}
); diff --git a/app/web/src/utils/ui/is-localhost.ts b/app/web/src/utils/ui/is-localhost.ts new file mode 100644 index 00000000..c7c914aa --- /dev/null +++ b/app/web/src/utils/ui/is-localhost.ts @@ -0,0 +1,5 @@ +export const isLocalhost = () => { + return ["localhost", "127.0.0.1", "trycloudflare.com", "ngrok"].find((e) => + location.hostname.includes(e) + ); +};