@lenne.tech/nest-server 11.6.2 → 11.7.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.
Files changed (136) hide show
  1. package/dist/config.env.js +19 -12
  2. package/dist/config.env.js.map +1 -1
  3. package/dist/core/common/helpers/filter.helper.d.ts +9 -9
  4. package/dist/core/common/helpers/filter.helper.js +2 -4
  5. package/dist/core/common/helpers/filter.helper.js.map +1 -1
  6. package/dist/core/common/helpers/gridfs.helper.js +3 -3
  7. package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
  8. package/dist/core/common/interfaces/server-options.interface.d.ts +21 -3
  9. package/dist/core/common/services/crud.service.d.ts +16 -16
  10. package/dist/core/common/services/crud.service.js +1 -1
  11. package/dist/core/common/services/crud.service.js.map +1 -1
  12. package/dist/core/modules/auth/core-auth.controller.d.ts +1 -0
  13. package/dist/core/modules/auth/core-auth.controller.js +28 -2
  14. package/dist/core/modules/auth/core-auth.controller.js.map +1 -1
  15. package/dist/core/modules/auth/core-auth.module.js +14 -1
  16. package/dist/core/modules/auth/core-auth.module.js.map +1 -1
  17. package/dist/core/modules/auth/core-auth.resolver.d.ts +1 -0
  18. package/dist/core/modules/auth/core-auth.resolver.js +20 -2
  19. package/dist/core/modules/auth/core-auth.resolver.js.map +1 -1
  20. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.d.ts +4 -0
  21. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js +17 -0
  22. package/dist/core/modules/auth/exceptions/legacy-auth-disabled.exception.js.map +1 -0
  23. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.d.ts +9 -0
  24. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js +74 -0
  25. package/dist/core/modules/auth/guards/legacy-auth-rate-limit.guard.js.map +1 -0
  26. package/dist/core/modules/auth/interfaces/auth-provider.interface.d.ts +7 -0
  27. package/dist/core/modules/auth/interfaces/auth-provider.interface.js +5 -0
  28. package/dist/core/modules/auth/interfaces/auth-provider.interface.js.map +1 -0
  29. package/dist/core/modules/auth/interfaces/core-auth-user.interface.d.ts +1 -0
  30. package/dist/core/modules/auth/services/core-auth.service.d.ts +10 -1
  31. package/dist/core/modules/auth/services/core-auth.service.js +141 -9
  32. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  33. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.d.ts +31 -0
  34. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js +153 -0
  35. package/dist/core/modules/auth/services/legacy-auth-rate-limiter.service.js.map +1 -0
  36. package/dist/core/modules/better-auth/better-auth-migration-status.model.d.ts +10 -0
  37. package/dist/core/modules/better-auth/better-auth-migration-status.model.js +57 -0
  38. package/dist/core/modules/better-auth/better-auth-migration-status.model.js.map +1 -0
  39. package/dist/core/modules/better-auth/better-auth-models.d.ts +0 -1
  40. package/dist/core/modules/better-auth/better-auth-models.js +0 -4
  41. package/dist/core/modules/better-auth/better-auth-models.js.map +1 -1
  42. package/dist/core/modules/better-auth/better-auth-user.mapper.d.ts +33 -0
  43. package/dist/core/modules/better-auth/better-auth-user.mapper.js +443 -0
  44. package/dist/core/modules/better-auth/better-auth-user.mapper.js.map +1 -1
  45. package/dist/core/modules/better-auth/better-auth.config.js +3 -0
  46. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  47. package/dist/core/modules/better-auth/better-auth.module.d.ts +10 -2
  48. package/dist/core/modules/better-auth/better-auth.module.js +40 -52
  49. package/dist/core/modules/better-auth/better-auth.module.js.map +1 -1
  50. package/dist/core/modules/better-auth/better-auth.resolver.d.ts +8 -12
  51. package/dist/core/modules/better-auth/better-auth.resolver.js +33 -351
  52. package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
  53. package/dist/core/modules/better-auth/better-auth.service.d.ts +0 -1
  54. package/dist/core/modules/better-auth/better-auth.service.js +0 -3
  55. package/dist/core/modules/better-auth/better-auth.service.js.map +1 -1
  56. package/dist/core/modules/better-auth/better-auth.types.d.ts +9 -8
  57. package/dist/core/modules/better-auth/better-auth.types.js +14 -3
  58. package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
  59. package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +67 -0
  60. package/dist/core/modules/better-auth/core-better-auth.controller.js +504 -0
  61. package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -0
  62. package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +61 -0
  63. package/dist/core/modules/better-auth/core-better-auth.resolver.js +552 -0
  64. package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -0
  65. package/dist/core/modules/better-auth/index.d.ts +3 -0
  66. package/dist/core/modules/better-auth/index.js +3 -0
  67. package/dist/core/modules/better-auth/index.js.map +1 -1
  68. package/dist/core/modules/user/core-user.service.d.ts +7 -1
  69. package/dist/core/modules/user/core-user.service.js +57 -3
  70. package/dist/core/modules/user/core-user.service.js.map +1 -1
  71. package/dist/core/modules/user/interfaces/core-user-service-options.interface.d.ts +4 -0
  72. package/dist/core/modules/user/interfaces/core-user-service-options.interface.js +3 -0
  73. package/dist/core/modules/user/interfaces/core-user-service-options.interface.js.map +1 -0
  74. package/dist/core.module.d.ts +3 -0
  75. package/dist/core.module.js +132 -54
  76. package/dist/core.module.js.map +1 -1
  77. package/dist/index.d.ts +5 -0
  78. package/dist/index.js +5 -0
  79. package/dist/index.js.map +1 -1
  80. package/dist/server/modules/auth/auth.resolver.js +2 -0
  81. package/dist/server/modules/auth/auth.resolver.js.map +1 -1
  82. package/dist/server/modules/better-auth/better-auth.controller.d.ts +10 -0
  83. package/dist/server/modules/better-auth/better-auth.controller.js +36 -0
  84. package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -0
  85. package/dist/server/modules/better-auth/better-auth.module.d.ts +9 -0
  86. package/dist/server/modules/better-auth/better-auth.module.js +44 -0
  87. package/dist/server/modules/better-auth/better-auth.module.js.map +1 -0
  88. package/dist/server/modules/better-auth/better-auth.resolver.d.ts +47 -0
  89. package/dist/server/modules/better-auth/better-auth.resolver.js +234 -0
  90. package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -0
  91. package/dist/server/modules/file/file-info.model.d.ts +71 -3
  92. package/dist/server/modules/user/user.model.d.ts +169 -3
  93. package/dist/server/modules/user/user.service.d.ts +3 -1
  94. package/dist/server/modules/user/user.service.js +7 -3
  95. package/dist/server/modules/user/user.service.js.map +1 -1
  96. package/dist/server/server.module.js +6 -1
  97. package/dist/server/server.module.js.map +1 -1
  98. package/dist/tsconfig.build.tsbuildinfo +1 -1
  99. package/package.json +20 -29
  100. package/src/config.env.ts +34 -13
  101. package/src/core/common/helpers/filter.helper.ts +15 -17
  102. package/src/core/common/helpers/gridfs.helper.ts +5 -5
  103. package/src/core/common/interfaces/server-options.interface.ts +222 -14
  104. package/src/core/common/services/crud.service.ts +22 -22
  105. package/src/core/modules/auth/core-auth.controller.ts +93 -5
  106. package/src/core/modules/auth/core-auth.module.ts +15 -1
  107. package/src/core/modules/auth/core-auth.resolver.ts +70 -2
  108. package/src/core/modules/auth/exceptions/legacy-auth-disabled.exception.ts +35 -0
  109. package/src/core/modules/auth/guards/legacy-auth-rate-limit.guard.ts +109 -0
  110. package/src/core/modules/auth/interfaces/auth-provider.interface.ts +86 -0
  111. package/src/core/modules/auth/interfaces/core-auth-user.interface.ts +6 -0
  112. package/src/core/modules/auth/services/core-auth.service.ts +245 -6
  113. package/src/core/modules/auth/services/legacy-auth-rate-limiter.service.ts +283 -0
  114. package/src/core/modules/better-auth/INTEGRATION-CHECKLIST.md +254 -0
  115. package/src/core/modules/better-auth/README.md +698 -54
  116. package/src/core/modules/better-auth/better-auth-migration-status.model.ts +73 -0
  117. package/src/core/modules/better-auth/better-auth-models.ts +0 -3
  118. package/src/core/modules/better-auth/better-auth-user.mapper.ts +805 -0
  119. package/src/core/modules/better-auth/better-auth.config.ts +5 -0
  120. package/src/core/modules/better-auth/better-auth.module.ts +107 -66
  121. package/src/core/modules/better-auth/better-auth.resolver.ts +88 -553
  122. package/src/core/modules/better-auth/better-auth.service.ts +0 -9
  123. package/src/core/modules/better-auth/better-auth.types.ts +25 -10
  124. package/src/core/modules/better-auth/core-better-auth.controller.ts +646 -0
  125. package/src/core/modules/better-auth/core-better-auth.resolver.ts +730 -0
  126. package/src/core/modules/better-auth/index.ts +9 -1
  127. package/src/core/modules/user/core-user.service.ts +131 -4
  128. package/src/core/modules/user/interfaces/core-user-service-options.interface.ts +15 -0
  129. package/src/core.module.ts +257 -74
  130. package/src/index.ts +5 -0
  131. package/src/server/modules/auth/auth.resolver.ts +8 -0
  132. package/src/server/modules/better-auth/better-auth.controller.ts +41 -0
  133. package/src/server/modules/better-auth/better-auth.module.ts +88 -0
  134. package/src/server/modules/better-auth/better-auth.resolver.ts +210 -0
  135. package/src/server/modules/user/user.service.ts +4 -2
  136. package/src/server/server.module.ts +10 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.6.2",
3
+ "version": "11.7.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",
@@ -77,13 +77,14 @@
77
77
  "node": ">= 20"
78
78
  },
79
79
  "dependencies": {
80
- "@apollo/server": "4.12.2",
81
- "@better-auth/passkey": "1.4.7",
80
+ "@apollo/server": "5.2.0",
81
+ "@as-integrations/express5": "1.1.2",
82
+ "@better-auth/passkey": "1.4.8-beta.4",
82
83
  "@getbrevo/brevo": "3.0.1",
83
- "@nestjs/apollo": "13.1.0",
84
+ "@nestjs/apollo": "13.2.3",
84
85
  "@nestjs/common": "11.1.9",
85
86
  "@nestjs/core": "11.1.9",
86
- "@nestjs/graphql": "13.2.0",
87
+ "@nestjs/graphql": "13.2.3",
87
88
  "@nestjs/jwt": "11.0.2",
88
89
  "@nestjs/mongoose": "11.0.4",
89
90
  "@nestjs/passport": "11.0.5",
@@ -92,16 +93,16 @@
92
93
  "@nestjs/swagger": "11.2.3",
93
94
  "@nestjs/terminus": "11.0.0",
94
95
  "@nestjs/websockets": "11.1.9",
95
- "@thallesp/nestjs-better-auth": "2.2.0",
96
96
  "apollo-server-core": "3.13.0",
97
97
  "bcrypt": "6.0.0",
98
- "better-auth": "1.4.7",
98
+ "better-auth": "1.4.8-beta.4",
99
99
  "class-transformer": "0.5.1",
100
100
  "class-validator": "0.14.3",
101
101
  "compression": "1.8.1",
102
102
  "cookie-parser": "1.4.7",
103
103
  "dotenv": "17.2.3",
104
104
  "ejs": "3.1.10",
105
+ "express": "5.1.0",
105
106
  "graphql": "16.12.0",
106
107
  "graphql-query-complexity": "1.1.0",
107
108
  "graphql-subscriptions": "3.0.0",
@@ -110,7 +111,7 @@
110
111
  "json-to-graphql-query": "2.3.0",
111
112
  "lodash": "4.17.21",
112
113
  "mongodb": "7.0.0",
113
- "mongoose": "8.19.3",
114
+ "mongoose": "9.0.2",
114
115
  "multer": "2.0.2",
115
116
  "node-mailjet": "6.0.11",
116
117
  "nodemailer": "7.0.11",
@@ -119,7 +120,6 @@
119
120
  "reflect-metadata": "0.2.2",
120
121
  "rfdc": "1.4.1",
121
122
  "rxjs": "7.8.2",
122
- "ts-jest": "29.4.6",
123
123
  "yuml-diagram": "1.2.0"
124
124
  },
125
125
  "devDependencies": {
@@ -129,23 +129,23 @@
129
129
  "@nestjs/schematics": "11.0.9",
130
130
  "@nestjs/testing": "11.1.9",
131
131
  "@swc/cli": "0.7.9",
132
- "@swc/core": "1.15.3",
132
+ "@swc/core": "1.15.7",
133
133
  "@types/compression": "1.8.1",
134
134
  "@types/cookie-parser": "1.4.10",
135
135
  "@types/ejs": "3.1.5",
136
136
  "@types/express": "4.17.21",
137
137
  "@types/lodash": "4.17.21",
138
138
  "@types/multer": "2.0.0",
139
- "@types/node": "25.0.1",
139
+ "@types/node": "25.0.3",
140
140
  "@types/nodemailer": "7.0.4",
141
141
  "@types/passport": "1.0.17",
142
142
  "@types/supertest": "6.0.3",
143
- "@typescript-eslint/eslint-plugin": "8.49.0",
144
- "@typescript-eslint/parser": "8.49.0",
145
- "@vitest/coverage-v8": "4.0.15",
146
- "@vitest/ui": "4.0.15",
143
+ "@typescript-eslint/eslint-plugin": "8.50.0",
144
+ "@typescript-eslint/parser": "8.50.0",
145
+ "@vitest/coverage-v8": "4.0.16",
146
+ "@vitest/ui": "4.0.16",
147
147
  "ansi-colors": "4.1.3",
148
- "eslint": "9.39.1",
148
+ "eslint": "9.39.2",
149
149
  "eslint-config-prettier": "10.1.8",
150
150
  "eslint-plugin-unused-imports": "4.3.0",
151
151
  "find-file-up": "2.0.1",
@@ -162,28 +162,19 @@
162
162
  "pretty-quick": "4.2.2",
163
163
  "rimraf": "6.1.2",
164
164
  "supertest": "7.1.4",
165
+ "ts-jest": "29.4.6",
165
166
  "ts-loader": "9.5.4",
166
167
  "ts-morph": "27.0.2",
167
168
  "ts-node": "10.9.2",
168
169
  "tsconfig-paths": "4.2.0",
169
170
  "typescript": "5.9.3",
170
171
  "unplugin-swc": "1.5.9",
171
- "vite": "7.2.7",
172
+ "vite": "7.3.0",
172
173
  "vite-plugin-node": "7.0.0",
173
- "vite-tsconfig-paths": "5.1.4",
174
- "vitest": "4.0.15",
174
+ "vite-tsconfig-paths": "6.0.3",
175
+ "vitest": "4.0.16",
175
176
  "yalc": "1.0.0-pre.53"
176
177
  },
177
- "overrides": {
178
- "@lykmapipo/common": {
179
- "flat": "5.0.2",
180
- "mime": "2.6.0"
181
- },
182
- "better-auth": {
183
- "mongodb": "7.0.0"
184
- },
185
- "ts-morph": "27.0.2"
186
- },
187
178
  "jest": {
188
179
  "collectCoverage": true,
189
180
  "coverageDirectory": "../coverage",
package/src/config.env.ts CHANGED
@@ -14,6 +14,16 @@ const config: { [env: string]: IServerOptions } = {
14
14
  // Development environment
15
15
  // ===========================================================================
16
16
  development: {
17
+ // Legacy Auth endpoint controls (for migration to BetterAuth)
18
+ // Set to false after all users have migrated to BetterAuth (IAM)
19
+ // See: .claude/rules/module-deprecation.md
20
+ auth: {
21
+ legacyEndpoints: {
22
+ enabled: true, // Set to false to disable legacy auth endpoints (returns HTTP 410)
23
+ // graphql: true, // Optionally disable only GraphQL endpoints
24
+ // rest: true, // Optionally disable only REST endpoints
25
+ },
26
+ },
17
27
  automaticObjectIdFiltering: true,
18
28
  betterAuth: {
19
29
  basePath: '/iam',
@@ -23,9 +33,6 @@ const config: { [env: string]: IServerOptions } = {
23
33
  enabled: true,
24
34
  expiresIn: '15m',
25
35
  },
26
- legacyPassword: {
27
- enabled: true,
28
- },
29
36
  passkey: {
30
37
  enabled: false,
31
38
  origin: 'http://localhost:3000',
@@ -165,27 +172,34 @@ const config: { [env: string]: IServerOptions } = {
165
172
  // Local environment
166
173
  // ===========================================================================
167
174
  local: {
175
+ // Legacy Auth endpoint controls (for migration to BetterAuth)
176
+ // Set to false after all users have migrated to BetterAuth (IAM)
177
+ // See: .claude/rules/module-deprecation.md
178
+ auth: {
179
+ legacyEndpoints: {
180
+ enabled: true, // Set to false to disable legacy auth endpoints (returns HTTP 410)
181
+ // graphql: true, // Optionally disable only GraphQL endpoints
182
+ // rest: true, // Optionally disable only REST endpoints
183
+ },
184
+ },
168
185
  automaticObjectIdFiltering: true,
169
186
  betterAuth: {
170
187
  basePath: '/iam',
171
188
  baseUrl: 'http://localhost:3000',
172
- // enabled: true by default - set false to explicitly disable
189
+ enabled: true, // Enable for Scenario 2 (Legacy + IAM) testing
173
190
  jwt: {
174
191
  enabled: true,
175
192
  expiresIn: '15m',
176
193
  },
177
- legacyPassword: {
178
- enabled: true,
179
- },
180
194
  passkey: {
181
- enabled: false,
195
+ enabled: true,
182
196
  origin: 'http://localhost:3000',
183
197
  rpId: 'localhost',
184
198
  rpName: 'Nest Server Local',
185
199
  },
186
200
  rateLimit: {
187
201
  enabled: true,
188
- max: 20,
202
+ max: 100, // Higher limit for local testing
189
203
  message: 'Too many requests, please try again later.',
190
204
  skipEndpoints: ['/session', '/callback'],
191
205
  strictEndpoints: ['/sign-in', '/sign-up', '/forgot-password', '/reset-password'],
@@ -211,7 +225,7 @@ const config: { [env: string]: IServerOptions } = {
211
225
  },
212
226
  twoFactor: {
213
227
  appName: 'Nest Server Local',
214
- enabled: false,
228
+ enabled: true,
215
229
  },
216
230
  },
217
231
  compression: true,
@@ -327,6 +341,16 @@ const config: { [env: string]: IServerOptions } = {
327
341
  // Production environment
328
342
  // ===========================================================================
329
343
  production: {
344
+ // Legacy Auth endpoint controls (for migration to BetterAuth)
345
+ // Set to false after all users have migrated to BetterAuth (IAM)
346
+ // See: .claude/rules/module-deprecation.md
347
+ auth: {
348
+ legacyEndpoints: {
349
+ enabled: process.env.LEGACY_AUTH_ENABLED !== 'false', // Disable via env var
350
+ // graphql: true, // Optionally disable only GraphQL endpoints
351
+ // rest: true, // Optionally disable only REST endpoints
352
+ },
353
+ },
330
354
  automaticObjectIdFiltering: true,
331
355
  betterAuth: {
332
356
  basePath: '/iam',
@@ -336,9 +360,6 @@ const config: { [env: string]: IServerOptions } = {
336
360
  enabled: true,
337
361
  expiresIn: '15m',
338
362
  },
339
- legacyPassword: {
340
- enabled: true,
341
- },
342
363
  passkey: {
343
364
  enabled: false,
344
365
  origin: process.env.BETTER_AUTH_URL || 'https://example.com',
@@ -1,4 +1,4 @@
1
- import { FilterQuery, QueryOptions } from 'mongoose';
1
+ import { QueryFilter, QueryOptions } from 'mongoose';
2
2
 
3
3
  import { FilterArgs } from '../args/filter.args';
4
4
  import { ComparisonOperatorEnum } from '../enums/comparison-operator.enum';
@@ -19,14 +19,14 @@ export class Filter {
19
19
  * Convert filter arguments to a query array
20
20
  * @param filterArgs
21
21
  */
22
- public static convertFilterArgsToQuery<T = any>(filterArgs: Partial<FilterArgs>): [FilterQuery<T>, QueryOptions] {
23
- return convertFilterArgsToQuery(filterArgs);
22
+ public static convertFilterArgsToQuery<T = Record<string, any>>(filterArgs: Partial<FilterArgs>): [T, QueryOptions] {
23
+ return convertFilterArgsToQuery<T>(filterArgs);
24
24
  }
25
25
 
26
26
  /**
27
27
  * Generate filter query
28
28
  */
29
- public static generateFilterQuery<T = any>(filter?: Partial<FilterInput>): any | FilterQuery<T> {
29
+ public static generateFilterQuery<T = any>(filter?: Partial<FilterInput>): any | QueryFilter<T> {
30
30
  return generateFilterQuery(filter);
31
31
  }
32
32
 
@@ -41,31 +41,29 @@ export class Filter {
41
41
  /**
42
42
  * Convert filter arguments to a query array
43
43
  */
44
- export function convertFilterArgsToQuery<T = any>(filterArgs: Partial<FilterArgs>): [FilterQuery<T>, QueryOptions] {
45
- return [generateFilterQuery(filterArgs?.filter), generateFindOptions(filterArgs)];
44
+ export function convertFilterArgsToQuery<T = Record<string, any>>(filterArgs: Partial<FilterArgs>): [T, QueryOptions] {
45
+ return [generateFilterQuery(filterArgs?.filter) as T, generateFindOptions(filterArgs)];
46
46
  }
47
47
 
48
48
  /**
49
49
  * Merge FilterArgs and FilterQueries
50
50
  */
51
- export function filterMerge<T = unknown>(
51
+ export function filterMerge<T = Record<string, any>>(
52
52
  filterArgs: Partial<FilterArgs>,
53
- filterQuery: Partial<FilterQuery<T>>,
53
+ filterQuery: Partial<T>,
54
54
  options?: {
55
55
  operator?: '$and' | '$nor' | '$or';
56
56
  queryOptions?: Partial<QueryOptions>;
57
57
  samples?: number;
58
58
  },
59
- ): { filterQuery: FilterQuery<T>; queryOptions?: QueryOptions; samples?: number } {
59
+ ): { filterQuery: T; queryOptions?: QueryOptions; samples?: number } {
60
60
  const config = {
61
61
  operator: '$and',
62
62
  ...options,
63
63
  };
64
64
  const converted = convertFilterArgsToQuery(filterArgs);
65
65
  return {
66
- filterQuery: (converted[0]
67
- ? { [config.operator]: [converted[0], filterQuery || {}] }
68
- : filterQuery) as FilterQuery<T>,
66
+ filterQuery: (converted[0] ? { [config.operator]: [converted[0], filterQuery || {}] } : filterQuery) as T,
69
67
  queryOptions: converted[1] || config.queryOptions ? { ...converted[1], ...config.queryOptions } : undefined,
70
68
  samples: config.samples,
71
69
  };
@@ -76,18 +74,18 @@ export function filterMerge<T = unknown>(
76
74
  */
77
75
  export function findFilter(options?: {
78
76
  conditions?: Record<string, any>[];
79
- filterOptions?: FilterQuery<any>;
77
+ filterOptions?: QueryFilter<any>;
80
78
  id?: any;
81
79
  ids?: any[];
82
80
  type?: '$and' | '$nor' | '$or';
83
- }): FilterQuery<any> {
81
+ }): QueryFilter<any> {
84
82
  const config = {
85
83
  type: '$and',
86
84
  ...options,
87
85
  };
88
86
 
89
87
  // Init filter Option
90
- let filterOptions: FilterQuery<any> = config?.filterOptions;
88
+ let filterOptions: QueryFilter<any> = config?.filterOptions;
91
89
 
92
90
  // Check where condition
93
91
  if (!filterOptions) {
@@ -120,7 +118,7 @@ export function findFilter(options?: {
120
118
  }
121
119
 
122
120
  // Filter falsy values
123
- filterOptions[config.type] = filterOptions[config.type].filter(value => value);
121
+ filterOptions[config.type] = filterOptions[config.type].filter((value) => value);
124
122
 
125
123
  // Optimizations
126
124
  if (!filterOptions[config.type].length) {
@@ -143,7 +141,7 @@ export function findFilter(options?: {
143
141
  export function generateFilterQuery<T = any>(
144
142
  filter?: Partial<FilterInput>,
145
143
  options?: { automaticObjectIdFiltering?: boolean },
146
- ): any | FilterQuery<T> {
144
+ ): any | QueryFilter<T> {
147
145
  // Check filter
148
146
  if (!filter) {
149
147
  return undefined;
@@ -166,7 +166,7 @@ export class GridFSHelper {
166
166
  */
167
167
  static async findFiles(bucket: GridFSBucket, filter: any = {}, options: any = {}): Promise<GridFSFileInfo[]> {
168
168
  const files = await bucket.find(filter, options).toArray();
169
- return files.map(file => GridFSHelper.normalizeFileInfo(file));
169
+ return files.map((file) => GridFSHelper.normalizeFileInfo(file));
170
170
  }
171
171
 
172
172
  /**
@@ -200,12 +200,12 @@ export class GridFSHelper {
200
200
  filename: string,
201
201
  options?: { contentType?: string },
202
202
  ): mongo.GridFSBucketWriteStream {
203
- // Store contentType in metadata to avoid deprecation warning
203
+ // Store contentType in metadata (mongodb 7.x no longer has contentType option)
204
204
  if (options?.contentType) {
205
205
  const metadata = { contentType: options.contentType };
206
206
  return bucket.openUploadStream(filename, { metadata });
207
207
  }
208
- return bucket.openUploadStream(filename, options);
208
+ return bucket.openUploadStream(filename);
209
209
  }
210
210
 
211
211
  /**
@@ -217,11 +217,11 @@ export class GridFSHelper {
217
217
  filename: string,
218
218
  options?: { contentType?: string },
219
219
  ): mongo.GridFSBucketWriteStream {
220
- // Store contentType in metadata to avoid deprecation warning
220
+ // Store contentType in metadata (mongodb 7.x no longer has contentType option)
221
221
  if (options?.contentType) {
222
222
  const metadata = { contentType: options.contentType };
223
223
  return bucket.openUploadStreamWithId(id, filename, { metadata });
224
224
  }
225
- return bucket.openUploadStreamWithId(id, filename, options);
225
+ return bucket.openUploadStreamWithId(id, filename);
226
226
  }
227
227
  }
@@ -22,6 +22,170 @@ import { MailjetOptions } from './mailjet-options.interface';
22
22
  */
23
23
  export type BetterAuthFieldType = 'boolean' | 'date' | 'json' | 'number' | 'number[]' | 'string' | 'string[]';
24
24
 
25
+ /**
26
+ * Interface for Auth configuration
27
+ *
28
+ * This configuration controls the authentication system behavior.
29
+ * In v11.x, Legacy Auth (CoreAuthService) is the default.
30
+ * In a future version, BetterAuth (IAM) will become the default.
31
+ *
32
+ * @since 11.7.1
33
+ *
34
+ * ## Migration Roadmap
35
+ *
36
+ * ### v11.x (Current)
37
+ * - Legacy Auth is the default and required for GraphQL Subscriptions
38
+ * - BetterAuth can be used alongside Legacy Auth
39
+ * - Use `legacyEndpoints.enabled: false` after all users migrated to IAM
40
+ *
41
+ * ### Future Version (Planned)
42
+ * - BetterAuth becomes the default
43
+ * - Legacy Auth becomes optional (must be explicitly enabled)
44
+ * - CoreModule.forRoot signature simplifies to `CoreModule.forRoot(options)`
45
+ *
46
+ * @see https://github.com/lenneTech/nest-server/blob/develop/.claude/rules/module-deprecation.md
47
+ */
48
+ export interface IAuth {
49
+ /**
50
+ * Configuration for legacy auth endpoints
51
+ *
52
+ * Legacy endpoints include:
53
+ * - GraphQL: signIn, signUp, signOut, refreshToken mutations
54
+ * - REST: /api/auth/* endpoints
55
+ *
56
+ * These can be disabled once all users have migrated to BetterAuth (IAM).
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * auth: {
61
+ * legacyEndpoints: {
62
+ * enabled: false // Disable all legacy endpoints after migration
63
+ * }
64
+ * }
65
+ * ```
66
+ */
67
+ legacyEndpoints?: IAuthLegacyEndpoints;
68
+
69
+ /**
70
+ * Prevent user enumeration via unified error messages
71
+ *
72
+ * When enabled, authentication errors return a generic "Invalid credentials"
73
+ * message instead of specific messages like "Unknown email" or "Wrong password".
74
+ *
75
+ * This prevents attackers from determining whether an email address exists
76
+ * in the system, but reduces UX clarity for legitimate users.
77
+ *
78
+ * @since 11.7.x
79
+ * @default false (backward compatible - specific error messages)
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * auth: {
84
+ * preventUserEnumeration: true // Returns "Invalid credentials" for all auth errors
85
+ * }
86
+ * ```
87
+ */
88
+ preventUserEnumeration?: boolean;
89
+
90
+ /**
91
+ * Rate limiting configuration for Legacy Auth endpoints
92
+ *
93
+ * Protects against brute-force attacks on signIn, signUp, and other
94
+ * authentication endpoints.
95
+ *
96
+ * Follows the same pattern as `betterAuth.rateLimit`.
97
+ *
98
+ * @since 11.7.x
99
+ * @default { enabled: false }
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * auth: {
104
+ * rateLimit: {
105
+ * enabled: true,
106
+ * max: 10,
107
+ * windowSeconds: 60,
108
+ * message: 'Too many login attempts, please try again later.',
109
+ * }
110
+ * }
111
+ * ```
112
+ */
113
+ rateLimit?: IAuthRateLimit;
114
+ }
115
+
116
+ /**
117
+ * Interface for Legacy Auth endpoints configuration
118
+ *
119
+ * These endpoints are part of the Legacy Auth system (CoreAuthService).
120
+ * In a future version, BetterAuth (IAM) will become the default and these endpoints
121
+ * can be disabled once all users have migrated.
122
+ *
123
+ * @since 11.7.1
124
+ * @see https://github.com/lenneTech/nest-server/blob/develop/.claude/rules/module-deprecation.md
125
+ */
126
+ export interface IAuthLegacyEndpoints {
127
+ /**
128
+ * Whether legacy auth endpoints are enabled.
129
+ *
130
+ * Set to false to disable all legacy auth endpoints (GraphQL and REST).
131
+ * Use this after all users have migrated to BetterAuth (IAM).
132
+ *
133
+ * Check migration status via the `betterAuthMigrationStatus` query.
134
+ *
135
+ * @default true
136
+ */
137
+ enabled?: boolean;
138
+
139
+ /**
140
+ * Whether legacy GraphQL auth endpoints are enabled.
141
+ * Affects: signIn, signUp, signOut, refreshToken mutations
142
+ *
143
+ * @default true (inherits from `enabled`)
144
+ */
145
+ graphql?: boolean;
146
+
147
+ /**
148
+ * Whether legacy REST auth endpoints are enabled.
149
+ * Affects: /api/auth/sign-in, /api/auth/sign-up, etc.
150
+ *
151
+ * @default true (inherits from `enabled`)
152
+ */
153
+ rest?: boolean;
154
+ }
155
+
156
+ /**
157
+ * Interface for Legacy Auth rate limiting configuration
158
+ *
159
+ * Same structure as IBetterAuthRateLimit for consistency.
160
+ *
161
+ * @since 11.7.x
162
+ */
163
+ export interface IAuthRateLimit {
164
+ /**
165
+ * Whether rate limiting is enabled
166
+ * @default false
167
+ */
168
+ enabled?: boolean;
169
+
170
+ /**
171
+ * Maximum number of requests within the time window
172
+ * @default 10
173
+ */
174
+ max?: number;
175
+
176
+ /**
177
+ * Custom message when rate limit is exceeded
178
+ * @default 'Too many requests, please try again later.'
179
+ */
180
+ message?: string;
181
+
182
+ /**
183
+ * Time window in seconds
184
+ * @default 60
185
+ */
186
+ windowSeconds?: number;
187
+ }
188
+
25
189
  /**
26
190
  * Interface for better-auth configuration
27
191
  */
@@ -41,6 +205,40 @@ export interface IBetterAuth {
41
205
  */
42
206
  additionalUserFields?: Record<string, IBetterAuthUserField>;
43
207
 
208
+ /**
209
+ * Whether BetterAuthModule should be auto-registered in CoreModule.
210
+ *
211
+ * When false (default), projects integrate BetterAuth via an extended module
212
+ * in their project (e.g., `src/server/modules/better-auth/better-auth.module.ts`).
213
+ * This follows the same pattern as Legacy Auth and allows for custom resolvers,
214
+ * controllers, and project-specific authentication logic.
215
+ *
216
+ * Set to true only for simple projects that don't need customization.
217
+ *
218
+ * @default false
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * // Recommended: Extend BetterAuthModule in your project
223
+ * // src/server/modules/better-auth/better-auth.module.ts
224
+ * import { BetterAuthModule as CoreBetterAuthModule } from '@lenne.tech/nest-server';
225
+ *
226
+ * @Module({})
227
+ * export class BetterAuthModule {
228
+ * static forRoot(options) {
229
+ * return {
230
+ * imports: [CoreBetterAuthModule.forRoot(options)],
231
+ * // Add custom providers, controllers, etc.
232
+ * };
233
+ * }
234
+ * }
235
+ *
236
+ * // Then import in ServerModule
237
+ * import { BetterAuthModule } from './modules/better-auth/better-auth.module';
238
+ * ```
239
+ */
240
+ autoRegister?: boolean;
241
+
44
242
  /**
45
243
  * Base path for better-auth endpoints
46
244
  * default: '/iam'
@@ -53,6 +251,19 @@ export interface IBetterAuth {
53
251
  */
54
252
  baseUrl?: string;
55
253
 
254
+ /**
255
+ * Email/password authentication configuration.
256
+ * Enabled by default.
257
+ * Set `enabled: false` to explicitly disable email/password auth.
258
+ */
259
+ emailAndPassword?: {
260
+ /**
261
+ * Whether email/password authentication is enabled.
262
+ * @default true
263
+ */
264
+ enabled?: boolean;
265
+ };
266
+
56
267
  /**
57
268
  * Whether better-auth is enabled.
58
269
  * BetterAuth is enabled by default (zero-config philosophy).
@@ -80,20 +291,6 @@ export interface IBetterAuth {
80
291
  expiresIn?: string;
81
292
  };
82
293
 
83
- /**
84
- * Legacy password handling configuration.
85
- * Used during migration from old auth system.
86
- * Enabled by default when this config block is present.
87
- * Set `enabled: false` to explicitly disable.
88
- */
89
- legacyPassword?: {
90
- /**
91
- * Whether legacy password handling is enabled.
92
- * @default true (when legacyPassword config block is present)
93
- */
94
- enabled?: boolean;
95
- };
96
-
97
294
  /**
98
295
  * Advanced Better-Auth options passthrough.
99
296
  * These options are passed directly to Better-Auth, allowing full customization.
@@ -380,6 +577,17 @@ export interface IJwt {
380
577
  * Options for the server
381
578
  */
382
579
  export interface IServerOptions {
580
+ /**
581
+ * Authentication system configuration
582
+ *
583
+ * Controls Legacy Auth endpoints and behavior.
584
+ * In a future version, this will also control BetterAuth as the default system.
585
+ *
586
+ * @since 11.7.1
587
+ * @see IAuth
588
+ */
589
+ auth?: IAuth;
590
+
383
591
  /**
384
592
  * Automatically detect ObjectIds in string values in FilterQueries
385
593
  * and expand them as OR query with string and ObjectId.