@casual-simulation/aux-vm-client
Version:
A set of utilities required to securely run an AUX as a client.
180 lines • 5.7 kB
JavaScript
import { remapProgressPercent } from '@casual-simulation/aux-common';
import { Subject } from 'rxjs';
import { proxy, createEndpoint } from 'comlink';
/**
* Defines a VM that is able to wrap a remote aux channel.
*/
export class RemoteAuxVM {
/**
* The ID of the simulation.
*/
get id() {
return this._id;
}
get configBotId() {
return this._configBotId;
}
get origin() {
return this._origin;
}
/**
* Creates a new Simulation VM.
*/
constructor(id, origin, configBotId, channel) {
this._id = id;
this._origin = origin;
this._configBotId = configBotId;
this._localEvents = new Subject();
this._deviceEvents = new Subject();
this._stateUpdated = new Subject();
this._versionUpdated = new Subject();
this._connectionStateChanged = new Subject();
this._onError = new Subject();
this._subVMAdded = new Subject();
this._subVMRemoved = new Subject();
this._subVMMap = new Map();
this._onAuthMessage = new Subject();
this._proxy = channel;
}
get subVMAdded() {
return this._subVMAdded;
}
get subVMRemoved() {
return this._subVMRemoved;
}
get connectionStateChanged() {
return this._connectionStateChanged;
}
get onError() {
return this._onError;
}
get onAuthMessage() {
return this._onAuthMessage;
}
/**
* Initaializes the VM.
*/
async init() {
return await this._init();
}
async _init() {
let statusMapper = remapProgressPercent(0.2, 1);
return await this._proxy.init(proxy((events) => this._localEvents.next(events)), proxy((events) => this._deviceEvents.next(events)), proxy((state) => this._stateUpdated.next(state)), proxy((version) => this._versionUpdated.next(version)), proxy((state) => this._connectionStateChanged.next(statusMapper(state))), proxy((err) => this._onError.next(err)), proxy((channel) => this._handleAddedSubChannel(channel)), proxy((id) => this._handleRemovedSubChannel(id)), proxy((message) => this._onAuthMessage.next(message)));
}
/**
* The observable list of events that should be produced locally.
*/
get localEvents() {
return this._localEvents;
}
get deviceEvents() {
return this._deviceEvents;
}
/**
* The observable list of bot state updates from this simulation.
*/
get stateUpdated() {
return this._stateUpdated;
}
get versionUpdated() {
return this._versionUpdated;
}
/**
* Sends the given list of events to the simulation.
* @param events The events to send to the simulation.
*/
async sendEvents(events) {
if (!this._proxy)
return null;
return await this._proxy.sendEvents(events);
}
/**
* Executes a shout with the given event name on the given bot IDs with the given argument.
* Also dispatches any actions and errors that occur.
* Returns the results from the event.
* @param eventName The name of the event.
* @param botIds The IDs of the bots that the shout is being sent to.
* @param arg The argument to include in the shout.
*/
async shout(eventName, botIds, arg) {
if (!this._proxy)
return null;
return await this._proxy.shout(eventName, botIds, arg);
}
async formulaBatch(formulas) {
if (!this._proxy)
return null;
return await this._proxy.formulaBatch(formulas);
}
async forkAux(newId) {
if (!this._proxy)
return null;
return await this._proxy.forkAux(newId);
}
async exportBots(botIds) {
if (!this._proxy)
return null;
return await this._proxy.exportBots(botIds);
}
/**
* Exports the causal tree for the simulation.
*/
async export() {
if (!this._proxy)
return null;
return await this._proxy.export();
}
async getTags() {
if (!this._proxy)
return null;
return await this._proxy.getTags();
}
async updateDevice(device) {
if (!this._proxy)
return null;
return await this._proxy.updateDevice(device);
}
/**
* Gets a new endpoint for the aux channel.
* Can then be used with a ConnectableAuxVM.
*/
createEndpoint() {
return this._proxy[createEndpoint]();
}
sendAuthMessage(message) {
return this._proxy.sendAuthMessage(message);
}
unsubscribe() {
if (this.closed) {
return;
}
this.closed = true;
this._proxy = null;
this._connectionStateChanged.unsubscribe();
this._connectionStateChanged = null;
this._localEvents.unsubscribe();
this._localEvents = null;
}
_createSubVM(id, origin, configBotId, channel) {
return new RemoteAuxVM(id, origin, configBotId, channel);
}
async _handleAddedSubChannel(subChannel) {
const { id, configBotId } = await subChannel.getInfo();
const channel = (await subChannel.getChannel());
const subVM = {
id,
vm: this._createSubVM(id, this.origin, configBotId, channel),
channel,
};
this._subVMMap.set(id, subVM);
this._subVMAdded.next(subVM);
}
async _handleRemovedSubChannel(channelId) {
const vm = this._subVMMap.get(channelId);
if (vm) {
this._subVMMap.delete(channelId);
this._subVMRemoved.next(vm);
}
}
}
//# sourceMappingURL=RemoteAuxVM.js.map