간단한 Deno + MySQL API 생성

이것은 Deno와 Typescript를 사용하여 REST API를 만드는 방법에 대한 간단한 개념입니다.

간단한 RESTful API는 다음과 같습니다.

급한 경우 소스 코드를 보려면 here을 클릭하십시오.

스택은 다음과 같습니다.
  • 데노
  • 도커
  • MySQL



  • 왜 도커인가?
  • 텍스트 파일이나 개체가 아닌 데이터베이스를 사용하여 실제 데이터 조작을 경험하기를 원하기 때문에 로컬 데이터베이스를 제공했습니다.

  • Deno를 컨테이너화하지 않은 이유는 무엇입니까?
  • Docker가 병목 현상이 되는 것을 원하지 않기 때문입니다. Docker를 원하지 않는다면 자체 DB를 사용하고 Deno 서버만 실행해도 됩니다. 나는 당신에게 선택권을 줄뿐입니다.



  • 시작하자



    데노 설치:

    curl -fsSL https://deno.land/x/install/install.sh | sh
    

    로컬 데이터베이스용 Docker 설치(개인 DB가 있는 경우 이를 사용하고 필요한 테이블 생성)


    저장소를 복제합니다.

    git clone https://github.com/karlodelarosa/deno-rest-api.git
    

    데노 실행:

    deno run --allow-net --allow-read --allow-write index.ts
    

    MySQL 컨테이너 실행:

    docker-compose up -d
    

    MySQL 및 Adminer에 대해 실행 중인 컨테이너를 볼 수 있어야 합니다.

    CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
    fa3924041b59        adminer             "entrypoint.sh docke…"   6 seconds ago       Up 4 seconds        0.0.0.0:50000->8080/tcp   deno-adminer
    7bf14f3a94ca        mysql:5.7.12        "docker-entrypoint.s…"   6 seconds ago       Up 4 seconds        0.0.0.0:3306->3306/tcp    deno-db
    

    관리자 열기

    localhost:50000
    

    신임장:

    server: deno-db
    user: root
    password: root
    db: deno-db
    

    사용자 테이블과 하나의 테스트 데이터가 자동으로 표시되어야 합니다.

    사용자 스키마:

    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(100) NOT NULL,
      `country` varchar(50) NOT NULL,
      `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
    



    단계:

    1. 이 앱의 서버 역할을 할 index.ts 생성



    import { Application } from 'https://deno.land/x/oak/mod.ts'
    import router from './routes/routes.ts';
    
    const app = new Application();
    
    app.use(router.routes())
    app.use(router.allowedMethods())
    
    app.use((ctx) => {
      ctx.response.body = "Welcome to deno-rest-api";
    });
    
    await app.listen({ port: 8000 });
    

    2. MySQL 데이터베이스에 연결하고 db/MySqlClient.ts를 생성합니다.



    import { Client } from "https://deno.land/x/mysql/mod.ts";
    
    const client = await new Client().connect({
      hostname: "localhost",
      username: "root",
      db: "deno-db",
      password: "root",
    });
    
    export default client
    

    3. route/routes.ts 생성



    import { Router } from 'https://deno.land/x/oak/mod.ts'
    import { getAllUsers } from '../handler/getAllUsers.ts';
    import { getUser } from '../handler/getUser.ts';
    import { addUser } from '../handler/addUser.ts';
    import { updateUser } from '../handler/updateUser.ts';
    import { deleteUser } from '../handler/deleteUser.ts';
    
    const router = new Router()
    
    router.get("/users", getAllUsers)
    .get("/user/:id", getUser)
    .post("/user", addUser)
    .put("/user/:id", updateUser)
    .delete("/user/:id", deleteUser)
    
    export default router
    

    4. 데이터 모델을 위한 인터페이스인 계약 생성



    export interface UserInterface {
        name: string;
        country: string
    }
    

    5. 처리기를 생성하면 요청을 포착하고 논리를 처리합니다.



    getAllUsers.ts

    import client from '../db/MySqlClient.ts';
    import { search } from '../repository/user.ts';
    
    export async function getAllUsers ({ response }: { response: any }) { 
      const result = await search();
      response.body = result.rows;
    }
    

    getUser.ts

    import client from '../db/MySqlClient.ts';
    import * as doesUserExist from '../specification/doesUserExist.ts';
    import { search } from '../repository/user.ts';
    
    export async function getUser ({ params, response }: { params: any; response: any }) {
        const hasRecord = await doesUserExist.isSatisfiedBy(params.id);
        let status = 200;
    
        if (hasRecord) {
          const result = await search(params);
          response.body = result.rows;
        } else {
          response.body = { "error": "User not found!" };
          status = 400;
        }
    
        response.status = status;
    };
    

    addUser.ts

    import client from '../db/MySqlClient.ts';
    import { insert } from '../repository/user.ts';
    import { UserInterface } from '../contract/userInterface.ts';
    
    export async function addUser ({ request, response }: { request: any; response: any }) {
        const body = await request.body();
        const userInfo: UserInterface = body.value;
        let status = 200;
    
        if (userInfo.hasOwnProperty('name') && userInfo.hasOwnProperty('country')) {
          response.body = await insert(userInfo);
        } else {
          response.body = { "error": "Invalid request!" };
          status = 400;
        }
    
        response.status = status;
    }
    

    updateUser.ts

    import client from '../db/MySqlClient.ts';
    import * as doesUserExist from '../specification/doesUserExist.ts';
    import { UserInterface } from '../contract/userInterface.ts';
    import { update } from '../repository/user.ts';
    
    export async function updateUser ({ request, response, params }: { request: any; response: any; params: any }) {
        const body = await request.body()
        const userInfo: UserInterface = body.value 
        const hasRecord = await doesUserExist.isSatisfiedBy(params.id);
        let responseMessage = {};
        let status = 200;
    
        if (hasRecord) {
          responseMessage = await update(userInfo.name, userInfo.country, params.id);
        } else {
          responseMessage = { "error": "User not found!" };
          status = 400;
        }
    
        response.body = responseMessage;
        response.status = status;
    }
    

    deleteUser.ts

    import client from '../db/MySqlClient.ts';
    import * as doesUserExist from '../specification/doesUserExist.ts';
    import { remove } from '../repository/user.ts';
    
    export async function deleteUser ({ params, response }: { params: any; response: any }) {
        const hasRecord = await doesUserExist.isSatisfiedBy(params.id);
        let responseMessage = {};
        let status = 200;
    
        if (hasRecord) {
          responseMessage = await remove(params.id);
        } else {
          responseMessage = { "error": "User not found!" };
          status = 400;
        }
    
        response.body = responseMessage
        response.status = status
    }
    

    6. 사양을 생성합니다. 도메인 주도 설계에 대해 읽어보세요.



    doesUserExist.ts

    import client from '../db/MySqlClient.ts';
    
    export async function isSatisfiedBy(id:number) {
        const result = await client.query(`SELECT COUNT(*) count FROM user WHERE id = ?`, [id]);
        return result[0].count >= 1;
    }
    

    7. 사용자 리포지토리를 생성합니다. 여기에서 사용자 API에 대한 쿼리가 저장됩니다.



    user.ts

    import client from '../db/MySqlClient.ts';
    
    interface Key {
        id?: any
    }
    
    export async function search(params:Key = {}) { 
        const isSpecific = Object.keys(params).length !== 0;
        if (isSpecific) {
            return await client.execute(`SELECT * FROM user WHERE id = ?`, [params.id]);
        } else {
            return await client.execute(`SELECT * FROM user`);   
        }
    }
    
    export async function insert({ name, country }: { name: string; country: string }) {
        return await client.execute(`INSERT INTO user(name, country) values(?,?)`, [
            name, country
        ]);
    }
    
    export async function update(name: string, country: string, id: string) {
        return await client.execute(`UPDATE user SET name= ?, country= ? WHERE id = ?`, [
            name, country, id
        ]);
    }
    
    export async function remove(id: string) {
        return await client.execute(`DELETE FROM user WHERE id = ?`, [id]); 
    }
    

    POSTMAN에서 사용해 보세요.

    날 따라와

    소스 코드: GitHub

    좋은 웹페이지 즐겨찾기