スキップしてメイン コンテンツに移動

[Angular][Nest.js] Add TypeOrm

Intro

This time I added TypeOrm into the Nest.js project.
[Angular 10 + NgRx + Nest.js] Create project

Use TypeOrm

Install

To use TypeOrm I installed some packages. 

And to integrate the Nest.js project, I add an additional package.
npm install --save @nestjs/typeorm typeorm pg
Database | NestJS - A progressive Node.js framework

Configuration

Last time I used "ormconfig.json" for TypeOrm configuration. In Nest.js projects, I also could write them in "app.module.ts".

server/app.module.ts


import { Module } from '@nestjs/common';
import { AngularUniversalModule } from '@nestjs/ng-universal';
import { TypeOrmModule } from '@nestjs/typeorm';
import { join } from 'path';
import { Workflow } from './entities/workflow.entity';

@Module({
  imports: [
    AngularUniversalModule.forRoot({
      viewsPath: join(process.cwd(), 'dist/browser'),
      bundle: require('../server/main'),
      liveReload: false
    }),
    TypeOrmModule.forRoot({
      type: "postgres",
      host: "localhost",
      port: 5432,
      username: "test",
      password: "test",
      database: "Example",
      entities: [Workflow],
      synchronize: true,
      logging: true,
      cache: false
    })
  ],
  controllers: [],
  providers: []
})
export class ApplicationModule {}

My choice

But I choosed using "ormconfig.json". When I migrated Database by migration files, I had to use TypeOrm commands. But TypeOrm commands couldn't read "app.module.ts". So I must add the "ormconfig.json" file anyway.

ormconfig.json


{
    "type": "postgres",
    "host": "localhost",
    "port": 5432,
    "username": "test",
    "password": "test",
    "database": "Example",
    "entities": ["dist/**/entities/*.entity{.ts,.js}"],
    "migrations": ["server/migrations/*.{.ts,.js}"],
    "synchronize": true,
    "logging": true,
    "cache": false,
    "cli": {
        "entitiesDir": "server/entities",
        "migrationsDir": "server/migrations"
    }
}

So I removed the configure informations from "app.module.ts".

server/app.module.ts


...
@Module({
  imports: [
...
    TypeOrmModule.forRoot()
  ],
  controllers: [],
  providers: []
})
export class ApplicationModule {}

Add an Entity class

server/entities/workflow.entity.ts


import {Entity, PrimaryGeneratedColumn, Column, OneToMany, UpdateDateColumn} from "typeorm";

@Entity("Workflow")
export class Workflow {
    @PrimaryGeneratedColumn()
    id: number = -1;
    @Column({ type: 'text', nullable: false })
    createUserMail: string = '';
    @Column({ type: 'timestamp with time zone', nullable: true })
    circulationLimit: Date|null = null;
    @Column({ type: 'timestamp with time zone', nullable: false })
    lastUpdateDate: Date = new Date();
    
    public create(createUserMail: string, circulationLimit: Date|null) {
        if (createUserMail == null ||
            createUserMail.length <= 0) {
            throw new Error("Can not set createUserMail empty");
        }
        this.createUserMail = createUserMail;
        this.update(circulationLimit);
    }
    public update(circulationLimit: Date|null) {
        this.circulationLimit = circulationLimit;
        this.lastUpdateDate = new Date();
    }
}

Use "nest generate"

To access TypeOrm classes, I wanted to add classes into the Nest.js project. But when I did "nest generate" command, the created files were put into "src" directory. How to change to "server"? I had to add nest-cli.json like below.

nest-cli.json


{
    "collection": "@nestjs/schematics",
    "sourceRoot": "server"
}

After I did this, the files could be into "server" directory.

Add "@nestjs/testing"

After I generated some classes(ex. controller, service, etc.), I got an error. It was because the test classes needed "@nestjs/testing" package.
npm install --save-dev @nestjs/testing

Access the Database by Repositories

Access the Database(failed)

I added one controller class and one service class to access the Database.

server/workflow/workflow.controller.ts


import { Controller, Get } from '@nestjs/common';
import { WorkflowService } from './workflow.service';
import { Workflow } from '../entities/workflow.entity';

@Controller('workflow')
export class WorkflowController {
    constructor(private readonly service: WorkflowService) {
    }
    @Get("search")
    public async getWorkflowItems(): Promise<Workflow[]> {
        return await this.service.findAll();
    }
}

server/workflow/workflow.service.ts


import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Workflow } from '../entities/workflow.entity';
import { Repository } from 'typeorm';
import { of } from 'rxjs';

@Injectable()
export class WorkflowService {
    constructor(
        @InjectRepository(Workflow)
        private workflowRepositiory: Repository<Workflow>
    ){}
    public findAll(): Promise<Workflow[]> {
        return this.workflowRepositiory.find();
    }
}

server/app.module.ts


...
import { WorkflowController } from './workflow/workflow.controller';
import { WorkflowService } from './workflow/workflow.service';
import { Workflow } from './entities/workflow.entity';

@Module({
  imports: [
...
  ],
  controllers: [WorkflowController],
  providers: [WorkflowService]
})
export class ApplicationModule {}

OK. I started serving the project. 

...And I got an error.
...
[Nest] 17376   - 07/11/2020, 8:22:27 PM   [ExceptionHandler] Nest can't resolve dependencies of the WorkflowService (?). Please make sure that the argument WorkflowRepository at index [0] is available in the ApplicationModule context.

Potential solutions:
- If WorkflowRepository is a provider, is it part of the current ApplicationModule?
- If WorkflowRepository is exported from a separate @Module, is that module imported within ApplicationModule?
  @Module({
    imports: [ /* the Module containing WorkflowRepository */ ]
  })
 +570ms
Error: Nest can't resolve dependencies of the WorkflowService (?). Please make sure that the argument WorkflowRepository at index [0] is available in the ApplicationModule context.

Potential solutions:
- If WorkflowRepository is a provider, is it part of the current ApplicationModule?
- If WorkflowRepository is exported from a separate @Module, is that module imported within ApplicationModule?
  @Module({
    imports: [ /* the Module containing WorkflowRepository */ ]
  })

    at Injector.lookupComponentInParentModules (C:\Users\example\Documents\workspace\proofreading-workflow\node_modules\@nestjs\core\injector\injector.js:190:19)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
[nodemon] app crashed - waiting for file changes before starting...

Resolve the dependencies

To resolve the dependencies of Repository class, I had to add a module.

server/app.module.ts


...
import { Workflow } from './entities/workflow.entity';

@Module({
  imports: [
...
    TypeOrmModule.forRoot(),
    TypeOrmModule.forFeature([Workflow])
  ],
  controllers: [ProofreaderController, WorkflowController],
  providers: [ProofreaderService, WorkflowService]
})
export class ApplicationModule {}

Finally, I could access the Database :).

Resources

コメント

このブログの人気の投稿

[Angular][ASP.NET Core] Upload chunked files

Intro I wanted to send files to Web application (made by ASP.NET Core). If the file size had been small, I didn't need do any special things. But when I tried to send a large file, the error was occurred by ASP.NET Core's limitation. Though I could change the settings, but I didn't want to do that, because I hadn't known the file sizes what would been actually using. So I splitted the data into chunks first, and sent them. After receiving all chunks, I merged them into one file. There might be some libraries or APIs (ex. Stream API) what did them automatically, but I couldn't find them. What I did [ASP.NET Core] Make CORS enabled [Angular] Split a large file into chunks [Angular][ASP.NET Core] Send and receive data as form data [ASP.NET Core] Merge chunks into one file [ASP.NET Core] Make CORS enabled Because the client side application(Angular) and the server side application(ASP.NET Core) had been separated, I had to make CORS(Cross-Origin Requests) ...

[Nest.js] Show static files

Intro I wanted to use Nest.js and WebRTC(node-webrtc). NestJS - A progressive Node.js framework Documentation | NestJS - A progressive Node.js framework And because I wanted to try with simple page(not use JavaScript frameworks), I added static HTML, CSS, JavaScript into a Nest.js project. Prepare Install First, I installed @nestjs/cli. First steps | NestJS - A progressive Node.js framework As same as last time , I couldn't do global install because I had used Volta. But I could installed by volta. volta install @nestjs/cli Create project nest new nest-web-rtc-sample volta pin node@12 Run npm start After doing "npm start", I could getting "Hello World!" from http://localhost:3000. Add static files I could add static files by two ways. @nestjs/serve-static First one of them was using "serve-static". Serve Static | NestJS - A progressive Node.js framework npm install --save @nestjs/serve-static And I needed adding a module into app.modu...

[Angular] Sending file with Observable and showing loading screen

Intro When I tried sending file data on last time, I had confused with "promise.then", "async/await" and "Observable". [Angular][ASP.NET Core] Upload chunked files So I wanted to distinct them, and this time, I tried to use "Observable" because HttpClient return Observable<any>. Call observables in order I sended file in these steps. Read file by FileReader Create directory for saving chunks send and saving chunks merge chunks to one file and delete chunks Each steps used the former steps result. So I could write by Promise.then like below. this.executeStep1() // return Promise<UploadResult> .then(result => this.executeStep2(result)) // return Promise<UploadResult> .then(result => this.executeStep3(result)) // return Promise<UploadResult> .catch(reason => console.log(reason)); Result I could write with pipe & flatMap. file-uploader.service.ts public upload(file: File): Observable<U...