UNPKG

nats-micro

Version:

NATS micro compatible extra-lightweight microservice library

261 lines 12.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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()); }); }; var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.NatsBroker = void 0; const nats = __importStar(require("nats")); const debug_js_1 = require("./debug.js"); const tokenEventEmitter_js_1 = require("./tokenEventEmitter.js"); const index_js_1 = require("./utils/index.js"); class NatsBroker { // eslint-disable-next-line no-useless-constructor, no-empty-function constructor(options) { this.options = options; this.ee = new tokenEventEmitter_js_1.TokenEventEmitter(); // eslint-disable-next-line new-cap this.codec = nats.JSONCodec(); this.subscriptions = {}; } get name() { var _a, _b; return (_a = this.options.name) !== null && _a !== void 0 ? _a : ((_b = process.env.MICROSERVICE_NODE_NAME) !== null && _b !== void 0 ? _b : ''); } connect() { var _a; return __awaiter(this, void 0, void 0, function* () { debug_js_1.debug.broker.info(`Connecting to ${this.options.servers} as "${this.options.name}"`); try { this.connection = yield nats.connect(this.options); this.clientId = (_a = this.connection.info) === null || _a === void 0 ? void 0 : _a.client_id; this.connectionClosedWaiter = this.connection.closed(); debug_js_1.debug.broker.info(`Connected as ${this.clientId}`); return this; } catch (err) { debug_js_1.debug.broker.error(`Failed to connect: ${(0, index_js_1.errorToString)(err)}`); throw err; } }); } disconnect() { return __awaiter(this, void 0, void 0, function* () { debug_js_1.debug.broker.info('Disconnecting from server'); try { if (!this.connection) { debug_js_1.debug.broker.info('Not connected to server'); return; } yield this.connection.close(); this.subscriptions = {}; const err = yield this.connectionClosedWaiter; if (err) throw err; debug_js_1.debug.broker.info('Disconnected from server'); } catch (err) { debug_js_1.debug.broker.error(`Error disconnecting from server: ${(0, index_js_1.errorToString)(err)}`); throw err; } }); } createInbox() { return nats.createInbox(); } decode(msg) { const str = msg.string(); if (str === '') return ''; return this.codec.decode(msg.data); } handleMessageFromSubscription(err, msg) { if (err) { debug_js_1.debug.broker.error(`Incoming error in message on "${msg.subject}": ${JSON.stringify(err)}`); } else { debug_js_1.debug.broker.debug(`Incoming message on "${msg.subject}": ${JSON.stringify(msg.string())}`); try { this.ee.emit(msg.subject, { data: this.decode(msg), headers: this.decodeHeaders(msg.headers), replyTo: msg.reply, }); } catch (ex) { let content; try { content = msg.string(); } catch (_a) { content = `${msg.data.byteLength} bytes`; } debug_js_1.debug.broker.error(`Error decoding JSON from "${content}"`); debug_js_1.debug.broker.debug(String(ex)); } } } encodeHeaders(headers) { const result = nats.headers(); if (headers) for (const [k, v] of headers) result.append(k, v.replace(/[\r\n]+/g, ' ')); return result; } decodeHeaders(headers) { if (!headers) return []; const result = []; for (const key of headers.keys()) for (const value of headers.values(key)) result.push([key, value]); return result; } subscribe(subject, queue) { if (!this.connection) throw new Error('Not connected'); debug_js_1.debug.broker.debug(`Subscribing to "${subject}"`); return this.connection.subscribe(subject, { queue, callback: this.handleMessageFromSubscription.bind(this), }); } unsubscribe(subscription) { if (!this.connection) throw new Error('Not connected'); debug_js_1.debug.broker.debug(`Unsubscribing from "${subscription.getSubject()}"`); subscription.unsubscribe(); } on(subject, listener, queue = undefined) { const subj = (0, index_js_1.subjectToString)(subject); if (!this.subscriptions[subj]) { this.subscriptions[subj] = this.subscribe(subj, queue); } this.ee.on(subj, listener); } off(subject, listener) { const subj = (0, index_js_1.subjectToString)(subject); this.ee.off(subj, listener); if (this.subscriptions[subj]) { if (!this.ee['handlers'].find((handler) => handler.wildcard === subj)) { this.unsubscribe(this.subscriptions[subj]); delete (this.subscriptions[subj]); } } } send(subject, data, options) { return __awaiter(this, void 0, void 0, function* () { if (!this.connection) throw new Error('Not connected'); yield this.connection.publish((0, index_js_1.subjectToString)(subject), this.codec.encode(data), { headers: this.encodeHeaders((0, index_js_1.addThreadContextHeaders)(options === null || options === void 0 ? void 0 : options.headers)), reply: (options && options.replyTo) ? options.replyTo : undefined, }); }); } requestMany(subject, data, options) { var _a, _b, _c; return __asyncGenerator(this, arguments, function* requestMany_1() { if (!this.connection) throw new Error('Not connected'); const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30000; try { const responses = yield __await(this.connection.requestMany((0, index_js_1.subjectToString)(subject), this.codec.encode(data), { headers: this.encodeHeaders((0, index_js_1.addThreadContextHeaders)(options === null || options === void 0 ? void 0 : options.headers)), noMux: true, strategy: ((_b = options === null || options === void 0 ? void 0 : options.limit) !== null && _b !== void 0 ? _b : 0) < 0 ? nats.RequestStrategy.Timer : nats.RequestStrategy.Count, maxMessages: ((_c = options === null || options === void 0 ? void 0 : options.limit) !== null && _c !== void 0 ? _c : 0) < 0 ? undefined : options === null || options === void 0 ? void 0 : options.limit, maxWait: timeout, // reply: `_INBOX.${microservice}.${randomId()}`, // timeout, })); const iterator = responses[Symbol.asyncIterator](); let result = yield __await(iterator.next()); while (!result.done) { yield yield __await({ data: this.codec.decode(result.value.data), headers: this.decodeHeaders(result.value.headers), subject: result.value.subject, }); result = yield __await(iterator.next()); } } catch (err) { if (typeof (err) === 'object' && err && 'code' in err && err.code === '503') return yield __await(void 0); // NATS no responders available throw err; } }); } request(subject, data, options) { var _a; return __awaiter(this, void 0, void 0, function* () { if (!this.connection) throw new Error('Not connected'); const timeout = (_a = options === null || options === void 0 ? void 0 : options.timeout) !== null && _a !== void 0 ? _a : 30000; const res = yield this.connection.request((0, index_js_1.subjectToString)(subject), this.codec.encode(data), { headers: this.encodeHeaders((0, index_js_1.addThreadContextHeaders)(options === null || options === void 0 ? void 0 : options.headers)), noMux: true, reply: `_INBOX.${(0, index_js_1.randomId)()}`, timeout, }); const headers = this.decodeHeaders(res.headers); const error = (0, index_js_1.errorFromHeaders)(headers); if (error) throw error; return { data: this.codec.decode(res.data), headers, subject: res.subject, }; }); } } exports.NatsBroker = NatsBroker; //# sourceMappingURL=natsBroker.js.map