iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
Modern Web

Medusa.js 石化我的心系列 第 20

Day20 進階實作 - 客製化 API 建立

  • 分享至 

  • xImage
  •  

今天,我們要在 MeudsaJS 建立端點API,這樣就可以接受客戶從前端所發出的需求,
執行我們的workflow(工作流程)來完成任務。

每一個API可以接受的HTTP Method(請求方法)皆有不同,都是要看當下任務最適合的情境為何。
以怕有人不知道APIHTTP Method(請求方法)的關係,以下兩點簡單解釋一下:

  • API 就是「功能 / 資源所在地」,暴露端點提供服務。
  • HTTP Method 就是「要對這個功能 / 資源 做什麼操作,或者這個功能提供什麼操作」

所以以下介紹一下基本HTTP Method(請求方法)有的操作,並且標示一下MedusaJS 是否有提供。

  • GET:✅MedusaJS
    常用於取得資料,因為請求參數都暴露於外。
  • HEAD:✅MedusaJS
    和 GET 一樣,但是會得到關於 Header 的回應,目標是看看資源是否存在。
  • POST:✅MedusaJS
    常用於新增資料,請求參數隱藏在 Body 當中。
  • PUT:✅MedusaJS
    更新整體資源,假如個人資料中只要修改名字,提交自此資源必須連其他個人資料參數一起提交,若沒有可能會被清除掉。
  • DELETE:✅MedusaJS
    用來刪除某一資源。
  • CONNECT:❌MedusaJS
    多用在代理伺服器(Proxy)上建立一條隧道(TUNNEL)。
  • OPTION:✅MedusaJS
    查詢目標伺服器支援哪些HTTP Method
  • TRACE:❌MedusaJS
    測試和診斷用,伺服器會把收到的請求「原封不動回傳」給客戶端。
  • PATCH:✅MedusaJS
    部分更新 某個資源。和 PUT 最大不同在於,它只會更新指定欄位,不會覆蓋整個資源。

規則

  1. 當我們點開專案資料夾src/api時候,會發現裡面有admin以及store兩個資料夾,這兩個資料夾的目的是區分放給前端串接的api(端口)或者放給後端串接的api(端口)
  2. 創建的資料夾就是我們的路徑,api(端口)路徑,比如說我要接收客戶發送的客製化需求,那我新增端口在src/store/supplement/createDemand,那當我進行測試時候,就是在{{baseUrl}}/store/supplement/createDemand進行測試。

我們先依照官方給的範例去理解怎麼創建端口。

  • 匯入 MedusaRequestMedusaResponse提供端口輸入與輸出的解析與限制。
  • 請求方法直接當變數名稱
//導入MedusaJS http函式 用來解析與限制 Req輸入 與 Res輸出
import {
  MedusaRequest,
  MedusaResponse,
} from "@medusajs/framework/http"

//匯入工作流程
import { 
  createBrandWorkflow,
} from "../../../workflows/create-brand"

//輸入型別
type PostAdminCreateBrandType = {
  name: string
}

//接受 POST 請求的 API
export const POST = async (
  req: MedusaRequest<PostAdminCreateBrandType>,
  res: MedusaResponse
) => {
  //將輸入送到workflow當中
  const { result } = await createBrandWorkflow(req.scope)
    .run({
      input: req.validatedBody,
    })
  //輸出結果
  res.json({ brand: result })
}

驗證

只有使用型別去進行驗證的話,雖然是可行且簡單的,但是如果想要更進階的驗證方式,就會比較難一些,例如 Mail格式、電話 等等。

所以MedusaJS使用zod做型別套件。
(不是那個LOL主播ZOD😅)

zod帶有許多驗證規則與自訂錯誤處理方法。歡迎有興趣的可以去官方看看。今天就不多做介紹,直接看官方教學。

首先在目標api資料夾下建立一個validators.ts資料夾,建立驗證機制

import { z } from "zod"

export const PostAdminCreateBrand = z.object({
  name: z.string(),
})

然後這一個驗證就可以在端口以及中介做套用。
(中介的簡單意思就是在傳送需求到端口前的處理)

// 剛剛的端口範例,更改輸入型別
import { z } from "zod"
import { PostAdminCreateBrand } from "./validators"

type PostAdminCreateBrandType = z.infer<typeof PostAdminCreateBrand>

// ...
//接受 POST 請求....
import { 
  defineMiddlewares,
  validateAndTransformBody,
} from "@medusajs/framework/http"
import { PostAdminCreateBrand } from "./admin/brands/validators"

export default defineMiddlewares({
  routes: [
    {
      matcher: "/admin/brands",
      method: "POST",
      middlewares: [
        validateAndTransformBody(PostAdminCreateBrand),
      ],
    },
  ],
})

實作啦!!

昨天我們製作了客戶需求填寫的workflow(工作流程),今天我們就依照此建立api(端口)

首先我們先建立驗證,建立src/store/supplement/createDemand/validator.ts
需要需求填寫及使用者ID來做關聯。

import { z } from "zod"

export const PostCusotmerCreateDemand = z.object({
requirement: z.string(),
user_id:z.string()
})

根據我們創建的資料夾,及MedusaJS的端口規則,我們已經知道我們的端口位置最終會暴露在{{baseUrl}}/store/supplement/createDemand

所以我們創建api/middleware輸入這一個端口會使用到的驗證。

import {
defineMiddlewares,
validateAndTransformBody,
} from "@medusajs/framework/http"

import { authenticate } from "@medusajs/medusa"

//顧客建立需求單驗證

import { PostCusotmerCreateDemand } from "./store/supplement/createDemand/validators"

export default defineMiddlewares({
	routes: [
		{ //顧客需求驗證中間件
		matcher: "/store/supplement/createDemand",
		method: "POST",
		middlewares: [
		validateAndTransformBody(PostCusotmerCreateDemand),
		authenticate('customer' , ["session" , "bearer"])
		//上面那行次驗證是否登入
		],
		}
	],
})

最後我們創建我們的端口src/api/store/supplement/createDemand/route.ts

import {
	MedusaRequest,
	MedusaResponse,
} from "@medusajs/framework/http"
//匯入workflow
import {
	createDemandWorkflow,
} from "../../../../workflows/supplements/create-demand"

//匯入驗證
import { z } from "zod"
import { PostCusotmerCreateDemand } from "./validators"

  
//驗證轉換
type PostCostomerCreateDemandtype = z.infer<typeof PostCusotmerCreateDemand>

  
  
  
//建立POST端口新增需求
export const POST = async (
	req: MedusaRequest<PostCostomerCreateDemandtype>,
	res: MedusaResponse
) => {

	const { result } = await createDemandWorkflow(req.scope)
		.run({
			input: req.validatedBody,
		})
	res.json({ demand: result })
}

大功告成!!接下來就可以執行後端程式去進行測試。
但請容我測試留到明天再寫,因為我把 Day17 寫的需求順序的 API(端口)與workflow(工作流程)都偷偷寫好了!!!

所以我們明天就休息一下,
寫點測試就好....


上一篇
Day19 進階實作 - WorkFlow
下一篇
Day21 API 端口測試
系列文
Medusa.js 石化我的心21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言