---
# System prepended metadata

title: "\U0001F3C5 Day 20 - 建立 API 與整合 TypeORM 查詢"
tags: [2025 Node.js 後端工程師培訓營]

---

# 🏅 Day 20 - 建立 API 與整合 TypeORM 查詢

## 設計 GET 和 POST API 路由。
API 是用來在客戶端與伺服器之間進行溝通的橋樑。

GET 請求：用於從伺服器取得資料，例如取得特定表中的所有記錄或特定條件的記錄。

POST 請求：用於將資料新增到伺服器，例如向特定表中插入一筆新的記錄。

設計 API 的基本步驟：

1. 確定 API 的路由結構，例如：/api/credit-package。
2. 確定使用的 HTTP 方法，例如：GET、POST。
3. 根據需求，撰寫相應的處理邏輯（例如資料庫操作、資料處理等）。

## 使用 TypeORM 進行資料查詢與新增

資料查詢（find 方法）：

使用 TypeORM 的 Repository 提供的方法可以輕鬆查詢資料，例如：

1. find()：查詢所有記錄，並可選擇特定欄位。
2. findOne()：查詢符合條件的一筆記錄。

## 舉例說明

GET 請求，取得所有 CreditPackage 資料：
```
if (req.url === "/api/credit-package" && req.method === "GET") {
  try {
    const purchases = await AppDataSource.getRepository("CreditPackage").find({
      select: ["id", "name", "credit_amount", "price"], // 指定需要的欄位
    });
    res.writeHead(200, { "Content-Type": "application/json" }); // 設定回應標頭
    res.write(
      JSON.stringify({
        status: "success",
        data: purchases, // 回傳資料
      })
    );
    res.end(); // 結束回應
  } catch (error) {
    res.writeHead(500, { "Content-Type": "application/json" });
    res.write(
      JSON.stringify({
        status: "error",
        message: error.message, // 錯誤訊息
      })
    );
    res.end();
  }
}
```

POST 請求，新增一筆 CreditPackage 資料：
```
if (req.url === "/api/credit-package" && req.method === "POST") {
  let body = "";
  req.on("data", (chunk) => {
    body += chunk; // 取得請求中的資料
  });
  req.on("end", async () => {
    try {
      const { name, credit_amount, price } = JSON.parse(body); // 解析請求中的 JSON 資料
      const newCreditPackage = {
        name,
        credit_amount,
        price,
      };
      const result = await AppDataSource.getRepository("CreditPackage").save(
        newCreditPackage
      ); // 將資料新增到資料庫
      res.writeHead(201, { "Content-Type": "application/json" }); // 設定回應標頭
      res.write(
        JSON.stringify({
          status: "success",
          data: result, // 回傳新增的資料
        })
      );
      res.end();
    } catch (error) {
      res.writeHead(500, { "Content-Type": "application/json" });
      res.write(
        JSON.stringify({
          status: "error",
          message: error.message, // 錯誤訊息
        })
      );
      res.end();
    }
  });
}
```

## 題目

建立一組新的 API，整合 typeorm 與資料庫的 Skill 表。

1.GET /api/skill，功能：查詢並回傳所有 Skill 資料，包含 id 和 name 欄位。

2.POST /api/skill，功能：新增一筆 Skill 資料。

( 請求 body 應包含：name：技能名稱，string 格式 )

回報區
---
| #   | Discord | CodePen / 答案 |
| -------- | -------- | -------- |
| 01 | helena | [CodePen](https://codepen.io/helena27/pen/gbYVZvw) |
| 02 | poyi | [CodePen](https://codepen.io/poyi-the-flexboxer/pen/ogvKWVo) | 
| 03 | Tau | [CodePen](https://codepen.io/Tau-Hsu/pen/EaxYPWd?editors=0010) |
| 04 | adengg | [CodePen](https://codepen.io/Osases/pen/bNGbBEL?editors=0010) |
| 05 | sian | [CodePen](https://codepen.io/uxitysjl-the-flexboxer/pen/wBvwoXE?editors=0010) |
| 06 | JC | [CodePen](https://codepen.io/lifetimingwhisper/pen/vEBoMJO) 
| 07 | hananhpun | [CodePen](https://codepen.io/hannahpun/pen/XJrvoyG) 
|08|janetlai|[Codepen](https://codepen.io/eiddkqxz-the-builder/pen/wBvwjez?editors=1010)
|09| sui_hsilan|[Codepen](https://codepen.io/suihsilan/pen/dPyyPLb?editors=0010)
|10 | hsin yu | [CodePen](https://codepen.io/tina2793778/pen/YPzzwNM) | 
|11 |ZoeKang|[CodePen](https://codepen.io/byehywmx-the-animator/pen/myddOoB?editors=0010)
| 12 | bian_yang_mofa | [CodePen](https://codepen.io/cssf998811/pen/ByaaGjP?editors=0010) | 
| 13 | yutzu | [CodePen](https://codepen.io/dtafsrmf-the-lessful/pen/OPJPmZg?editors=0010) |
| 14 | JerryOOO | [CodePen](https://codepen.io/fatiangel/pen/dPyMPWN?editors=0010) |
| 15 | HarryKuo | [CodePen](https://codepen.io/harry_kuo/pen/qEBqrwW?editors=0010) |
|16|wuyuli_21403| [CodePen](https://codepen.io/Job-Wilhelm/pen/ogNwzEE) |
|17|shiang| [CodePen](https://codepen.io/shiang29/pen/bNGLdqj?editors=1010) |
<!-- 可複製下方格式
|     |       | [CodePen]() | 
-->

<!-- 解答：
1.GET /api/skill，功能：查詢並回傳所有 Skill 資料，包含 id 和 name 欄位。

if (req.url === "/api/skill" && req.method === "GET") {
    try {
      const skill = await AppDataSource.getRepository("Skill").find({
        select: ["id", "name"]
      })
      res.writeHead(200, headers)
      res.write(JSON.stringify({
        status: "success",
        data: skill
      }))
      res.end()
    } catch (error) {
      res.writeHead(500, headers)
      res.write(JSON.stringify({
        status: "error",
        message: "伺服器錯誤"
      }))
      res.end()
    }
  } 

2. POST /api/skill，功能：新增一筆 Skill 資料。
if (req.url === "/api/skill" && req.method === "POST") {
  let body = "";
  req.on("data", (chunk) => {
    body += chunk;
  });
  req.on("end", async () => {
    try {
      const data = JSON.parse(body);
      if (!data.name || typeof data.name !== "string" || data.name.trim() === "") {
        res.write(
          JSON.stringify({
            status: "failed",
            message: "欄位未填寫正確",
          })
        );
        res.end();
        return;
      }
      const skillRepo = await AppDataSource.getRepository("Skill");
      const existSkill = await skillRepo.findOne({
        where: { name: data.name },
      });
      if (existSkill) {
        res.writeHead(409, { "Content-Type": "application/json" });
        res.write(
          JSON.stringify({
            status: "failed",
            message: "資料重複",
          })
        );
        res.end();
        return;
      }
      const newSkill = skillRepo.create({ name: data.name });
      const result = await skillRepo.save(newSkill);
      res.write(
        JSON.stringify({
          status: "success",
          data: result,
        })
      );
      res.end();
    } catch (error) {
      console.error(error);
      res.write(
        JSON.stringify({
          status: "error",
          message: error.message || "伺服器錯誤",
        })
      );
      res.end();
    }
  });
}
-->
