# 🏅 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(); } }); } -->