@lenne.tech/nest-server 11.6.2 → 11.7.0
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/dist/config.env.js +2 -11
- package/dist/config.env.js.map +1 -1
- package/dist/core/common/helpers/filter.helper.d.ts +9 -9
- package/dist/core/common/helpers/filter.helper.js +2 -4
- package/dist/core/common/helpers/filter.helper.js.map +1 -1
- package/dist/core/common/helpers/gridfs.helper.js +3 -3
- package/dist/core/common/helpers/gridfs.helper.js.map +1 -1
- package/dist/core/common/interfaces/server-options.interface.d.ts +4 -3
- package/dist/core/common/services/crud.service.d.ts +16 -16
- package/dist/core/common/services/crud.service.js +1 -1
- package/dist/core/common/services/crud.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth-models.d.ts +0 -1
- package/dist/core/modules/better-auth/better-auth-models.js +0 -4
- package/dist/core/modules/better-auth/better-auth-models.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.config.js +3 -0
- package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.module.d.ts +10 -2
- package/dist/core/modules/better-auth/better-auth.module.js +40 -52
- package/dist/core/modules/better-auth/better-auth.module.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.resolver.d.ts +8 -12
- package/dist/core/modules/better-auth/better-auth.resolver.js +33 -351
- package/dist/core/modules/better-auth/better-auth.resolver.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.service.d.ts +0 -1
- package/dist/core/modules/better-auth/better-auth.service.js +0 -3
- package/dist/core/modules/better-auth/better-auth.service.js.map +1 -1
- package/dist/core/modules/better-auth/better-auth.types.d.ts +9 -8
- package/dist/core/modules/better-auth/better-auth.types.js +14 -3
- package/dist/core/modules/better-auth/better-auth.types.js.map +1 -1
- package/dist/core/modules/better-auth/core-better-auth.controller.d.ts +66 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js +491 -0
- package/dist/core/modules/better-auth/core-better-auth.controller.js.map +1 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.d.ts +59 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js +538 -0
- package/dist/core/modules/better-auth/core-better-auth.resolver.js.map +1 -0
- package/dist/core/modules/better-auth/index.d.ts +2 -0
- package/dist/core/modules/better-auth/index.js +2 -0
- package/dist/core/modules/better-auth/index.js.map +1 -1
- package/dist/core.module.js +1 -1
- package/dist/core.module.js.map +1 -1
- package/dist/server/modules/better-auth/better-auth.controller.d.ts +10 -0
- package/dist/server/modules/better-auth/better-auth.controller.js +36 -0
- package/dist/server/modules/better-auth/better-auth.controller.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.module.d.ts +9 -0
- package/dist/server/modules/better-auth/better-auth.module.js +44 -0
- package/dist/server/modules/better-auth/better-auth.module.js.map +1 -0
- package/dist/server/modules/better-auth/better-auth.resolver.d.ts +45 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js +221 -0
- package/dist/server/modules/better-auth/better-auth.resolver.js.map +1 -0
- package/dist/server/modules/file/file-info.model.d.ts +71 -3
- package/dist/server/modules/user/user.model.d.ts +169 -3
- package/dist/server/server.module.js +6 -1
- package/dist/server/server.module.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +20 -29
- package/src/config.env.ts +2 -11
- package/src/core/common/helpers/filter.helper.ts +15 -17
- package/src/core/common/helpers/gridfs.helper.ts +5 -5
- package/src/core/common/interfaces/server-options.interface.ts +47 -14
- package/src/core/common/services/crud.service.ts +22 -22
- package/src/core/modules/better-auth/README.md +365 -39
- package/src/core/modules/better-auth/better-auth-models.ts +0 -3
- package/src/core/modules/better-auth/better-auth.config.ts +5 -0
- package/src/core/modules/better-auth/better-auth.module.ts +107 -66
- package/src/core/modules/better-auth/better-auth.resolver.ts +88 -553
- package/src/core/modules/better-auth/better-auth.service.ts +0 -9
- package/src/core/modules/better-auth/better-auth.types.ts +25 -10
- package/src/core/modules/better-auth/core-better-auth.controller.ts +605 -0
- package/src/core/modules/better-auth/core-better-auth.resolver.ts +705 -0
- package/src/core/modules/better-auth/index.ts +8 -1
- package/src/core.module.ts +3 -2
- package/src/server/modules/better-auth/better-auth.controller.ts +41 -0
- package/src/server/modules/better-auth/better-auth.module.ts +88 -0
- package/src/server/modules/better-auth/better-auth.resolver.ts +201 -0
- 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.
|
|
3
|
+
"version": "11.7.0",
|
|
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": "
|
|
81
|
-
"@
|
|
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.
|
|
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.
|
|
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.
|
|
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": "
|
|
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.
|
|
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.
|
|
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.
|
|
144
|
-
"@typescript-eslint/parser": "8.
|
|
145
|
-
"@vitest/coverage-v8": "4.0.
|
|
146
|
-
"@vitest/ui": "4.0.
|
|
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.
|
|
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.
|
|
172
|
+
"vite": "7.3.0",
|
|
172
173
|
"vite-plugin-node": "7.0.0",
|
|
173
|
-
"vite-tsconfig-paths": "
|
|
174
|
-
"vitest": "4.0.
|
|
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
|
@@ -23,9 +23,6 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
23
23
|
enabled: true,
|
|
24
24
|
expiresIn: '15m',
|
|
25
25
|
},
|
|
26
|
-
legacyPassword: {
|
|
27
|
-
enabled: true,
|
|
28
|
-
},
|
|
29
26
|
passkey: {
|
|
30
27
|
enabled: false,
|
|
31
28
|
origin: 'http://localhost:3000',
|
|
@@ -174,11 +171,8 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
174
171
|
enabled: true,
|
|
175
172
|
expiresIn: '15m',
|
|
176
173
|
},
|
|
177
|
-
legacyPassword: {
|
|
178
|
-
enabled: true,
|
|
179
|
-
},
|
|
180
174
|
passkey: {
|
|
181
|
-
enabled:
|
|
175
|
+
enabled: true,
|
|
182
176
|
origin: 'http://localhost:3000',
|
|
183
177
|
rpId: 'localhost',
|
|
184
178
|
rpName: 'Nest Server Local',
|
|
@@ -211,7 +205,7 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
211
205
|
},
|
|
212
206
|
twoFactor: {
|
|
213
207
|
appName: 'Nest Server Local',
|
|
214
|
-
enabled:
|
|
208
|
+
enabled: true,
|
|
215
209
|
},
|
|
216
210
|
},
|
|
217
211
|
compression: true,
|
|
@@ -336,9 +330,6 @@ const config: { [env: string]: IServerOptions } = {
|
|
|
336
330
|
enabled: true,
|
|
337
331
|
expiresIn: '15m',
|
|
338
332
|
},
|
|
339
|
-
legacyPassword: {
|
|
340
|
-
enabled: true,
|
|
341
|
-
},
|
|
342
333
|
passkey: {
|
|
343
334
|
enabled: false,
|
|
344
335
|
origin: process.env.BETTER_AUTH_URL || 'https://example.com',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
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 |
|
|
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
|
|
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 =
|
|
51
|
+
export function filterMerge<T = Record<string, any>>(
|
|
52
52
|
filterArgs: Partial<FilterArgs>,
|
|
53
|
-
filterQuery: Partial<
|
|
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:
|
|
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?:
|
|
77
|
+
filterOptions?: QueryFilter<any>;
|
|
80
78
|
id?: any;
|
|
81
79
|
ids?: any[];
|
|
82
80
|
type?: '$and' | '$nor' | '$or';
|
|
83
|
-
}):
|
|
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:
|
|
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 |
|
|
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
|
|
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
|
|
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
|
|
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
|
|
225
|
+
return bucket.openUploadStreamWithId(id, filename);
|
|
226
226
|
}
|
|
227
227
|
}
|
|
@@ -41,6 +41,40 @@ export interface IBetterAuth {
|
|
|
41
41
|
*/
|
|
42
42
|
additionalUserFields?: Record<string, IBetterAuthUserField>;
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Whether BetterAuthModule should be auto-registered in CoreModule.
|
|
46
|
+
*
|
|
47
|
+
* When false (default), projects integrate BetterAuth via an extended module
|
|
48
|
+
* in their project (e.g., `src/server/modules/better-auth/better-auth.module.ts`).
|
|
49
|
+
* This follows the same pattern as Legacy Auth and allows for custom resolvers,
|
|
50
|
+
* controllers, and project-specific authentication logic.
|
|
51
|
+
*
|
|
52
|
+
* Set to true only for simple projects that don't need customization.
|
|
53
|
+
*
|
|
54
|
+
* @default false
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* // Recommended: Extend BetterAuthModule in your project
|
|
59
|
+
* // src/server/modules/better-auth/better-auth.module.ts
|
|
60
|
+
* import { BetterAuthModule as CoreBetterAuthModule } from '@lenne.tech/nest-server';
|
|
61
|
+
*
|
|
62
|
+
* @Module({})
|
|
63
|
+
* export class BetterAuthModule {
|
|
64
|
+
* static forRoot(options) {
|
|
65
|
+
* return {
|
|
66
|
+
* imports: [CoreBetterAuthModule.forRoot(options)],
|
|
67
|
+
* // Add custom providers, controllers, etc.
|
|
68
|
+
* };
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* // Then import in ServerModule
|
|
73
|
+
* import { BetterAuthModule } from './modules/better-auth/better-auth.module';
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
autoRegister?: boolean;
|
|
77
|
+
|
|
44
78
|
/**
|
|
45
79
|
* Base path for better-auth endpoints
|
|
46
80
|
* default: '/iam'
|
|
@@ -53,6 +87,19 @@ export interface IBetterAuth {
|
|
|
53
87
|
*/
|
|
54
88
|
baseUrl?: string;
|
|
55
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Email/password authentication configuration.
|
|
92
|
+
* Enabled by default.
|
|
93
|
+
* Set `enabled: false` to explicitly disable email/password auth.
|
|
94
|
+
*/
|
|
95
|
+
emailAndPassword?: {
|
|
96
|
+
/**
|
|
97
|
+
* Whether email/password authentication is enabled.
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
enabled?: boolean;
|
|
101
|
+
};
|
|
102
|
+
|
|
56
103
|
/**
|
|
57
104
|
* Whether better-auth is enabled.
|
|
58
105
|
* BetterAuth is enabled by default (zero-config philosophy).
|
|
@@ -80,20 +127,6 @@ export interface IBetterAuth {
|
|
|
80
127
|
expiresIn?: string;
|
|
81
128
|
};
|
|
82
129
|
|
|
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
130
|
/**
|
|
98
131
|
* Advanced Better-Auth options passthrough.
|
|
99
132
|
* These options are passed directly to Better-Auth, allowing full customization.
|
|
@@ -2,10 +2,10 @@ import { NotFoundException } from '@nestjs/common';
|
|
|
2
2
|
import {
|
|
3
3
|
AggregateOptions,
|
|
4
4
|
Document,
|
|
5
|
-
FilterQuery,
|
|
6
5
|
Model as MongooseModel,
|
|
7
6
|
PipelineStage,
|
|
8
7
|
Query,
|
|
8
|
+
QueryFilter,
|
|
9
9
|
QueryOptions,
|
|
10
10
|
} from 'mongoose';
|
|
11
11
|
|
|
@@ -147,7 +147,7 @@ export abstract class CrudService<
|
|
|
147
147
|
* Get items via filter
|
|
148
148
|
*/
|
|
149
149
|
async find(
|
|
150
|
-
filter?: FilterArgs | { filterQuery?:
|
|
150
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
151
151
|
serviceOptions?: ServiceOptions,
|
|
152
152
|
): Promise<Model[]> {
|
|
153
153
|
// If filter is not instance of FilterArgs a simple form with filterQuery and queryOptions is set
|
|
@@ -191,7 +191,7 @@ export abstract class CrudService<
|
|
|
191
191
|
* Warning: Disables the handling of rights and restrictions!
|
|
192
192
|
*/
|
|
193
193
|
async findForce(
|
|
194
|
-
filter?: FilterArgs | { filterQuery?:
|
|
194
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
195
195
|
serviceOptions: ServiceOptions = {},
|
|
196
196
|
): Promise<Model[]> {
|
|
197
197
|
serviceOptions = serviceOptions || {};
|
|
@@ -204,7 +204,7 @@ export abstract class CrudService<
|
|
|
204
204
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
205
205
|
*/
|
|
206
206
|
async findRaw(
|
|
207
|
-
filter?: FilterArgs | { filterQuery?:
|
|
207
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
208
208
|
serviceOptions: ServiceOptions = {},
|
|
209
209
|
): Promise<Model[]> {
|
|
210
210
|
serviceOptions = serviceOptions || {};
|
|
@@ -216,7 +216,7 @@ export abstract class CrudService<
|
|
|
216
216
|
* Get items and total count via filter
|
|
217
217
|
*/
|
|
218
218
|
async findAndCount(
|
|
219
|
-
filter?: FilterArgs | { filterQuery?:
|
|
219
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
220
220
|
serviceOptions?: ServiceOptions,
|
|
221
221
|
): Promise<{ items: Model[]; totalCount: number }> {
|
|
222
222
|
// If filter is not instance of FilterArgs a simple form with filterQuery and queryOptions is set
|
|
@@ -280,10 +280,10 @@ export abstract class CrudService<
|
|
|
280
280
|
|
|
281
281
|
// Find and process db items
|
|
282
282
|
const collation = serviceOptions?.collation || ConfigService.get('mongoose.collation');
|
|
283
|
-
const dbResult
|
|
284
|
-
|
|
283
|
+
const dbResult =
|
|
284
|
+
(await this.mainDbModel.aggregate(aggregation, collation ? { collation } : {}).exec())[0] || {};
|
|
285
285
|
dbResult.totalCount = dbResult.totalCount?.[0]?.total || 0;
|
|
286
|
-
dbResult.items = dbResult.items?.map(item => this.mainDbModel.hydrate(item)) || [];
|
|
286
|
+
dbResult.items = dbResult.items?.map((item) => this.mainDbModel.hydrate(item)) || [];
|
|
287
287
|
return dbResult;
|
|
288
288
|
},
|
|
289
289
|
{ input: filter, outputPath: 'items', serviceOptions },
|
|
@@ -295,7 +295,7 @@ export abstract class CrudService<
|
|
|
295
295
|
* Warning: Disables the handling of rights and restrictions!
|
|
296
296
|
*/
|
|
297
297
|
async findAndCountForce(
|
|
298
|
-
filter?: FilterArgs | { filterQuery?:
|
|
298
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
299
299
|
serviceOptions: ServiceOptions = {},
|
|
300
300
|
): Promise<{ items: Model[]; totalCount: number }> {
|
|
301
301
|
serviceOptions.raw = true;
|
|
@@ -307,7 +307,7 @@ export abstract class CrudService<
|
|
|
307
307
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
308
308
|
*/
|
|
309
309
|
async findAndCountRaw(
|
|
310
|
-
filter?: FilterArgs | { filterQuery?:
|
|
310
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
311
311
|
serviceOptions: ServiceOptions = {},
|
|
312
312
|
): Promise<{ items: Model[]; totalCount: number }> {
|
|
313
313
|
serviceOptions = serviceOptions || {};
|
|
@@ -319,7 +319,7 @@ export abstract class CrudService<
|
|
|
319
319
|
* Find and update
|
|
320
320
|
*/
|
|
321
321
|
async findAndUpdate(
|
|
322
|
-
filter: FilterArgs | { filterQuery?:
|
|
322
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
323
323
|
update: PlainObject<UpdateInput>,
|
|
324
324
|
serviceOptions?: ServiceOptions,
|
|
325
325
|
): Promise<Model[]> {
|
|
@@ -348,7 +348,7 @@ export abstract class CrudService<
|
|
|
348
348
|
* Warning: Disables the handling of rights and restrictions!
|
|
349
349
|
*/
|
|
350
350
|
async findAndUpdateForce(
|
|
351
|
-
filter: FilterArgs | { filterQuery?:
|
|
351
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
352
352
|
update: PlainObject<UpdateInput>,
|
|
353
353
|
serviceOptions: ServiceOptions = {},
|
|
354
354
|
): Promise<Model[]> {
|
|
@@ -362,7 +362,7 @@ export abstract class CrudService<
|
|
|
362
362
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
363
363
|
*/
|
|
364
364
|
async findAndUpdateRaw(
|
|
365
|
-
filter: FilterArgs | { filterQuery?:
|
|
365
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
366
366
|
update: PlainObject<UpdateInput>,
|
|
367
367
|
serviceOptions: ServiceOptions = {},
|
|
368
368
|
): Promise<Model[]> {
|
|
@@ -375,7 +375,7 @@ export abstract class CrudService<
|
|
|
375
375
|
* Find one item via filter
|
|
376
376
|
*/
|
|
377
377
|
async findOne(
|
|
378
|
-
filter?: FilterArgs | { filterQuery?:
|
|
378
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
379
379
|
serviceOptions?: ServiceOptions,
|
|
380
380
|
): Promise<Model> {
|
|
381
381
|
// If filter is not instance of FilterArgs a simple form with filterQuery and queryOptions is set
|
|
@@ -414,7 +414,7 @@ export abstract class CrudService<
|
|
|
414
414
|
* Warning: Disables the handling of rights and restrictions!
|
|
415
415
|
*/
|
|
416
416
|
async findOneForce(
|
|
417
|
-
filter?: FilterArgs | { filterQuery?:
|
|
417
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
418
418
|
serviceOptions: ServiceOptions = {},
|
|
419
419
|
): Promise<Model> {
|
|
420
420
|
serviceOptions = serviceOptions || {};
|
|
@@ -427,7 +427,7 @@ export abstract class CrudService<
|
|
|
427
427
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
428
428
|
*/
|
|
429
429
|
async findOneRaw(
|
|
430
|
-
filter?: FilterArgs | { filterQuery?:
|
|
430
|
+
filter?: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions; samples?: number },
|
|
431
431
|
serviceOptions: ServiceOptions = {},
|
|
432
432
|
): Promise<Model> {
|
|
433
433
|
serviceOptions = serviceOptions || {};
|
|
@@ -452,7 +452,7 @@ export abstract class CrudService<
|
|
|
452
452
|
* CRUD alias for find
|
|
453
453
|
*/
|
|
454
454
|
async read(
|
|
455
|
-
filter: FilterArgs | { filterQuery?:
|
|
455
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
456
456
|
serviceOptions?: ServiceOptions,
|
|
457
457
|
): Promise<Model[]>;
|
|
458
458
|
|
|
@@ -460,7 +460,7 @@ export abstract class CrudService<
|
|
|
460
460
|
* CRUD alias for get or find
|
|
461
461
|
*/
|
|
462
462
|
async read(
|
|
463
|
-
input: FilterArgs | string | { filterQuery?:
|
|
463
|
+
input: FilterArgs | string | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
464
464
|
serviceOptions?: ServiceOptions,
|
|
465
465
|
): Promise<Model | Model[]> {
|
|
466
466
|
if (typeof input === 'string') {
|
|
@@ -481,7 +481,7 @@ export abstract class CrudService<
|
|
|
481
481
|
* Warning: Disables the handling of rights and restrictions!
|
|
482
482
|
*/
|
|
483
483
|
async readForce(
|
|
484
|
-
filter: FilterArgs | { filterQuery?:
|
|
484
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
485
485
|
serviceOptions?: ServiceOptions,
|
|
486
486
|
): Promise<Model[]>;
|
|
487
487
|
|
|
@@ -490,7 +490,7 @@ export abstract class CrudService<
|
|
|
490
490
|
* Warning: Disables the handling of rights and restrictions!
|
|
491
491
|
*/
|
|
492
492
|
async readForce(
|
|
493
|
-
input: FilterArgs | string | { filterQuery?:
|
|
493
|
+
input: FilterArgs | string | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
494
494
|
serviceOptions?: ServiceOptions,
|
|
495
495
|
): Promise<Model | Model[]> {
|
|
496
496
|
if (typeof input === 'string') {
|
|
@@ -511,7 +511,7 @@ export abstract class CrudService<
|
|
|
511
511
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
512
512
|
*/
|
|
513
513
|
async readRaw(
|
|
514
|
-
filter: FilterArgs | { filterQuery?:
|
|
514
|
+
filter: FilterArgs | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
515
515
|
serviceOptions?: ServiceOptions,
|
|
516
516
|
): Promise<Model[]>;
|
|
517
517
|
|
|
@@ -520,7 +520,7 @@ export abstract class CrudService<
|
|
|
520
520
|
* Warning: Disables the handling of rights and restrictions! The raw data may contain secrets (such as passwords).
|
|
521
521
|
*/
|
|
522
522
|
async readRaw(
|
|
523
|
-
input: FilterArgs | string | { filterQuery?:
|
|
523
|
+
input: FilterArgs | string | { filterQuery?: QueryFilter<any>; queryOptions?: QueryOptions },
|
|
524
524
|
serviceOptions?: ServiceOptions,
|
|
525
525
|
): Promise<Model | Model[]> {
|
|
526
526
|
if (typeof input === 'string') {
|