Fullstack NestJS

TypeORM and Databases


The Goal

We will show how to use an ORM like TypeORM to create an interface to a data persistence layer.

We will also show TypeORM handles a lot of the hard work for us under the hood once we have properly defined our entities and their relationships.

Create TypeORM functionality so that operations can be saved into a database

The Commands

Generate a database module for each feature.

npx nx g @nx/nest:module --name=database --project=challenges-api
npx nx g @nx/nest:module --name=database --project=flashcards-api
npx nx g @nx/nest:module --name=database --project=notes-api
npx nx g @nx/nest:module --name=database --project=users-api
mkdir -p remote/challenges/src/app/database/{entities,subscribers} 
mkdir -p remote/flashcards/src/app/database/{entities,subscribers} 
mkdir -p remote/notes/src/app/database/{entities,subscribers} 
mkdir -p remote/users/src/app/database/{entities,subscribers} 

Entities

touch remote/challenges/src/app/database/entities/challenge.entity.ts \
  remote/flashcards/src/app/database/entities/flashcard.entity.ts \
  remote/notes/src/app/database/entities/note.entity.ts \
  remote/users/src/app/database/entities/user.entity.ts

Subscribers

touch remote/challenges/src/app/database/subscribers/challenge.subscriber.ts \
  remote/flashcards/src/app/database/subscribers/flashcard.subscriber.ts \
  remote/notes/src/app/database/subscribers/note.subscriber.ts \
  remote/users/src/app/database/subscribers/user.subscriber.ts

Database Providers

touch remote/challenges/src/app/database/database.providers.ts \
  remote/flashcards/src/app/database/database.providers.ts \
  remote/notes/src/app/database/database.providers.ts \
  remote/users/src/app/database/database.providers.ts
touch remote/challenges/src/app/challenges/challenge.providers.ts \
  remote/flashcards/src/app/flashcards/flashcard.providers.ts \
  remote/notes/src/app/notes/note.providers.ts \
  remote/users/src/app/users/user.providers.ts

The Code

Entity

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class Challenge {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  title: string;

  @Column()
  description: string;

  @Column()
  completed: boolean;

  @Column()
  repo_url: string;

  @Column()
  comment: string;

  @Column()
  user_id: string;
}

Database Provider

import { InjectionToken } from '@nestjs/common';
import { getMetadataArgsStorage, DataSource, DataSourceOptions } from 'typeorm';

export const DATABASE_CONNECTION: InjectionToken = 'DATABASE_CONNECTION';

export const databaseProviders = [
  {
    provide: DATABASE_CONNECTION,
    useFactory: () =>
      new DataSource({
        type: 'sqlite',
        database: './databases/challenges.sqlite',
        synchronize: true,
        logging: false,
        entities: getMetadataArgsStorage().tables.map((tbl) => tbl.target),
        migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
        subscribers: [__dirname + '/subscribers/**/*{.ts,.js}'],
        cli: {
          entitiesDir: '/entities',
          migrationsDir: '/migrations',
          subscribersDir: '/subscribers',
        },
      } as DataSourceOptions).initialize(),
  },
];

Entity Provider

import { Challenge } from '../database/entities/challenge.entity';
import { Connection } from 'typeorm';

export const challengeProviders = [
  {
    provide: 'CHALLENGE_REPOSITORY',
    useFactory: (connection: Connection) => connection.getRepository(Challenge),
    inject: ['DATABASE_CONNECTION'],
  },
];

Database Module

import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

@Module({
  providers: [...databaseProviders],
  exports: [...databaseProviders],
})
export class DatabaseModule {}

Feature Module

import { Module } from '@nestjs/common';
import { ChallengesService } from './challenges.service';
import { ChallengesController } from './challenges.controller';
import { challengeProviders } from './challenge.provider';
import { DatabaseModule } from '../database/database.module';

@Module({
  imports: [DatabaseModule],
  controllers: [ChallengesController],
  providers: [...challengeProviders, ChallengesService],
  exports: [ChallengesService],
})
export class ChallengesModule {}

Challenges

Pending.

< Nest Home