@hocuspocus/server
Advanced tools
Comparing version 1.0.0-alpha.63 to 1.0.0-alpha.64
@@ -6,2 +6,14 @@ # Change Log | ||
# [1.0.0-alpha.64](https://github.com/ueberdosis/hocuspocus/compare/@hocuspocus/server@1.0.0-alpha.63...@hocuspocus/server@1.0.0-alpha.64) (2021-08-27) | ||
### Bug Fixes | ||
* Empty sync message causes error in client MessageReceiver ([#174](https://github.com/ueberdosis/hocuspocus/issues/174)) ([f9dca69](https://github.com/ueberdosis/hocuspocus/commit/f9dca69eb96d1ede37a0709bd3b7735bf1ff57ba)) | ||
* Potential onCreateDocument race condition ([#167](https://github.com/ueberdosis/hocuspocus/issues/167)) ([b3e3e4d](https://github.com/ueberdosis/hocuspocus/commit/b3e3e4dea74f9b833ccb0c6a6521f55c001411c1)) | ||
# [1.0.0-alpha.63](https://github.com/ueberdosis/hocuspocus/compare/@hocuspocus/server@1.0.0-alpha.62...@hocuspocus/server@1.0.0-alpha.63) (2021-08-19) | ||
@@ -8,0 +20,0 @@ |
@@ -423,2 +423,3 @@ import WebSocket from 'ws'; | ||
(function (MessageType) { | ||
MessageType[MessageType["Unknown"] = -1] = "Unknown"; | ||
MessageType[MessageType["Sync"] = 0] = "Sync"; | ||
@@ -1260,11 +1261,50 @@ MessageType[MessageType["Awareness"] = 1] = "Awareness"; | ||
} | ||
this.encoder = createEncoder(); | ||
this.decoder = createDecoder(input); | ||
} | ||
readSyncMessageAndApplyItTo(document, connection) { | ||
writeVarUint(this.encoder, MessageType.Sync); | ||
// this is a copy of the original y-protocols/sync/readSyncMessage function | ||
// which enables the read only mode | ||
switch (this.type) { | ||
readVarUint8Array() { | ||
return readVarUint8Array(this.decoder); | ||
} | ||
readVarUint() { | ||
return readVarUint(this.decoder); | ||
} | ||
toUint8Array() { | ||
return toUint8Array(this.encoder); | ||
} | ||
writeVarUint(type) { | ||
writeVarUint(this.encoder, type); | ||
} | ||
get length() { | ||
return length$1(this.encoder); | ||
} | ||
} | ||
class MessageReceiver { | ||
constructor(message) { | ||
this.message = message; | ||
} | ||
apply(connection) { | ||
const { document } = connection; | ||
const { message } = this; | ||
const type = message.readVarUint(); | ||
switch (type) { | ||
case MessageType.Sync: | ||
message.writeVarUint(MessageType.Sync); | ||
this.readSyncMessage(message, connection); | ||
if (message.length > 1) { | ||
connection.send(message.toUint8Array()); | ||
} | ||
break; | ||
case MessageType.Awareness: | ||
applyAwarenessUpdate(document.awareness, message.readVarUint8Array(), connection); | ||
break; | ||
// Do nothing | ||
} | ||
} | ||
readSyncMessage(message, connection) { | ||
const { document } = connection; | ||
const type = message.readVarUint(); | ||
switch (type) { | ||
case messageYjsSyncStep1: | ||
readSyncStep1(this.decoder, this.encoder, document); | ||
readSyncStep1(message.decoder, message.encoder, document); | ||
break; | ||
@@ -1275,3 +1315,3 @@ case messageYjsSyncStep2: | ||
} | ||
readSyncStep2(this.decoder, document, connection); | ||
readSyncStep2(message.decoder, document, null); | ||
break; | ||
@@ -1282,33 +1322,9 @@ case messageYjsUpdate: | ||
} | ||
readUpdate(this.decoder, document, connection); | ||
readUpdate(message.decoder, document, null); | ||
break; | ||
// TODO: Shouldn’t crash the whole server, | ||
// remove or catch exceptions in the top level? | ||
// throw new Error('Unknown message type') | ||
default: | ||
throw new Error(`Received a message with an unknown type: ${type}`); | ||
} | ||
return type; | ||
} | ||
readUint8Array() { | ||
return readVarUint8Array(this.decoder); | ||
} | ||
toUint8Array() { | ||
return toUint8Array(this.encoder); | ||
} | ||
get length() { | ||
return length$1(this.encoder); | ||
} | ||
get type() { | ||
try { | ||
return readVarUint(this.decoder); | ||
} | ||
catch { | ||
// Failed read the message type | ||
return -1; | ||
} | ||
} | ||
get encoder() { | ||
if (!this.syncMessageEncoder) { | ||
this.syncMessageEncoder = createEncoder(); | ||
} | ||
return this.syncMessageEncoder; | ||
} | ||
} | ||
@@ -1421,13 +1437,4 @@ | ||
*/ | ||
handleMessage(input) { | ||
const message = new IncomingMessage(input); | ||
if (message.type === MessageType.Awareness) { | ||
this.document.applyAwarenessUpdate(this, message.readUint8Array()); | ||
return; | ||
} | ||
message.readSyncMessageAndApplyItTo(this.document, this); | ||
if (message.length <= 1) { | ||
return; | ||
} | ||
return this.send(message.toUint8Array()); | ||
handleMessage(data) { | ||
new MessageReceiver(new IncomingMessage(data)).apply(this); | ||
} | ||
@@ -1449,3 +1456,3 @@ /** | ||
var description = "plug & play collaboration backend"; | ||
var version = "1.0.0-alpha.62"; | ||
var version = "1.0.0-alpha.63"; | ||
var homepage = "https://hocuspocus.dev"; | ||
@@ -1551,3 +1558,5 @@ var keywords = [ | ||
get authenticationRequired() { | ||
return this.configuration.onAuthenticate !== undefined; | ||
return !!this.configuration.extensions.find(extension => { | ||
return extension.onAuthenticate !== undefined; | ||
}); | ||
} | ||
@@ -1722,34 +1731,29 @@ /** | ||
async createDocument(documentName, request, socketId, context) { | ||
return new Promise(resolve => { | ||
if (this.documents.has(documentName)) { | ||
const document = this.documents.get(documentName); | ||
return resolve(document); | ||
if (this.documents.has(documentName)) { | ||
const document = this.documents.get(documentName); | ||
return document; | ||
} | ||
const document = new Document(documentName); | ||
this.documents.set(documentName, document); | ||
const hookPayload = { | ||
context, | ||
document, | ||
documentName, | ||
socketId, | ||
requestHeaders: request.headers, | ||
requestParameters: Hocuspocus.getParameters(request), | ||
}; | ||
await this.hooks('onCreateDocument', hookPayload, (loadedDocument) => { | ||
// if a hook returns a Y-Doc, encode the document state as update | ||
// and apply it to the newly created document | ||
// Note: instanceof doesn't work, because Doc !== Doc for some reason I don't understand | ||
if ((loadedDocument === null || loadedDocument === void 0 ? void 0 : loadedDocument.constructor.name) === 'Document' | ||
|| (loadedDocument === null || loadedDocument === void 0 ? void 0 : loadedDocument.constructor.name) === 'Doc') { | ||
applyUpdate(document, encodeStateAsUpdate(loadedDocument)); | ||
} | ||
const document = new Document(documentName); | ||
document.onUpdate((document, connection, update) => { | ||
this.handleDocumentUpdate(document, connection, update, request, connection === null || connection === void 0 ? void 0 : connection.socketId); | ||
}); | ||
const hookPayload = { | ||
context, | ||
document, | ||
documentName, | ||
socketId, | ||
requestHeaders: request.headers, | ||
requestParameters: Hocuspocus.getParameters(request), | ||
}; | ||
this.hooks('onCreateDocument', hookPayload, (loadedDocument) => { | ||
// if a hook returns a Y-Doc, encode the document state as update | ||
// and apply it to the newly created document | ||
// Note: instanceof doesn't work, because Doc !== Doc for some reason I don't understand | ||
if ((loadedDocument === null || loadedDocument === void 0 ? void 0 : loadedDocument.constructor.name) === 'Document' | ||
|| (loadedDocument === null || loadedDocument === void 0 ? void 0 : loadedDocument.constructor.name) === 'Doc') { | ||
applyUpdate(document, encodeStateAsUpdate(loadedDocument)); | ||
} | ||
}).then(() => { | ||
resolve(document); | ||
}).catch(e => { | ||
throw e; | ||
}); | ||
this.documents.set(documentName, document); | ||
}); | ||
document.onUpdate((document, connection, update) => { | ||
this.handleDocumentUpdate(document, connection, update, request, connection === null || connection === void 0 ? void 0 : connection.socketId); | ||
}); | ||
return document; | ||
} | ||
@@ -1756,0 +1760,0 @@ /** |
/// <reference types="node" /> | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDestroyPayload, onDisconnectPayload, onListenPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDisconnectPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { IncomingMessage, ServerResponse } from 'http'; | ||
@@ -37,5 +37,3 @@ import WebSocket from 'ws'; | ||
onChange(data: onChangePayload): Promise<void>; | ||
onListen(data: onListenPayload): Promise<void>; | ||
onDestroy(data: onDestroyPayload): Promise<void>; | ||
onConfigure(data: onConfigurePayload): Promise<void>; | ||
} |
@@ -41,2 +41,3 @@ import * as Y from 'yjs'; | ||
onDestroy: () => void; | ||
onAwarenessUpdate: (states: any) => void; | ||
onAwarenessChange: (states: any) => void; | ||
@@ -43,0 +44,0 @@ debug: boolean; |
@@ -1,11 +0,13 @@ | ||
import * as decoding from 'lib0/decoding'; | ||
import * as encoding from 'lib0/encoding'; | ||
import { Decoder } from 'lib0/decoding'; | ||
import { Encoder } from 'lib0/encoding'; | ||
import { MessageType } from './types'; | ||
export declare class IncomingMessage { | ||
data: any; | ||
encoder: encoding.Encoder; | ||
decoder: decoding.Decoder; | ||
type: MessageType; | ||
encoder: Encoder; | ||
decoder: Decoder; | ||
constructor(data: any); | ||
get name(): string; | ||
readVarUint(): MessageType; | ||
readVarUint8Array(): Uint8Array; | ||
writeVarUint(type: MessageType): void; | ||
writeVarUint8Array(data: Uint8Array): void; | ||
} |
@@ -1,2 +0,1 @@ | ||
import * as encoding from 'lib0/encoding'; | ||
import { HocuspocusProvider } from './HocuspocusProvider'; | ||
@@ -7,3 +6,3 @@ import { IncomingMessage } from './IncomingMessage'; | ||
constructor(message: IncomingMessage); | ||
apply(provider: HocuspocusProvider, emitSynced?: boolean): encoding.Encoder; | ||
apply(provider: HocuspocusProvider, emitSynced?: boolean): void; | ||
private applySyncMessage; | ||
@@ -10,0 +9,0 @@ private applyAwarenessMessage; |
@@ -1,2 +0,2 @@ | ||
import * as encoding from 'lib0/encoding'; | ||
import { Encoder } from 'lib0/encoding'; | ||
import { AuthenticationMessage } from './OutgoingMessages/AuthenticationMessage'; | ||
@@ -10,3 +10,3 @@ import { AwarenessMessage } from './OutgoingMessages/AwarenessMessage'; | ||
export declare class MessageSender { | ||
encoder: encoding.Encoder; | ||
encoder: Encoder; | ||
message: any; | ||
@@ -13,0 +13,0 @@ constructor(Message: Constructable<AuthenticationMessage> | Constructable<AwarenessMessage> | Constructable<QueryAwarenessMessage> | Constructable<SyncStepOneMessage> | Constructable<SyncStepTwoMessage> | Constructable<UpdateMessage>, args?: any); |
@@ -1,8 +0,8 @@ | ||
import * as encoding from 'lib0/encoding'; | ||
import { Encoder } from 'lib0/encoding'; | ||
import { MessageType, OutgoingMessageInterface } from './types'; | ||
export declare class OutgoingMessage implements OutgoingMessageInterface { | ||
encoder: encoding.Encoder; | ||
encoder: Encoder; | ||
type?: MessageType; | ||
constructor(); | ||
get name(): string; | ||
toUint8Array(): Uint8Array; | ||
} |
@@ -1,2 +0,1 @@ | ||
import * as encoding from 'lib0/encoding'; | ||
import { MessageType, OutgoingMessageArguments } from '../types'; | ||
@@ -7,3 +6,3 @@ import { OutgoingMessage } from '../OutgoingMessage'; | ||
description: string; | ||
get(args: Partial<OutgoingMessageArguments>): encoding.Encoder; | ||
get(args: Partial<OutgoingMessageArguments>): import("lib0/encoding").Encoder; | ||
} |
@@ -1,2 +0,1 @@ | ||
import * as encoding from 'lib0/encoding'; | ||
import { MessageType, OutgoingMessageArguments } from '../types'; | ||
@@ -7,3 +6,3 @@ import { OutgoingMessage } from '../OutgoingMessage'; | ||
description: string; | ||
get(args: Partial<OutgoingMessageArguments>): encoding.Encoder; | ||
get(args: Partial<OutgoingMessageArguments>): import("lib0/encoding").Encoder; | ||
} |
import { RedisPersistence } from 'y-redis'; | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDestroyPayload, onDisconnectPayload, onListenPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { Extension, onConnectPayload, onCreateDocumentPayload, onDisconnectPayload } from '@hocuspocus/server'; | ||
export interface Configuration { | ||
@@ -15,9 +15,3 @@ } | ||
onConnect(data: onConnectPayload): Promise<void>; | ||
onChange(data: onChangePayload): Promise<void>; | ||
onDisconnect(data: onDisconnectPayload): Promise<void>; | ||
onListen(data: onListenPayload): Promise<void>; | ||
onDestroy(data: onDestroyPayload): Promise<void>; | ||
onConfigure(data: onConfigurePayload): Promise<void>; | ||
onRequest(data: onRequestPayload): Promise<void>; | ||
onUpgrade(data: onUpgradePayload): Promise<void>; | ||
} |
@@ -1,2 +0,2 @@ | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDestroyPayload, onDisconnectPayload, onListenPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { Extension, onCreateDocumentPayload } from '@hocuspocus/server'; | ||
import { LeveldbPersistence } from 'y-leveldb'; | ||
@@ -22,10 +22,2 @@ export interface Configuration { | ||
store(documentName: string, update: Uint8Array): Promise<any>; | ||
onChange(data: onChangePayload): Promise<void>; | ||
onConnect(data: onConnectPayload): Promise<void>; | ||
onDisconnect(data: onDisconnectPayload): Promise<void>; | ||
onListen(data: onListenPayload): Promise<void>; | ||
onDestroy(data: onDestroyPayload): Promise<void>; | ||
onConfigure(data: onConfigurePayload): Promise<void>; | ||
onRequest(data: onRequestPayload): Promise<void>; | ||
onUpgrade(data: onUpgradePayload): Promise<void>; | ||
} |
import { Decoder } from 'lib0/decoding'; | ||
import { Encoder } from 'lib0/encoding'; | ||
import Document from './Document'; | ||
import Connection from './Connection'; | ||
import { MessageType } from './types'; | ||
export declare class IncomingMessage { | ||
/** | ||
* Access to the received message. | ||
*/ | ||
decoder: Decoder; | ||
syncMessageEncoder?: Encoder; | ||
/** | ||
* Access to the reply. | ||
*/ | ||
encoder: Encoder; | ||
constructor(input: any); | ||
readSyncMessageAndApplyItTo(document: Document, connection?: Connection): void; | ||
readUint8Array(): Uint8Array; | ||
readVarUint8Array(): Uint8Array; | ||
readVarUint(): number; | ||
toUint8Array(): Uint8Array; | ||
writeVarUint(type: MessageType): void; | ||
get length(): number; | ||
get type(): number; | ||
private get encoder(); | ||
} |
@@ -7,2 +7,3 @@ /// <reference types="node" /> | ||
export declare enum MessageType { | ||
Unknown = -1, | ||
Sync = 0, | ||
@@ -23,11 +24,11 @@ Awareness = 1, | ||
onAuthenticate?(data: onAuthenticatePayload): Promise<any>; | ||
onChange(data: onChangePayload): Promise<any>; | ||
onConnect(data: onConnectPayload): Promise<any>; | ||
onConfigure(data: onConfigurePayload): Promise<any>; | ||
onCreateDocument(data: onCreateDocumentPayload): Promise<any>; | ||
onDestroy(data: onDestroyPayload): Promise<any>; | ||
onDisconnect(data: onDisconnectPayload): Promise<any>; | ||
onListen(data: onListenPayload): Promise<any>; | ||
onRequest(data: onRequestPayload): Promise<any>; | ||
onUpgrade(data: onUpgradePayload): Promise<any>; | ||
onChange?(data: onChangePayload): Promise<any>; | ||
onConnect?(data: onConnectPayload): Promise<any>; | ||
onConfigure?(data: onConfigurePayload): Promise<any>; | ||
onCreateDocument?(data: onCreateDocumentPayload): Promise<any>; | ||
onDestroy?(data: onDestroyPayload): Promise<any>; | ||
onDisconnect?(data: onDisconnectPayload): Promise<any>; | ||
onListen?(data: onListenPayload): Promise<any>; | ||
onRequest?(data: onRequestPayload): Promise<any>; | ||
onUpgrade?(data: onUpgradePayload): Promise<any>; | ||
} | ||
@@ -34,0 +35,0 @@ export interface Configuration extends Extension { |
@@ -1,2 +0,2 @@ | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDestroyPayload, onDisconnectPayload, onListenPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { Extension, onConnectPayload } from '@hocuspocus/server'; | ||
export interface Configuration { | ||
@@ -20,10 +20,2 @@ throttle: number | null | false; | ||
onConnect(data: onConnectPayload): Promise<any>; | ||
onCreateDocument(data: onCreateDocumentPayload): Promise<void>; | ||
onChange(data: onChangePayload): Promise<void>; | ||
onDisconnect(data: onDisconnectPayload): Promise<void>; | ||
onUpgrade(data: onUpgradePayload): Promise<void>; | ||
onRequest(data: onRequestPayload): Promise<void>; | ||
onListen(data: onListenPayload): Promise<void>; | ||
onDestroy(data: onDestroyPayload): Promise<void>; | ||
onConfigure(data: onConfigurePayload): Promise<void>; | ||
} |
/// <reference types="node" /> | ||
import { Extension, onChangePayload, onConfigurePayload, onConnectPayload, onCreateDocumentPayload, onDestroyPayload, onDisconnectPayload, onListenPayload, onRequestPayload, onUpgradePayload } from '@hocuspocus/server'; | ||
import { Extension, onChangePayload, onConnectPayload, onCreateDocumentPayload, onDisconnectPayload } from '@hocuspocus/server'; | ||
import { Doc } from 'yjs'; | ||
@@ -59,7 +59,2 @@ import { Transformer } from '@hocuspocus/transformer'; | ||
onDisconnect(data: onDisconnectPayload): Promise<void>; | ||
onUpgrade(data: onUpgradePayload): Promise<void>; | ||
onRequest(data: onRequestPayload): Promise<void>; | ||
onListen(data: onListenPayload): Promise<void>; | ||
onDestroy(data: onDestroyPayload): Promise<void>; | ||
onConfigure(data: onConfigurePayload): Promise<void>; | ||
} |
{ | ||
"name": "@hocuspocus/server", | ||
"description": "plug & play collaboration backend", | ||
"version": "1.0.0-alpha.63", | ||
"version": "1.0.0-alpha.64", | ||
"homepage": "https://hocuspocus.dev", | ||
@@ -35,3 +35,3 @@ "keywords": [ | ||
}, | ||
"gitHead": "13bb2b38c5887bb09c2b6565754888092c8e345b" | ||
"gitHead": "d8938e5d42a85a8d447e7e63fd5e2bf4f18a7d2d" | ||
} |
@@ -7,4 +7,5 @@ import AsyncLock from 'async-lock' | ||
import { IncomingMessage } from './IncomingMessage' | ||
import { MessageType, WsReadyStates } from './types' | ||
import { WsReadyStates } from './types' | ||
import { OutgoingMessage } from './OutgoingMessage' | ||
import { MessageReceiver } from './MessageReceiver' | ||
@@ -170,20 +171,6 @@ class Connection { | ||
*/ | ||
private handleMessage(input: Iterable<number>): void { | ||
const message = new IncomingMessage(input) | ||
if (message.type === MessageType.Awareness) { | ||
this.document.applyAwarenessUpdate(this, message.readUint8Array()) | ||
return | ||
} | ||
message.readSyncMessageAndApplyItTo(this.document, this) | ||
if (message.length <= 1) { | ||
return | ||
} | ||
return this.send( | ||
message.toUint8Array(), | ||
) | ||
private handleMessage(data: Iterable<number>): void { | ||
new MessageReceiver( | ||
new IncomingMessage(data), | ||
).apply(this) | ||
} | ||
@@ -190,0 +177,0 @@ |
@@ -79,3 +79,5 @@ import * as decoding from 'lib0/decoding' | ||
get authenticationRequired(): boolean { | ||
return this.configuration.onAuthenticate !== undefined | ||
return !!this.configuration.extensions.find(extension => { | ||
return extension.onAuthenticate !== undefined | ||
}) | ||
} | ||
@@ -279,41 +281,36 @@ | ||
private async createDocument(documentName: string, request: IncomingMessage, socketId: string, context?: any): Promise<Document> { | ||
return new Promise(resolve => { | ||
if (this.documents.has(documentName)) { | ||
const document = this.documents.get(documentName) | ||
return resolve(document) | ||
} | ||
if (this.documents.has(documentName)) { | ||
const document = this.documents.get(documentName) | ||
return document | ||
} | ||
const document = new Document(documentName) | ||
const document = new Document(documentName) | ||
this.documents.set(documentName, document) | ||
document.onUpdate((document, connection, update) => { | ||
this.handleDocumentUpdate(document, connection, update, request, connection?.socketId) | ||
}) | ||
const hookPayload = { | ||
context, | ||
document, | ||
documentName, | ||
socketId, | ||
requestHeaders: request.headers, | ||
requestParameters: Hocuspocus.getParameters(request), | ||
} | ||
const hookPayload = { | ||
context, | ||
document, | ||
documentName, | ||
socketId, | ||
requestHeaders: request.headers, | ||
requestParameters: Hocuspocus.getParameters(request), | ||
} | ||
this.hooks('onCreateDocument', hookPayload, (loadedDocument: Doc | undefined) => { | ||
await this.hooks('onCreateDocument', hookPayload, (loadedDocument: Doc | undefined) => { | ||
// if a hook returns a Y-Doc, encode the document state as update | ||
// and apply it to the newly created document | ||
// Note: instanceof doesn't work, because Doc !== Doc for some reason I don't understand | ||
if ( | ||
loadedDocument?.constructor.name === 'Document' | ||
if ( | ||
loadedDocument?.constructor.name === 'Document' | ||
|| loadedDocument?.constructor.name === 'Doc' | ||
) { | ||
applyUpdate(document, encodeStateAsUpdate(loadedDocument)) | ||
} | ||
}).then(() => { | ||
resolve(document) | ||
}).catch(e => { | ||
throw e | ||
}) | ||
) { | ||
applyUpdate(document, encodeStateAsUpdate(loadedDocument)) | ||
} | ||
}) | ||
this.documents.set(documentName, document) | ||
document.onUpdate((document: Document, connection: Connection, update: Uint8Array) => { | ||
this.handleDocumentUpdate(document, connection, update, request, connection?.socketId) | ||
}) | ||
return document | ||
} | ||
@@ -320,0 +317,0 @@ |
@@ -10,24 +10,18 @@ import { | ||
Encoder, | ||
toUint8Array, | ||
writeVarUint, | ||
length, | ||
writeVarUint, | ||
toUint8Array, | ||
} from 'lib0/encoding' | ||
import { | ||
messageYjsSyncStep1, | ||
messageYjsSyncStep2, | ||
messageYjsUpdate, | ||
readSyncStep1, | ||
readSyncStep2, | ||
readUpdate, | ||
} from 'y-protocols/sync' | ||
import Document from './Document' | ||
import { MessageType } from './types' | ||
import Connection from './Connection' | ||
export class IncomingMessage { | ||
/** | ||
* Access to the received message. | ||
*/ | ||
decoder: Decoder | ||
syncMessageEncoder?: Encoder | ||
/** | ||
* Access to the reply. | ||
*/ | ||
encoder: Encoder | ||
@@ -39,66 +33,25 @@ constructor(input: any) { | ||
this.encoder = createEncoder() | ||
this.decoder = createDecoder(input) | ||
} | ||
readSyncMessageAndApplyItTo(document: Document, connection?: Connection): void { | ||
writeVarUint(this.encoder, MessageType.Sync) | ||
// this is a copy of the original y-protocols/sync/readSyncMessage function | ||
// which enables the read only mode | ||
switch (this.type) { | ||
case messageYjsSyncStep1: | ||
readSyncStep1(this.decoder, this.encoder, document) | ||
break | ||
case messageYjsSyncStep2: | ||
if (connection?.readOnly) { | ||
break | ||
} | ||
readSyncStep2(this.decoder, document, connection) | ||
break | ||
case messageYjsUpdate: | ||
if (connection?.readOnly) { | ||
break | ||
} | ||
readUpdate(this.decoder, document, connection) | ||
break | ||
default: | ||
// TODO: Shouldn’t crash the whole server, | ||
// remove or catch exceptions in the top level? | ||
// throw new Error('Unknown message type') | ||
} | ||
readVarUint8Array() { | ||
return readVarUint8Array(this.decoder) | ||
} | ||
readUint8Array(): Uint8Array { | ||
return readVarUint8Array(this.decoder) | ||
readVarUint() { | ||
return readVarUint(this.decoder) | ||
} | ||
toUint8Array(): Uint8Array { | ||
toUint8Array() { | ||
return toUint8Array(this.encoder) | ||
} | ||
writeVarUint(type: MessageType) { | ||
writeVarUint(this.encoder, type) | ||
} | ||
get length(): number { | ||
return length(this.encoder) | ||
} | ||
get type(): number { | ||
try { | ||
return readVarUint(this.decoder) | ||
} catch { | ||
// Failed read the message type | ||
return -1 | ||
} | ||
} | ||
private get encoder() { | ||
if (!this.syncMessageEncoder) { | ||
this.syncMessageEncoder = createEncoder() | ||
} | ||
return this.syncMessageEncoder | ||
} | ||
} |
@@ -9,2 +9,3 @@ import { | ||
export enum MessageType { | ||
Unknown = -1, | ||
Sync = 0, | ||
@@ -28,11 +29,11 @@ Awareness = 1, | ||
onAuthenticate?(data: onAuthenticatePayload): Promise<any>, | ||
onChange(data: onChangePayload): Promise<any>, | ||
onConnect(data: onConnectPayload): Promise<any>, | ||
onConfigure(data: onConfigurePayload): Promise<any>, | ||
onCreateDocument(data: onCreateDocumentPayload): Promise<any>, | ||
onDestroy(data: onDestroyPayload): Promise<any>, | ||
onDisconnect(data: onDisconnectPayload): Promise<any> | ||
onListen(data: onListenPayload): Promise<any>, | ||
onRequest(data: onRequestPayload): Promise<any>, | ||
onUpgrade(data: onUpgradePayload): Promise<any>, | ||
onChange?(data: onChangePayload): Promise<any>, | ||
onConnect?(data: onConnectPayload): Promise<any>, | ||
onConfigure?(data: onConfigurePayload): Promise<any>, | ||
onCreateDocument?(data: onCreateDocumentPayload): Promise<any>, | ||
onDestroy?(data: onDestroyPayload): Promise<any>, | ||
onDisconnect?(data: onDisconnectPayload): Promise<any> | ||
onListen?(data: onListenPayload): Promise<any>, | ||
onRequest?(data: onRequestPayload): Promise<any>, | ||
onUpgrade?(data: onUpgradePayload): Promise<any>, | ||
} | ||
@@ -39,0 +40,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
478528
66
5332