UNPKG

worker-websocket-ctrl

Version:

Share a websocket using a Worker/SharedWorker communicating through comlink

131 lines (130 loc) 6.13 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WorkerWsSubscriptions = void 0; const Comlink = __importStar(require("comlink")); class WorkerWsSubscriptions { constructor(options) { this.pathByResource = new Map(); this.resourceByPath = new Map(); this.workers = new Map(); this.subscriptions = new Map(); this.api = options.api; this.createWorker = options.createWorker; if (options.getProtocols) { const getProtocols = options.getProtocols; this.getProtocolsProxy = Comlink.proxy((path) => __awaiter(this, void 0, void 0, function* () { const resource = this.resourceByPath.get(path); if (!resource) { console.error(`Unable to get resource name for path ${path}`); return null; } return getProtocols(resource); })); } if (options.autoUnsubscribe) { this.autoUnsubscribeBinded = options.autoUnsubscribe.bind(this); } } subscribe(ctx, resource, onEvent, hooks = {}) { var _a; return __awaiter(this, void 0, void 0, function* () { let subscriptions = this.subscriptions.get(resource); if (subscriptions == null) { subscriptions = new Map(); this.subscriptions.set(resource, subscriptions); } else if (subscriptions.has(this)) { return; } (_a = this.autoUnsubscribeBinded) === null || _a === void 0 ? void 0 : _a.call(this, ctx, () => this.unsubscribe(ctx, resource)); let workerWs; const currentWorker = this.workers.get(resource); let _worker; if (!currentWorker) { _worker = this.createWorker(resource); if (!_worker) { this.checkSubscriptions(resource); throw new Error(`Unable to create worker for resource ${resource}`); } workerWs = Comlink.wrap(_worker instanceof Worker ? _worker : _worker.port); const path = yield workerWs.path; this.workers.set(resource, workerWs); this.pathByResource.set(resource, path); this.resourceByPath.set(path, resource); } else { workerWs = currentWorker; } yield workerWs.start(typeof this.api === 'string' ? this.api : this.api(), this.getProtocolsProxy); const unsubscribe = yield workerWs.subscribe(Comlink.proxy((data) => { onEvent(data); }), Comlink.proxy(pong => { pong(); }), Comlink.proxy(() => { var _a; (_a = hooks.onConnect) === null || _a === void 0 ? void 0 : _a.call(hooks); }), Comlink.proxy(() => { var _a; (_a = hooks.onDisconnect) === null || _a === void 0 ? void 0 : _a.call(hooks); }), Comlink.proxy(() => { var _a, _b; (_a = hooks.onConnect) === null || _a === void 0 ? void 0 : _a.call(hooks); console.error('Connection closed from the worker'); (_b = this.subscriptions.get(resource)) === null || _b === void 0 ? void 0 : _b.delete(ctx); this.checkSubscriptions(resource); })); subscriptions.set(ctx, { unsubscribe }); return (msg) => workerWs.sendMessage(msg); }); } unsubscribe(ctx, ...resources) { for (const resource of resources) { const resourceSubs = this.subscriptions.get(resource); const subscription = resourceSubs === null || resourceSubs === void 0 ? void 0 : resourceSubs.get(ctx); if (subscription) { subscription.unsubscribe(); resourceSubs === null || resourceSubs === void 0 ? void 0 : resourceSubs.delete(ctx); this.checkSubscriptions(resource); } } } checkSubscriptions(resource) { var _a; if (((_a = this.subscriptions.get(resource)) === null || _a === void 0 ? void 0 : _a.size) === 0) { this.workers.delete(resource); const path = this.pathByResource.get(resource); this.pathByResource.delete(resource); if (path) this.resourceByPath.delete(path); } } } exports.WorkerWsSubscriptions = WorkerWsSubscriptions;