🛠️ VitNode is still in development! You can try it out, but it is not recommended to use it now in production.
Backend
Database
Sorting

Sorting

VitNode provide a sorting system to order the query result.

Here is an example of how to use the sorting system. We will use the core_members table as an example.

⚠️

Sorting system is based on Pagination System. If you don't want to use the pagination system you can use the orderBy argument directly in the findMany() method.

Data Transfer Object (DTO)

We will create a DTO to create arguments values for the query.

Initialize

File: show/dto/show-core_members.args.ts

Arguments used as container for fields to create query in GraphQL schema.

import { ArgsType, Field, Int } from '@nestjs/graphql';
 
@ArgsType()
export class ShowCoreMembersArgs {}

Create a enum

To restrict sorting by selected columns you have to create a enum.

enum ShowCoreMembersSortingColumnEnum {
  name = 'name',
  joined = 'joined',
  first_name = 'first_name',
  last_name = 'last_name',
  posts = 'posts',
  followers = 'followers',
  reactions = 'reactions'
}
⚠️

Remember to export the enum. It will be used in the next steps.

Register the enum

NestJS require to register the enum in the GraphQL schema. You can read more in NestJS documentation (opens in a new tab).

import { registerEnumType } from '@nestjs/graphql';
 
registerEnumType(ShowCoreMembersSortingColumnEnum, {
  name: 'ShowCoreMembersSortingColumnEnum'
});

Create a input type

Now you have to create a input type to use the enum in the args type.

import { InputType } from '@nestjs/graphql';
 
import { SortDirectionEnum } from '@/types/database/sortDirection.type';
 
@InputType()
class SortByArgs {
  @Field(() => ShowCoreMembersSortingColumnEnum)
  column: ShowCoreMembersSortingColumnEnum;
 
  @Field(() => SortDirectionEnum)
  direction: SortDirectionEnum;
}

Add input type to args type

Now you have to add the input type to the args type as arry and make it optional (If you want).

import { ArgsType, Field } from '@nestjs/graphql';
 
@ArgsType()
export class ShowCoreMembersArgs {
  @Field(() => [SortByArgs], { nullable: true })
  sortBy: SortByArgs[] | null;
}

Complite example

import { ArgsType, Field, InputType, registerEnumType } from '@nestjs/graphql';
 
import { SortDirectionEnum } from '@/types/database/sortDirection.type';
 
enum ShowCoreMembersSortingColumnEnum {
  name = 'name',
  joined = 'joined',
  first_name = 'first_name',
  last_name = 'last_name',
  posts = 'posts',
  followers = 'followers',
  reactions = 'reactions'
}
 
registerEnumType(ShowCoreMembersSortingColumnEnum, {
  name: 'ShowCoreMembersSortingColumnEnum'
});
 
@InputType()
class SortByArgs {
  @Field(() => ShowCoreMembersSortingColumnEnum)
  column: ShowCoreMembersSortingColumnEnum;
 
  @Field(() => SortDirectionEnum)
  direction: SortDirectionEnum;
}
 
@ArgsType()
export class ShowCoreMembersArgs {
  @Field(() => [SortByArgs], { nullable: true })
  sortBy: SortByArgs[] | null;
}

Query GraphQL

Service

File: show/show-core_members.service.ts

Inside service file we will create a show method that will return a ShowCoreMembersObj object.

import { Injectable } from '@nestjs/common';
 
import { ShowCoreMembersObj } from './dto/show-core_members.obj';
import { ShowCoreMembersArgs } from './dto/show-core_members.args';
 
import { DatabaseService } from '@/database/database.service';
 
@Injectable()
export class ShowCoreMembersService {
  constructor(private databaseService: DatabaseService) {}
 
  async show({ sortBy }: ShowCoreMembersArgs): Promise<ShowCoreMembersObj> {}
}

Query from database

To the inputPaginationCursor() function you have to pass the sortBy argument.

import { inputPaginationCursor } from '@/functions/database/pagination';
 
const pagination = await inputPaginationCursor({
  cursor,
  database: core_users,
  databaseService: this.databaseService,
  first,
  last,
  primaryCursor: { order: 'ASC', key: 'id', schema: core_users.id },
  defaultSortBy: {
    direction: SortDirectionEnum.desc,
    column: 'joined'
  },
  sortBy
});

Complite example

import { Injectable } from '@nestjs/common';
import { and, count, eq, ilike, or } from 'drizzle-orm';
 
import { ShowCoreMembersObj } from './dto/show.obj';
import { ShowCoreMembersArgs } from './dto/show.args';
 
import { DatabaseService } from '@/database/database.service';
import { inputPaginationCursor, outputPagination } from '@/functions/database/pagination';
import { core_users } from '@/src/admin/core/database/schema/users';
import { SortDirectionEnum } from '@/types/database/sortDirection.type';
 
@Injectable()
export class ShowCoreMembersService {
  constructor(private databaseService: DatabaseService) {}
 
  async show({
    cursor,
    first,
    last,
    name_seo,
    search,
    sortBy
  }: ShowCoreMembersArgs): Promise<ShowCoreMembersObj> {
    const pagination = await inputPaginationCursor({
      cursor,
      database: core_users,
      databaseService: this.databaseService,
      first,
      last,
      primaryCursor: { order: 'ASC', key: 'id', schema: core_users.id },
      defaultSortBy: {
        direction: SortDirectionEnum.desc,
        column: 'joined'
      },
      sortBy
    });
 
    const where = or(
      eq(core_users.name_seo, name_seo),
      or(
        ilike(core_users.name, `%${search}%`),
        ilike(core_users.email, `%${search}%`),
        Number(search) ? eq(core_users.id, Number(search)) : undefined
      )
    );
 
    const edges = await this.databaseService.db.query.core_users.findMany({
      ...pagination,
      where: and(pagination.where, where),
      with: {
        avatar: true,
        group: {
          with: {
            name: true
          }
        }
      }
    });
 
    const totalCount = await this.databaseService.db
      .select({ count: count() })
      .from(core_users)
      .where(where);
 
    return outputPagination({ edges, totalCount, first, cursor, last });
  }
}