75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
import { z } from 'zod/v4';
|
|
import { ProductCategory, ServingUnit, ProductSource } from '../enums/product.enums.js';
|
|
|
|
export const NutritionInfoSchema = z.object({
|
|
calories: z.number().min(0),
|
|
protein: z.number().min(0),
|
|
carbs: z.number().min(0),
|
|
fat: z.number().min(0),
|
|
fiber: z.number().min(0).optional(),
|
|
sugar: z.number().min(0).optional(),
|
|
sodium: z.number().min(0).optional(),
|
|
saturatedFat: z.number().min(0).optional(),
|
|
cholesterol: z.number().min(0).optional(),
|
|
});
|
|
|
|
export const CreateProductSchema = z.object({
|
|
name: z.string().min(1).max(200).trim(),
|
|
brand: z.string().max(200).trim().optional(),
|
|
barcode: z
|
|
.string()
|
|
.regex(/^\d{8,14}$/, 'Barcode must be 8-14 digits')
|
|
.optional(),
|
|
category: z.nativeEnum(ProductCategory),
|
|
servingSize: z.number().positive(),
|
|
servingUnit: z.nativeEnum(ServingUnit),
|
|
densityGPerMl: z.number().positive().optional(),
|
|
nutrition: NutritionInfoSchema,
|
|
tags: z.array(z.string().min(1).max(50).trim()).max(20).default([]),
|
|
imageUrl: z.url().optional(),
|
|
source: z.nativeEnum(ProductSource).default(ProductSource.MANUAL),
|
|
});
|
|
|
|
export const UpdateProductSchema = CreateProductSchema.partial();
|
|
|
|
export const ProductQuerySchema = z.object({
|
|
q: z.string().optional(),
|
|
category: z.nativeEnum(ProductCategory).optional(),
|
|
tags: z.string().optional(),
|
|
barcode: z.string().optional(),
|
|
cursor: z.string().optional(),
|
|
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
});
|
|
|
|
export const ProductResponseSchema = z.object({
|
|
_id: z.string(),
|
|
householdId: z.string(),
|
|
name: z.string(),
|
|
brand: z.string().optional(),
|
|
barcode: z.string().optional(),
|
|
category: z.string(),
|
|
servingSize: z.number(),
|
|
servingUnit: z.string(),
|
|
densityGPerMl: z.number().optional(),
|
|
nutrition: NutritionInfoSchema,
|
|
tags: z.array(z.string()),
|
|
imageUrl: z.string().optional(),
|
|
source: z.string(),
|
|
createdBy: z.string(),
|
|
createdAt: z.string(),
|
|
updatedAt: z.string(),
|
|
deletedAt: z.string().optional(),
|
|
});
|
|
|
|
export const ProductListResponseSchema = z.object({
|
|
data: z.array(ProductResponseSchema),
|
|
pagination: z.object({
|
|
cursor: z.string().nullable(),
|
|
hasMore: z.boolean(),
|
|
total: z.number().optional(),
|
|
}),
|
|
});
|
|
|
|
export type CreateProductInput = z.infer<typeof CreateProductSchema>;
|
|
export type UpdateProductInput = z.infer<typeof UpdateProductSchema>;
|
|
export type ProductQueryInput = z.infer<typeof ProductQuerySchema>;
|