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.