import type { Debugger as Debug } from "debug"; import type { RouteOptions, FastifyRequest, FastifyReply } from "fastify"; import { z } from "zod"; import type { Database } from "../services/database/database.js"; import { OrderPaymentError, OrderPaymentService, } from "../services/order-payment-service.js"; export type OrdersRouteDeps = { database: Database; orderPaymentService: OrderPaymentService; syncServerUrl: string; debug: Debug; }; export class OrdersRoute { public constructor(private readonly deps: OrdersRouteDeps) {} public async getRoutes(): Promise> { return [ { method: "GET", url: "/orders", handler: this.getOrders.bind(this), }, { method: "GET", url: "/orders/:id", handler: this.getOrder.bind(this), }, { method: "POST", url: "/orders", handler: this.createOrder.bind(this), }, ]; } private async getOrders(_request: FastifyRequest, reply: FastifyReply) { const orders = await this.deps.database.db .selectFrom("orders") .selectAll() .execute(); return reply.send( orders.map((order) => ({ ...order, items: JSON.parse(order.items), })), ); } private async getOrder(request: FastifyRequest, reply: FastifyReply) { const { id } = OrdersRoute.getOrderSchema.parse(request.params); const order = await this.deps.database.db .selectFrom("orders") .selectAll() .where("id", "=", id) .executeTakeFirst(); if (!order) { return reply.status(404).send({ error: "Order not found" }); } return reply.send({ ...order, items: JSON.parse(order.items), syncServerUrl: this.deps.syncServerUrl, }); } private async createOrder(request: FastifyRequest, reply: FastifyReply) { const { items: itemsInput } = OrdersRoute.createOrderSchema.parse( request.body, ); try { const result = await this.deps.orderPaymentService.createOrder(itemsInput); return reply.status(201).send(result); } catch (error) { if (error instanceof OrderPaymentError) { return reply.status(error.statusCode).send({ error: error.message }); } this.deps.debug("Failed to create order: %o", error); return reply.status(500).send({ error: "Failed to create order" }); } } static getOrderSchema = z.object({ id: z.string(), }); static createOrderSchema = z.object({ items: z.array( z.object({ id: z.string(), quantity: z.number().int().positive(), }), ), }); }