@nestjs/platform-express 12.0.2 → 12.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -47,6 +47,10 @@ For questions and support please use the official [Discord channel](https://disc
47
47
 
48
48
  Please make sure to read the [Issue Reporting Checklist](https://github.com/nestjs/nest/blob/master/CONTRIBUTING.md#-submitting-an-issue) before opening an issue. Issues not conforming to the guidelines may be closed immediately.
49
49
 
50
+ ## Observability
51
+
52
+ [NestJS Observe](https://observe.nestjs.com) is the official observability platform for Nest applications. Install the `@nestjs/observe` SDK, pass an API key, and requests, background jobs, errors, logs, and distributed traces start streaming to a dashboard - no manual span wiring and no collector to run. Because the SDK hooks into Nest's own request lifecycle, a trace reads like a call graph of your controllers and providers instead of a bare HTTP route. Free for up to 300,000 events a month, and there is a [live demo](https://www.observe-demo.nestjs.com/dashboard) with no signup.
53
+
50
54
  ## Consulting
51
55
 
52
56
  With official support, you can get expert help straight from the Nest core team. We provide dedicated technical support, migration strategies, advice on best practices (and design decisions), PR reviews, and team augmentation. Read more about [support here](https://enterprise.nestjs.com).
@@ -2,7 +2,7 @@ import { __decorate, __metadata, __param } from "tslib";
2
2
  import { Inject, mixin, Optional, } from '@nestjs/common';
3
3
  import multer from 'multer';
4
4
  import { MULTER_MODULE_OPTIONS } from '../files.constants.js';
5
- import { transformException } from '../multer/multer.utils.js';
5
+ import { mergeMulterOptions, transformException, } from '../multer/multer.utils.js';
6
6
  /**
7
7
  * @param localOptions
8
8
  *
@@ -12,10 +12,7 @@ export function AnyFilesInterceptor(localOptions) {
12
12
  let MixinInterceptor = class MixinInterceptor {
13
13
  multer;
14
14
  constructor(options = {}) {
15
- this.multer = multer({
16
- ...options,
17
- ...localOptions,
18
- });
15
+ this.multer = multer(mergeMulterOptions(options, localOptions));
19
16
  }
20
17
  async intercept(context, next) {
21
18
  const ctx = context.switchToHttp();
@@ -2,7 +2,7 @@ import { __decorate, __metadata, __param } from "tslib";
2
2
  import { Inject, mixin, Optional, } from '@nestjs/common';
3
3
  import multer from 'multer';
4
4
  import { MULTER_MODULE_OPTIONS } from '../files.constants.js';
5
- import { transformException } from '../multer/multer.utils.js';
5
+ import { mergeMulterOptions, transformException, } from '../multer/multer.utils.js';
6
6
  /**
7
7
  * @param uploadFields
8
8
  * @param localOptions
@@ -12,10 +12,7 @@ export function FileFieldsInterceptor(uploadFields, localOptions) {
12
12
  let MixinInterceptor = class MixinInterceptor {
13
13
  multer;
14
14
  constructor(options = {}) {
15
- this.multer = multer({
16
- ...options,
17
- ...localOptions,
18
- });
15
+ this.multer = multer(mergeMulterOptions(options, localOptions));
19
16
  }
20
17
  async intercept(context, next) {
21
18
  const ctx = context.switchToHttp();
@@ -2,7 +2,7 @@ import { __decorate, __metadata, __param } from "tslib";
2
2
  import { Inject, mixin, Optional, } from '@nestjs/common';
3
3
  import multer from 'multer';
4
4
  import { MULTER_MODULE_OPTIONS } from '../files.constants.js';
5
- import { transformException } from '../multer/multer.utils.js';
5
+ import { mergeMulterOptions, transformException, } from '../multer/multer.utils.js';
6
6
  /**
7
7
  * @param fieldName
8
8
  * @param localOptions
@@ -13,10 +13,7 @@ export function FileInterceptor(fieldName, localOptions) {
13
13
  let MixinInterceptor = class MixinInterceptor {
14
14
  multer;
15
15
  constructor(options = {}) {
16
- this.multer = multer({
17
- ...options,
18
- ...localOptions,
19
- });
16
+ this.multer = multer(mergeMulterOptions(options, localOptions));
20
17
  }
21
18
  async intercept(context, next) {
22
19
  const ctx = context.switchToHttp();
@@ -2,7 +2,7 @@ import { __decorate, __metadata, __param } from "tslib";
2
2
  import { Inject, mixin, Optional, } from '@nestjs/common';
3
3
  import multer from 'multer';
4
4
  import { MULTER_MODULE_OPTIONS } from '../files.constants.js';
5
- import { transformException } from '../multer/multer.utils.js';
5
+ import { mergeMulterOptions, transformException, } from '../multer/multer.utils.js';
6
6
  /**
7
7
  *
8
8
  * @param fieldName
@@ -15,10 +15,7 @@ export function FilesInterceptor(fieldName, maxCount, localOptions) {
15
15
  let MixinInterceptor = class MixinInterceptor {
16
16
  multer;
17
17
  constructor(options = {}) {
18
- this.multer = multer({
19
- ...options,
20
- ...localOptions,
21
- });
18
+ this.multer = multer(mergeMulterOptions(options, localOptions));
22
19
  }
23
20
  async intercept(context, next) {
24
21
  const ctx = context.switchToHttp();
@@ -2,7 +2,7 @@ import { __decorate, __metadata, __param } from "tslib";
2
2
  import { Inject, mixin, Optional, } from '@nestjs/common';
3
3
  import multer from 'multer';
4
4
  import { MULTER_MODULE_OPTIONS } from '../files.constants.js';
5
- import { transformException } from '../multer/multer.utils.js';
5
+ import { mergeMulterOptions, transformException, } from '../multer/multer.utils.js';
6
6
  /**
7
7
  *
8
8
  * @param localOptions
@@ -12,10 +12,7 @@ export function NoFilesInterceptor(localOptions) {
12
12
  let MixinInterceptor = class MixinInterceptor {
13
13
  multer;
14
14
  constructor(options = {}) {
15
- this.multer = multer({
16
- ...options,
17
- ...localOptions,
18
- });
15
+ this.multer = multer(mergeMulterOptions(options, localOptions));
19
16
  }
20
17
  async intercept(context, next) {
21
18
  const ctx = context.switchToHttp();
@@ -1,3 +1,22 @@
1
+ /**
2
+ * @publicApi
3
+ */
4
+ export interface MulterLimits {
5
+ /** Max field name size (Default: 100 bytes) */
6
+ fieldNameSize?: number;
7
+ /** Max field value size (Default: 1MB) */
8
+ fieldSize?: number;
9
+ /** Max number of non- file fields (Default: Infinity) */
10
+ fields?: number;
11
+ /** For multipart forms, the max file size (in bytes)(Default: Infinity) */
12
+ fileSize?: number;
13
+ /** For multipart forms, the max number of file fields (Default: Infinity) */
14
+ files?: number;
15
+ /** For multipart forms, the max number of parts (fields + files)(Default: Infinity) */
16
+ parts?: number;
17
+ /** For multipart forms, the max number of header key=> value pairs to parse Default: 2000(same as node's http). */
18
+ headerPairs?: number;
19
+ }
1
20
  /**
2
21
  * @see https://github.com/expressjs/multer
3
22
  *
@@ -10,23 +29,10 @@ export interface MulterOptions {
10
29
  /**
11
30
  * An object specifying the size limits of the following optional properties. This object is passed to busboy
12
31
  * directly, and the details of properties can be found on https://github.com/mscdex/busboy#busboy-methods
32
+ *
33
+ * Since multer 2.4.0, this can also be a function of the request that returns such an object.
13
34
  */
14
- limits?: {
15
- /** Max field name size (Default: 100 bytes) */
16
- fieldNameSize?: number;
17
- /** Max field value size (Default: 1MB) */
18
- fieldSize?: number;
19
- /** Max number of non- file fields (Default: Infinity) */
20
- fields?: number;
21
- /** For multipart forms, the max file size (in bytes)(Default: Infinity) */
22
- fileSize?: number;
23
- /** For multipart forms, the max number of file fields (Default: Infinity) */
24
- files?: number;
25
- /** For multipart forms, the max number of parts (fields + files)(Default: Infinity) */
26
- parts?: number;
27
- /** For multipart forms, the max number of header key=> value pairs to parse Default: 2000(same as node's http). */
28
- headerPairs?: number;
29
- };
35
+ limits?: MulterLimits | ((req: any) => MulterLimits);
30
36
  /** Keep the full path of files instead of just the base name (Default: false) */
31
37
  preservePath?: boolean;
32
38
  /** Default character set for part header values (e.g. filename) (Default: 'latin1') */
@@ -6,7 +6,7 @@ export const multerExceptions = {
6
6
  LIMIT_FIELD_KEY: 'Field name too long',
7
7
  LIMIT_FIELD_VALUE: 'Field value too long',
8
8
  LIMIT_FIELD_COUNT: 'Too many fields',
9
- LIMIT_UNEXPECTED_FILE: 'Unexpected field',
9
+ LIMIT_UNEXPECTED_FILE: 'Unexpected file field',
10
10
  MISSING_FIELD_NAME: 'Field name missing',
11
11
  LIMIT_FIELD_NESTING: 'Field name nesting too deep',
12
12
  };
@@ -1,6 +1,21 @@
1
1
  import { HttpException } from '@nestjs/common';
2
+ import { MulterModuleOptions } from '../interfaces/index.js';
3
+ import { MulterOptions } from '../interfaces/multer-options.interface.js';
4
+ /**
5
+ * Merges module-level (global) multer options with interceptor-level (local)
6
+ * options. `limits` is merged key-by-key rather than replaced outright, so
7
+ * that a route overriding e.g. `limits.fileSize` doesn't silently drop other
8
+ * global limits (such as `limits.files`) it never intended to touch.
9
+ *
10
+ * `limits` may also be a function of the request (multer >= 2.4.0), which
11
+ * can't be merged key-by-key. In that case (or when only one side defines
12
+ * `limits`) the local value wins outright, matching the pre-merge behaviour.
13
+ */
14
+ export declare function mergeMulterOptions(options?: MulterModuleOptions, localOptions?: MulterOptions): MulterModuleOptions;
2
15
  export declare function transformException(error: (Error & {
3
16
  field?: string;
17
+ code?: string;
4
18
  }) | undefined): HttpException | (Error & {
5
19
  field?: string;
20
+ code?: string;
6
21
  }) | undefined;
@@ -1,12 +1,35 @@
1
1
  import { BadRequestException, HttpException, PayloadTooLargeException, } from '@nestjs/common';
2
+ import { isPlainObject } from '@nestjs/common/internal';
2
3
  import { multerExceptions, busboyExceptions } from './multer.constants.js';
4
+ /**
5
+ * Merges module-level (global) multer options with interceptor-level (local)
6
+ * options. `limits` is merged key-by-key rather than replaced outright, so
7
+ * that a route overriding e.g. `limits.fileSize` doesn't silently drop other
8
+ * global limits (such as `limits.files`) it never intended to touch.
9
+ *
10
+ * `limits` may also be a function of the request (multer >= 2.4.0), which
11
+ * can't be merged key-by-key. In that case (or when only one side defines
12
+ * `limits`) the local value wins outright, matching the pre-merge behaviour.
13
+ */
14
+ export function mergeMulterOptions(options = {}, localOptions = {}) {
15
+ const merged = { ...options, ...localOptions };
16
+ if (isPlainObject(options.limits) && isPlainObject(localOptions.limits)) {
17
+ merged.limits = { ...options.limits, ...localOptions.limits };
18
+ }
19
+ return merged;
20
+ }
3
21
  // Multer may add in a 'field' property to the error
4
22
  // https://github.com/expressjs/multer/blob/aa42bea6ac7d0cb8fcb279b15a7278cda805dc63/lib/multer-error.js#L19
5
23
  export function transformException(error) {
6
24
  if (!error || error instanceof HttpException) {
7
25
  return error;
8
26
  }
9
- switch (error.message) {
27
+ // Multer identifies its errors by `code`, while the messages may change
28
+ // between releases (e.g. "Unexpected field" became "Unexpected file field")
29
+ const exception = isMulterExceptionCode(error.code)
30
+ ? multerExceptions[error.code]
31
+ : error.message;
32
+ switch (exception) {
10
33
  case multerExceptions.LIMIT_FILE_SIZE:
11
34
  return new PayloadTooLargeException(error.message);
12
35
  case multerExceptions.LIMIT_FILE_COUNT:
@@ -30,3 +53,6 @@ export function transformException(error) {
30
53
  }
31
54
  return error;
32
55
  }
56
+ function isMulterExceptionCode(code) {
57
+ return typeof code === 'string' && Object.hasOwn(multerExceptions, code);
58
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/platform-express",
3
- "version": "12.0.2",
3
+ "version": "12.0.4",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@platform-express)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -27,17 +27,17 @@
27
27
  "dependencies": {
28
28
  "cors": "2.8.6",
29
29
  "express": "5.2.1",
30
- "multer": "2.3.0",
30
+ "multer": "2.4.0",
31
31
  "path-to-regexp": "8.4.2",
32
32
  "tslib": "2.8.1"
33
33
  },
34
34
  "devDependencies": {
35
- "@nestjs/common": "12.0.2",
36
- "@nestjs/core": "12.0.2"
35
+ "@nestjs/common": "12.0.4",
36
+ "@nestjs/core": "12.0.4"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@nestjs/common": "^12.0.0",
40
40
  "@nestjs/core": "^12.0.0"
41
41
  },
42
- "gitHead": "ee168a569d30e600d301ed38abb14d2171a6f315"
42
+ "gitHead": "899dbe3a0c1e59d1d0fb7e0c7ad0b2d2aa4ae771"
43
43
  }