🛠 نحوه ساخت مسیرها در یک Node.js API با Fastify و Prisma

در ادامه از پست قبلی 🚀 نحوه راه اندازی یک Node.js API با Fastify و Prisma ، بیایید اولین مسیر خود را کدگذاری کنیم.
تنظیم مشتری Prisma
اول ، ما باید یک مشتری PRISMA ایجاد کنیم که برای تعامل با پایگاه داده ما استفاده شود. در داخل /src/lib
دایرکتوری ، یک پرونده به نام ایجاد کنید prisma.ts
و کد زیر را اضافه کنید:
import { PrismaClient } from "@prisma/client";
export const prisma = new PrismaClient();
سازماندهی مسیرها
بعد ، پوشه ای به نام ایجاد کنید routes
درون /src
بشر در داخل /routes
، یک پوشه دیگر به نام ایجاد کنید users
، جایی که ما تمام عملکردهای مرتبط با کاربر را ذخیره خواهیم کرد.
اولین پرونده ما در داخل این پوشه خواهد بود create.ts
بشر واردات مورد نیاز برای این پرونده عبارتند از:
import bcrypt from "bcrypt";
import type { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import z from "zod";
import { prisma } from "../../lib/prisma"; // our newly defined client
از bcrypt
، تمام مسیرهای ما این کتابخانه های اصلی را از Fastify ، Zod و Prisma وارد می کنند.
تعریف مسیر
تعریف عملکرد شامل مسیر مسیر HTTP ، برخی از جزئیات مستندات و یک طرحواره ZOD برای اعتبارسنجی ورودی است. در اینجا به نظر می رسد:
export async function createAccount(app: FastifyInstance) {
app.withTypeProvider<ZodTypeProvider>().post(
"/users",
{
schema: {
summary: "Create account",
tags: ["users"],
body: z.object({
name: z.string(),
username: z.string().min(4),
email: z.string().email(),
password: z.string().min(8).max(32),
bio: z.string().optional(),
}),
},
},
async (request, reply) => {
// The next part will be placed here
}
);
}
ZOD ابزارهای قدرتمندی را برای تعیین قوانین اعتبار سنجی فراهم می کند ، و اطمینان می دهد که API ما فقط داده های فرمت شده درست را می پذیرد.
اجرای منطق مسیر
در داخل عملکرد ، ما باید داده های درخواست را بازیابی کنیم ، رمز عبور را هش دهیم و کاربر را در پایگاه داده ذخیره کنیم:
const { name, username, email, password, bio } = request.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user = await prisma.user.create({
data: {
name,
username,
email,
password: hashedPassword,
bio,
},
});
return reply.status(201).send({ userId: user.id });
ثبت مسیر در سرور
اکنون که مسیر ما ایجاد شده است ، ما باید آن را وارد کنیم server.ts
بنابراین می توان از آن استفاده کرد.
در آغاز server.ts
پرونده ، اضافه کنید:
import { createAccount } from "./routes/users/create";
سپس مسیر را قبل از app.listen
تماس:
app.register(createAccount);
اکنون ، صفحه Swagger را بارگیری مجدد کنید و مسیر باید به طور خودکار فهرست بندی شود. علاوه بر مستندات ، می توانید مسیر خود را با کلیک بر روی “امتحان کن” دکمه و ویرایش بدن. اگر مراحل را به درستی دنبال کردید ، مسیر شما باید کار کند!
ایجاد مسیر برای لیست کاربران
برای لیست همه کاربران ثبت شده ، یک فایل جدید به نام ایجاد کنید list.ts
در داخل /src/routes/users
پوشه و کد زیر را اضافه کنید:
import type { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import { prisma } from "../../lib/prisma";
export async function listAllUsers(app: FastifyInstance) {
app.withTypeProvider<ZodTypeProvider>().get(
"/users",
{
schema: {
summary: "List all the registered users",
tags: ["users"],
},
},
async (request, reply) => {
const users = await prisma.user.findMany({
select: {
id: true,
name: true,
username: true,
email: true,
bio: true,
createdAt: true,
},
});
return reply.send({ users });
}
);
}
توجه:
این طرح در اینجا شبیه به یکی برای ایجاد یک حساب است ، اما ساده تر است. ما از Prisma استفاده می کنیم
findMany()
روش باselect
گزینه ای برای بازیابی فقط زمینه های خاص از پایگاه داده. می توانید این مورد را در صورت لزوم فیلتر یا قالب بندی کنید.
این مسیر را در خود ثبت کنید server.ts
و آن را بر روی UI swagger آزمایش کنید.
به روزرسانی یک کاربر
بعد ، پرونده ای به نام ایجاد کنید update.ts
در همان پوشه (/src/routes/users
) با کد زیر:
import bcrypt from "bcrypt";
import type { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import z from "zod";
import { prisma } from "../../lib/prisma";
export async function updateUser(app: FastifyInstance) {
app.withTypeProvider<ZodTypeProvider>().put(
"/users/:userId",
{
schema: {
summary: "Update user",
tags: ["users"],
params: z.object({
userId: z.string().uuid(),
}),
body: z.object({
name: z.string().optional(),
username: z.string().min(4).optional(),
email: z.string().email().optional(),
password: z.string().min(8).max(32).optional(),
bio: z.string().optional(),
}),
},
},
async (request, reply) => {
const { userId } = request.params;
let { password } = request.body;
if (password) {
password = await bcrypt.hash(password, 10);
}
const user = await prisma.user.update({
where: { id: userId },
data: {
...request.body,
password, // will be undefined if not provided
},
});
return reply.status(200).send({ userId: user.id });
}
);
}
نکات کلیدی:
-
روش HTTP و پارامترهای URL:
ما از روش PUT استفاده می کنیم و یک پارامتر URL را درج می کنیم (:userId
) ، که توسط ZOD درparams
طرحواره -
زمینه های اختیاری:
همه قسمت های بدن اختیاری هستند زیرا کاربر ممکن است فقط زیر مجموعه ای از قسمت ها را به روز کند. -
رمزگذاری رمز عبور:
اگر یک رمز عبور جدید ارائه شود ، قبل از به روزرسانی رکورد هشدار داده می شود. -
اپراتور گسترش:
اپراتور گسترش (...request.body
) به استثنای رمز عبور که به طور جداگانه اداره می شود ، برای عبور از تمام قسمت ها استفاده می شود.
این مسیر را در خود ثبت کنید server.ts
و آن را از طریق swagger آزمایش کنید.
حذف کاربر
سرانجام ، برای تکمیل عملیات CRUD ، پرونده ای به نام ایجاد کنید delete.ts
در /src/routes/users
پوشه با کد زیر:
import type { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import { prisma } from "../../lib/prisma";
import z from "zod";
export async function deleteUser(app: FastifyInstance) {
app.withTypeProvider<ZodTypeProvider>().delete(
"/users/:userId",
{
schema: {
summary: "Delete user by id",
tags: ["users"],
params: z.object({
userId: z.string().uuid(),
}),
},
},
async (request, reply) => {
const { userId } = request.params;
const user = await prisma.user.delete({
where: { id: userId },
});
return reply.send({ user });
}
);
}
توجه:
این مسیر از همان الگوی دیگر پیروی می کند – تنها تفاوت روش حذف HTTP. آن را در سرور خود ثبت کنید و آن را در Swagger تست کنید.
بهبود واردات با یک پرونده فهرست مسیر
به عنوان شما server.ts
پرونده رشد می کند ، وارد کردن هر مسیر به صورت جداگانه می تواند آن را کثیف جلوه دهد. برای بهبود سازمان ، ایجاد یک index.ts
پرونده در داخل /src/routes/users
پوشه:
import type { FastifyInstance } from "fastify";
import { ZodTypeProvider } from "fastify-type-provider-zod";
import { createAccount } from "./create";
import { listAllUsers } from "./list";
import { updateUser } from "./update";
import { deleteUser } from "./delete";
export async function userRoutes(app: FastifyInstance) {
const typedApp = app.withTypeProvider<ZodTypeProvider>();
typedApp.register(createAccount);
typedApp.register(listAllUsers);
typedApp.register(updateUser);
typedApp.register(deleteUser);
}
اکنون ، در خود server.ts
، به جای ثبت هر مسیر به طور جداگانه ، ادغام شده را وارد و ثبت کنید userRoutes
عملکرد:
import { userRoutes } from "./routes/users";
app.register(userRoutes);
این تنظیم به سازماندهی کد شما و شما کمک می کند server.ts
پرونده تمیز
با وجود همه این مسیرها و ثبت نام ، API شما اکنون از ایجاد ، لیست ، به روزرسانی و حذف کاربران پشتیبانی می کند. تمام مسیرها را از طریق UI Swagger در http: // localhost: 3333/docs آزمایش کنید.
پایان
اکنون ما مهمترین ویژگی ها را پوشش داده ایم ، عملکردهای CRUD و برخی از بهترین شیوه ها را پوشش داده ایم. با این حال ، پیشرفت های احتمالی بسیاری وجود دارد که می تواند در نسخه های آینده انجام شود. به روزرسانی ها را در اینجا و در مخزن پروژه دنبال کنید: GitHub – Micaelmi/blog.Next مرحله اجرای احراز هویت و حفاظت از مسیر است ، با ما همراه باشید!