@lenne.tech/nest-server 11.0.0 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lenne.tech/nest-server",
3
- "version": "11.0.0",
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",
@@ -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
  };
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';