@textea/y-socket.io
Version:
Socket.io Connector for Yjs
109 lines (100 loc) • 4.15 kB
TypeScript
import { Server } from 'http';
import { Socket, Server as Server$1 } from 'socket.io';
import { Room as Room$1 } from 'socket.io-adapter';
import { Awareness } from 'y-protocols/awareness';
import * as Y from 'yjs';
import { CorsOptions, CorsOptionsDelegate } from 'cors';
import { ServerOptions } from 'engine.io/build/server';
declare type RoomName = Room$1;
declare type ClientId = Awareness['clientID'];
interface DefaultClientData {
}
declare type EventHandler = (...args: any[]) => void;
declare type DefaultEvents = {
[eventName: string]: EventHandler;
};
declare type EventNameWithScope<Scope extends string, Type extends string = string> = `${Scope}:${Type}`;
declare type DataScope = 'data';
declare type RoomScope = 'room';
declare type YDocScope = 'doc';
declare type AwarenessScope = 'awareness';
declare type ObservableScope = YDocScope | AwarenessScope;
declare type ValidEventScope = DataScope | RoomScope | ObservableScope;
declare type ValidateEvents<Events extends DefaultEvents & {
[EventName in keyof Events]: EventName extends EventNameWithScope<infer EventScope> ? EventScope extends ValidEventScope ? Events[EventName] : never : Events[EventName];
}> = Events;
declare type DefaultServerToClientEvents<ClientData extends DefaultClientData = DefaultClientData> = ValidateEvents<{
['data:update']: (data: ClientData) => void;
['doc:diff']: (diff: ArrayBuffer) => void;
['doc:update']: (updateV2: ArrayBuffer) => void;
['awareness:update']: (update: ArrayBuffer) => void;
}>;
interface ServerToClientEvents<ClientData extends DefaultClientData = DefaultClientData> extends DefaultServerToClientEvents<ClientData> {
}
declare type DefaultClientToServerEvents = ValidateEvents<{
['room:close']: () => void;
['doc:diff']: (diff: Uint8Array) => void;
['doc:update']: (updateV2: Uint8Array, callback?: () => void) => void;
['awareness:update']: (update: Uint8Array) => void;
}>;
interface ClientToServerEvents extends DefaultClientToServerEvents {
}
interface Persistence {
bindState: (roomName: RoomName, doc: Y.Doc) => Promise<void>;
writeState: (roomName: RoomName, doc: Y.Doc) => Promise<void>;
}
declare type UserId = string | ClientId;
declare type GetUserId = (socket: Omit<Socket, 'userId'>) => UserId | Error;
interface Room {
owner: UserId;
awareness: Awareness;
getDoc: () => Promise<Y.Doc>;
destroy: () => Promise<void>;
}
declare type RoomMap = Map<RoomName, Room>;
declare module 'socket.io' {
/**
* Data related to yjs
*/
interface SocketYjsData {
roomMap: RoomMap;
roomName: RoomName;
clientId: ClientId;
}
interface Socket {
yjs: SocketYjsData;
userId: UserId;
}
}
interface Options {
/**
* Handle auth and room permission
*/
getUserId?: GetUserId;
persistence?: Persistence;
/**
* @default false
*/
autoDeleteRoom?: boolean;
/**
* cors settings
*/
cors?: CorsOptions | CorsOptionsDelegate;
allowRequest?: ServerOptions['allowRequest'];
}
declare type CreateSocketIOServer = <ClientData extends DefaultClientData = DefaultClientData>(httpServer: Server, options?: Options) => Server$1<ClientToServerEvents, ServerToClientEvents<ClientData>>;
/**
* There are four scenarios:
* 1. Signed User share sheet to specified person with write permission (both side need authorization)
* 2. Signed User share sheet to specified person with only view permission (both side need authorization)
* 3. Signed User share sheet to everyone with write permission (only one side need authorization)
* 4. Signed User share sheet to everyone with only view permission (only one side need authorization)
*
* If sheet owner close sharing (or disable sharing), others won't see the sheet anymore,
* which means we will delete the sheet in their browser.
*
* We only consider scenario 3 for now, because It's easy to implement
*/
declare const createSocketIOServer: CreateSocketIOServer;
declare const createSimpleServer: (options?: Options) => Server;
export { Options, createSimpleServer, createSocketIOServer };