@lenne.tech/nest-server 10.8.11 → 11.0.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 (31) hide show
  1. package/dist/core/common/decorators/graphql-service-options.decorator.js +5 -0
  2. package/dist/core/common/decorators/graphql-service-options.decorator.js.map +1 -1
  3. package/dist/core/common/decorators/rest-service-options.decorator.d.ts +2 -0
  4. package/dist/core/common/decorators/rest-service-options.decorator.js +14 -0
  5. package/dist/core/common/decorators/rest-service-options.decorator.js.map +1 -0
  6. package/dist/core/common/decorators/translatable.decorator.d.ts +3 -0
  7. package/dist/core/common/decorators/translatable.decorator.js +22 -0
  8. package/dist/core/common/decorators/translatable.decorator.js.map +1 -0
  9. package/dist/core/common/helpers/service.helper.d.ts +1 -0
  10. package/dist/core/common/helpers/service.helper.js +12 -0
  11. package/dist/core/common/helpers/service.helper.js.map +1 -1
  12. package/dist/core/common/services/module.service.js +1 -0
  13. package/dist/core/common/services/module.service.js.map +1 -1
  14. package/dist/core/modules/auth/guards/auth.guard.js.map +1 -1
  15. package/dist/core/modules/auth/services/core-auth.service.js +3 -0
  16. package/dist/core/modules/auth/services/core-auth.service.js.map +1 -1
  17. package/dist/core/modules/auth/strategies/jwt-refresh.strategy.d.ts +1 -1
  18. package/dist/core/modules/auth/strategies/jwt.strategy.d.ts +1 -1
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/tsconfig.build.tsbuildinfo +1 -1
  23. package/package.json +32 -32
  24. package/src/core/common/decorators/graphql-service-options.decorator.ts +8 -0
  25. package/src/core/common/decorators/rest-service-options.decorator.ts +22 -0
  26. package/src/core/common/decorators/translatable.decorator.ts +24 -0
  27. package/src/core/common/helpers/service.helper.ts +16 -0
  28. package/src/core/common/services/module.service.ts +1 -0
  29. package/src/core/modules/auth/guards/auth.guard.ts +2 -2
  30. package/src/core/modules/auth/services/core-auth.service.ts +5 -0
  31. package/src/index.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "10.8.11",
3
+ "version": "11.0.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",
@@ -22,8 +22,8 @@
22
22
  "docs:ci": "ts-node ./scripts/init-server.ts && npm run docs:bootstrap && compodoc -p tsconfig.json",
23
23
  "format": "prettier --write 'src/**/*.ts'",
24
24
  "format:staged": "pretty-quick --staged",
25
- "lint": "eslint './src/**/*.{ts,js,vue}'",
26
- "lint:fix": "eslint './src/**/*.{ts,js,vue}' --fix",
25
+ "lint": "eslint '{src,apps,libs,test}/**/*.{ts,js}' --cache",
26
+ "lint:fix": "eslint '{src,apps,libs,test}/**/*.{ts,js}' --fix --cache",
27
27
  "prestart:prod": "npm run build",
28
28
  "reinit": "rimraf package-lock.json && rimraf node_modules && npm i && npm run lint && npm run test:e2e && npm run test:ci && npm run build",
29
29
  "reinit:clean": "rimraf package-lock.json && rimraf node_modules && npm cache clean --force && npm i && npm run test:e2e && npm run build",
@@ -65,21 +65,21 @@
65
65
  "node": ">= 20"
66
66
  },
67
67
  "dependencies": {
68
- "@apollo/gateway": "2.10.0",
68
+ "@apollo/gateway": "2.10.2",
69
69
  "@getbrevo/brevo": "1.0.1",
70
70
  "@lenne.tech/mongoose-gridfs": "1.4.2",
71
71
  "@lenne.tech/multer-gridfs-storage": "5.0.6",
72
- "@nestjs/apollo": "12.2.2",
73
- "@nestjs/common": "10.4.15",
74
- "@nestjs/core": "10.4.15",
75
- "@nestjs/graphql": "12.2.2",
76
- "@nestjs/jwt": "10.2.0",
77
- "@nestjs/mongoose": "10.1.0",
78
- "@nestjs/passport": "10.0.3",
79
- "@nestjs/platform-express": "10.4.15",
80
- "@nestjs/schedule": "4.1.2",
81
- "@nestjs/swagger": "8.1.1",
82
- "@nestjs/terminus": "10.3.0",
72
+ "@nestjs/apollo": "13.1.0",
73
+ "@nestjs/common": "11.0.17",
74
+ "@nestjs/core": "11.0.17",
75
+ "@nestjs/graphql": "13.1.0",
76
+ "@nestjs/jwt": "11.0.0",
77
+ "@nestjs/mongoose": "11.0.3",
78
+ "@nestjs/passport": "11.0.5",
79
+ "@nestjs/platform-express": "11.0.17",
80
+ "@nestjs/schedule": "5.0.1",
81
+ "@nestjs/swagger": "11.1.3",
82
+ "@nestjs/terminus": "11.0.0",
83
83
  "apollo-server-core": "3.13.0",
84
84
  "apollo-server-express": "3.13.0",
85
85
  "bcrypt": "5.1.1",
@@ -87,10 +87,10 @@
87
87
  "class-validator": "0.14.1",
88
88
  "compression": "1.8.0",
89
89
  "cookie-parser": "1.4.7",
90
- "dotenv": "16.4.7",
90
+ "dotenv": "16.5.0",
91
91
  "ejs": "3.1.10",
92
92
  "graphql": "16.10.0",
93
- "graphql-query-complexity": "1.0.0",
93
+ "graphql-query-complexity": "1.1.0",
94
94
  "graphql-subscriptions": "3.0.0",
95
95
  "graphql-upload": "15.0.2",
96
96
  "js-sha256": "0.11.0",
@@ -101,7 +101,7 @@
101
101
  "mongoose": "7.8.6",
102
102
  "multer": "1.4.5-lts.2",
103
103
  "node-mailjet": "6.0.8",
104
- "nodemailer": "6.10.0",
104
+ "nodemailer": "6.10.1",
105
105
  "nodemon": "3.1.9",
106
106
  "passport": "0.7.0",
107
107
  "passport-jwt": "4.0.1",
@@ -115,11 +115,11 @@
115
115
  "@babel/plugin-proposal-private-methods": "7.18.6",
116
116
  "@compodoc/compodoc": "1.1.26",
117
117
  "@lenne.tech/eslint-config-ts": "1.0.8",
118
- "@nestjs/cli": "10.4.9",
119
- "@nestjs/schematics": "10.2.3",
120
- "@nestjs/testing": "10.4.15",
121
- "@swc/cli": "0.5.2",
122
- "@swc/core": "1.11.13",
118
+ "@nestjs/cli": "11.0.6",
119
+ "@nestjs/schematics": "11.0.5",
120
+ "@nestjs/testing": "11.0.17",
121
+ "@swc/cli": "0.6.0",
122
+ "@swc/core": "1.11.21",
123
123
  "@swc/jest": "0.2.37",
124
124
  "@types/compression": "1.7.5",
125
125
  "@types/cookie-parser": "1.4.8",
@@ -128,15 +128,15 @@
128
128
  "@types/jest": "29.5.14",
129
129
  "@types/lodash": "4.17.16",
130
130
  "@types/multer": "1.4.12",
131
- "@types/node": "22.13.14",
131
+ "@types/node": "22.14.1",
132
132
  "@types/nodemailer": "6.4.17",
133
133
  "@types/passport": "1.0.17",
134
134
  "@types/supertest": "6.0.3",
135
- "@typescript-eslint/eslint-plugin": "8.28.0",
136
- "@typescript-eslint/parser": "8.28.0",
135
+ "@typescript-eslint/eslint-plugin": "8.30.1",
136
+ "@typescript-eslint/parser": "8.30.1",
137
137
  "coffeescript": "2.7.0",
138
- "eslint": "9.23.0",
139
- "eslint-config-prettier": "9.1.0",
138
+ "eslint": "9.24.0",
139
+ "eslint-config-prettier": "10.1.2",
140
140
  "eslint-plugin-unused-imports": "4.1.4",
141
141
  "find-file-up": "2.0.1",
142
142
  "grunt": "1.6.1",
@@ -147,16 +147,16 @@
147
147
  "husky": "9.1.7",
148
148
  "jest": "29.7.0",
149
149
  "npm-watch": "0.13.0",
150
- "pm2": "5.4.3",
150
+ "pm2": "6.0.5",
151
151
  "prettier": "3.5.3",
152
152
  "pretty-quick": "4.1.1",
153
153
  "supertest": "7.1.0",
154
- "ts-jest": "29.3.0",
154
+ "ts-jest": "29.3.2",
155
155
  "ts-loader": "9.5.2",
156
- "ts-morph": "24.0.0",
156
+ "ts-morph": "25.0.1",
157
157
  "ts-node": "10.9.2",
158
158
  "tsconfig-paths": "4.2.0",
159
- "typescript": "5.8.2",
159
+ "typescript": "5.8.3",
160
160
  "yalc": "1.0.0-pre.53"
161
161
  },
162
162
  "overrides": {
@@ -1,4 +1,5 @@
1
1
  import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+ import { GqlExecutionContext } from '@nestjs/graphql';
2
3
 
3
4
  import { currentUserDec, graphqlPopulateDec } from '../helpers/decorator.helper';
4
5
  import { ServiceOptions } from '../interfaces/service-options.interface';
@@ -8,6 +9,7 @@ import { ServiceOptions } from '../interfaces/service-options.interface';
8
9
  *
9
10
  * Includes following properties of ServiceOptions:
10
11
  * - currentUser
12
+ * - language
11
13
  * - populate
12
14
  *
13
15
  * Configuration via Decorator data:
@@ -22,8 +24,14 @@ import { ServiceOptions } from '../interfaces/service-options.interface';
22
24
  */
23
25
  export const GraphQLServiceOptions = createParamDecorator(
24
26
  (data: { gqlPath?: string; ignoreSelections?: boolean }, ctx: ExecutionContext): ServiceOptions => {
27
+ const gqlContext = GqlExecutionContext.create(ctx);
28
+ const request = gqlContext.getContext().req;
29
+
30
+ const language = request?.headers?.['accept-language'];
31
+
25
32
  return {
26
33
  currentUser: currentUserDec(null, ctx),
34
+ language,
27
35
  populate: graphqlPopulateDec(data, ctx),
28
36
  };
29
37
  },
@@ -0,0 +1,22 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+
3
+ import { currentUserDec } from '../helpers/decorator.helper';
4
+ import { ServiceOptions } from '../interfaces/service-options.interface';
5
+
6
+ /**
7
+ * Get standard ServiceOptions for REST-Requests
8
+ *
9
+ * Includes following properties of ServiceOptions:
10
+ * - currentUser
11
+ * - language
12
+ */
13
+ export const RESTServiceOptions = createParamDecorator((ctx: ExecutionContext): ServiceOptions => {
14
+ const request = ctx.switchToHttp().getRequest();
15
+
16
+ const language = request?.headers?.['accept-language'];
17
+
18
+ return {
19
+ currentUser: currentUserDec(null, ctx),
20
+ language,
21
+ };
22
+ });
@@ -0,0 +1,24 @@
1
+ import 'reflect-metadata';
2
+
3
+ const TRANSLATABLE_KEY = 'custom:translatable';
4
+
5
+ export function getTranslatablePropertyKeys(target: unknown): string[] {
6
+ // for classes
7
+ if (typeof target === 'function') {
8
+ return Reflect.getMetadata(TRANSLATABLE_KEY, target) || [];
9
+ }
10
+
11
+ // for instances
12
+ if (typeof target === 'object' && target.constructor) {
13
+ return Reflect.getMetadata(TRANSLATABLE_KEY, target.constructor) || [];
14
+ }
15
+
16
+ return [];
17
+ }
18
+
19
+ export function Translatable(): PropertyDecorator {
20
+ return (target: object, propertyKey: string | symbol) => {
21
+ const existingProperties: string[] = Reflect.getMetadata(TRANSLATABLE_KEY, target.constructor) || [];
22
+ Reflect.defineMetadata(TRANSLATABLE_KEY, [...existingProperties, propertyKey], target.constructor);
23
+ };
24
+ }
@@ -3,6 +3,7 @@ import { plainToInstance } from 'class-transformer';
3
3
  import { sha256 } from 'js-sha256';
4
4
  import { Types } from 'mongoose';
5
5
 
6
+ import { getTranslatablePropertyKeys } from '../decorators/translatable.decorator';
6
7
  import { RoleEnum } from '../enums/role.enum';
7
8
  import { PrepareInputOptions } from '../interfaces/prepare-input-options.interface';
8
9
  import { PrepareOutputOptions } from '../interfaces/prepare-output-options.interface';
@@ -187,6 +188,7 @@ export async function prepareOutput<T = { [key: string]: any; map: (...args: any
187
188
  circles?: boolean;
188
189
  clone?: boolean;
189
190
  getNewArray?: boolean;
191
+ language?: string;
190
192
  objectIdsToStrings?: boolean;
191
193
  proto?: boolean;
192
194
  removeSecrets?: boolean;
@@ -273,6 +275,20 @@ export async function prepareOutput<T = { [key: string]: any; map: (...args: any
273
275
  }
274
276
  }
275
277
 
278
+ // Add translated values of current selected language if _translations object exists
279
+ if (config.targetModel && config.language && typeof output === 'object' && '_translations' in output) {
280
+ const translation = output._translations?.[options.language];
281
+
282
+ if (typeof translation === 'object') {
283
+ const keys = getTranslatablePropertyKeys(config.targetModel);
284
+ for (const key of keys) {
285
+ if (translation[key] != null) {
286
+ output[key] = translation[key];
287
+ }
288
+ }
289
+ }
290
+ }
291
+
276
292
  // Return prepared output
277
293
  return output;
278
294
  }
@@ -258,6 +258,7 @@ export abstract class ModuleService<T extends CoreModel = any> {
258
258
  */
259
259
  async prepareOutput(output: any, options: ServiceOptions = {}) {
260
260
  const config = {
261
+ language: options?.language,
261
262
  targetModel: this.mainModelConstructor,
262
263
  ...options?.prepareOutput,
263
264
  };
@@ -49,7 +49,7 @@ const createPassportContext = (request, response) => (type, options, callback: (
49
49
  * Can be removed when pull request is merged:
50
50
  * https://github.com/nestjs/passport/pull/66
51
51
  */
52
- function createAuthGuard(type?: string): Type<CanActivate> {
52
+ function createAuthGuard(type?: AuthGuardStrategy | string | string[]): Type<IAuthGuard> {
53
53
  class MixinAuthGuard<TUser = any> {
54
54
  /**
55
55
  * Integrate options
@@ -127,7 +127,7 @@ function createAuthGuard(type?: string): Type<CanActivate> {
127
127
  }
128
128
  }
129
129
 
130
- const guard = mixin(MixinAuthGuard);
130
+ const guard = mixin<MixinAuthGuard>(MixinAuthGuard);
131
131
  return guard;
132
132
  }
133
133
 
@@ -89,6 +89,11 @@ export class CoreAuthService {
89
89
  * User sign in via email
90
90
  */
91
91
  async signIn(input: CoreAuthSignInInput, serviceOptions?: ServiceOptions): Promise<CoreAuthModel> {
92
+ // Check input
93
+ if (!input) {
94
+ throw new BadRequestException('Missing input');
95
+ }
96
+
92
97
  // Prepare service options
93
98
  const serviceOptionsForUserService = prepareServiceOptions(serviceOptions, {
94
99
  // We need password, so we can't use prepare output handling and have to deactivate it
package/src/index.ts CHANGED
@@ -14,9 +14,11 @@ export * from './core/common/decorators/current-user.decorator';
14
14
  export * from './core/common/decorators/graphql-populate.decorator';
15
15
  export * from './core/common/decorators/graphql-service-options.decorator';
16
16
  export * from './core/common/decorators/graphql-user.decorator';
17
+ export * from './core/common/decorators/rest-service-options.decorator';
17
18
  export * from './core/common/decorators/rest-user.decorator';
18
19
  export * from './core/common/decorators/restricted.decorator';
19
20
  export * from './core/common/decorators/roles.decorator';
21
+ export * from './core/common/decorators/translatable.decorator';
20
22
  export * from './core/common/enums/comparison-operator.enum';
21
23
  export * from './core/common/enums/logical-operator.enum';
22
24
  export * from './core/common/enums/process-type.enum';