fix
This commit is contained in:
parent
2fddcf1a78
commit
7052dad65b
|
|
@ -8,6 +8,7 @@
|
||||||
"@paralleldrive/cuid2": "^2.2.2",
|
"@paralleldrive/cuid2": "^2.2.2",
|
||||||
"@types/mime-types": "^2.1.2",
|
"@types/mime-types": "^2.1.2",
|
||||||
"esbuild": "^0.19.4",
|
"esbuild": "^0.19.4",
|
||||||
|
"lmdb": "^2.8.5",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"msgpackr": "^1.9.9",
|
"msgpackr": "^1.9.9",
|
||||||
"radix3": "^1.1.0"
|
"radix3": "^1.1.0"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { component, site, page } from "dbgen";
|
import { component, site, page } from "dbgen";
|
||||||
|
|
||||||
|
|
||||||
export const SyncActions = {
|
export const SyncActions = {
|
||||||
site: {
|
site: {
|
||||||
all: () =>
|
all: () =>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { user } from "../user";
|
||||||
|
|
||||||
|
export const syncEditorLoad = async (user_id: string) => {
|
||||||
|
const conf = user.conf.get(user_id);
|
||||||
|
if (conf) {
|
||||||
|
if (!conf.site_id) {
|
||||||
|
const site = await db.site.findFirst({
|
||||||
|
where: {
|
||||||
|
id_user: user_id,
|
||||||
|
is_deleted: false,
|
||||||
|
},
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
if (site) conf.site_id = site.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf.site_id && !conf.page_id) {
|
||||||
|
const page = await db.page.findFirst({
|
||||||
|
select: { id: true },
|
||||||
|
where: {
|
||||||
|
id_site: conf.site_id,
|
||||||
|
is_deleted: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (page) {
|
||||||
|
conf.page_id = page.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -2,6 +2,7 @@ import { createId } from "@paralleldrive/cuid2";
|
||||||
import { ServerWebSocket, WebSocketHandler } from "bun";
|
import { ServerWebSocket, WebSocketHandler } from "bun";
|
||||||
import { Packr } from "msgpackr";
|
import { Packr } from "msgpackr";
|
||||||
import { WSData } from "../../../../pkgs/core/server/create";
|
import { WSData } from "../../../../pkgs/core/server/create";
|
||||||
|
import { SyncType } from "./type";
|
||||||
const packr = new Packr({ structuredClone: true });
|
const packr = new Packr({ structuredClone: true });
|
||||||
|
|
||||||
const conns = new Map<
|
const conns = new Map<
|
||||||
|
|
@ -25,7 +26,7 @@ export const syncHandler: WebSocketHandler<WSData> = {
|
||||||
msg: { pending: {}, resolve: {} },
|
msg: { pending: {}, resolve: {} },
|
||||||
});
|
});
|
||||||
wconns.set(ws, client_id);
|
wconns.set(ws, client_id);
|
||||||
ws.sendBinary(packr.pack({ type: "client_id", client_id }));
|
ws.sendBinary(packr.pack({ type: SyncType.ClientID, client_id }));
|
||||||
},
|
},
|
||||||
close(ws, code, reason) {
|
close(ws, code, reason) {
|
||||||
const conn_id = wconns.get(ws);
|
const conn_id = wconns.get(ws);
|
||||||
|
|
@ -40,7 +41,7 @@ export const syncHandler: WebSocketHandler<WSData> = {
|
||||||
const conn = conns.get(conn_id);
|
const conn = conns.get(conn_id);
|
||||||
if (conn) {
|
if (conn) {
|
||||||
const msg = packr.unpack(Buffer.from(raw));
|
const msg = packr.unpack(Buffer.from(raw));
|
||||||
if (msg.type === "user_id") {
|
if (msg.type === SyncType.UserID) {
|
||||||
const { user_id } = msg;
|
const { user_id } = msg;
|
||||||
conn.user_id = user_id;
|
conn.user_id = user_id;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum SyncType {
|
||||||
|
ClientID,
|
||||||
|
UserID,
|
||||||
|
Event
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { dir } from "dir";
|
||||||
|
import { open } from "lmdb";
|
||||||
|
import { g } from "utils/global";
|
||||||
|
|
||||||
|
const defaultConf = {
|
||||||
|
site_id: "",
|
||||||
|
page_id: "",
|
||||||
|
};
|
||||||
|
type UserConf = typeof defaultConf;
|
||||||
|
|
||||||
|
const db = open<UserConf, string>({
|
||||||
|
name: "user-conf",
|
||||||
|
path: dir.path(`${g.datadir}/lmdb/user-conf.lmdb`),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const user = {
|
||||||
|
conf: {
|
||||||
|
get(user_id: string) {
|
||||||
|
return db.get(user_id);
|
||||||
|
},
|
||||||
|
set<T extends keyof UserConf>(user_id: string, key: T, value: UserConf[T]) {
|
||||||
|
let current = this.get(user_id);
|
||||||
|
if (!current) {
|
||||||
|
db.put(user_id, structuredClone(defaultConf));
|
||||||
|
current = this.get(user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current) {
|
||||||
|
db.put(user_id, { ...current, [key]: value });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -6,13 +6,17 @@ export default page({
|
||||||
url: "**",
|
url: "**",
|
||||||
component: ({}) => {
|
component: ({}) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (localStorage.getItem("prasi-session")) {
|
if (localStorage.getItem("prasi-session")) {
|
||||||
navigate("/editor/");
|
if (location.pathname.startsWith("/ed/")) {
|
||||||
|
navigate("/ed/_/_");
|
||||||
|
} else {
|
||||||
|
navigate("/editor/_/_");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
navigate("/login");
|
navigate("/login");
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
import { FC, useEffect } from "react";
|
|
||||||
import { page, useGlobal, useLocal } from "web-utils";
|
|
||||||
import { EditorGlobal } from "../../render/editor/logic/global";
|
|
||||||
import { Loading } from "../../utils/ui/loading";
|
|
||||||
|
|
||||||
export default page({
|
|
||||||
url: "/editor/**",
|
|
||||||
component: ({}) => {
|
|
||||||
const p = useGlobal(EditorGlobal, "EDITOR");
|
|
||||||
|
|
||||||
const local = useLocal({
|
|
||||||
loading: true,
|
|
||||||
session: null as any,
|
|
||||||
notfound: false,
|
|
||||||
init: false,
|
|
||||||
});
|
|
||||||
const site_id = params.site_id === "_" ? "" : params.site_id;
|
|
||||||
const page_id = params.page_id === "_" ? "" : params.page_id;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!local.init) {
|
|
||||||
(async () => {
|
|
||||||
let ses: any = null;
|
|
||||||
try {
|
|
||||||
ses = JSON.parse(localStorage.getItem("prasi-session") || "");
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
await new Promise<void>(async (done) => {
|
|
||||||
try {
|
|
||||||
if (!!ses) {
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
let e = await api.session();
|
|
||||||
if (!e) {
|
|
||||||
(window as any).redirectTo = location.pathname;
|
|
||||||
navigate("/login");
|
|
||||||
localStorage.removeItem("prasi-session");
|
|
||||||
} else {
|
|
||||||
localStorage.setItem("prasi-session", JSON.stringify(e));
|
|
||||||
}
|
|
||||||
if (!ses) {
|
|
||||||
ses = e;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ses) {
|
|
||||||
local.session = ses;
|
|
||||||
|
|
||||||
if (!site_id) {
|
|
||||||
const res = await db.site.findFirst({
|
|
||||||
where: {
|
|
||||||
is_deleted: false,
|
|
||||||
org: {
|
|
||||||
org_user: {
|
|
||||||
some: { id_user: ses.data.user.id },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (res) {
|
|
||||||
const page = await db.page.findFirst({
|
|
||||||
where: {
|
|
||||||
id_site: res.id,
|
|
||||||
is_deleted: false,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (page) {
|
|
||||||
local.loading = false;
|
|
||||||
local.render();
|
|
||||||
navigate(`/editor/${res.id}/${page.id}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
local.loading = false;
|
|
||||||
local.render();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (!page_id) {
|
|
||||||
let res = await db.page.findFirst({
|
|
||||||
where: {
|
|
||||||
id_site: site_id,
|
|
||||||
is_deleted: false,
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
id: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
res = await db.page.create({
|
|
||||||
data: {
|
|
||||||
content_tree: {
|
|
||||||
childs: [],
|
|
||||||
id: "root",
|
|
||||||
type: "root",
|
|
||||||
},
|
|
||||||
name: "home",
|
|
||||||
url: "/",
|
|
||||||
id_site: site_id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
local.loading = false;
|
|
||||||
local.render();
|
|
||||||
navigate(`/editor/${site_id}/${res.id}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
navigate(`/editor/${site_id}/${page_id}`);
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
}, [local.init]);
|
|
||||||
|
|
||||||
return <Loading note="base-page" />;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
@ -2,11 +2,12 @@ import { page, useGlobal } from "web-utils";
|
||||||
import { EditorGlobal } from "../../render/editor/logic/global";
|
import { EditorGlobal } from "../../render/editor/logic/global";
|
||||||
import { Loading } from "../../utils/ui/loading";
|
import { Loading } from "../../utils/ui/loading";
|
||||||
import { clientStartSync } from "../../utils/sync/client";
|
import { clientStartSync } from "../../utils/sync/client";
|
||||||
|
import { EDGlobal } from "../../render/ed/logic/global";
|
||||||
|
|
||||||
export default page({
|
export default page({
|
||||||
url: "/ned/:site_id/:page_id",
|
url: "/ed/:site_id/:page_id",
|
||||||
component: ({}) => {
|
component: ({}) => {
|
||||||
const p = useGlobal(EditorGlobal, "EDITOR");
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
|
||||||
const session = JSON.parse(
|
const session = JSON.parse(
|
||||||
localStorage.getItem("prasi-session") || "null"
|
localStorage.getItem("prasi-session") || "null"
|
||||||
|
|
@ -17,9 +18,10 @@ export default page({
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p.sync) {
|
if (!p.sync) {
|
||||||
// p.sync = clientStartSync({
|
p.sync = clientStartSync({
|
||||||
// user_id: session.data.user.id,
|
user_id: session.data.user.id,
|
||||||
// });
|
events: { editor_start() {} },
|
||||||
|
});
|
||||||
|
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,6 @@ export const all = {
|
||||||
url: "**",
|
url: "**",
|
||||||
page: () => import("./page/all"),
|
page: () => import("./page/all"),
|
||||||
};
|
};
|
||||||
export const ed = {
|
|
||||||
url: "/editor/**",
|
|
||||||
page: () => import("./page/ed"),
|
|
||||||
};
|
|
||||||
export const editor = {
|
export const editor = {
|
||||||
url: "/editor/:site_id/:page_id",
|
url: "/editor/:site_id/:page_id",
|
||||||
page: () => import("./page/editor"),
|
page: () => import("./page/editor"),
|
||||||
|
|
@ -27,6 +23,6 @@ export const live = {
|
||||||
page: () => import("./page/live"),
|
page: () => import("./page/live"),
|
||||||
};
|
};
|
||||||
export const ned = {
|
export const ned = {
|
||||||
url: "/ned/:site_id/:page_id",
|
url: "/ed/:site_id/:page_id",
|
||||||
page: () => import("./page/ned"),
|
page: () => import("./page/ned"),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { clientStartSync } from "../../../utils/sync/client";
|
||||||
|
|
||||||
|
export const EDGlobal = {
|
||||||
|
sync: null as unknown as ReturnType<typeof clientStartSync>,
|
||||||
|
};
|
||||||
|
|
@ -6,6 +6,7 @@ import { stringify } from "safe-stable-stringify";
|
||||||
import { SyncActions } from "../../../../srv/ws/sync/actions";
|
import { SyncActions } from "../../../../srv/ws/sync/actions";
|
||||||
import { SyncActionDefinition } from "../../../../srv/ws/sync/actions-def";
|
import { SyncActionDefinition } from "../../../../srv/ws/sync/actions-def";
|
||||||
import { initIDB } from "./idb";
|
import { initIDB } from "./idb";
|
||||||
|
import { SyncType } from "../../../../srv/ws/sync/type";
|
||||||
const packr = new Packr({ structuredClone: true });
|
const packr = new Packr({ structuredClone: true });
|
||||||
const conf = {
|
const conf = {
|
||||||
ws: null as null | WebSocket,
|
ws: null as null | WebSocket,
|
||||||
|
|
@ -21,7 +22,11 @@ type User = {
|
||||||
export const clientStartSync = async (arg: {
|
export const clientStartSync = async (arg: {
|
||||||
user_id: string;
|
user_id: string;
|
||||||
events: {
|
events: {
|
||||||
site_open: (arg: { site_id: string; user: User }) => void;
|
editor_start: (arg: {
|
||||||
|
user_id: string;
|
||||||
|
site_id?: string;
|
||||||
|
page_id?: string;
|
||||||
|
}) => void;
|
||||||
};
|
};
|
||||||
}) => {
|
}) => {
|
||||||
const { user_id, events } = arg;
|
const { user_id, events } = arg;
|
||||||
|
|
@ -69,15 +74,16 @@ const connect = (user_id: string) => {
|
||||||
const ws = new WebSocket(url.toString());
|
const ws = new WebSocket(url.toString());
|
||||||
conf.ws = ws;
|
conf.ws = ws;
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
ws.send(packr.pack({ type: "user_id", user_id }));
|
ws.send(packr.pack({ type: SyncType.UserID, user_id }));
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onmessage = async (e) => {
|
ws.onmessage = async (e) => {
|
||||||
const raw = e.data as Blob;
|
const raw = e.data as Blob;
|
||||||
const msg = packr.unpack(Buffer.from(await raw.arrayBuffer()));
|
const msg = packr.unpack(Buffer.from(await raw.arrayBuffer()));
|
||||||
if (msg.type === "client_id") {
|
if (msg.type === SyncType.ClientID) {
|
||||||
conf.client_id = msg.client_id;
|
conf.client_id = msg.client_id;
|
||||||
resolve(ws);
|
resolve(ws);
|
||||||
|
} else if (msg.type === "event") {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue