@lenne.tech/nest-server 11.14.1 → 11.15.1
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 +12 -12
- package/dist/config.env.js +5 -5
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +1 -1
- package/dist/core.module.d.ts +1 -0
- package/dist/core.module.js +41 -25
- package/dist/core.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +39 -22
- package/src/config.env.ts +5 -5
- package/src/core/common/interfaces/server-options.interface.ts +22 -18
- package/src/core.module.ts +52 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lenne.tech/nest-server",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.15.1",
|
|
4
4
|
"description": "Modern, fast, powerful Node.js web framework in TypeScript based on Nest with a GraphQL API and a connection to MongoDB (or other databases).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node",
|
|
@@ -14,25 +14,31 @@
|
|
|
14
14
|
"homepage": "https://github.com/lenneTech/nest-server",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"scripts": {
|
|
17
|
-
"build": "rimraf dist && nest build &&
|
|
17
|
+
"build": "rimraf dist && nest build && pnpm run build:copy-types && pnpm run build:copy-templates && pnpm run build:add-type-references",
|
|
18
18
|
"build:copy-types": "mkdir -p dist/types && cp src/types/*.d.ts dist/types/",
|
|
19
19
|
"build:copy-templates": "mkdir -p dist/core/modules/migrate/templates && cp src/core/modules/migrate/templates/migration-project.template.ts dist/core/modules/migrate/templates/",
|
|
20
20
|
"build:add-type-references": "node scripts/add-type-references.js",
|
|
21
|
-
"build:pack": "
|
|
22
|
-
"build:dev": "
|
|
23
|
-
"
|
|
21
|
+
"build:pack": "pnpm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
|
|
22
|
+
"build:dev": "pnpm run build",
|
|
23
|
+
"c": "pnpm run check",
|
|
24
|
+
"check": "pnpm audit && pnpm run format:check && pnpm run lint && pnpm test && pnpm run build && pnpm start",
|
|
25
|
+
"check:fix": "pnpm install && pnpm audit --fix && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && pnpm start",
|
|
26
|
+
"check:naf": "pnpm install && pnpm run format && pnpm run lint:fix && pnpm test && pnpm run build && pnpm start",
|
|
27
|
+
"cf": "pnpm run check:fix",
|
|
28
|
+
"cnaf": "pnpm run check:naf",
|
|
29
|
+
"docs": "pnpm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
|
|
24
30
|
"docs:bootstrap": "node extras/update-spectaql-version.mjs && node scripts/run-spectaql.mjs",
|
|
25
|
-
"docs:ci": "ts-node ./scripts/init-server.ts &&
|
|
31
|
+
"docs:ci": "ts-node ./scripts/init-server.ts && pnpm run docs:bootstrap && compodoc -p tsconfig.json",
|
|
26
32
|
"format": "oxfmt --write src/",
|
|
27
33
|
"format:check": "oxfmt --check src/",
|
|
28
34
|
"lint": "oxlint --ignore-path .oxlintignore src/ tests/",
|
|
29
35
|
"lint:fix": "oxlint --fix --fix-suggestions --ignore-path .oxlintignore src/ tests/",
|
|
30
|
-
"prestart:prod": "
|
|
31
|
-
"reinit": "rimraf
|
|
32
|
-
"reinit:clean": "rimraf
|
|
33
|
-
"reinit:force": "rimraf
|
|
34
|
-
"reinit:legacy": "rimraf
|
|
35
|
-
"start": "
|
|
36
|
+
"prestart:prod": "pnpm run build",
|
|
37
|
+
"reinit": "rimraf pnpm-lock.yaml && rimraf node_modules && pnpm install && pnpm run lint && pnpm run test:e2e && pnpm run test:ci && pnpm run build",
|
|
38
|
+
"reinit:clean": "rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install && pnpm run test:e2e && pnpm run build",
|
|
39
|
+
"reinit:force": "rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install --force && pnpm run test:e2e",
|
|
40
|
+
"reinit:legacy": "rimraf pnpm-lock.yaml && rimraf node_modules && pnpm store prune && pnpm install && pnpm run test:e2e",
|
|
41
|
+
"start": "pnpm run start:local",
|
|
36
42
|
"start:prod": "NODE_ENV=production node dist/main.js",
|
|
37
43
|
"start:nodemon": "ts-node -r tsconfig-paths/register src/main.ts",
|
|
38
44
|
"start:debug": "nodemon --config nodemon-debug.json",
|
|
@@ -40,12 +46,12 @@
|
|
|
40
46
|
"start:dev:swc": "nest start -b swc -w --type-check",
|
|
41
47
|
"start:local": "NODE_ENV=local nodemon",
|
|
42
48
|
"start:local:swc": "NODE_ENV=local nest start -b swc -w --type-check",
|
|
43
|
-
"test": "
|
|
44
|
-
"test:ci": "
|
|
45
|
-
"test:e2e": "
|
|
46
|
-
"prepack": "
|
|
47
|
-
"prepublishOnly": "
|
|
48
|
-
"preversion": "
|
|
49
|
+
"test": "pnpm run vitest",
|
|
50
|
+
"test:ci": "pnpm run vitest:ci",
|
|
51
|
+
"test:e2e": "pnpm run vitest",
|
|
52
|
+
"prepack": "pnpm run prestart:prod",
|
|
53
|
+
"prepublishOnly": "pnpm run lint && pnpm run test:ci",
|
|
54
|
+
"preversion": "pnpm run lint",
|
|
49
55
|
"vitest": "NODE_ENV=e2e vitest run --config vitest-e2e.config.ts",
|
|
50
56
|
"vitest:ci": "NODE_ENV=ci vitest run --config vitest-e2e.config.ts",
|
|
51
57
|
"vitest:cov": "NODE_ENV=e2e vitest run --coverage --config vitest-e2e.config.ts",
|
|
@@ -53,6 +59,7 @@
|
|
|
53
59
|
"vitest:unit": "vitest run --config vitest.config.ts",
|
|
54
60
|
"test:unit:watch": "vitest --config vitest.config.ts",
|
|
55
61
|
"test:types": "tsc --noEmit --skipLibCheck -p tests/types/tsconfig.json",
|
|
62
|
+
"test:cleanup": "find tests -type f \\( -name '*.txt' -o -name '*.bin' \\) -not -name '.gitkeep' -delete && echo 'Test artifacts cleaned up'",
|
|
56
63
|
"watch": "npm-watch"
|
|
57
64
|
},
|
|
58
65
|
"repository": {
|
|
@@ -152,8 +159,7 @@
|
|
|
152
159
|
"vite": "7.3.1",
|
|
153
160
|
"vite-plugin-node": "7.0.0",
|
|
154
161
|
"vite-tsconfig-paths": "6.1.0",
|
|
155
|
-
"vitest": "4.0.18"
|
|
156
|
-
"yalc": "1.0.0-pre.53"
|
|
162
|
+
"vitest": "4.0.18"
|
|
157
163
|
},
|
|
158
164
|
"main": "dist/index.js",
|
|
159
165
|
"types": "dist/index.d.ts",
|
|
@@ -169,7 +175,18 @@
|
|
|
169
175
|
"watch": {
|
|
170
176
|
"build:dev": "src"
|
|
171
177
|
},
|
|
172
|
-
"
|
|
173
|
-
|
|
178
|
+
"packageManager": "pnpm@10.29.2",
|
|
179
|
+
"pnpm": {
|
|
180
|
+
"overrides": {
|
|
181
|
+
"lodash": "4.17.23"
|
|
182
|
+
},
|
|
183
|
+
"onlyBuiltDependencies": [
|
|
184
|
+
"bcrypt",
|
|
185
|
+
"@swc/core",
|
|
186
|
+
"esbuild",
|
|
187
|
+
"@nestjs/core",
|
|
188
|
+
"@compodoc/compodoc",
|
|
189
|
+
"@apollo/protobufjs"
|
|
190
|
+
]
|
|
174
191
|
}
|
|
175
192
|
}
|
package/src/config.env.ts
CHANGED
|
@@ -77,7 +77,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
77
77
|
errorCode: {
|
|
78
78
|
autoRegister: false,
|
|
79
79
|
},
|
|
80
|
-
execAfterInit: '
|
|
80
|
+
execAfterInit: 'pnpm run docs:bootstrap',
|
|
81
81
|
filter: {
|
|
82
82
|
maxLimit: null,
|
|
83
83
|
},
|
|
@@ -183,7 +183,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
183
183
|
verificationLink: 'http://localhost:4200/user/verification',
|
|
184
184
|
},
|
|
185
185
|
env: 'development',
|
|
186
|
-
execAfterInit: '
|
|
186
|
+
execAfterInit: 'pnpm run docs:bootstrap',
|
|
187
187
|
filter: {
|
|
188
188
|
maxLimit: null,
|
|
189
189
|
},
|
|
@@ -321,7 +321,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
321
321
|
errorCode: {
|
|
322
322
|
autoRegister: false,
|
|
323
323
|
},
|
|
324
|
-
execAfterInit: '
|
|
324
|
+
execAfterInit: 'pnpm run docs:bootstrap',
|
|
325
325
|
filter: {
|
|
326
326
|
maxLimit: null,
|
|
327
327
|
},
|
|
@@ -439,7 +439,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
439
439
|
errorCode: {
|
|
440
440
|
autoRegister: false,
|
|
441
441
|
},
|
|
442
|
-
execAfterInit: '
|
|
442
|
+
execAfterInit: 'pnpm run docs:bootstrap',
|
|
443
443
|
filter: {
|
|
444
444
|
maxLimit: null,
|
|
445
445
|
},
|
|
@@ -563,7 +563,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
563
563
|
verificationLink: 'http://localhost:4200/user/verification',
|
|
564
564
|
},
|
|
565
565
|
env: 'production',
|
|
566
|
-
execAfterInit: '
|
|
566
|
+
execAfterInit: 'pnpm run docs:bootstrap',
|
|
567
567
|
filter: {
|
|
568
568
|
maxLimit: null,
|
|
569
569
|
},
|
|
@@ -1099,28 +1099,32 @@ export interface IServerOptions {
|
|
|
1099
1099
|
* Configuration of the GraphQL module
|
|
1100
1100
|
* see https://docs.nestjs.com/graphql/quick-start
|
|
1101
1101
|
* and https://www.apollographql.com/docs/apollo-server/api/apollo-server/
|
|
1102
|
+
*
|
|
1103
|
+
* Set to `false` to completely disable GraphQL (no GraphQLModule, no /graphql endpoint).
|
|
1102
1104
|
*/
|
|
1103
|
-
graphQl?:
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1105
|
+
graphQl?:
|
|
1106
|
+
| false
|
|
1107
|
+
| {
|
|
1108
|
+
/**
|
|
1109
|
+
* Driver configuration for Apollo
|
|
1110
|
+
*/
|
|
1111
|
+
driver?: ApolloDriverConfig;
|
|
1108
1112
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
+
/**
|
|
1114
|
+
* Subscription authentication
|
|
1115
|
+
*/
|
|
1116
|
+
enableSubscriptionAuth?: boolean;
|
|
1113
1117
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
+
/**
|
|
1119
|
+
* Maximum complexity of GraphQL requests
|
|
1120
|
+
*/
|
|
1121
|
+
maxComplexity?: number;
|
|
1118
1122
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1123
|
+
/**
|
|
1124
|
+
* Module options (forRootAsync)
|
|
1125
|
+
*/
|
|
1126
|
+
options?: GqlModuleAsyncOptions;
|
|
1127
|
+
};
|
|
1124
1128
|
|
|
1125
1129
|
/**
|
|
1126
1130
|
* Whether to activate health check endpoints
|
package/src/core.module.ts
CHANGED
|
@@ -42,11 +42,15 @@ import { CoreSystemSetupModule } from './core/modules/system-setup/core-system-s
|
|
|
42
42
|
@Global()
|
|
43
43
|
@Module({})
|
|
44
44
|
export class CoreModule implements NestModule {
|
|
45
|
+
private static graphQlEnabled = true;
|
|
46
|
+
|
|
45
47
|
/**
|
|
46
48
|
* Integrate middleware, e.g. GraphQL upload handing for express
|
|
47
49
|
*/
|
|
48
50
|
configure(consumer: MiddlewareConsumer) {
|
|
49
|
-
|
|
51
|
+
if (CoreModule.graphQlEnabled) {
|
|
52
|
+
consumer.apply(graphqlUploadExpress()).forRoutes('graphql');
|
|
53
|
+
}
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/**
|
|
@@ -138,24 +142,35 @@ export class CoreModule implements NestModule {
|
|
|
138
142
|
};
|
|
139
143
|
}
|
|
140
144
|
|
|
145
|
+
// Determine if GraphQL is enabled (false means explicitly disabled)
|
|
146
|
+
const isGraphQlEnabled = options.graphQl !== false;
|
|
147
|
+
CoreModule.graphQlEnabled = isGraphQlEnabled;
|
|
148
|
+
|
|
141
149
|
// Check if autoRegister: false for IAM-only mode (project imports its own BetterAuth module)
|
|
142
150
|
const rawBetterAuth = options?.betterAuth;
|
|
143
151
|
const isAutoRegisterDisabledEarly = typeof rawBetterAuth === 'object' && rawBetterAuth?.autoRegister === false;
|
|
144
152
|
|
|
145
|
-
// Build GraphQL driver configuration based on auth mode
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
153
|
+
// Build GraphQL driver configuration based on auth mode (only if GraphQL is enabled)
|
|
154
|
+
let graphQlDriverConfig = {};
|
|
155
|
+
if (isGraphQlEnabled) {
|
|
156
|
+
graphQlDriverConfig = isIamOnlyMode
|
|
157
|
+
? isAutoRegisterDisabledEarly
|
|
158
|
+
? this.buildLazyIamGraphQlDriver(cors, options)
|
|
159
|
+
: this.buildIamOnlyGraphQlDriver(cors, options)
|
|
160
|
+
: this.buildLegacyGraphQlDriver(AuthService, AuthModule, cors, options);
|
|
161
|
+
}
|
|
151
162
|
|
|
152
163
|
const config: IServerOptions = merge(
|
|
153
164
|
{
|
|
154
165
|
env: 'develop',
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
166
|
+
...(isGraphQlEnabled
|
|
167
|
+
? {
|
|
168
|
+
graphQl: {
|
|
169
|
+
driver: graphQlDriverConfig,
|
|
170
|
+
enableSubscriptionAuth: true,
|
|
171
|
+
},
|
|
172
|
+
}
|
|
173
|
+
: {}),
|
|
159
174
|
mongoose: {
|
|
160
175
|
options: {
|
|
161
176
|
connectionFactory: (connection) => {
|
|
@@ -190,8 +205,8 @@ export class CoreModule implements NestModule {
|
|
|
190
205
|
MailjetService,
|
|
191
206
|
];
|
|
192
207
|
|
|
193
|
-
// Add ComplexityPlugin only if not in Vitest (Vitest has dual GraphQL loading issue)
|
|
194
|
-
if (!process.env.VITEST) {
|
|
208
|
+
// Add ComplexityPlugin only if not in Vitest (Vitest has dual GraphQL loading issue) and GraphQL is enabled
|
|
209
|
+
if (!process.env.VITEST && isGraphQlEnabled) {
|
|
195
210
|
providers.push(ComplexityPlugin);
|
|
196
211
|
}
|
|
197
212
|
|
|
@@ -228,12 +243,15 @@ export class CoreModule implements NestModule {
|
|
|
228
243
|
// and: https://mongoosejs.com/docs/guide.html#strictQuery
|
|
229
244
|
mongoose.set('strictQuery', config.mongoose.strictQuery || false);
|
|
230
245
|
|
|
231
|
-
const imports: any[] = [
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
246
|
+
const imports: any[] = [MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options)];
|
|
247
|
+
|
|
248
|
+
if (isGraphQlEnabled && config.graphQl) {
|
|
249
|
+
imports.push(
|
|
250
|
+
GraphQLModule.forRootAsync<ApolloDriverConfig>(
|
|
251
|
+
Object.assign({ driver: ApolloDriver }, config.graphQl.driver, config.graphQl.options),
|
|
252
|
+
),
|
|
253
|
+
);
|
|
254
|
+
}
|
|
237
255
|
|
|
238
256
|
// Add ErrorCodeModule based on configuration
|
|
239
257
|
// autoRegister defaults to true (backward compatible)
|
|
@@ -311,7 +329,7 @@ export class CoreModule implements NestModule {
|
|
|
311
329
|
|
|
312
330
|
// Set exports
|
|
313
331
|
const exports: any[] = [ConfigService, EmailService, TemplateService, MailjetService];
|
|
314
|
-
if (!process.env.VITEST) {
|
|
332
|
+
if (!process.env.VITEST && isGraphQlEnabled) {
|
|
315
333
|
exports.push(ComplexityPlugin);
|
|
316
334
|
}
|
|
317
335
|
|
|
@@ -335,6 +353,8 @@ export class CoreModule implements NestModule {
|
|
|
335
353
|
* This is the recommended mode for new projects.
|
|
336
354
|
*/
|
|
337
355
|
private static buildIamOnlyGraphQlDriver(cors: object, options: Partial<IServerOptions>) {
|
|
356
|
+
// This method is only called when graphQl !== false, extract config with type narrowing
|
|
357
|
+
const graphQlOpts = typeof options?.graphQl === 'object' ? options.graphQl : undefined;
|
|
338
358
|
return {
|
|
339
359
|
imports: [CoreBetterAuthModule],
|
|
340
360
|
inject: [CoreBetterAuthService, CoreBetterAuthUserMapper],
|
|
@@ -350,7 +370,7 @@ export class CoreModule implements NestModule {
|
|
|
350
370
|
context: ({ extra }) => extra,
|
|
351
371
|
onConnect: async (context: Context<any>) => {
|
|
352
372
|
const { connectionParams, extra } = context;
|
|
353
|
-
const enableAuth =
|
|
373
|
+
const enableAuth = graphQlOpts?.enableSubscriptionAuth ?? true;
|
|
354
374
|
|
|
355
375
|
if (enableAuth) {
|
|
356
376
|
// Get headers from raw headers or connection params
|
|
@@ -385,7 +405,7 @@ export class CoreModule implements NestModule {
|
|
|
385
405
|
},
|
|
386
406
|
'subscriptions-transport-ws': {
|
|
387
407
|
onConnect: async (connectionParams) => {
|
|
388
|
-
const enableAuth =
|
|
408
|
+
const enableAuth = graphQlOpts?.enableSubscriptionAuth ?? true;
|
|
389
409
|
|
|
390
410
|
if (enableAuth) {
|
|
391
411
|
const authToken: string = connectionParams?.Authorization?.split(' ')[1];
|
|
@@ -415,7 +435,7 @@ export class CoreModule implements NestModule {
|
|
|
415
435
|
},
|
|
416
436
|
},
|
|
417
437
|
},
|
|
418
|
-
|
|
438
|
+
graphQlOpts?.driver,
|
|
419
439
|
),
|
|
420
440
|
};
|
|
421
441
|
}
|
|
@@ -430,6 +450,8 @@ export class CoreModule implements NestModule {
|
|
|
430
450
|
* which happens after all modules are initialized.
|
|
431
451
|
*/
|
|
432
452
|
private static buildLazyIamGraphQlDriver(cors: object, options: Partial<IServerOptions>) {
|
|
453
|
+
// This method is only called when graphQl !== false, extract config with type narrowing
|
|
454
|
+
const graphQlOpts = typeof options?.graphQl === 'object' ? options.graphQl : undefined;
|
|
433
455
|
return {
|
|
434
456
|
useFactory: async () =>
|
|
435
457
|
Object.assign(
|
|
@@ -443,7 +465,7 @@ export class CoreModule implements NestModule {
|
|
|
443
465
|
context: ({ extra }) => extra,
|
|
444
466
|
onConnect: async (context: Context<any>) => {
|
|
445
467
|
const { connectionParams, extra } = context;
|
|
446
|
-
const enableAuth =
|
|
468
|
+
const enableAuth = graphQlOpts?.enableSubscriptionAuth ?? true;
|
|
447
469
|
|
|
448
470
|
if (enableAuth) {
|
|
449
471
|
const betterAuthService = CoreBetterAuthModule.getServiceInstance();
|
|
@@ -482,7 +504,7 @@ export class CoreModule implements NestModule {
|
|
|
482
504
|
},
|
|
483
505
|
'subscriptions-transport-ws': {
|
|
484
506
|
onConnect: async (connectionParams) => {
|
|
485
|
-
const enableAuth =
|
|
507
|
+
const enableAuth = graphQlOpts?.enableSubscriptionAuth ?? true;
|
|
486
508
|
|
|
487
509
|
if (enableAuth) {
|
|
488
510
|
const betterAuthService = CoreBetterAuthModule.getServiceInstance();
|
|
@@ -517,7 +539,7 @@ export class CoreModule implements NestModule {
|
|
|
517
539
|
},
|
|
518
540
|
},
|
|
519
541
|
},
|
|
520
|
-
|
|
542
|
+
graphQlOpts?.driver,
|
|
521
543
|
),
|
|
522
544
|
};
|
|
523
545
|
}
|
|
@@ -536,8 +558,9 @@ export class CoreModule implements NestModule {
|
|
|
536
558
|
cors: object,
|
|
537
559
|
options: Partial<IServerOptions>,
|
|
538
560
|
) {
|
|
539
|
-
//
|
|
540
|
-
const
|
|
561
|
+
// This method is only called when graphQl !== false, extract config with type narrowing
|
|
562
|
+
const graphQlOpts = typeof options?.graphQl === 'object' ? options.graphQl : undefined;
|
|
563
|
+
const enableSubscriptionAuth = graphQlOpts?.enableSubscriptionAuth ?? true;
|
|
541
564
|
|
|
542
565
|
return {
|
|
543
566
|
imports: [AuthModule],
|
|
@@ -599,7 +622,7 @@ export class CoreModule implements NestModule {
|
|
|
599
622
|
},
|
|
600
623
|
},
|
|
601
624
|
},
|
|
602
|
-
|
|
625
|
+
graphQlOpts?.driver,
|
|
603
626
|
),
|
|
604
627
|
};
|
|
605
628
|
}
|