open-collaboration-service-process
Version:
A service process for integrating non Typescript projects with the Open Collaboration Tools project
81 lines (68 loc) • 4.48 kB
text/typescript
// ******************************************************************************
// Copyright 2024 TypeFox GmbH
// This program and the accompanying materials are made available under the
// terms of the MIT License, which is available in the project root.
// ******************************************************************************
import type * as types from 'open-collaboration-protocol';
import { CloseSessionRequest, CreateRoomRequest, fromEncodedOCPMessage, InternalError, JoinRoomRequest,
LoginRequest, OCPBroadCast, OCPNotification, OCPRequest, OpenDocument,
SessionData, UpdateDocumentContent, UpdateTextSelection } from './messages.js';
import { CollaborationInstance } from './collaboration-instance.js';
import { MessageConnection } from 'vscode-jsonrpc';
export class MessageHandler {
protected currentCollaborationInstance?: CollaborationInstance;
protected lastRequestId = 0;
constructor(private connectionProvider: types.ConnectionProvider, private communicationHandler: MessageConnection) {
communicationHandler.onRequest(LoginRequest, async () => this.login());
communicationHandler.onRequest(JoinRoomRequest, this.joinRoom.bind(this));
communicationHandler.onRequest(CreateRoomRequest, this.createRoom.bind(this));
communicationHandler.onRequest(CloseSessionRequest, () => this.currentCollaborationInstance?.currentConnection.dispose());
communicationHandler.onNotification(OpenDocument, (p1, p2, p3) => this.currentCollaborationInstance?.registerYjsObject(p1, p2, p3));
communicationHandler.onNotification(UpdateTextSelection, (p1, p2) => this.currentCollaborationInstance?.updateYjsObjectSelection(p1, p2));
communicationHandler.onNotification(UpdateDocumentContent, (p1, p2) => this.currentCollaborationInstance?.updateYjsObjectContent(p1, p2));
communicationHandler.onError(([error]) => communicationHandler.sendNotification(InternalError, {message: error.message, stack: error.stack}));
communicationHandler.onRequest(OCPRequest, (rawMessage) => {
const message = typeof rawMessage === 'string' ? fromEncodedOCPMessage(rawMessage) : rawMessage;
return this.currentCollaborationInstance?.currentConnection.sendRequest(message.method, message.target, ...message.params);
});
communicationHandler.onNotification(OCPNotification, async (rawMessage) => {
const message = typeof rawMessage === 'string' ? fromEncodedOCPMessage(rawMessage) : rawMessage;
this.currentCollaborationInstance?.currentConnection.sendNotification(message.method, message.target, ...message.params);
});
communicationHandler.onNotification(OCPBroadCast, async (rawMessage) => {
const message = typeof rawMessage === 'string' ? fromEncodedOCPMessage(rawMessage) : rawMessage;
this.currentCollaborationInstance?.currentConnection.sendBroadcast(message.method, ...message.params);
});
}
async login(): Promise<string> {
const authToken = await this.connectionProvider.login({ });
return authToken;
}
async joinRoom(roomId: string): Promise<SessionData> {
const resp = await this.connectionProvider.joinRoom({ roomId });
this.onConnection(await this.connectionProvider.connect(resp.roomToken), false);
return {
roomId: resp.roomId,
roomToken: resp.roomToken,
authToken: resp.loginToken ?? this.connectionProvider.authToken,
workspace: resp.workspace
};
}
async createRoom(workspace: types.Workspace): Promise<SessionData> {
const resp = await this.connectionProvider.createRoom({});
this.onConnection(await this.connectionProvider.connect(resp.roomToken), true, workspace);
return {
roomId: resp.roomId,
roomToken: resp.roomToken,
authToken: resp.loginToken ?? this.connectionProvider.authToken,
workspace,
};
}
onConnection(connection: types.ProtocolBroadcastConnection, host: boolean, workspace?: types.Workspace) {
this.currentCollaborationInstance?.dispose();
this.currentCollaborationInstance = new CollaborationInstance(connection, this.communicationHandler, host, workspace);
}
dispose() {
this.currentCollaborationInstance?.dispose();
}
}