Skip to content

Decorators to copy swagger & class-validator metadata from one class to another

License

Notifications You must be signed in to change notification settings

Re-Quant/api-entity-ref

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Z-Brain Api Entity Ref

Build status NPM version Code Coverage License: GPL v3

Decorators to copy @nestjs/swagger, class-validator and class-transformer metadata from one class to another.

Notice: If you have any propositions feel free to make an issue or create a pull request.

How to use

Installing

yarn add @z-brain/api-entity-ref
or
npm i -s @z-brain/api-entity-ref

Usage example

dtos/account-base.dto.ts

import { ApiPropertyRef } from '@z-brain/api-entity-ref';
import { Account } from '../types';

export abstract class AccountBaseDto implements Omit<Account, 'id'> {

  @ApiPropertyRef()
  public email!: string;

  @ApiPropertyRef()
  public firstName?: string;

}

dtos/account-create.dto.ts

import { ApiEntityRef, ApiPropertyRef } from '@z-brain/api-entity-ref';
import { EEntityValidationGroup } from '@lib/common/enums';
import { Account } from '../types';
import { AccountBaseDto } from './account-base.dto';

@ApiEntityRef(Account, { groups: [EEntityValidationGroup.Create] })
export class AccountCreateDto extends AccountBaseDto {

  @ApiPropertyRef()
  public lastName?: string;

}

dtos/account-update.dto.ts

import { Allow, IsNotEmpty } from 'class-validator';
import { ApiEntityRef } from '@z-brain/api-entity-ref';

import { IDInt } from '@lib/common/types';
import { EEntityValidationGroup } from '@lib/common/enums';

import { Account } from '../types';
import { AccountBaseDto } from './account-base.dto';

@ApiEntityRef(Account, { groups: [EEntityValidationGroup.Update] })
export class AccountUpdateDto extends AccountBaseDto implements Omit<Account, 'fullName'> {

  @Allow()
  @IsNotEmpty()
  public id!: IDInt;

}

types/account.entity.ts

import { ApiProperty, ApiPropertyOptional, ApiResponseProperty } from '@nestjs/swagger';
import { IsEmail, IsOptional, IsString, Length } from 'class-validator';
lmport { Type } from 'class-transformer';

import { IDInt } from '@lib/common/types';
import {
  DEFAULT_EMAIL_MAX_LEN,
  DEFAULT_EMAIL_MIN_LEN,
  DEFAULT_NAME_MAX_LEN,
  DEFAULT_NAME_MIN_LEN,
} from '@lib/common/db.constants';
import { IsUnique } from '@lib/common/validators';
import { EEntityValidationGroup } from '@lib/common/enums';

class FirstLast {
  @ApiPropertyOptional({
    example: 'Ivan',
    maxLength: DEFAULT_NAME_MAX_LEN,
    minLength: DEFAULT_NAME_MIN_LEN,
  })
  @IsOptional({ always: true })
  @IsString({ always: true })
  @Length(DEFAULT_NAME_MIN_LEN, DEFAULT_NAME_MAX_LEN, { always: true })
  @Column({ length: DEFAULT_NAME_MAX_LEN, nullable: true })
  public first!: string;

  @ApiPropertyOptional({
    example: 'Trump',
    maxLength: DEFAULT_NAME_MAX_LEN,
    minLength: DEFAULT_NAME_MIN_LEN,
  })
  @IsOptional({ always: true })
  @IsString({ always: true })
  @Length(DEFAULT_NAME_MIN_LEN, DEFAULT_NAME_MAX_LEN, { always: true })
  @Column({ length: DEFAULT_NAME_MAX_LEN, nullable: true })
  public last!: string;
}

@Entity()
export class Account {
  public static readonly NAMELESS_FULL_NAME: string = 'Nameless User';

  @ApiResponseProperty({ example: 1234 })
  @PrimaryGeneratedColumn('increment', { unsigned: true })
  public id!: IDInt;

  @ApiProperty({
    example: 'ivan@gmail.com',
    maxLength: DEFAULT_NAME_MAX_LEN,
    minLength: DEFAULT_NAME_MIN_LEN,
    uniqueItems: true,
  })
  @Column({ length: DEFAULT_EMAIL_MAX_LEN, unique: true })
  @IsOptional({ groups: [EEntityValidationGroup.Update] })
  @IsEmail(undefined, { always: true })
  @IsUnique(Account, undefined, { always: true })
  @Length(DEFAULT_EMAIL_MIN_LEN, DEFAULT_EMAIL_MAX_LEN, { always: true })
  public email!: string;

  @Column(() => Name)
  @Type(() => Name)
  public name: FirstLast;

  @ApiResponseProperty({
    example: 'Ivan Trump',
  })
  public get fullName(): string {
    return this.name.first && this.name.last
           ? `${ this.name.first } ${ this.name.last }`
           : this.name.first || this.name.last || (this.constructor as typeof Account).NAMELESS_FULL_NAME;
  }

}

Development notes

Quick Start

cd /code/z-brain
git clone git@github.com:z-brain/api-entity-ref.git
cd api-entity-ref
yarn install

How to use NodeJS version from the .nvmrc

  1. Install NVM

  2. Use .nvmrc file one of the next ways:

    • Execute nvm use in the project root directory
    • Install NVM Loader and your .nvmrc will be loaded automatically when you open the terminal. NVM Loader demo

How to make a build

npm run build

How to run lint

  • Just show problems npm run lint
  • Fix problems if it is possible npm run lint:fix

How to run tests

  • All tests

    npm run test
    npm run test:watch

  • Specific tests

    npm run test -- src/my.spec.ts
    npm run test:watch -- src/my.spec.ts

How to build and publish NPM package

NPM Token: npm_ggEB......6ZRs

CI configuration details here: .github/workflows/npmpublish.yml

npm run pre-push \
&& npm version patch -m 'Update package version version to %s' \
&& npm run gen-public-package.json \
&& cp README.md dist/ \
&& npm publish dist --access public \
&& git push --no-verify && git push --tags --no-verify

How to build package to local installation

  1. yarn run build:local
  2. Then you can install a local package build from path file:.../api-entity-ref/dist.

Author


Anton Korniychuk