import { ThunkAction } from 'redux-thunk' ; import { DataDocument , ErrorObject , JsonApiError } from '../../api/models/jsonapi' ; import { fetchDocument as fetchDocumentApi } from '../../api/http.client' ; import { AppState } from '../appState' ; import { createAction , ActionsUnion } from '../utils' ; import { JsonapiActionTypes } from './actionTypes' ; import { getEntity , getCollection } from './selectors' ; import { getEntityUrl } from '../../api/api-urls' ; export const requestEntity = ( type , id ) => createAction ( JsonapiActionTypes . REQUEST_ENTITY , { type , id } ) ; export const receivedEntity = ( type , id , dataDocument , receivedAt = Date . now ( ) ) => createAction ( JsonapiActionTypes . RECEIVED_ENTITY , { type , id , dataDocument , receivedAt , } ) ; export const receivedEntityError = ( type , id , error , receivedAt = Date . now ( ) ) => createAction ( JsonapiActionTypes . RECEIVED_ENTITY_ERROR , { type , id , error , receivedAt , } ) ; export const invalidateEntity = ( type , id ) => createAction ( JsonapiActionTypes . INVALIDATE_ENTITY , { type , id } ) ; export const requestCollection = ( url ) => createAction ( JsonapiActionTypes . REQUEST_COLLECTION , { url } ) ; export const receivedCollection = ( url , dataDocument , receivedAt = Date . now ( ) ) => createAction ( JsonapiActionTypes . RECEIVED_COLLECTION , { url , dataDocument , receivedAt , } ) ; export const receivedCollectionError = ( url , error , receivedAt = Date . now ( ) ) => createAction ( JsonapiActionTypes . RECEIVED_COLLECTION_ERROR , { url , error , receivedAt , } ) ; export const invalidateCollection = ( url ) => createAction ( JsonapiActionTypes . INVALIDATE_COLLECTION , { url } ) ; export const requestNextCollection = ( url ) => createAction ( JsonapiActionTypes . REQUEST_NEXT_COLLECTION , { url } ) ; export const receivedNextCollection = ( url , dataDocument , receivedAt = Date . now ( ) ) => createAction ( JsonapiActionTypes . RECEIVED_NEXT_COLLECTION , { url , dataDocument , receivedAt , } ) ; const actions = { requestEntity , receivedEntity , receivedEntityError , invalidateEntity , requestCollection , receivedCollection , receivedCollectionError , invalidateCollection , requestNextCollection , receivedNextCollection , } ; export type JsonapiActions = ActionsUnion < typeof actions > ; type ThunkResult = ThunkAction < void , AppState , undefined , JsonapiActions > ; const TTL = 10 * 60 * 1000 ; export function fetchEntity ( type , id ) { return async function ( dispatch , getState ) { const appState = getState ( ) ; const entity = getEntity ( appState , type , id ) ; if ( ! entity || ( ! entity . isFetching && ( entity . didInvalidate || Date . now ( ) - entity . lastUpdated > TTL ) ) ) { const url = getEntityUrl ( type , id ) ; dispatch ( requestEntity ( type , id ) ) ; if ( process . env . NODE_ENV !== 'production' ) { dispatch ( requestCollection ( url ) ) ; } try { const result = await fetchDocumentApi ( url ) ; const receivedAt = Date . now ( ) ; dispatch ( receivedEntity ( type , id , result , receivedAt ) ) ; if ( process . env . NODE_ENV !== 'production' ) { dispatch ( receivedCollection ( url , result , receivedAt ) ) ; } } catch ( e ) { const jsonApiError = e as JsonApiError ; const receivedAt = Date . now ( ) ; dispatch ( receivedEntityError ( type , id , jsonApiError . error , receivedAt ) ) ; if ( process . env . NODE_ENV !== 'production' ) { dispatch ( receivedCollectionError ( url , jsonApiError . error , receivedAt ) ) ; } } } } ; } export function fetchCollection ( url ) { return async function ( dispatch , getState ) { const appState = getState ( ) ; const collection = getCollection ( appState , url ) ; if ( ! collection || ( ! collection . isFetching && ( collection . didInvalidate || Date . now ( ) - collection . lastUpdated > TTL ) ) ) { dispatch ( requestCollection ( url ) ) ; try { const result = await fetchDocumentApi ( url ) ; dispatch ( receivedCollection ( url , result ) ) ; } catch ( e ) { const jsonApiError = e as JsonApiError ; dispatch ( receivedCollectionError ( url , jsonApiError . error ) ) ; } } } ; } export function fetchNextCollection ( url ) { return async function ( dispatch , getState ) { const appState = getState ( ) ; const collection = getCollection ( appState , url ) ; if ( collection && collection . pageInfo . hasNextPage && ! collection . pageInfo . isFetchingNextPage ) { dispatch ( requestNextCollection ( url ) ) ; try { const result = await fetchDocumentApi ( collection . pageInfo . nextPage ) ; dispatch ( receivedNextCollection ( url , result ) ) ; } catch ( e ) { const jsonApiError = e as JsonApiError ; dispatch ( receivedCollectionError ( url , jsonApiError . error ) ) ; } } } ; }