fix loading
This commit is contained in:
parent
812802a429
commit
214ffd84a8
|
|
@ -11,6 +11,9 @@
|
||||||
"lmdb": "^2.8.5",
|
"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",
|
||||||
|
"y-pojo": "^0.0.8",
|
||||||
|
"yjs": "^13.6.8",
|
||||||
|
"yjs-types": "^0.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ export const svLocal = async (ws: any, msg: WS_MSG_SV_LOCAL) => {
|
||||||
if (doc) {
|
if (doc) {
|
||||||
const diff_remote = Y.encodeStateAsUpdate(doc, changes);
|
const diff_remote = Y.encodeStateAsUpdate(doc, changes);
|
||||||
const sv_remote = Y.encodeStateVector(doc);
|
const sv_remote = Y.encodeStateVector(doc);
|
||||||
|
|
||||||
const sendmsg: WS_MSG_SVDIFF_REMOTE = {
|
const sendmsg: WS_MSG_SVDIFF_REMOTE = {
|
||||||
diff_remote: diff_remote.toString(),
|
diff_remote: diff_remote.toString(),
|
||||||
sv_remote: sv_remote.toString(),
|
sv_remote: sv_remote.toString(),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { component, site, page } from "dbgen";
|
import { component, page } from "dbgen";
|
||||||
import { ESite } from "../../../web/src/render/ed/logic/ed-global";
|
import { EPage, ESite } from "../../../web/src/render/ed/logic/ed-global";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
WARNING:
|
WARNING:
|
||||||
|
|
@ -15,7 +15,7 @@ export const SyncActions = {
|
||||||
list: async () =>
|
list: async () =>
|
||||||
({}) as Record<string, { id: string; name: string; domain: string }>,
|
({}) as Record<string, { id: string; name: string; domain: string }>,
|
||||||
group: async () => ({}) as Record<string, string[]>,
|
group: async () => ({}) as Record<string, string[]>,
|
||||||
load: async (id: string) => ({}) as ESite | undefined,
|
load: async (id: string) => ({}) as ESite | void,
|
||||||
},
|
},
|
||||||
comp: {
|
comp: {
|
||||||
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
list: () => ({}) as Record<string, Exclude<component, "content_tree">>,
|
||||||
|
|
@ -25,6 +25,6 @@ export const SyncActions = {
|
||||||
page: {
|
page: {
|
||||||
list: (id_site: string) =>
|
list: (id_site: string) =>
|
||||||
({}) as Record<string, Exclude<page, "content_tree">>,
|
({}) as Record<string, Exclude<page, "content_tree">>,
|
||||||
load: (id: string) => ({}) as Uint8Array,
|
load: async (id: string) => ({}) as EPage | void,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
export * from "./site_load";
|
export * from "./site_load";
|
||||||
export * from "./site_group";
|
export * from "./site_group";
|
||||||
|
export * from "./page_load";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import { syncronize } from "y-pojo";
|
||||||
|
import { SAction } from "../actions";
|
||||||
|
import { Y, docs } from "../entity/docs";
|
||||||
|
import { snapshot } from "../entity/snapshot";
|
||||||
|
import { ActionCtx } from "../type";
|
||||||
|
|
||||||
|
export const page_load: SAction["page"]["load"] = async function (
|
||||||
|
this: ActionCtx,
|
||||||
|
id: string
|
||||||
|
) {
|
||||||
|
let ss = snapshot.get("page", id);
|
||||||
|
let ydoc = docs.page[id];
|
||||||
|
|
||||||
|
if (!ss || !ydoc) {
|
||||||
|
const page = await db.page.findFirst({ where: { id } });
|
||||||
|
if (page) {
|
||||||
|
const doc = new Y.Doc();
|
||||||
|
let root = doc.getMap("map");
|
||||||
|
syncronize(root, { id, root: page.content_tree });
|
||||||
|
|
||||||
|
const um = new Y.UndoManager(root, { ignoreRemoteMapChanges: true });
|
||||||
|
docs.page[id] = {
|
||||||
|
doc: doc as any,
|
||||||
|
id,
|
||||||
|
um,
|
||||||
|
};
|
||||||
|
|
||||||
|
const bin = Y.encodeStateAsUpdate(doc);
|
||||||
|
snapshot.set({
|
||||||
|
bin,
|
||||||
|
id,
|
||||||
|
type: "page",
|
||||||
|
name: page.name,
|
||||||
|
ts: Date.now(),
|
||||||
|
url: page.url,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
url: page.url,
|
||||||
|
name: page.name,
|
||||||
|
snapshot: bin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ss) {
|
||||||
|
return {
|
||||||
|
id: ss.id,
|
||||||
|
url: ss.url,
|
||||||
|
name: ss.name,
|
||||||
|
snapshot: ss.bin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { user } from "../user";
|
import { user } from "../entity/user";
|
||||||
|
|
||||||
export const loadDefaultSite = async (user_id: string) => {
|
export const loadDefaultSite = async (user_id: string) => {
|
||||||
const conf = user.conf.get(user_id);
|
const conf = user.conf.get(user_id);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as Y from "yjs";
|
||||||
|
import { TypedDoc, TypedMap } from "yjs-types";
|
||||||
|
import { MItem } from "../../../../web/src/utils/types/item";
|
||||||
|
import { DPage } from "../../../../web/src/utils/types/root";
|
||||||
|
export * as Y from "yjs";
|
||||||
|
|
||||||
|
export const docs = {
|
||||||
|
page: {} as Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
doc: DPage;
|
||||||
|
um: Y.UndoManager;
|
||||||
|
}
|
||||||
|
>,
|
||||||
|
comp: {} as Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
doc: TypedDoc<{ map: TypedMap<{ id: string; item: MItem }> }>;
|
||||||
|
um: Y.UndoManager;
|
||||||
|
}
|
||||||
|
>,
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { dir } from "dir";
|
||||||
|
import { RootDatabase, open } from "lmdb";
|
||||||
|
import { g } from "utils/global";
|
||||||
|
|
||||||
|
const emptySnapshot = {
|
||||||
|
type: "" as "" | "comp" | "page",
|
||||||
|
id: "",
|
||||||
|
bin: new Uint8Array(),
|
||||||
|
url: "",
|
||||||
|
name: "",
|
||||||
|
ts: Date.now(),
|
||||||
|
};
|
||||||
|
export type DocSnapshot = typeof emptySnapshot;
|
||||||
|
|
||||||
|
export const snapshot = {
|
||||||
|
_db: null as null | RootDatabase<DocSnapshot>,
|
||||||
|
init() {
|
||||||
|
this._db = open<DocSnapshot, string>({
|
||||||
|
name: "user-conf",
|
||||||
|
path: dir.path(`${g.datadir}/lmdb/doc-snapshot.lmdb`),
|
||||||
|
});
|
||||||
|
return this._db;
|
||||||
|
},
|
||||||
|
get db() {
|
||||||
|
if (!this._db) {
|
||||||
|
this._db = this.init();
|
||||||
|
}
|
||||||
|
return this._db;
|
||||||
|
},
|
||||||
|
getOrCreate(data: DocSnapshot) {
|
||||||
|
const id = `${data.type}-${data.id}`;
|
||||||
|
let res = this.db.get(id);
|
||||||
|
if (!res) {
|
||||||
|
this.db.put(id, structuredClone(emptySnapshot));
|
||||||
|
res = this.db.get(id);
|
||||||
|
}
|
||||||
|
return res as DocSnapshot;
|
||||||
|
},
|
||||||
|
get(type: string, id: string) {
|
||||||
|
return this.db.get(`${type}-${id}`);
|
||||||
|
},
|
||||||
|
set(data: DocSnapshot) {
|
||||||
|
const id = `${data.type}-${data.id}`;
|
||||||
|
this.db.put(id, data);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@ -16,13 +16,11 @@ export const user = {
|
||||||
name: "user-conf",
|
name: "user-conf",
|
||||||
path: dir.path(`${g.datadir}/lmdb/user-conf.lmdb`),
|
path: dir.path(`${g.datadir}/lmdb/user-conf.lmdb`),
|
||||||
});
|
});
|
||||||
|
return this._db;
|
||||||
},
|
},
|
||||||
get db() {
|
get db() {
|
||||||
if (!this._db) {
|
if (!this._db) {
|
||||||
this._db = open<UserConf, string>({
|
this._db = this.init();
|
||||||
name: "user-conf",
|
|
||||||
path: dir.path(`${g.datadir}/lmdb/user-conf.lmdb`),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return this._db;
|
return this._db;
|
||||||
},
|
},
|
||||||
|
|
@ -7,7 +7,7 @@ import { loadDefaultSite } from "./editor/load";
|
||||||
import { ActionCtx, SyncType } from "./type";
|
import { ActionCtx, SyncType } from "./type";
|
||||||
import { SyncActionPaths } from "./actions-def";
|
import { SyncActionPaths } from "./actions-def";
|
||||||
import * as actions from "./actions/index";
|
import * as actions from "./actions/index";
|
||||||
import { UserConf, user } from "./user";
|
import { UserConf, user } from "./entity/user";
|
||||||
const packr = new Packr({ structuredClone: true });
|
const packr = new Packr({ structuredClone: true });
|
||||||
|
|
||||||
const conns = new Map<
|
const conns = new Map<
|
||||||
|
|
@ -79,17 +79,23 @@ export const syncHandler: WebSocketHandler<WSData> = {
|
||||||
const code = msg.code as keyof typeof SyncActionPaths;
|
const code = msg.code as keyof typeof SyncActionPaths;
|
||||||
const actionName = SyncActionPaths[code].replace(/\./gi, "_");
|
const actionName = SyncActionPaths[code].replace(/\./gi, "_");
|
||||||
if (actionName) {
|
if (actionName) {
|
||||||
const action = (actions as any)[actionName].bind({
|
const baseAction = (actions as any)[actionName];
|
||||||
user: { id: conn.user_id, conf: conn.conf },
|
if (!baseAction) {
|
||||||
} as ActionCtx);
|
console.log(`app/ws/edit/sync/${actionName}.ts not found}`);
|
||||||
|
}
|
||||||
|
if (baseAction) {
|
||||||
|
const action = baseAction.bind({
|
||||||
|
user: { id: conn.user_id, conf: conn.conf },
|
||||||
|
} as ActionCtx);
|
||||||
|
|
||||||
ws.sendBinary(
|
ws.sendBinary(
|
||||||
packr.pack({
|
packr.pack({
|
||||||
type: SyncType.ActionResult,
|
type: SyncType.ActionResult,
|
||||||
argid: msg.argid,
|
argid: msg.argid,
|
||||||
val: await action(...msg.args),
|
val: await action(...msg.args),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { UserConf } from "./user";
|
import { UserConf } from "./entity/user";
|
||||||
|
|
||||||
export enum SyncType {
|
export enum SyncType {
|
||||||
ClientID,
|
ClientID,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
"esbuild-wasm": "^0.19.4",
|
"esbuild-wasm": "^0.19.4",
|
||||||
"hash-wasm": "^4.10.0",
|
"hash-wasm": "^4.10.0",
|
||||||
"idb-keyval": "^6.2.1",
|
"idb-keyval": "^6.2.1",
|
||||||
|
"immer": "^10.0.3",
|
||||||
"js-base64": "^3.7.5",
|
"js-base64": "^3.7.5",
|
||||||
"lodash.capitalize": "^4.2.1",
|
"lodash.capitalize": "^4.2.1",
|
||||||
"lodash.concat": "^4.5.0",
|
"lodash.concat": "^4.5.0",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { page, useGlobal } from "web-utils";
|
import { page, useGlobal } from "web-utils";
|
||||||
import { Loading } from "../../utils/ui/loading";
|
|
||||||
import { bootEd } from "../../render/ed/ed";
|
|
||||||
import { EDGlobal } from "../../render/ed/logic/ed-global";
|
import { EDGlobal } from "../../render/ed/logic/ed-global";
|
||||||
|
import { edInitSync } from "../../render/ed/logic/ed-sync";
|
||||||
|
import { Loading } from "../../utils/ui/loading";
|
||||||
|
|
||||||
export default page({
|
export default page({
|
||||||
url: "**",
|
url: "**",
|
||||||
|
|
@ -14,7 +14,7 @@ export default page({
|
||||||
location.pathname === "/ed" ||
|
location.pathname === "/ed" ||
|
||||||
location.pathname.startsWith("/ed/")
|
location.pathname.startsWith("/ed/")
|
||||||
) {
|
) {
|
||||||
bootEd(p);
|
edInitSync(p);
|
||||||
} else if (location.pathname.startsWith("/editor")) {
|
} else if (location.pathname.startsWith("/editor")) {
|
||||||
const arr = location.pathname.split("/");
|
const arr = location.pathname.split("/");
|
||||||
if (arr.length <= 2) {
|
if (arr.length <= 2) {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,19 @@
|
||||||
import { page, useGlobal } from "web-utils";
|
import { page, useGlobal } from "web-utils";
|
||||||
import { Ed, bootEd } from "../../render/ed/ed";
|
import { EdBase } from "../../render/ed/ed-base";
|
||||||
import { EDGlobal } from "../../render/ed/logic/ed-global";
|
import { EDGlobal } from "../../render/ed/logic/ed-global";
|
||||||
import { Loading } from "../../utils/ui/loading";
|
import { Loading } from "../../utils/ui/loading";
|
||||||
|
import { initSync } from "wasm-gzip";
|
||||||
|
import { edInitSync } from "../../render/ed/logic/ed-sync";
|
||||||
|
|
||||||
export default page({
|
export default page({
|
||||||
url: "/ed/:site_id/:page_id",
|
url: "/ed/:site_id/:page_id",
|
||||||
component: ({}) => {
|
component: ({}) => {
|
||||||
const p = useGlobal(EDGlobal, "EDITOR");
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
|
||||||
if (!bootEd(p)) {
|
if (!edInitSync(p)) {
|
||||||
return <Loading note="booting editor" />;
|
return <Loading note="init sync" />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Ed />;
|
return <EdBase />;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ import { Root } from "./base/root";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api";
|
import { createAPI, createDB, reloadDBAPI } from "./utils/script/init-api";
|
||||||
import { w } from "./utils/types/general";
|
import { w } from "./utils/types/general";
|
||||||
|
import * as Y from "yjs";
|
||||||
|
|
||||||
|
(window as any).Y = Y;
|
||||||
|
|
||||||
const start = async () => {
|
const start = async () => {
|
||||||
const base = `${location.protocol}//${location.host}`;
|
const base = `${location.protocol}//${location.host}`;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { useGlobal } from "web-utils";
|
||||||
|
import { Loading } from "../../utils/ui/loading";
|
||||||
|
import { EDGlobal } from "./logic/ed-global";
|
||||||
|
import { edRoute } from "./logic/ed-route";
|
||||||
|
|
||||||
|
export const EdBase = () => {
|
||||||
|
const p = useGlobal(EDGlobal, "EDITOR");
|
||||||
|
|
||||||
|
if (p.status === "init") {
|
||||||
|
p.status = "ready";
|
||||||
|
}
|
||||||
|
|
||||||
|
edRoute(p);
|
||||||
|
|
||||||
|
if (p.status === "loading") {
|
||||||
|
return <Loading note="loading-page" />;
|
||||||
|
}
|
||||||
|
if (p.status === "site-not-found" || p.status === "page-not-found") {
|
||||||
|
return (
|
||||||
|
<div className="flex fixed inset-0 items-center justify-center">
|
||||||
|
{p.status === "site-not-found" ? "Site not found" : "Page not found"}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div>Editor</div>;
|
||||||
|
};
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import { clientStartSync } from "../../../utils/sync/client";
|
import { clientStartSync } from "../../../utils/sync/client";
|
||||||
|
import { IItem } from "../../../utils/types/item";
|
||||||
|
import { DPage, IRoot } from "../../../utils/types/root";
|
||||||
|
|
||||||
const EmptySite = {
|
const EmptySite = {
|
||||||
id: "",
|
id: "",
|
||||||
|
|
@ -9,8 +11,13 @@ const EmptySite = {
|
||||||
config: { api_url: "" },
|
config: { api_url: "" },
|
||||||
};
|
};
|
||||||
export type ESite = typeof EmptySite;
|
export type ESite = typeof EmptySite;
|
||||||
|
export type EPage = typeof EmptyPage;
|
||||||
|
|
||||||
const EmptyPage = {
|
const EmptyPage = {
|
||||||
id: "",
|
id: "",
|
||||||
|
name: "",
|
||||||
|
url: "",
|
||||||
|
snapshot: null as null | Uint8Array,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EDGlobal = {
|
export const EDGlobal = {
|
||||||
|
|
@ -22,7 +29,11 @@ export const EDGlobal = {
|
||||||
| "ready",
|
| "ready",
|
||||||
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,
|
sync: null as unknown as Awaited<ReturnType<typeof clientStartSync>>,
|
||||||
site: EmptySite,
|
site: EmptySite,
|
||||||
page: EmptyPage,
|
page: {
|
||||||
|
current: EmptyPage,
|
||||||
|
doc: null as null | DPage,
|
||||||
|
root: null as null | IRoot,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PG = typeof EDGlobal & { render: () => void };
|
export type PG = typeof EDGlobal & { render: () => void };
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
import { IRoot } from "../../../utils/types/root";
|
||||||
import { PG } from "./ed-global";
|
import { PG } from "./ed-global";
|
||||||
|
import { produce } from "immer";
|
||||||
export const edRoute = async (p: PG) => {
|
export const edRoute = async (p: PG) => {
|
||||||
if (p.status === "init") {
|
if (p.status === "ready") {
|
||||||
if (!p.site.domain && !p.site.name) {
|
if (!p.site.domain && !p.site.name) {
|
||||||
p.status = "loading";
|
p.status = "loading";
|
||||||
const site = await p.sync.site.load(p.site.id);
|
const site = await p.sync.site.load(p.site.id);
|
||||||
|
|
@ -14,8 +15,31 @@ export const edRoute = async (p: PG) => {
|
||||||
p.site = site;
|
p.site = site;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.site) {
|
if (p.page.current.id !== params.page_id || !p.page.current.snapshot) {
|
||||||
console.log(p.site);
|
p.status = "loading";
|
||||||
|
const page = await p.sync.page.load(params.page_id);
|
||||||
|
|
||||||
|
if (!page) {
|
||||||
|
p.status = "page-not-found";
|
||||||
|
p.render();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.page.current = page;
|
||||||
|
if (page.snapshot) {
|
||||||
|
const doc = new Y.Doc();
|
||||||
|
Y.applyUpdate(doc, page.snapshot);
|
||||||
|
p.page.doc = doc as any;
|
||||||
|
|
||||||
|
if (p.page.doc) {
|
||||||
|
const root = p.page.doc.getMap("map").get("root")?.toJSON() as IRoot;
|
||||||
|
if (root) {
|
||||||
|
p.page.root = produce(root, () => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.status = "ready";
|
||||||
|
p.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,8 @@
|
||||||
import { useGlobal } from "web-utils";
|
import { clientStartSync } from "../../../utils/sync/client";
|
||||||
import { Loading } from "../../utils/ui/loading";
|
import { Loading } from "../../../utils/ui/loading";
|
||||||
import { EDGlobal, PG } from "./logic/ed-global";
|
import { PG } from "./ed-global";
|
||||||
import { edRoute } from "./logic/ed-route";
|
|
||||||
import { clientStartSync } from "../../utils/sync/client";
|
|
||||||
|
|
||||||
export const Ed = () => {
|
export const edInitSync = (p: PG) => {
|
||||||
const p = useGlobal(EDGlobal, "EDITOR");
|
|
||||||
|
|
||||||
edRoute(p);
|
|
||||||
|
|
||||||
if (p.status === "loading") {
|
|
||||||
return <Loading />;
|
|
||||||
}
|
|
||||||
if (p.status === "site-not-found" || p.status === "page-not-found") {
|
|
||||||
return (
|
|
||||||
<div className="flex fixed inset-0 items-center justify-center">
|
|
||||||
{p.status === "site-not-found" ? "Site not found" : "Page not found"}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return <div>asfa</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const bootEd = (p: PG) => {
|
|
||||||
const session = JSON.parse(
|
const session = JSON.parse(
|
||||||
localStorage.getItem("prasi-session") || "null"
|
localStorage.getItem("prasi-session") || "null"
|
||||||
) as { data: { user: { id: string } } };
|
) as { data: { user: { id: string } } };
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { IItem } from "../../../../utils/types/item";
|
||||||
|
import { ISection } from "../../../../utils/types/section";
|
||||||
|
import { PG } from "../ed-global";
|
||||||
|
|
||||||
|
export const treeRebuild = (items: (ISection | IItem)[]) => {};
|
||||||
|
|
@ -4,7 +4,10 @@ import { UseStore, get, set } from "idb-keyval";
|
||||||
import { Packr } from "msgpackr";
|
import { Packr } from "msgpackr";
|
||||||
import { stringify } from "safe-stable-stringify";
|
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,
|
||||||
|
SyncActionPaths,
|
||||||
|
} from "../../../../srv/ws/sync/actions-def";
|
||||||
import { initIDB } from "./idb";
|
import { initIDB } from "./idb";
|
||||||
import { SyncType } from "../../../../srv/ws/sync/type";
|
import { SyncType } from "../../../../srv/ws/sync/type";
|
||||||
import { w } from "../types/general";
|
import { w } from "../types/general";
|
||||||
|
|
@ -48,31 +51,23 @@ export const clientStartSync = async (arg: {
|
||||||
const { user_id, events } = arg;
|
const { user_id, events } = arg;
|
||||||
conf.idb = initIDB(user_id);
|
conf.idb = initIDB(user_id);
|
||||||
await connect(user_id, events);
|
await connect(user_id, events);
|
||||||
const path: any[] = [];
|
|
||||||
return new DeepProxy(
|
return new DeepProxy(
|
||||||
SyncActionDefinition,
|
SyncActionDefinition,
|
||||||
({ trapName, value, key, DEFAULT, PROXY }) => {
|
({ target, trapName, value, key, DEFAULT, PROXY }) => {
|
||||||
if (trapName === "set") {
|
if (trapName === "set") {
|
||||||
throw new TypeError("target is immutable");
|
throw new TypeError("target is immutable");
|
||||||
}
|
}
|
||||||
|
|
||||||
path.push(key);
|
|
||||||
if (typeof value === "string") {
|
if (typeof value === "string") {
|
||||||
for (let i = 0; i < path.length; i++) {
|
return (...args: any[]) => {
|
||||||
if (path[i] !== "then") {
|
return new Promise((resolve) => {
|
||||||
path.splice(0, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (...args: any[]) =>
|
|
||||||
new Promise((resolve) => {
|
|
||||||
doAction({
|
doAction({
|
||||||
path: path.join("."),
|
|
||||||
code: value,
|
code: value,
|
||||||
resolve,
|
resolve,
|
||||||
args,
|
args,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trapName === "get") {
|
if (trapName === "get") {
|
||||||
|
|
@ -168,16 +163,16 @@ const loadEventOffline = async (name: ClientEvent) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const doAction = async <T>(arg: {
|
const doAction = async <T>(arg: {
|
||||||
path: string;
|
|
||||||
code: string;
|
code: string;
|
||||||
resolve: (value: any) => void;
|
resolve: (value: any) => void;
|
||||||
args: any[];
|
args: any[];
|
||||||
}) => {
|
}) => {
|
||||||
const { path, args, code, resolve } = arg;
|
const { args, code, resolve } = arg;
|
||||||
const ws = conf.ws;
|
const ws = conf.ws;
|
||||||
const idb = conf.idb;
|
const idb = conf.idb;
|
||||||
if (idb) {
|
if (idb) {
|
||||||
const sargs = stringify(args);
|
const sargs = stringify(args);
|
||||||
|
const path = (SyncActionPaths as any)[code];
|
||||||
const argid = await xxhash32(`op-${path}-${sargs}`);
|
const argid = await xxhash32(`op-${path}-${sargs}`);
|
||||||
|
|
||||||
if (ws && ws.readyState === ws.OPEN) {
|
if (ws && ws.readyState === ws.OPEN) {
|
||||||
|
|
@ -186,6 +181,7 @@ const doAction = async <T>(arg: {
|
||||||
ts: Date.now(),
|
ts: Date.now(),
|
||||||
resolve,
|
resolve,
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.send(packr.pack({ type: SyncType.Action, code, args, argid }));
|
ws.send(packr.pack({ type: SyncType.Action, code, args, argid }));
|
||||||
} else {
|
} else {
|
||||||
// offline
|
// offline
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { TypedArray, TypedMap } from "yjs-types";
|
import { TypedArray, TypedDoc, TypedMap } from "yjs-types";
|
||||||
import { ISection } from "./section";
|
import { ISection } from "./section";
|
||||||
|
|
||||||
export type IRoot = {
|
export type IRoot = {
|
||||||
|
|
@ -12,3 +12,5 @@ export type MRoot = TypedMap<{
|
||||||
type: "root";
|
type: "root";
|
||||||
childs: TypedArray<ISection>;
|
childs: TypedArray<ISection>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
export type DPage = TypedDoc<{ map: TypedMap<{ id: string; root: MRoot }> }>;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ import { g } from "./utils/global";
|
||||||
import { createLogger } from "./utils/logger";
|
import { createLogger } from "./utils/logger";
|
||||||
import { preparePrisma } from "./utils/prisma";
|
import { preparePrisma } from "./utils/prisma";
|
||||||
import { syncActionDefinition } from "utils/sync-def";
|
import { syncActionDefinition } from "utils/sync-def";
|
||||||
import { user } from "../../app/srv/ws/sync/user";
|
import { user } from "../../app/srv/ws/sync/entity/user";
|
||||||
|
import { snapshot } from "../../app/srv/ws/sync/entity/snapshot";
|
||||||
|
|
||||||
g.status = "init";
|
g.status = "init";
|
||||||
|
|
||||||
|
|
@ -24,7 +25,10 @@ if (g.mode === "dev") {
|
||||||
await startDevWatcher();
|
await startDevWatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** init lmdb */
|
||||||
user.conf.init();
|
user.conf.init();
|
||||||
|
snapshot.init();
|
||||||
|
|
||||||
await preparePrisma();
|
await preparePrisma();
|
||||||
await ensureNotRunning();
|
await ensureNotRunning();
|
||||||
|
|
||||||
|
|
@ -37,8 +41,8 @@ if (g.db) {
|
||||||
await syncActionDefinition();
|
await syncActionDefinition();
|
||||||
await generateAPIFrm();
|
await generateAPIFrm();
|
||||||
await prepareApiRoutes();
|
await prepareApiRoutes();
|
||||||
await createServer();
|
|
||||||
await prepareAPITypes();
|
await prepareAPITypes();
|
||||||
await parcelBuild();
|
await parcelBuild();
|
||||||
|
await createServer();
|
||||||
|
|
||||||
g.status = "ready";
|
g.status = "ready";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import goober from "goober";
|
import goober from "goober";
|
||||||
import type { PrismaClient } from "../../../app/db/db";
|
import type { PrismaClient } from "../../../app/db/db";
|
||||||
|
import * as Yjs from "yjs";
|
||||||
declare global {
|
declare global {
|
||||||
const navigate: (path: string) => void;
|
const navigate: (path: string) => void;
|
||||||
const params: any;
|
const params: any;
|
||||||
|
|
@ -9,5 +10,6 @@ declare global {
|
||||||
const db: PrismaClient;
|
const db: PrismaClient;
|
||||||
const prasiContext: any;
|
const prasiContext: any;
|
||||||
const serverurl: string;
|
const serverurl: string;
|
||||||
|
const Y: typeof Yjs;
|
||||||
}
|
}
|
||||||
export {};
|
export {};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue