diff --git a/src/api/loggingMiddlewares.ts b/src/api/loggingMiddlewares.ts index 89a785f..3b000f8 100644 --- a/src/api/loggingMiddlewares.ts +++ b/src/api/loggingMiddlewares.ts @@ -6,7 +6,15 @@ import { isRejectedWithValue, } from '@reduxjs/toolkit' -const shouldLogExpanded = false +const shouldLogExpanded = true +const enableLogging = true +const log = (msg: any, ...params: any[]) => { + if (enableLogging) console.log('[api]', msg, ...params) +} +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const logExpanded = (msg: any, ...params: any[]) => { + if (shouldLogExpanded) log(msg, ...params) +} /** * Log an error @@ -20,20 +28,26 @@ export const rtkQueryErrorLogger: Middleware = ? (action.error.data as { message: string }).message : action.error.message const payload = JSON.stringify(action.payload, null, 4) + let requestDetails = undefined + if (hasRTKQMeta(action)) { + const baseQueryMeta = action.meta.baseQueryMeta + requestDetails = + `(${baseQueryMeta.response?.status ?? 'UNKNOWN'})` + + baseQueryMeta.request.method + + baseQueryMeta.request.url + } console.error( + '[api]', 'We got a rejected action!', `\n error.data: "${errorData}"`, `\n payload: ${payload}`, + requestDetails, ) } - if (isFulfilled(action)) { - if (shouldLogExpanded) { - console.log('Fulfilled action:', action.meta.arg) - } - } return next(action) } + export const loggerMiddleware: Middleware = api => next => async action => { if (isPending(action)) { const arg = action.meta.arg @@ -41,14 +55,37 @@ export const loggerMiddleware: Middleware = api => next => async action => { const endpointName = 'endpointName' in arg ? (arg.endpointName as string) : undefined - if (endpointName) { - if (shouldLogExpanded) { - console.log(`Request to ${endpointName} :`, arg) - } else { - console.log(`Request to ${endpointName}`) - } + log('Started request', endpointName) + } + if (isFulfilled(action)) { + const arg = action.meta.arg + if (typeof arg !== 'object' || !arg) return + const endpointName = + 'endpointName' in arg ? (arg.endpointName as string) : undefined + + if (hasRTKQMeta(action)) { + const baseQueryMeta = action.meta.baseQueryMeta + + log( + 'Finished request', + `(${baseQueryMeta.response?.status ?? 'UNKNOWN'})`, + endpointName, + baseQueryMeta.request.method, + baseQueryMeta.request.url, + ) } } return next(action) } + +const hasRTKQMeta = ( + action: any, +): action is { + meta: { + baseQueryMeta: { + request: Request + response?: Response + } + } +} => action?.meta?.baseQueryMeta?.request instanceof Request diff --git a/src/api/wanikaniApi.ts b/src/api/wanikaniApi.ts index b61e679..9e0c286 100644 --- a/src/api/wanikaniApi.ts +++ b/src/api/wanikaniApi.ts @@ -31,6 +31,16 @@ export const wanikaniApi = createApi({ reducerPath: 'wanikaniApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://api.wanikani.com/v2/', + validateStatus(response, body) { + // We don't want to treat 304(not modified) as an error. + // + // NOTE: fetchApi in production will use cache headers and 304 will be a + // common response. + return ( + response.status === 304 || + (response.status >= 200 && response.status < 300) + ) + }, prepareHeaders: headers => { // TODO: getState can be used here. See documentation of fetchBaseQuery if (apiKey) {