@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.14.1",
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 && npm run build:copy-types && npm run build:copy-templates && npm run build:add-type-references",
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": "npm pack && echo 'use file:/ROOT_PATH_TO_TGZ_FILE to integrate the package'",
22
- "build:dev": "npm run build && yalc push --private",
23
- "docs": "npm run docs:ci && open http://127.0.0.1:8080/ && open ./public/index.html && compodoc -p tsconfig.json -s ",
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 && npm run docs:bootstrap && compodoc -p tsconfig.json",
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": "npm run build",
31
- "reinit": "rimraf package-lock.json && rimraf node_modules && npm i && npm run lint && npm run test:e2e && npm run test:ci && npm run build",
32
- "reinit:clean": "rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i && npm run test:e2e && npm run build",
33
- "reinit:force": "rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i --force && npm run test:e2e",
34
- "reinit:legacy": "rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i --legacy-peer-deps && npm run test:e2e",
35
- "start": "npm run start:local",
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": "npm run vitest",
44
- "test:ci": "npm run vitest:ci",
45
- "test:e2e": "npm run vitest",
46
- "prepack": "npm run prestart:prod",
47
- "prepublishOnly": "npm run lint && npm run test:ci",
48
- "preversion": "npm run lint",
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
- "overrides": {
173
- "lodash": "4.17.23"
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: 'npm run docs:bootstrap',
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: 'npm run docs:bootstrap',
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: 'npm run docs:bootstrap',
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: 'npm run docs:bootstrap',
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: 'npm run docs:bootstrap',
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
- * Driver configuration for Apollo
1106
- */
1107
- driver?: ApolloDriverConfig;
1105
+ graphQl?:
1106
+ | false
1107
+ | {
1108
+ /**
1109
+ * Driver configuration for Apollo
1110
+ */
1111
+ driver?: ApolloDriverConfig;
1108
1112
 
1109
- /**
1110
- * Subscription authentication
1111
- */
1112
- enableSubscriptionAuth?: boolean;
1113
+ /**
1114
+ * Subscription authentication
1115
+ */
1116
+ enableSubscriptionAuth?: boolean;
1113
1117
 
1114
- /**
1115
- * Maximum complexity of GraphQL requests
1116
- */
1117
- maxComplexity?: number;
1118
+ /**
1119
+ * Maximum complexity of GraphQL requests
1120
+ */
1121
+ maxComplexity?: number;
1118
1122
 
1119
- /**
1120
- * Module options (forRootAsync)
1121
- */
1122
- options?: GqlModuleAsyncOptions;
1123
- };
1123
+ /**
1124
+ * Module options (forRootAsync)
1125
+ */
1126
+ options?: GqlModuleAsyncOptions;
1127
+ };
1124
1128
 
1125
1129
  /**
1126
1130
  * Whether to activate health check endpoints
@@ -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
- consumer.apply(graphqlUploadExpress()).forRoutes('graphql');
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
- const graphQlDriverConfig = isIamOnlyMode
147
- ? isAutoRegisterDisabledEarly
148
- ? this.buildLazyIamGraphQlDriver(cors, options)
149
- : this.buildIamOnlyGraphQlDriver(cors, options)
150
- : this.buildLegacyGraphQlDriver(AuthService, AuthModule, cors, options);
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
- graphQl: {
156
- driver: graphQlDriverConfig,
157
- enableSubscriptionAuth: true,
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
- MongooseModule.forRoot(config.mongoose.uri, config.mongoose.options),
233
- GraphQLModule.forRootAsync<ApolloDriverConfig>(
234
- Object.assign({ driver: ApolloDriver }, config.graphQl.driver, config.graphQl.options),
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 = options?.graphQl?.enableSubscriptionAuth ?? true;
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 = options?.graphQl?.enableSubscriptionAuth ?? true;
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
- options?.graphQl?.driver,
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 = options?.graphQl?.enableSubscriptionAuth ?? true;
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 = options?.graphQl?.enableSubscriptionAuth ?? true;
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
- options?.graphQl?.driver,
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
- // Store config reference for use in callbacks
540
- const enableSubscriptionAuth = options?.graphQl?.enableSubscriptionAuth ?? true;
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
- options?.graphQl?.driver,
625
+ graphQlOpts?.driver,
603
626
  ),
604
627
  };
605
628
  }