UNPKG

@casual-simulation/aux-vm-browser

Version:

A set of utilities required to securely run an AUX in a web browser.

180 lines 6.13 kB
/* CasualOS is a set of web-based tools designed to facilitate the creation of real-time, multi-user, context-aware interactive experiences. * * Copyright (c) 2019-2025 Casual Simulation, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ import { remapProgressPercent, } from '@casual-simulation/aux-common'; import { Subject } from 'rxjs'; /** * Defines a class that represents an AUX VM that provides no isolation or sandboxing. */ export default class AuxNoVM { /** * The ID of the simulation. */ get id() { return this._id; } get configBotId() { return this._configBotId; } /** * Creates a new AUX VM that provides no isolation or sandboxing. * @param id The ID of the inst. * @param origin The origin of the inst. * @param config The config that should be used. */ constructor(id, origin, configBotId, channel) { this._id = id; this._origin = origin; this._configBotId = configBotId; this._channel = channel; 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(); } async init() { // if (!this._channel) { // } let statusMapper = remapProgressPercent(0.2, 1); return await this._channel.init((events) => this._localEvents.next(events), (events) => this._deviceEvents.next(events), (state) => this._stateUpdated.next(state), (version) => this._versionUpdated.next(version), (state) => this._connectionStateChanged.next(statusMapper(state)), (err) => this._onError.next(err), // TODO: Support sub channels properly (channel) => { }, //this._handleAddedSubChannel(channel), (id) => { }, //this._handleRemovedSubChannel(id), (message) => this._onAuthMessage.next(message)); } unsubscribe() { if (this.closed) { return; } this.closed = true; if (this._channel) { this._channel.unsubscribe(); this._channel = null; } this._connectionStateChanged.unsubscribe(); this._connectionStateChanged = null; this._localEvents.unsubscribe(); this._localEvents = null; } get origin() { return this._origin; } 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; } /** * 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; } async sendEvents(events) { return await this._channel.sendEvents(events); } async shout(eventName, botIds, arg) { return await this._channel.shout(eventName, botIds, arg); } async formulaBatch(formulas) { return await this._channel.formulaBatch(formulas); } async forkAux(newId) { return await this._channel.forkAux(newId); } async exportBots(botIds) { return await this._channel.exportBots(botIds); } async export() { return await this._channel.export(); } async getTags() { return await this._channel.getTags(); } async updateDevice(device) { return await this._channel.updateDevice(device); } async sendAuthMessage(message) { return await this._channel.sendAuthMessage(message); } _createSubVM(id, origin, configBotId, channel) { return new AuxNoVM(id, origin, configBotId, channel); } async _handleAddedSubChannel(subChannel) { const { id, configBotId } = await subChannel.getInfo(); const channel = await subChannel.getChannel(); const subVM = { id: 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); } } } export function processPartitions(config) { const processed = { ...config, partitions: { ...config.partitions } }; for (let key in processed.partitions) { const partition = processed.partitions[key]; if (!partition) { delete processed.partitions[key]; } else if (partition.type === 'proxy') { processed.partitions[key] = { type: 'injected', partition: partition.partition, }; } } return config; } //# sourceMappingURL=AuxNoVM.js.map