import type { ResolveType, Denormalize, DenormalizeNullable, } from '@rest-hooks/react'; import { StateContext, ExpiryStatus } from '@rest-hooks/react'; import { useMemo, useContext } from 'react'; import useError from './useError.js'; import useRetrieve from './useRetrieve.js'; import { ReadShape, ParamsFromShape } from '../endpoint/index.js'; import { useDenormalized } from '../selectors/index.js'; type ResourceArgs< S extends ReadShape, P extends ParamsFromShape | null, > = readonly [S, P]; type ResourceReturn = CondNull< P, S['schema'] extends undefined ? ResolveType | undefined : DenormalizeNullable, S['schema'] extends undefined ? ResolveType : Denormalize >; /** single form resource */ function useOneResource< Shape extends ReadShape, Params extends ParamsFromShape | null, >( fetchShape: Shape, params: Params, ): CondNull< Params, DenormalizeNullable, Denormalize > { const state = useContext(StateContext); const { data, expiryStatus, expiresAt } = useDenormalized( fetchShape, params, state, ); const error = useError(fetchShape, params); const maybePromise = useRetrieve( fetchShape, params, expiryStatus === ExpiryStatus.Invalid, expiresAt, ); if (expiryStatus !== ExpiryStatus.Valid && maybePromise) { throw maybePromise; } if (error) throw error; return data as any; } /** many form resource */ function useManyResources[]>( ...resourceList: A ) { const state = useContext(StateContext); const denormalizedValues = resourceList.map( < Shape extends ReadShape, Params extends ParamsFromShape | null, >([fetchShape, params]: ResourceArgs) => // eslint-disable-next-line react-hooks/rules-of-hooks useDenormalized(fetchShape, params, state), ); const errorValues = resourceList.map( < Shape extends ReadShape, Params extends ParamsFromShape | null, >( [fetchShape, params]: ResourceArgs, i: number, ) => // eslint-disable-next-line react-hooks/rules-of-hooks useError(fetchShape, params), ); const promises = resourceList .map(([fetchShape, params], i) => // eslint-disable-next-line react-hooks/rules-of-hooks useRetrieve( fetchShape, params, denormalizedValues[i].expiryStatus === ExpiryStatus.Invalid, denormalizedValues[i].expiresAt, ), ) // only wait on promises without results .map( (p, i) => denormalizedValues[i].expiryStatus !== ExpiryStatus.Valid && p, ); // throw first valid error for (let i = 0; i < resourceList.length; i++) { const err = errorValues[i]; // we aren't fetching at all // then throw that error if (err && !promises[i]) throw err; } const promise = useMemo(() => { const activePromises = promises.filter(p => p); if (activePromises.length) { return Promise.all(activePromises); } // eslint-disable-next-line react-hooks/exhaustive-deps }, promises); if (promise) throw promise; return denormalizedValues.map(({ data }) => data); } type CondNull = P extends null ? A : B; /** * Ensure a resource is available. * Suspends until it is. * * `useResource` guarantees referential equality globally. * @deprecated use https://resthooks.io/docs/api/useSuspense * @throws {Promise} If data is not yet available. * @throws {NetworkError} If fetch fails. */ export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, >(v1: readonly [S1, P1]): [ResourceReturn]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], ): [ResourceReturn, ResourceReturn]; export default function useResource< S extends ReadShape, P extends ParamsFromShape | null, >(fetchShape: S, params: P): ResourceReturn; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], ): [ResourceReturn, ResourceReturn, ResourceReturn]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, S12 extends ReadShape, P12 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], v12: readonly [S12, P12], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, S12 extends ReadShape, P12 extends ParamsFromShape | null, S13 extends ReadShape, P13 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], v12: readonly [S12, P12], v13: readonly [S13, P13], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, S12 extends ReadShape, P12 extends ParamsFromShape | null, S13 extends ReadShape, P13 extends ParamsFromShape | null, S14 extends ReadShape, P14 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], v12: readonly [S12, P12], v13: readonly [S13, P13], v14: readonly [S14, P14], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, S12 extends ReadShape, P12 extends ParamsFromShape | null, S13 extends ReadShape, P13 extends ParamsFromShape | null, S14 extends ReadShape, P14 extends ParamsFromShape | null, S15 extends ReadShape, P15 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], v12: readonly [S12, P12], v13: readonly [S13, P13], v14: readonly [S14, P14], v15: readonly [S15, P15], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< S1 extends ReadShape, P1 extends ParamsFromShape | null, S2 extends ReadShape, P2 extends ParamsFromShape | null, S3 extends ReadShape, P3 extends ParamsFromShape | null, S4 extends ReadShape, P4 extends ParamsFromShape | null, S5 extends ReadShape, P5 extends ParamsFromShape | null, S6 extends ReadShape, P6 extends ParamsFromShape | null, S7 extends ReadShape, P7 extends ParamsFromShape | null, S8 extends ReadShape, P8 extends ParamsFromShape | null, S9 extends ReadShape, P9 extends ParamsFromShape | null, S10 extends ReadShape, P10 extends ParamsFromShape | null, S11 extends ReadShape, P11 extends ParamsFromShape | null, S12 extends ReadShape, P12 extends ParamsFromShape | null, S13 extends ReadShape, P13 extends ParamsFromShape | null, S14 extends ReadShape, P14 extends ParamsFromShape | null, S15 extends ReadShape, P15 extends ParamsFromShape | null, S16 extends ReadShape, P16 extends ParamsFromShape | null, >( v1: readonly [S1, P1], v2: readonly [S2, P2], v3: readonly [S3, P3], v4: readonly [S4, P4], v5: readonly [S5, P5], v6: readonly [S6, P6], v7: readonly [S7, P7], v8: readonly [S8, P8], v9: readonly [S9, P9], v10: readonly [S10, P10], v11: readonly [S11, P11], v12: readonly [S12, P12], v13: readonly [S13, P13], v14: readonly [S14, P14], v15: readonly [S15, P15], v16: readonly [S16, P16], ): [ ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ResourceReturn, ]; export default function useResource< Shape extends ReadShape, Params extends ParamsFromShape | null, >(...args: ResourceArgs | ResourceArgs[]): any { // this conditional use of hooks is ok as long as the structure of the arguments don't change if (Array.isArray(args[0])) { // TODO: provide type guard function to detect this // eslint-disable-next-line react-hooks/rules-of-hooks return useManyResources(...(args as ResourceArgs[])); } args = args as ResourceArgs; // TODO: make return types match up with the branching logic we put in here. // eslint-disable-next-line react-hooks/rules-of-hooks return useOneResource(args[0], args[1]); }