今天,我們要在 MeudsaJS
建立端點API
,這樣就可以接受客戶從前端所發出的需求,
執行我們的workflow(工作流程)
來完成任務。
每一個API
可以接受的HTTP Method(請求方法)
皆有不同,都是要看當下任務最適合的情境為何。
以怕有人不知道API
跟HTTP Method(請求方法)
的關係,以下兩點簡單解釋一下:
API
就是「功能 / 資源所在地」,暴露端點提供服務。HTTP Method
就是「要對這個功能 / 資源 做什麼操作,或者這個功能提供什麼操作」所以以下介紹一下基本HTTP Method(請求方法)
有的操作,並且標示一下MedusaJS
是否有提供。
GET
:✅MedusaJS
HEAD
:✅MedusaJS
POST
:✅MedusaJS
PUT
:✅MedusaJS
DELETE
:✅MedusaJS
CONNECT
:❌MedusaJS
OPTION
:✅MedusaJS
TRACE
:❌MedusaJS
PATCH
:✅MedusaJS
PUT
最大不同在於,它只會更新指定欄位,不會覆蓋整個資源。src/api
時候,會發現裡面有admin
以及store
兩個資料夾,這兩個資料夾的目的是區分放給前端串接的api(端口)
或者放給後端串接的api(端口)
。api(端口)
路徑,比如說我要接收客戶發送的客製化需求,那我新增端口在src/store/supplement/createDemand
,那當我進行測試時候,就是在{{baseUrl}}/store/supplement/createDemand
進行測試。我們先依照官方給的範例去理解怎麼創建端口。
MedusaRequest
與MedusaResponse
提供端口輸入與輸出的解析與限制。//導入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(工作流程)
都偷偷寫好了!!!
所以我們明天就休息一下,
寫點測試就好....