This commit is contained in:
Nông Đức Huy
2026-08-13 23:20:23 +07:00
parent d9f159a8c3
commit cda5d21d0d
53 changed files with 2711 additions and 162 deletions
+12
View File
@@ -42,6 +42,18 @@ const csvList = <T extends z.ZodTypeAny>(item: T) =>
*/
export const productFilterSchema = cursorPageQuerySchema.extend({
q: z.string().trim().max(120).optional(),
/**
* Fetch specific products by id.
*
* Exists for callers that already hold a set of ids and need them rendered as
* cards — the wishlist is the first. Safe on a public endpoint because the
* usual visibility rules still apply: an id for an unpublished product simply
* does not come back. Capped so it cannot be used to dump the catalog in one
* request.
*/
ids: csvList(z.uuid()).refine((value) => !value || value.length <= 60, {
message: 'Too many ids',
}),
categorySlug: slugSchema.optional(),
collectionSlug: slugSchema.optional(),
brandSlugs: csvList(slugSchema),
+42
View File
@@ -0,0 +1,42 @@
import { z } from 'zod';
import { phoneSchema } from './common';
/**
* The shopper's own profile.
*
* Email is absent on purpose: changing the address an account signs in with is
* an identity change, not a profile edit, and needs its own verified flow. A
* `PATCH /account/profile` that quietly accepted a new email would be an
* account-takeover primitive.
*/
export const updateProfileSchema = z.object({
firstName: z.string().trim().min(1).max(80).optional(),
lastName: z.string().trim().min(1).max(80).optional(),
phone: phoneSchema.nullish(),
acceptsMarketing: z.boolean().optional(),
dateOfBirth: z.iso.date().nullish(),
});
export const customerAddressSchema = z.object({
fullName: z.string().trim().min(1).max(160),
phone: phoneSchema,
line1: z.string().trim().min(1).max(255),
line2: z.string().trim().max(255).nullish(),
ward: z.string().trim().max(120).nullish(),
district: z.string().trim().max(120).nullish(),
province: z.string().trim().min(1).max(120),
countryCode: z.string().trim().length(2).default('VN'),
postalCode: z.string().trim().max(20).nullish(),
isDefaultShipping: z.boolean().default(false),
isDefaultBilling: z.boolean().default(false),
});
/** Email is proof of nothing here — the endpoint is authenticated. */
export const wishlistItemSchema = z.object({
productId: z.uuid(),
});
export type UpdateProfileInput = z.output<typeof updateProfileSchema>;
export type CustomerAddressInput = z.output<typeof customerAddressSchema>;
export type WishlistItemInput = z.output<typeof wishlistItemSchema>;
+1
View File
@@ -19,3 +19,4 @@ export * from './users';
export * from './catalog-admin';
export * from './commerce';
export * from './content';
export * from './customers';