apitally 0.11.3 → 0.11.5

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.
Files changed (73) hide show
  1. package/README.md +25 -12
  2. package/dist/common/client.cjs +21 -18
  3. package/dist/common/client.cjs.map +1 -1
  4. package/dist/common/client.d.cts +2 -0
  5. package/dist/common/client.d.ts +2 -0
  6. package/dist/common/client.js +21 -18
  7. package/dist/common/client.js.map +1 -1
  8. package/dist/common/consumerRegistry.cjs.map +1 -1
  9. package/dist/common/consumerRegistry.js.map +1 -1
  10. package/dist/common/logging.cjs.map +1 -1
  11. package/dist/common/logging.js.map +1 -1
  12. package/dist/common/packageVersions.cjs.map +1 -1
  13. package/dist/common/packageVersions.js.map +1 -1
  14. package/dist/common/paramValidation.cjs.map +1 -1
  15. package/dist/common/paramValidation.js.map +1 -1
  16. package/dist/common/requestCounter.cjs.map +1 -1
  17. package/dist/common/requestCounter.js.map +1 -1
  18. package/dist/common/requestLogger.cjs +8 -5
  19. package/dist/common/requestLogger.cjs.map +1 -1
  20. package/dist/common/requestLogger.d.cts +1 -0
  21. package/dist/common/requestLogger.d.ts +1 -0
  22. package/dist/common/requestLogger.js +8 -5
  23. package/dist/common/requestLogger.js.map +1 -1
  24. package/dist/common/serverErrorCounter.cjs.map +1 -1
  25. package/dist/common/serverErrorCounter.js.map +1 -1
  26. package/dist/common/tempGzipFile.cjs +2 -2
  27. package/dist/common/tempGzipFile.cjs.map +1 -1
  28. package/dist/common/tempGzipFile.js +2 -2
  29. package/dist/common/tempGzipFile.js.map +1 -1
  30. package/dist/common/types.cjs.map +1 -1
  31. package/dist/common/types.d.cts +1 -1
  32. package/dist/common/types.d.ts +1 -1
  33. package/dist/common/validationErrorCounter.cjs.map +1 -1
  34. package/dist/common/validationErrorCounter.js.map +1 -1
  35. package/dist/express/index.cjs +29 -19
  36. package/dist/express/index.cjs.map +1 -1
  37. package/dist/express/index.js +29 -19
  38. package/dist/express/index.js.map +1 -1
  39. package/dist/express/middleware.cjs +29 -19
  40. package/dist/express/middleware.cjs.map +1 -1
  41. package/dist/express/middleware.js +29 -19
  42. package/dist/express/middleware.js.map +1 -1
  43. package/dist/express/utils.cjs.map +1 -1
  44. package/dist/express/utils.js.map +1 -1
  45. package/dist/fastify/index.cjs +26 -20
  46. package/dist/fastify/index.cjs.map +1 -1
  47. package/dist/fastify/index.js +26 -20
  48. package/dist/fastify/index.js.map +1 -1
  49. package/dist/fastify/plugin.cjs +26 -20
  50. package/dist/fastify/plugin.cjs.map +1 -1
  51. package/dist/fastify/plugin.js +26 -20
  52. package/dist/fastify/plugin.js.map +1 -1
  53. package/dist/hono/index.cjs +27 -19
  54. package/dist/hono/index.cjs.map +1 -1
  55. package/dist/hono/index.js +27 -19
  56. package/dist/hono/index.js.map +1 -1
  57. package/dist/hono/middleware.cjs +27 -19
  58. package/dist/hono/middleware.cjs.map +1 -1
  59. package/dist/hono/middleware.js +27 -19
  60. package/dist/hono/middleware.js.map +1 -1
  61. package/dist/koa/index.cjs +25 -18
  62. package/dist/koa/index.cjs.map +1 -1
  63. package/dist/koa/index.js +25 -18
  64. package/dist/koa/index.js.map +1 -1
  65. package/dist/koa/middleware.cjs +25 -18
  66. package/dist/koa/middleware.cjs.map +1 -1
  67. package/dist/koa/middleware.js +25 -18
  68. package/dist/koa/middleware.js.map +1 -1
  69. package/dist/nestjs/index.cjs +29 -19
  70. package/dist/nestjs/index.cjs.map +1 -1
  71. package/dist/nestjs/index.js +29 -19
  72. package/dist/nestjs/index.js.map +1 -1
  73. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/common/validationErrorCounter.ts"],"sourcesContent":["import { createHash } from \"crypto\";\n\nimport {\n ConsumerMethodPath,\n ValidationError,\n ValidationErrorsItem,\n} from \"./types.js\";\n\nexport default class ValidationErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ValidationError>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n }\n\n public addValidationError(\n validationError: ConsumerMethodPath & ValidationError,\n ) {\n const key = this.getKey(validationError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, validationError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n }\n\n public getAndResetValidationErrors() {\n const data: Array<ValidationErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const validationError = this.errorDetails.get(key);\n if (validationError) {\n data.push({\n consumer: validationError.consumer || null,\n method: validationError.method,\n path: validationError.path,\n loc: validationError.loc.split(\".\"),\n msg: validationError.msg,\n type: validationError.type,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n return data;\n }\n\n private getKey(validationError: ConsumerMethodPath & ValidationError) {\n const hashInput = [\n validationError.consumer || \"\",\n validationError.method.toUpperCase(),\n validationError.path,\n validationError.loc,\n validationError.msg.trim(),\n validationError.type,\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAQ3B,IAAqBC,0BAArB,MAAqBA,wBAAAA;EACXC;EACAC;EAERC,cAAc;AACZ,SAAKF,cAAc,oBAAIG,IAAAA;AACvB,SAAKF,eAAe,oBAAIE,IAAAA;EAC1B;EAEOC,mBACLC,iBACA;AACA,UAAMC,MAAM,KAAKC,OAAOF,eAAAA;AACxB,QAAI,CAAC,KAAKJ,aAAaO,IAAIF,GAAAA,GAAM;AAC/B,WAAKL,aAAaQ,IAAIH,KAAKD,eAAAA;IAC7B;AACA,SAAKL,YAAYS,IAAIH,MAAM,KAAKN,YAAYU,IAAIJ,GAAAA,KAAQ,KAAK,CAAA;EAC/D;EAEOK,8BAA8B;AACnC,UAAMC,OAAoC,CAAA;AAC1C,SAAKZ,YAAYa,QAAQ,CAACC,OAAOR,QAAAA;AAC/B,YAAMD,kBAAkB,KAAKJ,aAAaS,IAAIJ,GAAAA;AAC9C,UAAID,iBAAiB;AACnBO,aAAKG,KAAK;UACRC,UAAUX,gBAAgBW,YAAY;UACtCC,QAAQZ,gBAAgBY;UACxBC,MAAMb,gBAAgBa;UACtBC,KAAKd,gBAAgBc,IAAIC,MAAM,GAAA;UAC/BC,KAAKhB,gBAAgBgB;UACrBC,MAAMjB,gBAAgBiB;UACtBC,aAAaT;QACf,CAAA;MACF;IACF,CAAA;AACA,SAAKd,YAAYwB,MAAK;AACtB,SAAKvB,aAAauB,MAAK;AACvB,WAAOZ;EACT;EAEQL,OAAOF,iBAAuD;AACpE,UAAMoB,YAAY;MAChBpB,gBAAgBW,YAAY;MAC5BX,gBAAgBY,OAAOS,YAAW;MAClCrB,gBAAgBa;MAChBb,gBAAgBc;MAChBd,gBAAgBgB,IAAIM,KAAI;MACxBtB,gBAAgBiB;MAChBM,KAAK,GAAA;AACP,WAAOC,WAAW,KAAA,EAAOC,OAAOL,SAAAA,EAAWM,OAAO,KAAA;EACpD;AACF;AAnDqBhC;AAArB,IAAqBA,yBAArB;","names":["createHash","ValidationErrorCounter","errorCounts","errorDetails","constructor","Map","addValidationError","validationError","key","getKey","has","set","get","getAndResetValidationErrors","data","forEach","count","push","consumer","method","path","loc","split","msg","type","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest"]}
1
+ {"version":3,"sources":["validationErrorCounter.ts"],"sourcesContent":["import { createHash } from \"crypto\";\n\nimport {\n ConsumerMethodPath,\n ValidationError,\n ValidationErrorsItem,\n} from \"./types.js\";\n\nexport default class ValidationErrorCounter {\n private errorCounts: Map<string, number>;\n private errorDetails: Map<string, ConsumerMethodPath & ValidationError>;\n\n constructor() {\n this.errorCounts = new Map();\n this.errorDetails = new Map();\n }\n\n public addValidationError(\n validationError: ConsumerMethodPath & ValidationError,\n ) {\n const key = this.getKey(validationError);\n if (!this.errorDetails.has(key)) {\n this.errorDetails.set(key, validationError);\n }\n this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);\n }\n\n public getAndResetValidationErrors() {\n const data: Array<ValidationErrorsItem> = [];\n this.errorCounts.forEach((count, key) => {\n const validationError = this.errorDetails.get(key);\n if (validationError) {\n data.push({\n consumer: validationError.consumer || null,\n method: validationError.method,\n path: validationError.path,\n loc: validationError.loc.split(\".\"),\n msg: validationError.msg,\n type: validationError.type,\n error_count: count,\n });\n }\n });\n this.errorCounts.clear();\n this.errorDetails.clear();\n return data;\n }\n\n private getKey(validationError: ConsumerMethodPath & ValidationError) {\n const hashInput = [\n validationError.consumer || \"\",\n validationError.method.toUpperCase(),\n validationError.path,\n validationError.loc,\n validationError.msg.trim(),\n validationError.type,\n ].join(\"|\");\n return createHash(\"md5\").update(hashInput).digest(\"hex\");\n }\n}\n"],"mappings":";;;;AAAA,SAASA,kBAAkB;AAQ3B,IAAqBC,0BAArB,MAAqBA,wBAAAA;EACXC;EACAC;EAERC,cAAc;AACZ,SAAKF,cAAc,oBAAIG,IAAAA;AACvB,SAAKF,eAAe,oBAAIE,IAAAA;EAC1B;EAEOC,mBACLC,iBACA;AACA,UAAMC,MAAM,KAAKC,OAAOF,eAAAA;AACxB,QAAI,CAAC,KAAKJ,aAAaO,IAAIF,GAAAA,GAAM;AAC/B,WAAKL,aAAaQ,IAAIH,KAAKD,eAAAA;IAC7B;AACA,SAAKL,YAAYS,IAAIH,MAAM,KAAKN,YAAYU,IAAIJ,GAAAA,KAAQ,KAAK,CAAA;EAC/D;EAEOK,8BAA8B;AACnC,UAAMC,OAAoC,CAAA;AAC1C,SAAKZ,YAAYa,QAAQ,CAACC,OAAOR,QAAAA;AAC/B,YAAMD,kBAAkB,KAAKJ,aAAaS,IAAIJ,GAAAA;AAC9C,UAAID,iBAAiB;AACnBO,aAAKG,KAAK;UACRC,UAAUX,gBAAgBW,YAAY;UACtCC,QAAQZ,gBAAgBY;UACxBC,MAAMb,gBAAgBa;UACtBC,KAAKd,gBAAgBc,IAAIC,MAAM,GAAA;UAC/BC,KAAKhB,gBAAgBgB;UACrBC,MAAMjB,gBAAgBiB;UACtBC,aAAaT;QACf,CAAA;MACF;IACF,CAAA;AACA,SAAKd,YAAYwB,MAAK;AACtB,SAAKvB,aAAauB,MAAK;AACvB,WAAOZ;EACT;EAEQL,OAAOF,iBAAuD;AACpE,UAAMoB,YAAY;MAChBpB,gBAAgBW,YAAY;MAC5BX,gBAAgBY,OAAOS,YAAW;MAClCrB,gBAAgBa;MAChBb,gBAAgBc;MAChBd,gBAAgBgB,IAAIM,KAAI;MACxBtB,gBAAgBiB;MAChBM,KAAK,GAAA;AACP,WAAOC,WAAW,KAAA,EAAOC,OAAOL,SAAAA,EAAWM,OAAO,KAAA;EACpD;AACF;AAnDqBhC;AAArB,IAAqBA,yBAArB;","names":["createHash","ValidationErrorCounter","errorCounts","errorDetails","constructor","Map","addValidationError","validationError","key","getKey","has","set","get","getAndResetValidationErrors","data","forEach","count","push","consumer","method","path","loc","split","msg","type","error_count","clear","hashInput","toUpperCase","trim","join","createHash","update","digest"]}
@@ -240,9 +240,9 @@ var _TempGzipFile = class _TempGzipFile {
240
240
  this.writeStream.once("ready", resolve);
241
241
  this.writeStream.once("error", reject);
242
242
  });
243
- this.closedPromise = new Promise((resolve) => {
243
+ this.closedPromise = new Promise((resolve, reject) => {
244
244
  this.writeStream.once("close", resolve);
245
- this.writeStream.once("error", resolve);
245
+ this.writeStream.once("error", reject);
246
246
  });
247
247
  this.gzip = (0, import_zlib.createGzip)();
248
248
  this.gzip.pipe(this.writeStream);
@@ -392,7 +392,10 @@ var _RequestLogger = class _RequestLogger {
392
392
  hasSupportedContentType(headers) {
393
393
  var _a2;
394
394
  const contentType = (_a2 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a2[1];
395
- return contentType !== void 0 && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
395
+ return this.isSupportedContentType(contentType);
396
+ }
397
+ isSupportedContentType(contentType) {
398
+ return typeof contentType === "string" && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
396
399
  }
397
400
  maskQueryParams(search) {
398
401
  const params = new URLSearchParams(search);
@@ -420,8 +423,6 @@ var _RequestLogger = class _RequestLogger {
420
423
  }
421
424
  url.search = this.config.logQueryParams ? this.maskQueryParams(url.search) : "";
422
425
  request.url = url.toString();
423
- request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
424
- response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
425
426
  if (!this.config.logRequestBody || !this.hasSupportedContentType(request.headers)) {
426
427
  request.body = void 0;
427
428
  } else if (request.body) {
@@ -454,6 +455,8 @@ var _RequestLogger = class _RequestLogger {
454
455
  }
455
456
  }
456
457
  }
458
+ request.headers = this.config.logRequestHeaders ? this.maskHeaders(request.headers) : [];
459
+ response.headers = this.config.logResponseHeaders ? this.maskHeaders(response.headers) : [];
457
460
  const item = {
458
461
  uuid: (0, import_crypto2.randomUUID)(),
459
462
  request: skipEmptyValues(request),
@@ -790,6 +793,7 @@ var _ApitallyClient = class _ApitallyClient {
790
793
  syncIntervalId;
791
794
  startupData;
792
795
  startupDataSent = false;
796
+ enabled = true;
793
797
  requestCounter;
794
798
  requestLogger;
795
799
  validationErrorCounter;
@@ -826,12 +830,16 @@ var _ApitallyClient = class _ApitallyClient {
826
830
  }
827
831
  return _ApitallyClient.instance;
828
832
  }
833
+ isEnabled() {
834
+ return this.enabled;
835
+ }
829
836
  static async shutdown() {
830
837
  if (_ApitallyClient.instance) {
831
838
  await _ApitallyClient.instance.handleShutdown();
832
839
  }
833
840
  }
834
841
  async handleShutdown() {
842
+ this.enabled = false;
835
843
  this.stopSync();
836
844
  await this.sendSyncData();
837
845
  await this.sendLogData();
@@ -931,7 +939,7 @@ var _ApitallyClient = class _ApitallyClient {
931
939
  async sendSyncData() {
932
940
  this.logger.debug("Synchronizing data with Apitally Hub");
933
941
  const newPayload = {
934
- time_offset: 0,
942
+ timestamp: Date.now() / 1e3,
935
943
  instance_uuid: this.instanceUuid,
936
944
  message_uuid: (0, import_crypto5.randomUUID)(),
937
945
  requests: this.requestCounter.getAndResetRequests(),
@@ -939,22 +947,16 @@ var _ApitallyClient = class _ApitallyClient {
939
947
  server_errors: this.serverErrorCounter.getAndResetServerErrors(),
940
948
  consumers: this.consumerRegistry.getAndResetUpdatedConsumers()
941
949
  };
942
- this.syncDataQueue.push([
943
- Date.now(),
944
- newPayload
945
- ]);
950
+ this.syncDataQueue.push(newPayload);
946
951
  let i = 0;
947
952
  while (this.syncDataQueue.length > 0) {
948
- const queueItem = this.syncDataQueue.shift();
949
- if (queueItem) {
950
- const [time, payload] = queueItem;
953
+ const payload = this.syncDataQueue.shift();
954
+ if (payload) {
951
955
  try {
952
- const timeOffset = Date.now() - time;
953
- if (timeOffset <= MAX_QUEUE_TIME) {
956
+ if (Date.now() - payload.timestamp * 1e3 <= MAX_QUEUE_TIME) {
954
957
  if (i > 0) {
955
958
  await this.randomDelay();
956
959
  }
957
- payload.time_offset = timeOffset / 1e3;
958
960
  await this.sendData("sync", payload);
959
961
  i += 1;
960
962
  }
@@ -964,7 +966,7 @@ var _ApitallyClient = class _ApitallyClient {
964
966
  this.logger.debug("Error while synchronizing data with Apitally Hub (will retry)", {
965
967
  error
966
968
  });
967
- this.syncDataQueue.push(queueItem);
969
+ this.syncDataQueue.push(payload);
968
970
  break;
969
971
  }
970
972
  }
@@ -1021,6 +1023,7 @@ var _ApitallyClient = class _ApitallyClient {
1021
1023
  if (error instanceof HTTPError) {
1022
1024
  if (error.response.status === 404) {
1023
1025
  this.logger.error(`Invalid Apitally client ID: '${this.clientId}'`);
1026
+ this.enabled = false;
1024
1027
  this.stopSync();
1025
1028
  return true;
1026
1029
  }
@@ -1032,7 +1035,7 @@ var _ApitallyClient = class _ApitallyClient {
1032
1035
  return false;
1033
1036
  }
1034
1037
  async randomDelay() {
1035
- const delay = 100 + Math.random() * 200;
1038
+ const delay = 100 + Math.random() * 400;
1036
1039
  await new Promise((resolve) => setTimeout(resolve, delay));
1037
1040
  }
1038
1041
  };
@@ -1196,6 +1199,10 @@ var useApitally = /* @__PURE__ */ __name((app, config) => {
1196
1199
  var getMiddleware = /* @__PURE__ */ __name((app, client) => {
1197
1200
  let errorHandlerConfigured = false;
1198
1201
  return (req, res, next) => {
1202
+ if (!client.isEnabled()) {
1203
+ next();
1204
+ return;
1205
+ }
1199
1206
  if (!errorHandlerConfigured) {
1200
1207
  app.use((err, req2, res2, next2) => {
1201
1208
  res2.locals.serverError = err;
@@ -1207,7 +1214,10 @@ var getMiddleware = /* @__PURE__ */ __name((app, client) => {
1207
1214
  const startTime = import_perf_hooks.performance.now();
1208
1215
  const originalSend = res.send;
1209
1216
  res.send = (body) => {
1210
- res.locals.body = body;
1217
+ const contentType = res.get("content-type");
1218
+ if (client.requestLogger.isSupportedContentType(contentType)) {
1219
+ res.locals.body = body;
1220
+ }
1211
1221
  return originalSend.call(res, body);
1212
1222
  };
1213
1223
  res.on("finish", () => {