@nestjs/platform-fastify 11.1.15 → 12.0.0-alpha.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.
@@ -1,14 +1,14 @@
1
1
  import { FastifyCorsOptions } from '@fastify/cors';
2
- import { Logger, RequestMethod, VersioningOptions } from '@nestjs/common';
3
- import { VersionValue } from '@nestjs/common/interfaces';
4
- import { AbstractHttpAdapter } from '@nestjs/core/adapters/http-adapter';
2
+ import { Logger, type RequestMethod, type VersioningOptions } from '@nestjs/common';
5
3
  import { FastifyBaseLogger, FastifyBodyParser, FastifyInstance, FastifyPluginAsync, FastifyPluginCallback, FastifyRegister, FastifyReply, FastifyRequest, FastifyServerOptions, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerBase, RawServerDefault, RequestGenericInterface, RouteGenericInterface } from 'fastify';
6
4
  import * as http from 'http';
7
5
  import * as http2 from 'http2';
8
6
  import * as https from 'https';
9
7
  import { InjectOptions, Chain as LightMyRequestChain, Response as LightMyRequestResponse } from 'light-my-request';
10
- import { NestFastifyBodyParserOptions } from '../interfaces';
11
- import { FastifyStaticOptions, FastifyViewOptions } from '../interfaces/external';
8
+ import { type VersionValue } from '@nestjs/common/internal';
9
+ import { AbstractHttpAdapter } from '@nestjs/core';
10
+ import { FastifyStaticOptions, FastifyViewOptions } from '../interfaces/external/index.js';
11
+ import { NestFastifyBodyParserOptions } from '../interfaces/index.js';
12
12
  type FastifyAdapterBaseOptions<Server extends RawServerBase = RawServerDefault, Logger extends FastifyBaseLogger = FastifyBaseLogger> = FastifyServerOptions<Server, Logger> & {
13
13
  skipMiddie?: boolean;
14
14
  };
@@ -81,7 +81,7 @@ export declare class FastifyAdapter<TServer extends RawServerBase = RawServerDef
81
81
  end(response: TReply, message?: string): void;
82
82
  render(response: TReply & {
83
83
  view: Function;
84
- }, view: string, options: any): any;
84
+ }, view: string, options: any): FastifyReply<RouteGenericInterface, RawServerDefault, http.IncomingMessage, http.ServerResponse<http.IncomingMessage>, unknown, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown>;
85
85
  redirect(response: TReply, statusCode: number, url: string): FastifyReply<RouteGenericInterface, TServer, TRawRequest, TRawResponse, unknown, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown>;
86
86
  setErrorHandler(handler: Parameters<TInstance['setErrorHandler']>[0]): FastifyInstance<TServer, TRawRequest, TRawResponse, FastifyBaseLogger, import("fastify").FastifyTypeProvider>;
87
87
  setNotFoundHandler(handler: Function): FastifyInstance<TServer, TRawRequest, TRawResponse, FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>;
@@ -92,8 +92,8 @@ export declare class FastifyAdapter<TServer extends RawServerBase = RawServerDef
92
92
  inject(opts: InjectOptions | string): Promise<LightMyRequestResponse>;
93
93
  close(): Promise<undefined>;
94
94
  initHttpServer(): void;
95
- useStaticAssets(options: FastifyStaticOptions): any;
96
- setViewEngine(options: FastifyViewOptions | string): any;
95
+ useStaticAssets(options: FastifyStaticOptions): Promise<any>;
96
+ setViewEngine(options: FastifyViewOptions | string): Promise<any>;
97
97
  isHeadersSent(response: TReply): boolean;
98
98
  getHeader(response: any, name: string): any;
99
99
  setHeader(response: TReply, name: string, value: string): FastifyReply<RouteGenericInterface, TServer, TRawRequest, TRawResponse, unknown, import("fastify").FastifySchema, import("fastify").FastifyTypeProviderDefault, unknown>;
@@ -108,6 +108,8 @@ export declare class FastifyAdapter<TServer extends RawServerBase = RawServerDef
108
108
  createMiddlewareFactory(requestMethod: RequestMethod): Promise<(path: string, callback: Function) => any>;
109
109
  getType(): string;
110
110
  use(...args: any[]): any;
111
+ mapException(error: unknown): unknown;
112
+ private isHttpFastifyError;
111
113
  protected registerWithPrefix(factory: FastifyPluginCallback<any> | FastifyPluginAsync<any> | Promise<{
112
114
  default: FastifyPluginCallback<any>;
113
115
  }> | Promise<{
@@ -121,8 +123,5 @@ export declare class FastifyAdapter<TServer extends RawServerBase = RawServerDef
121
123
  private registerMiddie;
122
124
  private getRequestOriginalUrl;
123
125
  private injectRouteOptions;
124
- private sanitizeUrl;
125
- private removeDuplicateSlashes;
126
- private trimLastSlash;
127
126
  }
128
127
  export {};
@@ -1,98 +1,102 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FastifyAdapter = void 0;
4
- const common_1 = require("@nestjs/common");
5
- const load_package_util_1 = require("@nestjs/common/utils/load-package.util");
6
- const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
7
- const http_adapter_1 = require("@nestjs/core/adapters/http-adapter");
8
- const legacy_route_converter_1 = require("@nestjs/core/router/legacy-route-converter");
9
- const fastify_1 = require("fastify");
10
- const Reply = require("fastify/lib/reply");
11
- const symbols_1 = require("fastify/lib/symbols");
12
- const path_to_regexp_1 = require("path-to-regexp");
1
+ import { HttpException, HttpStatus, Logger, StreamableFile, VERSION_NEUTRAL, VersioningType, } from '@nestjs/common';
2
+ import { fastify, } from 'fastify';
3
+ import * as Reply from 'fastify/lib/reply.js';
4
+ import fastifySymbols from 'fastify/lib/symbols.js';
5
+ import { pathToRegexp } from 'path-to-regexp';
6
+ import { loadPackage, isString, isUndefined, } from '@nestjs/common/internal';
7
+ import { AbstractHttpAdapter } from '@nestjs/core';
8
+ import { LegacyRouteConverter } from '@nestjs/core/internal';
9
+ const { kRouteContext } = fastifySymbols;
13
10
  // Fastify uses `fast-querystring` internally to quickly parse URL query strings.
14
- const fast_querystring_1 = require("fast-querystring");
15
- const url_sanitizer_1 = require("find-my-way/lib/url-sanitizer");
16
- const constants_1 = require("../constants");
17
- const fastify_middie_1 = require("./middie/fastify-middie");
11
+ import { parse as querystringParse } from 'fast-querystring';
12
+ import urlSanitizer from 'find-my-way/lib/url-sanitizer.js';
13
+ import { FASTIFY_ROUTE_CONFIG_METADATA, FASTIFY_ROUTE_CONSTRAINTS_METADATA, FASTIFY_ROUTE_SCHEMA_METADATA, } from '../constants.js';
14
+ import middie from './middie/fastify-middie.js';
15
+ const { safeDecodeURI } = urlSanitizer;
18
16
  /**
19
17
  * @publicApi
20
18
  */
21
- class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
19
+ export class FastifyAdapter extends AbstractHttpAdapter {
20
+ logger = new Logger(FastifyAdapter.name);
21
+ _pathPrefix;
22
+ _isParserRegistered;
23
+ onRequestHook;
24
+ onResponseHook;
25
+ isMiddieRegistered;
26
+ pendingMiddlewares = [];
27
+ versioningOptions;
28
+ versionConstraint = {
29
+ name: 'version',
30
+ validate(value) {
31
+ if (!isString(value) && !Array.isArray(value)) {
32
+ throw new Error('Version constraint should be a string or an array of strings.');
33
+ }
34
+ },
35
+ storage() {
36
+ const versions = new Map();
37
+ return {
38
+ get(version) {
39
+ if (Array.isArray(version)) {
40
+ return versions.get(version.find(v => versions.has(v))) || null;
41
+ }
42
+ return versions.get(version) || null;
43
+ },
44
+ set(versionOrVersions, store) {
45
+ const storeVersionConstraint = (version) => versions.set(version, store);
46
+ if (Array.isArray(versionOrVersions))
47
+ versionOrVersions.forEach(storeVersionConstraint);
48
+ else
49
+ storeVersionConstraint(versionOrVersions);
50
+ },
51
+ del(version) {
52
+ if (Array.isArray(version)) {
53
+ version.forEach(v => versions.delete(v));
54
+ }
55
+ else {
56
+ versions.delete(version);
57
+ }
58
+ },
59
+ empty() {
60
+ versions.clear();
61
+ },
62
+ };
63
+ },
64
+ deriveConstraint: (req) => {
65
+ // Media Type (Accept Header) Versioning Handler
66
+ if (this.versioningOptions?.type === VersioningType.MEDIA_TYPE) {
67
+ const MEDIA_TYPE_HEADER = 'Accept';
68
+ const acceptHeaderValue = (req.headers?.[MEDIA_TYPE_HEADER] || req.headers?.[MEDIA_TYPE_HEADER.toLowerCase()]);
69
+ const acceptHeaderVersionParameter = acceptHeaderValue
70
+ ? acceptHeaderValue.split(';')[1]
71
+ : '';
72
+ return isUndefined(acceptHeaderVersionParameter)
73
+ ? VERSION_NEUTRAL // No version was supplied
74
+ : acceptHeaderVersionParameter.split(this.versioningOptions.key)[1];
75
+ }
76
+ // Header Versioning Handler
77
+ else if (this.versioningOptions?.type === VersioningType.HEADER) {
78
+ const customHeaderVersionParameter = req.headers?.[this.versioningOptions.header] ||
79
+ req.headers?.[this.versioningOptions.header.toLowerCase()];
80
+ return isUndefined(customHeaderVersionParameter)
81
+ ? VERSION_NEUTRAL // No version was supplied
82
+ : customHeaderVersionParameter;
83
+ }
84
+ // Custom Versioning Handler
85
+ else if (this.versioningOptions?.type === VersioningType.CUSTOM) {
86
+ return this.versioningOptions.extractor(req);
87
+ }
88
+ return undefined;
89
+ },
90
+ mustMatchWhenDerived: false,
91
+ };
22
92
  get isParserRegistered() {
23
93
  return !!this._isParserRegistered;
24
94
  }
25
95
  constructor(instanceOrOptions) {
26
96
  super();
27
- this.logger = new common_1.Logger(FastifyAdapter.name);
28
- this.pendingMiddlewares = [];
29
- this.versionConstraint = {
30
- name: 'version',
31
- validate(value) {
32
- if (!(0, shared_utils_1.isString)(value) && !Array.isArray(value)) {
33
- throw new Error('Version constraint should be a string or an array of strings.');
34
- }
35
- },
36
- storage() {
37
- const versions = new Map();
38
- return {
39
- get(version) {
40
- if (Array.isArray(version)) {
41
- return versions.get(version.find(v => versions.has(v))) || null;
42
- }
43
- return versions.get(version) || null;
44
- },
45
- set(versionOrVersions, store) {
46
- const storeVersionConstraint = (version) => versions.set(version, store);
47
- if (Array.isArray(versionOrVersions))
48
- versionOrVersions.forEach(storeVersionConstraint);
49
- else
50
- storeVersionConstraint(versionOrVersions);
51
- },
52
- del(version) {
53
- if (Array.isArray(version)) {
54
- version.forEach(v => versions.delete(v));
55
- }
56
- else {
57
- versions.delete(version);
58
- }
59
- },
60
- empty() {
61
- versions.clear();
62
- },
63
- };
64
- },
65
- deriveConstraint: (req) => {
66
- // Media Type (Accept Header) Versioning Handler
67
- if (this.versioningOptions?.type === common_1.VersioningType.MEDIA_TYPE) {
68
- const MEDIA_TYPE_HEADER = 'Accept';
69
- const acceptHeaderValue = (req.headers?.[MEDIA_TYPE_HEADER] || req.headers?.[MEDIA_TYPE_HEADER.toLowerCase()]);
70
- const acceptHeaderVersionParameter = acceptHeaderValue
71
- ? acceptHeaderValue.split(';')[1]
72
- : '';
73
- return (0, shared_utils_1.isUndefined)(acceptHeaderVersionParameter)
74
- ? common_1.VERSION_NEUTRAL // No version was supplied
75
- : acceptHeaderVersionParameter.split(this.versioningOptions.key)[1];
76
- }
77
- // Header Versioning Handler
78
- else if (this.versioningOptions?.type === common_1.VersioningType.HEADER) {
79
- const customHeaderVersionParameter = req.headers?.[this.versioningOptions.header] ||
80
- req.headers?.[this.versioningOptions.header.toLowerCase()];
81
- return (0, shared_utils_1.isUndefined)(customHeaderVersionParameter)
82
- ? common_1.VERSION_NEUTRAL // No version was supplied
83
- : customHeaderVersionParameter;
84
- }
85
- // Custom Versioning Handler
86
- else if (this.versioningOptions?.type === common_1.VersioningType.CUSTOM) {
87
- return this.versioningOptions.extractor(req);
88
- }
89
- return undefined;
90
- },
91
- mustMatchWhenDerived: false,
92
- };
93
97
  const instance = instanceOrOptions && instanceOrOptions.server
94
98
  ? instanceOrOptions
95
- : (0, fastify_1.fastify)({
99
+ : fastify({
96
100
  ...instanceOrOptions,
97
101
  routerOptions: {
98
102
  ...instanceOrOptions?.routerOptions,
@@ -218,7 +222,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
218
222
  reply(response, body, statusCode) {
219
223
  const fastifyReply = this.isNativeResponse(response)
220
224
  ? new Reply(response, {
221
- [symbols_1.kRouteContext]: {
225
+ [kRouteContext]: {
222
226
  preSerialization: null,
223
227
  preValidation: [],
224
228
  preHandler: [],
@@ -230,7 +234,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
230
234
  if (statusCode) {
231
235
  fastifyReply.status(statusCode);
232
236
  }
233
- if (body instanceof common_1.StreamableFile) {
237
+ if (body instanceof StreamableFile) {
234
238
  const streamHeaders = body.getHeaders();
235
239
  if (fastifyReply.getHeader('Content-Type') === undefined &&
236
240
  streamHeaders.type !== undefined) {
@@ -248,8 +252,8 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
248
252
  }
249
253
  if (fastifyReply.getHeader('Content-Type') !== undefined &&
250
254
  fastifyReply.getHeader('Content-Type') !== 'application/json' &&
251
- body?.statusCode >= common_1.HttpStatus.BAD_REQUEST) {
252
- common_1.Logger.warn("Content-Type doesn't match Reply body, you might need a custom ExceptionFilter for non-JSON responses", FastifyAdapter.name);
255
+ body?.statusCode >= HttpStatus.BAD_REQUEST) {
256
+ Logger.warn("Content-Type doesn't match Reply body, you might need a custom ExceptionFilter for non-JSON responses", FastifyAdapter.name);
253
257
  fastifyReply.header('Content-Type', 'application/json');
254
258
  }
255
259
  return fastifyReply.send(body);
@@ -268,7 +272,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
268
272
  return response && response.view(view, options);
269
273
  }
270
274
  redirect(response, statusCode, url) {
271
- const code = statusCode ?? common_1.HttpStatus.FOUND;
275
+ const code = statusCode ?? HttpStatus.FOUND;
272
276
  return response.status(code).redirect(url);
273
277
  }
274
278
  setErrorHandler(handler) {
@@ -304,15 +308,15 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
304
308
  initHttpServer() {
305
309
  this.httpServer = this.instance.server;
306
310
  }
307
- useStaticAssets(options) {
308
- return this.register((0, load_package_util_1.loadPackage)('@fastify/static', 'FastifyAdapter.useStaticAssets()', () => require('@fastify/static')), options);
311
+ async useStaticAssets(options) {
312
+ return this.register(await loadPackage('@fastify/static', 'FastifyAdapter.useStaticAssets()', () => import('@fastify/static')), options);
309
313
  }
310
- setViewEngine(options) {
311
- if ((0, shared_utils_1.isString)(options)) {
312
- new common_1.Logger('FastifyAdapter').error("setViewEngine() doesn't support a string argument.");
314
+ async setViewEngine(options) {
315
+ if (isString(options)) {
316
+ new Logger('FastifyAdapter').error("setViewEngine() doesn't support a string argument.");
313
317
  process.exit(1);
314
318
  }
315
- return this.register((0, load_package_util_1.loadPackage)('@fastify/view', 'FastifyAdapter.setViewEngine()', () => require('@fastify/view')), options);
319
+ return this.register(await loadPackage('@fastify/view', 'FastifyAdapter.setViewEngine()', () => import('@fastify/view')), options);
316
320
  }
317
321
  isHeadersSent(response) {
318
322
  return response.sent;
@@ -336,7 +340,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
336
340
  return this.getRequestOriginalUrl(request.raw || request);
337
341
  }
338
342
  enableCors(options) {
339
- this.register(Promise.resolve().then(() => require('@fastify/cors')), options);
343
+ this.register(import('@fastify/cors'), options);
340
344
  }
341
345
  registerParserMiddleware(prefix, rawBody) {
342
346
  if (this._isParserRegistered) {
@@ -377,7 +381,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
377
381
  return (path, callback) => {
378
382
  const hasEndOfStringCharacter = path.endsWith('$');
379
383
  path = hasEndOfStringCharacter ? path.slice(0, -1) : path;
380
- let normalizedPath = legacy_route_converter_1.LegacyRouteConverter.tryConvert(path);
384
+ let normalizedPath = LegacyRouteConverter.tryConvert(path);
381
385
  // Fallback to "*path" to support plugins like GraphQL
382
386
  normalizedPath = normalizedPath === '/*path' ? '*path' : normalizedPath;
383
387
  // Normalize the path to support the prefix if it set in application
@@ -388,7 +392,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
388
392
  }
389
393
  }
390
394
  try {
391
- let { regexp: re } = (0, path_to_regexp_1.pathToRegexp)(normalizedPath);
395
+ let { regexp: re } = pathToRegexp(normalizedPath);
392
396
  re = hasEndOfStringCharacter
393
397
  ? new RegExp(re.source + '$', re.flags)
394
398
  : re;
@@ -399,7 +403,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
399
403
  let pathname = queryParamsIndex >= 0
400
404
  ? req.originalUrl.slice(0, queryParamsIndex)
401
405
  : req.originalUrl;
402
- pathname = this.sanitizeUrl(pathname);
406
+ pathname = safeDecodeURI(pathname).path;
403
407
  if (!re.exec(pathname + '/') && normalizedPath) {
404
408
  return next();
405
409
  }
@@ -408,7 +412,7 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
408
412
  }
409
413
  catch (e) {
410
414
  if (e instanceof TypeError) {
411
- legacy_route_converter_1.LegacyRouteConverter.printError(path);
415
+ LegacyRouteConverter.printError(path);
412
416
  }
413
417
  throw e;
414
418
  }
@@ -426,6 +430,18 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
426
430
  }
427
431
  return this.instance.use(...args);
428
432
  }
433
+ mapException(error) {
434
+ if (this.isHttpFastifyError(error)) {
435
+ return new HttpException(error.message, error.statusCode);
436
+ }
437
+ return error;
438
+ }
439
+ isHttpFastifyError(error) {
440
+ // condition based on this code - https://github.com/fastify/fastify-error/blob/d669b150a82968322f9f7be992b2f6b463272de3/index.js#L22
441
+ return (error.statusCode !== undefined &&
442
+ error instanceof Error &&
443
+ error.name === 'FastifyError');
444
+ }
429
445
  registerWithPrefix(factory, prefix = '/') {
430
446
  return this.instance.register(factory, { prefix });
431
447
  }
@@ -447,32 +463,32 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
447
463
  const withRawBody = !!rawBody;
448
464
  const { bodyLimit } = this.getInstance().initialConfig;
449
465
  this.useBodyParser(contentType, withRawBody, { bodyLimit }, (_req, body, done) => {
450
- done(null, (0, fast_querystring_1.parse)(body.toString()));
466
+ done(null, querystringParse(body.toString()));
451
467
  });
452
468
  }
453
469
  async registerMiddie() {
454
470
  this.isMiddieRegistered = true;
455
- await this.register(fastify_middie_1.default);
471
+ await this.register(middie);
456
472
  }
457
473
  getRequestOriginalUrl(rawRequest) {
458
474
  return rawRequest.originalUrl || rawRequest.url;
459
475
  }
460
476
  injectRouteOptions(routerMethodKey, ...args) {
461
477
  const handlerRef = args[args.length - 1];
462
- const isVersioned = !(0, shared_utils_1.isUndefined)(handlerRef.version) &&
463
- handlerRef.version !== common_1.VERSION_NEUTRAL;
464
- const routeConfig = Reflect.getMetadata(constants_1.FASTIFY_ROUTE_CONFIG_METADATA, handlerRef);
465
- const routeConstraints = Reflect.getMetadata(constants_1.FASTIFY_ROUTE_CONSTRAINTS_METADATA, handlerRef);
466
- const routeSchema = Reflect.getMetadata(constants_1.FASTIFY_ROUTE_SCHEMA_METADATA, handlerRef);
467
- const hasConfig = !(0, shared_utils_1.isUndefined)(routeConfig);
468
- const hasConstraints = !(0, shared_utils_1.isUndefined)(routeConstraints);
469
- const hasSchema = !(0, shared_utils_1.isUndefined)(routeSchema);
478
+ const isVersioned = !isUndefined(handlerRef.version) &&
479
+ handlerRef.version !== VERSION_NEUTRAL;
480
+ const routeConfig = Reflect.getMetadata(FASTIFY_ROUTE_CONFIG_METADATA, handlerRef);
481
+ const routeConstraints = Reflect.getMetadata(FASTIFY_ROUTE_CONSTRAINTS_METADATA, handlerRef);
482
+ const routeSchema = Reflect.getMetadata(FASTIFY_ROUTE_SCHEMA_METADATA, handlerRef);
483
+ const hasConfig = !isUndefined(routeConfig);
484
+ const hasConstraints = !isUndefined(routeConstraints);
485
+ const hasSchema = !isUndefined(routeSchema);
470
486
  const routeToInject = {
471
487
  method: routerMethodKey,
472
488
  url: args[0],
473
489
  handler: handlerRef,
474
490
  };
475
- if (this.instance.supportedMethods.indexOf(routerMethodKey) === -1) {
491
+ if (!this.instance.supportedMethods.includes(routerMethodKey)) {
476
492
  this.instance.addHttpMethod(routerMethodKey, { hasBody: true });
477
493
  }
478
494
  if (isVersioned || hasConstraints || hasConfig || hasSchema) {
@@ -501,35 +517,4 @@ class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
501
517
  }
502
518
  return this.instance.route(routeToInject);
503
519
  }
504
- sanitizeUrl(url) {
505
- const initialConfig = this.instance.initialConfig;
506
- const routerOptions = initialConfig.routerOptions;
507
- if (routerOptions.ignoreDuplicateSlashes ||
508
- initialConfig.ignoreDuplicateSlashes) {
509
- url = this.removeDuplicateSlashes(url);
510
- }
511
- if (routerOptions.ignoreTrailingSlash ||
512
- initialConfig.ignoreTrailingSlash) {
513
- url = this.trimLastSlash(url);
514
- }
515
- if (routerOptions.caseSensitive === false ||
516
- initialConfig.caseSensitive === false) {
517
- url = url.toLowerCase();
518
- }
519
- return (0, url_sanitizer_1.safeDecodeURI)(url, routerOptions.useSemicolonDelimiter ||
520
- initialConfig.useSemicolonDelimiter).path;
521
- }
522
- removeDuplicateSlashes(path) {
523
- const REMOVE_DUPLICATE_SLASHES_REGEXP = /\/\/+/g;
524
- return path.indexOf('//') !== -1
525
- ? path.replace(REMOVE_DUPLICATE_SLASHES_REGEXP, '/')
526
- : path;
527
- }
528
- trimLastSlash(path) {
529
- if (path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
530
- return path.slice(0, -1);
531
- }
532
- return path;
533
- }
534
520
  }
535
- exports.FastifyAdapter = FastifyAdapter;
@@ -1 +1 @@
1
- export * from './fastify-adapter';
1
+ export * from './fastify-adapter.js';
package/adapters/index.js CHANGED
@@ -1,4 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./fastify-adapter"), exports);
1
+ export * from './fastify-adapter.js';
@@ -1,24 +1,19 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fastifyMiddie = fastifyMiddie;
4
- const fastify_plugin_1 = require("fastify-plugin");
5
- const url_sanitizer_1 = require("find-my-way/lib/url-sanitizer");
6
- const path_to_regexp_1 = require("path-to-regexp");
7
- const reusify = require("reusify");
8
- function bindLast(fn, last) {
9
- return (...args) => fn(...args, last);
10
- }
1
+ import fp from 'fastify-plugin';
2
+ import urlSanitizer from 'find-my-way/lib/url-sanitizer.js';
3
+ import { pathToRegexp } from 'path-to-regexp';
4
+ import reusify from 'reusify';
5
+ const { safeDecodeURI } = urlSanitizer;
11
6
  /**
12
7
  * A clone of `@fastify/middie` engine https://github.com/fastify/middie
13
8
  * with an extra vulnerability fix. Path is now decoded before matching to
14
9
  * avoid bypassing middleware with encoded characters.
15
10
  */
16
- function middie(complete, initialConfig) {
11
+ function middie(complete) {
17
12
  const middlewares = [];
18
13
  const pool = reusify(Holder);
19
14
  return {
20
15
  use,
21
- run: bindLast(run, initialConfig),
16
+ run,
22
17
  };
23
18
  function use(url, f) {
24
19
  if (f === undefined) {
@@ -27,7 +22,7 @@ function middie(complete, initialConfig) {
27
22
  }
28
23
  let regexp;
29
24
  if (typeof url === 'string') {
30
- const pathRegExp = (0, path_to_regexp_1.pathToRegexp)(sanitizePrefixUrl(url), {
25
+ const pathRegExp = pathToRegexp(sanitizePrefixUrl(url), {
31
26
  end: false,
32
27
  });
33
28
  regexp = pathRegExp.regexp;
@@ -42,7 +37,7 @@ function middie(complete, initialConfig) {
42
37
  }
43
38
  return this;
44
39
  }
45
- function run(req, res, ctx, initialConfig) {
40
+ function run(req, res, ctx) {
46
41
  if (!middlewares.length) {
47
42
  complete(null, req, res, ctx);
48
43
  return;
@@ -53,7 +48,6 @@ function middie(complete, initialConfig) {
53
48
  holder.res = res;
54
49
  holder.url = sanitizeUrl(req.url);
55
50
  holder.context = ctx;
56
- holder.initialConfig = initialConfig;
57
51
  holder.done();
58
52
  }
59
53
  function Holder() {
@@ -61,7 +55,6 @@ function middie(complete, initialConfig) {
61
55
  this.res = null;
62
56
  this.url = null;
63
57
  this.context = null;
64
- this.initialConfig = null;
65
58
  this.i = 0;
66
59
  const that = this;
67
60
  this.done = function (err) {
@@ -83,21 +76,7 @@ function middie(complete, initialConfig) {
83
76
  const { fn, regexp } = middlewares[i];
84
77
  if (regexp) {
85
78
  // Decode URL before matching to avoid bypassing middleware
86
- let sanitizedUrl = url;
87
- if (that.initialConfig.ignoreDuplicateSlashes ||
88
- that.initialConfig.routerOptions?.ignoreDuplicateSlashes) {
89
- sanitizedUrl = removeDuplicateSlashes(sanitizedUrl);
90
- }
91
- if (that.initialConfig.ignoreTrailingSlash ||
92
- that.initialConfig.routerOptions?.ignoreTrailingSlash) {
93
- sanitizedUrl = trimLastSlash(sanitizedUrl);
94
- }
95
- if (that.initialConfig.caseSensitive === false ||
96
- that.initialConfig.routerOptions?.caseSensitive === false) {
97
- sanitizedUrl = sanitizedUrl.toLowerCase();
98
- }
99
- const decodedUrl = (0, url_sanitizer_1.safeDecodeURI)(sanitizedUrl, that.initialConfig?.routerOptions?.useSemicolonDelimiter ||
100
- that.initialConfig?.useSemicolonDelimiter).path;
79
+ const decodedUrl = safeDecodeURI(url).path;
101
80
  const result = regexp.exec(decodedUrl);
102
81
  if (result) {
103
82
  req.url = req.url.replace(result[0], '');
@@ -118,24 +97,11 @@ function middie(complete, initialConfig) {
118
97
  that.req = null;
119
98
  that.res = null;
120
99
  that.context = null;
121
- that.initialConfig = null;
122
100
  that.i = 0;
123
101
  pool.release(that);
124
102
  }
125
103
  }
126
104
  }
127
- function removeDuplicateSlashes(path) {
128
- const REMOVE_DUPLICATE_SLASHES_REGEXP = /\/\/+/g;
129
- return path.indexOf('//') !== -1
130
- ? path.replace(REMOVE_DUPLICATE_SLASHES_REGEXP, '/')
131
- : path;
132
- }
133
- function trimLastSlash(path) {
134
- if (path.length > 1 && path.charCodeAt(path.length - 1) === 47) {
135
- return path.slice(0, -1);
136
- }
137
- return path;
138
- }
139
105
  function sanitizeUrl(url) {
140
106
  for (let i = 0, len = url.length; i < len; i++) {
141
107
  const charCode = url.charCodeAt(i);
@@ -176,7 +142,7 @@ function fastifyMiddie(fastify, options, next) {
176
142
  fastify.decorate('use', use);
177
143
  fastify[kMiddlewares] = [];
178
144
  fastify[kMiddieHasMiddlewares] = false;
179
- fastify[kMiddie] = middie(onMiddieEnd, fastify.initialConfig);
145
+ fastify[kMiddie] = middie(onMiddieEnd);
180
146
  const hook = options.hook || 'onRequest';
181
147
  if (!supportedHooks.includes(hook)) {
182
148
  next(new Error(`The hook "${hook}" is not supported by fastify-middie`));
@@ -230,7 +196,7 @@ function fastifyMiddie(fastify, options, next) {
230
196
  function onRegister(instance) {
231
197
  const middlewares = instance[kMiddlewares].slice();
232
198
  instance[kMiddlewares] = [];
233
- instance[kMiddie] = middie(onMiddieEnd, instance.initialConfig);
199
+ instance[kMiddie] = middie(onMiddieEnd);
234
200
  instance[kMiddieHasMiddlewares] = false;
235
201
  instance.decorate('use', use);
236
202
  for (const middleware of middlewares) {
@@ -244,7 +210,8 @@ function fastifyMiddie(fastify, options, next) {
244
210
  * with an extra vulnerability fix. Path is now decoded before matching to
245
211
  * avoid bypassing middleware with encoded characters.
246
212
  */
247
- exports.default = (0, fastify_plugin_1.default)(fastifyMiddie, {
213
+ export default fp(fastifyMiddie, {
248
214
  fastify: '5.x',
249
215
  name: '@fastify/middie',
250
216
  });
217
+ export { fastifyMiddie };
package/constants.js CHANGED
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FASTIFY_ROUTE_SCHEMA_METADATA = exports.FASTIFY_ROUTE_CONSTRAINTS_METADATA = exports.FASTIFY_ROUTE_CONFIG_METADATA = void 0;
4
- exports.FASTIFY_ROUTE_CONFIG_METADATA = '__fastify_route_config__';
5
- exports.FASTIFY_ROUTE_CONSTRAINTS_METADATA = '__fastify_route_constraints__';
6
- exports.FASTIFY_ROUTE_SCHEMA_METADATA = '__fastify_route_schema__';
1
+ export const FASTIFY_ROUTE_CONFIG_METADATA = '__fastify_route_config__';
2
+ export const FASTIFY_ROUTE_CONSTRAINTS_METADATA = '__fastify_route_constraints__';
3
+ export const FASTIFY_ROUTE_SCHEMA_METADATA = '__fastify_route_schema__';
@@ -1,3 +1,3 @@
1
- export * from './route-config.decorator';
2
- export * from './route-constraints.decorator';
3
- export * from './route-schema.decorator';
1
+ export * from './route-config.decorator.js';
2
+ export * from './route-constraints.decorator.js';
3
+ export * from './route-schema.decorator.js';
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./route-config.decorator"), exports);
5
- tslib_1.__exportStar(require("./route-constraints.decorator"), exports);
6
- tslib_1.__exportStar(require("./route-schema.decorator"), exports);
1
+ export * from './route-config.decorator.js';
2
+ export * from './route-constraints.decorator.js';
3
+ export * from './route-schema.decorator.js';
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RouteConfig = void 0;
4
- const common_1 = require("@nestjs/common");
5
- const constants_1 = require("../constants");
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { FASTIFY_ROUTE_CONFIG_METADATA } from '../constants.js';
6
3
  /**
7
4
  * @publicApi
8
5
  *
9
6
  * @param config See {@link https://fastify.dev/docs/latest/Reference/Routes/#config}
10
7
  */
11
- const RouteConfig = (config) => (0, common_1.SetMetadata)(constants_1.FASTIFY_ROUTE_CONFIG_METADATA, config);
12
- exports.RouteConfig = RouteConfig;
8
+ export const RouteConfig = (config) => SetMetadata(FASTIFY_ROUTE_CONFIG_METADATA, config);
@@ -1,12 +1,8 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RouteConstraints = void 0;
4
- const common_1 = require("@nestjs/common");
5
- const constants_1 = require("../constants");
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { FASTIFY_ROUTE_CONSTRAINTS_METADATA } from '../constants.js';
6
3
  /**
7
4
  * @publicApi
8
5
  *
9
6
  * @param config See {@link https://fastify.dev/docs/latest/Reference/Routes/#constraints}
10
7
  */
11
- const RouteConstraints = (config) => (0, common_1.SetMetadata)(constants_1.FASTIFY_ROUTE_CONSTRAINTS_METADATA, config);
12
- exports.RouteConstraints = RouteConstraints;
8
+ export const RouteConstraints = (config) => SetMetadata(FASTIFY_ROUTE_CONSTRAINTS_METADATA, config);
@@ -1,8 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RouteSchema = void 0;
4
- const common_1 = require("@nestjs/common");
5
- const constants_1 = require("../constants");
1
+ import { SetMetadata } from '@nestjs/common';
2
+ import { FASTIFY_ROUTE_SCHEMA_METADATA } from '../constants.js';
6
3
  /**
7
4
  * @publicApi
8
5
  * Allows setting the schema for the route. Schema is an object that can contain the following properties:
@@ -12,5 +9,4 @@ const constants_1 = require("../constants");
12
9
  * - response: Record<HttpStatusCode, JsonSchema>
13
10
  * @param schema See {@link https://fastify.dev/docs/latest/Reference/Routes/#routes-options}
14
11
  */
15
- const RouteSchema = (schema) => (0, common_1.SetMetadata)(constants_1.FASTIFY_ROUTE_SCHEMA_METADATA, schema);
16
- exports.RouteSchema = RouteSchema;
12
+ export const RouteSchema = (schema) => SetMetadata(FASTIFY_ROUTE_SCHEMA_METADATA, schema);
package/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './adapters';
2
- export * from './interfaces';
3
- export * from './decorators';
1
+ export * from './adapters/index.js';
2
+ export * from './interfaces/index.js';
3
+ export * from './decorators/index.js';
package/index.js CHANGED
@@ -1,12 +1,9 @@
1
- "use strict";
2
1
  /*
3
2
  * Nest @platform-fastify
4
3
  * Copyright(c) 2017 - 2025 Kamil Mysliwiec
5
4
  * https://nestjs.com
6
5
  * MIT Licensed
7
6
  */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- const tslib_1 = require("tslib");
10
- tslib_1.__exportStar(require("./adapters"), exports);
11
- tslib_1.__exportStar(require("./interfaces"), exports);
12
- tslib_1.__exportStar(require("./decorators"), exports);
7
+ export * from './adapters/index.js';
8
+ export * from './interfaces/index.js';
9
+ export * from './decorators/index.js';
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1,2 @@
1
- export * from './fastify-static-options.interface';
2
- export * from './fastify-view-options.interface';
1
+ export * from './fastify-static-options.interface.js';
2
+ export * from './fastify-view-options.interface.js';
@@ -1,5 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./fastify-static-options.interface"), exports);
5
- tslib_1.__exportStar(require("./fastify-view-options.interface"), exports);
1
+ export * from './fastify-static-options.interface.js';
2
+ export * from './fastify-view-options.interface.js';
@@ -1,2 +1,2 @@
1
- export * from './nest-fastify-application.interface';
2
- export * from './nest-fastify-body-parser-options.interface';
1
+ export * from './nest-fastify-application.interface.js';
2
+ export * from './nest-fastify-body-parser-options.interface.js';
@@ -1,5 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./nest-fastify-application.interface"), exports);
5
- tslib_1.__exportStar(require("./nest-fastify-body-parser-options.interface"), exports);
1
+ export * from './nest-fastify-application.interface.js';
2
+ export * from './nest-fastify-body-parser-options.interface.js';
@@ -1,9 +1,9 @@
1
1
  import { FastifyCorsOptions } from '@fastify/cors';
2
- import { HttpServer, INestApplication } from '@nestjs/common';
2
+ import type { HttpServer, INestApplication } from '@nestjs/common';
3
3
  import { FastifyBodyParser, FastifyInstance, FastifyListenOptions, FastifyPluginAsync, FastifyPluginCallback, FastifyPluginOptions, FastifyRegisterOptions, FastifyReply, FastifyRequest, RawServerBase, RawServerDefault } from 'fastify';
4
4
  import { InjectOptions, Chain as LightMyRequestChain, Response as LightMyRequestResponse } from 'light-my-request';
5
- import { FastifyStaticOptions, FastifyViewOptions } from './external';
6
- import { NestFastifyBodyParserOptions } from './nest-fastify-body-parser-options.interface';
5
+ import { FastifyStaticOptions, FastifyViewOptions } from './external/index.js';
6
+ import { NestFastifyBodyParserOptions } from './nest-fastify-body-parser-options.interface.js';
7
7
  /**
8
8
  * @publicApi
9
9
  */
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
package/package.json CHANGED
@@ -1,9 +1,20 @@
1
1
  {
2
2
  "name": "@nestjs/platform-fastify",
3
- "version": "11.1.15",
3
+ "version": "12.0.0-alpha.0",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@platform-fastify)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
7
+ "type": "module",
8
+ "main": "./index.js",
9
+ "exports": {
10
+ ".": "./index.js",
11
+ "./*.js": "./*.js",
12
+ "./*": "./*.js",
13
+ "./adapters": "./adapters/index.js",
14
+ "./decorators": "./decorators/index.js",
15
+ "./interfaces": "./interfaces/index.js",
16
+ "./interfaces/external": "./interfaces/external/index.js"
17
+ },
7
18
  "homepage": "https://nestjs.com",
8
19
  "funding": {
9
20
  "type": "opencollective",
@@ -23,7 +34,7 @@
23
34
  "fast-querystring": "1.1.2",
24
35
  "fastify": "5.7.4",
25
36
  "fastify-plugin": "5.1.0",
26
- "find-my-way": "9.5.0",
37
+ "find-my-way": "9.4.0",
27
38
  "light-my-request": "6.6.0",
28
39
  "path-to-regexp": "8.3.0",
29
40
  "reusify": "1.1.0",
@@ -43,5 +54,5 @@
43
54
  "optional": true
44
55
  }
45
56
  },
46
- "gitHead": "cb68ac211dc7df39a8bac01cae043c50634ca303"
57
+ "gitHead": "7035ecc828a2a9f752aad188871b1171663a20c2"
47
58
  }
@@ -2,13 +2,7 @@
2
2
  "extends": "../tsconfig.build.json",
3
3
  "compilerOptions": {
4
4
  "outDir": ".",
5
- "rootDir": ".",
6
- "paths": {
7
- "@nestjs/common": ["../common"],
8
- "@nestjs/common/*": ["../common/*"],
9
- "@nestjs/core": ["../core"],
10
- "@nestjs/core/*": ["../core/*"]
11
- }
5
+ "rootDir": "."
12
6
  },
13
7
  "exclude": ["node_modules", "dist", "test/**/*", "*.spec.ts"],
14
8
  "references": [