🎉 init: 小龙的工作空间

This commit is contained in:
大海
2026-06-06 10:40:48 +08:00
commit a188ee1426
3201 changed files with 231817 additions and 0 deletions
@@ -0,0 +1,121 @@
// Authentication routes
import type { FastifyInstance } from "fastify";
import bcrypt from "bcrypt";
import { queryOne, execute } from "../db/client.js";
import { authenticate } from "../middleware/auth.js";
import type { User, RegisterInput, LoginInput, AuthResponse } from "../types/index.js";
const SALT_ROUNDS = 10;
export async function authRoutes(app: FastifyInstance): Promise<void> {
// POST /api/auth/register
app.post<{ Body: RegisterInput }>("/register", async (request, reply) => {
const { username, password, nickname } = request.body;
if (!username || !password) {
return reply.status(400).send({
error: "Bad Request",
message: "Username and password are required",
statusCode: 400,
});
}
if (password.length < 6) {
return reply.status(400).send({
error: "Bad Request",
message: "Password must be at least 6 characters",
statusCode: 400,
});
}
const existing = queryOne("SELECT id FROM users WHERE username = ?", [username]);
if (existing) {
return reply.status(409).send({
error: "Conflict",
message: "Username already exists",
statusCode: 409,
});
}
const id = crypto.randomUUID();
const passwordHash = await bcrypt.hash(password, SALT_ROUNDS);
const now = new Date().toISOString();
execute(
"INSERT INTO users (id, username, password_hash, nickname, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)",
[id, username, passwordHash, nickname || username, now, now]
);
const user = queryOne<User>(
"SELECT id, username, nickname, role, created_at, updated_at FROM users WHERE id = ?",
[id]
);
if (!user) {
return reply.status(500).send({ error: "Internal Error", message: "Failed to create user", statusCode: 500 });
}
const token = app.jwt.sign({ userId: id, username, role: user.role });
return reply.status(201).send({ token, user } satisfies AuthResponse);
});
// POST /api/auth/login
app.post<{ Body: LoginInput }>("/login", async (request, reply) => {
const { username, password } = request.body;
if (!username || !password) {
return reply.status(400).send({
error: "Bad Request",
message: "Username and password are required",
statusCode: 400,
});
}
const user = queryOne<User & { password_hash: string }>(
"SELECT * FROM users WHERE username = ?",
[username]
);
if (!user) {
return reply.status(401).send({
error: "Unauthorized",
message: "Invalid username or password",
statusCode: 401,
});
}
const valid = await bcrypt.compare(password, user.password_hash);
if (!valid) {
return reply.status(401).send({
error: "Unauthorized",
message: "Invalid username or password",
statusCode: 401,
});
}
const token = app.jwt.sign({ userId: user.id, username: user.username, role: user.role });
const { password_hash, ...safeUser } = user;
return { token, user: safeUser } satisfies AuthResponse;
});
// GET /api/auth/me — current user info
app.get("/me", { onRequest: [authenticate] }, async (request, reply) => {
const jwtUser = request.user as unknown as { userId: string };
const user = queryOne<User>(
"SELECT id, username, nickname, role, created_at, updated_at FROM users WHERE id = ?",
[jwtUser.userId]
);
if (!user) {
return reply.status(404).send({
error: "Not Found",
message: "User not found",
statusCode: 404,
});
}
return { data: user };
});
}
@@ -0,0 +1,51 @@
// Auto-generated Customer routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { CustomerService } from "../services/customer.js";
import type { CreateCustomerInput, UpdateCustomerInput } from "../types/index.js";
const service = new CustomerService();
export async function customersRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/customers — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/customers/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Customer not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/customers — create
app.post<{ Body: CreateCustomerInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/customers/:id — update
app.put<{ Params: { id: string }; Body: UpdateCustomerInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Customer not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/customers/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Customer not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Food routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { FoodService } from "../services/food.js";
import type { CreateFoodInput, UpdateFoodInput } from "../types/index.js";
const service = new FoodService();
export async function foodsRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/foods — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/foods/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Food not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/foods — create
app.post<{ Body: CreateFoodInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/foods/:id — update
app.put<{ Params: { id: string }; Body: UpdateFoodInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Food not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/foods/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Food not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Logistic routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { LogisticService } from "../services/logistic.js";
import type { CreateLogisticInput, UpdateLogisticInput } from "../types/index.js";
const service = new LogisticService();
export async function logisticsRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/logistics — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/logistics/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Logistic not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/logistics — create
app.post<{ Body: CreateLogisticInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/logistics/:id — update
app.put<{ Params: { id: string }; Body: UpdateLogisticInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Logistic not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/logistics/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Logistic not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated MealPlan routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { MealPlanService } from "../services/meal_plan.js";
import type { CreateMealPlanInput, UpdateMealPlanInput } from "../types/index.js";
const service = new MealPlanService();
export async function meal_plansRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/meal_plans — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/meal_plans/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "MealPlan not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/meal_plans — create
app.post<{ Body: CreateMealPlanInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/meal_plans/:id — update
app.put<{ Params: { id: string }; Body: UpdateMealPlanInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "MealPlan not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/meal_plans/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "MealPlan not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Nutrition routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { NutritionService } from "../services/nutrition.js";
import type { CreateNutritionInput, UpdateNutritionInput } from "../types/index.js";
const service = new NutritionService();
export async function nutritionRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/nutrition — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/nutrition/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Nutrition not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/nutrition — create
app.post<{ Body: CreateNutritionInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/nutrition/:id — update
app.put<{ Params: { id: string }; Body: UpdateNutritionInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Nutrition not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/nutrition/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Nutrition not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated OrderItem routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { OrderItemService } from "../services/order_item.js";
import type { CreateOrderItemInput, UpdateOrderItemInput } from "../types/index.js";
const service = new OrderItemService();
export async function order_itemsRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/order_items — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/order_items/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "OrderItem not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/order_items — create
app.post<{ Body: CreateOrderItemInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/order_items/:id — update
app.put<{ Params: { id: string }; Body: UpdateOrderItemInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "OrderItem not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/order_items/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "OrderItem not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Order routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { OrderService } from "../services/order.js";
import type { CreateOrderInput, UpdateOrderInput } from "../types/index.js";
const service = new OrderService();
export async function ordersRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/orders — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/orders/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Order not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/orders — create
app.post<{ Body: CreateOrderInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/orders/:id — update
app.put<{ Params: { id: string }; Body: UpdateOrderInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Order not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/orders/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Order not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Product routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { ProductService } from "../services/product.js";
import type { CreateProductInput, UpdateProductInput } from "../types/index.js";
const service = new ProductService();
export async function productsRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/products — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/products/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Product not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/products — create
app.post<{ Body: CreateProductInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/products/:id — update
app.put<{ Params: { id: string }; Body: UpdateProductInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Product not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/products/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Product not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated ShoppingList routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { ShoppingListService } from "../services/shopping_list.js";
import type { CreateShoppingListInput, UpdateShoppingListInput } from "../types/index.js";
const service = new ShoppingListService();
export async function shopping_listsRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/shopping_lists — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/shopping_lists/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "ShoppingList not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/shopping_lists — create
app.post<{ Body: CreateShoppingListInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/shopping_lists/:id — update
app.put<{ Params: { id: string }; Body: UpdateShoppingListInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "ShoppingList not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/shopping_lists/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "ShoppingList not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated Template routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { TemplateService } from "../services/template.js";
import type { CreateTemplateInput, UpdateTemplateInput } from "../types/index.js";
const service = new TemplateService();
export async function templatesRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/templates — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/templates/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Template not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/templates — create
app.post<{ Body: CreateTemplateInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/templates/:id — update
app.put<{ Params: { id: string }; Body: UpdateTemplateInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "Template not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/templates/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "Template not found", statusCode: 404 });
}
return reply.status(204).send();
});
}
@@ -0,0 +1,51 @@
// Auto-generated User routes
import type { FastifyInstance } from "fastify";
import { authenticate } from "../middleware/auth.js";
import { UserService } from "../services/user.js";
import type { CreateUserInput, UpdateUserInput } from "../types/index.js";
const service = new UserService();
export async function usersRoutes(app: FastifyInstance): Promise<void> {
// All routes require authentication
app.addHook("onRequest", authenticate);
// GET /api/users — list
app.get("/", async (request, reply) => {
const items = service.list();
return { data: items };
});
// GET /api/users/:id — get by id
app.get<{ Params: { id: string } }>("/:id", async (request, reply) => {
const item = service.getById(request.params.id);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "User not found", statusCode: 404 });
}
return { data: item };
});
// POST /api/users — create
app.post<{ Body: CreateUserInput }>("/", async (request, reply) => {
const item = service.create(request.body);
return reply.status(201).send({ data: item });
});
// PUT /api/users/:id — update
app.put<{ Params: { id: string }; Body: UpdateUserInput }>("/:id", async (request, reply) => {
const item = service.update(request.params.id, request.body);
if (!item) {
return reply.status(404).send({ error: "Not Found", message: "User not found", statusCode: 404 });
}
return { data: item };
});
// DELETE /api/users/:id — delete
app.delete<{ Params: { id: string } }>("/:id", async (request, reply) => {
const deleted = service.delete(request.params.id);
if (!deleted) {
return reply.status(404).send({ error: "Not Found", message: "User not found", statusCode: 404 });
}
return reply.status(204).send();
});
}