프로그래밍(Web)/Javascript(TS,Node)

[바미] Typescript-restful-starter - Update 될 때 텍스트뿐만 아니라 이메일도 수정 할 수 있게 변경하기!

Bami 2020. 12. 22. 17:25
728x90
반응형

코드 수정 전


Sample.schemas.ts

import { number, object, string } from "joi";

/* 구조 정의 */ 
export const createSample = object().keys({
    text: string().required(),
    email: string().required(),
});

export const updateSample = object().keys({
    id: number().required(),
    text: string().required(),
});

export const deleteSample = object().keys({
    id: number().required(),
});

코드 수정 후


Sample.schemas.ts

import { number, object, string } from "joi";

/* 구조 정의 */ 
export const createSample = object().keys({
    text: string().required(),
    email: string().required(),
});

export const updateSample = object().keys({
    id: number().required(),
    text: string().required(),
    email: string().required(), // 추가
});

export const deleteSample = object().keys({
    id: number().required(),
});

변경 전 List

출력화면


Tester

Web


  • 두 번째 코드 수정
    • get으로 id로 검색외에 text, email로 검색된 데이터 출력.

코드 수정 전


Sample.test.ts

변수 선언

let IdRecord: number;

기능 예제

//... 중략
it("Can search for Sample by Id", (done) => {
        supertest(app).get(`/find/id/:${IdRecord}`)
            .set("Authorization", `bearer ${token}`).set("Accept", "application/json")
            .end((err: Error, res: supertest.Response) => {
                chai.expect(res.status).to.eq(200);
                chai.expect(res.body).to.be.a("object");
                chai.expect(res.body).to.have.all.keys("id", "text", "email");
                chai.expect(res.body.text).to.be.a("string");
                done();
            });
    });

Sample.repository.ts

import { EntityRepository, Repository } from "typeorm";
import { Sample } from "../models";

@EntityRepository(Sample)
export class SampleRepository extends Repository<Sample> {

    public bulkCreate(Samples: Sample[]): Promise<any> {
        return this.manager.createQueryBuilder().insert().into(Sample).values(Samples).execute();
    }

    public async removeById(id: number): Promise<Sample> {
        const itemToRemove: Sample = await this.findOne({id});
        return this.manager.remove(itemToRemove);
    }

    public findByText(text: string): Promise<Sample[]> {
        return this.manager.find(Sample, {where: {text}});
    }

    public findOneById(id: number): Promise<Sample> {
        return this.manager.findOne(Sample, {where: {id}});
    }

}

Sample.service.ts

import { getCustomRepository } from "typeorm";
import { Sample } from "../models";
import { SampleRepository } from "../repository";

export class SampleService {

    public findByText(text: string): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).findByText(text);
    }

    public findByEmail(email: string): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).findByEmail(email);
    }

    public bulkCreate(Samples: Sample[]): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).bulkCreate(Samples);
    }

    public findOneById(id: number): Promise<Sample> {
        return getCustomRepository(SampleRepository).findOneById(id);
    }

    public find(): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).find();
    }

    public remove(sample: Sample): Promise<Sample> {
        return getCustomRepository(SampleRepository).remove(sample);
    }

    public removeById(id: number): Promise<Sample> {
        return getCustomRepository(SampleRepository).removeById(id);
    }

    public save(sample: Sample): Promise<Sample> {
        return getCustomRepository(SampleRepository).save(sample);
    }
}

Sample.route.ts

import { SampleController } from "../controllers";
import { Validator } from "../middlewares";
import { createSample, deleteSample, updateSample } from "../schemas";
import { Router } from "./Router";

/*  Method 방식에 따른 처리 
    .get("/",...) - get방식에서 '/'이후 아무것도 입력하지 않았을 때 'createSample'을 통해 만들어진 데이터들이 리스트로 출력된다.
    .get("/:id", ...) - get방식에서 '/'옆에 id값을 입력 시 해당 id값의 데이터를 출력시켜준다. ex: http://localhost:8080/2
    .post("/", ...) - post방식에서 Sample.schemas.ts의 형식에 맞게 json값을 입력 시 id, text, eamil 값이 DB에 생성된다. (현재는 임의적인 text값만 주면 생성된다.)
    .put("/", ...) - put 방식에서 id값을 json방식으로 입력 시 해당 id값이 삭제된다. (routes/Sample.route.ts에서 )
*/
export class SampleRouter extends Router {
    constructor() {
        super(SampleController);
        this.router
            .get("/", this.handler(SampleController.prototype.all))
            .get("/:id", this.handler(SampleController.prototype.find))
            .post("/", [ Validator(createSample) ], this.handler(SampleController.prototype.create))
            .put("/", [ Validator(updateSample) ],  this.handler(SampleController.prototype.update))
            .delete("/", [ Validator(deleteSample) ], this.handler(SampleController.prototype.delete));
    }
}

코드 수정 후


Sample.test.ts

변수 선언

let IdRecord: number;
let textRecord: string; // 조회할 text값을 받는 변수(추가)
let emailRecord: string; // 조회할 email값을 받는 변수(추가)

기능 예제

//... 중략
 it("Can search for Sample by Id", (done) => {
        supertest(app).get(`/find/id/:${IdRecord}`)
            .set("Authorization", `bearer ${token}`).set("Accept", "application/json")
            .end((err: Error, res: supertest.Response) => {
                chai.expect(res.status).to.eq(200);
                chai.expect(res.body).to.be.a("object");
                chai.expect(res.body).to.have.all.keys("id", "text", "email");
                chai.expect(res.body.text).to.be.a("string");
                done();
            });
    });

    it("Can search for Sample by Text", (done) => { // text검색기능
        supertest(app).get(`/find/text/:${textRecord}`)
            .set("Authorization", `bearer ${token}`).set("Accept", "application/json")
            .end((err: Error, res: supertest.Response) => {
                chai.expect(res.status).to.eq(200);
                chai.expect(res.body).to.be.a("object");
                chai.expect(res.body).to.have.all.keys("id", "text", "email");
                chai.expect(res.body.text).to.be.a("string");
                done();
            });
    });

    it("Can search for Sample by Email", (done) => { // email검색기능
        supertest(app).get(`/find/email/:${emailRecord}`)
            .set("Authorization", `bearer ${token}`).set("Accept", "application/json")
            .end((err: Error, res: supertest.Response) => {
                chai.expect(res.status).to.eq(200);
                chai.expect(res.body).to.be.a("object");
                chai.expect(res.body).to.have.all.keys("id", "text", "email");
                chai.expect(res.body.text).to.be.a("string");
                done();
            });
    });

Sample.repository.ts

import { EntityRepository, Repository } from "typeorm";
import { Sample } from "../models";

@EntityRepository(Sample)
export class SampleRepository extends Repository<Sample> {

    public bulkCreate(Samples: Sample[]): Promise<any> {
        return this.manager.createQueryBuilder().insert().into(Sample).values(Samples).execute();
    }

    public async removeById(id: number): Promise<Sample> {
        const itemToRemove: Sample = await this.findOne({id});
        return this.manager.remove(itemToRemove);
    }

    public findByText(text: string): Promise<Sample[]> {
        return this.manager.find(Sample, {where: {text}});
    }
    // 입력받은 email과 DB안에 저장되어 있는 email이 같은 값이 있는지 조회. (추가)
    public findByEmail(email: string): Promise<Sample[]> {
        return this.manager.find(Sample, {where: {email}});
    }

    public findOneById(id: number): Promise<Sample> {
        return this.manager.findOne(Sample, {where: {id}});
    }
}

Sample.service.ts

import { getCustomRepository } from "typeorm";
import { Sample } from "../models";
import { SampleRepository } from "../repository";

export class SampleService {

    public findByText(text: string): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).findByText(text);
    }

    public findByEmail(email: string): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).findByEmail(email);
    }

    public bulkCreate(Samples: Sample[]): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).bulkCreate(Samples);
    }

    public findOneById(id: number): Promise<Sample> {
        return getCustomRepository(SampleRepository).findOneById(id);
    }

    public find(): Promise<Sample[]> {
        return getCustomRepository(SampleRepository).find();
    }

    public remove(sample: Sample): Promise<Sample> {
        return getCustomRepository(SampleRepository).remove(sample);
    }

    public removeById(id: number): Promise<Sample> {
        return getCustomRepository(SampleRepository).removeById(id);
    }

    public save(sample: Sample): Promise<Sample> {
        return getCustomRepository(SampleRepository).save(sample);
    }
}

Sample.route.ts

import { SampleController } from "../controllers";
import { Validator } from "../middlewares";
import { createSample, deleteSample, updateSample } from "../schemas";
import { Router } from "./Router";

export class SampleRouter extends Router {
    constructor() {
        super(SampleController);
        this.router
            .get("/", this.handler(SampleController.prototype.all))
            .get("/find/text/:text", this.handler(SampleController.prototype.find)) // text 찾는 route
            .get("/find/id/:id", this.handler(SampleController.prototype.find2)) // id 찾는 route
            .get("/find/email/:email", this.handler(SampleController.prototype.find3)) // email 찾는 route
            .post("/", [ Validator(createSample) ], this.handler(SampleController.prototype.create))
            .put("/", [ Validator(updateSample) ],  this.handler(SampleController.prototype.update))
            .delete("/", [ Validator(deleteSample) ], this.handler(SampleController.prototype.delete));
    }
}

출력화면


Tester

  • id로 검색 시

  • text로 검색 시

  • email로 검색 시

note(remind)

원래 의도는 id검색 외에도 text를 검색하게 하고 싶었다.
그래서 Sample.service.ts, Sample.test.ts,등 4군데 코드를 수정 및 추가했다.
하지만 의도와는 다르게 text로만 검색이 될 뿐 id로는 검색이 되지 않았다.

문제의 원인은
.get("/:text", this.handler(SampleController.prototype.find))
.get("/:id", this.handler(SampleController.prototype.find2))
로만 해서 서로의 경로가 겹쳤기 때문이였다. 위와 같이 하면 text값과 id값을 분리시켜 검색 될 줄 알았기 때문이다.
그래서 Sample.route.ts에서
.get("/find/text/:text", this.handler(SampleController.prototype.find))
.get("/find/id/:id", this.handler(SampleController.prototype.find2))
으로 수정하였고, 경로 또한 더 명확하게 구별 시켜주었다. 그래서 이를 더 응용하여 eamil 까지 검색 하는 기능을 구현했다.

728x90
반응형