Skip to content

Commit

Permalink
feat: config typeorm in a single file
Browse files Browse the repository at this point in the history
  • Loading branch information
leosuncin committed Sep 5, 2022
1 parent 3c2e617 commit 2d7dd11
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 64 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"db:create": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js db:create -r src --synchronize=no --initialDatabase=postgres",
"db:drop": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js db:drop -r src --initialDatabase=postgres",
"db:seed": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js seed -r src",
"db:create": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js db:create -r src/config --synchronize=no --initialDatabase=postgres",
"db:drop": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js db:drop -r src/config --initialDatabase=postgres",
"db:seed": "ts-node -r dotenv/config -r tsconfig-paths/register node_modules/typeorm-extension/dist/cli/index.js seed -r src/config",
"format": "prettier --write \"{src,apps,libs,test}/**/*.ts\"",
"lint": "eslint .",
"prepare": "husky install",
Expand All @@ -30,7 +30,7 @@
"test:e2e": "jest --selectProjects 'E2E test'",
"test:watch": "jest --watch",
"type-check": "tsc --noEmit --noErrorTruncation --pretty false --incremental false -p tsconfig.build.json",
"typeorm": "NODE_OPTIONS='-r dotenv/config -r tsconfig-paths/register' typeorm-ts-node-commonjs -d src/data-source"
"typeorm": "NODE_OPTIONS='-r dotenv/config -r tsconfig-paths/register' typeorm-ts-node-commonjs -d src/config/data-source"
},
"dependencies": {
"@nestjs/common": "^9.0.0",
Expand Down
14 changes: 8 additions & 6 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';

import { AppController } from '~app/app.controller';
import { AppService } from '~app/app.service';
import { AuthModule } from '~auth/auth.module';
import { BlogModule } from '~blog/blog.module';
import { configuration } from '~config/configuration';
import { dataSource } from '~config/data-source';

@Module({
imports: [
Expand All @@ -15,11 +16,12 @@ import { configuration } from '~config/configuration';
expandVariables: true,
load: [configuration],
}),
TypeOrmModule.forRoot({
type: 'postgres',
url: process.env.DATABASE_URL,
synchronize: false,
autoLoadEntities: true,
TypeOrmModule.forRootAsync({
imports: [ConfigModule.forFeature(dataSource)],
inject: [ConfigService],
useFactory(config: ConfigService) {
return config.getOrThrow('data-source');
},
}),
AuthModule,
BlogModule,
Expand Down
41 changes: 16 additions & 25 deletions src/common/build-test-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,16 @@ import {
HttpStatus,
ValidationPipe,
} from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { Test } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { useContainer } from 'class-validator';
import cookieParser from 'cookie-parser';
import type { DataSource } from 'typeorm';

import { User } from '~auth/entities/user.entity';
import { userFactory } from '~auth/factories/user.factory';
import { UserSeeder } from '~auth/seeders/user.seeder';
import { Article } from '~blog/entities/article.entity';
import { Comment } from '~blog/entities/comment.entity';
import { articleFactory } from '~blog/factories/article.factory';
import { commentFactory } from '~blog/factories/comment.factory';
import { ArticleSeeder } from '~blog/seeders/article.seeder';
import { CommentSeeder } from '~blog/seeders/comment.seeder';
import { database } from '~common/database';
import { CreateUser1637703183543 } from '~migrations/1637703183543-create-user';
import { CreateArticleComment1651517018946 } from '~migrations/1651517018946-create-article-comment';
import { configuration } from '~config/configuration';
import { dataSource } from '~config/data-source';

export async function buildTestApplication(
...modules: Array<
Expand All @@ -32,20 +24,18 @@ export async function buildTestApplication(
): Promise<INestApplication> {
const module = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
isGlobal: true,
expandVariables: true,
load: [configuration],
}),
TypeOrmModule.forRootAsync({
useFactory: () => ({
type: 'postgres',
entities: [User, Article, Comment],
migrations: [
CreateUser1637703183543,
CreateArticleComment1651517018946,
],
factories: [userFactory, articleFactory, commentFactory],
seeds: [UserSeeder, ArticleSeeder, CommentSeeder],
migrationsRun: true,
autoLoadEntities: true,
}),
dataSourceFactory: (options): Promise<DataSource> =>
imports: [ConfigModule.forFeature(dataSource)],
inject: [ConfigService],
useFactory(config: ConfigService) {
return config.getOrThrow('data-source');
},
dataSourceFactory: (options) =>
database.adapters.createTypeormDataSource(
options,
) as Promise<DataSource>,
Expand All @@ -54,6 +44,7 @@ export async function buildTestApplication(
],
}).compile();
const app = module.createNestApplication();
const config = app.get(ConfigService);

app.useGlobalPipes(
new ValidationPipe({
Expand All @@ -62,7 +53,7 @@ export async function buildTestApplication(
errorHttpStatusCode: HttpStatus.UNPROCESSABLE_ENTITY,
}),
);
app.use(cookieParser(process.env['SECRET']));
app.use(cookieParser(config.get('secret', 's€cr3to')));
useContainer(module, { fallbackOnErrors: true });

return app.init();
Expand Down
80 changes: 80 additions & 0 deletions src/config/data-source.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { registerAs } from '@nestjs/config';
import type { TypeOrmModuleOptions } from '@nestjs/typeorm';
import invariant from 'tiny-invariant';
import { type DataSourceOptions, DataSource } from 'typeorm';
import type { SeederOptions } from 'typeorm-extension';

import { User } from '~auth/entities/user.entity';
import { userFactory } from '~auth/factories/user.factory';
import { UserSeeder } from '~auth/seeders/user.seeder';
import { Article } from '~blog/entities/article.entity';
import { Comment } from '~blog/entities/comment.entity';
import { articleFactory } from '~blog/factories/article.factory';
import { commentFactory } from '~blog/factories/comment.factory';
import { ArticleSeeder } from '~blog/seeders/article.seeder';
import { CommentSeeder } from '~blog/seeders/comment.seeder';
import { CreateUser1637703183543 } from '~migrations/1637703183543-create-user';
import { CreateArticleComment1651517018946 } from '~migrations/1651517018946-create-article-comment';

// needed by TypeORM CLI
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace NodeJS {
// eslint-disable-next-line unicorn/prevent-abbreviations
interface ProcessEnv {
readonly NODE_ENV: 'development' | 'production' | 'test';
readonly DATABASE_URL: string;
}
}
}

const type: DataSourceOptions['type'] = 'postgres';
const entities: DataSourceOptions['entities'] = [User, Article, Comment];
const migrations: DataSourceOptions['migrations'] = [
CreateUser1637703183543,
CreateArticleComment1651517018946,
];
const factories: SeederOptions['factories'] = [
userFactory,
articleFactory,
commentFactory,
];
const seeds: SeederOptions['seeds'] = [
UserSeeder,
ArticleSeeder,
CommentSeeder,
];

const dataSourceOptions: DataSourceOptions & SeederOptions = {
type,
url: process.env.DATABASE_URL,
synchronize: false,
entities,
migrations,
factories,
seeds,
};

export const dataSource = registerAs('data-source', () => {
if (process.env.NODE_ENV === 'test') {
return {
type,
entities,
migrations,
factories,
seeds,
migrationsRun: true,
} as DataSourceOptions & SeederOptions;
}

invariant(process.env.DATABASE_URL, 'DATABASE_URL is missing');

return {
type,
url: process.env.DATABASE_URL,
synchronize: false,
autoLoadEntities: true,
} as TypeOrmModuleOptions;
});

export default new DataSource(dataSourceOptions);
29 changes: 0 additions & 29 deletions src/data-source.ts

This file was deleted.

0 comments on commit 2d7dd11

Please sign in to comment.