UNPKG

node-universe

Version:

基于 Nodejs 环境的一款微服务框架,原理来自于宇宙中的恒星,行星,卫星等系统。

1,241 lines (1,235 loc) 574 kB
'use strict';var path=require('path'),fs=require('fs'),os=require('os'),kleur=require('kleur'),EventEmitter2=require('eventemitter2'),_=require('lodash'),util=require('util'),log4js=require('log4js'),Pino=require('pino'),http=require('http'),zlib=require('zlib'),fetch=require('node-fetch'),dgram=require('dgram'),v8=require('v8'),gc=require('gc-stats'),eventLoop=require('event-loop-stats'),watch=require('recursive-watch'),etcd3=require('etcd3'),Redis=require('ioredis'),cborX=require('cbor-x'),notepack=require('notepack.io'),lruCache=require('lru-cache'),crypto=require('crypto'),Redlock=require('redlock'),stream=require('stream'),Kafka=require('kafka-node'),EventEmitter=require('events'),ipaddr=require('ipaddr.js'),net=require('net'),Validator=require('fastest-validator'),perf_hooks=require('perf_hooks'),glob=require('glob');var C$1 = { CIRCUIT_CLOSE: 'close', CIRCUIT_HALF_OPEN: 'half_open', CIRCUIT_HALF_OPEN_WAIT: 'half_open_wait', CIRCUIT_OPEN: 'open', FAILED_PROCESSING_PACKET: 'failedProcessingPacket', FAILED_SEND_REQUEST_PACKET: 'failedSendRequestPacket', FAILED_SEND_EVENT_PACKET: 'failedSendEventPacket', FAILED_SEND_RESPONSE_PACKET: 'failedSendResponsePacket', FAILED_NODES_DISCOVERY: 'failedNodesDiscovery', FAILED_NODE_DISCOVERY: 'failedNodeDiscovery', FAILED_SEND_INFO_PACKET: 'failedSendInfoPacket', FAILED_SEND_PING_PACKET: 'failedSendPingPacket', FAILED_SEND_PONG_PACKET: 'failedSendPongPacket', FAILED_SEND_HEARTBEAT_PACKET: 'failedSendHeartbeatPacket', FAILED_STOPPING_SERVICES: 'failedServicesStop', FAILED_LOAD_SERVICE: 'failedServiceLoad', FAILED_RESTART_SERVICE: 'failedServiceRestart', FAILED_DESTRUCTION_SERVICE: 'failedServiceDestruction', CLIENT_ERROR: 'clientError', FAILED_SEND_PING: 'failedSendPing', FAILED_COLLECT_KEYS: 'failedCollectKeys', FAILED_SEND_INFO: 'failedSendInfo', FAILED_KEY_SCAN: 'failedKeyScan', FAILED_PUBLISHER_ERROR: 'publisherError', FAILED_CONSUMER_ERROR: 'consumerError', FAILED_TOPIC_CREATION: 'failedTopicCreation', FAILED_CONNECTION_ERROR: 'failedConnection', FAILED_CHANNEL_ERROR: 'failedChannel', FAILED_REQUEST_ACK: 'requestAck', FAILED_DISCONNECTION: 'failedDisconnection', FAILED_PUBLISH_BALANCED_EVENT: 'failedPublishBalancedEvent', FAILED_PUBLISH_BALANCED_REQUEST: 'publishBalancedRequest' };/****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __awaiter(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()); }); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; };class BaseError extends Error { constructor(message = '') { super(message); Object.defineProperty(this, 'message', { configurable: true, enumerable: false, value: message, writable: true }); Object.defineProperty(this, 'name', { configurable: true, enumerable: false, value: this.constructor.name, writable: true }); if (Object.prototype.hasOwnProperty.call(Error, 'captureStackTrace')) { Error.captureStackTrace(this, this.constructor); return; } Object.defineProperty(this, 'stack', { configurable: true, enumerable: false, value: new Error(message).stack, writable: true }); } }function promiseAllControl(promises, settled, promise = Promise) { return settled ? promise.allSettled(promises) : promise.all(promises); }function sleep(time = 1000) { let timer = null; let now = Date.now(); return new Promise((resolve, reject) => { timer = setInterval(() => { if (now + time < Date.now()) { clearInterval(timer); timer = null; resolve(true); } }, 10); }); }function getMilliseconds() { const ms = new Date().getMilliseconds(); if (ms < 10) { return `00${ms}`; } else if (ms >= 10 && ms < 100) { return `0${ms}`; } else { return `${ms}`; } }function promiseMethod(fn) { let promiseFunc = function (func) { return function (...args) { return new Promise((resolve, reject) => { try { const val = func.apply(this, args); resolve(val); } catch (error) { reject(error); } }); }; }; return promiseFunc(fn); }function functionArguments(function_) { if (typeof function_ !== 'function') { throw new TypeError('Expected a function'); } const commentRegex = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm; const quotes = ['`', '"', "'"]; const functionSource = function_.toString().replace(commentRegex, ''); let functionWithNoDefaults = ''; let depth = 0; let index = 0; for (; index < functionSource.length && functionSource.charAt(index) !== ')'; index += 1) { if (functionSource.startsWith('=>', index)) { functionWithNoDefaults = functionSource; index = functionSource.length; break; } if (functionSource.charAt(index) === '=') { for (; index < functionSource.length && ((functionSource.charAt(index) !== ',' && functionSource.charAt(index) !== ')') || depth !== 0); index += 1) { let wasQuote = false; for (const quote of quotes) { if (functionSource.charAt(index) === quote) { index += 1; for (; index < functionSource.length && functionSource.charAt(index) !== quote;) { index += 1; } wasQuote = true; break; } } if (wasQuote) { continue; } switch (functionSource.charAt(index)) { case '(': case '[': case '{': depth += 1; break; case ')': case ']': case '}': depth -= 1; break; } } if (functionSource.charAt(index) === ',') { functionWithNoDefaults += ','; } if (functionSource.charAt(index) === ')') { functionWithNoDefaults += ')'; break; } } else { functionWithNoDefaults += functionSource.charAt(index); } } if (index < functionSource.length && functionSource.charAt(index) === ')') { functionWithNoDefaults += ')'; } const regexFnArguments = /^(?:async)?([^=()]+)=|\(([^)]+)\)/; const match = regexFnArguments.exec(functionWithNoDefaults); return match ? (match[1] || match[2]) .split(',') .map((x) => x.trim()) .filter(Boolean) : []; }function isNewSignature(args) { return args.length > 0 && ['ctx', 'context'].indexOf(args[0].toLowerCase()) !== -1; }function clearRequireCache(filename) { Object.keys(require.cache).forEach((key) => { if (key === filename) { delete require.cache[key]; } }); }const RegexCache = new Map(); const deprecateList = []; const units = ['h', 'm', 's', 'ms', 'μs', 'ns']; const divisors = [60 * 60 * 1000, 60 * 1000, 1000, 1, 1e-3, 1e-6]; const lut = []; for (let i = 0; i < 256; i++) { lut[i] = (i < 16 ? '0' : '') + i.toString(16); } class TimeoutError extends BaseError { } function isObject(o) { return o !== null && typeof o === 'object' && !(o instanceof String); } function isString(s) { return s !== null && (typeof s === 'string' || s instanceof String); } function isFunction(fn) { return typeof fn === 'function'; } function isPlainObject(o) { return o != null ? Object.getPrototypeOf(o) === Object.prototype || Object.getPrototypeOf(o) === null : false; } function getConstructorName(obj) { if (obj == null) return undefined; let target = obj.prototype; if (target && target.constructor && target.constructor.name) { return target.constructor.name; } if (obj.constructor && obj.constructor.name) { return obj.constructor.name; } return undefined; } function isInheritedClass(instance, baseClass) { const baseClassName = getConstructorName(baseClass); let proto = instance; while ((proto = Object.getPrototypeOf(proto))) { const protoName = getConstructorName(proto); if (baseClassName == protoName) return true; } return false; } function matchActionOrEvent(text, pattern) { if (pattern.indexOf('?') == -1) { const firstStarPosition = pattern.indexOf('*'); if (firstStarPosition == -1) { return pattern === text; } const len = pattern.length; if (len > 2 && pattern.endsWith('**') && firstStarPosition > len - 3) { pattern = pattern.substring(0, len - 2); return text.startsWith(pattern); } if (len > 1 && pattern.endsWith('*') && firstStarPosition > len - 2) { pattern = pattern.substring(0, len - 1); if (text.startsWith(pattern)) { return text.indexOf('.', len) == -1; } return false; } if (len == 1 && firstStarPosition == 0) { return text.indexOf('.') == -1; } if (len == 2 && firstStarPosition == 0 && pattern.lastIndexOf('*') == 1) { return true; } } const origPattern = pattern; let regex = RegexCache.get(origPattern); if (regex == null) { if (pattern.startsWith('$')) { pattern = '\\' + pattern; } pattern = pattern.replace(/\?/g, '.'); pattern = pattern.replace(/\*\*/g, '§§§'); pattern = pattern.replace(/\*/g, '[^\\.]*'); pattern = pattern.replace(/§§§/g, '.*'); pattern = '^' + pattern + '$'; regex = new RegExp(pattern, ''); RegexCache.set(origPattern, regex); } return regex.test(text); } function makeDirs(filePath) { filePath.split(path.sep).reduce((prevPath, folder) => { const currentPath = path.join(prevPath, folder, path.sep); if (!fs.existsSync(currentPath)) { fs.mkdirSync(currentPath); } return currentPath; }, ''); } function getNodeID() { return os.hostname().toLocaleLowerCase() + '-' + process.pid; } function generateToken() { const d0 = (Math.random() * 0xffffffff) | 0; const d1 = (Math.random() * 0xffffffff) | 0; const d2 = (Math.random() * 0xffffffff) | 0; const d3 = (Math.random() * 0xffffffff) | 0; return (lut[d0 & 0xff] + lut[(d0 >> 8) & 0xff] + lut[(d0 >> 16) & 0xff] + lut[(d0 >> 24) & 0xff] + '-' + lut[d1 & 0xff] + lut[(d1 >> 8) & 0xff] + '-' + lut[((d1 >> 16) & 0x0f) | 0x40] + lut[(d1 >> 24) & 0xff] + '-' + lut[(d2 & 0x3f) | 0x80] + lut[(d2 >> 8) & 0xff] + '-' + lut[(d2 >> 16) & 0xff] + lut[(d2 >> 24) & 0xff] + lut[d3 & 0xff] + lut[(d3 >> 8) & 0xff] + lut[(d3 >> 16) & 0xff] + lut[(d3 >> 24) & 0xff]); } function polyfillPromise(P) { if (!isFunction(P.method)) { P.method = function (fn) { return () => { try { const val = fn.apply(this, arguments); return P.resolve(val); } catch (error) { return P.reject(error); } }; }; } if (!isFunction(P.delay)) { P.delay = function (ms) { return new P((resolve) => setTimeout(resolve, ms)); }; P.prototype.delay = function (ms) { return this.then((res) => P.delay(ms).then(() => res)); }; } if (!isFunction(P.prototype.timeout)) { P.TimeoutError = TimeoutError; P.prototype.timeout = function (ms, message) { let timer = null; const timeout = new P((resolve, reject) => { timer = setTimeout(() => reject(new P.TimeoutError(message)), +ms); }); return P.race([timeout, this]) .then((value) => { clearTimeout(timer); return value; }) .catch((err) => { clearTimeout(timer); throw err; }); }; } if (!isFunction(P.mapSeries)) { P.mapSeries = function (arr, fn) { const promFn = P.method(fn); const res = []; return arr .reduce((p, item, i) => { return p.then((r) => { res[i] = r; return promFn(item, i); }); }, P.resolve()) .then((r) => { res[arr.length] = r; return res.slice(1); }); }; } } function getIpList() { var _a; const list = []; const ipList = []; const interfaces = os.networkInterfaces(); for (let iface in interfaces) { for (let i in interfaces[iface]) { if ((_a = interfaces[iface]) === null || _a === void 0 ? void 0 : _a.length) { const f = interfaces[iface][i]; if (f.family === 'IPv4') { if (f.internal) { ipList.push(f.address); break; } else { list.push(f.address); break; } } } } } return list.length > 0 ? list : ipList; } function match(text, pattern) { if (pattern.indexOf('?') == -1) { const firstStarPosition = pattern.indexOf('*'); if (firstStarPosition == -1) { return pattern === text; } const len = pattern.length; if (len > 2 && pattern.endsWith('**') && firstStarPosition > len - 3) { pattern = pattern.substring(0, len - 2); return text.startsWith(pattern); } if (len > 1 && pattern.endsWith('*') && firstStarPosition > len - 2) { pattern = pattern.substring(0, len - 1); if (text.startsWith(pattern)) { return text.indexOf('.', len) == -1; } return false; } if (len == 1 && firstStarPosition == 0) { return text.indexOf('.') == -1; } if (len == 2 && firstStarPosition == 0 && pattern.lastIndexOf('*') == 1) { return true; } } const origPattern = pattern; let regex = RegexCache.get(origPattern); if (regex == null) { if (pattern.startsWith('$')) { pattern = '\\' + pattern; } pattern = pattern.replace(/\?/g, '.'); pattern = pattern.replace(/\*\*/g, '§§§'); pattern = pattern.replace(/\*/g, '[^\\.]*'); pattern = pattern.replace(/§§§/g, '.*'); pattern = '^' + pattern + '$'; regex = new RegExp(pattern, ''); RegexCache.set(origPattern, regex); } return regex.test(text); } function deprecate(prop, msg) { if (arguments.length === 1) { msg = prop; } if (deprecateList.indexOf(prop) === -1) { console.warn(kleur.yellow().bold(`DeprecationWarning: ${msg}`)); deprecateList.push(prop); } } function wrapToArray(o) { return Array.isArray(o) ? o : [o]; } function wrapToHandler(o) { return isFunction(o) ? { handler: o } : o; } function circularReplacer(options = { maxSafeObjectSize: Infinity }) { const seen = new WeakSet(); return function (key, value) { if (typeof value === 'object' && value !== null) { const objectType = (value.constructor && value.constructor.name) || typeof value; if (options.maxSafeObjectSize && 'length' in value && value.length > options.maxSafeObjectSize) { return `[${objectType} ${value.length}]`; } if (options.maxSafeObjectSize && 'size' in value && value.size > options.maxSafeObjectSize) { return `[${objectType} ${value.size}]`; } if (seen.has(value)) { return; } seen.add(value); } return value; }; } function safetyObject(obj, options) { return JSON.parse(JSON.stringify(obj, circularReplacer(options))); } function removeFromArray(arr, item) { if (!arr || arr.length === 0) return arr; const index = arr.indexOf(item); if (index !== -1) arr.splice(item, 1); return arr; } function humanize(milli) { if (milli == null) return '?'; for (let i = 0; i < divisors.length; i++) { const value = milli / divisors[i]; if (value >= 1.0) return '' + Math.floor(value) + units[i]; } return 'now'; } function randomInt(a = 1, b = 0) { const lower = Math.ceil(Math.min(a, b)); const upper = Math.floor(Math.max(a, b)); return Math.floor(lower + Math.random() * (upper - lower + 1)); } function isDate(date) { return date instanceof Date && !Number.isNaN(date.getTime()); }var UniverseErrorOptionsType; (function (UniverseErrorOptionsType) { UniverseErrorOptionsType["BAD_GETWAY"] = "BAD_GETWAY"; UniverseErrorOptionsType["SERVICE_NOT_FOUND"] = "SERVICE_NOT_FOUND"; UniverseErrorOptionsType["SERVICE_NOT_AVAILABLE"] = "SERVICE_NOT_AVAILABLE"; UniverseErrorOptionsType["REQUEST_TIMEOUT"] = "REQUEST_TIMEOUT"; UniverseErrorOptionsType["REQUEST_SKIPPED"] = "REQUEST_SKIPPED"; UniverseErrorOptionsType["REQUEST_REJECTED"] = "REQUEST_REJECTED"; UniverseErrorOptionsType["QUEUE_FULL"] = "QUEUE_FULL"; UniverseErrorOptionsType["VALIDATION_ERROR"] = "VALIDATION_ERROR"; UniverseErrorOptionsType["MAX_CALL_LEVEL"] = "MAX_CALL_LEVEL"; UniverseErrorOptionsType["SERVICE_SCHEMA_ERROR"] = "SERVICE_SCHEMA_ERROR"; UniverseErrorOptionsType["STAR_OPTIONS_ERROR"] = "STAR_OPTIONS_ERROR"; UniverseErrorOptionsType["GRACEFUL_STOP_TIMEOUT"] = "GRACEFUL_STOP_TIMEOUT"; UniverseErrorOptionsType["PROTOCOL_VERSION_MISMATCH"] = "PROTOCOL_VERSION_MISMATCH"; UniverseErrorOptionsType["INVALID_PACKET_DATA"] = "INVALID_PACKET_DATA"; UniverseErrorOptionsType["MISSING_PAYLOAD"] = "MISSING_PAYLOAD"; UniverseErrorOptionsType["INVALID_ENDPOINT"] = "INVALID_ENDPOINT"; UniverseErrorOptionsType["INVALID_PARAMETERS"] = "INVALID_PARAMETERS"; UniverseErrorOptionsType["METRICS_DISABLED"] = "METRICS_DISABLED"; UniverseErrorOptionsType["NOT_FOUND_EVENT"] = "NOT_FOUND_EVENT"; UniverseErrorOptionsType["WAITFOR_SERVICES"] = "WAITFOR_SERVICES"; })(UniverseErrorOptionsType || (UniverseErrorOptionsType = {})); var UniverseErrorType; (function (UniverseErrorType) { UniverseErrorType["UniverseError"] = "UniverseError"; UniverseErrorType["UniverseRetryableError"] = "UniverseRetryableError"; UniverseErrorType["StarDisconnectedError"] = "StarDisconnectedError"; UniverseErrorType["StarServerError"] = "StarServerError"; UniverseErrorType["StarClientError"] = "StarClientError"; UniverseErrorType["ServiceNotFoundError"] = "ServiceNotFoundError"; UniverseErrorType["ServiceNotAvailableError"] = "ServiceNotAvailableError"; UniverseErrorType["RequestTimeoutError"] = "RequestTimeoutError"; UniverseErrorType["RequestSkippedError"] = "RequestSkippedError"; UniverseErrorType["RequestRejectedError"] = "RequestRejectedError"; UniverseErrorType["QueueIsFullError"] = "QueueIsFullError"; UniverseErrorType["ValidationError"] = "ValidationError"; UniverseErrorType["MaxCallLevelError"] = "MaxCallLevelError"; UniverseErrorType["ServiceSchemaError"] = "ServiceSchemaError"; UniverseErrorType["StarOptionsError"] = "StarOptionsError"; UniverseErrorType["GracefulStopTimeoutError"] = "GracefulStopTimeoutError"; UniverseErrorType["ProtocolVersionMismatchError"] = "ProtocolVersionMismatchError"; UniverseErrorType["InvalidPacketDataError"] = "InvalidPacketDataError"; })(UniverseErrorType || (UniverseErrorType = {})); var UniverseErrorCode; (function (UniverseErrorCode) { UniverseErrorCode[UniverseErrorCode["RESPONSE_ERROR"] = 400] = "RESPONSE_ERROR"; UniverseErrorCode[UniverseErrorCode["SERVICE_NOT_FOUND"] = 404] = "SERVICE_NOT_FOUND"; UniverseErrorCode[UniverseErrorCode["VALIDATION_ERROR"] = 422] = "VALIDATION_ERROR"; UniverseErrorCode[UniverseErrorCode["QUEUE_FULL"] = 429] = "QUEUE_FULL"; UniverseErrorCode[UniverseErrorCode["SERVICE_ERROR"] = 500] = "SERVICE_ERROR"; UniverseErrorCode[UniverseErrorCode["BAD_GETWAY"] = 502] = "BAD_GETWAY"; UniverseErrorCode[UniverseErrorCode["REQUEST_REJECTED"] = 503] = "REQUEST_REJECTED"; UniverseErrorCode[UniverseErrorCode["REQUEST_TIMEOUT"] = 504] = "REQUEST_TIMEOUT"; UniverseErrorCode[UniverseErrorCode["REQUEST_SKIPPED"] = 514] = "REQUEST_SKIPPED"; })(UniverseErrorCode || (UniverseErrorCode = {}));class UniverseError extends BaseError { constructor(message, code, type, data) { super(message); this.code = code || UniverseErrorCode.BAD_GETWAY; this.type = type || UniverseErrorOptionsType.BAD_GETWAY; this.data = data; this.retryable = false; } } class UniverseRetryableError extends UniverseError { constructor(message, code, type, data) { super(message, code, type, data); this.retryable = true; } } class StarDisconnectedError extends UniverseRetryableError { constructor() { super(`The star's transporter has disconnected. Please try again when a connection is reestablished.`, 502, UniverseErrorOptionsType.BAD_GETWAY); this.stack = ''; } } class StarServerError extends UniverseRetryableError { } class StarClientError extends UniverseError { constructor(message, code, type, data) { super(message, code || UniverseErrorCode.RESPONSE_ERROR, type, data); } } class ServiceNotFoundError extends UniverseRetryableError { constructor(data = {}) { let msg = ''; if ((data === null || data === void 0 ? void 0 : data.nodeID) && (data === null || data === void 0 ? void 0 : data.action)) msg = `Service '${data === null || data === void 0 ? void 0 : data.action}' is not found on '${data === null || data === void 0 ? void 0 : data.nodeID}' node.`; else if (data === null || data === void 0 ? void 0 : data.action) msg = `Service '${data === null || data === void 0 ? void 0 : data.action}' is not found.`; if ((data === null || data === void 0 ? void 0 : data.service) && (data === null || data === void 0 ? void 0 : data.version)) msg = `Service '${data === null || data === void 0 ? void 0 : data.version}.${data === null || data === void 0 ? void 0 : data.service}' not found.`; else if (data === null || data === void 0 ? void 0 : data.service) msg = `Service '${data === null || data === void 0 ? void 0 : data.service}' not found.`; super(msg, UniverseErrorCode.SERVICE_NOT_FOUND, UniverseErrorOptionsType.SERVICE_NOT_FOUND, data); } } class ServiceNotAvailableError extends UniverseRetryableError { constructor(data = {}) { let msg = ''; if (data === null || data === void 0 ? void 0 : data.nodeID) msg = `Service '${data === null || data === void 0 ? void 0 : data.action}' is not available on '${data === null || data === void 0 ? void 0 : data.nodeID}' node.`; else msg = `Service '${data === null || data === void 0 ? void 0 : data.action}' is not available.`; super(msg, UniverseErrorCode.SERVICE_NOT_FOUND, UniverseErrorOptionsType.SERVICE_NOT_AVAILABLE, data); } } class RequestTimeoutError extends UniverseRetryableError { constructor(data = {}) { super(`Request is timed out when call '${data === null || data === void 0 ? void 0 : data.action}' action on '${data === null || data === void 0 ? void 0 : data.nodeID}' node.`, UniverseErrorCode.REQUEST_TIMEOUT, UniverseErrorOptionsType.REQUEST_TIMEOUT, data); } } class RequestSkippedError extends UniverseError { constructor(data = {}) { super(`Calling '${data.action}' is skipped because timeout reached on '${data.nodeID}' node.`, UniverseErrorCode.REQUEST_SKIPPED, UniverseErrorOptionsType.REQUEST_SKIPPED, data); this.retryable = false; } } class RequestRejectedError extends UniverseRetryableError { constructor(data = {}) { super(`Request is rejected when call '${data === null || data === void 0 ? void 0 : data.action}' action on '${data === null || data === void 0 ? void 0 : data.nodeID}' node.`, UniverseErrorCode.REQUEST_REJECTED, UniverseErrorOptionsType.REQUEST_REJECTED, data); } } class QueueIsFullError extends UniverseRetryableError { constructor(data = {}) { super(`Queue is full. Request '${data === null || data === void 0 ? void 0 : data.action}' action on '${data === null || data === void 0 ? void 0 : data.nodeID}' node is rejected.`, UniverseErrorCode.QUEUE_FULL, UniverseErrorOptionsType.QUEUE_FULL, data); } } class ValidationError extends StarClientError { constructor(message, type, data) { super(message, UniverseErrorCode.VALIDATION_ERROR, type || UniverseErrorOptionsType.VALIDATION_ERROR, data); } } class MaxCallLevelError extends UniverseError { constructor(data) { super(`Request level is reached the limit (${data === null || data === void 0 ? void 0 : data.level}) on '${data === null || data === void 0 ? void 0 : data.nodeID}' node.`, UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.MAX_CALL_LEVEL, data); this.retryable = false; } } class ServiceSchemaError extends UniverseError { constructor(message, data) { super(message, UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.SERVICE_SCHEMA_ERROR, data); } } class StarOptionsError extends UniverseError { constructor(message, data) { super(message, UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.STAR_OPTIONS_ERROR, data); } } class GracefulStopTimeoutError extends UniverseError { constructor(data) { if (data && (data === null || data === void 0 ? void 0 : data.service)) { super(`Unable to stop '${data === null || data === void 0 ? void 0 : data.service.name}' service gracefully.`, UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.GRACEFUL_STOP_TIMEOUT, data && (data === null || data === void 0 ? void 0 : data.service) ? { name: data === null || data === void 0 ? void 0 : data.service.name, version: data === null || data === void 0 ? void 0 : data.service.version } : undefined); } else { super('Unable to stop ServiceBroker gracefully.', UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.GRACEFUL_STOP_TIMEOUT); } } } class ProtocolVersionMismatchError extends UniverseError { constructor(data) { super('Protocol version mismatch.', UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.PROTOCOL_VERSION_MISMATCH, data); } } class InvalidPacketDataError extends UniverseError { constructor(data) { super('Invalid packet data.', UniverseErrorCode.SERVICE_ERROR, UniverseErrorOptionsType.INVALID_PACKET_DATA, data); } }function mergeMeta(ctx, newMeta) { if (newMeta) { Object.assign(ctx.meta, newMeta); } return ctx.meta; } class Context { constructor(star, endpoint) { this.id = ''; this.nodeID = ''; this.endpoint = null; this.action = null; this.service = null; this.event = null; this.starHrTime = null; this.star = star; if (this.star) { this.nodeID = this.star.nodeID || ''; this.id = this.star.generateUid(); } else { this.nodeID = null; } if (endpoint) { this.setEndpoint(endpoint); } else { this.endpoint = null; this.service = null; this.action = null; this.event = null; } this.eventName = null; this.eventType = null; this.eventGroups = null; this.options = { timeout: null, retries: null }; this.parentID = null; this.caller = null; this.level = 1; this.params = null; this.meta = {}; this.locals = {}; this.requestID = this.id; this.tracing = null; this.span = null; this._spanStack = []; this.needAck = null; this.ackID = null; this.cachedResult = false; } static create(star, endpoint, params, options) { var _a, _b, _c, _d, _e; const ctx = new Context(star, endpoint); if (endpoint != null) { ctx.setEndpoint(endpoint); } if (params != null) { let cloning = star ? star.options.contextParamsCloning : false; if (options && options.paramsCloning != null) { cloning = options.paramsCloning; } ctx.setParams(params, cloning); } if (options) ctx.options = options; if (options === null || options === void 0 ? void 0 : options.requestID) ctx.requestID = options.requestID; else if ((options === null || options === void 0 ? void 0 : options.parentCtx) && options.parentCtx.requestID) ctx.requestID = options.parentCtx.requestID; if ((options === null || options === void 0 ? void 0 : options.parentCtx) && options.parentCtx.meta) ctx.meta = Object.assign({}, options.parentCtx.meta || {}, options.meta || {}); else if (options === null || options === void 0 ? void 0 : options.meta) ctx.meta = options.meta; if (options === null || options === void 0 ? void 0 : options.parentCtx) { ctx.tracing = options.parentCtx.tracing; ctx.level = options.parentCtx.level + 1; if ((_a = options.parentCtx) === null || _a === void 0 ? void 0 : _a.span) { ctx.parentID = (_b = options.parentCtx.span) === null || _b === void 0 ? void 0 : _b.id; } else { ctx.parentID = options.parentCtx.id; } if (options.parentCtx.service) ctx.caller = options.parentCtx.service.fullName; } if (options === null || options === void 0 ? void 0 : options.caller) { ctx.caller = options.caller; } if (options === null || options === void 0 ? void 0 : options.parentSpan) { ctx.parentID = (_c = options.parentSpan) === null || _c === void 0 ? void 0 : _c.id; ctx.requestID = (_d = options.parentSpan) === null || _d === void 0 ? void 0 : _d.traceID; ctx.tracing = (_e = options.parentSpan) === null || _e === void 0 ? void 0 : _e.sampled; } if (options === null || options === void 0 ? void 0 : options.needAck) { ctx.needAck = options.needAck; } return ctx; } copy(endpoint) { const newCtx = new Context(this.star); newCtx.nodeID = this.nodeID; newCtx.setEndpoint(endpoint || this.endpoint); newCtx.options = this.options; newCtx.parentID = this.parentID; newCtx.caller = this.caller; newCtx.level = this.level; newCtx.params = this.params; newCtx.meta = this.meta; newCtx.locals = this.locals; newCtx.requestID = this.requestID; newCtx.tracing = this.tracing; newCtx.span = this.span; newCtx.needAck = this.needAck; newCtx.ackID = this.ackID; newCtx.eventName = this.eventName; newCtx.eventType = this.eventType; newCtx.eventGroups = this.eventGroups; newCtx.cachedResult = this.cachedResult; return newCtx; } setParams(newParams, cloning = false) { if (cloning && newParams) { this.params = Object.assign({}, newParams); } else { this.params = newParams; } } setEndpoint(endpoint) { this.endpoint = endpoint; if (this.endpoint) { this.nodeID = endpoint.id; if (endpoint.action) { this.action = endpoint.action; if (this.action.service) { this.service = this.action.service; } this.event = null; } else if (endpoint.event) { this.event = endpoint.event; if (this.event.service) { this.service = this.event.service; } this.action = null; } } } call(actionName, params, options) { var _a; const _options = Object.assign({ parentCtx: this }, options); if (this.options.timeout && this.options.timeout > 0 && this.starHrTime) { const diff = process.hrtime(this.starHrTime); const duration = diff[0] * 1e3 + diff[1] / 1e6; const distTimeout = this.options.timeout - duration; if (distTimeout <= 0) { return Promise.reject(new RequestSkippedError({ action: actionName, nodeID: this.star.nodeID || '' })); } if (!_options.timeout || distTimeout < _options.timeout) _options.timeout = distTimeout; } if (((_a = this.star.options) === null || _a === void 0 ? void 0 : _a.maxCallLevel) && this.star.options.maxCallLevel > 0 && this.level >= this.star.options.maxCallLevel) { return Promise.reject(new MaxCallLevelError({ nodeID: this.star.nodeID || '', level: this.level })); } let p = this.star.call(actionName, params, options); return p .then((res) => { if (p.ctx) { mergeMeta(this, p.ctx.meta); } return res; }) .catch((err) => { if (p.ctx) { mergeMeta(this, p.ctx.meta); } return Promise.reject(err); }); } mcall(def, opts = {}) { const options = Object.assign({ parentCtx: this }, opts); if (this.options.timeout && this.options.timeout > 0 && this.starHrTime) { const diff = process.hrtime(this.starHrTime); const duration = diff[0] * 1e3 + diff[1] / 1e6; const distTimeout = this.options.timeout - duration; if (distTimeout <= 0) { const action = (Array.isArray(def) ? def : Object.values(def)).map((d) => d.action).join(', '); return Promise.reject(new RequestSkippedError({ action, nodeID: this.star.nodeID || '' })); } if (!options.timeout || distTimeout < options.timeout) options.timeout = distTimeout; } if (this.star.options.maxCallLevel && this.star.options.maxCallLevel > 0 && this.level >= this.star.options.maxCallLevel) { return Promise.reject(new MaxCallLevelError({ nodeID: this.star.nodeID || '', level: this.level })); } let p = this.star.mcall(def, options); return p .then((res) => { if (Array.isArray(p.ctx) && p.ctx.length) { p.ctx.forEach((ctx) => mergeMeta(this, ctx.meta)); } return res; }) .catch((err) => { if (Array.isArray(p.ctx) && p.ctx.length) { p.ctx.forEach((ctx) => mergeMeta(this, ctx.meta)); } return Promise.reject(err); }); } emit(eventName, data, options) { if (Array.isArray(options) || isString(options)) { options = { groups: options }; } else if (options == null) { options = {}; } if (options.groups && !Array.isArray(options.groups)) { options.groups = [options.groups]; } options.parentCtx = this; return this.star.emit(eventName, data, options); } broadcast(eventName, data, options) { if (Array.isArray(options) || isString(options)) { options = { groups: options }; } else if (options == null) { options = {}; } if (options.groups && !Array.isArray(options.groups)) { options.groups = [options.groups]; } options.parentCtx = this; return this.star.broadcast(eventName, data, options); } setContextEventData(options) { if (options.eventName) { this.eventName = options.eventName; } if (options.eventType) { this.eventType = options.eventType; } if (options.eventGroups) { this.eventGroups = options.eventGroups; } } startSpan(name, opts) { var _a; let span; if (this.span) { span = this.span.startSpan(name, Object.assign({ ctx: this }, opts)); } else { span = (_a = this.star.tracer) === null || _a === void 0 ? void 0 : _a.startSpan(name, Object.assign({ ctx: this }, opts)); } this._spanStack.push(span); this.span = span; return span; } finishSpan(span, time) { var _a, _b; if (!span.isActive()) return; span.finish(time); const idx = this._spanStack.findIndex((sp) => sp == span); if (idx !== -1) { this._spanStack.splice(idx, 1); this.span = this._spanStack[this._spanStack.length - 1]; } else { (_b = (_a = this.service) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.warn('This span is not assigned to this context', span); } } toJSON() { const res = _.pick(this, [ 'id', 'nodeID', 'action.name', 'event.name', 'service.name', 'service.version', 'service.fullName', 'options', 'parentID', 'caller', 'level', 'params', 'meta', 'requestID', 'tracing', 'span', 'needAck', 'ackID', 'eventName', 'eventType', 'eventGroups', 'cachedResult' ]); return res; } [util.inspect.custom](depth, options) { if (depth < 0) { return options === null || options === void 0 ? void 0 : options.stylize('[Context]', 'special'); } const inner = util.inspect(this.toJSON(), options); return `${options === null || options === void 0 ? void 0 : options.stylize('Context', 'special')}< ${inner} >`; } }function recreateError(error) { switch (error.name) { case UniverseErrorType.UniverseError: return new UniverseError(error.message, error.code, error.type, error.data); case UniverseErrorType.UniverseRetryableError: return new UniverseRetryableError(error.message, error.code, error.type, error.data); case UniverseErrorType.StarServerError: return new StarServerError(error.message, error.code, error.type, error.data); case UniverseErrorType.StarClientError: return new StarClientError(error.message, error.code, error.type, error.data); case UniverseErrorType.ValidationError: return new ValidationError(error.message, error.type, error.data); case UniverseErrorType.ServiceNotFoundError: return new ServiceNotFoundError(error.data); case UniverseErrorType.ServiceNotAvailableError: return new ServiceNotFoundError(error.data); case UniverseErrorType.RequestSkippedError: return new ServiceNotFoundError(error.data); case UniverseErrorType.RequestRejectedError: return new ServiceNotFoundError(error.data); case UniverseErrorType.RequestTimeoutError: return new ServiceNotFoundError(error.data); case UniverseErrorType.MaxCallLevelError: return new MaxCallLevelError(error.data); case UniverseErrorType.QueueIsFullError: return new QueueIsFullError(error.data); case UniverseErrorType.GracefulStopTimeoutError: return new GracefulStopTimeoutError(error.data); case UniverseErrorType.ProtocolVersionMismatchError: return new ProtocolVersionMismatchError(error.data); case UniverseErrorType.InvalidPacketDataError: return new InvalidPacketDataError(error.data); case UniverseErrorType.ServiceSchemaError: return new ServiceSchemaError(error.message, error.data); case UniverseErrorType.StarOptionsError: return new StarOptionsError(error.message, error.data); case UniverseErrorType.StarDisconnectedError: return new StarDisconnectedError(); } } class Regenerator { constructor() { this.star = null; } init(star) { this.star = star; } restore(plainError, payload) { let err = this.restoreCustomError(plainError, payload); if (!err) err = recreateError(plainError); if (!err) err = this.createDefaultError(plainError); this.restoreExternalFields(plainError, err, payload); this.restoreStack(plainError, err); return err; } extracPlainError(err, payload) { var _a; return { name: err.name, message: err.message, nodeID: err.nodeID || payload.nodeID || ((_a = this.star) === null || _a === void 0 ? void 0 : _a.nodeID), code: err.code, type: err.type, retryable: err.retryable, stack: err.stack, data: err.data }; } restoreCustomError(plainError, payload) { return undefined; } createDefaultError(plainError) { const err = new UniverseError(plainError.message); err.name = plainError.name; err.code = plainError.code; err.type = plainError.type; err.data = plainError.data; return err; } restoreExternalFields(plainError, err, payload) { err.retryable = plainError.retryable; err.nodeID = plainError.nodeID || payload.sender; } restoreStack(plainError, err) { if (plainError.stack) err.stack = plainError.stack; } } function resolveRengerator(options) { if (options instanceof Regenerator) { return options; } return new Regenerator(); }var BaseLoggerLevels; (function (BaseLoggerLevels) { BaseLoggerLevels["fatal"] = "fatal"; BaseLoggerLevels["error"] = "error"; BaseLoggerLevels["warn"] = "warn"; BaseLoggerLevels["debug"] = "debug"; BaseLoggerLevels["info"] = "info"; BaseLoggerLevels["trace"] = "trace"; })(BaseLoggerLevels || (BaseLoggerLevels = {}));const LEVELS = [ BaseLoggerLevels.fatal, BaseLoggerLevels.error, BaseLoggerLevels.warn, BaseLoggerLevels.debug, BaseLoggerLevels.info, BaseLoggerLevels.trace ]; class BaseLogger { constructor(options) { this.options = _.defaultsDeep(options, { level: BaseLoggerLevels.info, createLogger: null }); } init(loggerFactory) { this.loggerFactory = loggerFactory; this.star = loggerFactory.star; } stop() { return Promise.resolve(); } getLogLevel(mod) { const logMod = mod ? mod.toUpperCase() : ''; const level = this.options.level; if (isString(level)) return level; if (isObject(level)) { if (level[logMod]) return level[logMod]; const key = Object.keys(level).find((item) => matchActionOrEvent(logMod, item) && item !== '**'); if (key) return level[key]; else if (level['**']) { return level['**']; } } return null; } getLogHandler(bindings) { return null; } }function getColor(type) { switch (type) { case BaseLoggerLevels.fatal: return kleur.red().inverse; case BaseLoggerLevels.error: return kleur.red; case BaseLoggerLevels.warn: return kleur.yellow; case BaseLoggerLevels.debug: return kleur.magenta; case BaseLoggerLevels.trace: return kleur.gray; case BaseLoggerLevels.info: return kleur.green; default: return kleur.green; } } class FormattedLogger extends BaseLogger { constructor(options) { super(options); this.options = {}; this.maxPrefixLength = 0; this.levelColorStr = {}; this.options = _.defaultsDeep(this.options, options, { colors: true, moduleColors: false, formatter: 'full', objectPrinter: null, autoPadding: false }); this.maxPrefixLength = 0; } init(loggerFactory) { super.init(loggerFactory); if (!this.options.colors) kleur.enabled = false; this.objectPrinter = this.options.objectPrinter ? this.options.objectPrinter : (object) => util.inspect(object, { showHidden: false, depth: 2, colors: kleur.enabled, breakLength: Number.POSITIVE_INFINITY }); this.levelColorStr = LEVELS.reduce((err, level) => { err[level] = getColor(level)(_.padEnd(level.toUpperCase(), 5)); return err; }, {}); if (this.options.colors && this.options.moduleColor === true) { this.options.moduleColor = [ 'yellow', 'bold.yellow', 'cyan', 'bold.cyan', 'green', 'bold.green', 'magenta', 'bold.magenta', 'blue', 'bold.blue' ]; } } getNextColor(mod) { if (this.options.colors && Array.isArray(this.options.moduleColor)) { let hash = 0; for (let i = 0; i < mod.length; i++) { hash = (hash << 5) - hash + mod.charCodeAt(i); hash |= 0; } return this.options.moduleColor[Math.abs(hash) % this.options.moduleColor.length]; } return 'grey'; } padLeft(len) { if (this.options.autoPadding) return ' '.repeat(this.maxPrefixLength - len); return ''; } render(str, obj) { return str.replace(/\{\s?(\w+)\s?\}/g, (match, v) => obj[v] || ''); } getFormatter(bindings) { const formatter = this.options.formatter; const mod = bindings && bindings.mod ? bindings.mod.toUpperCase() : ''; const color = this.getNextColor(mod); const modColorName = color.split('.').reduce((a, b) => a[b] || a()[b], kleur)(mod); bindings ? kleur.grey(bindings.nodeID + '/') + modColorName : ''; const printAr