Как настроить отдельный DTO, отличный от Persistable Model, в Loopback 4 - PullRequest
0 голосов
/ 28 ноября 2018

Рассмотрим эту модель lb4

@model({
  name: 'users'
})
export class User extends Entity {
  @property({
    type: 'number',
    id: true,
  })
  id: number;

  @property({
    type: 'string',
    required: true,
  })
  first_name: string;

  @property({
    type: 'string',
  })
  middle_name?: string;

  @property({
    type: 'string',
  })
  last_name?: string;

  @property({
    type: 'string',
    required: true,
  })
  username: string;

  @property({
    type: 'string',
  })
  email?: string;

  @property({
    type: 'string',
  })
  phone?: string;

  @property({
    type: 'string',
    required: true,
  })
  password: string;

  @property({
    type: 'string',
  })
  external_id: string;

  @belongsTo(() => UserTenant)
  created_by: number;

  @belongsTo(() => UserTenant)
  modified_by: number;

  constructor(data?: Partial<User>) {
    super(data);
  }
}

В настоящее время, если мы создадим репозиторий и контроллер для этой модели, используя lb4 cli, он сгенерирует методы маршрутизации CRUD с этой же моделью в качестве ввода / вывода.Однако нам нужно иметь отдельную модель DTO (не сохраненную в БД), используемую в качестве DTO ввода / вывода для контроллера, за исключением свойств password, create_by иified_by.Один из способов - вручную создать такой класс модели и записать класс преобразователя, который преобразует объект UserDTO в модель пользователя выше (скопируйте отдельные свойства).Но это похоже на накладные расходы.Более того, мы хотим, чтобы это было сделано для многих других моделей.Таким образом, делать это таким образом не кажется правильным подходом.Предоставляет ли lb4 лучший способ добиться этого?

1 Ответ

0 голосов
/ 01 декабря 2018

По-видимому, в настоящее время есть способ «скрыть» свойства изначально в LB4.Затем я изменил класс Entity с помощью новой сущности HideableEntity (расширяющей Entity).В HideableEntity я изменил функцию toJson () следующим образом:

import {Entity, AnyObject} from '@loopback/repository';
import {Options} from '@loopback/repository/src/common-types';

export abstract class HideableEntity extends Entity {
  /**
   * Serialize into a plain JSON object
   */
  toJSON(): Object {
    const def = (<typeof HideableEntity>this.constructor).definition;
    if (def == null || def.settings.strict === false) {
      return this.toObject({ignoreUnknownProperties: false});
    }

    const json: AnyObject = {};
    for (const p in def.properties) {
      if (p in this) {
        json[p] = asJSON((this as AnyObject)[p]);
      }
    }
    return json;
  }

  /**
   * Convert to a plain object as DTO
   */
  toObject(options?: Options): Object {
    const def = (<typeof HideableEntity>this.constructor).definition;

    let obj: AnyObject;
    if (options && options.ignoreUnknownProperties === false) {
      obj = {};
      for (const p in this) {
        if (def != null && def.properties[p] && def.properties[p]['hide']) {
          continue;
        }
        let val = (this as AnyObject)[p];
        obj[p] = asObject(val, options);
      }
    } else {
      obj = this.toJSON();
    }
    return obj;
  }
}

function asJSON(value: any): any {
  if (value == null) return value;
  if (typeof value.toJSON === 'function') {
    return value.toJSON();
  }
  // Handle arrays
  if (Array.isArray(value)) {
    return value.map(item => asJSON(item));
  }
  return value;
}

function asObject(value: any, options?: Options): any {
  if (value == null) return value;
  if (typeof value.toObject === 'function') {
    return value.toObject(options);
  }
  if (typeof value.toJSON === 'function') {
    return value.toJSON();
  }
  if (Array.isArray(value)) {
    return value.map(item => asObject(item, options));
  }
  return value;
}

Затем теперь в моем расширении модели HideableEntity я добавляю свойство hide: true, и оно не будет добавлено в вывод JSON:

export class User extends HideableEntity {
  @property({
    type: 'number',
    id: true,
    required: false,
  })
  id: number;

    @property({
        type: 'string',
        required: true,
    })
    email: string;

    @property({
        type: 'string',
        required: true,
        hide: true,
    })
    password: string;

    [...]

В приведенном выше случае пароль будет скрыт.

...