fix
This commit is contained in:
parent
faed51c613
commit
64491439c3
|
|
@ -9,6 +9,7 @@
|
||||||
"@types/mime-types": "^2.1.2",
|
"@types/mime-types": "^2.1.2",
|
||||||
"esbuild": "^0.19.4",
|
"esbuild": "^0.19.4",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
|
"msgpackr": "^1.9.9",
|
||||||
"radix3": "^1.1.0"
|
"radix3": "^1.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { svLocal } from "./edit/action/sv-local";
|
||||||
import { svdiffRemote } from "./edit/action/svdiff-remote";
|
import { svdiffRemote } from "./edit/action/svdiff-remote";
|
||||||
import { redo, undo } from "./edit/action/undo-redo";
|
import { redo, undo } from "./edit/action/undo-redo";
|
||||||
import { eg } from "./edit/edit-global";
|
import { eg } from "./edit/edit-global";
|
||||||
|
import { syncHandler } from "./sync/sync-handler";
|
||||||
|
|
||||||
eg.edit = {
|
eg.edit = {
|
||||||
site: {},
|
site: {},
|
||||||
|
|
@ -21,6 +22,7 @@ const site = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const wsHandler: Record<string, WebSocketHandler<WSData>> = {
|
export const wsHandler: Record<string, WebSocketHandler<WSData>> = {
|
||||||
|
"/sync": syncHandler,
|
||||||
"/edit": {
|
"/edit": {
|
||||||
open(ws) {
|
open(ws) {
|
||||||
eg.edit.ws.set(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",
|
"@paralleldrive/cuid2": "2.2.2",
|
||||||
"@parcel/packager-wasm": "^2.10.0",
|
"@parcel/packager-wasm": "^2.10.0",
|
||||||
"@parcel/service-worker": "^2.10.0",
|
"@parcel/service-worker": "^2.10.0",
|
||||||
|
"msgpackr": "^1.9.9",
|
||||||
"@swc/wasm-web": "1.3.94-nightly-20231014.1",
|
"@swc/wasm-web": "1.3.94-nightly-20231014.1",
|
||||||
"algoliasearch": "^4.20.0",
|
"algoliasearch": "^4.20.0",
|
||||||
"date-fns": "^2.30.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