From b1270251679c41cb41488bd1d9ea6f7ca5a47ce2 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 22 Mar 2023 15:31:58 -0500 Subject: [PATCH] Move useCreateEntity into its own hook as well, because why not --- .../entity-store/hooks/useCreateEntity.ts | 74 +++++++++++++++++++ .../entity-store/hooks/useEntityActions.ts | 49 +++--------- 2 files changed, 83 insertions(+), 40 deletions(-) create mode 100644 app/soapbox/entity-store/hooks/useCreateEntity.ts diff --git a/app/soapbox/entity-store/hooks/useCreateEntity.ts b/app/soapbox/entity-store/hooks/useCreateEntity.ts new file mode 100644 index 000000000..72873504b --- /dev/null +++ b/app/soapbox/entity-store/hooks/useCreateEntity.ts @@ -0,0 +1,74 @@ +import { z } from 'zod'; + +import { useAppDispatch } from 'soapbox/hooks'; + +import { importEntities } from '../actions'; + +import type { Entity } from '../types'; +import type { EntitySchema } from './types'; + +type EntityPath = [entityType: string, listKey?: string] +type CreateFn = (params: Params) => Promise | Result; + +interface UseCreateEntityOpts { + schema?: EntitySchema +} + +type CreateEntityResult = + { + success: true + result: Result + entity: TEntity + } | { + success: false + error: Error + } + +interface EntityCallbacks { + onSuccess?(entity: TEntity): void + onError?(error: Error): void +} + +function useCreateEntity( + path: EntityPath, + createFn: CreateFn, + opts: UseCreateEntityOpts = {}, +) { + const [entityType, listKey] = path; + const dispatch = useAppDispatch(); + + return async function createEntity( + params: Params, + callbacks: EntityCallbacks = {}, + ): Promise> { + try { + const result = await createFn(params); + const schema = opts.schema || z.custom(); + const entity = schema.parse(result); + + // TODO: optimistic updating + dispatch(importEntities([entity], entityType, listKey)); + + if (callbacks.onSuccess) { + callbacks.onSuccess(entity); + } + + return { + success: true, + result, + entity, + }; + } catch (error) { + if (callbacks.onError) { + callbacks.onError(error); + } + + return { + success: false, + error, + }; + } + }; +} + +export { useCreateEntity }; \ No newline at end of file diff --git a/app/soapbox/entity-store/hooks/useEntityActions.ts b/app/soapbox/entity-store/hooks/useEntityActions.ts index 8f286633a..8a259c0e0 100644 --- a/app/soapbox/entity-store/hooks/useEntityActions.ts +++ b/app/soapbox/entity-store/hooks/useEntityActions.ts @@ -1,14 +1,10 @@ -import { z } from 'zod'; - -import { useApi, useAppDispatch } from 'soapbox/hooks'; - -import { importEntities } from '../actions'; +import { useApi } from 'soapbox/hooks'; +import { useCreateEntity } from './useCreateEntity'; import { useDeleteEntity } from './useDeleteEntity'; import type { Entity } from '../types'; import type { EntitySchema } from './types'; -import type { AxiosResponse } from 'axios'; type EntityPath = [entityType: string, listKey?: string] @@ -16,59 +12,32 @@ interface UseEntityActionsOpts { schema?: EntitySchema } -interface CreateEntityResult { - response: AxiosResponse - entity: TEntity -} - interface EntityActionEndpoints { post?: string delete?: string } -interface EntityCallbacks { - onSuccess?(entity: TEntity): void -} - -function useEntityActions( +function useEntityActions( path: EntityPath, endpoints: EntityActionEndpoints, opts: UseEntityActionsOpts = {}, ) { - const [entityType, listKey] = path; - const api = useApi(); - const dispatch = useAppDispatch(); + const [entityType] = path; const deleteEntity = useDeleteEntity(entityType, (entityId) => { if (!endpoints.delete) return Promise.reject(endpoints); return api.delete(endpoints.delete.replace(':id', entityId)); }); - function createEntity(params: P, callbacks: EntityCallbacks = {}): Promise> { + const createEntity = useCreateEntity(path, (params: Params) => { if (!endpoints.post) return Promise.reject(endpoints); - - return api.post(endpoints.post, params).then((response) => { - const schema = opts.schema || z.custom(); - const entity = schema.parse(response.data); - - // TODO: optimistic updating - dispatch(importEntities([entity], entityType, listKey)); - - if (callbacks.onSuccess) { - callbacks.onSuccess(entity); - } - - return { - response, - entity, - }; - }); - } + return api.post(endpoints.post, params); + }, opts); return { - createEntity: createEntity, - deleteEntity: endpoints.delete ? deleteEntity : undefined, + createEntity, + deleteEntity, }; }