UNPKG

@devgrid/netron

Version:

A powerful TypeScript library for building distributed systems with event bus, streaming capabilities, and remote object invocation. Features WebSocket-based bidirectional communication between Node.js and browser environments, service discovery, and type

203 lines 8.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LocalPeer = void 0; const interface_1 = require("./interface"); const definition_1 = require("./definition"); const service_stub_1 = require("./service-stub"); const abstract_peer_1 = require("./abstract-peer"); const predicates_1 = require("./predicates"); const utils_1 = require("./utils"); const constants_1 = require("./constants"); class LocalPeer extends abstract_peer_1.AbstractPeer { constructor(netron) { super(netron, netron.id); this.stubs = new Map(); this.serviceInstances = new Map(); this.logger = netron.logger.child({ peerId: this.id }); this.abilities = { allowServiceEvents: netron.options?.allowServiceEvents ?? false, }; } async exposeService(instance) { this.logger.info('Exposing service', { instance }); const meta = (0, utils_1.getServiceMetadata)(instance); if (!meta) { this.logger.error('Invalid service: Service metadata could not be retrieved'); throw new Error('Invalid service: Service metadata could not be retrieved'); } const existingStub = this.serviceInstances.get(instance); if (existingStub) { this.logger.warn('Service instance already exposed', { name: meta.name }); throw new Error(`Service instance already exposed: ${meta.name}`); } const serviceKey = (0, utils_1.getQualifiedName)(meta.name, meta.version); if (this.netron.services.has(serviceKey)) { this.logger.warn('Service already exposed', { serviceKey }); throw new Error(`Service already exposed: ${serviceKey}`); } this.logger.info('Creating service stub', { serviceKey }); const stub = new service_stub_1.ServiceStub(this, instance, meta); const def = stub.definition; this.stubs.set(def.id, stub); this.netron.services.set(serviceKey, stub); this.serviceInstances.set(instance, stub); this.netron.emitSpecial(constants_1.NETRON_EVENT_SERVICE_EXPOSE, (0, utils_1.getServiceEventName)(serviceKey), { name: def.meta.name, version: def.meta.version, qualifiedName: serviceKey, peerId: this.id, definition: def, }); await this.netron.discovery?.updateServices(this.netron.getExposedServices()); this.logger.info('Service exposed successfully', { serviceKey }); return def; } exposeRemoteService(peer, meta) { const def = new definition_1.Definition(definition_1.Definition.nextId(), peer.id, meta); const iInstance = interface_1.Interface.create(def, peer); const stub = new service_stub_1.ServiceStub(this, iInstance, def); this.stubs.set(def.id, stub); this.netron.services.set(meta.name, stub); this.serviceInstances.set(iInstance, stub); peer.definitions.set(def.id, def); this.netron.emitSpecial(constants_1.NETRON_EVENT_SERVICE_EXPOSE, (0, utils_1.getServiceEventName)(def.meta.name), { name: def.meta.name, version: def.meta.version, qualifiedName: (0, utils_1.getQualifiedName)(def.meta.name, def.meta.version), peerId: this.id, remotePeerId: peer.id, definition: def, }); return def; } async unexposeService(serviceName) { this.logger.info('Unexposing service', { serviceName }); const def = this.getDefinitionByServiceName(serviceName); const defId = def.id; for (const i of this.interfaces.values()) { if (i.instance.$def?.parentId === defId) { this.logger.debug('Releasing interface', { defId }); this.releaseInterface(i.instance); } } this.netron.services.delete(serviceName); const stub = this.stubs.get(defId); if (stub) { this.serviceInstances.delete(stub.instance); this.stubs.delete(defId); } this.netron.emitSpecial(constants_1.NETRON_EVENT_SERVICE_UNEXPOSE, (0, utils_1.getServiceEventName)(serviceName), { name: def.meta.name, version: def.meta.version, qualifiedName: serviceName, peerId: this.id, defId, }); await this.netron.discovery?.updateServices(this.netron.getExposedServices()); this.logger.info('Service unexposed successfully', { serviceName }); } unexposeRemoteService(peer, serviceName) { const def = this.getDefinitionByServiceName(serviceName); const defId = def.id; for (const i of this.interfaces.values()) { if (i.instance.$def?.parentId === defId) { this.releaseInterface(i.instance); } } peer.definitions.delete(defId); this.netron.services.delete(serviceName); const stub = this.stubs.get(defId); if (stub) { this.serviceInstances.delete(stub.instance); this.stubs.delete(defId); } this.netron.emitSpecial(constants_1.NETRON_EVENT_SERVICE_UNEXPOSE, (0, utils_1.getServiceEventName)(serviceName), { name: def.meta.name, version: def.meta.version, qualifiedName: serviceName, peerId: this.id, remotePeerId: peer.id, defId, }); return def.id; } async releaseInterfaceInternal(iInstance) { this.unrefService(iInstance.$def?.id); } refService(instance, parentDef) { const existingStub = this.serviceInstances.get(instance); if (existingStub) { return existingStub.definition; } const meta = (0, predicates_1.isServiceInterface)(instance) ? instance.$def.meta : (0, utils_1.getServiceMetadata)(instance); const stub = new service_stub_1.ServiceStub(this, instance, meta); stub.definition.parentId = parentDef.id; this.serviceInstances.set(instance, stub); this.stubs.set(stub.definition.id, stub); return stub.definition; } unrefService(defId) { if (defId) { const stub = this.stubs.get(defId); if (stub) { this.serviceInstances.delete(stub.instance); if (!this.netron.services.has((0, utils_1.getQualifiedName)(stub.definition.meta.name, stub.definition.meta.version))) { this.stubs.delete(stub.definition.id); } } } } subscribe(eventName, handler) { this.netron.on(eventName, handler); } unsubscribe(eventName, handler) { this.netron.removeListener(eventName, handler); } async set(defId, name, value) { this.logger.debug('Setting property', { defId, name }); return this.getStubByDefinitionId(defId).set(name, value); } async get(defId, name) { this.logger.debug('Getting property', { defId, name }); return this.processResult(await this.getStubByDefinitionId(defId).get(name)); } async call(defId, method, args) { this.logger.debug('Calling method', { defId, method }); return this.processResult(await this.getStubByDefinitionId(defId).call(method, args)); } hasStub(defId) { return this.stubs.has(defId); } getServiceNames() { return this.netron.getServiceNames(); } getStubByDefinitionId(defId) { const stub = this.stubs.get(defId); if (stub === void 0) { throw new Error(`Unknown definition: ${defId}.`); } return stub; } getDefinitionById(defId) { const stub = this.stubs.get(defId); if (stub === void 0) { throw new Error(`Unknown definition: ${defId}.`); } return stub.definition; } getDefinitionByServiceName(name) { const stub = this.netron.services.get(name); if (stub === void 0) { throw new Error(`Unknown service: ${name}.`); } return stub.definition; } processResult(result) { if ((0, predicates_1.isServiceDefinition)(result)) { return this.queryInterfaceByDefId(result.id, result); } return result; } } exports.LocalPeer = LocalPeer; //# sourceMappingURL=local-peer.js.map