Skip to content

Latest commit

 

History

History
223 lines (144 loc) · 7.45 KB

DOCUMENTATION.md

File metadata and controls

223 lines (144 loc) · 7.45 KB

Documentation

Exception Filters

Exception filters allow us not to use try / catch as often as we do now, and to handle them within the same class (like the error aggregator class). Find out more here:

Interceptors

An interceptor that logs request/response, the execution time of the function, the name of the methods that were executed, headers. Suitable for debug mode, when the service is already in dev. Retrieves the x-request-id if passed in the header. You can turn on / off some functions: headers, request, response, handlers

// .env
LOGGING_INTERCEPTOR_MODES = request, headers, handlers, response

// main.ts
async function bootstrap(): Promise<void> {
    const app = await NestFactory.create(AppModule)

    const configService = app.get(ConfigService)

    const interceptorModes = configService.get<string>('LOGGING_INTERCEPTOR_MODES') || ''

    app.useGlobalInterceptors(
        new LoggingInterceptor({ modes: interceptorModes.split(',') })
    )

    await app.listen(port, hostname, () =>
        logger.log(`Server running at ${hostname}:${port}`),
    )
}

GraphQL

The service provides methods for sending GQL queries over HTTP. Benefits of using:

  • Ability to type server responses
  • Single sendQuery method for sending requests
  • Ease of injection into other projects
  • Ability to log GQL queries to the console
@Injectable()
export class CatService extends GraphQLClientService {

    constructor(private readonly _configService: ConfigService) {
        super(_configService.get<string>('CAT_API_URL'))
    }

    async sendCats(query: string): Promise<CatResponse> {
        return await this._sendQuery(query, {
            headers: {
                authorization: 'my-cat-token'
            }
            log: true, // prints a GQL query to the console
            name: 'sendCats' // prints '[sendCats] request sent to http://localhost:3000/graphql' to the console
        })
    }
}

When implementing sorting, it is very often necessary to implement ascending/descending sorting. SortOrderEnum contains two values ​​ASC and DESC, it can be used in GQL inputs and inserted into typeorm sort fields.

GQL Input is often used when filtering needs to be implemented. The main fields for filtering are ids, skip, limit. FilterInput implements them, and sets default values.

import { Field, ID, InputType, Int } from '@nestjs/graphql'

@InputType()
export class CatInput extends FilterInput {
    @Field(() => BlockchainEnum, { nullable: true })
    blockchain?: BlockchainEnum

    @Field(() => TokenEnum, { nullable: true })
    token?: TokenEnum
}

Scalars are used to use types not found in GraphQL. For example BigNumber, a type with which it is convenient to work with large numbers. BigNumberScalar takes a string as input and parses it into BigNumber, thus we can validate fields and get rid of unnecessary code

GraphQL type that implements pagination. With it, not all essences can be given to the front, but only a certain part. Using skip and limit, you can get from

features “page by page”.

@ObjectType('Balance')
export class BalanceType {
    @Field(() => BigNumberScalar)
    totalSupply: BigNumber

    @Field(() => BigNumberScalar)
    apy: BigNumber

    @Field(() => BigNumberScalar)
    apyChange: BigNumber

    @Field(() => BigNumberScalar)
    collateral: BigNumber

    @Field(() => BigNumberScalar)
    pnl: BigNumber
}

@ObjectType('Balances')
export class BalancesType extends PaginatedType(BalancesType) {}

Helpers

The clearUndefinedProperties function removes fields in an object whose type is undefined. It is very often used when you need to send a GQL request, or find entities using a filter, since typeorm does not accept undefined well.

async findEntity(filter: Filter): Promise<Entity> {
    const clearedFilter = clearUndefinedProperties(filter)

    return await this._entityRepository.find(clearedFilter)
}

The betweenDates function is used for filtering in typeorm. Typeorm has its own Between() function, but it doesn't work well with dates. The function parses the date into the correct values ​​and returns FindOperator

const entities = await this._entityRepository.find({
    where: {
        createdAt: betweenDates(from, to)
    }
})

Returns a random string of the given length. You can use the onlyNumbers flag to get a string of numbers.

Returns an object with the passed fields for filtering. Gets the ids, skip, limit fields and puts them in their places. Returns an object that can be used in entity search methods

const findOptions = applyFilterToSelector({}, filter)

const entities = await this._entityRepository.find(findOptions)

Interfaces

Interface implementing pagination with template type

export interface Paginated<T> {
    nodes: T[]
    cursor: number
    count:number
}

TypeORM

Entity implements the main fields in the database, such as id, createdAt, updatedAt, deletedAt, version.

export class CatEntity extends CommonBaseEntity {
    @Column()
    name:string
}

Result in database

name createdAt updatedAt deletedAt version
cat time-here time-here NULL 1
cat2 time-here time-here time-here 3

Transformer for typeorm. With it, you can pass BigNumber types to entities, which will be represented in the database in other types (string by default)

@Entity('cats')
export class CatEntity extends CommonBaseEntity {
    @Column({
        type: 'decimal', // you can specify another type, but it's better in what to use decimals transformer: new BigNumber Field Transformer(), default: '0', }) age: BigNumber
}