Migrate to external library for interacting with API

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-08-06 19:52:36 +02:00
parent 3b87810f85
commit 32c68a9221
89 changed files with 364 additions and 710 deletions

View File

@ -35,7 +35,7 @@ interface EntityCallbacks<Value, Error = unknown> {
* Passed into hooks to make requests.
* Must return a response.
*/
type EntityFn<T> = (value: T) => Promise<PlApiResponse>
type EntityFn<T> = (value: T) => Promise<T>
export type {
EntitySchema,

View File

@ -23,7 +23,7 @@ interface UseBatchedEntitiesOpts<TEntity extends Entity> {
const useBatchedEntities = <TEntity extends Entity>(
expandedPath: ExpandedEntitiesPath,
ids: string[],
entityFn: EntityFn<string[]>,
entityFn: EntityFn<TEntity[]>,
opts: UseBatchedEntitiesOpts<TEntity> = {},
) => {
const getState = useGetState();
@ -54,10 +54,10 @@ const useBatchedEntities = <TEntity extends Entity>(
dispatch(entitiesFetchRequest(entityType, listKey));
try {
const response = await entityFn(filteredIds);
const entities = filteredArray(schema).parse(response.json);
const entities = filteredArray(schema).parse(response);
dispatch(entitiesFetchSuccess(entities, entityType, listKey, 'end', {
next: undefined,
prev: undefined,
next: null,
prev: null,
totalCount: undefined,
fetching: false,
fetched: true,

View File

@ -1,13 +1,11 @@
import { useEffect } from 'react';
import z from 'zod';
import { getNextLink, getPrevLink } from 'soapbox/api';
import { useClient } from 'soapbox/hooks';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch';
import { useAppSelector } from 'soapbox/hooks/useAppSelector';
import { useGetState } from 'soapbox/hooks/useGetState';
import { filteredArray } from 'soapbox/schemas/utils';
import { realNumberSchema } from 'soapbox/utils/numbers';
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess, invalidateEntityList } from '../actions';
import { selectEntities, selectListState, useListState } from '../selectors';
@ -16,6 +14,7 @@ import { parseEntitiesPath } from './utils';
import type { EntityFn, EntitySchema, ExpandedEntitiesPath } from './types';
import type { Entity } from '../types';
import type { PaginatedResponse } from 'pl-api';
/** Additional options for the hook. */
interface UseEntitiesOpts<TEntity extends Entity> {
@ -58,7 +57,7 @@ const useEntities = <TEntity extends Entity>(
const next = useListState(path, 'next');
const prev = useListState(path, 'prev');
const fetchPage = async(req: EntityFn<void>, pos: 'start' | 'end', overwrite = false): Promise<void> => {
const fetchPage = async(req: () => Promise<PaginatedResponse<any>>, pos: 'start' | 'end', overwrite = false): Promise<void> => {
// Get `isFetching` state from the store again to prevent race conditions.
const isFetching = selectListState(getState(), path, 'fetching');
if (isFetching) return;
@ -66,14 +65,12 @@ const useEntities = <TEntity extends Entity>(
dispatch(entitiesFetchRequest(entityType, listKey));
try {
const response = await req();
const entities = filteredArray(schema).parse(response.json);
const parsedCount = realNumberSchema.safeParse(response.headers.get('x-total-count'));
const totalCount = parsedCount.success ? parsedCount.data : undefined;
const entities = filteredArray(schema).parse(response);
dispatch(entitiesFetchSuccess(entities, entityType, listKey, pos, {
next: getNextLink(response),
prev: getPrevLink(response),
totalCount: Number(totalCount) >= entities.length ? totalCount : undefined,
next: response.next,
prev: response.previous,
totalCount: undefined,
fetching: false,
fetched: true,
error: null,
@ -91,13 +88,13 @@ const useEntities = <TEntity extends Entity>(
const fetchNextPage = async(): Promise<void> => {
if (next) {
await fetchPage(() => client.request(next), 'end');
await fetchPage(() => next(), 'end');
}
};
const fetchPreviousPage = async(): Promise<void> => {
if (prev) {
await fetchPage(() => client.request(prev), 'start');
await fetchPage(() => prev(), 'start');
}
};

View File

@ -24,7 +24,7 @@ interface UseEntityOpts<TEntity extends Entity> {
const useEntity = <TEntity extends Entity>(
path: EntityPath,
entityFn: EntityFn<void>,
entityFn: EntityFn<TEntity>,
opts: UseEntityOpts<TEntity> = {},
) => {
const [isFetching, setPromise] = useLoading(true);
@ -46,7 +46,7 @@ const useEntity = <TEntity extends Entity>(
const fetchEntity = async () => {
try {
const response = await setPromise(entityFn());
const entity = schema.parse(response.json);
const entity = schema.parse(response);
dispatch(importEntities([entity], entityType));
} catch (e) {
setError(e);

View File

@ -1,3 +1,5 @@
import type { PaginatedResponse } from 'pl-api';
/** A Mastodon API entity. */
interface Entity {
/** Unique ID for the entity (usually the primary key in the database). */
@ -20,9 +22,9 @@ interface EntityList {
/** Fetch state for an entity list. */
interface EntityListState {
/** Next URL for pagination, if any. */
next: string | undefined;
next: (() => Promise<PaginatedResponse<any>>) | null;
/** Previous URL for pagination, if any. */
prev: string | undefined;
prev: (() => Promise<PaginatedResponse<any>>) | null;
/** Total number of items according to the API. */
totalCount: number | undefined;
/** Error returned from the API, if any. */