mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 19:41:09 +02:00
refactor(mana/web): consume shared AI Zod schemas via z.infer
Drops the hand-written MealAnalysisResult / AnalyzedFood / NutritionData
interfaces in nutriphi/{api,types}.ts and the IdentifyResult interface
in planta/api.ts. They are now type aliases that re-export the inferred
types from @mana/shared-types — same types the backend validates against
at the boundary, so frontend and backend can no longer drift.
Net result is end-to-end type safety: a field rename in the shared
schema lights up red in both apps/api routes and apps/mana/apps/web
consumers in the same tsc pass. No more interface duplication, no more
manual sync.
Storage shapes (LocalMeal, LocalGoal, LocalFavorite) stay module-local
because they compose the shared NutritionData / AnalyzedFood with
storage-specific BaseRecord fields (id, userId, _fieldTimestamps,
deletedAt, etc.) that have no place in the wire format.
Tests: 29/29 nutriphi + 20/20 planta still green — the shapes are
identical, only the source of the type aliases changed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0c0e31d2f3
commit
f9b83990c6
3 changed files with 19 additions and 42 deletions
|
|
@ -9,7 +9,11 @@
|
|||
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { getManaApiUrl } from '$lib/api/config';
|
||||
import type { NutritionData } from './types';
|
||||
// Wire format is the single source of truth in @mana/shared-types —
|
||||
// the backend validates AI responses with these same Zod schemas.
|
||||
import type { MealAnalysis } from '@mana/shared-types';
|
||||
|
||||
export type MealAnalysisResult = MealAnalysis;
|
||||
|
||||
export interface UploadMealPhotoResult {
|
||||
mediaId: string;
|
||||
|
|
@ -18,21 +22,6 @@ export interface UploadMealPhotoResult {
|
|||
storagePath: string;
|
||||
}
|
||||
|
||||
export interface AnalyzedFood {
|
||||
name: string;
|
||||
quantity?: string;
|
||||
calories?: number;
|
||||
}
|
||||
|
||||
export interface MealAnalysisResult {
|
||||
foods?: AnalyzedFood[];
|
||||
totalNutrition?: NutritionData;
|
||||
description?: string;
|
||||
confidence?: number;
|
||||
warnings?: string[];
|
||||
suggestions?: string[];
|
||||
}
|
||||
|
||||
async function authHeader(): Promise<Record<string, string>> {
|
||||
const token = await authStore.getAccessToken();
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
|
|
|
|||
|
|
@ -1,28 +1,21 @@
|
|||
/**
|
||||
* NutriPhi module types for the unified app.
|
||||
*
|
||||
* NutritionData and AnalyzedFood are re-exported from @mana/shared-types
|
||||
* because they double as the AI wire format (same Zod schema lives in
|
||||
* packages/shared-types/src/ai-schemas.ts and is used by the backend
|
||||
* generateObject() validator). Module-local types like LocalMeal compose
|
||||
* those shared shapes with storage-specific BaseRecord fields.
|
||||
*/
|
||||
|
||||
import type { BaseRecord } from '@mana/local-store';
|
||||
import type { NutritionData, AnalyzedFood } from '@mana/shared-types';
|
||||
|
||||
export type { NutritionData, AnalyzedFood };
|
||||
|
||||
export type MealType = 'breakfast' | 'lunch' | 'dinner' | 'snack';
|
||||
export type InputType = 'photo' | 'text';
|
||||
|
||||
export interface NutritionData {
|
||||
calories: number;
|
||||
protein: number;
|
||||
carbohydrates: number;
|
||||
fat: number;
|
||||
fiber: number;
|
||||
sugar: number;
|
||||
}
|
||||
|
||||
/** A single food item identified by Gemini Vision in a meal photo. */
|
||||
export interface AnalyzedFood {
|
||||
name: string;
|
||||
quantity?: string | null;
|
||||
calories?: number | null;
|
||||
}
|
||||
|
||||
export interface LocalMeal extends BaseRecord {
|
||||
date: string;
|
||||
mealType: MealType;
|
||||
|
|
|
|||
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
import { authStore } from '$lib/stores/auth.svelte';
|
||||
import { getManaApiUrl } from '$lib/api/config';
|
||||
// Wire format is the single source of truth in @mana/shared-types —
|
||||
// the backend validates AI responses with the same Zod schema.
|
||||
import type { PlantIdentification } from '@mana/shared-types';
|
||||
|
||||
export type IdentifyResult = PlantIdentification;
|
||||
|
||||
export interface UploadPhotoResult {
|
||||
storagePath: string;
|
||||
|
|
@ -16,16 +21,6 @@ export interface UploadPhotoResult {
|
|||
plantId: string | null;
|
||||
}
|
||||
|
||||
export interface IdentifyResult {
|
||||
scientificName?: string;
|
||||
commonNames?: string[];
|
||||
confidence?: number;
|
||||
healthAssessment?: string;
|
||||
wateringAdvice?: string;
|
||||
lightAdvice?: string;
|
||||
generalTips?: string[];
|
||||
}
|
||||
|
||||
async function authHeader(): Promise<Record<string, string>> {
|
||||
const token = await authStore.getAccessToken();
|
||||
return token ? { Authorization: `Bearer ${token}` } : {};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue