@orion-js/echoes 4.0.0-next.2 → 4.0.0-next.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Orionjs Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.cjs CHANGED
@@ -4,7 +4,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getProtoOf = Object.getPrototypeOf;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
8
7
  var __export = (target, all) => {
9
8
  for (var name in all)
10
9
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -63,19 +62,15 @@ function getEcho_default(method) {
63
62
  }
64
63
  return echo2;
65
64
  }
66
- __name(getEcho_default, "default");
67
65
 
68
66
  // src/publish/serialize.ts
69
67
  var import_serialize_javascript = __toESM(require("serialize-javascript"), 1);
70
68
  var import_cloneDeep = __toESM(require("lodash/cloneDeep"), 1);
71
69
  function serialize_default(data) {
72
70
  const cloned = (0, import_cloneDeep.default)(data);
73
- const serialized = (0, import_serialize_javascript.default)(cloned, {
74
- ignoreFunction: true
75
- });
71
+ const serialized = (0, import_serialize_javascript.default)(cloned, { ignoreFunction: true });
76
72
  return serialized;
77
73
  }
78
- __name(serialize_default, "default");
79
74
 
80
75
  // src/request/getSignature.ts
81
76
  var import_jssha = __toESM(require("jssha"), 1);
@@ -83,14 +78,15 @@ var import_jssha = __toESM(require("jssha"), 1);
83
78
  // src/request/getPassword.ts
84
79
  var import_env = require("@orion-js/env");
85
80
  function getEchoesPassword() {
86
- var _a2, _b;
87
- const secret = ((_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.key) || (0, import_env.internalGetEnv)("echoes_password", "ECHOES_PASSWORD");
81
+ var _a, _b;
82
+ const secret = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.key) || (0, import_env.internalGetEnv)("echoes_password", "ECHOES_PASSWORD");
88
83
  if (!secret) {
89
- console.warn('Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD');
84
+ console.warn(
85
+ 'Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD'
86
+ );
90
87
  }
91
88
  return secret;
92
89
  }
93
- __name(getEchoesPassword, "getEchoesPassword");
94
90
 
95
91
  // src/request/getSignature.ts
96
92
  function getSignature_default(body) {
@@ -100,7 +96,6 @@ function getSignature_default(body) {
100
96
  shaObj.update(body);
101
97
  return shaObj.getHMAC("HEX");
102
98
  }
103
- __name(getSignature_default, "default");
104
99
 
105
100
  // src/requestsHandler/checkSignature.ts
106
101
  function checkSignature_default(body, signature) {
@@ -109,11 +104,10 @@ function checkSignature_default(body, signature) {
109
104
  throw new Error("Echoes invalid signature");
110
105
  }
111
106
  }
112
- __name(checkSignature_default, "default");
113
107
 
114
108
  // src/requestsHandler/index.ts
115
109
  var import_http = require("@orion-js/http");
116
- var requestsHandler_default = /* @__PURE__ */ __name((options) => (0, import_http.route)({
110
+ var requestsHandler_default = (options) => (0, import_http.route)({
117
111
  method: "post",
118
112
  path: options.requests.handlerPath || "/echoes-services",
119
113
  bodyParser: "json",
@@ -146,7 +140,7 @@ var requestsHandler_default = /* @__PURE__ */ __name((options) => (0, import_htt
146
140
  };
147
141
  }
148
142
  }
149
- }), "default");
143
+ });
150
144
 
151
145
  // src/startService/KafkaManager.ts
152
146
  var import_kafkajs = require("kafkajs");
@@ -154,8 +148,7 @@ var HEARTBEAT_INTERVAL_SECONDS = 5;
154
148
  var CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30;
155
149
  var DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4;
156
150
  var DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1;
157
- var _a;
158
- var KafkaManager = (_a = class {
151
+ var KafkaManager = class {
159
152
  kafka;
160
153
  options;
161
154
  producer;
@@ -168,29 +161,34 @@ var KafkaManager = (_a = class {
168
161
  this.options = options;
169
162
  this.producer = this.kafka.producer(options.producer);
170
163
  this.consumer = this.kafka.consumer(options.consumer);
171
- this.topics = Object.keys(options.echoes).filter((key) => options.echoes[key].type === types_default.event);
164
+ this.topics = Object.keys(options.echoes).filter(
165
+ (key) => options.echoes[key].type === types_default.event
166
+ );
172
167
  }
173
168
  async checkJoinConsumerGroupConditions() {
174
169
  const admin = this.kafka.admin();
175
170
  try {
176
171
  await admin.connect();
177
- const groupDescriptions = await admin.describeGroups([
178
- this.options.consumer.groupId
179
- ]);
172
+ const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId]);
180
173
  const group = groupDescriptions.groups[0];
181
174
  if (group.state === "Empty") {
182
175
  console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
183
176
  return true;
184
177
  }
185
- const topicsMetadata = await admin.fetchTopicMetadata({
186
- topics: this.topics
187
- });
188
- const totalPartitions = topicsMetadata.topics.reduce((acc, topic) => acc + topic.partitions.length, 0);
189
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`);
178
+ const topicsMetadata = await admin.fetchTopicMetadata({ topics: this.topics });
179
+ const totalPartitions = topicsMetadata.topics.reduce(
180
+ (acc, topic) => acc + topic.partitions.length,
181
+ 0
182
+ );
183
+ console.info(
184
+ `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`
185
+ );
190
186
  const partitionsRatio = this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO;
191
187
  const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio);
192
188
  if (partitionsThreshold > group.members.length) {
193
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`);
189
+ console.info(
190
+ `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`
191
+ );
194
192
  return true;
195
193
  }
196
194
  } catch (error) {
@@ -204,12 +202,10 @@ var KafkaManager = (_a = class {
204
202
  }
205
203
  async joinConsumerGroup() {
206
204
  await this.consumer.connect();
207
- await this.consumer.subscribe({
208
- topics: this.topics
209
- });
205
+ await this.consumer.subscribe({ topics: this.topics });
210
206
  await this.consumer.run({
211
207
  partitionsConsumedConcurrently: this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,
212
- eachMessage: /* @__PURE__ */ __name((params) => this.handleMessage(params), "eachMessage")
208
+ eachMessage: (params) => this.handleMessage(params)
213
209
  });
214
210
  }
215
211
  async conditionalStart() {
@@ -248,7 +244,9 @@ var KafkaManager = (_a = class {
248
244
  });
249
245
  intervalsCount++;
250
246
  if (intervalsCount * HEARTBEAT_INTERVAL_SECONDS % 30 === 0) {
251
- console.warn(`Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`);
247
+ console.warn(
248
+ `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`
249
+ );
252
250
  }
253
251
  }, HEARTBEAT_INTERVAL_SECONDS * 1e3);
254
252
  try {
@@ -261,9 +259,9 @@ var KafkaManager = (_a = class {
261
259
  }
262
260
  }
263
261
  async handleRetries(echo2, params, error) {
264
- var _a2, _b;
262
+ var _a, _b;
265
263
  const { message, topic } = params;
266
- const retries = Number.parseInt(((_b = (_a2 = message == null ? void 0 : message.headers) == null ? void 0 : _a2.retries) == null ? void 0 : _b.toString()) || "0", 10);
264
+ const retries = Number.parseInt(((_b = (_a = message == null ? void 0 : message.headers) == null ? void 0 : _a.retries) == null ? void 0 : _b.toString()) || "0", 10);
267
265
  if (echo2.attemptsBeforeDeadLetter === void 0 || echo2.attemptsBeforeDeadLetter === null) {
268
266
  throw error;
269
267
  }
@@ -283,12 +281,16 @@ var KafkaManager = (_a = class {
283
281
  ]
284
282
  });
285
283
  if (exceededMaxRetries) {
286
- console.error(`Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`);
284
+ console.error(
285
+ `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`
286
+ );
287
287
  } else {
288
- console.warn(`Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`);
288
+ console.warn(
289
+ `Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`
290
+ );
289
291
  }
290
292
  }
291
- }, __name(_a, "KafkaManager"), _a);
293
+ };
292
294
  var KafkaManager_default = KafkaManager;
293
295
 
294
296
  // src/startService/index.ts
@@ -307,7 +309,6 @@ async function startService(options) {
307
309
  config_default.consumer = kafkaManager.consumer;
308
310
  }
309
311
  }
310
- __name(startService, "startService");
311
312
  async function stopService() {
312
313
  if (kafkaManager) {
313
314
  console.info("Stoping echoes...");
@@ -315,7 +316,6 @@ async function stopService() {
315
316
  console.info("Echoes stopped");
316
317
  }
317
318
  }
318
- __name(stopService, "stopService");
319
319
 
320
320
  // src/publish/index.ts
321
321
  async function publish(options) {
@@ -336,7 +336,6 @@ async function publish(options) {
336
336
  ]
337
337
  });
338
338
  }
339
- __name(publish, "publish");
340
339
 
341
340
  // src/echo/deserialize.ts
342
341
  function deserialize_default(serializedJavascript) {
@@ -346,13 +345,12 @@ function deserialize_default(serializedJavascript) {
346
345
  throw new Error("Error deserializing echo message");
347
346
  }
348
347
  }
349
- __name(deserialize_default, "default");
350
348
 
351
349
  // src/echo/index.ts
352
- var echo = /* @__PURE__ */ __name(function createNewEcho(options) {
350
+ var echo = function createNewEcho(options) {
353
351
  return {
354
352
  ...options,
355
- onMessage: /* @__PURE__ */ __name(async (messageData) => {
353
+ onMessage: async (messageData) => {
356
354
  const { message } = messageData;
357
355
  const data = deserialize_default(message.value.toString());
358
356
  const context = {
@@ -360,68 +358,66 @@ var echo = /* @__PURE__ */ __name(function createNewEcho(options) {
360
358
  data
361
359
  };
362
360
  await options.resolve(data.params || {}, context);
363
- }, "onMessage"),
364
- onRequest: /* @__PURE__ */ __name(async (serializedParams) => {
361
+ },
362
+ onRequest: async (serializedParams) => {
365
363
  const context = {};
366
364
  const params = deserialize_default(serializedParams);
367
365
  const result = await options.resolve(params || {}, context);
368
366
  return result;
369
- }, "onRequest")
367
+ }
370
368
  };
371
- }, "createNewEcho");
369
+ };
372
370
  echo.types = types_default;
373
371
  var echo_default = echo;
374
372
 
375
373
  // src/request/getURL.ts
376
374
  function getURL_default(serviceName) {
377
- var _a2, _b;
375
+ var _a, _b;
378
376
  if (serviceName.startsWith("http")) return serviceName;
379
- const url = (_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.services[serviceName];
377
+ const url = (_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.services[serviceName];
380
378
  if (!url) {
381
379
  throw new Error(`No URL found in echoes config for service ${serviceName}`);
382
380
  }
383
381
  return url;
384
382
  }
385
- __name(getURL_default, "default");
386
383
 
387
384
  // src/request/makeRequest.ts
388
385
  var import_axios = __toESM(require("axios"), 1);
389
386
  var import_helpers = require("@orion-js/helpers");
390
- var makeRequest = /* @__PURE__ */ __name(async (options) => {
391
- const result = await (0, import_helpers.executeWithRetries)(async () => {
392
- return await (0, import_axios.default)({
393
- method: "post",
394
- url: options.url,
395
- timeout: options.timeout,
396
- headers: {
397
- "User-Agent": "Orionjs-Echoes/1.1"
398
- },
399
- data: options.data
400
- });
401
- }, options.retries, 200);
387
+ var makeRequest = async (options) => {
388
+ const result = await (0, import_helpers.executeWithRetries)(
389
+ async () => {
390
+ return await (0, import_axios.default)({
391
+ method: "post",
392
+ url: options.url,
393
+ timeout: options.timeout,
394
+ headers: {
395
+ "User-Agent": "Orionjs-Echoes/1.1"
396
+ },
397
+ data: options.data
398
+ });
399
+ },
400
+ options.retries,
401
+ 200
402
+ );
402
403
  return {
403
404
  data: result.data,
404
405
  statusCode: result.status
405
406
  };
406
- }, "makeRequest");
407
+ };
407
408
 
408
409
  // src/request/index.ts
409
410
  var import_schema = require("@orion-js/schema");
410
411
  var import_helpers2 = require("@orion-js/helpers");
411
412
  async function request(options) {
412
- var _a2, _b;
413
+ var _a, _b;
413
414
  const { method, service, params } = options;
414
415
  const serializedParams = serialize_default(params);
415
416
  const date = /* @__PURE__ */ new Date();
416
- const body = {
417
- method,
418
- service,
419
- serializedParams,
420
- date
421
- };
417
+ const body = { method, service, serializedParams, date };
422
418
  const signature = getSignature_default(body);
423
419
  try {
424
- const requestMaker = ((_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.makeRequest) || makeRequest;
420
+ const requestMaker = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.makeRequest) || makeRequest;
425
421
  const requestOptions = {
426
422
  url: getURL_default(service),
427
423
  retries: options.retries,
@@ -455,54 +451,61 @@ async function request(options) {
455
451
  throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`);
456
452
  }
457
453
  }
458
- __name(request, "request");
459
454
 
460
455
  // src/service/index.ts
461
456
  var import_services = require("@orion-js/services");
457
+ var serviceMetadata = /* @__PURE__ */ new WeakMap();
458
+ var echoesMetadata = /* @__PURE__ */ new WeakMap();
462
459
  function Echoes() {
463
- return function(target) {
464
- (0, import_services.Service)()(target);
465
- target.prototype.service = target;
460
+ return function(target, context) {
461
+ (0, import_services.Service)()(target, context);
462
+ context.addInitializer(function() {
463
+ serviceMetadata.set(this, { _serviceType: "echoes" });
464
+ });
466
465
  };
467
466
  }
468
- __name(Echoes, "Echoes");
469
- function EchoRequest(options = {}) {
470
- return function(target, propertyKey, descriptor) {
471
- if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`);
472
- target.echoes = target.echoes || {};
473
- target.echoes[propertyKey] = echo_default({
474
- ...options,
475
- type: "request",
476
- resolve: /* @__PURE__ */ __name(async (params, viewer) => {
477
- const instance = (0, import_services.getInstance)(target.service);
478
- return await instance[propertyKey](params, viewer);
479
- }, "resolve")
467
+ function EchoEvent(options = {}) {
468
+ return function(method, context) {
469
+ const propertyKey = String(context.name);
470
+ context.addInitializer(function() {
471
+ const echoes = echoesMetadata.get(this) || {};
472
+ echoes[propertyKey] = echo_default({
473
+ ...options,
474
+ type: "event",
475
+ resolve: this[propertyKey].bind(this)
476
+ });
477
+ echoesMetadata.set(this, echoes);
480
478
  });
479
+ return method;
481
480
  };
482
481
  }
483
- __name(EchoRequest, "EchoRequest");
484
- function EchoEvent(options = {}) {
485
- return function(target, propertyKey, descriptor) {
486
- if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`);
487
- target.echoes = target.echoes || {};
488
- target.echoes[propertyKey] = echo_default({
489
- ...options,
490
- type: "event",
491
- resolve: /* @__PURE__ */ __name(async (params, viewer) => {
492
- const instance = (0, import_services.getInstance)(target.service);
493
- return await instance[propertyKey](params, viewer);
494
- }, "resolve")
482
+ function EchoRequest(options = {}) {
483
+ return function(method, context) {
484
+ const propertyKey = String(context.name);
485
+ context.addInitializer(function() {
486
+ const echoes = echoesMetadata.get(this) || {};
487
+ echoes[propertyKey] = echo_default({
488
+ ...options,
489
+ type: "request",
490
+ resolve: this[propertyKey].bind(this)
491
+ });
492
+ echoesMetadata.set(this, echoes);
495
493
  });
494
+ return method;
496
495
  };
497
496
  }
498
- __name(EchoEvent, "EchoEvent");
499
497
  function getServiceEchoes(target) {
500
- if (!target.prototype) {
501
- throw new Error("You must pass a class to getServiceRoutes");
498
+ const instance = (0, import_services.getInstance)(target);
499
+ if (!serviceMetadata.has(instance.constructor)) {
500
+ throw new Error("You must pass a class decorated with @Echoes to getServiceEchoes");
501
+ }
502
+ const instanceMetadata = serviceMetadata.get(instance.constructor);
503
+ if (instanceMetadata._serviceType !== "echoes") {
504
+ throw new Error("You must pass a class decorated with @Echoes to getServiceEchoes");
502
505
  }
503
- return target.prototype.echoes || {};
506
+ const echoesMap = echoesMetadata.get(instance) || {};
507
+ return echoesMap;
504
508
  }
505
- __name(getServiceEchoes, "getServiceEchoes");
506
509
  // Annotate the CommonJS export names for ESM import in node:
507
510
  0 && (module.exports = {
508
511
  EchoEvent,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/echo/types.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/echo/deserialize.ts","../src/echo/index.ts","../src/request/getURL.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/service/index.ts"],"sourcesContent":["import startService, {stopService} from './startService'\nimport publish from './publish'\nimport echo from './echo'\nimport request from './request'\n\nexport * from './types'\nexport * from './service'\n\nexport {publish, startService, stopService, echo, request}\n","import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","export default {\n event: 'event',\n request: 'request'\n}\n","import config from '../config'\nimport types from '../echo/types'\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 !== types.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 cloneDeep from 'lodash/cloneDeep'\n\nexport default function (data: any): string {\n const cloned = cloneDeep(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 types from '../echo/types'\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.Timer\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(\n key => options.echoes[key].type === types.event,\n )\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 !== types.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","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 {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig} from '../types'\nimport deserialize from './deserialize'\nimport types from './types'\n\nconst echo = function createNewEcho(options: EchoConfig): EchoType {\n return {\n ...options,\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 options.resolve(data.params || {}, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n const result = await options.resolve(params || {}, context)\n return result\n }\n }\n}\n\necho.types = types\n\nexport default echo\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","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 {getInstance, Service} from '@orion-js/services'\nimport echo from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\n\nexport function Echoes(): ClassDecorator {\n return function (target: any) {\n Service()(target)\n target.prototype.service = target\n }\n}\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig['resolve']\n}\n\nexport function EchoRequest(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) {\n if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`)\n\n target.echoes = target.echoes || {}\n target.echoes[propertyKey] = echo({\n ...options,\n type: 'request',\n resolve: async (params, viewer) => {\n const instance: any = getInstance(target.service)\n return await instance[propertyKey](params, viewer)\n }\n })\n }\n}\n\nexport function EchoEvent(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) {\n if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`)\n\n target.echoes = target.echoes || {}\n target.echoes[propertyKey] = echo({\n ...options,\n type: 'event',\n resolve: async (params, viewer) => {\n const instance: any = getInstance(target.service)\n return await instance[propertyKey](params, viewer)\n }\n })\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n if (!target.prototype) {\n throw new Error('You must pass a class to getServiceRoutes')\n }\n\n return target.prototype.echoes || {}\n}\n"],"mappings":"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","names":["config","event","request","method","echo","config","echoes","Error","type","types","request","data","cloned","cloneDeep","serialized","serialize","ignoreFunction","getEchoesPassword","_a","secret","config","requests","key","internalGetEnv","console","warn","body","password","getEchoesPassword","shaObj","JSSHA","setHMACKey","update","getHMAC","body","signature","generatedSignature","getSignature","Error","options","route","method","path","requests","handlerPath","bodyParser","bodyParserOptions","limit","resolve","req","body","signature","checkSignature","serializedParams","echo","getEcho","result","onRequest","serialize","error","getInfo","console","message","errorInfo","isValidationError","isUserError","HEARTBEAT_INTERVAL_SECONDS","CHECK_JOIN_CONSUMER_INTERVAL_SECONDS","DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY","DEFAULT_MEMBERS_TO_PARTITIONS_RATIO","KafkaManager","kafka","options","producer","consumer","topics","started","interval","constructor","Kafka","client","Object","keys","echoes","filter","key","type","types","event","checkJoinConsumerGroupConditions","admin","connect","groupDescriptions","describeGroups","groupId","group","groups","state","console","info","topicsMetadata","fetchTopicMetadata","totalPartitions","reduce","acc","topic","partitions","length","members","partitionsRatio","membersToPartitionsRatio","partitionsThreshold","Math","ceil","error","message","disconnect","catch","joinConsumerGroup","subscribe","run","partitionsConsumedConcurrently","eachMessage","params","handleMessage","conditionalStart","start","setInterval","clearInterval","stop","warn","echo","intervalsCount","heartbeatInterval","heartbeat","onMessage","handleRetries","_a","retries","Number","parseInt","headers","toString","attemptsBeforeDeadLetter","undefined","maxRetries","exceededMaxRetries","nextTopic","send","messages","value","String","import_http","kafkaManager","options","config","echoes","requests","registerRoute","requestsHandler","client","KafkaManager","start","producer","consumer","startService","stopService","console","info","stop","options","config","producer","Error","payload","params","send","acks","timeout","topic","messages","value","serialize","publish","serializedJavascript","eval","error","Error","echo","createNewEcho","options","onMessage","messageData","message","data","deserialize","value","toString","context","resolve","params","onRequest","serializedParams","result","types","serviceName","_a","startsWith","url","config","requests","services","Error","makeRequest","options","result","executeWithRetries","axios","method","url","timeout","headers","data","retries","statusCode","status","import_helpers","options","_a","method","service","params","serializedParams","serialize","date","Date","body","signature","getSignature","requestMaker","config","requests","makeRequest","requestOptions","url","getURL","retries","timeout","data","result","statusCode","Error","error","info","errorInfo","isValidationError","ValidationError","validationErrors","isUserError","UserError","message","extra","response","deserialize","isOrionError","request","Echoes","target","Service","prototype","service","EchoRequest","options","propertyKey","descriptor","value","Error","echoes","echo","type","resolve","params","viewer","instance","getInstance","EchoEvent","getServiceEchoes"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/config.ts","../src/echo/types.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/echo/deserialize.ts","../src/echo/index.ts","../src/request/getURL.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/service/index.ts"],"sourcesContent":["import startService, {stopService} from './startService'\nimport publish from './publish'\nimport echo from './echo'\nimport request from './request'\n\nexport * from './types'\nexport * from './service'\n\nexport {publish, startService, stopService, echo, request}\n","import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","export default {\n event: 'event',\n request: 'request',\n}\n","import config from '../config'\nimport types from '../echo/types'\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 !== types.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 cloneDeep from 'lodash/cloneDeep'\n\nexport default function (data: any): string {\n const cloned = cloneDeep(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 types from '../echo/types'\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.Timer\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(\n key => options.echoes[key].type === types.event,\n )\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 !== types.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","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 {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig} from '../types'\nimport deserialize from './deserialize'\nimport types from './types'\n\nconst echo = function createNewEcho(options: EchoConfig): EchoType {\n return {\n ...options,\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 options.resolve(data.params || {}, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n const result = await options.resolve(params || {}, context)\n return result\n },\n }\n}\n\necho.types = types\n\nexport default echo\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","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 echo 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['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 function (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 This,\n TArgs extends Parameters<EchoConfig['resolve']>,\n TReturn extends ReturnType<EchoConfig['resolve']>,\n>(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (\n method: (this: This, ...args: TArgs) => TReturn,\n context: ClassMethodDecoratorContext<This, typeof method>,\n ) {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this: This) {\n const echoes = echoesMetadata.get(this) || {}\n\n echoes[propertyKey] = echo({\n ...options,\n type: 'event',\n resolve: this[propertyKey].bind(this),\n })\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest<\n This,\n TArgs extends Parameters<EchoConfig['resolve']>,\n TReturn extends ReturnType<EchoConfig['resolve']>,\n>(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (\n method: (this: This, ...args: TArgs) => TReturn,\n context: ClassMethodDecoratorContext<This, typeof method>,\n ) {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this: This) {\n const echoes = echoesMetadata.get(this) || {}\n\n echoes[propertyKey] = echo({\n ...options,\n type: 'request',\n resolve: this[propertyKey].bind(this),\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","cloneDeep","serialize","JSSHA","echo","echo","import_http","axios","import_helpers"]}
package/dist/index.d.cts CHANGED
@@ -117,12 +117,12 @@ declare const echo: {
117
117
 
118
118
  declare function request<TData = any, TParams = any>(options: RequestOptions<TParams>): Promise<TData>;
119
119
 
120
- declare function Echoes(): ClassDecorator;
121
120
  interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {
122
121
  value?: EchoConfig['resolve'];
123
122
  }
124
- declare function EchoRequest(options?: Omit<EchoConfig, 'resolve' | 'type'>): (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) => void;
125
- declare function EchoEvent(options?: Omit<EchoConfig, 'resolve' | 'type'>): (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) => void;
123
+ declare function Echoes(): (target: any, context: ClassDecoratorContext<any>) => void;
124
+ declare function EchoEvent<This, TArgs extends Parameters<EchoConfig['resolve']>, TReturn extends ReturnType<EchoConfig['resolve']>>(options?: Omit<EchoConfig, 'resolve' | 'type'>): (method: (this: This, ...args: TArgs) => TReturn, context: ClassMethodDecoratorContext<This, typeof method>) => (this: This, ...args: TArgs) => TReturn;
125
+ declare function EchoRequest<This, TArgs extends Parameters<EchoConfig['resolve']>, TReturn extends ReturnType<EchoConfig['resolve']>>(options?: Omit<EchoConfig, 'resolve' | 'type'>): (method: (this: This, ...args: TArgs) => TReturn, context: ClassMethodDecoratorContext<This, typeof method>) => (this: This, ...args: TArgs) => TReturn;
126
126
  declare function getServiceEchoes(target: any): EchoesMap;
127
127
 
128
128
  export { type EchoConfig, EchoEvent, EchoRequest, type EchoType, Echoes, type EchoesConfigHandler, type EchoesMap, type EchoesOptions, type EchoesPropertyDescriptor, type MakeRequestParams, type PublishOptions, type RequestHandlerResponse, type RequestMaker, type RequestMakerResult, type RequestOptions, type RequestsConfig, echo, getServiceEchoes, publish, request, startService, stopService };
package/dist/index.d.ts CHANGED
@@ -117,12 +117,12 @@ declare const echo: {
117
117
 
118
118
  declare function request<TData = any, TParams = any>(options: RequestOptions<TParams>): Promise<TData>;
119
119
 
120
- declare function Echoes(): ClassDecorator;
121
120
  interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {
122
121
  value?: EchoConfig['resolve'];
123
122
  }
124
- declare function EchoRequest(options?: Omit<EchoConfig, 'resolve' | 'type'>): (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) => void;
125
- declare function EchoEvent(options?: Omit<EchoConfig, 'resolve' | 'type'>): (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) => void;
123
+ declare function Echoes(): (target: any, context: ClassDecoratorContext<any>) => void;
124
+ declare function EchoEvent<This, TArgs extends Parameters<EchoConfig['resolve']>, TReturn extends ReturnType<EchoConfig['resolve']>>(options?: Omit<EchoConfig, 'resolve' | 'type'>): (method: (this: This, ...args: TArgs) => TReturn, context: ClassMethodDecoratorContext<This, typeof method>) => (this: This, ...args: TArgs) => TReturn;
125
+ declare function EchoRequest<This, TArgs extends Parameters<EchoConfig['resolve']>, TReturn extends ReturnType<EchoConfig['resolve']>>(options?: Omit<EchoConfig, 'resolve' | 'type'>): (method: (this: This, ...args: TArgs) => TReturn, context: ClassMethodDecoratorContext<This, typeof method>) => (this: This, ...args: TArgs) => TReturn;
126
126
  declare function getServiceEchoes(target: any): EchoesMap;
127
127
 
128
128
  export { type EchoConfig, EchoEvent, EchoRequest, type EchoType, Echoes, type EchoesConfigHandler, type EchoesMap, type EchoesOptions, type EchoesPropertyDescriptor, type MakeRequestParams, type PublishOptions, type RequestHandlerResponse, type RequestMaker, type RequestMakerResult, type RequestOptions, type RequestsConfig, echo, getServiceEchoes, publish, request, startService, stopService };
package/dist/index.js CHANGED
@@ -1,6 +1,3 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
1
  // src/config.ts
5
2
  var config = {};
6
3
  var config_default = config;
@@ -22,19 +19,15 @@ function getEcho_default(method) {
22
19
  }
23
20
  return echo2;
24
21
  }
25
- __name(getEcho_default, "default");
26
22
 
27
23
  // src/publish/serialize.ts
28
24
  import serialize from "serialize-javascript";
29
25
  import cloneDeep from "lodash/cloneDeep";
30
26
  function serialize_default(data) {
31
27
  const cloned = cloneDeep(data);
32
- const serialized = serialize(cloned, {
33
- ignoreFunction: true
34
- });
28
+ const serialized = serialize(cloned, { ignoreFunction: true });
35
29
  return serialized;
36
30
  }
37
- __name(serialize_default, "default");
38
31
 
39
32
  // src/request/getSignature.ts
40
33
  import JSSHA from "jssha";
@@ -42,14 +35,15 @@ import JSSHA from "jssha";
42
35
  // src/request/getPassword.ts
43
36
  import { internalGetEnv } from "@orion-js/env";
44
37
  function getEchoesPassword() {
45
- var _a2, _b;
46
- const secret = ((_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.key) || internalGetEnv("echoes_password", "ECHOES_PASSWORD");
38
+ var _a, _b;
39
+ const secret = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.key) || internalGetEnv("echoes_password", "ECHOES_PASSWORD");
47
40
  if (!secret) {
48
- console.warn('Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD');
41
+ console.warn(
42
+ 'Warning: no secret key found for echoes requests. Init echoes or set the env var "echoes_password" or process.env.ECHOES_PASSWORD'
43
+ );
49
44
  }
50
45
  return secret;
51
46
  }
52
- __name(getEchoesPassword, "getEchoesPassword");
53
47
 
54
48
  // src/request/getSignature.ts
55
49
  function getSignature_default(body) {
@@ -59,7 +53,6 @@ function getSignature_default(body) {
59
53
  shaObj.update(body);
60
54
  return shaObj.getHMAC("HEX");
61
55
  }
62
- __name(getSignature_default, "default");
63
56
 
64
57
  // src/requestsHandler/checkSignature.ts
65
58
  function checkSignature_default(body, signature) {
@@ -68,11 +61,10 @@ function checkSignature_default(body, signature) {
68
61
  throw new Error("Echoes invalid signature");
69
62
  }
70
63
  }
71
- __name(checkSignature_default, "default");
72
64
 
73
65
  // src/requestsHandler/index.ts
74
66
  import { route } from "@orion-js/http";
75
- var requestsHandler_default = /* @__PURE__ */ __name((options) => route({
67
+ var requestsHandler_default = (options) => route({
76
68
  method: "post",
77
69
  path: options.requests.handlerPath || "/echoes-services",
78
70
  bodyParser: "json",
@@ -105,7 +97,7 @@ var requestsHandler_default = /* @__PURE__ */ __name((options) => route({
105
97
  };
106
98
  }
107
99
  }
108
- }), "default");
100
+ });
109
101
 
110
102
  // src/startService/KafkaManager.ts
111
103
  import { Kafka } from "kafkajs";
@@ -113,8 +105,7 @@ var HEARTBEAT_INTERVAL_SECONDS = 5;
113
105
  var CHECK_JOIN_CONSUMER_INTERVAL_SECONDS = 30;
114
106
  var DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY = 4;
115
107
  var DEFAULT_MEMBERS_TO_PARTITIONS_RATIO = 1;
116
- var _a;
117
- var KafkaManager = (_a = class {
108
+ var KafkaManager = class {
118
109
  kafka;
119
110
  options;
120
111
  producer;
@@ -127,29 +118,34 @@ var KafkaManager = (_a = class {
127
118
  this.options = options;
128
119
  this.producer = this.kafka.producer(options.producer);
129
120
  this.consumer = this.kafka.consumer(options.consumer);
130
- this.topics = Object.keys(options.echoes).filter((key) => options.echoes[key].type === types_default.event);
121
+ this.topics = Object.keys(options.echoes).filter(
122
+ (key) => options.echoes[key].type === types_default.event
123
+ );
131
124
  }
132
125
  async checkJoinConsumerGroupConditions() {
133
126
  const admin = this.kafka.admin();
134
127
  try {
135
128
  await admin.connect();
136
- const groupDescriptions = await admin.describeGroups([
137
- this.options.consumer.groupId
138
- ]);
129
+ const groupDescriptions = await admin.describeGroups([this.options.consumer.groupId]);
139
130
  const group = groupDescriptions.groups[0];
140
131
  if (group.state === "Empty") {
141
132
  console.info(`Echoes: Consumer group ${this.options.consumer.groupId} is empty, joining`);
142
133
  return true;
143
134
  }
144
- const topicsMetadata = await admin.fetchTopicMetadata({
145
- topics: this.topics
146
- });
147
- const totalPartitions = topicsMetadata.topics.reduce((acc, topic) => acc + topic.partitions.length, 0);
148
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`);
135
+ const topicsMetadata = await admin.fetchTopicMetadata({ topics: this.topics });
136
+ const totalPartitions = topicsMetadata.topics.reduce(
137
+ (acc, topic) => acc + topic.partitions.length,
138
+ 0
139
+ );
140
+ console.info(
141
+ `Echoes: Consumer group ${this.options.consumer.groupId} has ${group.members.length} members and ${totalPartitions} partitions`
142
+ );
149
143
  const partitionsRatio = this.options.membersToPartitionsRatio || DEFAULT_MEMBERS_TO_PARTITIONS_RATIO;
150
144
  const partitionsThreshold = Math.ceil(totalPartitions * partitionsRatio);
151
145
  if (partitionsThreshold > group.members.length) {
152
- console.info(`Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`);
146
+ console.info(
147
+ `Echoes: Consumer group ${this.options.consumer.groupId} has room for more members ${group.members.length}/${partitionsThreshold}, joining`
148
+ );
153
149
  return true;
154
150
  }
155
151
  } catch (error) {
@@ -163,12 +159,10 @@ var KafkaManager = (_a = class {
163
159
  }
164
160
  async joinConsumerGroup() {
165
161
  await this.consumer.connect();
166
- await this.consumer.subscribe({
167
- topics: this.topics
168
- });
162
+ await this.consumer.subscribe({ topics: this.topics });
169
163
  await this.consumer.run({
170
164
  partitionsConsumedConcurrently: this.options.partitionsConsumedConcurrently || DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY,
171
- eachMessage: /* @__PURE__ */ __name((params) => this.handleMessage(params), "eachMessage")
165
+ eachMessage: (params) => this.handleMessage(params)
172
166
  });
173
167
  }
174
168
  async conditionalStart() {
@@ -207,7 +201,9 @@ var KafkaManager = (_a = class {
207
201
  });
208
202
  intervalsCount++;
209
203
  if (intervalsCount * HEARTBEAT_INTERVAL_SECONDS % 30 === 0) {
210
- console.warn(`Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`);
204
+ console.warn(
205
+ `Echoes: Event is taking too long to process: ${params.topic} ${intervalsCount * HEARTBEAT_INTERVAL_SECONDS}s`
206
+ );
211
207
  }
212
208
  }, HEARTBEAT_INTERVAL_SECONDS * 1e3);
213
209
  try {
@@ -220,9 +216,9 @@ var KafkaManager = (_a = class {
220
216
  }
221
217
  }
222
218
  async handleRetries(echo2, params, error) {
223
- var _a2, _b;
219
+ var _a, _b;
224
220
  const { message, topic } = params;
225
- const retries = Number.parseInt(((_b = (_a2 = message == null ? void 0 : message.headers) == null ? void 0 : _a2.retries) == null ? void 0 : _b.toString()) || "0", 10);
221
+ const retries = Number.parseInt(((_b = (_a = message == null ? void 0 : message.headers) == null ? void 0 : _a.retries) == null ? void 0 : _b.toString()) || "0", 10);
226
222
  if (echo2.attemptsBeforeDeadLetter === void 0 || echo2.attemptsBeforeDeadLetter === null) {
227
223
  throw error;
228
224
  }
@@ -242,12 +238,16 @@ var KafkaManager = (_a = class {
242
238
  ]
243
239
  });
244
240
  if (exceededMaxRetries) {
245
- console.error(`Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`);
241
+ console.error(
242
+ `Echoes: a message has reached the maximum number of retries, sending it to DLQ: ${nextTopic}`
243
+ );
246
244
  } else {
247
- console.warn(`Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`);
245
+ console.warn(
246
+ `Echoes: a retryable message failed "${error.message}", re-sending it to topic: ${nextTopic}`
247
+ );
248
248
  }
249
249
  }
250
- }, __name(_a, "KafkaManager"), _a);
250
+ };
251
251
  var KafkaManager_default = KafkaManager;
252
252
 
253
253
  // src/startService/index.ts
@@ -266,7 +266,6 @@ async function startService(options) {
266
266
  config_default.consumer = kafkaManager.consumer;
267
267
  }
268
268
  }
269
- __name(startService, "startService");
270
269
  async function stopService() {
271
270
  if (kafkaManager) {
272
271
  console.info("Stoping echoes...");
@@ -274,7 +273,6 @@ async function stopService() {
274
273
  console.info("Echoes stopped");
275
274
  }
276
275
  }
277
- __name(stopService, "stopService");
278
276
 
279
277
  // src/publish/index.ts
280
278
  async function publish(options) {
@@ -295,7 +293,6 @@ async function publish(options) {
295
293
  ]
296
294
  });
297
295
  }
298
- __name(publish, "publish");
299
296
 
300
297
  // src/echo/deserialize.ts
301
298
  function deserialize_default(serializedJavascript) {
@@ -305,13 +302,12 @@ function deserialize_default(serializedJavascript) {
305
302
  throw new Error("Error deserializing echo message");
306
303
  }
307
304
  }
308
- __name(deserialize_default, "default");
309
305
 
310
306
  // src/echo/index.ts
311
- var echo = /* @__PURE__ */ __name(function createNewEcho(options) {
307
+ var echo = function createNewEcho(options) {
312
308
  return {
313
309
  ...options,
314
- onMessage: /* @__PURE__ */ __name(async (messageData) => {
310
+ onMessage: async (messageData) => {
315
311
  const { message } = messageData;
316
312
  const data = deserialize_default(message.value.toString());
317
313
  const context = {
@@ -319,68 +315,66 @@ var echo = /* @__PURE__ */ __name(function createNewEcho(options) {
319
315
  data
320
316
  };
321
317
  await options.resolve(data.params || {}, context);
322
- }, "onMessage"),
323
- onRequest: /* @__PURE__ */ __name(async (serializedParams) => {
318
+ },
319
+ onRequest: async (serializedParams) => {
324
320
  const context = {};
325
321
  const params = deserialize_default(serializedParams);
326
322
  const result = await options.resolve(params || {}, context);
327
323
  return result;
328
- }, "onRequest")
324
+ }
329
325
  };
330
- }, "createNewEcho");
326
+ };
331
327
  echo.types = types_default;
332
328
  var echo_default = echo;
333
329
 
334
330
  // src/request/getURL.ts
335
331
  function getURL_default(serviceName) {
336
- var _a2, _b;
332
+ var _a, _b;
337
333
  if (serviceName.startsWith("http")) return serviceName;
338
- const url = (_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.services[serviceName];
334
+ const url = (_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.services[serviceName];
339
335
  if (!url) {
340
336
  throw new Error(`No URL found in echoes config for service ${serviceName}`);
341
337
  }
342
338
  return url;
343
339
  }
344
- __name(getURL_default, "default");
345
340
 
346
341
  // src/request/makeRequest.ts
347
342
  import axios from "axios";
348
343
  import { executeWithRetries } from "@orion-js/helpers";
349
- var makeRequest = /* @__PURE__ */ __name(async (options) => {
350
- const result = await executeWithRetries(async () => {
351
- return await axios({
352
- method: "post",
353
- url: options.url,
354
- timeout: options.timeout,
355
- headers: {
356
- "User-Agent": "Orionjs-Echoes/1.1"
357
- },
358
- data: options.data
359
- });
360
- }, options.retries, 200);
344
+ var makeRequest = async (options) => {
345
+ const result = await executeWithRetries(
346
+ async () => {
347
+ return await axios({
348
+ method: "post",
349
+ url: options.url,
350
+ timeout: options.timeout,
351
+ headers: {
352
+ "User-Agent": "Orionjs-Echoes/1.1"
353
+ },
354
+ data: options.data
355
+ });
356
+ },
357
+ options.retries,
358
+ 200
359
+ );
361
360
  return {
362
361
  data: result.data,
363
362
  statusCode: result.status
364
363
  };
365
- }, "makeRequest");
364
+ };
366
365
 
367
366
  // src/request/index.ts
368
367
  import { ValidationError } from "@orion-js/schema";
369
368
  import { UserError } from "@orion-js/helpers";
370
369
  async function request(options) {
371
- var _a2, _b;
370
+ var _a, _b;
372
371
  const { method, service, params } = options;
373
372
  const serializedParams = serialize_default(params);
374
373
  const date = /* @__PURE__ */ new Date();
375
- const body = {
376
- method,
377
- service,
378
- serializedParams,
379
- date
380
- };
374
+ const body = { method, service, serializedParams, date };
381
375
  const signature = getSignature_default(body);
382
376
  try {
383
- const requestMaker = ((_b = (_a2 = config_default) == null ? void 0 : _a2.requests) == null ? void 0 : _b.makeRequest) || makeRequest;
377
+ const requestMaker = ((_b = (_a = config_default) == null ? void 0 : _a.requests) == null ? void 0 : _b.makeRequest) || makeRequest;
384
378
  const requestOptions = {
385
379
  url: getURL_default(service),
386
380
  retries: options.retries,
@@ -414,54 +408,61 @@ async function request(options) {
414
408
  throw new Error(`Echoes request network error calling ${service}/${method}: ${error.message}`);
415
409
  }
416
410
  }
417
- __name(request, "request");
418
411
 
419
412
  // src/service/index.ts
420
413
  import { getInstance, Service } from "@orion-js/services";
414
+ var serviceMetadata = /* @__PURE__ */ new WeakMap();
415
+ var echoesMetadata = /* @__PURE__ */ new WeakMap();
421
416
  function Echoes() {
422
- return function(target) {
423
- Service()(target);
424
- target.prototype.service = target;
417
+ return function(target, context) {
418
+ Service()(target, context);
419
+ context.addInitializer(function() {
420
+ serviceMetadata.set(this, { _serviceType: "echoes" });
421
+ });
425
422
  };
426
423
  }
427
- __name(Echoes, "Echoes");
428
- function EchoRequest(options = {}) {
429
- return function(target, propertyKey, descriptor) {
430
- if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`);
431
- target.echoes = target.echoes || {};
432
- target.echoes[propertyKey] = echo_default({
433
- ...options,
434
- type: "request",
435
- resolve: /* @__PURE__ */ __name(async (params, viewer) => {
436
- const instance = getInstance(target.service);
437
- return await instance[propertyKey](params, viewer);
438
- }, "resolve")
424
+ function EchoEvent(options = {}) {
425
+ return function(method, context) {
426
+ const propertyKey = String(context.name);
427
+ context.addInitializer(function() {
428
+ const echoes = echoesMetadata.get(this) || {};
429
+ echoes[propertyKey] = echo_default({
430
+ ...options,
431
+ type: "event",
432
+ resolve: this[propertyKey].bind(this)
433
+ });
434
+ echoesMetadata.set(this, echoes);
439
435
  });
436
+ return method;
440
437
  };
441
438
  }
442
- __name(EchoRequest, "EchoRequest");
443
- function EchoEvent(options = {}) {
444
- return function(target, propertyKey, descriptor) {
445
- if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`);
446
- target.echoes = target.echoes || {};
447
- target.echoes[propertyKey] = echo_default({
448
- ...options,
449
- type: "event",
450
- resolve: /* @__PURE__ */ __name(async (params, viewer) => {
451
- const instance = getInstance(target.service);
452
- return await instance[propertyKey](params, viewer);
453
- }, "resolve")
439
+ function EchoRequest(options = {}) {
440
+ return function(method, context) {
441
+ const propertyKey = String(context.name);
442
+ context.addInitializer(function() {
443
+ const echoes = echoesMetadata.get(this) || {};
444
+ echoes[propertyKey] = echo_default({
445
+ ...options,
446
+ type: "request",
447
+ resolve: this[propertyKey].bind(this)
448
+ });
449
+ echoesMetadata.set(this, echoes);
454
450
  });
451
+ return method;
455
452
  };
456
453
  }
457
- __name(EchoEvent, "EchoEvent");
458
454
  function getServiceEchoes(target) {
459
- if (!target.prototype) {
460
- throw new Error("You must pass a class to getServiceRoutes");
455
+ const instance = getInstance(target);
456
+ if (!serviceMetadata.has(instance.constructor)) {
457
+ throw new Error("You must pass a class decorated with @Echoes to getServiceEchoes");
458
+ }
459
+ const instanceMetadata = serviceMetadata.get(instance.constructor);
460
+ if (instanceMetadata._serviceType !== "echoes") {
461
+ throw new Error("You must pass a class decorated with @Echoes to getServiceEchoes");
461
462
  }
462
- return target.prototype.echoes || {};
463
+ const echoesMap = echoesMetadata.get(instance) || {};
464
+ return echoesMap;
463
465
  }
464
- __name(getServiceEchoes, "getServiceEchoes");
465
466
  export {
466
467
  EchoEvent,
467
468
  EchoRequest,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/echo/types.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/echo/deserialize.ts","../src/echo/index.ts","../src/request/getURL.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/service/index.ts"],"sourcesContent":["import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","export default {\n event: 'event',\n request: 'request'\n}\n","import config from '../config'\nimport types from '../echo/types'\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 !== types.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 cloneDeep from 'lodash/cloneDeep'\n\nexport default function (data: any): string {\n const cloned = cloneDeep(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 types from '../echo/types'\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.Timer\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(\n key => options.echoes[key].type === types.event,\n )\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 !== types.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","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 {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig} from '../types'\nimport deserialize from './deserialize'\nimport types from './types'\n\nconst echo = function createNewEcho(options: EchoConfig): EchoType {\n return {\n ...options,\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 options.resolve(data.params || {}, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n const result = await options.resolve(params || {}, context)\n return result\n }\n }\n}\n\necho.types = types\n\nexport default echo\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","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 {getInstance, Service} from '@orion-js/services'\nimport echo from '../echo'\nimport {EchoConfig, EchoesMap} from '../types'\n\nexport function Echoes(): ClassDecorator {\n return function (target: any) {\n Service()(target)\n target.prototype.service = target\n }\n}\n\nexport interface EchoesPropertyDescriptor extends Omit<PropertyDecorator, 'value'> {\n value?: EchoConfig['resolve']\n}\n\nexport function EchoRequest(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) {\n if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`)\n\n target.echoes = target.echoes || {}\n target.echoes[propertyKey] = echo({\n ...options,\n type: 'request',\n resolve: async (params, viewer) => {\n const instance: any = getInstance(target.service)\n return await instance[propertyKey](params, viewer)\n }\n })\n }\n}\n\nexport function EchoEvent(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (target: any, propertyKey: string, descriptor: EchoesPropertyDescriptor) {\n if (!descriptor.value) throw new Error(`You must pass resolver function to ${propertyKey}`)\n\n target.echoes = target.echoes || {}\n target.echoes[propertyKey] = echo({\n ...options,\n type: 'event',\n resolve: async (params, viewer) => {\n const instance: any = getInstance(target.service)\n return await instance[propertyKey](params, viewer)\n }\n })\n }\n}\n\nexport function getServiceEchoes(target: any): EchoesMap {\n if (!target.prototype) {\n throw new Error('You must pass a class to getServiceRoutes')\n }\n\n return target.prototype.echoes || {}\n}\n"],"mappings":"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","names":["config","event","request","method","echo","config","echoes","Error","type","types","request","serialize","cloneDeep","data","cloned","cloneDeep","serialized","serialize","ignoreFunction","JSSHA","internalGetEnv","getEchoesPassword","_a","secret","config","requests","key","internalGetEnv","console","warn","body","password","getEchoesPassword","shaObj","JSSHA","setHMACKey","update","getHMAC","body","signature","generatedSignature","getSignature","Error","route","options","route","method","path","requests","handlerPath","bodyParser","bodyParserOptions","limit","resolve","req","body","signature","checkSignature","serializedParams","echo","getEcho","result","onRequest","serialize","error","getInfo","console","message","errorInfo","isValidationError","isUserError","Kafka","HEARTBEAT_INTERVAL_SECONDS","CHECK_JOIN_CONSUMER_INTERVAL_SECONDS","DEFAULT_PARTITIONS_CONSUMED_CONCURRENTLY","DEFAULT_MEMBERS_TO_PARTITIONS_RATIO","KafkaManager","kafka","options","producer","consumer","topics","started","interval","constructor","Kafka","client","Object","keys","echoes","filter","key","type","types","event","checkJoinConsumerGroupConditions","admin","connect","groupDescriptions","describeGroups","groupId","group","groups","state","console","info","topicsMetadata","fetchTopicMetadata","totalPartitions","reduce","acc","topic","partitions","length","members","partitionsRatio","membersToPartitionsRatio","partitionsThreshold","Math","ceil","error","message","disconnect","catch","joinConsumerGroup","subscribe","run","partitionsConsumedConcurrently","eachMessage","params","handleMessage","conditionalStart","start","setInterval","clearInterval","stop","warn","echo","intervalsCount","heartbeatInterval","heartbeat","onMessage","handleRetries","_a","retries","Number","parseInt","headers","toString","attemptsBeforeDeadLetter","undefined","maxRetries","exceededMaxRetries","nextTopic","send","messages","value","String","registerRoute","kafkaManager","options","config","echoes","requests","registerRoute","requestsHandler","client","KafkaManager","start","producer","consumer","startService","stopService","console","info","stop","options","config","producer","Error","payload","params","send","acks","timeout","topic","messages","value","serialize","publish","serializedJavascript","eval","error","Error","echo","createNewEcho","options","onMessage","messageData","message","data","deserialize","value","toString","context","resolve","params","onRequest","serializedParams","result","types","serviceName","_a","startsWith","url","config","requests","services","Error","axios","executeWithRetries","makeRequest","options","result","executeWithRetries","axios","method","url","timeout","headers","data","retries","statusCode","status","ValidationError","UserError","options","_a","method","service","params","serializedParams","serialize","date","Date","body","signature","getSignature","requestMaker","config","requests","makeRequest","requestOptions","url","getURL","retries","timeout","data","result","statusCode","Error","error","info","errorInfo","isValidationError","ValidationError","validationErrors","isUserError","UserError","message","extra","response","deserialize","isOrionError","request","getInstance","Service","Echoes","target","Service","prototype","service","EchoRequest","options","propertyKey","descriptor","value","Error","echoes","echo","type","resolve","params","viewer","instance","getInstance","EchoEvent","getServiceEchoes"]}
1
+ {"version":3,"sources":["../src/config.ts","../src/echo/types.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/echo/deserialize.ts","../src/echo/index.ts","../src/request/getURL.ts","../src/request/makeRequest.ts","../src/request/index.ts","../src/service/index.ts"],"sourcesContent":["import {EchoesConfigHandler} from './types'\n\nconst config: EchoesConfigHandler = {}\n\nexport default config\n","export default {\n event: 'event',\n request: 'request',\n}\n","import config from '../config'\nimport types from '../echo/types'\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 !== types.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 cloneDeep from 'lodash/cloneDeep'\n\nexport default function (data: any): string {\n const cloned = cloneDeep(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 types from '../echo/types'\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.Timer\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(\n key => options.echoes[key].type === types.event,\n )\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 !== types.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","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 {EachMessagePayload} from 'kafkajs'\nimport {EchoType, EchoConfig} from '../types'\nimport deserialize from './deserialize'\nimport types from './types'\n\nconst echo = function createNewEcho(options: EchoConfig): EchoType {\n return {\n ...options,\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 options.resolve(data.params || {}, context)\n },\n onRequest: async (serializedParams: string) => {\n const context = {}\n const params = deserialize(serializedParams)\n const result = await options.resolve(params || {}, context)\n return result\n },\n }\n}\n\necho.types = types\n\nexport default echo\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","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 echo 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['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 function (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 This,\n TArgs extends Parameters<EchoConfig['resolve']>,\n TReturn extends ReturnType<EchoConfig['resolve']>,\n>(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (\n method: (this: This, ...args: TArgs) => TReturn,\n context: ClassMethodDecoratorContext<This, typeof method>,\n ) {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this: This) {\n const echoes = echoesMetadata.get(this) || {}\n\n echoes[propertyKey] = echo({\n ...options,\n type: 'event',\n resolve: this[propertyKey].bind(this),\n })\n\n echoesMetadata.set(this, echoes)\n })\n\n return method\n }\n}\n\nexport function EchoRequest<\n This,\n TArgs extends Parameters<EchoConfig['resolve']>,\n TReturn extends ReturnType<EchoConfig['resolve']>,\n>(options: Omit<EchoConfig, 'resolve' | 'type'> = {}) {\n return function (\n method: (this: This, ...args: TArgs) => TReturn,\n context: ClassMethodDecoratorContext<This, typeof method>,\n ) {\n const propertyKey = String(context.name)\n\n context.addInitializer(function (this: This) {\n const echoes = echoesMetadata.get(this) || {}\n\n echoes[propertyKey] = echo({\n ...options,\n type: 'request',\n resolve: this[propertyKey].bind(this),\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-js/echoes",
3
- "version": "4.0.0-next.2",
3
+ "version": "4.0.0-next.4",
4
4
  "main": "./dist/index.cjs",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -14,15 +14,14 @@
14
14
  "kafkajs": "^2.2.4",
15
15
  "lodash": "^4.17.21",
16
16
  "serialize-javascript": "^6.0.0",
17
- "@orion-js/env": "4.0.0-next.2",
18
- "@orion-js/helpers": "4.0.0-next.2",
19
- "@orion-js/http": "4.0.0-next.2",
20
- "@orion-js/schema": "4.0.0-next.2",
21
- "@orion-js/services": "4.0.0-next.2"
17
+ "@orion-js/env": "4.0.0-next.4",
18
+ "@orion-js/helpers": "4.0.0-next.4",
19
+ "@orion-js/services": "4.0.0-next.4",
20
+ "@orion-js/http": "4.0.0-next.4",
21
+ "@orion-js/schema": "4.0.0-next.4"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/supertest": "2.0.11",
25
- "reflect-metadata": "^0.1.13",
26
25
  "supertest": "^6.1.6",
27
26
  "typescript": "^5.4.5",
28
27
  "@types/node": "^18.0.0",