Initial Commit

This commit is contained in:
2026-05-23 10:39:41 +02:00
commit 7890669eda
16 changed files with 3003 additions and 0 deletions

2
src/routes/index.ts Normal file
View File

@@ -0,0 +1,2 @@
export * from './items.js';
export * from './orders.js';

73
src/routes/items.ts Normal file
View File

@@ -0,0 +1,73 @@
import type { Debugger as Debug } from 'debug';
import type { RouteOptions, FastifyRequest, FastifyReply } from 'fastify';
import type { Engine } from '@xo-cash/engine'
import type { Database } from '../services/database/database.js'
import { z } from 'zod';
export type ItemsRouteDeps = {
database: Database;
engine: Engine;
debug: Debug;
}
export class ItemsRoute {
public constructor(private readonly deps: ItemsRouteDeps) {}
public async getRoutes(): Promise<Array<RouteOptions>> {
return [
{
method: 'GET',
url: '/items',
handler: this.getItems.bind(this),
},
{
method: 'GET',
url: '/items/:id',
handler: this.getItem.bind(this),
},
]
}
/**
* Get all items from the database
* @param request
* @param reply
* @returns
*/
private async getItems(request: FastifyRequest, reply: FastifyReply) {
// Get all items from the database.
const items = await this.deps.database.db.selectFrom('items').selectAll().execute();
// Return the items.
return reply.send(items);
}
/**
* Get an item from the database by id
* @param request
* @param reply
* @returns
*/
private async getItem(request: FastifyRequest, reply: FastifyReply) {
// Parse the request parameters.
const { id } = ItemsRoute.getItemSchema.parse(request.params);
// Get the item from the database.
const item = await this.deps.database.db.selectFrom('items').where('id', '=', id).selectAll().executeTakeFirst();
// If the item is not found, return a 404 error.
if (!item) {
return reply.status(404).send({
error: 'Item not found'
});
}
// Return the item.
return reply.send(item);
}
static getItemSchema = z.object({
id: z.string(),
});
}

88
src/routes/orders.ts Normal file
View File

@@ -0,0 +1,88 @@
import type { Debugger as Debug } from 'debug';
import type { RouteOptions, FastifyRequest, FastifyReply } from 'fastify';
import type { Engine } from '@xo-cash/engine'
import type { Database } from '../services/database/database.js'
import { z } from 'zod';
export type OrdersRouteDeps = {
database: Database;
engine: Engine
debug: Debug;
}
export class OrdersRoute {
public constructor(private readonly deps: OrdersRouteDeps) {}
public async getRoutes(): Promise<Array<RouteOptions>> {
return [
{
method: 'GET',
url: '/orders',
handler: this.getOrders.bind(this),
},
{
method: 'POST',
url: '/orders',
handler: this.createOrder.bind(this),
},
]
}
private async getOrders(request: FastifyRequest, reply: FastifyReply) {
// Get all orders from the database.
const orders = await this.deps.database.db.selectFrom('orders').selectAll().execute();
// Return the orders.
return reply.send(orders);
}
private async createOrder(request: FastifyRequest, reply: FastifyReply) {
// Parse the request body.
const { items: itemsInput } = OrdersRoute.createOrderSchema.parse(request.body);
// Get the items from the database.
const items = await this.deps.database.db.selectFrom('items').where('id', 'in', itemsInput.map((item) => item.id)).selectAll().execute();
// If the items are not found, return a 404 error.
if (items.length !== items.length) {
return reply.status(404).send({
error: 'Items not found'
});
}
// TODO: Create an XO Engine Invitation with the relavent data in it so we can pass it back to the client.
// Create the order in the database.
const order = await this.deps.database.db.insertInto('orders').values({
// user_id: request.user.id,
status: 'pending',
total_price: 0,
total_quantity: 0,
items: JSON.stringify(items.map((item) => ({
id: item.id,
quantity: item.quantity,
}))),
}).execute();
// If the order is not created, return a 500 error.
if (!order) {
return reply.status(500).send({
error: 'Failed to create order'
});
}
// Return the order.
return reply.send(order);
}
/**
* Schema for creating an order.
*/
static createOrderSchema = z.object({
items: z.array(z.object({
id: z.string(),
quantity: z.number(),
})),
});
}