@burdenoff/microfe-mybodyshield 2026.1101.2 → 2026.1107.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"useMyBodyShieldApi.js","names":["clearGraphqlReadCaches","g","mybQuery","response","graphqlFetch","query","KEY","id","name","range","barcode","DEFAULT_PAGE","PROGRAM_FIELDS","EXERCISE_FIELDS","WORKOUT_FIELDS","SET_FIELDS","SESSION_FIELDS","GOAL_FIELDS","MEAL_FIELDS","PLAN_FIELDS","METRIC_FIELDS","RECOVERY_FIELDS","COACHING_FIELDS","GUIDANCE_FIELDS","INSIGHTS_FIELDS","AI_SETTINGS_FIELDS","AI_OPERATION_LOG_FIELDS","AI_PROCESSING_CONSENT_FIELDS","FOOD_FIELDS","MACROS_FIELDS","unwrapWorkoutItems","items","workout","exercises","useMybPrograms","useMyBodyShield","useQuery","filters","apiGatewayUrl","useMybProgram","result","program","workouts","useMybProgramWorkouts","programId","useMybWorkoutExercises","workoutId","a","b","useMybCreateProgram","qc","useQueryClient","useMutation","useMybUpdateProgram","vars","data","useMybTransitionProgram","useMybArchiveProgram","useMybAddWorkout","useMybAddExercise","useMybSessions","useMybSession","session","sets","useMybExerciseBestSet","trimmed","exerciseName","useMybStartSession","useMybLogSet","useMybCompleteSession","useMybGoals","useMybCreateGoal","useMybUpdateGoal","useMybAchieveGoal","useMybActiveNutritionPlan","memberId","useMybMeals","useMybDailyMacros","date","useMybCreateNutritionPlan","useMybUpdateNutritionPlan","useMybActivateNutritionPlan","useMybLogMeal","useMybDeleteMeal","useMybBodyMetrics","useMybRecordBodyMetric","useMybRecoveryLogs","metric","useMybLogRecovery","MINDFULNESS_EXERCISE_FIELDS","MINDFULNESS_SESSION_FIELDS","useMybMindfulnessExercises","useMybMindfulnessSessions","useMybCompleteMindfulnessSession","useMybCoaching","status","useMybCreateCoaching","useMybTransitionCoaching","useMybTodayGuidance","useMybInsights","rangeKey","useMybAiSettings","useMybUpdateAiSettings","useMybAiOperationLogs","pagination","useMybAiProcessingConsent","useMybSetAiProcessingConsent","useMybSearchFoods","useMybFoodByBarcode"],"sources":["../../../src/mybodyshield/hooks/useMyBodyShieldApi.ts"],"sourcesContent":["/**\n * MyBodyShield API hooks\n * @module mybodyshield/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-mybodyshield-svc`\n * federated GraphQL contract (the `myb*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useMyBodyShield } from '../context';\nimport type {\n MybConnection,\n MybProgram,\n MybProgramStatus,\n MybWorkout,\n MybExercise,\n MybWorkoutSession,\n MybSessionStatus,\n MybSessionSet,\n MybGoal,\n MybGoalStatus,\n MybMealLog,\n MybMealType,\n MybNutritionPlan,\n MybDailyMacros,\n MybBodyMetric,\n MybBodyMetricType,\n MybRecoveryLog,\n MybRecoveryMetric,\n MybCoachingRelationship,\n MybCoachingStatus,\n MybCreateProgramInput,\n MybUpdateProgramInput,\n MybCreateWorkoutInput,\n MybCreateExerciseInput,\n MybStartSessionInput,\n MybLogSetInput,\n MybCompleteSessionInput,\n MybCreateGoalInput,\n MybUpdateGoalInput,\n MybCreateNutritionPlanInput,\n MybUpdateNutritionPlanInput,\n MybLogMealInput,\n MybRecordMetricInput,\n MybLogRecoveryInput,\n MybCreateCoachingInput,\n PaginationInput,\n MybDeviceConnection,\n MybDeviceProvider,\n MybWearableMetricType,\n MybTodayGuidance,\n MybFood,\n MybInsights,\n MybAiSettings,\n MybAiOperationLogConnection,\n MybUpdateAiSettingsInput,\n MybAiProcessingConsent,\n MybMindfulnessExercise,\n MybMindfulnessSession,\n MybCompleteMindfulnessSessionInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * fe-libs' documented remedy is that write-performing callers clear those caches;\n * we do exactly that after every myb mutation so every follow-up read is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst mybQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n programs: ['mybodyshield', 'programs'] as const,\n program: (id: string) => ['mybodyshield', 'program', id] as const,\n programWorkouts: (id: string) => ['mybodyshield', 'program-workouts', id] as const,\n workoutExercises: (id: string) => ['mybodyshield', 'workout-exercises', id] as const,\n sessions: ['mybodyshield', 'sessions'] as const,\n session: (id: string) => ['mybodyshield', 'session', id] as const,\n exerciseBestSet: (name: string) => ['mybodyshield', 'exercise-best-set', name] as const,\n goals: ['mybodyshield', 'goals'] as const,\n goal: (id: string) => ['mybodyshield', 'goal', id] as const,\n meals: ['mybodyshield', 'meals'] as const,\n nutritionPlan: (id: string) => ['mybodyshield', 'nutrition-plan', id] as const,\n activePlan: ['mybodyshield', 'active-plan'] as const,\n dailyMacros: ['mybodyshield', 'daily-macros'] as const,\n bodyMetrics: ['mybodyshield', 'body-metrics'] as const,\n recovery: ['mybodyshield', 'recovery'] as const,\n coaching: ['mybodyshield', 'coaching'] as const,\n deviceConnections: ['mybodyshield', 'device-connections'] as const,\n guidance: ['mybodyshield', 'guidance'] as const,\n insights: (range: string) => ['mybodyshield', 'insights', range] as const,\n foodSearch: (query: string) => ['mybodyshield', 'food-search', query] as const,\n foodByBarcode: (barcode: string) => ['mybodyshield', 'food-barcode', barcode] as const,\n aiSettings: ['mybodyshield', 'ai-settings'] as const,\n aiOperationLogs: ['mybodyshield', 'ai-operation-logs'] as const,\n aiConsent: ['mybodyshield', 'ai-consent'] as const,\n mindfulnessExercises: ['mybodyshield', 'mindfulness-exercises'] as const,\n mindfulnessSessions: ['mybodyshield', 'mindfulness-sessions'] as const,\n};\n\nconst DEFAULT_PAGE: PaginationInput = { limit: 50 };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst PROGRAM_FIELDS = `\n id workspaceId memberId coachId name description goalType level phase status\n weeks daysPerWeek startDate endDate tags createdAt updatedAt\n`;\n\nconst EXERCISE_FIELDS = `\n id workspaceId workoutId name instructions muscleGroup sets reps targetWeight\n restSeconds orderIndex demo { id } createdAt updatedAt\n`;\n\nconst WORKOUT_FIELDS = `\n id workspaceId programId name description type dayOfWeek weekNumber orderIndex\n durationMin createdAt updatedAt\n`;\n\nconst SET_FIELDS = `\n id workspaceId sessionId exerciseName setNumber reps weight distanceM durationSec\n isPersonalRecord createdAt updatedAt\n`;\n\nconst SESSION_FIELDS = `\n id workspaceId memberId programId workoutId status scheduledFor startedAt completedAt\n caloriesBurned perceivedExertion notes createdAt updatedAt\n`;\n\nconst GOAL_FIELDS = `\n id workspaceId memberId title description type status targetValue currentValue\n baselineValue unit targetDate achievedAt createdAt updatedAt\n`;\n\nconst MEAL_FIELDS = `\n id workspaceId memberId planId name mealType calories proteinG carbsG fatG servings\n isFavorite loggedAt barcode createdAt updatedAt\n`;\n\nconst PLAN_FIELDS = `\n id workspaceId memberId coachId name goalType calorieTarget proteinTarget carbsTarget\n fatTarget startDate endDate isActive notes createdAt updatedAt\n`;\n\nconst METRIC_FIELDS = `\n id workspaceId memberId type value unit measuredAt notes photo { id } createdAt updatedAt\n`;\n\nconst RECOVERY_FIELDS = `\n id workspaceId memberId metric score sleepHours notes loggedAt createdAt updatedAt\n`;\n\nconst COACHING_FIELDS = `\n id workspaceId coachId memberId status specialty shareWorkouts shareNutrition\n shareMetrics startedAt endedAt notes createdAt updatedAt\n`;\n\nconst DEVICE_CONNECTION_FIELDS = `\n id workspaceId memberId provider status externalAccountId lastSyncedAt scopes createdAt updatedAt\n`;\n\nconst GUIDANCE_FIELDS = `\n memberId date readinessScore aiSummary cards { signal action reason }\n`;\n\nconst INSIGHTS_FIELDS = `\n dateRangeStart dateRangeEnd\n summary { consistencyStreakDays totalSessions totalVolumeKg averageReadiness macroAdherencePercent }\n daily { date sessions volumeKg readiness sleepHours calories proteinG carbsG fatG weight }\n goals { ${GOAL_FIELDS} }\n`;\n\nconst AI_SETTINGS_FIELDS = `\n id workspaceId memberId provider hasProviderKey modelName dailyAllowance dailyAllowanceUsed allowanceResetAt createdAt updatedAt\n`;\n\nconst AI_OPERATION_LOG_FIELDS = `\n id workspaceId memberId operationType provider modelName inputTokens outputTokens status errorMessage createdAt\n`;\n\nconst AI_PROCESSING_CONSENT_FIELDS = `\n id workspaceId actorId enabled acceptedAt withdrawnAt createdAt updatedAt\n`;\n\nconst FOOD_FIELDS = `\n barcode name brand servingG calories proteinG carbsG fatG imageUrl\n`;\n\nconst MACROS_FIELDS = `\n date calories proteinG carbsG fatG calorieTarget proteinTarget carbsTarget fatTarget\n`;\n\n/**\n * `MybWorkout.exercises` is a paginated `MybExerciseConnection` on the wire\n * (see `.hive-schema.graphql`); unwrap it back to the flat `MybExercise[]`\n * shape the rest of the app consumes.\n */\ntype MybWorkoutWithExerciseConnection = Omit<MybWorkout, 'exercises'> & {\n exercises: { items: MybExercise[] };\n};\n\nconst unwrapWorkoutItems = (items: MybWorkoutWithExerciseConnection[]): MybWorkout[] =>\n items.map(({ exercises, ...workout }) => ({ ...workout, exercises: exercises.items }));\n\n// ============================================================================\n// Programs (Training)\n// ============================================================================\n\nexport interface ProgramFilters {\n status?: MybProgramStatus;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybPrograms = (filters: ProgramFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.programs, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListPrograms: MybConnection<MybProgram> }>(\n `query MybListPrograms($status: MybProgramStatus, $memberId: ID, $pagination: PaginationInput) {\n mybListPrograms(status: $status, memberId: $memberId, pagination: $pagination) {\n items { ${PROGRAM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListPrograms;\n },\n });\n};\n\nexport const useMybProgram = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.program(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{\n mybProgram:\n | (Omit<MybProgram, 'workouts'> & {\n workouts: { items: MybWorkoutWithExerciseConnection[] };\n })\n | null;\n }>(\n `query MybProgram($id: ID!) {\n mybProgram(id: $id) {\n ${PROGRAM_FIELDS}\n workouts {\n items {\n ${WORKOUT_FIELDS}\n exercises { items { ${EXERCISE_FIELDS} } }\n }\n }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n if (!result.mybProgram) return null;\n const { workouts, ...program } = result.mybProgram;\n return { ...program, workouts: unwrapWorkoutItems(workouts.items) };\n },\n });\n};\n\nexport const useMybProgramWorkouts = (programId: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.programWorkouts(programId ?? ''),\n enabled: Boolean(programId),\n queryFn: async () => {\n const result = await mybQuery<{\n mybProgramWorkouts: { items: MybWorkoutWithExerciseConnection[] };\n }>(\n `query MybProgramWorkouts($programId: ID!) {\n mybProgramWorkouts(programId: $programId) {\n items {\n ${WORKOUT_FIELDS}\n exercises { items { ${EXERCISE_FIELDS} } }\n }\n }\n }`,\n { programId },\n apiGatewayUrl\n );\n return unwrapWorkoutItems(result.mybProgramWorkouts.items);\n },\n });\n};\n\n/**\n * Planned exercises for a single workout, in `orderIndex` order — the\n * guided-workout stepper (BOFF-4096) walks a live session's `workoutId`\n * through these to drive the \"next exercise\" flow.\n */\nexport const useMybWorkoutExercises = (workoutId: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.workoutExercises(workoutId ?? ''),\n enabled: Boolean(workoutId),\n queryFn: async () => {\n const result = await mybQuery<{ mybWorkoutExercises: { items: MybExercise[] } }>(\n `query MybWorkoutExercises($workoutId: ID!) {\n mybWorkoutExercises(workoutId: $workoutId, pagination: { limit: 100 }) {\n items { ${EXERCISE_FIELDS} }\n }\n }`,\n { workoutId },\n apiGatewayUrl\n );\n return result.mybWorkoutExercises.items.slice().sort((a, b) => a.orderIndex - b.orderIndex);\n },\n });\n};\n\nexport const useMybCreateProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateProgramInput) => {\n const result = await mybQuery<{ mybCreateProgram: MybProgram }>(\n `mutation MybCreateProgram($input: MybCreateProgramInput!) {\n mybCreateProgram(input: $input) { ${PROGRAM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateProgram;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.programs }),\n });\n};\n\nexport const useMybUpdateProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateProgramInput }) => {\n const result = await mybQuery<{ mybUpdateProgram: MybProgram }>(\n `mutation MybUpdateProgram($id: ID!, $input: MybUpdateProgramInput!) {\n mybUpdateProgram(id: $id, input: $input) { ${PROGRAM_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateProgram;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.programs });\n qc.invalidateQueries({ queryKey: KEY.program(data.id) });\n },\n });\n};\n\nexport const useMybTransitionProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: MybProgramStatus }) => {\n const result = await mybQuery<{ mybTransitionProgram: MybProgram }>(\n `mutation MybTransitionProgram($id: ID!, $status: MybProgramStatus!) {\n mybTransitionProgram(id: $id, status: $status) { ${PROGRAM_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybTransitionProgram;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.programs });\n qc.invalidateQueries({ queryKey: KEY.program(data.id) });\n },\n });\n};\n\nexport const useMybArchiveProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybArchiveProgram: boolean }>(\n `mutation MybArchiveProgram($id: ID!) { mybArchiveProgram(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybArchiveProgram;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.programs }),\n });\n};\n\nexport const useMybAddWorkout = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateWorkoutInput) => {\n const result = await mybQuery<{ mybAddWorkout: MybWorkout }>(\n `mutation MybAddWorkout($input: MybCreateWorkoutInput!) {\n mybAddWorkout(input: $input) { ${WORKOUT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybAddWorkout;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.program(data.programId) });\n qc.invalidateQueries({ queryKey: KEY.programWorkouts(data.programId) });\n },\n });\n};\n\nexport const useMybAddExercise = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateExerciseInput) => {\n const result = await mybQuery<{ mybAddExercise: { id: string; workoutId: string } }>(\n `mutation MybAddExercise($input: MybCreateExerciseInput!) {\n mybAddExercise(input: $input) { id workoutId }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybAddExercise;\n },\n onSuccess: () => {\n // Exercises live under a program's workouts; invalidate program + workout\n // caches so the newly-added exercise appears on the program detail tree.\n qc.invalidateQueries({ queryKey: ['mybodyshield', 'program'] });\n qc.invalidateQueries({ queryKey: ['mybodyshield', 'program-workouts'] });\n },\n });\n};\n\n// ============================================================================\n// Sessions / Sets (Training — live logging)\n// ============================================================================\n\nexport interface SessionFilters {\n status?: MybSessionStatus;\n programId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybSessions = (filters: SessionFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.sessions, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListSessions: MybConnection<MybWorkoutSession> }>(\n `query MybListSessions($status: MybSessionStatus, $programId: ID, $pagination: PaginationInput) {\n mybListSessions(status: $status, programId: $programId, pagination: $pagination) {\n items { ${SESSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n programId: filters.programId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListSessions;\n },\n });\n};\n\nexport const useMybSession = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.session(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{\n mybSession: (Omit<MybWorkoutSession, 'sets'> & { sets: { items: MybSessionSet[] } }) | null;\n }>(\n `query MybSession($id: ID!) {\n mybSession(id: $id) {\n ${SESSION_FIELDS}\n sets { items { ${SET_FIELDS} } }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n if (!result.mybSession) return null;\n const { sets, ...session } = result.mybSession;\n return { ...session, sets: sets.items };\n },\n });\n};\n\n/**\n * The calling member's own best-ever logged set for `exerciseName` (backend:\n * `mybExerciseBestSet`, self-scoped — no memberId argument). Drives live\n * auto-PR detection in the log-set dialog (BOFF-4096): `null` means the\n * member has never logged this exercise before, so there is no record to\n * beat yet.\n */\nexport const useMybExerciseBestSet = (exerciseName: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const trimmed = exerciseName.trim();\n return useQuery({\n queryKey: KEY.exerciseBestSet(trimmed),\n enabled: trimmed.length > 0,\n queryFn: async () => {\n const result = await mybQuery<{ mybExerciseBestSet: MybSessionSet | null }>(\n `query MybExerciseBestSet($exerciseName: String!) {\n mybExerciseBestSet(exerciseName: $exerciseName) { ${SET_FIELDS} }\n }`,\n { exerciseName: trimmed },\n apiGatewayUrl\n );\n return result.mybExerciseBestSet;\n },\n // Best-set history changes rarely mid-session; a short stale window\n // avoids refiring on every keystroke while the exercise name settles.\n staleTime: 15_000,\n });\n};\n\nexport const useMybStartSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybStartSessionInput) => {\n const result = await mybQuery<{ mybStartSession: MybWorkoutSession }>(\n `mutation MybStartSession($input: MybStartSessionInput!) {\n mybStartSession(input: $input) { ${SESSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybStartSession;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sessions }),\n });\n};\n\nexport const useMybLogSet = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogSetInput) => {\n const result = await mybQuery<{ mybLogSet: MybSessionSet }>(\n `mutation MybLogSet($input: MybLogSetInput!) {\n mybLogSet(input: $input) { ${SET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogSet;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.session(data.sessionId) });\n qc.invalidateQueries({ queryKey: KEY.sessions });\n // A just-logged set may itself now be the best-ever for this exercise —\n // refresh so the next auto-PR comparison (this session or a later one)\n // sees it (BOFF-4096).\n qc.invalidateQueries({ queryKey: KEY.exerciseBestSet(data.exerciseName) });\n },\n });\n};\n\nexport const useMybCompleteSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybCompleteSessionInput }) => {\n const result = await mybQuery<{ mybCompleteSession: MybWorkoutSession }>(\n `mutation MybCompleteSession($id: ID!, $input: MybCompleteSessionInput!) {\n mybCompleteSession(id: $id, input: $input) { ${SESSION_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybCompleteSession;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.session(data.id) });\n qc.invalidateQueries({ queryKey: KEY.sessions });\n },\n });\n};\n\n// ============================================================================\n// Goals (Progress)\n// ============================================================================\n\nexport interface GoalFilters {\n status?: MybGoalStatus;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybGoals = (filters: GoalFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.goals, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListGoals: MybConnection<MybGoal> }>(\n `query MybListGoals($status: MybGoalStatus, $memberId: ID, $pagination: PaginationInput) {\n mybListGoals(status: $status, memberId: $memberId, pagination: $pagination) {\n items { ${GOAL_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListGoals;\n },\n });\n};\n\nexport const useMybCreateGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateGoalInput) => {\n const result = await mybQuery<{ mybCreateGoal: MybGoal }>(\n `mutation MybCreateGoal($input: MybCreateGoalInput!) {\n mybCreateGoal(input: $input) { ${GOAL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\nexport const useMybUpdateGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateGoalInput }) => {\n const result = await mybQuery<{ mybUpdateGoal: MybGoal }>(\n `mutation MybUpdateGoal($id: ID!, $input: MybUpdateGoalInput!) {\n mybUpdateGoal(id: $id, input: $input) { ${GOAL_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\nexport const useMybAchieveGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybAchieveGoal: MybGoal }>(\n `mutation MybAchieveGoal($id: ID!) {\n mybAchieveGoal(id: $id) { ${GOAL_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybAchieveGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\n// ============================================================================\n// Nutrition (plans, meals, macros)\n// ============================================================================\n\nexport const useMybActiveNutritionPlan = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.activePlan, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybActiveNutritionPlan: MybNutritionPlan | null }>(\n `query MybActiveNutritionPlan($memberId: ID) {\n mybActiveNutritionPlan(memberId: $memberId) { ${PLAN_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybActiveNutritionPlan;\n },\n });\n};\n\nexport const useMybNutritionPlan = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.nutritionPlan(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{ mybNutritionPlan: MybNutritionPlan | null }>(\n `query MybNutritionPlan($id: ID!) {\n mybNutritionPlan(id: $id) {\n ${PLAN_FIELDS}\n meals { ${MEAL_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybNutritionPlan;\n },\n });\n};\n\nexport interface MealFilters {\n mealType?: MybMealType;\n planId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybMeals = (filters: MealFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.meals, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListMeals: MybConnection<MybMealLog> }>(\n `query MybListMeals($mealType: MybMealType, $planId: ID, $pagination: PaginationInput) {\n mybListMeals(mealType: $mealType, planId: $planId, pagination: $pagination) {\n items { ${MEAL_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n mealType: filters.mealType,\n planId: filters.planId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListMeals;\n },\n });\n};\n\nexport const useMybDailyMacros = (date?: string, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.dailyMacros, date ?? 'today', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybDailyMacros: MybDailyMacros }>(\n `query MybDailyMacros($date: DateTime, $memberId: ID) {\n mybDailyMacros(date: $date, memberId: $memberId) { ${MACROS_FIELDS} }\n }`,\n { date, memberId },\n apiGatewayUrl\n );\n return result.mybDailyMacros;\n },\n });\n};\n\nexport const useMybCreateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateNutritionPlanInput) => {\n const result = await mybQuery<{ mybCreateNutritionPlan: MybNutritionPlan }>(\n `mutation MybCreateNutritionPlan($input: MybCreateNutritionPlanInput!) {\n mybCreateNutritionPlan(input: $input) { ${PLAN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateNutritionPlan;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n },\n });\n};\n\nexport const useMybUpdateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateNutritionPlanInput }) => {\n const result = await mybQuery<{ mybUpdateNutritionPlan: MybNutritionPlan }>(\n `mutation MybUpdateNutritionPlan($id: ID!, $input: MybUpdateNutritionPlanInput!) {\n mybUpdateNutritionPlan(id: $id, input: $input) { ${PLAN_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateNutritionPlan;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.id) });\n },\n });\n};\n\nexport const useMybActivateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybActivateNutritionPlan: MybNutritionPlan }>(\n `mutation MybActivateNutritionPlan($id: ID!) {\n mybActivateNutritionPlan(id: $id) { ${PLAN_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybActivateNutritionPlan;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.id) });\n },\n });\n};\n\nexport const useMybLogMeal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogMealInput) => {\n const result = await mybQuery<{ mybLogMeal: MybMealLog }>(\n `mutation MybLogMeal($input: MybLogMealInput!) {\n mybLogMeal(input: $input) { ${MEAL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogMeal;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.meals });\n qc.invalidateQueries({ queryKey: KEY.dailyMacros });\n if (data.planId) qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.planId) });\n },\n });\n};\n\nexport const useMybDeleteMeal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybDeleteMeal: boolean }>(\n `mutation MybDeleteMeal($id: ID!) { mybDeleteMeal(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybDeleteMeal;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.meals });\n qc.invalidateQueries({ queryKey: KEY.dailyMacros });\n },\n });\n};\n\n// ============================================================================\n// Body metrics (Progress)\n// ============================================================================\n\nexport interface BodyMetricFilters {\n type?: MybBodyMetricType;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybBodyMetrics = (filters: BodyMetricFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.bodyMetrics, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListBodyMetrics: MybConnection<MybBodyMetric> }>(\n `query MybListBodyMetrics($type: MybBodyMetricType, $memberId: ID, $pagination: PaginationInput) {\n mybListBodyMetrics(type: $type, memberId: $memberId, pagination: $pagination) {\n items { ${METRIC_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n type: filters.type,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListBodyMetrics;\n },\n });\n};\n\nexport const useMybRecordBodyMetric = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybRecordMetricInput) => {\n const result = await mybQuery<{ mybRecordBodyMetric: MybBodyMetric }>(\n `mutation MybRecordBodyMetric($input: MybRecordMetricInput!) {\n mybRecordBodyMetric(input: $input) { ${METRIC_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybRecordBodyMetric;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.bodyMetrics }),\n });\n};\n\n// ============================================================================\n// Recovery (Wellbeing)\n// ============================================================================\n\nexport const useMybRecoveryLogs = (metric?: MybRecoveryMetric, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.recovery, metric ?? 'all', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListRecoveryLogs: MybConnection<MybRecoveryLog> }>(\n `query MybListRecoveryLogs($metric: MybRecoveryMetric, $memberId: ID) {\n mybListRecoveryLogs(metric: $metric, memberId: $memberId) {\n items { ${RECOVERY_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { metric, memberId },\n apiGatewayUrl\n );\n return result.mybListRecoveryLogs;\n },\n });\n};\n\nexport const useMybLogRecovery = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogRecoveryInput) => {\n const result = await mybQuery<{ mybLogRecovery: MybRecoveryLog }>(\n `mutation MybLogRecovery($input: MybLogRecoveryInput!) {\n mybLogRecovery(input: $input) { ${RECOVERY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogRecovery;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.recovery }),\n });\n};\n\nconst MINDFULNESS_EXERCISE_FIELDS = `\n id slug title description kind durationSeconds inhaleSeconds holdSeconds\n exhaleSeconds cycles contentSource\n`;\n\nconst MINDFULNESS_SESSION_FIELDS = `\n id workspaceId memberId startedAt completedAt durationSeconds cyclesCompleted createdAt\n exercise { ${MINDFULNESS_EXERCISE_FIELDS} }\n`;\n\nexport const useMybMindfulnessExercises = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.mindfulnessExercises,\n queryFn: async () => {\n const result = await mybQuery<{ mybListMindfulnessExercises: MybMindfulnessExercise[] }>(\n `query MybListMindfulnessExercises { mybListMindfulnessExercises { ${MINDFULNESS_EXERCISE_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybListMindfulnessExercises;\n },\n });\n};\n\nexport const useMybMindfulnessSessions = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.mindfulnessSessions,\n queryFn: async () => {\n const result = await mybQuery<{\n mybListMindfulnessSessions: MybConnection<MybMindfulnessSession>;\n }>(\n `query MybListMindfulnessSessions { mybListMindfulnessSessions { items { ${MINDFULNESS_SESSION_FIELDS} } pageInfo { cursor hasMore } } }`,\n {},\n apiGatewayUrl\n );\n return result.mybListMindfulnessSessions;\n },\n });\n};\n\nexport const useMybCompleteMindfulnessSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCompleteMindfulnessSessionInput) => {\n const result = await mybQuery<{ mybCompleteMindfulnessSession: MybMindfulnessSession }>(\n `mutation MybCompleteMindfulnessSession($input: MybCompleteMindfulnessSessionInput!) {\n mybCompleteMindfulnessSession(input: $input) { ${MINDFULNESS_SESSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCompleteMindfulnessSession;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.mindfulnessSessions }),\n });\n};\n\n// ============================================================================\n// Coaching (Wellbeing)\n// ============================================================================\n\nexport const useMybCoaching = (status?: MybCoachingStatus, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.coaching, status ?? 'all', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListCoaching: MybConnection<MybCoachingRelationship> }>(\n `query MybListCoaching($status: MybCoachingStatus, $memberId: ID) {\n mybListCoaching(status: $status, memberId: $memberId) {\n items { ${COACHING_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, memberId },\n apiGatewayUrl\n );\n return result.mybListCoaching;\n },\n });\n};\n\nexport const useMybCreateCoaching = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateCoachingInput) => {\n const result = await mybQuery<{ mybCreateCoaching: MybCoachingRelationship }>(\n `mutation MybCreateCoaching($input: MybCreateCoachingInput!) {\n mybCreateCoaching(input: $input) { ${COACHING_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateCoaching;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.coaching }),\n });\n};\n\nexport const useMybTransitionCoaching = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: MybCoachingStatus }) => {\n const result = await mybQuery<{ mybTransitionCoaching: MybCoachingRelationship }>(\n `mutation MybTransitionCoaching($id: ID!, $status: MybCoachingStatus!) {\n mybTransitionCoaching(id: $id, status: $status) { ${COACHING_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybTransitionCoaching;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.coaching }),\n });\n};\n\n// ============================================================================\n// Wearable device integrations (BOFF-4172)\n// ============================================================================\n\nexport const useMybDeviceConnections = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.deviceConnections, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListDeviceConnections: MybDeviceConnection[] }>(\n `query MybListDeviceConnections($memberId: ID) {\n mybListDeviceConnections(memberId: $memberId) { ${DEVICE_CONNECTION_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybListDeviceConnections;\n },\n });\n};\n\nexport const useMybConnectDevice = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: {\n provider: MybDeviceProvider;\n externalAccountId?: string;\n scopes?: string[];\n }) => {\n const result = await mybQuery<{ mybConnectDevice: MybDeviceConnection }>(\n `mutation MybConnectDevice($input: MybConnectDeviceInput!) {\n mybConnectDevice(input: $input) { ${DEVICE_CONNECTION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybConnectDevice;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.deviceConnections }),\n });\n};\n\nexport const useMybDisconnectDevice = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybDisconnectDevice: boolean }>(\n `mutation MybDisconnectDevice($id: ID!) { mybDisconnectDevice(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybDisconnectDevice;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.deviceConnections }),\n });\n};\n\nexport interface MybSyncReadingInput {\n metricType: MybWearableMetricType;\n value: number;\n unit?: string;\n recordedAt: string;\n}\n\n/**\n * Sync a batch of readings a native health bridge (Apple HealthKit / Google\n * Health Connect) already pulled on-device. The bridge itself is a Capacitor\n * plugin concern that lives in the app shell (`mybodyshield-app`), not this\n * MFE; this hook is the transport primitive it calls once it has readings to\n * push (BOFF-4172).\n */\nexport const useMybSyncDeviceReadings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { connectionId: string; readings: MybSyncReadingInput[] }) => {\n const result = await mybQuery<{ mybSyncDeviceReadings: unknown[] }>(\n `mutation MybSyncDeviceReadings($connectionId: ID!, $readings: [MybSyncReadingInput!]!) {\n mybSyncDeviceReadings(connectionId: $connectionId, readings: $readings) { id }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybSyncDeviceReadings;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.deviceConnections });\n qc.invalidateQueries({ queryKey: KEY.recovery });\n qc.invalidateQueries({ queryKey: KEY.bodyMetrics });\n },\n });\n};\n\n// ============================================================================\n// Adaptive guidance (BOFF-4174)\n// ============================================================================\n\nexport const useMybTodayGuidance = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.guidance, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybTodayGuidance: MybTodayGuidance }>(\n `query MybTodayGuidance($memberId: ID) {\n mybTodayGuidance(memberId: $memberId) { ${GUIDANCE_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybTodayGuidance;\n },\n // Guidance is derived from the day's logged data; a short stale window\n // avoids refetching on every focus while still catching a fresh log.\n staleTime: 60_000,\n });\n};\n\nexport interface InsightsRange {\n dateRangeStart?: string;\n dateRangeEnd?: string;\n /** Set only for an active coach/member relationship. */\n memberId?: string;\n}\n\nexport const useMybInsights = (range: InsightsRange = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const rangeKey = `${range.dateRangeStart ?? ''}|${range.dateRangeEnd ?? ''}|${range.memberId ?? 'me'}`;\n return useQuery({\n queryKey: KEY.insights(rangeKey),\n queryFn: async () => {\n const result = await mybQuery<{ mybInsights: MybInsights }>(\n `query MybInsights($dateRangeStart: DateTime, $dateRangeEnd: DateTime, $memberId: ID) {\n mybInsights(dateRangeStart: $dateRangeStart, dateRangeEnd: $dateRangeEnd, memberId: $memberId) { ${INSIGHTS_FIELDS} }\n }`,\n {\n dateRangeStart: range.dateRangeStart,\n dateRangeEnd: range.dateRangeEnd,\n memberId: range.memberId,\n },\n apiGatewayUrl\n );\n return result.mybInsights;\n },\n });\n};\n\n// ============================================================================\n// AI controls (BOFF-5949)\n// ============================================================================\n\nexport const useMybAiSettings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.aiSettings,\n queryFn: async () => {\n const result = await mybQuery<{ mybAiSettings: MybAiSettings }>(\n `query MybAiSettings { mybAiSettings { ${AI_SETTINGS_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybAiSettings;\n },\n });\n};\n\nexport const useMybUpdateAiSettings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybUpdateAiSettingsInput) => {\n const result = await mybQuery<{ mybUpdateAiSettings: MybAiSettings }>(\n `mutation MybUpdateAiSettings($input: MybUpdateAiSettingsInput!) {\n mybUpdateAiSettings(input: $input) { ${AI_SETTINGS_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybUpdateAiSettings;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.aiSettings });\n },\n });\n};\n\nexport const useMybAiOperationLogs = (pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.aiOperationLogs, pagination ?? DEFAULT_PAGE],\n queryFn: async () => {\n const result = await mybQuery<{ mybListAiOperationLogs: MybAiOperationLogConnection }>(\n `query MybListAiOperationLogs($pagination: PaginationInput) {\n mybListAiOperationLogs(pagination: $pagination) {\n items { ${AI_OPERATION_LOG_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: pagination ?? DEFAULT_PAGE },\n apiGatewayUrl\n );\n return result.mybListAiOperationLogs;\n },\n });\n};\n\n// ============================================================================\n// AI processing consent (BOFF-3838)\n// ============================================================================\n\nexport const useMybAiProcessingConsent = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.aiConsent,\n queryFn: async () => {\n const result = await mybQuery<{ mybMyAiProcessingConsent: MybAiProcessingConsent }>(\n `query MybMyAiProcessingConsent { mybMyAiProcessingConsent { ${AI_PROCESSING_CONSENT_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybMyAiProcessingConsent;\n },\n });\n};\n\nexport const useMybSetAiProcessingConsent = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (enabled: boolean) => {\n const result = await mybQuery<{ mybSetAiProcessingConsent: MybAiProcessingConsent }>(\n `mutation MybSetAiProcessingConsent($enabled: Boolean!) {\n mybSetAiProcessingConsent(enabled: $enabled) { ${AI_PROCESSING_CONSENT_FIELDS} }\n }`,\n { enabled },\n apiGatewayUrl\n );\n return result.mybSetAiProcessingConsent;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.aiConsent });\n },\n });\n};\n\n// ============================================================================\n// Food database — Open Food Facts (BOFF-4173)\n// ============================================================================\n\nexport const useMybSearchFoods = (query: string, limit = 10) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const trimmed = query.trim();\n return useQuery({\n queryKey: KEY.foodSearch(trimmed),\n enabled: trimmed.length >= 2,\n queryFn: async () => {\n const result = await mybQuery<{ mybSearchFoods: MybFood[] }>(\n `query MybSearchFoods($query: String!, $limit: Int) {\n mybSearchFoods(query: $query, limit: $limit) { ${FOOD_FIELDS} }\n }`,\n { query: trimmed, limit },\n apiGatewayUrl\n );\n return result.mybSearchFoods;\n },\n staleTime: 30_000,\n });\n};\n\nexport const useMybFoodByBarcode = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useMutation({\n mutationFn: async (barcode: string) => {\n const result = await mybQuery<{ mybFoodByBarcode: MybFood | null }>(\n `query MybFoodByBarcode($barcode: String!) {\n mybFoodByBarcode(barcode: $barcode) { ${FOOD_FIELDS} }\n }`,\n { barcode },\n apiGatewayUrl\n );\n return result.mybFoodByBarcode;\n },\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useMyBodyShieldApi.js","names":["clearGraphqlReadCaches","g","mybQuery","response","graphqlFetch","query","KEY","id","name","range","barcode","DEFAULT_PAGE","PROGRAM_FIELDS","EXERCISE_FIELDS","WORKOUT_FIELDS","SET_FIELDS","SESSION_FIELDS","GOAL_FIELDS","MEAL_FIELDS","PLAN_FIELDS","METRIC_FIELDS","RECOVERY_FIELDS","COACHING_FIELDS","GUIDANCE_FIELDS","INSIGHTS_FIELDS","AI_SETTINGS_FIELDS","AI_OPERATION_LOG_FIELDS","AI_PROCESSING_CONSENT_FIELDS","FOOD_FIELDS","MACROS_FIELDS","unwrapWorkoutItems","items","workout","exercises","useMybPrograms","useMyBodyShield","useQuery","filters","apiGatewayUrl","useMybProgram","result","program","workouts","useMybProgramWorkouts","programId","useMybWorkoutExercises","workoutId","a","b","useMybCreateProgram","qc","useQueryClient","useMutation","useMybUpdateProgram","vars","data","useMybTransitionProgram","useMybArchiveProgram","useMybAddWorkout","useMybAddExercise","useMybSessions","useMybSession","session","sets","useMybExerciseBestSet","trimmed","exerciseName","useMybStartSession","useMybLogSet","useMybCompleteSession","useMybGoals","useMybCreateGoal","useMybUpdateGoal","useMybAchieveGoal","useMybActiveNutritionPlan","memberId","useMybMeals","useMybDailyMacros","date","useMybCreateNutritionPlan","useMybUpdateNutritionPlan","useMybActivateNutritionPlan","useMybLogMeal","useMybDeleteMeal","useMybBodyMetrics","useMybRecordBodyMetric","useMybRecoveryLogs","metric","useMybLogRecovery","MINDFULNESS_EXERCISE_FIELDS","MINDFULNESS_SESSION_FIELDS","useMybMindfulnessExercises","useMybMindfulnessSessions","useMybCompleteMindfulnessSession","CHALLENGE_FIELDS","SOCIAL_PROFILE_FIELDS","SOCIAL_POST_FIELDS","FEED_POLL_MS","useMybChallenges","status","useMybChallengeLeaderboard","challengeId","useMybCreateChallenge","useChallengeMembershipMutation","operation","useMybJoinChallenge","useMybLeaveChallenge","useMybCancelChallenge","useMybMySocialProfile","useMybUpdateMySocialProfile","useMybSocialFeed","pagination","keepPreviousData","useMybShareableItems","useMybShareToFeed","usePostMutation","postId","useMybGiveKudos","useMybRemoveKudos","useMybDeleteMySocialPost","useMybModerateSocialPost","useMybCoaching","useMybCreateCoaching","useMybTransitionCoaching","useMybTodayGuidance","useMybInsights","rangeKey","useMybAiSettings","useMybUpdateAiSettings","useMybAiOperationLogs","useMybAiProcessingConsent","useMybSetAiProcessingConsent","useMybSearchFoods","useMybFoodByBarcode"],"sources":["../../../src/mybodyshield/hooks/useMyBodyShieldApi.ts"],"sourcesContent":["/**\n * MyBodyShield API hooks\n * @module mybodyshield/hooks\n *\n * React-Query hooks wired DIRECTLY to the real `wspace-mybodyshield-svc`\n * federated GraphQL contract (the `myb*` operations). Every query/mutation\n * below uses an inline gql string whose fields match the svc\n * `.hive-schema.graphql` exactly. No mock data.\n *\n * Transport: `graphqlFetch({ gateway: 'workspace', workspaceToken: true })` —\n * the host shell supplies the gateway base URL + a workspace-scoped token.\n */\n\nimport { keepPreviousData, useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useMyBodyShield } from '../context';\nimport type {\n MybConnection,\n MybProgram,\n MybProgramStatus,\n MybWorkout,\n MybExercise,\n MybWorkoutSession,\n MybSessionStatus,\n MybSessionSet,\n MybGoal,\n MybGoalStatus,\n MybMealLog,\n MybMealType,\n MybNutritionPlan,\n MybDailyMacros,\n MybBodyMetric,\n MybBodyMetricType,\n MybRecoveryLog,\n MybRecoveryMetric,\n MybCoachingRelationship,\n MybCoachingStatus,\n MybCreateProgramInput,\n MybUpdateProgramInput,\n MybCreateWorkoutInput,\n MybCreateExerciseInput,\n MybStartSessionInput,\n MybLogSetInput,\n MybCompleteSessionInput,\n MybCreateGoalInput,\n MybUpdateGoalInput,\n MybCreateNutritionPlanInput,\n MybUpdateNutritionPlanInput,\n MybLogMealInput,\n MybRecordMetricInput,\n MybLogRecoveryInput,\n MybCreateCoachingInput,\n PaginationInput,\n MybDeviceConnection,\n MybDeviceProvider,\n MybWearableMetricType,\n MybTodayGuidance,\n MybFood,\n MybInsights,\n MybAiSettings,\n MybAiOperationLogConnection,\n MybUpdateAiSettingsInput,\n MybAiProcessingConsent,\n MybMindfulnessExercise,\n MybMindfulnessSession,\n MybCompleteMindfulnessSessionInput,\n MybChallenge,\n MybChallengeStatus,\n MybCreateChallengeInput,\n MybLeaderboardEntry,\n MybSocialProfile,\n MybUpdateSocialProfileInput,\n MybSocialPost,\n MybShareableItem,\n MybShareToFeedInput,\n} from '../types';\n\n// ============================================================================\n// Transport\n// ============================================================================\n\n/**\n * fe-libs `graphqlFetch` coalesces `query` responses in an in-memory cache keyed\n * by operationName+variables for ~15s (mutations are never cached). A read\n * issued right after a write (e.g. React-Query refetch triggered by our\n * `invalidateQueries`) would otherwise return the PRE-mutation response until the\n * TTL expires — making just-created/updated rows invisible until a full reload.\n * fe-libs' documented remedy is that write-performing callers clear those caches;\n * we do exactly that after every myb mutation so every follow-up read is fresh.\n */\ntype GraphqlReadCacheGlobals = {\n __graphqlFetchResponseCache?: { clear: () => void };\n __graphqlFetchPendingResponses?: { clear: () => void };\n __boffGraphQLResponseCache?: { clear: () => void };\n};\n\nconst clearGraphqlReadCaches = (): void => {\n const g = globalThis as GraphqlReadCacheGlobals;\n g.__graphqlFetchResponseCache?.clear();\n g.__graphqlFetchPendingResponses?.clear();\n g.__boffGraphQLResponseCache?.clear();\n};\n\nconst mybQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlReadCaches();\n }\n return response.data;\n};\n\n// React-Query key roots (one namespace per domain entity).\nconst KEY = {\n programs: ['mybodyshield', 'programs'] as const,\n program: (id: string) => ['mybodyshield', 'program', id] as const,\n programWorkouts: (id: string) => ['mybodyshield', 'program-workouts', id] as const,\n workoutExercises: (id: string) => ['mybodyshield', 'workout-exercises', id] as const,\n sessions: ['mybodyshield', 'sessions'] as const,\n session: (id: string) => ['mybodyshield', 'session', id] as const,\n exerciseBestSet: (name: string) => ['mybodyshield', 'exercise-best-set', name] as const,\n goals: ['mybodyshield', 'goals'] as const,\n goal: (id: string) => ['mybodyshield', 'goal', id] as const,\n meals: ['mybodyshield', 'meals'] as const,\n nutritionPlan: (id: string) => ['mybodyshield', 'nutrition-plan', id] as const,\n activePlan: ['mybodyshield', 'active-plan'] as const,\n dailyMacros: ['mybodyshield', 'daily-macros'] as const,\n bodyMetrics: ['mybodyshield', 'body-metrics'] as const,\n recovery: ['mybodyshield', 'recovery'] as const,\n coaching: ['mybodyshield', 'coaching'] as const,\n deviceConnections: ['mybodyshield', 'device-connections'] as const,\n guidance: ['mybodyshield', 'guidance'] as const,\n insights: (range: string) => ['mybodyshield', 'insights', range] as const,\n foodSearch: (query: string) => ['mybodyshield', 'food-search', query] as const,\n foodByBarcode: (barcode: string) => ['mybodyshield', 'food-barcode', barcode] as const,\n aiSettings: ['mybodyshield', 'ai-settings'] as const,\n aiOperationLogs: ['mybodyshield', 'ai-operation-logs'] as const,\n aiConsent: ['mybodyshield', 'ai-consent'] as const,\n mindfulnessExercises: ['mybodyshield', 'mindfulness-exercises'] as const,\n mindfulnessSessions: ['mybodyshield', 'mindfulness-sessions'] as const,\n challenges: ['mybodyshield', 'challenges'] as const,\n leaderboard: (id: string) => ['mybodyshield', 'leaderboard', id] as const,\n socialProfile: ['mybodyshield', 'social-profile'] as const,\n socialFeed: ['mybodyshield', 'social-feed'] as const,\n shareableItems: ['mybodyshield', 'shareable-items'] as const,\n};\n\nconst DEFAULT_PAGE: PaginationInput = { limit: 50 };\n\n// ============================================================================\n// Reusable gql field selections (codegen-free strictness)\n// ============================================================================\n\nconst PROGRAM_FIELDS = `\n id workspaceId memberId coachId name description goalType level phase status\n weeks daysPerWeek startDate endDate tags createdAt updatedAt\n`;\n\nconst EXERCISE_FIELDS = `\n id workspaceId workoutId name instructions muscleGroup sets reps targetWeight\n restSeconds orderIndex demo { id } createdAt updatedAt\n`;\n\nconst WORKOUT_FIELDS = `\n id workspaceId programId name description type dayOfWeek weekNumber orderIndex\n durationMin createdAt updatedAt\n`;\n\nconst SET_FIELDS = `\n id workspaceId sessionId exerciseName setNumber reps weight distanceM durationSec\n isPersonalRecord createdAt updatedAt\n`;\n\nconst SESSION_FIELDS = `\n id workspaceId memberId programId workoutId status scheduledFor startedAt completedAt\n caloriesBurned perceivedExertion notes createdAt updatedAt\n`;\n\nconst GOAL_FIELDS = `\n id workspaceId memberId title description type status targetValue currentValue\n baselineValue unit targetDate achievedAt createdAt updatedAt\n`;\n\nconst MEAL_FIELDS = `\n id workspaceId memberId planId name mealType calories proteinG carbsG fatG servings\n isFavorite loggedAt barcode createdAt updatedAt\n`;\n\nconst PLAN_FIELDS = `\n id workspaceId memberId coachId name goalType calorieTarget proteinTarget carbsTarget\n fatTarget startDate endDate isActive notes createdAt updatedAt\n`;\n\nconst METRIC_FIELDS = `\n id workspaceId memberId type value unit measuredAt notes photo { id } createdAt updatedAt\n`;\n\nconst RECOVERY_FIELDS = `\n id workspaceId memberId metric score sleepHours notes loggedAt createdAt updatedAt\n`;\n\nconst COACHING_FIELDS = `\n id workspaceId coachId memberId status specialty shareWorkouts shareNutrition\n shareMetrics startedAt endedAt notes createdAt updatedAt\n`;\n\nconst DEVICE_CONNECTION_FIELDS = `\n id workspaceId memberId provider status externalAccountId lastSyncedAt scopes createdAt updatedAt\n`;\n\nconst GUIDANCE_FIELDS = `\n memberId date readinessScore aiSummary cards { signal action reason }\n`;\n\nconst INSIGHTS_FIELDS = `\n dateRangeStart dateRangeEnd\n summary { consistencyStreakDays totalSessions totalVolumeKg averageReadiness macroAdherencePercent }\n daily { date sessions volumeKg readiness sleepHours calories proteinG carbsG fatG weight }\n goals { ${GOAL_FIELDS} }\n`;\n\nconst AI_SETTINGS_FIELDS = `\n id workspaceId memberId provider hasProviderKey modelName dailyAllowance dailyAllowanceUsed allowanceResetAt createdAt updatedAt\n`;\n\nconst AI_OPERATION_LOG_FIELDS = `\n id workspaceId memberId operationType provider modelName inputTokens outputTokens status errorMessage createdAt\n`;\n\nconst AI_PROCESSING_CONSENT_FIELDS = `\n id workspaceId actorId enabled acceptedAt withdrawnAt createdAt updatedAt\n`;\n\nconst FOOD_FIELDS = `\n barcode name brand servingG calories proteinG carbsG fatG imageUrl\n`;\n\nconst MACROS_FIELDS = `\n date calories proteinG carbsG fatG calorieTarget proteinTarget carbsTarget fatTarget\n`;\n\n/**\n * `MybWorkout.exercises` is a paginated `MybExerciseConnection` on the wire\n * (see `.hive-schema.graphql`); unwrap it back to the flat `MybExercise[]`\n * shape the rest of the app consumes.\n */\ntype MybWorkoutWithExerciseConnection = Omit<MybWorkout, 'exercises'> & {\n exercises: { items: MybExercise[] };\n};\n\nconst unwrapWorkoutItems = (items: MybWorkoutWithExerciseConnection[]): MybWorkout[] =>\n items.map(({ exercises, ...workout }) => ({ ...workout, exercises: exercises.items }));\n\n// ============================================================================\n// Programs (Training)\n// ============================================================================\n\nexport interface ProgramFilters {\n status?: MybProgramStatus;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybPrograms = (filters: ProgramFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.programs, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListPrograms: MybConnection<MybProgram> }>(\n `query MybListPrograms($status: MybProgramStatus, $memberId: ID, $pagination: PaginationInput) {\n mybListPrograms(status: $status, memberId: $memberId, pagination: $pagination) {\n items { ${PROGRAM_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListPrograms;\n },\n });\n};\n\nexport const useMybProgram = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.program(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{\n mybProgram:\n | (Omit<MybProgram, 'workouts'> & {\n workouts: { items: MybWorkoutWithExerciseConnection[] };\n })\n | null;\n }>(\n `query MybProgram($id: ID!) {\n mybProgram(id: $id) {\n ${PROGRAM_FIELDS}\n workouts {\n items {\n ${WORKOUT_FIELDS}\n exercises { items { ${EXERCISE_FIELDS} } }\n }\n }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n if (!result.mybProgram) return null;\n const { workouts, ...program } = result.mybProgram;\n return { ...program, workouts: unwrapWorkoutItems(workouts.items) };\n },\n });\n};\n\nexport const useMybProgramWorkouts = (programId: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.programWorkouts(programId ?? ''),\n enabled: Boolean(programId),\n queryFn: async () => {\n const result = await mybQuery<{\n mybProgramWorkouts: { items: MybWorkoutWithExerciseConnection[] };\n }>(\n `query MybProgramWorkouts($programId: ID!) {\n mybProgramWorkouts(programId: $programId) {\n items {\n ${WORKOUT_FIELDS}\n exercises { items { ${EXERCISE_FIELDS} } }\n }\n }\n }`,\n { programId },\n apiGatewayUrl\n );\n return unwrapWorkoutItems(result.mybProgramWorkouts.items);\n },\n });\n};\n\n/**\n * Planned exercises for a single workout, in `orderIndex` order — the\n * guided-workout stepper (BOFF-4096) walks a live session's `workoutId`\n * through these to drive the \"next exercise\" flow.\n */\nexport const useMybWorkoutExercises = (workoutId: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.workoutExercises(workoutId ?? ''),\n enabled: Boolean(workoutId),\n queryFn: async () => {\n const result = await mybQuery<{ mybWorkoutExercises: { items: MybExercise[] } }>(\n `query MybWorkoutExercises($workoutId: ID!) {\n mybWorkoutExercises(workoutId: $workoutId, pagination: { limit: 100 }) {\n items { ${EXERCISE_FIELDS} }\n }\n }`,\n { workoutId },\n apiGatewayUrl\n );\n return result.mybWorkoutExercises.items.slice().sort((a, b) => a.orderIndex - b.orderIndex);\n },\n });\n};\n\nexport const useMybCreateProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateProgramInput) => {\n const result = await mybQuery<{ mybCreateProgram: MybProgram }>(\n `mutation MybCreateProgram($input: MybCreateProgramInput!) {\n mybCreateProgram(input: $input) { ${PROGRAM_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateProgram;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.programs }),\n });\n};\n\nexport const useMybUpdateProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateProgramInput }) => {\n const result = await mybQuery<{ mybUpdateProgram: MybProgram }>(\n `mutation MybUpdateProgram($id: ID!, $input: MybUpdateProgramInput!) {\n mybUpdateProgram(id: $id, input: $input) { ${PROGRAM_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateProgram;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.programs });\n qc.invalidateQueries({ queryKey: KEY.program(data.id) });\n },\n });\n};\n\nexport const useMybTransitionProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: MybProgramStatus }) => {\n const result = await mybQuery<{ mybTransitionProgram: MybProgram }>(\n `mutation MybTransitionProgram($id: ID!, $status: MybProgramStatus!) {\n mybTransitionProgram(id: $id, status: $status) { ${PROGRAM_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybTransitionProgram;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.programs });\n qc.invalidateQueries({ queryKey: KEY.program(data.id) });\n },\n });\n};\n\nexport const useMybArchiveProgram = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybArchiveProgram: boolean }>(\n `mutation MybArchiveProgram($id: ID!) { mybArchiveProgram(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybArchiveProgram;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.programs }),\n });\n};\n\nexport const useMybAddWorkout = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateWorkoutInput) => {\n const result = await mybQuery<{ mybAddWorkout: MybWorkout }>(\n `mutation MybAddWorkout($input: MybCreateWorkoutInput!) {\n mybAddWorkout(input: $input) { ${WORKOUT_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybAddWorkout;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.program(data.programId) });\n qc.invalidateQueries({ queryKey: KEY.programWorkouts(data.programId) });\n },\n });\n};\n\nexport const useMybAddExercise = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateExerciseInput) => {\n const result = await mybQuery<{ mybAddExercise: { id: string; workoutId: string } }>(\n `mutation MybAddExercise($input: MybCreateExerciseInput!) {\n mybAddExercise(input: $input) { id workoutId }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybAddExercise;\n },\n onSuccess: () => {\n // Exercises live under a program's workouts; invalidate program + workout\n // caches so the newly-added exercise appears on the program detail tree.\n qc.invalidateQueries({ queryKey: ['mybodyshield', 'program'] });\n qc.invalidateQueries({ queryKey: ['mybodyshield', 'program-workouts'] });\n },\n });\n};\n\n// ============================================================================\n// Sessions / Sets (Training — live logging)\n// ============================================================================\n\nexport interface SessionFilters {\n status?: MybSessionStatus;\n programId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybSessions = (filters: SessionFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.sessions, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListSessions: MybConnection<MybWorkoutSession> }>(\n `query MybListSessions($status: MybSessionStatus, $programId: ID, $pagination: PaginationInput) {\n mybListSessions(status: $status, programId: $programId, pagination: $pagination) {\n items { ${SESSION_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n programId: filters.programId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListSessions;\n },\n });\n};\n\nexport const useMybSession = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.session(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{\n mybSession: (Omit<MybWorkoutSession, 'sets'> & { sets: { items: MybSessionSet[] } }) | null;\n }>(\n `query MybSession($id: ID!) {\n mybSession(id: $id) {\n ${SESSION_FIELDS}\n sets { items { ${SET_FIELDS} } }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n if (!result.mybSession) return null;\n const { sets, ...session } = result.mybSession;\n return { ...session, sets: sets.items };\n },\n });\n};\n\n/**\n * The calling member's own best-ever logged set for `exerciseName` (backend:\n * `mybExerciseBestSet`, self-scoped — no memberId argument). Drives live\n * auto-PR detection in the log-set dialog (BOFF-4096): `null` means the\n * member has never logged this exercise before, so there is no record to\n * beat yet.\n */\nexport const useMybExerciseBestSet = (exerciseName: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const trimmed = exerciseName.trim();\n return useQuery({\n queryKey: KEY.exerciseBestSet(trimmed),\n enabled: trimmed.length > 0,\n queryFn: async () => {\n const result = await mybQuery<{ mybExerciseBestSet: MybSessionSet | null }>(\n `query MybExerciseBestSet($exerciseName: String!) {\n mybExerciseBestSet(exerciseName: $exerciseName) { ${SET_FIELDS} }\n }`,\n { exerciseName: trimmed },\n apiGatewayUrl\n );\n return result.mybExerciseBestSet;\n },\n // Best-set history changes rarely mid-session; a short stale window\n // avoids refiring on every keystroke while the exercise name settles.\n staleTime: 15_000,\n });\n};\n\nexport const useMybStartSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybStartSessionInput) => {\n const result = await mybQuery<{ mybStartSession: MybWorkoutSession }>(\n `mutation MybStartSession($input: MybStartSessionInput!) {\n mybStartSession(input: $input) { ${SESSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybStartSession;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.sessions }),\n });\n};\n\nexport const useMybLogSet = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogSetInput) => {\n const result = await mybQuery<{ mybLogSet: MybSessionSet }>(\n `mutation MybLogSet($input: MybLogSetInput!) {\n mybLogSet(input: $input) { ${SET_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogSet;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.session(data.sessionId) });\n qc.invalidateQueries({ queryKey: KEY.sessions });\n // A just-logged set may itself now be the best-ever for this exercise —\n // refresh so the next auto-PR comparison (this session or a later one)\n // sees it (BOFF-4096).\n qc.invalidateQueries({ queryKey: KEY.exerciseBestSet(data.exerciseName) });\n },\n });\n};\n\nexport const useMybCompleteSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybCompleteSessionInput }) => {\n const result = await mybQuery<{ mybCompleteSession: MybWorkoutSession }>(\n `mutation MybCompleteSession($id: ID!, $input: MybCompleteSessionInput!) {\n mybCompleteSession(id: $id, input: $input) { ${SESSION_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybCompleteSession;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.session(data.id) });\n qc.invalidateQueries({ queryKey: KEY.sessions });\n },\n });\n};\n\n// ============================================================================\n// Goals (Progress)\n// ============================================================================\n\nexport interface GoalFilters {\n status?: MybGoalStatus;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybGoals = (filters: GoalFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.goals, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListGoals: MybConnection<MybGoal> }>(\n `query MybListGoals($status: MybGoalStatus, $memberId: ID, $pagination: PaginationInput) {\n mybListGoals(status: $status, memberId: $memberId, pagination: $pagination) {\n items { ${GOAL_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n status: filters.status,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListGoals;\n },\n });\n};\n\nexport const useMybCreateGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateGoalInput) => {\n const result = await mybQuery<{ mybCreateGoal: MybGoal }>(\n `mutation MybCreateGoal($input: MybCreateGoalInput!) {\n mybCreateGoal(input: $input) { ${GOAL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\nexport const useMybUpdateGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateGoalInput }) => {\n const result = await mybQuery<{ mybUpdateGoal: MybGoal }>(\n `mutation MybUpdateGoal($id: ID!, $input: MybUpdateGoalInput!) {\n mybUpdateGoal(id: $id, input: $input) { ${GOAL_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\nexport const useMybAchieveGoal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybAchieveGoal: MybGoal }>(\n `mutation MybAchieveGoal($id: ID!) {\n mybAchieveGoal(id: $id) { ${GOAL_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybAchieveGoal;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.goals }),\n });\n};\n\n// ============================================================================\n// Nutrition (plans, meals, macros)\n// ============================================================================\n\nexport const useMybActiveNutritionPlan = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.activePlan, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybActiveNutritionPlan: MybNutritionPlan | null }>(\n `query MybActiveNutritionPlan($memberId: ID) {\n mybActiveNutritionPlan(memberId: $memberId) { ${PLAN_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybActiveNutritionPlan;\n },\n });\n};\n\nexport const useMybNutritionPlan = (id: string | undefined) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.nutritionPlan(id ?? ''),\n enabled: Boolean(id),\n queryFn: async () => {\n const result = await mybQuery<{ mybNutritionPlan: MybNutritionPlan | null }>(\n `query MybNutritionPlan($id: ID!) {\n mybNutritionPlan(id: $id) {\n ${PLAN_FIELDS}\n meals { ${MEAL_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybNutritionPlan;\n },\n });\n};\n\nexport interface MealFilters {\n mealType?: MybMealType;\n planId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybMeals = (filters: MealFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.meals, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListMeals: MybConnection<MybMealLog> }>(\n `query MybListMeals($mealType: MybMealType, $planId: ID, $pagination: PaginationInput) {\n mybListMeals(mealType: $mealType, planId: $planId, pagination: $pagination) {\n items { ${MEAL_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n mealType: filters.mealType,\n planId: filters.planId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListMeals;\n },\n });\n};\n\nexport const useMybDailyMacros = (date?: string, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.dailyMacros, date ?? 'today', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybDailyMacros: MybDailyMacros }>(\n `query MybDailyMacros($date: DateTime, $memberId: ID) {\n mybDailyMacros(date: $date, memberId: $memberId) { ${MACROS_FIELDS} }\n }`,\n { date, memberId },\n apiGatewayUrl\n );\n return result.mybDailyMacros;\n },\n });\n};\n\nexport const useMybCreateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateNutritionPlanInput) => {\n const result = await mybQuery<{ mybCreateNutritionPlan: MybNutritionPlan }>(\n `mutation MybCreateNutritionPlan($input: MybCreateNutritionPlanInput!) {\n mybCreateNutritionPlan(input: $input) { ${PLAN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateNutritionPlan;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n },\n });\n};\n\nexport const useMybUpdateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; input: MybUpdateNutritionPlanInput }) => {\n const result = await mybQuery<{ mybUpdateNutritionPlan: MybNutritionPlan }>(\n `mutation MybUpdateNutritionPlan($id: ID!, $input: MybUpdateNutritionPlanInput!) {\n mybUpdateNutritionPlan(id: $id, input: $input) { ${PLAN_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybUpdateNutritionPlan;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.id) });\n },\n });\n};\n\nexport const useMybActivateNutritionPlan = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybActivateNutritionPlan: MybNutritionPlan }>(\n `mutation MybActivateNutritionPlan($id: ID!) {\n mybActivateNutritionPlan(id: $id) { ${PLAN_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.mybActivateNutritionPlan;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.activePlan });\n qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.id) });\n },\n });\n};\n\nexport const useMybLogMeal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogMealInput) => {\n const result = await mybQuery<{ mybLogMeal: MybMealLog }>(\n `mutation MybLogMeal($input: MybLogMealInput!) {\n mybLogMeal(input: $input) { ${MEAL_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogMeal;\n },\n onSuccess: (data) => {\n qc.invalidateQueries({ queryKey: KEY.meals });\n qc.invalidateQueries({ queryKey: KEY.dailyMacros });\n if (data.planId) qc.invalidateQueries({ queryKey: KEY.nutritionPlan(data.planId) });\n },\n });\n};\n\nexport const useMybDeleteMeal = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybDeleteMeal: boolean }>(\n `mutation MybDeleteMeal($id: ID!) { mybDeleteMeal(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybDeleteMeal;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.meals });\n qc.invalidateQueries({ queryKey: KEY.dailyMacros });\n },\n });\n};\n\n// ============================================================================\n// Body metrics (Progress)\n// ============================================================================\n\nexport interface BodyMetricFilters {\n type?: MybBodyMetricType;\n memberId?: string;\n pagination?: PaginationInput;\n}\n\nexport const useMybBodyMetrics = (filters: BodyMetricFilters = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.bodyMetrics, filters],\n queryFn: async () => {\n const result = await mybQuery<{ mybListBodyMetrics: MybConnection<MybBodyMetric> }>(\n `query MybListBodyMetrics($type: MybBodyMetricType, $memberId: ID, $pagination: PaginationInput) {\n mybListBodyMetrics(type: $type, memberId: $memberId, pagination: $pagination) {\n items { ${METRIC_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n type: filters.type,\n memberId: filters.memberId,\n pagination: filters.pagination ?? DEFAULT_PAGE,\n },\n apiGatewayUrl\n );\n return result.mybListBodyMetrics;\n },\n });\n};\n\nexport const useMybRecordBodyMetric = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybRecordMetricInput) => {\n const result = await mybQuery<{ mybRecordBodyMetric: MybBodyMetric }>(\n `mutation MybRecordBodyMetric($input: MybRecordMetricInput!) {\n mybRecordBodyMetric(input: $input) { ${METRIC_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybRecordBodyMetric;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.bodyMetrics }),\n });\n};\n\n// ============================================================================\n// Recovery (Wellbeing)\n// ============================================================================\n\nexport const useMybRecoveryLogs = (metric?: MybRecoveryMetric, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.recovery, metric ?? 'all', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListRecoveryLogs: MybConnection<MybRecoveryLog> }>(\n `query MybListRecoveryLogs($metric: MybRecoveryMetric, $memberId: ID) {\n mybListRecoveryLogs(metric: $metric, memberId: $memberId) {\n items { ${RECOVERY_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { metric, memberId },\n apiGatewayUrl\n );\n return result.mybListRecoveryLogs;\n },\n });\n};\n\nexport const useMybLogRecovery = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybLogRecoveryInput) => {\n const result = await mybQuery<{ mybLogRecovery: MybRecoveryLog }>(\n `mutation MybLogRecovery($input: MybLogRecoveryInput!) {\n mybLogRecovery(input: $input) { ${RECOVERY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybLogRecovery;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.recovery }),\n });\n};\n\nconst MINDFULNESS_EXERCISE_FIELDS = `\n id slug title description kind durationSeconds inhaleSeconds holdSeconds\n exhaleSeconds cycles contentSource\n`;\n\nconst MINDFULNESS_SESSION_FIELDS = `\n id workspaceId memberId startedAt completedAt durationSeconds cyclesCompleted createdAt\n exercise { ${MINDFULNESS_EXERCISE_FIELDS} }\n`;\n\nexport const useMybMindfulnessExercises = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.mindfulnessExercises,\n queryFn: async () => {\n const result = await mybQuery<{ mybListMindfulnessExercises: MybMindfulnessExercise[] }>(\n `query MybListMindfulnessExercises { mybListMindfulnessExercises { ${MINDFULNESS_EXERCISE_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybListMindfulnessExercises;\n },\n });\n};\n\nexport const useMybMindfulnessSessions = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.mindfulnessSessions,\n queryFn: async () => {\n const result = await mybQuery<{\n mybListMindfulnessSessions: MybConnection<MybMindfulnessSession>;\n }>(\n `query MybListMindfulnessSessions { mybListMindfulnessSessions { items { ${MINDFULNESS_SESSION_FIELDS} } pageInfo { cursor hasMore } } }`,\n {},\n apiGatewayUrl\n );\n return result.mybListMindfulnessSessions;\n },\n });\n};\n\nexport const useMybCompleteMindfulnessSession = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCompleteMindfulnessSessionInput) => {\n const result = await mybQuery<{ mybCompleteMindfulnessSession: MybMindfulnessSession }>(\n `mutation MybCompleteMindfulnessSession($input: MybCompleteMindfulnessSessionInput!) {\n mybCompleteMindfulnessSession(input: $input) { ${MINDFULNESS_SESSION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCompleteMindfulnessSession;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.mindfulnessSessions }),\n });\n};\n\n// ============================================================================\n// Community (BOFF-4175): challenges, leaderboards, opt-in feed\n// ============================================================================\n\nconst CHALLENGE_FIELDS = `\n id workspaceId title description metric targetValue status startDate endDate\n createdAt updatedAt isJoined isMine participantCount\n`;\n\nconst SOCIAL_PROFILE_FIELDS = `id workspaceId memberId displayName shareActivity createdAt updatedAt`;\n\nconst SOCIAL_POST_FIELDS = `\n id workspaceId authorId authorDisplayName kind visibility sourceId title\n highlights { label value } caption kudosCount hasGivenKudos isMine createdAt\n`;\n\n/** Feed polling interval — the v1 feed refreshes by polling, not a live socket. */\nconst FEED_POLL_MS = 60_000;\n\nexport const useMybChallenges = (status?: MybChallengeStatus) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.challenges, status ?? 'all'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListChallenges: MybConnection<MybChallenge> }>(\n `query MybListChallenges($pagination: PaginationInput, $status: MybChallengeStatus) {\n mybListChallenges(pagination: $pagination, status: $status) {\n items { ${CHALLENGE_FIELDS} } pageInfo { cursor hasMore }\n }\n }`,\n { pagination: DEFAULT_PAGE, status: status ?? null },\n apiGatewayUrl\n );\n return result.mybListChallenges;\n },\n });\n};\n\nexport const useMybChallengeLeaderboard = (challengeId: string | null) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.leaderboard(challengeId ?? 'none'),\n enabled: Boolean(challengeId),\n refetchInterval: FEED_POLL_MS,\n queryFn: async () => {\n const result = await mybQuery<{ mybChallengeLeaderboard: MybLeaderboardEntry[] }>(\n `query MybChallengeLeaderboard($challengeId: ID!) {\n mybChallengeLeaderboard(challengeId: $challengeId) { memberId displayName rank value joinedAt }\n }`,\n { challengeId },\n apiGatewayUrl\n );\n return result.mybChallengeLeaderboard;\n },\n });\n};\n\nexport const useMybCreateChallenge = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateChallengeInput) => {\n const result = await mybQuery<{ mybCreateChallenge: MybChallenge }>(\n `mutation MybCreateChallenge($input: MybCreateChallengeInput!) {\n mybCreateChallenge(input: $input) { ${CHALLENGE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateChallenge;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.challenges }),\n });\n};\n\nconst useChallengeMembershipMutation = (operation: 'join' | 'leave' | 'cancel') => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (challengeId: string) => {\n if (operation === 'join') {\n await mybQuery(\n `mutation MybJoinChallenge($challengeId: ID!) { mybJoinChallenge(challengeId: $challengeId) { id } }`,\n { challengeId },\n apiGatewayUrl\n );\n } else if (operation === 'leave') {\n await mybQuery(\n `mutation MybLeaveChallenge($challengeId: ID!) { mybLeaveChallenge(challengeId: $challengeId) }`,\n { challengeId },\n apiGatewayUrl\n );\n } else {\n await mybQuery(\n `mutation MybCancelChallenge($id: ID!) { mybCancelChallenge(id: $id) { id } }`,\n { id: challengeId },\n apiGatewayUrl\n );\n }\n return challengeId;\n },\n onSuccess: (challengeId) => {\n void qc.invalidateQueries({ queryKey: KEY.challenges });\n void qc.invalidateQueries({ queryKey: KEY.leaderboard(challengeId) });\n },\n });\n};\n\nexport const useMybJoinChallenge = () => useChallengeMembershipMutation('join');\nexport const useMybLeaveChallenge = () => useChallengeMembershipMutation('leave');\nexport const useMybCancelChallenge = () => useChallengeMembershipMutation('cancel');\n\nexport const useMybMySocialProfile = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.socialProfile,\n queryFn: async () => {\n const result = await mybQuery<{ mybMySocialProfile: MybSocialProfile | null }>(\n `query MybMySocialProfile { mybMySocialProfile { ${SOCIAL_PROFILE_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybMySocialProfile;\n },\n });\n};\n\nexport const useMybUpdateMySocialProfile = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybUpdateSocialProfileInput) => {\n const result = await mybQuery<{ mybUpdateMySocialProfile: MybSocialProfile }>(\n `mutation MybUpdateMySocialProfile($input: MybUpdateSocialProfileInput!) {\n mybUpdateMySocialProfile(input: $input) { ${SOCIAL_PROFILE_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybUpdateMySocialProfile;\n },\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: KEY.socialProfile });\n void qc.invalidateQueries({ queryKey: KEY.socialFeed });\n void qc.invalidateQueries({ queryKey: KEY.challenges });\n },\n });\n};\n\nexport const useMybSocialFeed = (pagination: PaginationInput = { limit: 20 }) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.socialFeed, pagination],\n refetchInterval: FEED_POLL_MS,\n // Keep the posts on screen while a larger page loads after \"Show more\".\n placeholderData: keepPreviousData,\n queryFn: async () => {\n const result = await mybQuery<{ mybSocialFeed: MybConnection<MybSocialPost> }>(\n `query MybSocialFeed($pagination: PaginationInput) {\n mybSocialFeed(pagination: $pagination) { items { ${SOCIAL_POST_FIELDS} } pageInfo { cursor hasMore } }\n }`,\n { pagination },\n apiGatewayUrl\n );\n return result.mybSocialFeed;\n },\n });\n};\n\nexport const useMybShareableItems = (enabled: boolean) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.shareableItems,\n enabled,\n queryFn: async () => {\n const result = await mybQuery<{ mybShareableItems: MybShareableItem[] }>(\n `query MybShareableItems { mybShareableItems { kind sourceId title occurredAt alreadyShared } }`,\n {},\n apiGatewayUrl\n );\n return result.mybShareableItems;\n },\n });\n};\n\nexport const useMybShareToFeed = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybShareToFeedInput) => {\n const result = await mybQuery<{ mybShareToFeed: MybSocialPost }>(\n `mutation MybShareToFeed($input: MybShareToFeedInput!) {\n mybShareToFeed(input: $input) { ${SOCIAL_POST_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybShareToFeed;\n },\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: KEY.socialFeed });\n void qc.invalidateQueries({ queryKey: KEY.shareableItems });\n },\n });\n};\n\nconst usePostMutation = (operation: 'giveKudos' | 'removeKudos' | 'delete' | 'moderate') => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (postId: string) => {\n if (operation === 'giveKudos') {\n await mybQuery(\n `mutation MybGiveKudos($postId: ID!) { mybGiveKudos(postId: $postId) { id } }`,\n { postId },\n apiGatewayUrl\n );\n } else if (operation === 'removeKudos') {\n await mybQuery(\n `mutation MybRemoveKudos($postId: ID!) { mybRemoveKudos(postId: $postId) { id } }`,\n { postId },\n apiGatewayUrl\n );\n } else if (operation === 'delete') {\n await mybQuery(\n `mutation MybDeleteMySocialPost($id: ID!) { mybDeleteMySocialPost(id: $id) }`,\n { id: postId },\n apiGatewayUrl\n );\n } else {\n await mybQuery(\n `mutation MybModerateSocialPost($id: ID!) { mybModerateSocialPost(id: $id) }`,\n { id: postId },\n apiGatewayUrl\n );\n }\n return postId;\n },\n onSuccess: () => {\n void qc.invalidateQueries({ queryKey: KEY.socialFeed });\n void qc.invalidateQueries({ queryKey: KEY.shareableItems });\n },\n });\n};\n\nexport const useMybGiveKudos = () => usePostMutation('giveKudos');\nexport const useMybRemoveKudos = () => usePostMutation('removeKudos');\nexport const useMybDeleteMySocialPost = () => usePostMutation('delete');\nexport const useMybModerateSocialPost = () => usePostMutation('moderate');\n\n// ============================================================================\n// Coaching (Wellbeing)\n// ============================================================================\n\nexport const useMybCoaching = (status?: MybCoachingStatus, memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.coaching, status ?? 'all', memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListCoaching: MybConnection<MybCoachingRelationship> }>(\n `query MybListCoaching($status: MybCoachingStatus, $memberId: ID) {\n mybListCoaching(status: $status, memberId: $memberId) {\n items { ${COACHING_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { status, memberId },\n apiGatewayUrl\n );\n return result.mybListCoaching;\n },\n });\n};\n\nexport const useMybCreateCoaching = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybCreateCoachingInput) => {\n const result = await mybQuery<{ mybCreateCoaching: MybCoachingRelationship }>(\n `mutation MybCreateCoaching($input: MybCreateCoachingInput!) {\n mybCreateCoaching(input: $input) { ${COACHING_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybCreateCoaching;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.coaching }),\n });\n};\n\nexport const useMybTransitionCoaching = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { id: string; status: MybCoachingStatus }) => {\n const result = await mybQuery<{ mybTransitionCoaching: MybCoachingRelationship }>(\n `mutation MybTransitionCoaching($id: ID!, $status: MybCoachingStatus!) {\n mybTransitionCoaching(id: $id, status: $status) { ${COACHING_FIELDS} }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybTransitionCoaching;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.coaching }),\n });\n};\n\n// ============================================================================\n// Wearable device integrations (BOFF-4172)\n// ============================================================================\n\nexport const useMybDeviceConnections = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.deviceConnections, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybListDeviceConnections: MybDeviceConnection[] }>(\n `query MybListDeviceConnections($memberId: ID) {\n mybListDeviceConnections(memberId: $memberId) { ${DEVICE_CONNECTION_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybListDeviceConnections;\n },\n });\n};\n\nexport const useMybConnectDevice = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: {\n provider: MybDeviceProvider;\n externalAccountId?: string;\n scopes?: string[];\n }) => {\n const result = await mybQuery<{ mybConnectDevice: MybDeviceConnection }>(\n `mutation MybConnectDevice($input: MybConnectDeviceInput!) {\n mybConnectDevice(input: $input) { ${DEVICE_CONNECTION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybConnectDevice;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.deviceConnections }),\n });\n};\n\nexport const useMybDisconnectDevice = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await mybQuery<{ mybDisconnectDevice: boolean }>(\n `mutation MybDisconnectDevice($id: ID!) { mybDisconnectDevice(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.mybDisconnectDevice;\n },\n onSuccess: () => qc.invalidateQueries({ queryKey: KEY.deviceConnections }),\n });\n};\n\nexport interface MybSyncReadingInput {\n metricType: MybWearableMetricType;\n value: number;\n unit?: string;\n recordedAt: string;\n}\n\n/**\n * Sync a batch of readings a native health bridge (Apple HealthKit / Google\n * Health Connect) already pulled on-device. The bridge itself is a Capacitor\n * plugin concern that lives in the app shell (`mybodyshield-app`), not this\n * MFE; this hook is the transport primitive it calls once it has readings to\n * push (BOFF-4172).\n */\nexport const useMybSyncDeviceReadings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (vars: { connectionId: string; readings: MybSyncReadingInput[] }) => {\n const result = await mybQuery<{ mybSyncDeviceReadings: unknown[] }>(\n `mutation MybSyncDeviceReadings($connectionId: ID!, $readings: [MybSyncReadingInput!]!) {\n mybSyncDeviceReadings(connectionId: $connectionId, readings: $readings) { id }\n }`,\n vars,\n apiGatewayUrl\n );\n return result.mybSyncDeviceReadings;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.deviceConnections });\n qc.invalidateQueries({ queryKey: KEY.recovery });\n qc.invalidateQueries({ queryKey: KEY.bodyMetrics });\n },\n });\n};\n\n// ============================================================================\n// Adaptive guidance (BOFF-4174)\n// ============================================================================\n\nexport const useMybTodayGuidance = (memberId?: string) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.guidance, memberId ?? 'me'],\n queryFn: async () => {\n const result = await mybQuery<{ mybTodayGuidance: MybTodayGuidance }>(\n `query MybTodayGuidance($memberId: ID) {\n mybTodayGuidance(memberId: $memberId) { ${GUIDANCE_FIELDS} }\n }`,\n { memberId },\n apiGatewayUrl\n );\n return result.mybTodayGuidance;\n },\n // Guidance is derived from the day's logged data; a short stale window\n // avoids refetching on every focus while still catching a fresh log.\n staleTime: 60_000,\n });\n};\n\nexport interface InsightsRange {\n dateRangeStart?: string;\n dateRangeEnd?: string;\n /** Set only for an active coach/member relationship. */\n memberId?: string;\n}\n\nexport const useMybInsights = (range: InsightsRange = {}) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const rangeKey = `${range.dateRangeStart ?? ''}|${range.dateRangeEnd ?? ''}|${range.memberId ?? 'me'}`;\n return useQuery({\n queryKey: KEY.insights(rangeKey),\n queryFn: async () => {\n const result = await mybQuery<{ mybInsights: MybInsights }>(\n `query MybInsights($dateRangeStart: DateTime, $dateRangeEnd: DateTime, $memberId: ID) {\n mybInsights(dateRangeStart: $dateRangeStart, dateRangeEnd: $dateRangeEnd, memberId: $memberId) { ${INSIGHTS_FIELDS} }\n }`,\n {\n dateRangeStart: range.dateRangeStart,\n dateRangeEnd: range.dateRangeEnd,\n memberId: range.memberId,\n },\n apiGatewayUrl\n );\n return result.mybInsights;\n },\n });\n};\n\n// ============================================================================\n// AI controls (BOFF-5949)\n// ============================================================================\n\nexport const useMybAiSettings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.aiSettings,\n queryFn: async () => {\n const result = await mybQuery<{ mybAiSettings: MybAiSettings }>(\n `query MybAiSettings { mybAiSettings { ${AI_SETTINGS_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybAiSettings;\n },\n });\n};\n\nexport const useMybUpdateAiSettings = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (input: MybUpdateAiSettingsInput) => {\n const result = await mybQuery<{ mybUpdateAiSettings: MybAiSettings }>(\n `mutation MybUpdateAiSettings($input: MybUpdateAiSettingsInput!) {\n mybUpdateAiSettings(input: $input) { ${AI_SETTINGS_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.mybUpdateAiSettings;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.aiSettings });\n },\n });\n};\n\nexport const useMybAiOperationLogs = (pagination?: PaginationInput) => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: [...KEY.aiOperationLogs, pagination ?? DEFAULT_PAGE],\n queryFn: async () => {\n const result = await mybQuery<{ mybListAiOperationLogs: MybAiOperationLogConnection }>(\n `query MybListAiOperationLogs($pagination: PaginationInput) {\n mybListAiOperationLogs(pagination: $pagination) {\n items { ${AI_OPERATION_LOG_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n { pagination: pagination ?? DEFAULT_PAGE },\n apiGatewayUrl\n );\n return result.mybListAiOperationLogs;\n },\n });\n};\n\n// ============================================================================\n// AI processing consent (BOFF-3838)\n// ============================================================================\n\nexport const useMybAiProcessingConsent = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useQuery({\n queryKey: KEY.aiConsent,\n queryFn: async () => {\n const result = await mybQuery<{ mybMyAiProcessingConsent: MybAiProcessingConsent }>(\n `query MybMyAiProcessingConsent { mybMyAiProcessingConsent { ${AI_PROCESSING_CONSENT_FIELDS} } }`,\n {},\n apiGatewayUrl\n );\n return result.mybMyAiProcessingConsent;\n },\n });\n};\n\nexport const useMybSetAiProcessingConsent = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n const qc = useQueryClient();\n return useMutation({\n mutationFn: async (enabled: boolean) => {\n const result = await mybQuery<{ mybSetAiProcessingConsent: MybAiProcessingConsent }>(\n `mutation MybSetAiProcessingConsent($enabled: Boolean!) {\n mybSetAiProcessingConsent(enabled: $enabled) { ${AI_PROCESSING_CONSENT_FIELDS} }\n }`,\n { enabled },\n apiGatewayUrl\n );\n return result.mybSetAiProcessingConsent;\n },\n onSuccess: () => {\n qc.invalidateQueries({ queryKey: KEY.aiConsent });\n },\n });\n};\n\n// ============================================================================\n// Food database — Open Food Facts (BOFF-4173)\n// ============================================================================\n\nexport const useMybSearchFoods = (query: string, limit = 10) => {\n const { apiGatewayUrl } = useMyBodyShield();\n const trimmed = query.trim();\n return useQuery({\n queryKey: KEY.foodSearch(trimmed),\n enabled: trimmed.length >= 2,\n queryFn: async () => {\n const result = await mybQuery<{ mybSearchFoods: MybFood[] }>(\n `query MybSearchFoods($query: String!, $limit: Int) {\n mybSearchFoods(query: $query, limit: $limit) { ${FOOD_FIELDS} }\n }`,\n { query: trimmed, limit },\n apiGatewayUrl\n );\n return result.mybSearchFoods;\n },\n staleTime: 30_000,\n });\n};\n\nexport const useMybFoodByBarcode = () => {\n const { apiGatewayUrl } = useMyBodyShield();\n return useMutation({\n mutationFn: async (barcode: string) => {\n const result = await mybQuery<{ mybFoodByBarcode: MybFood | null }>(\n `query MybFoodByBarcode($barcode: String!) {\n mybFoodByBarcode(barcode: $barcode) { ${FOOD_FIELDS} }\n }`,\n { barcode },\n apiGatewayUrl\n );\n return result.mybFoodByBarcode;\n },\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Community — workspace challenges, live leaderboards and the opt-in feed.
3
+ * @module mybodyshield/pages/community
4
+ *
5
+ * Three tabs backed by the real `wspace-mybodyshield-svc` social module
6
+ * (BOFF-4175):
7
+ * - Feed: sessions and achievements members explicitly shared, with kudos,
8
+ * comments (platform entity comments) and moderator removal.
9
+ * - Challenges: create/join/leave workspace challenges and see the live
10
+ * leaderboard computed from completed workout sessions.
11
+ * - Privacy: the member's community display name and the opt-in switch.
12
+ * Nothing is shared until the member turns sharing on, and turning it off
13
+ * hides every post they published.
14
+ */
15
+ export declare function CommunityPage(): import('react').JSX.Element;
16
+ //# sourceMappingURL=CommunityPage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommunityPage.d.ts","sourceRoot":"","sources":["../../../../src/mybodyshield/pages/community/CommunityPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA09BH,wBAAgB,aAAa,gCAsD5B"}