diff --git a/bun.lockb b/bun.lockb index c5149c8..72b1d6b 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 12b128f..823fa66 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,9 @@ "fastify": "^4.0.0", "fastify-cli": "^6.0.1", "fastify-plugin": "^4.0.0", - "pino": "^8.17.2" + "fastify-type-provider-zod": "^1.1.9", + "pino": "^8.17.2", + "zod": "^3.22.4" }, "devDependencies": { "@types/bun": "latest", diff --git a/src/app.ts b/src/app.ts index 55a983e..6899dac 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,6 +1,10 @@ import * as path from 'path' import AutoLoad from '@fastify/autoload' import { type FastifyPluginAsync } from 'fastify' +import { + serializerCompiler, + validatorCompiler, +} from 'fastify-type-provider-zod' const app: FastifyPluginAsync = async (fastify, opts): Promise => { fastify.register(AutoLoad, { @@ -8,6 +12,9 @@ const app: FastifyPluginAsync = async (fastify, opts): Promise => { options: opts, }) + fastify.setValidatorCompiler(validatorCompiler) + fastify.setSerializerCompiler(serializerCompiler) + fastify.register(AutoLoad, { dir: path.join(__dirname, 'routes'), options: opts, diff --git a/src/domains/users/db/createUser.db.ts b/src/domains/users/db/createUser.db.ts new file mode 100644 index 0000000..e3a0c63 --- /dev/null +++ b/src/domains/users/db/createUser.db.ts @@ -0,0 +1,10 @@ +import type { PrismaClient } from '@prisma/client' +import type { CreateUserSchema } from '../schemas/user.schema' + +export const createUser = (prisma: PrismaClient, user: CreateUserSchema) => + prisma.user.create({ + data: { + email: user.email, + name: user.name, + }, + }) diff --git a/src/domains/users/db/findAllUsers.db.ts b/src/domains/users/db/findAllUsers.db.ts new file mode 100644 index 0000000..340b7e3 --- /dev/null +++ b/src/domains/users/db/findAllUsers.db.ts @@ -0,0 +1,3 @@ +import type { PrismaClient } from '@prisma/client' + +export const findAllUsers = (prisma: PrismaClient) => prisma.user.findMany() diff --git a/src/domains/users/schemas/user.schema.ts b/src/domains/users/schemas/user.schema.ts new file mode 100644 index 0000000..06e27cf --- /dev/null +++ b/src/domains/users/schemas/user.schema.ts @@ -0,0 +1,25 @@ +import { z } from 'zod' + +const user = { + email: z + .string({ + required_error: 'Email is required', + invalid_type_error: 'Email must be a string', + }) + .email(), + name: z + .string({ + invalid_type_error: 'Name must be a string', + }) + .nullish(), +} + +export const findAllUsersSchema = z.array(z.object({ ...user, id: z.string() })) + +export const createUserSchema = z.object(user) +export const createUserResponseSchema = z.object({ + id: z.string(), + ...user, +}) + +export type CreateUserSchema = z.infer diff --git a/src/routes/example/index.route.ts b/src/routes/example/index.route.ts index 07e2170..eb9b76e 100644 --- a/src/routes/example/index.route.ts +++ b/src/routes/example/index.route.ts @@ -1,9 +1,17 @@ import type { FastifyPluginAsync } from 'fastify' +import type { ZodTypeProvider } from 'fastify-type-provider-zod' +import { z } from 'zod' const example: FastifyPluginAsync = async (fastify, _opts): Promise => { - fastify.get('/', async (_request, _reply) => { - return 'this is an example' - }) + fastify + .withTypeProvider() + .get( + '/', + { schema: { response: { 200: z.string() } } }, + async (_request, _reply) => { + return 'this is an example' + }, + ) } export default example diff --git a/src/routes/users/users.route.ts b/src/routes/users/users.route.ts index 9a43e75..1c79a95 100644 --- a/src/routes/users/users.route.ts +++ b/src/routes/users/users.route.ts @@ -1,9 +1,35 @@ import type { FastifyPluginAsync } from 'fastify' +import type { ZodTypeProvider } from 'fastify-type-provider-zod' +import { findAllUsers } from '../../domains/users/db/findAllUsers.db' +import { + createUserResponseSchema, + createUserSchema, + findAllUsersSchema, +} from '../../domains/users/schemas/user.schema' +import { createUser } from '../../domains/users/db/createUser.db' const users: FastifyPluginAsync = async (fastify, _opts) => { - fastify.get('/', async (_request, _reply) => { - return fastify.prisma.user.findMany() - }) + fastify + .withTypeProvider() + .get('/', { schema: { response: { 200: findAllUsersSchema } } }, () => { + return findAllUsers(fastify.prisma) + }) + + fastify.withTypeProvider().post( + '/', + { + schema: { + body: createUserSchema, + response: { + 201: createUserResponseSchema, + }, + }, + }, + async (request, reply) => { + const user = await createUser(fastify.prisma, request.body) + reply.code(201).send(user) + }, + ) } export default users