From ecd2dc33f91c6c8dc0da4bc1280fe0cc5a228449 Mon Sep 17 00:00:00 2001 From: Rizky Date: Sun, 22 Oct 2023 12:22:25 +0700 Subject: [PATCH] fix --- app/srv/ws/sync/entity/user.ts | 6 ++ app/web/src/render/ed/logic/ed-global.ts | 4 + app/web/src/render/ed/logic/tree/build.tsx | 42 +++++++---- app/web/src/utils/sync/keymap.ts | 86 ++++++++++++++++++++++ pkgs/core/server/prep-api-ts.ts | 20 ++++- 5 files changed, 140 insertions(+), 18 deletions(-) create mode 100644 app/web/src/utils/sync/keymap.ts diff --git a/app/srv/ws/sync/entity/user.ts b/app/srv/ws/sync/entity/user.ts index 53fd594f..165482ac 100644 --- a/app/srv/ws/sync/entity/user.ts +++ b/app/srv/ws/sync/entity/user.ts @@ -1,6 +1,7 @@ import { dir } from "dir"; import { RootDatabase, open } from "lmdb"; import { g } from "utils/global"; +import { KeyMap } from "../../../../web/src/utils/sync/keymap"; const defaultConf = { site_id: "", @@ -9,6 +10,11 @@ const defaultConf = { export type UserConf = typeof defaultConf; export const user = { + active: KeyMap.create<{ + user_id: string; + site_id: string; + page_id: string; + }>("user_id"), conf: { _db: null as null | RootDatabase, init() { diff --git a/app/web/src/render/ed/logic/ed-global.ts b/app/web/src/render/ed/logic/ed-global.ts index ed378e5e..def03dc7 100644 --- a/app/web/src/render/ed/logic/ed-global.ts +++ b/app/web/src/render/ed/logic/ed-global.ts @@ -33,6 +33,10 @@ const EmptyComp = { export type EdMeta = { item: IItem | IText; mitem?: MItem | MText; + parent_item: { + id: string; + mitem?: MItem; + }; parent_comp?: { ref_ids: Record; mcomp: MItem; diff --git a/app/web/src/render/ed/logic/tree/build.tsx b/app/web/src/render/ed/logic/tree/build.tsx index 13dfa04d..0db0c7b2 100644 --- a/app/web/src/render/ed/logic/tree/build.tsx +++ b/app/web/src/render/ed/logic/tree/build.tsx @@ -20,16 +20,25 @@ export const treeRebuild = async (p: PG) => { p.page.tree = []; p.page.meta = {}; - const portal = {}; + const portal = { + in: {} as Record, + out: {} as Record, + }; const sections = root.get("childs"); if (sections) { await Promise.all( sections.map(async (e) => { p.page.entry.push(e.get("id")); - await walkMap(p, { mitem: e, tree_parent_id: "root", portal }); + await walkMap(p, { mitem: e, parent_item: { id: "root" }, portal }); }) ); - console.log(p.page); + + for (const [k, v] of Object.entries(portal.out)) { + const name = k.replace(/⮕/gi, "").trim(); + const portal_in = portal.in[`⬅${name}`]; + if (portal_in) { + } + } } } }; @@ -54,13 +63,16 @@ const walkMap = async ( p: PG, arg: { mitem: MItem | MSection; - portal: Record; - tree_parent_id: string; + portal: { + in: Record; + out: Record; + }; + parent_item: EdMeta["parent_item"]; parent_comp?: EdMeta["parent_comp"]; skip_add_tree?: boolean; } ) => { - const { mitem, tree_parent_id, parent_comp } = arg; + const { mitem, parent_item, parent_comp } = arg; const item = {} as unknown as IItem; mapItem(mitem, item); @@ -80,7 +92,7 @@ const walkMap = async ( if (!arg.skip_add_tree) { p.page.tree.push({ id: item.id, - parent: tree_parent_id, + parent: parent_item.id, text: item.name, }); } @@ -122,7 +134,7 @@ const walkMap = async ( if (mcontent) { walkMap(p, { mitem: mcontent, - tree_parent_id: item.id, + parent_item: { id: item.id, mitem: mitem as MItem }, parent_comp: { ref_ids, mcomp }, portal: arg.portal, }); @@ -137,7 +149,7 @@ const walkMap = async ( mcomp.get("childs")?.map(async (e) => { await walkMap(p, { mitem: e, - tree_parent_id: item.id, + parent_item: { id: item.id, mitem: mitem as MItem }, parent_comp: { ref_ids, mcomp }, skip_add_tree: true, portal: arg.portal, @@ -156,15 +168,16 @@ const walkMap = async ( const meta: EdMeta = { item, mitem: mitem as MItem, + parent_item, parent_comp, }; if (!item_comp) { if (item.name.startsWith("⬅")) { - arg.portal[item.name] = meta; + arg.portal.in[item.name] = meta; } if (item.name.startsWith("⮕")) { - arg.portal[item.name] = meta; + arg.portal.out[item.name] = meta; } } @@ -173,7 +186,7 @@ const walkMap = async ( if (!arg.skip_add_tree) { p.page.tree.push({ id: item.id, - parent: tree_parent_id, + parent: parent_item.id, text: item.name, data: meta, }); @@ -186,7 +199,7 @@ const walkMap = async ( item.childs.push(e.get("id")); await walkMap(p, { mitem: e, - tree_parent_id: item.id, + parent_item: { id: item.id, mitem: mitem as MItem }, portal: arg.portal, }); }) || [] @@ -195,14 +208,13 @@ const walkMap = async ( }; const loadComponent = async (p: PG, item_comp: FNComponent) => { - let found = false; const cur = await p.sync.comp.load(item_comp.id); if (cur && cur.snapshot) { const doc = new Y.Doc() as DComp; if (cur.snapshot) { Y.applyUpdate(doc as any, cur.snapshot); p.comp.list[item_comp.id] = { cur, doc }; - found = true; + return true; } } return false; diff --git a/app/web/src/utils/sync/keymap.ts b/app/web/src/utils/sync/keymap.ts new file mode 100644 index 00000000..6f6630d8 --- /dev/null +++ b/app/web/src/utils/sync/keymap.ts @@ -0,0 +1,86 @@ +export const KeyMap = { + create: >(main: keyof K) => { + const childs = {} as Record>; + + const all = {} as Record>; + + const createChild = (key: string) => { + return { + remove(id: string) { + if (all[id]) { + map.delete(all[key][id]); + } + }, + }; + }; + + const map = new EventedMap({ + onSet({ key, value }) { + for (const [k, v] of Object.entries(value)) { + if (!childs[k]) { + childs[k] = createChild(k); + all[k] = {}; + } + all[k][v] = key; + } + }, + onDelete(key) { + const val = map.get(key); + for (const [k, v] of Object.entries(val)) { + delete all[k][v as string]; + } + return true; + }, + }); + return new Proxy( + {}, + { + get(_, key: string, receiver) { + if (key === "get") { + return map.get; + } + if (key === "set") { + return (val: K) => { + const key = val[main]; + map.set(key, val); + }; + } + + if (!childs[key]) { + childs[key] = createChild(key); + } + return childs[key]; + }, + } + ) as { get: (key: typeof main) => K; set: (val: K) => void } & Record< + keyof K, + EventedMap + >; + }, +}; + +type MapEvents = Partial<{ + onSet: (arg: { key: string; value: Record }) => void; + onDelete: (key: string) => boolean; +}>; + +class EventedMap extends Map { + _events: MapEvents; + + constructor(events: MapEvents) { + super(); + this._events = events; + } + set(key: string, value: Record): this { + super.set(key, value); + this._events.onSet?.({ key, value }); + return this; + } + delete(key: string): boolean { + const value = this.get(key); + if (value) { + this._events.onDelete?.(key); + } + return super.delete(key); + } +} diff --git a/pkgs/core/server/prep-api-ts.ts b/pkgs/core/server/prep-api-ts.ts index 70422d3f..f1ded836 100644 --- a/pkgs/core/server/prep-api-ts.ts +++ b/pkgs/core/server/prep-api-ts.ts @@ -1,5 +1,5 @@ import { spawn, spawnSync } from "bun"; -import { readAsync } from "fs-jetpack"; +import { existsAsync, readAsync } from "fs-jetpack"; import { dir } from "../utils/dir"; import { g } from "../utils/global"; @@ -7,13 +7,27 @@ export const prepareAPITypes = async () => { const out: string[] = []; for (const [k, v] of Object.entries(g.api)) { const name = k.substring(0, k.length - 3).replace(/\W/gi, "_"); + + let p = { + path: `app/srv/api/${v.path}`, + handler: `"./api/${v.path.substring(0, v.path.length - 3)}"`, + }; + + if (!(await existsAsync(dir.path(p.path)))) { + p.path = `pkgs/core/api/${v.path}`; + p.handler = `"../../pkgs/core/api/${v.path.substring( + 0, + v.path.length - 3 + )}"`; + } + out.push(`\ export const ${name} = { name: "${name}", url: "${v.url}", - path: "app/srv/api/${v.path}", + path: "${p.path}", args: ${JSON.stringify(v.args)}, - handler: import("./api/${v.path.substring(0, v.path.length - 3)}") + handler: import(${p.handler}) }`); } await Bun.write(dir.path(`app/srv/exports.ts`), out.join(`\n`));