Skip to content

Commit

Permalink
Merge pull request #51 from electricmonk/fastify-zod
Browse files Browse the repository at this point in the history
added schema using zod
  • Loading branch information
electricmonk authored Sep 29, 2023
2 parents 11001ba + 0cb17d3 commit a33b4db
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 41 deletions.
1 change: 1 addition & 0 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"dependencies": {
"@fastify/cors": "^8.4.0",
"fastify": "^4.23.2",
"fastify-type-provider-zod": "^1.1.9",
"mongodb": "^4.17.1",
"nanoid": "^4.0.2",
"ts-byob": "^1.0.3",
Expand Down
139 changes: 98 additions & 41 deletions packages/server/src/routes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {LineItem, Order, Product, ProductTemplate} from "./types";
import {FastifyInstance, FastifyRequest} from "fastify";

import {FastifyInstance} from "fastify";
import {serializerCompiler, validatorCompiler, ZodTypeProvider} from "fastify-type-provider-zod";
import {z} from "zod";

type Cart = {
id: string;
Expand All @@ -9,76 +10,132 @@ type Cart = {

export interface ProductRepository {
findById(productId: Product["id"]): Promise<Product | undefined>;

create(template: Omit<Product, "id">): Promise<Product>;

findAll(): Promise<Product[]>;
}

export interface OrderRepository {
create(order: Omit<Order, "id">): Promise<Order>;

findById(orderId: string): Promise<Order | null>;

}

type CartId = {Params: {cartId: string}};
type OrderId = {Params: {orderId: string}};
const CartIdSchema = z.object({
cartId: z.string()
});

export const createRoutes = (productRepo: ProductRepository, orderRepo: OrderRepository) => (fastify: FastifyInstance, opts: any, done: () => void) => {
fastify.setValidatorCompiler(validatorCompiler);
fastify.setSerializerCompiler(serializerCompiler);

const f = fastify.withTypeProvider<ZodTypeProvider>();

const sessions: Record<string, Cart> = {};

fastify.get("/cart/:cartId", (req: FastifyRequest<CartId>, res) => {
const {cartId} = req.params;
res.send(sessions[cartId]);
f.route({
url: "/cart/:cartId",
method: "GET",
schema: {
params: CartIdSchema,
},
handler: (req, res) => {
const {cartId} = req.params;
res.send(sessions[cartId]);
}
});

fastify.get("/cart/:cartId/count", (req: FastifyRequest<CartId>, res) => {
const {cartId} = req.params;
res.send(sessions[cartId]?.items.length || 0);
f.route({
method: "GET",
url: "/cart/:cartId/count",
schema: {
params: CartIdSchema,
},
handler: (req, res) => {
const {cartId} = req.params;
res.send(sessions[cartId]?.items.length || 0);
}
});

fastify.post("/cart/:cartId", async (req: FastifyRequest<CartId & {Body: {productId: string}}> , res) => {
const {cartId} = req.params;
const {productId} = req.body;
sessions[cartId] = sessions[cartId] || {id: cartId, items: []};
const product = await productRepo.findById(productId);

if (product) {
sessions[cartId].items.push(({productId, name: product.title, price: product.price}))
res.status(201).send();
} else {
res.status(404).send();
f.route({
url: "/cart/:cartId",
method: "POST",
schema: {
body: z.object({
productId: z.string()
}),
params: CartIdSchema,
},
handler: async (req, res) => {
const {cartId} = req.params;
const {productId} = req.body;
sessions[cartId] = sessions[cartId] || {id: cartId, items: []};
const product = await productRepo.findById(productId);

if (product) {
sessions[cartId].items.push(({productId, name: product.title, price: product.price}))
res.status(201).send();
} else {
res.status(404).send();
}
}
});

fastify.post("/checkout/:cartId", async (req: FastifyRequest<CartId>, res) => {
const {cartId} = req.params;
const cart = sessions[cartId];
if (!cart) {
throw new Error(`no cart with id ${cartId} was found`);
} else {

const order = await orderRepo.create({items: cart.items});
res.status(201).send(order.id);
f.route({
method: "POST",
url: "/checkout/:cartId",
schema: {
params: CartIdSchema,
},
handler: async (req, res) => {
const {cartId} = req.params;
const cart = sessions[cartId];
if (!cart) {
throw new Error(`no cart with id ${cartId} was found`);
} else {

const order = await orderRepo.create({items: cart.items});
res.status(201).send(order.id);
}
}
});

fastify.get("/order/:orderId", async (req: FastifyRequest<OrderId>, res) => {
const {orderId} = req.params;
const order = await orderRepo.findById(orderId);
if (order) {
res.send(order);
} else {
res.status(404).send(`Order with id ${orderId} was not found`);
f.route({
method: "GET",
url: "/order/:orderId",
schema: {
params: z.object({
orderId: z.string(),
})
},
handler: async (req, res) => {
const {orderId} = req.params;
const order = await orderRepo.findById(orderId);
if (order) {
res.send(order);
} else {
res.status(404).send(`Order with id ${orderId} was not found`);
}
}
});


//TODO remove
fastify.post("/products", async (req, res) => {
const product = await productRepo.create(ProductTemplate.parse(req.body));
res.status(201).send(product);
f.route({
method: "POST",
url: "/products",
schema: {
body: ProductTemplate,
},
handler: async (req, res) => {
const product = await productRepo.create(req.body);
res.status(201).send(product);
}
})

fastify.get("/products", async (_, res) => {
f.get("/products", async (_, res) => {
res.send(await productRepo.findAll());
})

Expand Down
22 changes: 22 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2727,6 +2727,7 @@ __metadata:
"@types/morgan": ^1.9.5
"@types/node": ^17.0.45
fastify: ^4.23.2
fastify-type-provider-zod: ^1.1.9
jest: ^28.1.3
mongodb: ^4.17.1
nanoid: ^4.0.2
Expand Down Expand Up @@ -4997,6 +4998,18 @@ __metadata:
languageName: node
linkType: hard

"fastify-type-provider-zod@npm:^1.1.9":
version: 1.1.9
resolution: "fastify-type-provider-zod@npm:1.1.9"
dependencies:
zod-to-json-schema: ^3.17.1
peerDependencies:
fastify: ^4.0.0
zod: ^3.14.2
checksum: 86792031057cf3807a2e77ef41b16161d94c89ab95bd6284574502351df9c4d1e1621d4f7e7f3f14cd81aec9923c3a4f61c8889d5abb3b57e52ee9c0015056e1
languageName: node
linkType: hard

"fastify@npm:^4.23.2":
version: 4.23.2
resolution: "fastify@npm:4.23.2"
Expand Down Expand Up @@ -9416,6 +9429,15 @@ __metadata:
languageName: node
linkType: hard

"zod-to-json-schema@npm:^3.17.1":
version: 3.21.4
resolution: "zod-to-json-schema@npm:3.21.4"
peerDependencies:
zod: ^3.21.4
checksum: 899c1f461fb6547c0b08a265c82040c250be9b88d3f408f2f3ff77a418fdfad7549077e589d418fccb312c1f6d555c3c7217b199cc9072762e1fab20716dd2a6
languageName: node
linkType: hard

"zod@npm:^3.22.2":
version: 3.22.2
resolution: "zod@npm:3.22.2"
Expand Down

0 comments on commit a33b4db

Please sign in to comment.