ADR-026: Client-Side Logging + linting fixes
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled
This commit is contained in:
@@ -94,8 +94,7 @@ export const apiFetch = async (
|
||||
// unless the path is already a full URL. This works for both browser and Node.js.
|
||||
const fullUrl = url.startsWith('http') ? url : joinUrl(API_BASE_URL, url);
|
||||
|
||||
logger.debug(`apiFetch: ${options.method || 'GET'} ${fullUrl}`);
|
||||
console.error(`[apiClient] apiFetch Request: ${options.method || 'GET'} ${fullUrl}`);
|
||||
logger.debug({ method: options.method || 'GET', url: fullUrl }, 'apiFetch: Request');
|
||||
|
||||
// Create a new headers object to avoid mutating the original options.
|
||||
const headers = new Headers(options.headers || {});
|
||||
@@ -150,7 +149,8 @@ export const apiFetch = async (
|
||||
// --- DEBUG LOGGING for failed requests ---
|
||||
if (!response.ok) {
|
||||
const responseText = await response.clone().text();
|
||||
logger.error({ url: fullUrl, status: response.status, body: responseText },
|
||||
logger.error(
|
||||
{ url: fullUrl, status: response.status, body: responseText },
|
||||
'apiFetch: Request failed',
|
||||
);
|
||||
}
|
||||
@@ -181,7 +181,11 @@ export const authedGet = (endpoint: string, options: ApiOptions = {}): Promise<R
|
||||
};
|
||||
|
||||
/** Helper for authenticated POST requests with a JSON body */
|
||||
export const authedPost = <T>(endpoint: string, body: T, options: ApiOptions = {}): Promise<Response> => {
|
||||
export const authedPost = <T>(
|
||||
endpoint: string,
|
||||
body: T,
|
||||
options: ApiOptions = {},
|
||||
): Promise<Response> => {
|
||||
return apiFetch(
|
||||
endpoint,
|
||||
{ method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) },
|
||||
@@ -204,7 +208,11 @@ export const authedPostForm = (
|
||||
};
|
||||
|
||||
/** Helper for authenticated PUT requests with a JSON body */
|
||||
export const authedPut = <T>(endpoint: string, body: T, options: ApiOptions = {}): Promise<Response> => {
|
||||
export const authedPut = <T>(
|
||||
endpoint: string,
|
||||
body: T,
|
||||
options: ApiOptions = {},
|
||||
): Promise<Response> => {
|
||||
return apiFetch(
|
||||
endpoint,
|
||||
{ method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) },
|
||||
@@ -406,7 +414,8 @@ export const addWatchedItem = (
|
||||
itemName: string,
|
||||
category: string,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPost('/users/watched-items', { itemName, category }, { tokenOverride });
|
||||
): Promise<Response> =>
|
||||
authedPost('/users/watched-items', { itemName, category }, { tokenOverride });
|
||||
|
||||
export const removeWatchedItem = (
|
||||
masterItemId: number,
|
||||
@@ -426,10 +435,8 @@ export const fetchBestSalePrices = (tokenOverride?: string): Promise<Response> =
|
||||
export const fetchShoppingLists = (tokenOverride?: string): Promise<Response> =>
|
||||
authedGet('/users/shopping-lists', { tokenOverride });
|
||||
|
||||
export const fetchShoppingListById = (
|
||||
listId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedGet(`/users/shopping-lists/${listId}`, { tokenOverride });
|
||||
export const fetchShoppingListById = (listId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedGet(`/users/shopping-lists/${listId}`, { tokenOverride });
|
||||
|
||||
export const createShoppingList = (name: string, tokenOverride?: string): Promise<Response> =>
|
||||
authedPost('/users/shopping-lists', { name }, { tokenOverride });
|
||||
@@ -451,10 +458,8 @@ export const updateShoppingListItem = (
|
||||
): Promise<Response> =>
|
||||
authedPut(`/users/shopping-lists/items/${itemId}`, updates, { tokenOverride });
|
||||
|
||||
export const removeShoppingListItem = (
|
||||
itemId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedDelete(`/users/shopping-lists/items/${itemId}`, { tokenOverride });
|
||||
export const removeShoppingListItem = (itemId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedDelete(`/users/shopping-lists/items/${itemId}`, { tokenOverride });
|
||||
|
||||
/**
|
||||
* Fetches the full profile for the currently authenticated user.
|
||||
@@ -483,10 +488,7 @@ export async function loginUser(
|
||||
* @param receiptImage The image file of the receipt.
|
||||
* @returns A promise that resolves with the backend's response, including the newly created receipt record.
|
||||
*/
|
||||
export const uploadReceipt = (
|
||||
receiptImage: File,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => {
|
||||
export const uploadReceipt = (receiptImage: File, tokenOverride?: string): Promise<Response> => {
|
||||
const formData = new FormData();
|
||||
formData.append('receiptImage', receiptImage);
|
||||
return authedPostForm('/receipts/upload', formData, { tokenOverride });
|
||||
@@ -580,18 +582,14 @@ export const getUserFeed = (
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedGet(`/users/feed?limit=${limit}&offset=${offset}`, { tokenOverride });
|
||||
|
||||
export const forkRecipe = (
|
||||
originalRecipeId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPostEmpty(`/recipes/${originalRecipeId}/fork`, { tokenOverride });
|
||||
export const forkRecipe = (originalRecipeId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedPostEmpty(`/recipes/${originalRecipeId}/fork`, { tokenOverride });
|
||||
|
||||
export const followUser = (userIdToFollow: string, tokenOverride?: string): Promise<Response> =>
|
||||
authedPostEmpty(`/users/${userIdToFollow}/follow`, { tokenOverride });
|
||||
|
||||
export const unfollowUser = (
|
||||
userIdToUnfollow: string,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedDelete(`/users/${userIdToUnfollow}/follow`, { tokenOverride });
|
||||
export const unfollowUser = (userIdToUnfollow: string, tokenOverride?: string): Promise<Response> =>
|
||||
authedDelete(`/users/${userIdToUnfollow}/follow`, { tokenOverride });
|
||||
|
||||
// --- Activity Log API Function ---
|
||||
|
||||
@@ -618,15 +616,11 @@ export const fetchActivityLog = (
|
||||
export const getUserFavoriteRecipes = (tokenOverride?: string): Promise<Response> =>
|
||||
authedGet('/users/me/favorite-recipes', { tokenOverride });
|
||||
|
||||
export const addFavoriteRecipe = (
|
||||
recipeId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPost('/users/me/favorite-recipes', { recipeId }, { tokenOverride });
|
||||
export const addFavoriteRecipe = (recipeId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedPost('/users/me/favorite-recipes', { recipeId }, { tokenOverride });
|
||||
|
||||
export const removeFavoriteRecipe = (
|
||||
recipeId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedDelete(`/users/me/favorite-recipes/${recipeId}`, { tokenOverride });
|
||||
export const removeFavoriteRecipe = (recipeId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedDelete(`/users/me/favorite-recipes/${recipeId}`, { tokenOverride });
|
||||
|
||||
// --- Recipe Comments API Functions ---
|
||||
|
||||
@@ -655,10 +649,7 @@ export const addRecipeComment = (
|
||||
* @param tokenOverride Optional token for testing.
|
||||
* @returns A promise that resolves to the API response containing the suggestion.
|
||||
*/
|
||||
export const suggestRecipe = (
|
||||
ingredients: string[],
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => {
|
||||
export const suggestRecipe = (ingredients: string[], tokenOverride?: string): Promise<Response> => {
|
||||
// This is a protected endpoint, so we use authedPost.
|
||||
return authedPost('/recipes/suggest', { ingredients }, { tokenOverride });
|
||||
};
|
||||
@@ -687,7 +678,8 @@ export const updateRecipeCommentStatus = (
|
||||
commentId: number,
|
||||
status: 'visible' | 'hidden' | 'reported',
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPut(`/admin/comments/${commentId}/status`, { status }, { tokenOverride });
|
||||
): Promise<Response> =>
|
||||
authedPut(`/admin/comments/${commentId}/status`, { status }, { tokenOverride });
|
||||
|
||||
/**
|
||||
* Fetches all brands from the backend. Requires admin privileges.
|
||||
@@ -737,12 +729,11 @@ export const getFlyersForReview = (tokenOverride?: string): Promise<Response> =>
|
||||
export const approveCorrection = (
|
||||
correctionId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPostEmpty(`/admin/corrections/${correctionId}/approve`, { tokenOverride });
|
||||
): Promise<Response> =>
|
||||
authedPostEmpty(`/admin/corrections/${correctionId}/approve`, { tokenOverride });
|
||||
|
||||
export const rejectCorrection = (
|
||||
correctionId: number,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> => authedPostEmpty(`/admin/corrections/${correctionId}/reject`, { tokenOverride });
|
||||
export const rejectCorrection = (correctionId: number, tokenOverride?: string): Promise<Response> =>
|
||||
authedPostEmpty(`/admin/corrections/${correctionId}/reject`, { tokenOverride });
|
||||
|
||||
export const updateSuggestedCorrection = (
|
||||
correctionId: number,
|
||||
@@ -1032,7 +1023,9 @@ export const getSpendingAnalysis = (
|
||||
endDate: string,
|
||||
tokenOverride?: string,
|
||||
): Promise<Response> =>
|
||||
authedGet(`/budgets/spending-analysis?startDate=${startDate}&endDate=${endDate}`, { tokenOverride });
|
||||
authedGet(`/budgets/spending-analysis?startDate=${startDate}&endDate=${endDate}`, {
|
||||
tokenOverride,
|
||||
});
|
||||
|
||||
// --- Gamification API Functions ---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user