@lokalise/fastify-extras 16.3.1 → 16.5.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
@@ -2,62 +2,65 @@
2
2
 
3
3
  Reusable plugins for Fastify.
4
4
 
5
- * [Dependency Management](#dependency-management)
6
- * [Plugins](#plugins)
7
-
8
- * [RequestContext Provider Plugin](#requestcontext-provider-plugin)
9
- * [Public Healthcheck Plugin](#public-healthcheck-plugin)
10
- * [Split IO Plugin](#split-io-plugin)
11
- * [BugSnag Plugin](#bugsnag-plugin)
12
- * [Metrics Plugin](#metrics-plugin)
13
- * [NewRelic Transaction Manager Plugin](#newrelic-transaction-manager-plugin)
14
- * [UnhandledException Plugin](#unhandledexception-plugin)
5
+ - [Dependency Management](#dependency-management)
6
+ - [Plugins](#plugins)
7
+
8
+ - [RequestContext Provider Plugin](#requestcontext-provider-plugin)
9
+ - [Public Healthcheck Plugin](#public-healthcheck-plugin)
10
+ - [Split IO Plugin](#split-io-plugin)
11
+ - [BugSnag Plugin](#bugsnag-plugin)
12
+ - [Metrics Plugin](#metrics-plugin)
13
+ - [NewRelic Transaction Manager Plugin](#newrelic-transaction-manager-plugin)
14
+ - [UnhandledException Plugin](#unhandledexception-plugin)
15
15
 
16
16
  ## Dependency Management
17
17
 
18
18
  The following needs to be taken into consideration when adding new runtime dependency for the `fastify-extras` package:
19
19
 
20
- * If dependency is an implementation detail, and end consumer is not expected to import and use the dependency directly, it should be a `dependency`;
21
- * If dependency needs to be imported and used by consumer directly for it to function properly, it should be a `peerDependency`.
20
+ - If dependency is an implementation detail, and end consumer is not expected to import and use the dependency directly, it should be a `dependency`;
21
+ - If dependency needs to be imported and used by consumer directly for it to function properly, it should be a `peerDependency`.
22
22
 
23
23
  ### Dependencies
24
24
 
25
- * `@bugsnag/js`;
26
- * `@opentelemetry/api`;
27
- * `@opentelemetry/exporter-trace-otlp-grpc`;
28
- * `@opentelemetry/instrumentation`;
29
- * `@opentelemetry/resources`;
30
- * `@opentelemetry/sdk-trace-base`;
31
- * `@opentelemetry/sdk-trace-node`;
32
- * `@opentelemetry/semantic-conventions`;
33
- * `@prisma/instrumentation`;
34
- * `@splitsoftware/splitio`;
35
- * `fastify-metrics`;
36
- * `fastify-plugin`;
37
- * `tslib`.
25
+ - `@bugsnag/js`;
26
+ - `@opentelemetry/api`;
27
+ - `@opentelemetry/exporter-trace-otlp-grpc`;
28
+ - `@opentelemetry/instrumentation`;
29
+ - `@opentelemetry/resources`;
30
+ - `@opentelemetry/sdk-trace-base`;
31
+ - `@opentelemetry/sdk-trace-node`;
32
+ - `@opentelemetry/semantic-conventions`;
33
+ - `@prisma/instrumentation`;
34
+ - `@splitsoftware/splitio`;
35
+ - `fastify-metrics`;
36
+ - `fastify-plugin`;
37
+ - `tslib`.
38
38
 
39
39
  ### Peer Dependencies
40
40
 
41
- * `@fastify/request-context`;
42
- * `fastify`;
43
- * `newrelic`;
44
- * `pino`.
41
+ - `@fastify/request-context`;
42
+ - `@fastify/jwt`;
43
+ - `fastify`;
44
+ - `newrelic`;
45
+ - `pino`.
45
46
 
46
47
  ## Plugins
47
48
 
48
49
  ### RequestContext Provider Plugin
49
50
 
50
51
  Plugin to:
51
- * extend existing `FastifyRequest` with request context by setting the following:
52
- * `logger`, an instance of `FastifyBaseLogger`;
53
- * `reqId`, the request-id;
54
- * store the request-id in Asynchronous Local Storage to be picked up by instrumentation tooling (e. g. OpenTelemetry).
52
+
53
+ - extend existing `FastifyRequest` with request context by setting the following:
54
+ - `logger`, an instance of `FastifyBaseLogger`;
55
+ - `reqId`, the request-id;
56
+ - store the request-id in Asynchronous Local Storage to be picked up by instrumentation tooling (e. g. OpenTelemetry).
55
57
 
56
58
  No options are required to register the plugin.
57
59
 
58
60
  The `getRequestIdFastifyAppConfig()` method is exported and returns:
59
- * `genReqId`, a function for generating the request-id;
60
- * `requestIdHeader`, the header name used to set the request-id.
61
+
62
+ - `genReqId`, a function for generating the request-id;
63
+ - `requestIdHeader`, the header name used to set the request-id.
61
64
 
62
65
  Which can be passed to Fastify during instantiation.
63
66
 
@@ -66,10 +69,11 @@ Which can be passed to Fastify during instantiation.
66
69
  Plugin to monitor app status through public healthcheck.
67
70
 
68
71
  Add the plugin to your Fastify instance by registering it with the following options:
69
- * `healthChecks`, a list of promises with healthcheck in the callback;
70
- * `responsePayload` (optional), the response payload that the public healthcheck should return. If no response payload is provided, the default response is:
72
+
73
+ - `healthChecks`, a list of promises with healthcheck in the callback;
74
+ - `responsePayload` (optional), the response payload that the public healthcheck should return. If no response payload is provided, the default response is:
71
75
  ```json
72
- {"heartbeat": "HEALTHY"}
76
+ { "heartbeat": "HEALTHY" }
73
77
  ```
74
78
 
75
79
  Your Fastify app will reply with the status of the app when hitting the `GET /` route.
@@ -79,35 +83,38 @@ Your Fastify app will reply with the status of the app when hitting the `GET /`
79
83
  Plugin to handle feature flags in Split IO.
80
84
 
81
85
  Add the plugin to your Fastify instance by registering it with the following options:
82
- * `isEnabled`, if `true` the plugin will connect to [Split IO](https://split.io) using the provided `apiKey` and store data in memory with background syncing;
83
- * `apiKey`, your SDK key;
84
- * `debugMode`;
85
- * `localhostFilePath` (optional), used to utilize the SDK in [localhost mode](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode). It corresponds to the full path to a file with the mapping of feature flag name to treatment. `apiKey` will be automatically replaced with `localhost` if `localhostFilePath` is provided.
86
+
87
+ - `isEnabled`, if `true` the plugin will connect to [Split IO](https://split.io) using the provided `apiKey` and store data in memory with background syncing;
88
+ - `apiKey`, your SDK key;
89
+ - `debugMode`;
90
+ - `localhostFilePath` (optional), used to utilize the SDK in [localhost mode](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK#localhost-mode). It corresponds to the full path to a file with the mapping of feature flag name to treatment. `apiKey` will be automatically replaced with `localhost` if `localhostFilePath` is provided.
86
91
 
87
92
  The plugin decorates your Fastify instance with a `SplitIOFeatureManager`, which you can inject and use to leverage the following methods:
88
93
 
89
- * `init()`, returns a promise that resolves once the SDK has finished loading. It's called automatically when registering the plugin;
90
- * `getTreatment()`, returns the proper treatment based on the feature flag name and the key in input. Expected parameters are:
91
- * `key`, the ID of the user/account/etc. you're trying to evaluate a treatment for;
92
- * `splitName`, the Split IO feature flag name;
93
- * `attributes` (optional), a set of [Attributes](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax) used in evaluation to further decide whether to show the on or off treatment;
94
+ - `init()`, returns a promise that resolves once the SDK has finished loading. It's called automatically when registering the plugin;
95
+ - `getTreatment()`, returns the proper treatment based on the feature flag name and the key in input. Expected parameters are:
96
+
97
+ - `key`, the ID of the user/account/etc. you're trying to evaluate a treatment for;
98
+ - `splitName`, the Split IO feature flag name;
99
+ - `attributes` (optional), a set of [Attributes](https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#attribute-syntax) used in evaluation to further decide whether to show the on or off treatment;
94
100
 
95
101
  > **_NOTE:_** If `isEnabled` is false, `getTreatement()` will return `control` to signal disabled treatment.
96
- * `getTreatmentWithConfig()`, used to leverage [dynamic configurations with your treatment](https://help.split.io/hc/en-us/articles/360026943552). It accepts the same parameters as `getTreatment()`, but the response structure is as follows:
102
+
103
+ - `getTreatmentWithConfig()`, used to leverage [dynamic configurations with your treatment](https://help.split.io/hc/en-us/articles/360026943552). It accepts the same parameters as `getTreatment()`, but the response structure is as follows:
97
104
  ```ts
98
105
  type TreatmentResult = {
99
- treatment: string,
106
+ treatment: string
100
107
  config: string | null
101
- };
108
+ }
102
109
  ```
103
110
  > **_NOTE:_** If `isEnabled` is false, `getTreatementWithConfig()` will return `control` as `treatment` and `null` as `config` to signal disabled treatment.
104
- * `track()`, used to record any actions your customers perform. Returns a boolean to indicate whether or not the SDK was able to successfully queue the event. Expected parameters are:
105
- * `key`, the ID of the user/account/etc. you're trying to evaluate a treatment for;
106
- * `trafficType`, the [traffic type](https://help.split.io/hc/en-us/articles/360019916311-Traffic-type) of the key;
107
- * `eventType`, the event type that this event should correspond to;
108
- * `value` (optional), the value to be used in creating the metric;
109
- * `properties`(optional), an object of key value pairs that represent the [properties](https://help.split.io/hc/en-us/articles/360027333612-Event-property-capture-) to be used to filter your metrics;
110
- * `shutdown()`, gracefully shuts down the client.
111
+ - `track()`, used to record any actions your customers perform. Returns a boolean to indicate whether or not the SDK was able to successfully queue the event. Expected parameters are:
112
+ - `key`, the ID of the user/account/etc. you're trying to evaluate a treatment for;
113
+ - `trafficType`, the [traffic type](https://help.split.io/hc/en-us/articles/360019916311-Traffic-type) of the key;
114
+ - `eventType`, the event type that this event should correspond to;
115
+ - `value` (optional), the value to be used in creating the metric;
116
+ - `properties`(optional), an object of key value pairs that represent the [properties](https://help.split.io/hc/en-us/articles/360027333612-Event-property-capture-) to be used to filter your metrics;
117
+ - `shutdown()`, gracefully shuts down the client.
111
118
 
112
119
  More info about Split IO can be checked [here](https://help.split.io/hc/en-us/articles/360020564931-Node-js-SDK).
113
120
 
@@ -116,8 +123,9 @@ More info about Split IO can be checked [here](https://help.split.io/hc/en-us/ar
116
123
  Plugin to report errors to BugSnag.
117
124
 
118
125
  Add the plugin to your Fastify instance by registering it with the following options:
119
- * `isEnabled`;
120
- * `bugsnag`, a set of customizable [xonfiguration options](https://docs.bugsnag.com/platforms/javascript/configuration-options/).
126
+
127
+ - `isEnabled`;
128
+ - `bugsnag`, a set of customizable [xonfiguration options](https://docs.bugsnag.com/platforms/javascript/configuration-options/).
121
129
 
122
130
  Once the plugin has been added to your Fastify instance and loaded, errors will be reported to BugSnag.
123
131
 
@@ -126,10 +134,11 @@ Once the plugin has been added to your Fastify instance and loaded, errors will
126
134
  Plugin to expose Prometheus metrics.
127
135
 
128
136
  Add the plugin to your Fastify instance by registering it with the following options:
129
- * `loggerOptions`, used to configure the internal logger instance. It can be a boolean or a set of [Pino options](https://getpino.io/#/docs/api?id=options). By default it is set to `false` and the logger is disabled;
130
- * `disablePrometheusRequestLogging` (optional). By default Fastify will issue an `info` level log message when a request is received and when the response for that request has been sent. By setting this option to `true`, these log messages will be disabled. Defaults to `true`;
131
- * `bindAddress` (optional). By default, the server will listen on the address(es) resolved by localhost when no specific host is provided. See the possible values for host when targeting localhost [here](https://fastify.dev/docs/latest/Reference/Server#listen);
132
- * `errorObjectResolver`, a resolver method that, given an `err` and optionally a `correlationID`, it will log the error if something goes wrong.
137
+
138
+ - `loggerOptions`, used to configure the internal logger instance. It can be a boolean or a set of [Pino options](https://getpino.io/#/docs/api?id=options). By default it is set to `false` and the logger is disabled;
139
+ - `disablePrometheusRequestLogging` (optional). By default Fastify will issue an `info` level log message when a request is received and when the response for that request has been sent. By setting this option to `true`, these log messages will be disabled. Defaults to `true`;
140
+ - `bindAddress` (optional). By default, the server will listen on the address(es) resolved by localhost when no specific host is provided. See the possible values for host when targeting localhost [here](https://fastify.dev/docs/latest/Reference/Server#listen);
141
+ - `errorObjectResolver`, a resolver method that, given an `err` and optionally a `correlationID`, it will log the error if something goes wrong.
133
142
 
134
143
  The plugin exposes a `GET /metrics` route in your Fastify app to retrieve Prometheus metrics. If something goes wrong while starting the Prometheus metrics server, an `Error` is thrown. Otherwise, a success message is displayed when the plugin has been loaded.
135
144
 
@@ -138,27 +147,31 @@ The plugin exposes a `GET /metrics` route in your Fastify app to retrieve Promet
138
147
  Plugin to create custom NewRelic spans for background jobs.
139
148
 
140
149
  Add the plugin to your Fastify instance by registering it with the following options:
141
- * `isEnabled`.
150
+
151
+ - `isEnabled`.
142
152
 
143
153
  The plugin decorates your Fastify instance with a `NewRelicTransactionManager`, which you can inject and use to leverage the following methods:
144
- * `start()`, which takes a `jobName`, and starts a background transaction with the provided name;
145
- * `stop()`, which takes a `jobId`, and ends the background transaction referenced by the ID;
146
- * `addCustomAttribute()`, which takes `attrName` and `attrValue` and records the custom attribute as such defined. `attrValue` can be a string, a number, or a boolean.
154
+
155
+ - `start()`, which takes a `jobName`, and starts a background transaction with the provided name;
156
+ - `stop()`, which takes a `jobId`, and ends the background transaction referenced by the ID;
157
+ - `addCustomAttribute()`, which takes `attrName` and `attrValue` and records the custom attribute as such defined. `attrValue` can be a string, a number, or a boolean.
147
158
 
148
159
  ### Amplitude Plugin
149
160
 
150
161
  This plugin facilitates the transmission of events to Amplitude.
151
162
 
152
163
  To add this plugin to your Fastify instance, register it with the following configurations:
153
- * `isEnabled`: A flag utilized to activate or de-activate the plugin.
154
- * `apiKey` (optional): This refers to the Amplitude API key which can be procured from your respective Amplitude project.
155
- * `options` (optional): To configure Amplitude, please refer to [this documentation](https://amplitude.github.io/Amplitude-TypeScript/modules/_amplitude_analytics_node.Types.html#NodeOptions).
156
- * `apiUsageTracking` (optional): You can use this callback to generate an event that will automatically be sent for tracking API usage. Non-specification of this feature will lead to disabling of API tracking.
157
- * `plugins` (optional): This feature allows you to expand the plugin's functionality, from altering event properties to relaying to third-party APIs. To learn more, visit [this link](https://www.docs.developers.amplitude.com/data/sdks/typescript-node/#plugins).
164
+
165
+ - `isEnabled`: A flag utilized to activate or de-activate the plugin.
166
+ - `apiKey` (optional): This refers to the Amplitude API key which can be procured from your respective Amplitude project.
167
+ - `options` (optional): To configure Amplitude, please refer to [this documentation](https://amplitude.github.io/Amplitude-TypeScript/modules/_amplitude_analytics_node.Types.html#NodeOptions).
168
+ - `apiUsageTracking` (optional): You can use this callback to generate an event that will automatically be sent for tracking API usage. Non-specification of this feature will lead to disabling of API tracking.
169
+ - `plugins` (optional): This feature allows you to expand the plugin's functionality, from altering event properties to relaying to third-party APIs. To learn more, visit [this link](https://www.docs.developers.amplitude.com/data/sdks/typescript-node/#plugins).
158
170
 
159
171
  The plugin decorates your Fastify instance with a `Amplitude`, which you can inject and use the `track` method on it to send events whenever you need
160
172
 
161
173
  > 📘 To ensure optimal functionality with this plugin, you may need to incorporate Amplitude types into your development dependencies.
174
+ >
162
175
  > ```
163
176
  > "@amplitude/analytics-types": "*"
164
177
  > ```
@@ -174,8 +187,8 @@ To integrate this plugin into your Fastify instance, follow these steps:
174
187
  1. First, import the necessary types and the plugin:
175
188
 
176
189
  ```typescript
177
- import { FastifyInstance } from 'fastify';
178
- import { unhandledExceptionPlugin, ErrorObjectResolver } from '@lokalise/fastify-extras';
190
+ import { FastifyInstance } from 'fastify'
191
+ import { unhandledExceptionPlugin, ErrorObjectResolver } from '@lokalise/fastify-extras'
179
192
  ```
180
193
 
181
194
  2. Configure the plugin:
@@ -186,28 +199,28 @@ Define your own `ErrorObjectResolver` to dictate how the uncaught exceptions wil
186
199
  const myErrorResolver: ErrorObjectResolver = (err, correlationID) => {
187
200
  return {
188
201
  error: err,
189
- id: correlationID
190
- };
191
- };
202
+ id: correlationID,
203
+ }
204
+ }
192
205
  ```
193
206
 
194
207
  You'll also need to provide an `ErrorReporter` instance. This instance should have a `report` method to handle the error reporting logic. For example:
195
208
 
196
209
  ```typescript
197
- import { ErrorReporter } from "@lokalise/node-core";
210
+ import { ErrorReporter } from '@lokalise/node-core'
198
211
 
199
- const myErrorReporter = new ErrorReporter(/* initialization params */);
212
+ const myErrorReporter = new ErrorReporter(/* initialization params */)
200
213
  ```
201
214
 
202
215
  3. Register the plugin with your Fastify instance:
203
216
 
204
217
  ```typescript
205
- const fastify = Fastify();
218
+ const fastify = Fastify()
206
219
 
207
220
  fastify.register(unhandledExceptionPlugin, {
208
221
  errorObjectResolver: myErrorResolver,
209
- errorReporter: myErrorReporter
210
- });
222
+ errorReporter: myErrorReporter,
223
+ })
211
224
  ```
212
225
 
213
226
  #### Options
@@ -236,4 +249,4 @@ When an uncaught exception occurs, the plugin:
236
249
 
237
250
  - `fastify`: The framework this plugin is designed for.
238
251
 
239
- > 🚨 It's critical to note that this plugin listens to the process's 'uncaughtException' event. Multiple listeners on this event can introduce unpredictable behavior in your application. Ensure that this is the sole listener for this event or handle interactions between multiple listeners carefully.
252
+ > 🚨 It's critical to note that this plugin listens to the process's 'uncaughtException' event. Multiple listeners on this event can introduce unpredictable behavior in your application. Ensure that this is the sole listener for this event or handle interactions between multiple listeners carefully.
@@ -1,5 +1,6 @@
1
1
  import type { ErrorReporter } from '@lokalise/node-core';
2
2
  import type { FastifyRequest, FastifyReply, FastifyInstance } from 'fastify';
3
+ import type { ZodError } from 'zod';
3
4
  export type FreeformRecord = Record<string, any>;
4
5
  type ErrorResponseObject = {
5
6
  statusCode: number;
@@ -9,6 +10,7 @@ type ErrorResponseObject = {
9
10
  details?: FreeformRecord;
10
11
  };
11
12
  };
13
+ export declare function isZodError(value: unknown): value is ZodError;
12
14
  export type ErrorHandlerParams = {
13
15
  errorReporter: ErrorReporter;
14
16
  resolveResponseObject?: (error: FreeformRecord) => ErrorResponseObject | undefined;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createErrorHandler = void 0;
3
+ exports.createErrorHandler = exports.isZodError = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const node_core_1 = require("@lokalise/node-core");
6
6
  const pino_1 = tslib_1.__importDefault(require("pino"));
@@ -12,6 +12,7 @@ const knownAuthErrors = new Set([
12
12
  function isZodError(value) {
13
13
  return value.name === 'ZodError';
14
14
  }
15
+ exports.isZodError = isZodError;
15
16
  function resolveLogObject(error) {
16
17
  if ((0, node_core_1.isInternalError)(error)) {
17
18
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../lib/errors/errorHandler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errorHandler.js","sourceRoot":"","sources":["../../lib/errors/errorHandler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { OptionalMessageErrorParams } from '@lokalise/node-core';
2
+ import { PublicNonRecoverableError } from '@lokalise/node-core';
3
+ export declare class EmptyTokenError extends PublicNonRecoverableError {
4
+ constructor(params?: OptionalMessageErrorParams);
5
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EmptyTokenError = void 0;
4
+ const node_core_1 = require("@lokalise/node-core");
5
+ class EmptyTokenError extends node_core_1.PublicNonRecoverableError {
6
+ constructor(params = {}) {
7
+ super({
8
+ message: params.message ?? 'Empty token',
9
+ errorCode: 'EMPTY_TOKEN',
10
+ httpStatusCode: 401,
11
+ details: params.details,
12
+ });
13
+ }
14
+ }
15
+ exports.EmptyTokenError = EmptyTokenError;
16
+ //# sourceMappingURL=publicErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publicErrors.js","sourceRoot":"","sources":["../../lib/errors/publicErrors.ts"],"names":[],"mappings":";;;AACA,mDAA+D;AAE/D,MAAa,eAAgB,SAAQ,qCAAyB;IAC5D,YAAY,SAAqC,EAAE;QACjD,KAAK,CAAC;YACJ,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,aAAa;YACxC,SAAS,EAAE,aAAa;YACxB,cAAc,EAAE,GAAG;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAA;IACJ,CAAC;CACF;AATD,0CASC"}
package/dist/index.d.ts CHANGED
@@ -20,5 +20,6 @@ export { amplitudePlugin, Amplitude, type AmplitudeConfig, type CreateApiTrackin
20
20
  export type { FastifyReplyWithPayload } from './types';
21
21
  export { unhandledExceptionPlugin } from './plugins/unhandledExceptionPlugin';
22
22
  export type { UnhandledExceptionPluginOptions } from './plugins/unhandledExceptionPlugin';
23
- export { createErrorHandler } from './errors/errorHandler';
23
+ export { createErrorHandler, isZodError } from './errors/errorHandler';
24
24
  export type { ErrorHandlerParams, FreeformRecord } from './errors/errorHandler';
25
+ export { generateJwtToken, decodeJwtToken } from './jwt-utils/tokenUtils';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createErrorHandler = exports.unhandledExceptionPlugin = exports.Amplitude = exports.amplitudePlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.prismaOtelTracingPlugin = exports.metricsPlugin = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.REQUEST_ID_STORE_KEY = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = exports.bugsnagErrorReporter = exports.reportErrorToBugsnag = exports.bugsnagPlugin = void 0;
3
+ exports.decodeJwtToken = exports.generateJwtToken = exports.isZodError = exports.createErrorHandler = exports.unhandledExceptionPlugin = exports.Amplitude = exports.amplitudePlugin = exports.wrapHealthCheck = exports.publicHealthcheckPlugin = exports.prismaOtelTracingPlugin = exports.metricsPlugin = exports.wrapHealthCheckForPrometheus = exports.healthcheckMetricsPlugin = exports.SplitIOFeatureManager = exports.splitIOFeatureManagerPlugin = exports.NewRelicTransactionManager = exports.newrelicTransactionManagerPlugin = exports.REQUEST_ID_STORE_KEY = exports.getRequestIdFastifyAppConfig = exports.requestContextProviderPlugin = 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; } });
@@ -33,4 +33,8 @@ var unhandledExceptionPlugin_1 = require("./plugins/unhandledExceptionPlugin");
33
33
  Object.defineProperty(exports, "unhandledExceptionPlugin", { enumerable: true, get: function () { return unhandledExceptionPlugin_1.unhandledExceptionPlugin; } });
34
34
  var errorHandler_1 = require("./errors/errorHandler");
35
35
  Object.defineProperty(exports, "createErrorHandler", { enumerable: true, get: function () { return errorHandler_1.createErrorHandler; } });
36
+ Object.defineProperty(exports, "isZodError", { enumerable: true, get: function () { return errorHandler_1.isZodError; } });
37
+ var tokenUtils_1 = require("./jwt-utils/tokenUtils");
38
+ Object.defineProperty(exports, "generateJwtToken", { enumerable: true, get: function () { return tokenUtils_1.generateJwtToken; } });
39
+ Object.defineProperty(exports, "decodeJwtToken", { enumerable: true, get: function () { return tokenUtils_1.decodeJwtToken; } });
36
40
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAAmG;AAA1F,8GAAA,aAAa,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAGlE,uFAI+C;AAH7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAC5B,oIAAA,oBAAoB,OAAA;AAItB,+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,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAOhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,6DAKkC;AAJhC,kHAAA,eAAe,OAAA;AACf,4GAAA,SAAS,OAAA;AAOX,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAGjC,sDAA0D;AAAjD,kHAAA,kBAAkB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":";;;AAAA,yDAAmG;AAA1F,8GAAA,aAAa,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAAE,qHAAA,oBAAoB,OAAA;AAGlE,uFAI+C;AAH7C,4IAAA,4BAA4B,OAAA;AAC5B,4IAAA,4BAA4B,OAAA;AAC5B,oIAAA,oBAAoB,OAAA;AAItB,+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,yDAAuD;AAA9C,8GAAA,aAAa,OAAA;AAGtB,2FAAyF;AAAhF,kIAAA,uBAAuB,OAAA;AAGhC,yFAAuF;AAA9E,kIAAA,uBAAuB,OAAA;AAOhC,+EAA0E;AAAjE,qHAAA,eAAe,OAAA;AAGxB,6DAKkC;AAJhC,kHAAA,eAAe,OAAA;AACf,4GAAA,SAAS,OAAA;AAOX,+EAA6E;AAApE,oIAAA,wBAAwB,OAAA;AAGjC,sDAAsE;AAA7D,kHAAA,kBAAkB,OAAA;AAAE,0GAAA,UAAU,OAAA;AAGvC,qDAAyE;AAAhE,8GAAA,gBAAgB,OAAA;AAAE,4GAAA,cAAc,OAAA"}
@@ -0,0 +1,3 @@
1
+ import type { JWT } from '@fastify/jwt';
2
+ export declare function generateJwtToken(jwt: JWT, payload: Record<string, unknown>, ttlInSeconds: number): Promise<string>;
3
+ export declare function decodeJwtToken(jwt: JWT, encodedToken: string): Promise<any>;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeJwtToken = exports.generateJwtToken = void 0;
4
+ const node_core_1 = require("@lokalise/node-core");
5
+ const publicErrors_1 = require("../errors/publicErrors");
6
+ function generateJwtToken(jwt, payload, ttlInSeconds) {
7
+ return new Promise((resolve, reject) => {
8
+ jwt.sign(payload, { expiresIn: ttlInSeconds }, (err, encoded) => {
9
+ /* v8 ignore next 3 */
10
+ if (err) {
11
+ return reject(err);
12
+ }
13
+ /* v8 ignore next 3 */
14
+ if (!encoded) {
15
+ throw new publicErrors_1.EmptyTokenError();
16
+ }
17
+ resolve(encoded);
18
+ });
19
+ });
20
+ }
21
+ exports.generateJwtToken = generateJwtToken;
22
+ const hasCode = (error) => typeof error === 'object' && error !== null && 'code' in error;
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ function decodeJwtToken(jwt, encodedToken) {
25
+ return new Promise((resolve, reject) => {
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ jwt.verify(encodedToken, (err, decoded) => {
28
+ /* v8 ignore next 3 */
29
+ if (err) {
30
+ return reject(err);
31
+ }
32
+ /* v8 ignore next 3 */
33
+ if (!decoded) {
34
+ throw new publicErrors_1.EmptyTokenError();
35
+ }
36
+ resolve(decoded);
37
+ });
38
+ }).catch((err) => {
39
+ if (hasCode(err) && err.code === 'FAST_JWT_INVALID_SIGNATURE') {
40
+ throw new node_core_1.AuthFailedError({ message: 'Auth error' });
41
+ }
42
+ throw err;
43
+ });
44
+ }
45
+ exports.decodeJwtToken = decodeJwtToken;
46
+ //# sourceMappingURL=tokenUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenUtils.js","sourceRoot":"","sources":["../../lib/jwt-utils/tokenUtils.ts"],"names":[],"mappings":";;;AACA,mDAAqD;AAErD,yDAAwD;AAExD,SAAgB,gBAAgB,CAC9B,GAAQ,EACR,OAAgC,EAChC,YAAoB;IAEpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;YAC9D,sBAAsB;YACtB,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;YACpB,CAAC;YACD,sBAAsB;YACtB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,8BAAe,EAAE,CAAA;YAC7B,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAlBD,4CAkBC;AAED,MAAM,OAAO,GAAG,CAAC,KAAc,EAA8B,EAAE,CAC7D,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,CAAA;AAEhE,8DAA8D;AAC9D,SAAgB,cAAc,CAAC,GAAQ,EAAE,YAAoB;IAC3D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,8DAA8D;QAC9D,GAAG,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,GAAiB,EAAE,OAAY,EAAE,EAAE;YAC3D,sBAAsB;YACtB,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;YACpB,CAAC;YACD,sBAAsB;YACtB,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,8BAAe,EAAE,CAAA;YAC7B,CAAC;YACD,OAAO,CAAC,OAAO,CAAC,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACf,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,4BAA4B,EAAE,CAAC;YAC9D,MAAM,IAAI,2BAAe,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAA;QACtD,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC,CAAC,CAAA;AACJ,CAAC;AApBD,wCAoBC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const jwt_1 = tslib_1.__importDefault(require("@fastify/jwt"));
5
+ const fastify_1 = tslib_1.__importDefault(require("fastify"));
6
+ const ACCESS_TOKEN_TTL_IN_SECONDS = 60;
7
+ const tokenUtils_1 = require("./tokenUtils");
8
+ describe('tokenUtils', () => {
9
+ describe('generateJwtToken', () => {
10
+ it('successfully generate jwt token', async () => {
11
+ const app = (0, fastify_1.default)();
12
+ void app.register(jwt_1.default, {
13
+ secret: 'secret',
14
+ });
15
+ await app.ready();
16
+ const payload = {
17
+ userId: 1,
18
+ };
19
+ const token = await (0, tokenUtils_1.generateJwtToken)(app.jwt, payload, ACCESS_TOKEN_TTL_IN_SECONDS);
20
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
21
+ const decodedToken = await (0, tokenUtils_1.decodeJwtToken)(app.jwt, token);
22
+ expect(decodedToken).toMatchObject({
23
+ userId: 1,
24
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
25
+ exp: expect.any(Number),
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
27
+ iat: expect.any(Number),
28
+ });
29
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
30
+ expect(decodedToken.exp - decodedToken.iat).toEqual(ACCESS_TOKEN_TTL_IN_SECONDS);
31
+ await app.close();
32
+ });
33
+ it('unsuccessfully decrypt jwt token', async () => {
34
+ const app = (0, fastify_1.default)();
35
+ void app.register(jwt_1.default, {
36
+ secret: 'secret',
37
+ });
38
+ await app.ready();
39
+ const app2 = (0, fastify_1.default)();
40
+ void app2.register(jwt_1.default, {
41
+ secret: 'secret2',
42
+ });
43
+ await app2.ready();
44
+ const payload = {
45
+ userId: 1,
46
+ };
47
+ const token = await (0, tokenUtils_1.generateJwtToken)(app.jwt, payload, ACCESS_TOKEN_TTL_IN_SECONDS);
48
+ await expect(() => {
49
+ return (0, tokenUtils_1.decodeJwtToken)(app2.jwt, token);
50
+ }).rejects.toThrow('Auth error');
51
+ await app.close();
52
+ await app2.close();
53
+ });
54
+ it('throws error on empty token', async () => {
55
+ const app = (0, fastify_1.default)();
56
+ void app.register(jwt_1.default, {
57
+ secret: 'secret',
58
+ });
59
+ await app.ready();
60
+ await expect(() => {
61
+ return (0, tokenUtils_1.decodeJwtToken)(app.jwt, '');
62
+ }).rejects.toThrow('missing token');
63
+ await app.close();
64
+ });
65
+ });
66
+ });
67
+ //# sourceMappingURL=tokenUtils.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenUtils.spec.js","sourceRoot":"","sources":["../../lib/jwt-utils/tokenUtils.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lokalise/fastify-extras",
3
- "version": "16.3.1",
3
+ "version": "16.5.0",
4
4
  "description": "Opinionated set of fastify plugins, commonly used in Lokalise",
5
5
  "author": {
6
6
  "name": "Lokalise",
@@ -37,9 +37,8 @@
37
37
  "test": "vitest",
38
38
  "test:coverage": "vitest --coverage",
39
39
  "test:ci": "npm run lint && npm run test:coverage",
40
- "lint": "eslint .",
41
- "lint:fix": "eslint . --fix",
42
- "format": "prettier --write .",
40
+ "lint": "eslint . --ext .ts && prettier --check --log-level warn \"**/*.{json,md,ts}\"",
41
+ "lint:fix": "eslint . --fix && prettier --write --log-level warn \"**/*.{json,md,ts}\"",
43
42
  "version": "auto-changelog -p && git add CHANGELOG.md"
44
43
  },
45
44
  "dependencies": {
@@ -61,35 +60,34 @@
61
60
  "peerDependencies": {
62
61
  "@fastify/request-context": "^5.0.0",
63
62
  "fastify": "^4.24.3",
63
+ "@fastify/jwt": "^8.0.0",
64
64
  "newrelic": "^11.0.0",
65
65
  "pino": "^8.16.2",
66
66
  "zod": "^3.22.4"
67
67
  },
68
68
  "devDependencies": {
69
69
  "@fastify/request-context": "^5.0.0",
70
- "@lokalise/node-core": "^9.1.0",
70
+ "@lokalise/node-core": "^9.6.1",
71
71
  "@types/newrelic": "^9.14.3",
72
- "@types/node": "^20.10.1",
72
+ "@types/node": "^20.11.5",
73
73
  "@amplitude/analytics-types": "^2.3.1",
74
- "@typescript-eslint/eslint-plugin": "^6.13.1",
75
- "@typescript-eslint/parser": "^6.13.1",
76
- "@vitest/coverage-v8": "^0.34.6",
74
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
75
+ "@typescript-eslint/parser": "^6.19.0",
76
+ "@vitest/coverage-v8": "^1.2.1",
77
77
  "auto-changelog": "^2.4.0",
78
- "eslint": "^8.54.0",
79
- "eslint-config-prettier": "^9.0.0",
80
- "eslint-plugin-import": "^2.29.0",
81
- "eslint-plugin-vitest": "^0.3.10",
82
- "eslint-plugin-prettier": "^5.0.0",
83
- "fastify": "^4.24.3",
84
- "newrelic": "11.8.0",
85
- "pino": "^8.16.2",
86
- "pino-pretty": "^10.2.3",
87
- "prettier": "^3.1.0",
78
+ "eslint": "^8.56.0",
79
+ "eslint-config-prettier": "^9.1.0",
80
+ "eslint-plugin-import": "^2.29.1",
81
+ "eslint-plugin-vitest": "^0.3.20",
82
+ "fastify": "^4.25.2",
83
+ "newrelic": "11.10.1",
84
+ "pino": "^8.17.2",
85
+ "pino-pretty": "^10.3.1",
86
+ "prettier": "^3.2.4",
88
87
  "shx": "^0.3.4",
89
88
  "ts-node": "^10.9.1",
90
89
  "typescript": "^5.3.3",
91
- "vitest": "^0.34.6",
92
- "vite": "4.5.0",
90
+ "vitest": "^1.2.1",
93
91
  "zod": "^3.22.4"
94
92
  },
95
93
  "engines": {