@orion-js/echoes 4.0.17 → 4.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -72,12 +72,13 @@ function serialize_default(data) {
72
72
  var import_jssha = __toESM(require("jssha"), 1);
73
73
 
74
74
  // src/request/getPassword.ts
75
+ var import_logger = require("@orion-js/logger");
75
76
  var import_env = require("@orion-js/env");
76
77
  function getEchoesPassword() {
77
78
  var _a, _b;
78
79
  const secret = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.key) || (0, import_env.internalGetEnv)("echoes_password", "ECHOES_PASSWORD");
79
80
  if (!secret) {
80
- console.warn(
81
+ import_logger.logger.warn(
81
82
  'Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD'
82
83
  );
83
84
  }
@@ -140,6 +141,7 @@ var requestsHandler_default = (options) => (0, import_http.route)({
140
141
 
141
142
  // src/startService/KafkaManager.ts
142
143
  var import_kafkajs = require("kafkajs");
144
+ var import_logger2 = require("@orion-js/logger");
143
145
  var HEARTBEAT_INTERVAL_SECONDS = 5;
144
146
  var CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30;
145
147
  var DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4;
@@ -166,7 +168,7 @@ var KafkaManager = class {
166
168
  const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId]);
167
169
  const group = groupDescriptions.groups[0];
168
170
  if (group.state === "Empty") {
169
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
171
+ import_logger2.logger.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
170
172
  return true;
171
173
  }
172
174
  const topicsMetadata = await admin.fetchTopicMetadata({ topics: this.topics });
@@ -174,23 +176,23 @@ var KafkaManager = class {
174
176
  (acc, topic) => acc + topic.partitions.length,
175
177
  0
176
178
  );
177
- console.info(
179
+ import_logger2.logger.info(
178
180
  `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`
179
181
  );
180
182
  const partitionsRatio = this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO;
181
183
  const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio);
182
184
  if (partitionsThreshold > group.members.length) {
183
- console.info(
185
+ import_logger2.logger.info(
184
186
  `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`
185
187
  );
186
188
  return true;
187
189
  }
188
190
  } catch (error) {
189
- console.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`);
191
+ import_logger2.logger.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`);
190
192
  return true;
191
193
  } finally {
192
194
  await admin.disconnect().catch((error) => {
193
- console.error(`Echoes: Error disconnecting admin client: ${error.message}`);
195
+ import_logger2.logger.error(`Echoes: Error disconnecting admin client: ${error.message}`);
194
196
  });
195
197
  }
196
198
  }
@@ -213,14 +215,14 @@ var KafkaManager = class {
213
215
  await this.producer.connect();
214
216
  this.started = await this.conditionalStart();
215
217
  if (this.started) return;
216
- console.info("Echoes: Delaying consumer group join, waiting for conditions to be met");
218
+ import_logger2.logger.info("Echoes: Delaying consumer group join, waiting for conditions to be met");
217
219
  this.interval = setInterval(async () => {
218
220
  this.started = await this.conditionalStart();
219
221
  if (this.started) clearInterval(this.interval);
220
222
  }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1e3);
221
223
  }
222
224
  async stop() {
223
- console.warn("Echoes: Stopping echoes");
225
+ import_logger2.logger.warn("Echoes: Stopping echoes");
224
226
  if (this.interval) clearInterval(this.interval);
225
227
  if (this.consumer) await this.consumer.disconnect();
226
228
  if (this.producer) await this.producer.disconnect();
@@ -228,17 +230,17 @@ var KafkaManager = class {
228
230
  async handleMessage(params) {
229
231
  const echo2 = this.options.echoes[params.topic];
230
232
  if (!echo2 || echo2.type !== "event") {
231
- console.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`);
233
+ import_logger2.logger.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`);
232
234
  return;
233
235
  }
234
236
  let intervalsCount = 0;
235
237
  const heartbeatInterval = setInterval(async () => {
236
238
  await params.heartbeat().catch((error) => {
237
- console.warn(`Echoes: Error sending heartbeat: ${error.message}`);
239
+ import_logger2.logger.warn(`Echoes: Error sending heartbeat: ${error.message}`);
238
240
  });
239
241
  intervalsCount++;
240
242
  if (intervalsCount * HEARTBEAT_INTERVAL_SECONDS % 30 === 0) {
241
- console.warn(
243
+ import_logger2.logger.warn(
242
244
  `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`
243
245
  );
244
246
  }
@@ -246,7 +248,7 @@ var KafkaManager = class {
246
248
  try {
247
249
  await echo2.onMessage(params).catch((error) => this.handleRetries(echo2, params, error));
248
250
  } catch (error) {
249
- console.error(`Echoes: error processing a message: ${params.topic} ${error.message}`);
251
+ import_logger2.logger.error(`Echoes: error processing a message: ${params.topic} ${error.message}`);
250
252
  throw error;
251
253
  } finally {
252
254
  clearInterval(heartbeatInterval);
@@ -275,11 +277,11 @@ var KafkaManager = class {
275
277
  ]
276
278
  });
277
279
  if (exceededMaxRetries) {
278
- console.error(
280
+ import_logger2.logger.error(
279
281
  `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`
280
282
  );
281
283
  } else {
282
- console.warn(
284
+ import_logger2.logger.warn(
283
285
  `Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`
284
286
  );
285
287
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/requestsHandler/getEcho.ts","../src/publish/serialize.ts","../src/request/getSignature.ts","../src/request/getPassword.ts","../src/requestsHandler/checkSignature.ts","../src/requestsHandler/index.ts","../src/startService/KafkaManager.ts","../src/startService/index.ts","../src/publish/index.ts","../src/request/getURL.ts","../src/echo/deserialize.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/echo/index.ts","../src/service/index.ts"],"sourcesContent":["import startService, {stopService} from './startService'\nimport publish from './publish'\nimport request from './request'\n\nexport * from './types'\nexport * from './service'\nexport * from './echo'\n\nexport {publish, startService, stopService, request}\n","import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","import config from '../config'\n\nexport default function (method: string) {\n const echo = config.echoes[method]\n\n if (!echo) {\n throw new Error(`Echo named ${method} not found in this service`)\n }\n\n if (echo.type !== 'request') {\n throw new Error(`Echo named ${method} is not of type request`)\n }\n\n return echo\n}\n","import serialize from 'serialize-javascript'\nimport {clone} from '@orion-js/helpers'\n\nexport default function (data: any): string {\n const cloned = clone(data)\n const serialized = serialize(cloned, {ignoreFunction: true})\n return serialized\n}\n","import JSSHA from 'jssha'\nimport {getEchoesPassword} from './getPassword'\n\nexport default function (body: any): string {\n const password = getEchoesPassword()\n const shaObj = new JSSHA('SHA-1', 'TEXT')\n shaObj.setHMACKey(password, 'TEXT')\n shaObj.update(body)\n return shaObj.getHMAC('HEX')\n}\n","import config from '../config'\nimport {internalGetEnv} from '@orion-js/env'\n\nexport function getEchoesPassword() {\n const secret = config?.requests?.key || internalGetEnv('echoes_password', 'ECHOES_PASSWORD')\n if (!secret) {\n console.warn(\n 'Warning: no secret key found for echoes requests. Init echoes or set the env var \"echoes_password\" or process.env.ECHOES_PASSWORD',\n )\n }\n\n return secret\n}\n","import getSignature from '../request/getSignature'\n\nexport default function (body: any, signature: string) {\n const generatedSignature = getSignature(body)\n if (generatedSignature !== signature) {\n throw new Error('Echoes invalid signature')\n }\n}\n","import getEcho from './getEcho'\nimport serialize from '../publish/serialize'\nimport checkSignature from './checkSignature'\nimport {route} from '@orion-js/http'\nimport {EchoesOptions} from '../types'\n\nexport default (options: EchoesOptions) =>\n route({\n method: 'post',\n path: options.requests.handlerPath || '/echoes-services',\n bodyParser: 'json',\n bodyParserOptions: {\n limit: '10mb',\n },\n async resolve(req) {\n try {\n const {body, signature} = req.body\n\n checkSignature(body, signature)\n\n const {method, serializedParams} = body\n\n const echo = getEcho(method)\n const result = await echo.onRequest(serializedParams)\n\n return {\n body: {\n result: serialize(result),\n },\n }\n } catch (error) {\n if (!error.getInfo) {\n console.error('Error at echo requests handler:', error)\n }\n\n return {\n body: {\n error: error.message,\n errorInfo: error.getInfo ? error.getInfo() : null,\n isValidationError: !!error.isValidationError,\n isUserError: !!error.isUserError,\n },\n }\n }\n },\n })\n","import {Kafka, EachMessagePayload, Producer, Consumer} from 'kafkajs'\nimport {EchoesOptions, EchoType} from '../types'\n\nconst HEARTBEAT_INTERVAL_SECONDS = 5 // This value must be less than the kafkajs session timeout\nconst CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30\nconst DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4 // How many partitions to consume concurrently, adjust this with the members to partitions ratio to avoid idle consumers.\nconst DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1 // How many members are in comparison to partitions, this is used to determine if the consumer group has room for more members. Numbers over 1 leads to idle consumers. Numbers under 1 needs partitionsConsumedConcurrently to be more than 1.\n\n/**\n * Manages the Kafka connection and the consumers.\n */\nclass KafkaManager {\n kafka: Kafka\n options: EchoesOptions\n producer: Producer\n consumer: Consumer\n topics: string[]\n started: boolean\n interval: NodeJS.Timeout\n\n constructor(options: EchoesOptions) {\n this.kafka = new Kafka(options.client)\n this.options = options\n this.producer = this.kafka.producer(options.producer)\n this.consumer = this.kafka.consumer(options.consumer)\n this.topics = Object.keys(options.echoes).filter(key => options.echoes[key].type === 'event')\n }\n\n async checkJoinConsumerGroupConditions(): Promise<boolean> {\n const admin = this.kafka.admin()\n try {\n await admin.connect()\n const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId])\n const group = groupDescriptions.groups[0]\n if (group.state === 'Empty') {\n console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`)\n return true\n }\n const topicsMetadata = await admin.fetchTopicMetadata({topics: this.topics})\n const totalPartitions = topicsMetadata.topics.reduce(\n (acc, topic) => acc + topic.partitions.length,\n 0,\n )\n console.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`,\n )\n const partitionsRatio =\n this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO\n const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio)\n if (partitionsThreshold > group.members.length) {\n console.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`,\n )\n return true\n }\n } catch (error) {\n console.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`)\n return true\n } finally {\n await admin.disconnect().catch(error => {\n console.error(`Echoes: Error disconnecting admin client: ${error.message}`)\n })\n }\n }\n\n async joinConsumerGroup() {\n await this.consumer.connect()\n await this.consumer.subscribe({topics: this.topics})\n await this.consumer.run({\n partitionsConsumedConcurrently:\n this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,\n eachMessage: params => this.handleMessage(params),\n })\n }\n\n async conditionalStart(): Promise<boolean> {\n if (await this.checkJoinConsumerGroupConditions()) {\n await this.joinConsumerGroup()\n return true\n }\n }\n\n async start() {\n if (this.started) return\n await this.producer.connect()\n this.started = await this.conditionalStart()\n if (this.started) return\n console.info('Echoes: Delaying consumer group join, waiting for conditions to be met')\n this.interval = setInterval(async () => {\n this.started = await this.conditionalStart()\n if (this.started) clearInterval(this.interval)\n }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1000)\n }\n\n async stop() {\n console.warn('Echoes: Stopping echoes')\n if (this.interval) clearInterval(this.interval)\n if (this.consumer) await this.consumer.disconnect()\n if (this.producer) await this.producer.disconnect()\n }\n\n async handleMessage(params: EachMessagePayload) {\n const echo = this.options.echoes[params.topic]\n if (!echo || echo.type !== 'event') {\n console.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`)\n return\n }\n\n let intervalsCount = 0\n const heartbeatInterval = setInterval(async () => {\n await params.heartbeat().catch(error => {\n console.warn(`Echoes: Error sending heartbeat: ${error.message}`)\n })\n intervalsCount++\n if ((intervalsCount * HEARTBEAT_INTERVAL_SECONDS) % 30 === 0) {\n console.warn(\n `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`,\n )\n }\n }, HEARTBEAT_INTERVAL_SECONDS * 1000)\n\n try {\n await echo.onMessage(params).catch(error => this.handleRetries(echo, params, error))\n } catch (error) {\n console.error(`Echoes: error processing a message: ${params.topic} ${error.message}`)\n throw error\n } finally {\n clearInterval(heartbeatInterval)\n }\n }\n\n async handleRetries(echo: EchoType, params: EachMessagePayload, error: Error) {\n const {message, topic} = params\n const retries = Number.parseInt(message?.headers?.retries?.toString() || '0', 10)\n if (echo.attemptsBeforeDeadLetter === undefined || echo.attemptsBeforeDeadLetter === null) {\n throw error\n }\n const maxRetries = echo.attemptsBeforeDeadLetter || 0\n const exceededMaxRetries = retries >= maxRetries\n const nextTopic = exceededMaxRetries ? `DLQ-${topic}` : topic\n await this.producer.send({\n topic: nextTopic,\n messages: [\n {\n value: message.value.toString(),\n headers: {\n retries: String(retries + 1),\n error: error.message,\n },\n },\n ],\n })\n\n if (exceededMaxRetries) {\n console.error(\n `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`,\n )\n } else {\n console.warn(\n `Echoes: a retryable message failed \"${error.message}\", re-sending it to topic: ${nextTopic}`,\n )\n }\n }\n}\n\nexport default KafkaManager\n","import config from '../config'\nimport requestsHandler from '../requestsHandler'\nimport {EchoesOptions} from '../types'\nimport KafkaManager from './KafkaManager'\nimport {registerRoute} from '@orion-js/http'\n\nlet kafkaManager: KafkaManager = null\n\nexport default async function startService(options: EchoesOptions) {\n config.echoes = options.echoes\n\n if (options.requests) {\n config.requests = options.requests\n registerRoute(requestsHandler(options))\n }\n\n if (options.client) {\n kafkaManager = new KafkaManager(options)\n await kafkaManager.start()\n config.producer = kafkaManager.producer\n config.consumer = kafkaManager.consumer\n }\n}\n\nexport async function stopService() {\n if (kafkaManager) {\n console.info('Stoping echoes...')\n await kafkaManager.stop()\n console.info('Echoes stopped')\n }\n}\n","import config from '../config'\nimport {PublishOptions} from '../types'\nimport serialize from './serialize'\n\n/**\n * Publish\n */\nexport default async function publish<TParams = any>(options: PublishOptions<TParams>) {\n if (!config.producer) {\n throw new Error('You must initialize echoes configruation to use publish')\n }\n\n const payload = {\n params: options.params,\n }\n\n return await config.producer.send({\n acks: options.acks,\n timeout: options.timeout,\n topic: options.topic,\n messages: [\n {\n value: serialize(payload),\n },\n ],\n })\n}\n","import config from '../config'\n\nexport default function (serviceName: string): string {\n if (serviceName.startsWith('http')) return serviceName\n\n const url = config?.requests?.services[serviceName]\n\n if (!url) {\n throw new Error(`No URL found in echoes config for service ${serviceName}`)\n }\n\n return url\n}\n","export default function (serializedJavascript: string): any {\n try {\n return eval('(' + serializedJavascript + ')')\n } catch (error) {\n throw new Error('Error deserializing echo message')\n }\n}\n","import axios from 'axios'\nimport {RequestMaker} from '../types'\nimport {executeWithRetries} from '@orion-js/helpers'\n\nexport const makeRequest: RequestMaker = async options => {\n const result = await executeWithRetries(\n async () => {\n return await axios({\n method: 'post',\n url: options.url,\n timeout: options.timeout,\n headers: {\n 'User-Agent': 'Orionjs-Echoes/1.1',\n },\n data: options.data,\n })\n },\n options.retries,\n 200,\n )\n\n return {\n data: result.data as object,\n statusCode: result.status,\n }\n}\n","import getURL from './getURL'\nimport getSignature from './getSignature'\nimport serialize from '../publish/serialize'\nimport deserialize from '../echo/deserialize'\nimport type {\n MakeRequestParams,\n RequestHandlerResponse,\n RequestMaker,\n RequestOptions,\n} from '../types'\nimport config from '../config'\nimport {makeRequest} from './makeRequest'\nimport {ValidationError} from '@orion-js/schema'\nimport {UserError} from '@orion-js/helpers'\n\nexport default async function request<TData = any, TParams = any>(\n options: RequestOptions<TParams>,\n): Promise<TData> {\n const {method, service, params} = options\n const serializedParams = serialize(params)\n const date = new Date()\n const body = {method, service, serializedParams, date}\n const signature = getSignature(body)\n\n try {\n const requestMaker: RequestMaker = config?.requests?.makeRequest || makeRequest\n const requestOptions: MakeRequestParams = {\n url: getURL(service),\n retries: options.retries,\n timeout: options.timeout,\n data: {\n body,\n signature,\n },\n }\n const result = await requestMaker(requestOptions)\n\n if (result.statusCode !== 200) {\n throw new Error(`Wrong status code ${result.statusCode}`)\n }\n\n const data: RequestHandlerResponse = result.data\n\n if (data.error) {\n const info = data.errorInfo\n if (info) {\n if (data.isValidationError) {\n throw new ValidationError(info.validationErrors)\n }\n if (data.isUserError) {\n throw new UserError(info.error, info.message, info.extra)\n }\n }\n\n throw new Error(`${data.error}`)\n }\n\n const response = deserialize(data.result)\n return response\n } catch (error) {\n if (error.isOrionError) throw error\n\n throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`)\n }\n}\n","import {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig, EchoRequestConfig, EchoEventConfig} from '../types'\nimport deserialize from './deserialize'\nimport {clean, cleanAndValidate, InferSchemaType} from '@orion-js/schema'\nimport {SchemaFieldType} from '@orion-js/schema'\n\n/**\n * @deprecated Use createEchoRequest and createEchoEvent instead\n */\nconst echo = function createNewEcho<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n TEchoType extends 'event' | 'request',\n>(\n options: EchoConfig<TParamsSchema, TReturnsSchema, TEchoType>,\n): EchoType<TParamsSchema, TReturnsSchema, TEchoType> {\n const resolve = async (params: InferSchemaType<TParamsSchema>, context: any) => {\n const cleaned = options.params\n ? await cleanAndValidate(options.params, params)\n : (params ?? ({} as InferSchemaType<TParamsSchema>))\n\n const result = await options.resolve(cleaned, context)\n\n if (options.returns) {\n return await clean(options.returns, result)\n }\n\n return result\n }\n\n return {\n type: options.type,\n params: options.params,\n returns: options.returns,\n attemptsBeforeDeadLetter:\n options.type === 'event' ? options.attemptsBeforeDeadLetter : undefined,\n resolve,\n onMessage: async (messageData: EachMessagePayload) => {\n const {message} = messageData\n\n const data = deserialize(message.value.toString())\n\n const context = {\n ...messageData,\n data,\n }\n\n await resolve(data.params, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n\n return await resolve(params, context)\n },\n }\n}\n\nexport function createEchoRequest<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoRequestConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'request'> {\n return echo({...options, type: 'request'})\n}\nexport function createEchoEvent<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoEventConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'event'> {\n return echo({...options, type: 'event' as any})\n}\n\nexport {echo}\n","import {createEchoEvent, createEchoRequest} from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\nimport {getInstance, Service} from '@orion-js/services'\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig<any, any>['resolve']\n}\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst echoesMetadata = new WeakMap<any, Record<string, any>>()\n\nexport function Echoes() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'echoes'})\n })\n }\n}\n\nexport function EchoEvent(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoEvent(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoEvent(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoEvent({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoRequest(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoRequest(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoRequest({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'echoes') {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const echoesMap = echoesMetadata.get(instance) || {}\n\n return echoesMap\n}\n"],"mappings":"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","names":["echo","serialize","JSSHA","echo","echo","import_http","import_helpers","axios","import_helpers","import_schema"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/requestsHandler/getEcho.ts","../src/publish/serialize.ts","../src/request/getSignature.ts","../src/request/getPassword.ts","../src/requestsHandler/checkSignature.ts","../src/requestsHandler/index.ts","../src/startService/KafkaManager.ts","../src/startService/index.ts","../src/publish/index.ts","../src/request/getURL.ts","../src/echo/deserialize.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/echo/index.ts","../src/service/index.ts"],"sourcesContent":["import startService, {stopService} from './startService'\nimport publish from './publish'\nimport request from './request'\n\nexport * from './types'\nexport * from './service'\nexport * from './echo'\n\nexport {publish, startService, stopService, request}\n","import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","import config from '../config'\n\nexport default function (method: string) {\n const echo = config.echoes[method]\n\n if (!echo) {\n throw new Error(`Echo named ${method} not found in this service`)\n }\n\n if (echo.type !== 'request') {\n throw new Error(`Echo named ${method} is not of type request`)\n }\n\n return echo\n}\n","import serialize from 'serialize-javascript'\nimport {clone} from '@orion-js/helpers'\n\nexport default function (data: any): string {\n const cloned = clone(data)\n const serialized = serialize(cloned, {ignoreFunction: true})\n return serialized\n}\n","import JSSHA from 'jssha'\nimport {getEchoesPassword} from './getPassword'\n\nexport default function (body: any): string {\n const password = getEchoesPassword()\n const shaObj = new JSSHA('SHA-1', 'TEXT')\n shaObj.setHMACKey(password, 'TEXT')\n shaObj.update(body)\n return shaObj.getHMAC('HEX')\n}\n","import {logger} from '@orion-js/logger'\nimport config from '../config'\nimport {internalGetEnv} from '@orion-js/env'\n\nexport function getEchoesPassword() {\n const secret = config?.requests?.key || internalGetEnv('echoes_password', 'ECHOES_PASSWORD')\n if (!secret) {\n logger.warn(\n 'Warning: no secret key found for echoes requests. Init echoes or set the env var \"echoes_password\" or process.env.ECHOES_PASSWORD',\n )\n }\n\n return secret\n}\n","import getSignature from '../request/getSignature'\n\nexport default function (body: any, signature: string) {\n const generatedSignature = getSignature(body)\n if (generatedSignature !== signature) {\n throw new Error('Echoes invalid signature')\n }\n}\n","import getEcho from './getEcho'\nimport serialize from '../publish/serialize'\nimport checkSignature from './checkSignature'\nimport {route} from '@orion-js/http'\nimport {EchoesOptions} from '../types'\n\nexport default (options: EchoesOptions) =>\n route({\n method: 'post',\n path: options.requests.handlerPath || '/echoes-services',\n bodyParser: 'json',\n bodyParserOptions: {\n limit: '10mb',\n },\n async resolve(req) {\n try {\n const {body, signature} = req.body\n\n checkSignature(body, signature)\n\n const {method, serializedParams} = body\n\n const echo = getEcho(method)\n const result = await echo.onRequest(serializedParams)\n\n return {\n body: {\n result: serialize(result),\n },\n }\n } catch (error) {\n if (!error.getInfo) {\n console.error('Error at echo requests handler:', error)\n }\n\n return {\n body: {\n error: error.message,\n errorInfo: error.getInfo ? error.getInfo() : null,\n isValidationError: !!error.isValidationError,\n isUserError: !!error.isUserError,\n },\n }\n }\n },\n })\n","import {Kafka, EachMessagePayload, Producer, Consumer} from 'kafkajs'\nimport {EchoesOptions, EchoType} from '../types'\nimport {logger} from '@orion-js/logger'\n\nconst HEARTBEAT_INTERVAL_SECONDS = 5 // This value must be less than the kafkajs session timeout\nconst CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30\nconst DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4 // How many partitions to consume concurrently, adjust this with the members to partitions ratio to avoid idle consumers.\nconst DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1 // How many members are in comparison to partitions, this is used to determine if the consumer group has room for more members. Numbers over 1 leads to idle consumers. Numbers under 1 needs partitionsConsumedConcurrently to be more than 1.\n\n/**\n * Manages the Kafka connection and the consumers.\n */\nclass KafkaManager {\n kafka: Kafka\n options: EchoesOptions\n producer: Producer\n consumer: Consumer\n topics: string[]\n started: boolean\n interval: NodeJS.Timeout\n\n constructor(options: EchoesOptions) {\n this.kafka = new Kafka(options.client)\n this.options = options\n this.producer = this.kafka.producer(options.producer)\n this.consumer = this.kafka.consumer(options.consumer)\n this.topics = Object.keys(options.echoes).filter(key => options.echoes[key].type === 'event')\n }\n\n async checkJoinConsumerGroupConditions(): Promise<boolean> {\n const admin = this.kafka.admin()\n try {\n await admin.connect()\n const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId])\n const group = groupDescriptions.groups[0]\n if (group.state === 'Empty') {\n logger.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`)\n return true\n }\n const topicsMetadata = await admin.fetchTopicMetadata({topics: this.topics})\n const totalPartitions = topicsMetadata.topics.reduce(\n (acc, topic) => acc + topic.partitions.length,\n 0,\n )\n logger.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`,\n )\n const partitionsRatio =\n this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO\n const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio)\n if (partitionsThreshold > group.members.length) {\n logger.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`,\n )\n return true\n }\n } catch (error) {\n logger.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`)\n return true\n } finally {\n await admin.disconnect().catch(error => {\n logger.error(`Echoes: Error disconnecting admin client: ${error.message}`)\n })\n }\n }\n\n async joinConsumerGroup() {\n await this.consumer.connect()\n await this.consumer.subscribe({topics: this.topics})\n await this.consumer.run({\n partitionsConsumedConcurrently:\n this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,\n eachMessage: params => this.handleMessage(params),\n })\n }\n\n async conditionalStart(): Promise<boolean> {\n if (await this.checkJoinConsumerGroupConditions()) {\n await this.joinConsumerGroup()\n return true\n }\n }\n\n async start() {\n if (this.started) return\n await this.producer.connect()\n this.started = await this.conditionalStart()\n if (this.started) return\n logger.info('Echoes: Delaying consumer group join, waiting for conditions to be met')\n this.interval = setInterval(async () => {\n this.started = await this.conditionalStart()\n if (this.started) clearInterval(this.interval)\n }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1000)\n }\n\n async stop() {\n logger.warn('Echoes: Stopping echoes')\n if (this.interval) clearInterval(this.interval)\n if (this.consumer) await this.consumer.disconnect()\n if (this.producer) await this.producer.disconnect()\n }\n\n async handleMessage(params: EachMessagePayload) {\n const echo = this.options.echoes[params.topic]\n if (!echo || echo.type !== 'event') {\n logger.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`)\n return\n }\n\n let intervalsCount = 0\n const heartbeatInterval = setInterval(async () => {\n await params.heartbeat().catch(error => {\n logger.warn(`Echoes: Error sending heartbeat: ${error.message}`)\n })\n intervalsCount++\n if ((intervalsCount * HEARTBEAT_INTERVAL_SECONDS) % 30 === 0) {\n logger.warn(\n `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`,\n )\n }\n }, HEARTBEAT_INTERVAL_SECONDS * 1000)\n\n try {\n await echo.onMessage(params).catch(error => this.handleRetries(echo, params, error))\n } catch (error) {\n logger.error(`Echoes: error processing a message: ${params.topic} ${error.message}`)\n throw error\n } finally {\n clearInterval(heartbeatInterval)\n }\n }\n\n async handleRetries(echo: EchoType, params: EachMessagePayload, error: Error) {\n const {message, topic} = params\n const retries = Number.parseInt(message?.headers?.retries?.toString() || '0', 10)\n if (echo.attemptsBeforeDeadLetter === undefined || echo.attemptsBeforeDeadLetter === null) {\n throw error\n }\n const maxRetries = echo.attemptsBeforeDeadLetter || 0\n const exceededMaxRetries = retries >= maxRetries\n const nextTopic = exceededMaxRetries ? `DLQ-${topic}` : topic\n await this.producer.send({\n topic: nextTopic,\n messages: [\n {\n value: message.value.toString(),\n headers: {\n retries: String(retries + 1),\n error: error.message,\n },\n },\n ],\n })\n\n if (exceededMaxRetries) {\n logger.error(\n `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`,\n )\n } else {\n logger.warn(\n `Echoes: a retryable message failed \"${error.message}\", re-sending it to topic: ${nextTopic}`,\n )\n }\n }\n}\n\nexport default KafkaManager\n","import config from '../config'\nimport requestsHandler from '../requestsHandler'\nimport {EchoesOptions} from '../types'\nimport KafkaManager from './KafkaManager'\nimport {registerRoute} from '@orion-js/http'\n\nlet kafkaManager: KafkaManager = null\n\nexport default async function startService(options: EchoesOptions) {\n config.echoes = options.echoes\n\n if (options.requests) {\n config.requests = options.requests\n registerRoute(requestsHandler(options))\n }\n\n if (options.client) {\n kafkaManager = new KafkaManager(options)\n await kafkaManager.start()\n config.producer = kafkaManager.producer\n config.consumer = kafkaManager.consumer\n }\n}\n\nexport async function stopService() {\n if (kafkaManager) {\n console.info('Stoping echoes...')\n await kafkaManager.stop()\n console.info('Echoes stopped')\n }\n}\n","import config from '../config'\nimport {PublishOptions} from '../types'\nimport serialize from './serialize'\n\n/**\n * Publish\n */\nexport default async function publish<TParams = any>(options: PublishOptions<TParams>) {\n if (!config.producer) {\n throw new Error('You must initialize echoes configruation to use publish')\n }\n\n const payload = {\n params: options.params,\n }\n\n return await config.producer.send({\n acks: options.acks,\n timeout: options.timeout,\n topic: options.topic,\n messages: [\n {\n value: serialize(payload),\n },\n ],\n })\n}\n","import config from '../config'\n\nexport default function (serviceName: string): string {\n if (serviceName.startsWith('http')) return serviceName\n\n const url = config?.requests?.services[serviceName]\n\n if (!url) {\n throw new Error(`No URL found in echoes config for service ${serviceName}`)\n }\n\n return url\n}\n","export default function (serializedJavascript: string): any {\n try {\n return eval('(' + serializedJavascript + ')')\n } catch (error) {\n throw new Error('Error deserializing echo message')\n }\n}\n","import axios from 'axios'\nimport {RequestMaker} from '../types'\nimport {executeWithRetries} from '@orion-js/helpers'\n\nexport const makeRequest: RequestMaker = async options => {\n const result = await executeWithRetries(\n async () => {\n return await axios({\n method: 'post',\n url: options.url,\n timeout: options.timeout,\n headers: {\n 'User-Agent': 'Orionjs-Echoes/1.1',\n },\n data: options.data,\n })\n },\n options.retries,\n 200,\n )\n\n return {\n data: result.data as object,\n statusCode: result.status,\n }\n}\n","import getURL from './getURL'\nimport getSignature from './getSignature'\nimport serialize from '../publish/serialize'\nimport deserialize from '../echo/deserialize'\nimport type {\n MakeRequestParams,\n RequestHandlerResponse,\n RequestMaker,\n RequestOptions,\n} from '../types'\nimport config from '../config'\nimport {makeRequest} from './makeRequest'\nimport {ValidationError} from '@orion-js/schema'\nimport {UserError} from '@orion-js/helpers'\n\nexport default async function request<TData = any, TParams = any>(\n options: RequestOptions<TParams>,\n): Promise<TData> {\n const {method, service, params} = options\n const serializedParams = serialize(params)\n const date = new Date()\n const body = {method, service, serializedParams, date}\n const signature = getSignature(body)\n\n try {\n const requestMaker: RequestMaker = config?.requests?.makeRequest || makeRequest\n const requestOptions: MakeRequestParams = {\n url: getURL(service),\n retries: options.retries,\n timeout: options.timeout,\n data: {\n body,\n signature,\n },\n }\n const result = await requestMaker(requestOptions)\n\n if (result.statusCode !== 200) {\n throw new Error(`Wrong status code ${result.statusCode}`)\n }\n\n const data: RequestHandlerResponse = result.data\n\n if (data.error) {\n const info = data.errorInfo\n if (info) {\n if (data.isValidationError) {\n throw new ValidationError(info.validationErrors)\n }\n if (data.isUserError) {\n throw new UserError(info.error, info.message, info.extra)\n }\n }\n\n throw new Error(`${data.error}`)\n }\n\n const response = deserialize(data.result)\n return response\n } catch (error) {\n if (error.isOrionError) throw error\n\n throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`)\n }\n}\n","import {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig, EchoRequestConfig, EchoEventConfig} from '../types'\nimport deserialize from './deserialize'\nimport {clean, cleanAndValidate, InferSchemaType} from '@orion-js/schema'\nimport {SchemaFieldType} from '@orion-js/schema'\n\n/**\n * @deprecated Use createEchoRequest and createEchoEvent instead\n */\nconst echo = function createNewEcho<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n TEchoType extends 'event' | 'request',\n>(\n options: EchoConfig<TParamsSchema, TReturnsSchema, TEchoType>,\n): EchoType<TParamsSchema, TReturnsSchema, TEchoType> {\n const resolve = async (params: InferSchemaType<TParamsSchema>, context: any) => {\n const cleaned = options.params\n ? await cleanAndValidate(options.params, params)\n : (params ?? ({} as InferSchemaType<TParamsSchema>))\n\n const result = await options.resolve(cleaned, context)\n\n if (options.returns) {\n return await clean(options.returns, result)\n }\n\n return result\n }\n\n return {\n type: options.type,\n params: options.params,\n returns: options.returns,\n attemptsBeforeDeadLetter:\n options.type === 'event' ? options.attemptsBeforeDeadLetter : undefined,\n resolve,\n onMessage: async (messageData: EachMessagePayload) => {\n const {message} = messageData\n\n const data = deserialize(message.value.toString())\n\n const context = {\n ...messageData,\n data,\n }\n\n await resolve(data.params, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n\n return await resolve(params, context)\n },\n }\n}\n\nexport function createEchoRequest<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoRequestConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'request'> {\n return echo({...options, type: 'request'})\n}\nexport function createEchoEvent<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoEventConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'event'> {\n return echo({...options, type: 'event' as any})\n}\n\nexport {echo}\n","import {createEchoEvent, createEchoRequest} from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\nimport {getInstance, Service} from '@orion-js/services'\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig<any, any>['resolve']\n}\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst echoesMetadata = new WeakMap<any, Record<string, any>>()\n\nexport function Echoes() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'echoes'})\n })\n }\n}\n\nexport function EchoEvent(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoEvent(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoEvent(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoEvent({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoRequest(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoRequest(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoRequest({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'echoes') {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const echoesMap = echoesMetadata.get(instance) || {}\n\n return echoesMap\n}\n"],"mappings":"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","names":["echo","serialize","JSSHA","echo","import_logger","echo","import_http","import_helpers","axios","import_helpers","import_schema"]}
package/dist/index.js CHANGED
@@ -27,12 +27,13 @@ function serialize_default(data) {
27
27
  import JSSHA from "jssha";
28
28
 
29
29
  // src/request/getPassword.ts
30
+ import { logger } from "@orion-js/logger";
30
31
  import { internalGetEnv } from "@orion-js/env";
31
32
  function getEchoesPassword() {
32
33
  var _a, _b;
33
34
  const secret = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.key) || internalGetEnv("echoes_password", "ECHOES_PASSWORD");
34
35
  if (!secret) {
35
- console.warn(
36
+ logger.warn(
36
37
  'Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD'
37
38
  );
38
39
  }
@@ -95,6 +96,7 @@ var requestsHandler_default = (options) => route({
95
96
 
96
97
  // src/startService/KafkaManager.ts
97
98
  import { Kafka } from "kafkajs";
99
+ import { logger as logger2 } from "@orion-js/logger";
98
100
  var HEARTBEAT_INTERVAL_SECONDS = 5;
99
101
  var CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30;
100
102
  var DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4;
@@ -121,7 +123,7 @@ var KafkaManager = class {
121
123
  const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId]);
122
124
  const group = groupDescriptions.groups[0];
123
125
  if (group.state === "Empty") {
124
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
126
+ logger2.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
125
127
  return true;
126
128
  }
127
129
  const topicsMetadata = await admin.fetchTopicMetadata({ topics: this.topics });
@@ -129,23 +131,23 @@ var KafkaManager = class {
129
131
  (acc, topic) => acc + topic.partitions.length,
130
132
  0
131
133
  );
132
- console.info(
134
+ logger2.info(
133
135
  `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`
134
136
  );
135
137
  const partitionsRatio = this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO;
136
138
  const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio);
137
139
  if (partitionsThreshold > group.members.length) {
138
- console.info(
140
+ logger2.info(
139
141
  `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`
140
142
  );
141
143
  return true;
142
144
  }
143
145
  } catch (error) {
144
- console.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`);
146
+ logger2.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`);
145
147
  return true;
146
148
  } finally {
147
149
  await admin.disconnect().catch((error) => {
148
- console.error(`Echoes: Error disconnecting admin client: ${error.message}`);
150
+ logger2.error(`Echoes: Error disconnecting admin client: ${error.message}`);
149
151
  });
150
152
  }
151
153
  }
@@ -168,14 +170,14 @@ var KafkaManager = class {
168
170
  await this.producer.connect();
169
171
  this.started = await this.conditionalStart();
170
172
  if (this.started) return;
171
- console.info("Echoes: Delaying consumer group join, waiting for conditions to be met");
173
+ logger2.info("Echoes: Delaying consumer group join, waiting for conditions to be met");
172
174
  this.interval = setInterval(async () => {
173
175
  this.started = await this.conditionalStart();
174
176
  if (this.started) clearInterval(this.interval);
175
177
  }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1e3);
176
178
  }
177
179
  async stop() {
178
- console.warn("Echoes: Stopping echoes");
180
+ logger2.warn("Echoes: Stopping echoes");
179
181
  if (this.interval) clearInterval(this.interval);
180
182
  if (this.consumer) await this.consumer.disconnect();
181
183
  if (this.producer) await this.producer.disconnect();
@@ -183,17 +185,17 @@ var KafkaManager = class {
183
185
  async handleMessage(params) {
184
186
  const echo2 = this.options.echoes[params.topic];
185
187
  if (!echo2 || echo2.type !== "event") {
186
- console.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`);
188
+ logger2.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`);
187
189
  return;
188
190
  }
189
191
  let intervalsCount = 0;
190
192
  const heartbeatInterval = setInterval(async () => {
191
193
  await params.heartbeat().catch((error) => {
192
- console.warn(`Echoes: Error sending heartbeat: ${error.message}`);
194
+ logger2.warn(`Echoes: Error sending heartbeat: ${error.message}`);
193
195
  });
194
196
  intervalsCount++;
195
197
  if (intervalsCount * HEARTBEAT_INTERVAL_SECONDS % 30 === 0) {
196
- console.warn(
198
+ logger2.warn(
197
199
  `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`
198
200
  );
199
201
  }
@@ -201,7 +203,7 @@ var KafkaManager = class {
201
203
  try {
202
204
  await echo2.onMessage(params).catch((error) => this.handleRetries(echo2, params, error));
203
205
  } catch (error) {
204
- console.error(`Echoes: error processing a message: ${params.topic} ${error.message}`);
206
+ logger2.error(`Echoes: error processing a message: ${params.topic} ${error.message}`);
205
207
  throw error;
206
208
  } finally {
207
209
  clearInterval(heartbeatInterval);
@@ -230,11 +232,11 @@ var KafkaManager = class {
230
232
  ]
231
233
  });
232
234
  if (exceededMaxRetries) {
233
- console.error(
235
+ logger2.error(
234
236
  `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`
235
237
  );
236
238
  } else {
237
- console.warn(
239
+ logger2.warn(
238
240
  `Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`
239
241
  );
240
242
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/requestsHandler/getEcho.ts","../src/publish/serialize.ts","../src/request/getSignature.ts","../src/request/getPassword.ts","../src/requestsHandler/checkSignature.ts","../src/requestsHandler/index.ts","../src/startService/KafkaManager.ts","../src/startService/index.ts","../src/publish/index.ts","../src/request/getURL.ts","../src/echo/deserialize.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/echo/index.ts","../src/service/index.ts"],"sourcesContent":["import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","import config from '../config'\n\nexport default function (method: string) {\n const echo = config.echoes[method]\n\n if (!echo) {\n throw new Error(`Echo named ${method} not found in this service`)\n }\n\n if (echo.type !== 'request') {\n throw new Error(`Echo named ${method} is not of type request`)\n }\n\n return echo\n}\n","import serialize from 'serialize-javascript'\nimport {clone} from '@orion-js/helpers'\n\nexport default function (data: any): string {\n const cloned = clone(data)\n const serialized = serialize(cloned, {ignoreFunction: true})\n return serialized\n}\n","import JSSHA from 'jssha'\nimport {getEchoesPassword} from './getPassword'\n\nexport default function (body: any): string {\n const password = getEchoesPassword()\n const shaObj = new JSSHA('SHA-1', 'TEXT')\n shaObj.setHMACKey(password, 'TEXT')\n shaObj.update(body)\n return shaObj.getHMAC('HEX')\n}\n","import config from '../config'\nimport {internalGetEnv} from '@orion-js/env'\n\nexport function getEchoesPassword() {\n const secret = config?.requests?.key || internalGetEnv('echoes_password', 'ECHOES_PASSWORD')\n if (!secret) {\n console.warn(\n 'Warning: no secret key found for echoes requests. Init echoes or set the env var \"echoes_password\" or process.env.ECHOES_PASSWORD',\n )\n }\n\n return secret\n}\n","import getSignature from '../request/getSignature'\n\nexport default function (body: any, signature: string) {\n const generatedSignature = getSignature(body)\n if (generatedSignature !== signature) {\n throw new Error('Echoes invalid signature')\n }\n}\n","import getEcho from './getEcho'\nimport serialize from '../publish/serialize'\nimport checkSignature from './checkSignature'\nimport {route} from '@orion-js/http'\nimport {EchoesOptions} from '../types'\n\nexport default (options: EchoesOptions) =>\n route({\n method: 'post',\n path: options.requests.handlerPath || '/echoes-services',\n bodyParser: 'json',\n bodyParserOptions: {\n limit: '10mb',\n },\n async resolve(req) {\n try {\n const {body, signature} = req.body\n\n checkSignature(body, signature)\n\n const {method, serializedParams} = body\n\n const echo = getEcho(method)\n const result = await echo.onRequest(serializedParams)\n\n return {\n body: {\n result: serialize(result),\n },\n }\n } catch (error) {\n if (!error.getInfo) {\n console.error('Error at echo requests handler:', error)\n }\n\n return {\n body: {\n error: error.message,\n errorInfo: error.getInfo ? error.getInfo() : null,\n isValidationError: !!error.isValidationError,\n isUserError: !!error.isUserError,\n },\n }\n }\n },\n })\n","import {Kafka, EachMessagePayload, Producer, Consumer} from 'kafkajs'\nimport {EchoesOptions, EchoType} from '../types'\n\nconst HEARTBEAT_INTERVAL_SECONDS = 5 // This value must be less than the kafkajs session timeout\nconst CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30\nconst DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4 // How many partitions to consume concurrently, adjust this with the members to partitions ratio to avoid idle consumers.\nconst DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1 // How many members are in comparison to partitions, this is used to determine if the consumer group has room for more members. Numbers over 1 leads to idle consumers. Numbers under 1 needs partitionsConsumedConcurrently to be more than 1.\n\n/**\n * Manages the Kafka connection and the consumers.\n */\nclass KafkaManager {\n kafka: Kafka\n options: EchoesOptions\n producer: Producer\n consumer: Consumer\n topics: string[]\n started: boolean\n interval: NodeJS.Timeout\n\n constructor(options: EchoesOptions) {\n this.kafka = new Kafka(options.client)\n this.options = options\n this.producer = this.kafka.producer(options.producer)\n this.consumer = this.kafka.consumer(options.consumer)\n this.topics = Object.keys(options.echoes).filter(key => options.echoes[key].type === 'event')\n }\n\n async checkJoinConsumerGroupConditions(): Promise<boolean> {\n const admin = this.kafka.admin()\n try {\n await admin.connect()\n const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId])\n const group = groupDescriptions.groups[0]\n if (group.state === 'Empty') {\n console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`)\n return true\n }\n const topicsMetadata = await admin.fetchTopicMetadata({topics: this.topics})\n const totalPartitions = topicsMetadata.topics.reduce(\n (acc, topic) => acc + topic.partitions.length,\n 0,\n )\n console.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`,\n )\n const partitionsRatio =\n this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO\n const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio)\n if (partitionsThreshold > group.members.length) {\n console.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`,\n )\n return true\n }\n } catch (error) {\n console.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`)\n return true\n } finally {\n await admin.disconnect().catch(error => {\n console.error(`Echoes: Error disconnecting admin client: ${error.message}`)\n })\n }\n }\n\n async joinConsumerGroup() {\n await this.consumer.connect()\n await this.consumer.subscribe({topics: this.topics})\n await this.consumer.run({\n partitionsConsumedConcurrently:\n this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,\n eachMessage: params => this.handleMessage(params),\n })\n }\n\n async conditionalStart(): Promise<boolean> {\n if (await this.checkJoinConsumerGroupConditions()) {\n await this.joinConsumerGroup()\n return true\n }\n }\n\n async start() {\n if (this.started) return\n await this.producer.connect()\n this.started = await this.conditionalStart()\n if (this.started) return\n console.info('Echoes: Delaying consumer group join, waiting for conditions to be met')\n this.interval = setInterval(async () => {\n this.started = await this.conditionalStart()\n if (this.started) clearInterval(this.interval)\n }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1000)\n }\n\n async stop() {\n console.warn('Echoes: Stopping echoes')\n if (this.interval) clearInterval(this.interval)\n if (this.consumer) await this.consumer.disconnect()\n if (this.producer) await this.producer.disconnect()\n }\n\n async handleMessage(params: EachMessagePayload) {\n const echo = this.options.echoes[params.topic]\n if (!echo || echo.type !== 'event') {\n console.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`)\n return\n }\n\n let intervalsCount = 0\n const heartbeatInterval = setInterval(async () => {\n await params.heartbeat().catch(error => {\n console.warn(`Echoes: Error sending heartbeat: ${error.message}`)\n })\n intervalsCount++\n if ((intervalsCount * HEARTBEAT_INTERVAL_SECONDS) % 30 === 0) {\n console.warn(\n `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`,\n )\n }\n }, HEARTBEAT_INTERVAL_SECONDS * 1000)\n\n try {\n await echo.onMessage(params).catch(error => this.handleRetries(echo, params, error))\n } catch (error) {\n console.error(`Echoes: error processing a message: ${params.topic} ${error.message}`)\n throw error\n } finally {\n clearInterval(heartbeatInterval)\n }\n }\n\n async handleRetries(echo: EchoType, params: EachMessagePayload, error: Error) {\n const {message, topic} = params\n const retries = Number.parseInt(message?.headers?.retries?.toString() || '0', 10)\n if (echo.attemptsBeforeDeadLetter === undefined || echo.attemptsBeforeDeadLetter === null) {\n throw error\n }\n const maxRetries = echo.attemptsBeforeDeadLetter || 0\n const exceededMaxRetries = retries >= maxRetries\n const nextTopic = exceededMaxRetries ? `DLQ-${topic}` : topic\n await this.producer.send({\n topic: nextTopic,\n messages: [\n {\n value: message.value.toString(),\n headers: {\n retries: String(retries + 1),\n error: error.message,\n },\n },\n ],\n })\n\n if (exceededMaxRetries) {\n console.error(\n `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`,\n )\n } else {\n console.warn(\n `Echoes: a retryable message failed \"${error.message}\", re-sending it to topic: ${nextTopic}`,\n )\n }\n }\n}\n\nexport default KafkaManager\n","import config from '../config'\nimport requestsHandler from '../requestsHandler'\nimport {EchoesOptions} from '../types'\nimport KafkaManager from './KafkaManager'\nimport {registerRoute} from '@orion-js/http'\n\nlet kafkaManager: KafkaManager = null\n\nexport default async function startService(options: EchoesOptions) {\n config.echoes = options.echoes\n\n if (options.requests) {\n config.requests = options.requests\n registerRoute(requestsHandler(options))\n }\n\n if (options.client) {\n kafkaManager = new KafkaManager(options)\n await kafkaManager.start()\n config.producer = kafkaManager.producer\n config.consumer = kafkaManager.consumer\n }\n}\n\nexport async function stopService() {\n if (kafkaManager) {\n console.info('Stoping echoes...')\n await kafkaManager.stop()\n console.info('Echoes stopped')\n }\n}\n","import config from '../config'\nimport {PublishOptions} from '../types'\nimport serialize from './serialize'\n\n/**\n * Publish\n */\nexport default async function publish<TParams = any>(options: PublishOptions<TParams>) {\n if (!config.producer) {\n throw new Error('You must initialize echoes configruation to use publish')\n }\n\n const payload = {\n params: options.params,\n }\n\n return await config.producer.send({\n acks: options.acks,\n timeout: options.timeout,\n topic: options.topic,\n messages: [\n {\n value: serialize(payload),\n },\n ],\n })\n}\n","import config from '../config'\n\nexport default function (serviceName: string): string {\n if (serviceName.startsWith('http')) return serviceName\n\n const url = config?.requests?.services[serviceName]\n\n if (!url) {\n throw new Error(`No URL found in echoes config for service ${serviceName}`)\n }\n\n return url\n}\n","export default function (serializedJavascript: string): any {\n try {\n return eval('(' + serializedJavascript + ')')\n } catch (error) {\n throw new Error('Error deserializing echo message')\n }\n}\n","import axios from 'axios'\nimport {RequestMaker} from '../types'\nimport {executeWithRetries} from '@orion-js/helpers'\n\nexport const makeRequest: RequestMaker = async options => {\n const result = await executeWithRetries(\n async () => {\n return await axios({\n method: 'post',\n url: options.url,\n timeout: options.timeout,\n headers: {\n 'User-Agent': 'Orionjs-Echoes/1.1',\n },\n data: options.data,\n })\n },\n options.retries,\n 200,\n )\n\n return {\n data: result.data as object,\n statusCode: result.status,\n }\n}\n","import getURL from './getURL'\nimport getSignature from './getSignature'\nimport serialize from '../publish/serialize'\nimport deserialize from '../echo/deserialize'\nimport type {\n MakeRequestParams,\n RequestHandlerResponse,\n RequestMaker,\n RequestOptions,\n} from '../types'\nimport config from '../config'\nimport {makeRequest} from './makeRequest'\nimport {ValidationError} from '@orion-js/schema'\nimport {UserError} from '@orion-js/helpers'\n\nexport default async function request<TData = any, TParams = any>(\n options: RequestOptions<TParams>,\n): Promise<TData> {\n const {method, service, params} = options\n const serializedParams = serialize(params)\n const date = new Date()\n const body = {method, service, serializedParams, date}\n const signature = getSignature(body)\n\n try {\n const requestMaker: RequestMaker = config?.requests?.makeRequest || makeRequest\n const requestOptions: MakeRequestParams = {\n url: getURL(service),\n retries: options.retries,\n timeout: options.timeout,\n data: {\n body,\n signature,\n },\n }\n const result = await requestMaker(requestOptions)\n\n if (result.statusCode !== 200) {\n throw new Error(`Wrong status code ${result.statusCode}`)\n }\n\n const data: RequestHandlerResponse = result.data\n\n if (data.error) {\n const info = data.errorInfo\n if (info) {\n if (data.isValidationError) {\n throw new ValidationError(info.validationErrors)\n }\n if (data.isUserError) {\n throw new UserError(info.error, info.message, info.extra)\n }\n }\n\n throw new Error(`${data.error}`)\n }\n\n const response = deserialize(data.result)\n return response\n } catch (error) {\n if (error.isOrionError) throw error\n\n throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`)\n }\n}\n","import {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig, EchoRequestConfig, EchoEventConfig} from '../types'\nimport deserialize from './deserialize'\nimport {clean, cleanAndValidate, InferSchemaType} from '@orion-js/schema'\nimport {SchemaFieldType} from '@orion-js/schema'\n\n/**\n * @deprecated Use createEchoRequest and createEchoEvent instead\n */\nconst echo = function createNewEcho<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n TEchoType extends 'event' | 'request',\n>(\n options: EchoConfig<TParamsSchema, TReturnsSchema, TEchoType>,\n): EchoType<TParamsSchema, TReturnsSchema, TEchoType> {\n const resolve = async (params: InferSchemaType<TParamsSchema>, context: any) => {\n const cleaned = options.params\n ? await cleanAndValidate(options.params, params)\n : (params ?? ({} as InferSchemaType<TParamsSchema>))\n\n const result = await options.resolve(cleaned, context)\n\n if (options.returns) {\n return await clean(options.returns, result)\n }\n\n return result\n }\n\n return {\n type: options.type,\n params: options.params,\n returns: options.returns,\n attemptsBeforeDeadLetter:\n options.type === 'event' ? options.attemptsBeforeDeadLetter : undefined,\n resolve,\n onMessage: async (messageData: EachMessagePayload) => {\n const {message} = messageData\n\n const data = deserialize(message.value.toString())\n\n const context = {\n ...messageData,\n data,\n }\n\n await resolve(data.params, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n\n return await resolve(params, context)\n },\n }\n}\n\nexport function createEchoRequest<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoRequestConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'request'> {\n return echo({...options, type: 'request'})\n}\nexport function createEchoEvent<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoEventConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'event'> {\n return echo({...options, type: 'event' as any})\n}\n\nexport {echo}\n","import {createEchoEvent, createEchoRequest} from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\nimport {getInstance, Service} from '@orion-js/services'\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig<any, any>['resolve']\n}\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst echoesMetadata = new WeakMap<any, Record<string, any>>()\n\nexport function Echoes() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'echoes'})\n })\n }\n}\n\nexport function EchoEvent(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoEvent(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoEvent(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoEvent({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoRequest(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoRequest(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoRequest({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'echoes') {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const echoesMap = echoesMetadata.get(instance) || {}\n\n return echoesMap\n}\n"],"mappings":"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","names":["echo","echo","echo"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/requestsHandler/getEcho.ts","../src/publish/serialize.ts","../src/request/getSignature.ts","../src/request/getPassword.ts","../src/requestsHandler/checkSignature.ts","../src/requestsHandler/index.ts","../src/startService/KafkaManager.ts","../src/startService/index.ts","../src/publish/index.ts","../src/request/getURL.ts","../src/echo/deserialize.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/echo/index.ts","../src/service/index.ts"],"sourcesContent":["import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","import config from '../config'\n\nexport default function (method: string) {\n const echo = config.echoes[method]\n\n if (!echo) {\n throw new Error(`Echo named ${method} not found in this service`)\n }\n\n if (echo.type !== 'request') {\n throw new Error(`Echo named ${method} is not of type request`)\n }\n\n return echo\n}\n","import serialize from 'serialize-javascript'\nimport {clone} from '@orion-js/helpers'\n\nexport default function (data: any): string {\n const cloned = clone(data)\n const serialized = serialize(cloned, {ignoreFunction: true})\n return serialized\n}\n","import JSSHA from 'jssha'\nimport {getEchoesPassword} from './getPassword'\n\nexport default function (body: any): string {\n const password = getEchoesPassword()\n const shaObj = new JSSHA('SHA-1', 'TEXT')\n shaObj.setHMACKey(password, 'TEXT')\n shaObj.update(body)\n return shaObj.getHMAC('HEX')\n}\n","import {logger} from '@orion-js/logger'\nimport config from '../config'\nimport {internalGetEnv} from '@orion-js/env'\n\nexport function getEchoesPassword() {\n const secret = config?.requests?.key || internalGetEnv('echoes_password', 'ECHOES_PASSWORD')\n if (!secret) {\n logger.warn(\n 'Warning: no secret key found for echoes requests. Init echoes or set the env var \"echoes_password\" or process.env.ECHOES_PASSWORD',\n )\n }\n\n return secret\n}\n","import getSignature from '../request/getSignature'\n\nexport default function (body: any, signature: string) {\n const generatedSignature = getSignature(body)\n if (generatedSignature !== signature) {\n throw new Error('Echoes invalid signature')\n }\n}\n","import getEcho from './getEcho'\nimport serialize from '../publish/serialize'\nimport checkSignature from './checkSignature'\nimport {route} from '@orion-js/http'\nimport {EchoesOptions} from '../types'\n\nexport default (options: EchoesOptions) =>\n route({\n method: 'post',\n path: options.requests.handlerPath || '/echoes-services',\n bodyParser: 'json',\n bodyParserOptions: {\n limit: '10mb',\n },\n async resolve(req) {\n try {\n const {body, signature} = req.body\n\n checkSignature(body, signature)\n\n const {method, serializedParams} = body\n\n const echo = getEcho(method)\n const result = await echo.onRequest(serializedParams)\n\n return {\n body: {\n result: serialize(result),\n },\n }\n } catch (error) {\n if (!error.getInfo) {\n console.error('Error at echo requests handler:', error)\n }\n\n return {\n body: {\n error: error.message,\n errorInfo: error.getInfo ? error.getInfo() : null,\n isValidationError: !!error.isValidationError,\n isUserError: !!error.isUserError,\n },\n }\n }\n },\n })\n","import {Kafka, EachMessagePayload, Producer, Consumer} from 'kafkajs'\nimport {EchoesOptions, EchoType} from '../types'\nimport {logger} from '@orion-js/logger'\n\nconst HEARTBEAT_INTERVAL_SECONDS = 5 // This value must be less than the kafkajs session timeout\nconst CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30\nconst DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4 // How many partitions to consume concurrently, adjust this with the members to partitions ratio to avoid idle consumers.\nconst DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1 // How many members are in comparison to partitions, this is used to determine if the consumer group has room for more members. Numbers over 1 leads to idle consumers. Numbers under 1 needs partitionsConsumedConcurrently to be more than 1.\n\n/**\n * Manages the Kafka connection and the consumers.\n */\nclass KafkaManager {\n kafka: Kafka\n options: EchoesOptions\n producer: Producer\n consumer: Consumer\n topics: string[]\n started: boolean\n interval: NodeJS.Timeout\n\n constructor(options: EchoesOptions) {\n this.kafka = new Kafka(options.client)\n this.options = options\n this.producer = this.kafka.producer(options.producer)\n this.consumer = this.kafka.consumer(options.consumer)\n this.topics = Object.keys(options.echoes).filter(key => options.echoes[key].type === 'event')\n }\n\n async checkJoinConsumerGroupConditions(): Promise<boolean> {\n const admin = this.kafka.admin()\n try {\n await admin.connect()\n const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId])\n const group = groupDescriptions.groups[0]\n if (group.state === 'Empty') {\n logger.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`)\n return true\n }\n const topicsMetadata = await admin.fetchTopicMetadata({topics: this.topics})\n const totalPartitions = topicsMetadata.topics.reduce(\n (acc, topic) => acc + topic.partitions.length,\n 0,\n )\n logger.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`,\n )\n const partitionsRatio =\n this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO\n const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio)\n if (partitionsThreshold > group.members.length) {\n logger.info(\n `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`,\n )\n return true\n }\n } catch (error) {\n logger.error(`Echoes: Error checking consumer group conditions, join: ${error.message}`)\n return true\n } finally {\n await admin.disconnect().catch(error => {\n logger.error(`Echoes: Error disconnecting admin client: ${error.message}`)\n })\n }\n }\n\n async joinConsumerGroup() {\n await this.consumer.connect()\n await this.consumer.subscribe({topics: this.topics})\n await this.consumer.run({\n partitionsConsumedConcurrently:\n this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,\n eachMessage: params => this.handleMessage(params),\n })\n }\n\n async conditionalStart(): Promise<boolean> {\n if (await this.checkJoinConsumerGroupConditions()) {\n await this.joinConsumerGroup()\n return true\n }\n }\n\n async start() {\n if (this.started) return\n await this.producer.connect()\n this.started = await this.conditionalStart()\n if (this.started) return\n logger.info('Echoes: Delaying consumer group join, waiting for conditions to be met')\n this.interval = setInterval(async () => {\n this.started = await this.conditionalStart()\n if (this.started) clearInterval(this.interval)\n }, CHECK_JOIN_CONSUMER_INTERVAL_SECONDS * 1000)\n }\n\n async stop() {\n logger.warn('Echoes: Stopping echoes')\n if (this.interval) clearInterval(this.interval)\n if (this.consumer) await this.consumer.disconnect()\n if (this.producer) await this.producer.disconnect()\n }\n\n async handleMessage(params: EachMessagePayload) {\n const echo = this.options.echoes[params.topic]\n if (!echo || echo.type !== 'event') {\n logger.warn(`Echoes: Received a message for an unknown topic: ${params.topic}, ignoring it`)\n return\n }\n\n let intervalsCount = 0\n const heartbeatInterval = setInterval(async () => {\n await params.heartbeat().catch(error => {\n logger.warn(`Echoes: Error sending heartbeat: ${error.message}`)\n })\n intervalsCount++\n if ((intervalsCount * HEARTBEAT_INTERVAL_SECONDS) % 30 === 0) {\n logger.warn(\n `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`,\n )\n }\n }, HEARTBEAT_INTERVAL_SECONDS * 1000)\n\n try {\n await echo.onMessage(params).catch(error => this.handleRetries(echo, params, error))\n } catch (error) {\n logger.error(`Echoes: error processing a message: ${params.topic} ${error.message}`)\n throw error\n } finally {\n clearInterval(heartbeatInterval)\n }\n }\n\n async handleRetries(echo: EchoType, params: EachMessagePayload, error: Error) {\n const {message, topic} = params\n const retries = Number.parseInt(message?.headers?.retries?.toString() || '0', 10)\n if (echo.attemptsBeforeDeadLetter === undefined || echo.attemptsBeforeDeadLetter === null) {\n throw error\n }\n const maxRetries = echo.attemptsBeforeDeadLetter || 0\n const exceededMaxRetries = retries >= maxRetries\n const nextTopic = exceededMaxRetries ? `DLQ-${topic}` : topic\n await this.producer.send({\n topic: nextTopic,\n messages: [\n {\n value: message.value.toString(),\n headers: {\n retries: String(retries + 1),\n error: error.message,\n },\n },\n ],\n })\n\n if (exceededMaxRetries) {\n logger.error(\n `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`,\n )\n } else {\n logger.warn(\n `Echoes: a retryable message failed \"${error.message}\", re-sending it to topic: ${nextTopic}`,\n )\n }\n }\n}\n\nexport default KafkaManager\n","import config from '../config'\nimport requestsHandler from '../requestsHandler'\nimport {EchoesOptions} from '../types'\nimport KafkaManager from './KafkaManager'\nimport {registerRoute} from '@orion-js/http'\n\nlet kafkaManager: KafkaManager = null\n\nexport default async function startService(options: EchoesOptions) {\n config.echoes = options.echoes\n\n if (options.requests) {\n config.requests = options.requests\n registerRoute(requestsHandler(options))\n }\n\n if (options.client) {\n kafkaManager = new KafkaManager(options)\n await kafkaManager.start()\n config.producer = kafkaManager.producer\n config.consumer = kafkaManager.consumer\n }\n}\n\nexport async function stopService() {\n if (kafkaManager) {\n console.info('Stoping echoes...')\n await kafkaManager.stop()\n console.info('Echoes stopped')\n }\n}\n","import config from '../config'\nimport {PublishOptions} from '../types'\nimport serialize from './serialize'\n\n/**\n * Publish\n */\nexport default async function publish<TParams = any>(options: PublishOptions<TParams>) {\n if (!config.producer) {\n throw new Error('You must initialize echoes configruation to use publish')\n }\n\n const payload = {\n params: options.params,\n }\n\n return await config.producer.send({\n acks: options.acks,\n timeout: options.timeout,\n topic: options.topic,\n messages: [\n {\n value: serialize(payload),\n },\n ],\n })\n}\n","import config from '../config'\n\nexport default function (serviceName: string): string {\n if (serviceName.startsWith('http')) return serviceName\n\n const url = config?.requests?.services[serviceName]\n\n if (!url) {\n throw new Error(`No URL found in echoes config for service ${serviceName}`)\n }\n\n return url\n}\n","export default function (serializedJavascript: string): any {\n try {\n return eval('(' + serializedJavascript + ')')\n } catch (error) {\n throw new Error('Error deserializing echo message')\n }\n}\n","import axios from 'axios'\nimport {RequestMaker} from '../types'\nimport {executeWithRetries} from '@orion-js/helpers'\n\nexport const makeRequest: RequestMaker = async options => {\n const result = await executeWithRetries(\n async () => {\n return await axios({\n method: 'post',\n url: options.url,\n timeout: options.timeout,\n headers: {\n 'User-Agent': 'Orionjs-Echoes/1.1',\n },\n data: options.data,\n })\n },\n options.retries,\n 200,\n )\n\n return {\n data: result.data as object,\n statusCode: result.status,\n }\n}\n","import getURL from './getURL'\nimport getSignature from './getSignature'\nimport serialize from '../publish/serialize'\nimport deserialize from '../echo/deserialize'\nimport type {\n MakeRequestParams,\n RequestHandlerResponse,\n RequestMaker,\n RequestOptions,\n} from '../types'\nimport config from '../config'\nimport {makeRequest} from './makeRequest'\nimport {ValidationError} from '@orion-js/schema'\nimport {UserError} from '@orion-js/helpers'\n\nexport default async function request<TData = any, TParams = any>(\n options: RequestOptions<TParams>,\n): Promise<TData> {\n const {method, service, params} = options\n const serializedParams = serialize(params)\n const date = new Date()\n const body = {method, service, serializedParams, date}\n const signature = getSignature(body)\n\n try {\n const requestMaker: RequestMaker = config?.requests?.makeRequest || makeRequest\n const requestOptions: MakeRequestParams = {\n url: getURL(service),\n retries: options.retries,\n timeout: options.timeout,\n data: {\n body,\n signature,\n },\n }\n const result = await requestMaker(requestOptions)\n\n if (result.statusCode !== 200) {\n throw new Error(`Wrong status code ${result.statusCode}`)\n }\n\n const data: RequestHandlerResponse = result.data\n\n if (data.error) {\n const info = data.errorInfo\n if (info) {\n if (data.isValidationError) {\n throw new ValidationError(info.validationErrors)\n }\n if (data.isUserError) {\n throw new UserError(info.error, info.message, info.extra)\n }\n }\n\n throw new Error(`${data.error}`)\n }\n\n const response = deserialize(data.result)\n return response\n } catch (error) {\n if (error.isOrionError) throw error\n\n throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`)\n }\n}\n","import {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig, EchoRequestConfig, EchoEventConfig} from '../types'\nimport deserialize from './deserialize'\nimport {clean, cleanAndValidate, InferSchemaType} from '@orion-js/schema'\nimport {SchemaFieldType} from '@orion-js/schema'\n\n/**\n * @deprecated Use createEchoRequest and createEchoEvent instead\n */\nconst echo = function createNewEcho<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n TEchoType extends 'event' | 'request',\n>(\n options: EchoConfig<TParamsSchema, TReturnsSchema, TEchoType>,\n): EchoType<TParamsSchema, TReturnsSchema, TEchoType> {\n const resolve = async (params: InferSchemaType<TParamsSchema>, context: any) => {\n const cleaned = options.params\n ? await cleanAndValidate(options.params, params)\n : (params ?? ({} as InferSchemaType<TParamsSchema>))\n\n const result = await options.resolve(cleaned, context)\n\n if (options.returns) {\n return await clean(options.returns, result)\n }\n\n return result\n }\n\n return {\n type: options.type,\n params: options.params,\n returns: options.returns,\n attemptsBeforeDeadLetter:\n options.type === 'event' ? options.attemptsBeforeDeadLetter : undefined,\n resolve,\n onMessage: async (messageData: EachMessagePayload) => {\n const {message} = messageData\n\n const data = deserialize(message.value.toString())\n\n const context = {\n ...messageData,\n data,\n }\n\n await resolve(data.params, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n\n return await resolve(params, context)\n },\n }\n}\n\nexport function createEchoRequest<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoRequestConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'request'> {\n return echo({...options, type: 'request'})\n}\nexport function createEchoEvent<\n TParamsSchema extends SchemaFieldType,\n TReturnsSchema extends SchemaFieldType,\n>(\n options: EchoEventConfig<TParamsSchema, TReturnsSchema>,\n): EchoType<TParamsSchema, TReturnsSchema, 'event'> {\n return echo({...options, type: 'event' as any})\n}\n\nexport {echo}\n","import {createEchoEvent, createEchoRequest} from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\nimport {getInstance, Service} from '@orion-js/services'\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig<any, any>['resolve']\n}\n// Define metadata storage using WeakMaps\nconst serviceMetadata = new WeakMap<any, {_serviceType: string}>()\nconst echoesMetadata = new WeakMap<any, Record<string, any>>()\n\nexport function Echoes() {\n return (target: any, context: ClassDecoratorContext<any>) => {\n Service()(target, context)\n\n context.addInitializer(function (this) {\n serviceMetadata.set(this, {_serviceType: 'echoes'})\n })\n }\n}\n\nexport function EchoEvent(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoEvent(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoEvent(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoEvent({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest(): (\n method: any,\n context: ClassFieldDecoratorContext | ClassMethodDecoratorContext,\n) => any\nexport function EchoRequest(\n options?: Omit<EchoConfig<any, any>, 'resolve' | 'type'>,\n): (method: any, context: ClassMethodDecoratorContext) => any\nexport function EchoRequest(options = {}) {\n return (method: any, context: ClassMethodDecoratorContext | ClassFieldDecoratorContext) => {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this) {\n const echoes = echoesMetadata.get(this) || {}\n\n if (context.kind === 'method') {\n echoes[propertyKey] = createEchoRequest({\n ...options,\n resolve: this[propertyKey].bind(this),\n })\n }\n\n if (context.kind === 'field') {\n echoes[propertyKey] = this[propertyKey]\n }\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n const instance = getInstance(target)\n\n if (!serviceMetadata.has(instance.constructor)) {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const instanceMetadata = serviceMetadata.get(instance.constructor)\n if (instanceMetadata._serviceType !== 'echoes') {\n throw new Error('You must pass a class decorated with @Echoes to getServiceEchoes')\n }\n\n const echoesMap = echoesMetadata.get(instance) || {}\n\n return echoesMap\n}\n"],"mappings":"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","names":["echo","echo","logger","echo"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-js/echoes",
3
- "version": "4.0.17",
3
+ "version": "4.0.19",
4
4
  "main": "./dist/index.cjs",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -13,11 +13,14 @@
13
13
  "jssha": "^3.2.0",
14
14
  "kafkajs": "^2.2.4",
15
15
  "serialize-javascript": "^6.0.0",
16
- "@orion-js/env": "4.0.3",
17
- "@orion-js/helpers": "4.0.1",
18
- "@orion-js/http": "4.0.17",
19
- "@orion-js/schema": "4.0.12",
20
- "@orion-js/services": "4.0.2"
16
+ "@orion-js/env": "4.0.4",
17
+ "@orion-js/helpers": "4.0.2",
18
+ "@orion-js/http": "4.0.18",
19
+ "@orion-js/schema": "4.0.13",
20
+ "@orion-js/services": "4.0.3"
21
+ },
22
+ "peerDependencies": {
23
+ "@orion-js/logger": "4.0.5"
21
24
  },
22
25
  "devDependencies": {
23
26
  "@types/node": "^18.0.0",