fix
This commit is contained in:
parent
faed51c613
commit
64491439c3
|
|
@ -9,6 +9,7 @@
|
|||
"@types/mime-types": "^2.1.2",
|
||||
"esbuild": "^0.19.4",
|
||||
"mime-types": "^2.1.35",
|
||||
"msgpackr": "^1.9.9",
|
||||
"radix3": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { svLocal } from "./edit/action/sv-local";
|
|||
import { svdiffRemote } from "./edit/action/svdiff-remote";
|
||||
import { redo, undo } from "./edit/action/undo-redo";
|
||||
import { eg } from "./edit/edit-global";
|
||||
import { syncHandler } from "./sync/sync-handler";
|
||||
|
||||
eg.edit = {
|
||||
site: {},
|
||||
|
|
@ -21,6 +22,7 @@ const site = {
|
|||
};
|
||||
|
||||
export const wsHandler: Record<string, WebSocketHandler<WSData>> = {
|
||||
"/sync": syncHandler,
|
||||
"/edit": {
|
||||
open(ws) {
|
||||
eg.edit.ws.set(ws, {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
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";
|
||||
const packr = new Packr({ structuredClone: true });
|
||||
|
||||
const conns = new Map<
|
||||
string,
|
||||
{
|
||||
ws: ServerWebSocket<WSData>;
|
||||
msg: {
|
||||
pending: Record<string, Promise<any>>;
|
||||
resolve: Record<string, (result: any) => void>;
|
||||
};
|
||||
}
|
||||
>();
|
||||
const wconns = new WeakMap<ServerWebSocket<WSData>, string>();
|
||||
export const syncHandler: WebSocketHandler<WSData> = {
|
||||
open(ws) {
|
||||
const id = createId();
|
||||
conns.set(id, { ws, msg: { pending: {}, resolve: {} } });
|
||||
wconns.set(ws, id);
|
||||
ws.sendBinary(packr.pack({ type: "identify", id }));
|
||||
},
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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;
|
||||
};
|
||||
|
|
@ -13,6 +13,7 @@
|
|||
"@paralleldrive/cuid2": "2.2.2",
|
||||
"@parcel/packager-wasm": "^2.10.0",
|
||||
"@parcel/service-worker": "^2.10.0",
|
||||
"msgpackr": "^1.9.9",
|
||||
"@swc/wasm-web": "1.3.94-nightly-20231014.1",
|
||||
"algoliasearch": "^4.20.0",
|
||||
"date-fns": "^2.30.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
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";
|
||||
const packr = new Packr({ structuredClone: true });
|
||||
|
||||
export class SyncClient {
|
||||
private id = "";
|
||||
private ws: WebSocket;
|
||||
private wsPending?: Promise<void>;
|
||||
public connected = false;
|
||||
public loaded = {
|
||||
site: new Map<string, SyncSite>(),
|
||||
};
|
||||
|
||||
public site = {
|
||||
load: async (id: string) => {
|
||||
this.loaded.site.set(id, new SyncSite(this, id));
|
||||
},
|
||||
};
|
||||
|
||||
public _internal = {
|
||||
msg: {
|
||||
pending: {} as Record<string, Promise<any>>,
|
||||
resolve: {} as Record<string, (result: any) => 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;
|
||||
}
|
||||
|
||||
this.ws.send(packr.pack({ ...msg, msg_client_id: createId() }));
|
||||
},
|
||||
};
|
||||
|
||||
constructor(ws: WebSocket) {
|
||||
this.ws = ws;
|
||||
}
|
||||
|
||||
private static instance = null as SyncClient | null;
|
||||
static connect() {
|
||||
if (SyncClient.instance) return SyncClient.instance;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
if (!client.id) {
|
||||
if (msg.action === ClientAction.Identify) {
|
||||
client.id = msg.id;
|
||||
client.connected = true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
};
|
||||
|
||||
return client;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { DType, ServerAction } from "../../../../srv/ws/sync/type";
|
||||
import { SyncClient } from "./client";
|
||||
|
||||
export class SyncSite {
|
||||
private c: SyncClient;
|
||||
private id = "";
|
||||
public status = "loading" as "loading" | "ready";
|
||||
|
||||
constructor(c: SyncClient, id: string) {
|
||||
this.c = c;
|
||||
c._internal.send({ type: DType.Site, action: ServerAction.Load, id });
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue