@lokalise/fastify-extras 26.0.0 → 26.1.0

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/README.md CHANGED
@@ -240,6 +240,10 @@ Additionally, you have the option to enhance the safety and accuracy of your eve
240
240
 
241
241
  > 📘Check [`AmplitudeAdapter.spec.ts](./lib/plugins/amplitude/amplitudePlugin.spec.ts) for a practical example
242
242
 
243
+ ### Strip Trailing Slash Plugin
244
+
245
+ This plugin helps with SEO and SSR by ensuring search engines index only one version of a URL, avoiding duplicate content. It redirects URLs with a trailing slash to the version without it, making it easier for search engines to crawl your site consistently.
246
+
243
247
  ### UnhandledException Plugin
244
248
 
245
249
  This plugin provides a mechanism for handling uncaught exceptions within your Fastify application, ensuring that such exceptions are logged and reported. It's especially useful for capturing unforeseen exceptions and provides a controlled shutdown of the Fastify server, thereby ensuring no potential data corruption.
package/dist/index.d.ts CHANGED
@@ -25,6 +25,7 @@ export { amplitudePlugin, type AmplitudeConfig, type CreateApiTrackingEventFn, }
25
25
  export { Amplitude } from './plugins/amplitude/Amplitude';
26
26
  export { AmplitudeAdapter, AMPLITUDE_BASE_MESSAGE_SCHEMA, type AmplitudeMessage, type AmplitudeAdapterDependencies, } from './plugins/amplitude/AmplitudeAdapter';
27
27
  export type { FastifyReplyWithPayload } from './types';
28
+ export { stripTrailingSlashPlugin } from './plugins/stripTrailingSlashPlugin';
28
29
  export { unhandledExceptionPlugin, commonErrorObjectResolver, } from './plugins/unhandledExceptionPlugin';
29
30
  export type { UnhandledExceptionPluginOptions } from './plugins/unhandledExceptionPlugin';
30
31
  export { createErrorHandler, isZodError, type ErrorResponseObject } from './errors/errorHandler';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createStaticTokenAuthPreHandler = exports.decodeJwtToken = exports.generateJwtToken = exports.isZodError = exports.createErrorHandler = exports.commonErrorObjectResolver = exports.unhandledExceptionPlugin = exports.AMPLITUDE_BASE_MESSAGE_SCHEMA = exports.AmplitudeAdapter = exports.Amplitude = exports.amplitudePlugin = exports.commonHealthcheckPlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.metricsPlugin = exports.BackgroundJobsBasedQueueDiscoverer = exports.RedisBasedQueueDiscoverer = exports.bullMqMetricsPlugin = exports.PrometheusCounterTransactionManager = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = exports.addFeatureFlag = exports.bugsnagErrorReporter = exports.reportErrorToBugsnag = exports.bugsnagPlugin = void 0;
3
+ exports.createStaticTokenAuthPreHandler = exports.decodeJwtToken = exports.generateJwtToken = exports.isZodError = exports.createErrorHandler = exports.commonErrorObjectResolver = exports.unhandledExceptionPlugin = exports.stripTrailingSlashPlugin = exports.AMPLITUDE_BASE_MESSAGE_SCHEMA = exports.AmplitudeAdapter = exports.Amplitude = exports.amplitudePlugin = exports.commonHealthcheckPlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.metricsPlugin = exports.BackgroundJobsBasedQueueDiscoverer = exports.RedisBasedQueueDiscoverer = exports.bullMqMetricsPlugin = exports.PrometheusCounterTransactionManager = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = exports.addFeatureFlag = exports.bugsnagErrorReporter = exports.reportErrorToBugsnag = exports.bugsnagPlugin = void 0;
4
4
  var bugsnagPlugin_1 = require("./plugins/bugsnagPlugin");
5
5
  Object.defineProperty(exports, "bugsnagPlugin", { enumerable: true, get: function () { return bugsnagPlugin_1.bugsnagPlugin; } });
6
6
  Object.defineProperty(exports, "reportErrorToBugsnag", { enumerable: true, get: function () { return bugsnagPlugin_1.reportErrorToBugsnag; } });
@@ -40,6 +40,8 @@ Object.defineProperty(exports, "Amplitude", { enumerable: true, get: function ()
40
40
  var AmplitudeAdapter_1 = require("./plugins/amplitude/AmplitudeAdapter");
41
41
  Object.defineProperty(exports, "AmplitudeAdapter", { enumerable: true, get: function () { return AmplitudeAdapter_1.AmplitudeAdapter; } });
42
42
  Object.defineProperty(exports, "AMPLITUDE_BASE_MESSAGE_SCHEMA", { enumerable: true, get: function () { return AmplitudeAdapter_1.AMPLITUDE_BASE_MESSAGE_SCHEMA; } });
43
+ var stripTrailingSlashPlugin_1 = require("./plugins/stripTrailingSlashPlugin");
44
+ Object.defineProperty(exports, "stripTrailingSlashPlugin", { enumerable: true, get: function () { return stripTrailingSlashPlugin_1.stripTrailingSlashPlugin; } });
43
45
  var unhandledExceptionPlugin_1 = require("./plugins/unhandledExceptionPlugin");
44
46
  Object.defineProperty(exports, "unhandledExceptionPlugin", { enumerable: true, get: function () { return unhandledExceptionPlugin_1.unhandledExceptionPlugin; } });
45
47
  Object.defineProperty(exports, "commonErrorObjectResolver", { enumerable: true, get: function () { return unhandledExceptionPlugin_1.commonErrorObjectResolver; } });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAKgC;AAJ9B,8GAAA,aAAa,OAAA;AACb,qHAAA,oBAAoB,OAAA;AACpB,qHAAA,oBAAoB,OAAA;AACpB,+GAAA,cAAc,OAAA;AAIhB,uFAG+C;AAF7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAI9B,+FAGmD;AAFjD,oJAAA,gCAAgC,OAAA;AAChC,8IAAA,0BAA0B,OAAA;AAI5B,qFAG8C;AAF5C,0IAAA,2BAA2B,OAAA;AAC3B,oIAAA,qBAAqB,OAAA;AAIvB,2FAGuD;AAFrD,oIAAA,wBAAwB,OAAA;AACxB,wIAAA,4BAA4B,OAAA;AAQ9B,gHAA8G;AAArG,0JAAA,mCAAmC,OAAA;AAE5C,qEAAmE;AAA1D,0HAAA,mBAAmB,OAAA;AAE5B,+EAGmD;AAFjD,6HAAA,yBAAyB,OAAA;AACzB,sIAAA,kCAAkC,OAAA;AAIpC,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAMtB,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAOhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAGhC,uEAI4C;AAH1C,kHAAA,eAAe,OAAA;AAIjB,2DAAyD;AAAhD,sGAAA,SAAS,OAAA;AAClB,yEAK6C;AAJ3C,oHAAA,gBAAgB,OAAA;AAChB,iIAAA,6BAA6B,OAAA;AAO/B,+EAG2C;AAFzC,oIAAA,wBAAwB,OAAA;AACxB,qIAAA,yBAAyB,OAAA;AAI3B,sDAAgG;AAAvF,kHAAA,kBAAkB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAGvC,qDAAyE;AAAhE,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA;AAEzC,iEAA+E;AAAtE,kIAAA,+BAA+B,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAKgC;AAJ9B,8GAAA,aAAa,OAAA;AACb,qHAAA,oBAAoB,OAAA;AACpB,qHAAA,oBAAoB,OAAA;AACpB,+GAAA,cAAc,OAAA;AAIhB,uFAG+C;AAF7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAI9B,+FAGmD;AAFjD,oJAAA,gCAAgC,OAAA;AAChC,8IAAA,0BAA0B,OAAA;AAI5B,qFAG8C;AAF5C,0IAAA,2BAA2B,OAAA;AAC3B,oIAAA,qBAAqB,OAAA;AAIvB,2FAGuD;AAFrD,oIAAA,wBAAwB,OAAA;AACxB,wIAAA,4BAA4B,OAAA;AAQ9B,gHAA8G;AAArG,0JAAA,mCAAmC,OAAA;AAE5C,qEAAmE;AAA1D,0HAAA,mBAAmB,OAAA;AAE5B,+EAGmD;AAFjD,6HAAA,yBAAyB,OAAA;AACzB,sIAAA,kCAAkC,OAAA;AAIpC,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAMtB,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAOhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAGhC,uEAI4C;AAH1C,kHAAA,eAAe,OAAA;AAIjB,2DAAyD;AAAhD,sGAAA,SAAS,OAAA;AAClB,yEAK6C;AAJ3C,oHAAA,gBAAgB,OAAA;AAChB,iIAAA,6BAA6B,OAAA;AAO/B,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAEjC,+EAG2C;AAFzC,oIAAA,wBAAwB,OAAA;AACxB,qIAAA,yBAAyB,OAAA;AAI3B,sDAAgG;AAAvF,kHAAA,kBAAkB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAGvC,qDAAyE;AAAhE,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA;AAEzC,iEAA+E;AAAtE,kIAAA,+BAA+B,OAAA"}
@@ -5,6 +5,7 @@ export interface CommonHealthcheckPluginOptions {
5
5
  logLevel?: 'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent';
6
6
  healthChecks: readonly HealthCheck[];
7
7
  infoProviders?: readonly InfoProvider[];
8
+ isRootRouteEnabled?: boolean;
8
9
  }
9
10
  export type InfoProvider = {
10
11
  name: string;
@@ -43,31 +43,26 @@ function addRoute(app, opts, routeOpts) {
43
43
  let isPartiallyHealthy = false;
44
44
  let healthChecks = {};
45
45
  if (opts.healthChecks.length) {
46
- const results = await Promise.all(opts.healthChecks.map((healthcheck) => {
47
- return healthcheck.checker(app).then((result) => {
48
- if (result.error) {
49
- app.log.error(result.error, `${healthcheck.name} healthcheck has failed`);
50
- }
51
- return {
52
- name: healthcheck.name,
53
- result,
54
- isMandatory: healthcheck.isMandatory,
55
- };
56
- });
46
+ const results = await Promise.all(opts.healthChecks.map(async (healthcheck) => {
47
+ const result = await healthcheck.checker(app);
48
+ if (result.error) {
49
+ app.log.error(result.error, `${healthcheck.name} healthcheck has failed`);
50
+ }
51
+ return {
52
+ name: healthcheck.name,
53
+ result,
54
+ isMandatory: healthcheck.isMandatory,
55
+ };
57
56
  }));
58
57
  const resolvedHealthcheckResponse = resolveHealthcheckResults(results, opts);
59
58
  healthChecks = resolvedHealthcheckResponse.healthChecks;
60
59
  isFullyHealthy = resolvedHealthcheckResponse.isFullyHealthy;
61
60
  isPartiallyHealthy = resolvedHealthcheckResponse.isPartiallyHealthy;
62
61
  }
63
- const extraInfo = opts.infoProviders
64
- ? opts.infoProviders.map((infoProvider) => {
65
- return {
66
- name: infoProvider.name,
67
- value: infoProvider.dataResolver(),
68
- };
69
- })
70
- : undefined;
62
+ const extraInfo = opts.infoProviders?.map((infoProvider) => ({
63
+ name: infoProvider.name,
64
+ value: infoProvider.dataResolver(),
65
+ }));
71
66
  const heartbeat = isFullyHealthy
72
67
  ? 'HEALTHY'
73
68
  : isPartiallyHealthy
@@ -84,17 +79,20 @@ function addRoute(app, opts, routeOpts) {
84
79
  },
85
80
  });
86
81
  }
87
- function plugin(app, opts, done) {
88
- addRoute(app, opts, {
89
- url: '/',
90
- isPublicRoute: true,
91
- });
82
+ const plugin = (app, opts, done) => {
83
+ const isRootRouteEnabled = opts.isRootRouteEnabled ?? true;
84
+ if (isRootRouteEnabled) {
85
+ addRoute(app, opts, {
86
+ url: '/',
87
+ isPublicRoute: true,
88
+ });
89
+ }
92
90
  addRoute(app, opts, {
93
91
  url: '/health',
94
92
  isPublicRoute: false,
95
93
  });
96
94
  done();
97
- }
95
+ };
98
96
  exports.commonHealthcheckPlugin = (0, fastify_plugin_1.default)(plugin, {
99
97
  fastify: '5.x',
100
98
  name: 'common-healthcheck-plugin',
@@ -1 +1 @@
1
- {"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"commonHealthcheckPlugin.js","sourceRoot":"","sources":["../../../lib/plugins/healthcheck/commonHealthcheckPlugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { FastifyPluginCallback } from 'fastify';
2
+ export declare const stripTrailingSlashPlugin: FastifyPluginCallback;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stripTrailingSlashPlugin = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fastify_plugin_1 = tslib_1.__importDefault(require("fastify-plugin"));
6
+ const pluginCallback = (fastify, _options, done) => {
7
+ fastify.addHook('onRequest', (request, reply, done) => {
8
+ const { pathname, search } = new URL(`${request.protocol}://${request.hostname}:${request.port}${request.url}`);
9
+ if (pathname.length > 1 && pathname.endsWith('/')) {
10
+ reply.redirect(`${pathname.slice(0, -1)}${search}`, 302);
11
+ }
12
+ else {
13
+ done();
14
+ }
15
+ });
16
+ done();
17
+ };
18
+ exports.stripTrailingSlashPlugin = (0, fastify_plugin_1.default)(pluginCallback, {
19
+ fastify: '5.x',
20
+ name: 'strip-trailing-slash-plugin',
21
+ });
22
+ //# sourceMappingURL=stripTrailingSlashPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripTrailingSlashPlugin.js","sourceRoot":"","sources":["../../lib/plugins/stripTrailingSlashPlugin.ts"],"names":[],"mappings":";;;;AACA,4EAA+B;AAE/B,MAAM,cAAc,GAA0B,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;IACxE,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACpD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,CAClC,GAAG,OAAO,CAAC,QAAQ,MAAM,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAC1E,CAAA;QAED,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,KAAK,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,EAAE,GAAG,CAAC,CAAA;QAC1D,CAAC;aAAM,CAAC;YACN,IAAI,EAAE,CAAA;QACR,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,IAAI,EAAE,CAAA;AACR,CAAC,CAAA;AAEY,QAAA,wBAAwB,GAAG,IAAA,wBAAE,EAAC,cAAc,EAAE;IACzD,OAAO,EAAE,KAAK;IACd,IAAI,EAAE,6BAA6B;CACpC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokalise/fastify-extras",
3
- "version": "26.0.0",
3
+ "version": "26.1.0",
4
4
  "description": "Opinionated set of fastify plugins, commonly used in Lokalise",
5
5
  "author": {
6
6
  "name": "Lokalise",
@@ -59,7 +59,7 @@
59
59
  "@amplitude/analytics-types": "^2.8.4",
60
60
  "@biomejs/biome": "^1.9.4",
61
61
  "@lokalise/backend-http-client": "^3.0.0",
62
- "@lokalise/background-jobs-common": "^9.0.3",
62
+ "@lokalise/background-jobs-common": "^10.0.1",
63
63
  "@lokalise/biome-config": "^1.5.0",
64
64
  "@lokalise/node-core": "^13.3.0",
65
65
  "@types/newrelic": "^9.14.6",
@@ -70,7 +70,7 @@
70
70
  "fastify": "^5.2.0",
71
71
  "fastify-type-provider-zod": "^4.0.2",
72
72
  "ioredis": "^5.4.1",
73
- "newrelic": "12.8.2",
73
+ "newrelic": "12.13.0",
74
74
  "pino": "^9.5.0",
75
75
  "pino-pretty": "^13.0.0",
76
76
  "shx": "^0.3.4",