Derive client domain types from the shared schema contracts

Add entity/response Zod schemas to @trek/shared (place, trip, assignment, day, budget, packing, reservation), each matched against the producing server service, and re-export them from client types.ts instead of the hand-written duplicates that had drifted (name/title, amount/total_price, owner_id/user_id, cover_url/cover_image, ...). Updates the call sites and test fixtures the corrected types surfaced; type-only, no runtime behaviour change.
This commit is contained in:
Maurice
2026-05-31 15:42:39 +02:00
parent 239a68bb48
commit 3977a5ecba
52 changed files with 732 additions and 435 deletions
+45
View File
@@ -13,6 +13,51 @@ import { z } from 'zod';
* permission checks + audit logging. Trip rows are wide, so responses stay open.
*/
/**
* Trip entity as returned by the trip list / get / create / update endpoints
* (server/src/services/tripService.ts -> TRIP_SELECT). Columns of the `trips`
* table plus the computed list fields (day_count, place_count, is_owner as 0/1,
* owner_username, shared_count). `is_archived` is the raw SQLite INTEGER.
*/
export const tripSchema = z.object({
id: z.number(),
user_id: z.number(),
title: z.string(),
description: z.string().nullable().optional(),
start_date: z.string().nullable().optional(),
end_date: z.string().nullable().optional(),
currency: z.string(),
cover_image: z.string().nullable().optional(),
is_archived: z.number(),
reminder_days: z.number(),
created_at: z.string().optional(),
updated_at: z.string().optional(),
// computed in TRIP_SELECT (list/get)
day_count: z.number().optional(),
place_count: z.number().optional(),
is_owner: z.number().optional(),
owner_username: z.string().optional(),
shared_count: z.number().optional(),
});
export type Trip = z.infer<typeof tripSchema>;
/**
* Trip member as returned by the members endpoint
* (server/src/services/tripService.ts -> listMembers). Owner + collaborators
* share this shape; `avatar_url` is resolved from the stored avatar.
*/
export const tripMemberSchema = z.object({
id: z.number(),
username: z.string(),
email: z.string().optional(),
avatar: z.string().nullable().optional(),
avatar_url: z.string().nullable().optional(),
role: z.string().optional(),
added_at: z.string().nullable().optional(),
invited_by_username: z.string().nullable().optional(),
});
export type TripMember = z.infer<typeof tripMemberSchema>;
export const tripCreateRequestSchema = z.object({
title: z.string().min(1),
description: z.string().nullable().optional(),