@lenne.tech/nest-server 11.42.5 → 11.42.7
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/.claude/rules/configurable-features.md +2 -1
- package/.claude/rules/testing.md +3 -3
- package/FRAMEWORK-API.md +1 -1
- package/dist/core/common/helpers/swagger.helper.d.ts +11 -0
- package/dist/core/common/helpers/swagger.helper.js +362 -0
- package/dist/core/common/helpers/swagger.helper.js.map +1 -0
- package/dist/core/common/interfaces/swagger-setup-options.interface.d.ts +33 -0
- package/dist/core/common/interfaces/swagger-setup-options.interface.js +3 -0
- package/dist/core/common/interfaces/swagger-setup-options.interface.js.map +1 -0
- package/dist/core/common/services/core-body-parser.initializer.d.ts +2 -0
- package/dist/core/common/services/core-body-parser.initializer.js +23 -3
- package/dist/core/common/services/core-body-parser.initializer.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/main.js +8 -14
- package/dist/main.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/REQUEST-LIFECYCLE.md +1 -1
- package/migration-guides/11.42.3-to-11.42.4.md +10 -1
- package/migration-guides/11.42.5-to-11.42.6.md +113 -0
- package/migration-guides/11.42.6-to-11.42.7.md +115 -0
- package/package.json +4 -4
- package/src/core/common/helpers/swagger.helper.ts +529 -0
- package/src/core/common/interfaces/server-options.interface.ts +5 -0
- package/src/core/common/interfaces/swagger-setup-options.interface.ts +131 -0
- package/src/core/common/services/core-body-parser.initializer.ts +47 -5
- package/src/index.ts +2 -0
- package/src/main.ts +9 -15
|
@@ -90,11 +90,8 @@ export class CoreBodyParserInitializer implements OnModuleInit {
|
|
|
90
90
|
const limit = this.resolveLimit(type, config?.[type]?.limit);
|
|
91
91
|
const layers = stack.filter((layer) => this.isGlobalParserLayer(layer, type));
|
|
92
92
|
|
|
93
|
-
if (
|
|
94
|
-
this.
|
|
95
|
-
`bodyParser.${type}.limit is configured, but no global ${type} body parser is registered ` +
|
|
96
|
-
'(was the app created with `bodyParser: false`?) — the limit has no effect.',
|
|
97
|
-
);
|
|
93
|
+
if (!layers.length) {
|
|
94
|
+
this.warnMissingGlobalParser(type, stack, limit);
|
|
98
95
|
continue;
|
|
99
96
|
}
|
|
100
97
|
|
|
@@ -147,6 +144,18 @@ export class CoreBodyParserInitializer implements OnModuleInit {
|
|
|
147
144
|
return layer?.slash === true && typeof layer.handle === 'function' && layer.handle.name === PARSER_NAMES[type];
|
|
148
145
|
}
|
|
149
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Whether the application was created without `bodyParser: false`.
|
|
149
|
+
*
|
|
150
|
+
* Read from the same container options as `rawBody`. Under `Test.createTestingModule()` those
|
|
151
|
+
* options never reach the container, so the answer there is always "enabled".
|
|
152
|
+
*/
|
|
153
|
+
protected isBodyParserEnabled(): boolean {
|
|
154
|
+
const container = (this.moduleRef as unknown as { container?: { contextOptions?: { bodyParser?: boolean } } })
|
|
155
|
+
?.container;
|
|
156
|
+
return container?.contextOptions?.bodyParser !== false;
|
|
157
|
+
}
|
|
158
|
+
|
|
150
159
|
/**
|
|
151
160
|
* Whether the application was created with `rawBody: true`.
|
|
152
161
|
*
|
|
@@ -210,6 +219,39 @@ export class CoreBodyParserInitializer implements OnModuleInit {
|
|
|
210
219
|
);
|
|
211
220
|
}
|
|
212
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Explain why there is no global parser of this type, when there should be one.
|
|
224
|
+
*
|
|
225
|
+
* NestJS registers its own parsers inside `app.init()` only if no layer with the parser's function
|
|
226
|
+
* name exists yet (`ExpressAdapter.isMiddlewareApplied()` compares the NAME and nothing else). A
|
|
227
|
+
* path-scoped `server.use('/upload', json({ limit }))` in `main.ts` therefore counts as "applied",
|
|
228
|
+
* NestJS skips its global parser, and every request outside that path reaches its handler with an
|
|
229
|
+
* empty body — a sign-in fails with a validation error, and nothing says why. Restoring the parser
|
|
230
|
+
* from here is not safe: NestJS would have placed it after everything `main.ts` registered, and that
|
|
231
|
+
* position is no longer knowable during module init (a raw-body webhook or a proxy registered after
|
|
232
|
+
* the path-scoped parser must keep seeing the unread stream). So this reports, with the remedy.
|
|
233
|
+
*/
|
|
234
|
+
protected warnMissingGlobalParser(type: CoreBodyParserType, stack: ExpressLayer[], limit: number | undefined): void {
|
|
235
|
+
const name = PARSER_NAMES[type];
|
|
236
|
+
const shadowed = stack.some((layer) => layer?.slash !== true && layer?.handle?.name === name);
|
|
237
|
+
if (shadowed && this.isBodyParserEnabled()) {
|
|
238
|
+
this.logger.warn(
|
|
239
|
+
`No global ${type} body parser is registered: NestJS skips its own when a layer named \`${name}\` ` +
|
|
240
|
+
`already exists, and a path-scoped \`${type}()\` parser registered before \`app.init()\` counts as one. ` +
|
|
241
|
+
`Every request outside that path reaches its handler with an EMPTY body. Register the global parser ` +
|
|
242
|
+
`in main.ts as well — \`server.useBodyParser('${type}')\` — a configured \`bodyParser.${type}.limit\` ` +
|
|
243
|
+
'is applied to it.',
|
|
244
|
+
);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (limit !== undefined) {
|
|
248
|
+
this.logger.warn(
|
|
249
|
+
`bodyParser.${type}.limit is configured, but no global ${type} body parser is registered ` +
|
|
250
|
+
'(was the app created with `bodyParser: false`?) — the limit has no effect.',
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
213
255
|
/**
|
|
214
256
|
* Wrap a parser so its 413 is translated, keeping the name NestJS identifies the layer by.
|
|
215
257
|
*
|
package/src/index.ts
CHANGED
|
@@ -53,6 +53,7 @@ export * from './core/common/helpers/process-diagnostics.helper';
|
|
|
53
53
|
export * from './core/common/helpers/register-enum.helper';
|
|
54
54
|
export * from './core/common/helpers/scim.helper';
|
|
55
55
|
export * from './core/common/helpers/service.helper';
|
|
56
|
+
export * from './core/common/helpers/swagger.helper';
|
|
56
57
|
export * from './core/common/helpers/table.helper';
|
|
57
58
|
export * from './core/common/inputs/combined-filter.input';
|
|
58
59
|
export * from './core/common/inputs/core-input.input';
|
|
@@ -73,6 +74,7 @@ export * from './core/common/interfaces/prepare-output-options.interface';
|
|
|
73
74
|
export * from './core/common/interfaces/resolve-selector.interface';
|
|
74
75
|
export * from './core/common/interfaces/server-options.interface';
|
|
75
76
|
export * from './core/common/interfaces/service-options.interface';
|
|
77
|
+
export * from './core/common/interfaces/swagger-setup-options.interface';
|
|
76
78
|
export * from './core/common/middleware/request-context.middleware';
|
|
77
79
|
export * from './core/common/middlewares/to-lower-case.middleware';
|
|
78
80
|
export * from './core/common/middlewares/security-headers.middleware';
|
package/src/main.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { NestFactory } from '@nestjs/core';
|
|
2
2
|
import { NestExpressApplication } from '@nestjs/platform-express';
|
|
3
|
-
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
|
|
4
3
|
import { exec } from 'child_process';
|
|
5
4
|
import compression = require('compression');
|
|
6
5
|
import cookieParser = require('cookie-parser');
|
|
@@ -11,6 +10,7 @@ import { buildCorsConfig, isCookiesEnabled, isCorsDisabled } from './core/common
|
|
|
11
10
|
import { HttpExceptionLogFilter } from './core/common/filters/http-exception-log.filter';
|
|
12
11
|
import { installGracefulShutdown } from './core/common/helpers/graceful-shutdown.helper';
|
|
13
12
|
import { handleFatalBootstrapError, installProcessDiagnostics } from './core/common/helpers/process-diagnostics.helper';
|
|
13
|
+
import { setupSwagger } from './core/common/helpers/swagger.helper';
|
|
14
14
|
import { CorePersistenceModel } from './core/common/models/core-persistence.model';
|
|
15
15
|
import { CoreAuthModel } from './core/modules/auth/core-auth.model';
|
|
16
16
|
import { CoreUserModel } from './core/modules/user/core-user.model';
|
|
@@ -96,21 +96,15 @@ async function bootstrap() {
|
|
|
96
96
|
// to avoid open CORS with credentials). Callers should configure appUrl/baseUrl/allowedOrigins.
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
// Swagger documentation
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.addBearerAuth()
|
|
105
|
-
.build();
|
|
106
|
-
const documentFactory = () =>
|
|
107
|
-
SwaggerModule.createDocument(server, config, {
|
|
108
|
-
autoTagControllers: true,
|
|
109
|
-
deepScanRoutes: true,
|
|
99
|
+
// Swagger documentation: security, API-token scopes and the tenant header are read from the same
|
|
100
|
+
// decorators the guards read (see setupSwagger), so "Authorize" applies to every route.
|
|
101
|
+
setupSwagger(server, {
|
|
102
|
+
description: 'API lenne.Tech Nest Server',
|
|
103
|
+
documentOptions: {
|
|
110
104
|
extraModels: [CoreUserModel, CoreAuthModel, Auth, User, PersistenceModel, CorePersistenceModel, FilterArgs],
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
},
|
|
106
|
+
title: 'Nest Server API',
|
|
107
|
+
version: '1.0.0',
|
|
114
108
|
});
|
|
115
109
|
|
|
116
110
|
// Drain the event loop on SIGTERM/SIGINT so the process actually exits.
|