import { Id } from '../types'; import { useAsync, UseAsyncResult, UseDeleteResult } from './use-async'; import { useBaseModelRelation, useSDKEventBus } from './use-models'; import { HasMany } from '../models/has-many'; import { EventTopic, BaseModel, CHANGE_EVENT_TYPE } from '../models'; import { useEffect, useState } from 'react'; export type UseHasMany = { model: any; getAllByParentId: (parentId: Id) => UseAsyncResult; createByParentId: (parentId: Id) => UseAsyncResult; updateAllByParentId: (parentId: Id) => UseAsyncResult; delAllByParentId: (parentId: Id) => UseDeleteResult; }; export const useHasMany = ( model: BaseModel, classProp: string, ) => { const relation = useBaseModelRelation(model, classProp); const eventBus = useSDKEventBus(); return { model: relation, getAllByParentId: useGetAllByParentId(relation, eventBus), createByParentId: useCreateByParentId(relation, eventBus), updateAllByParentId: useUpdateAllByParentId(relation, eventBus), delAllByParentId: useDelAllByParentId(relation, eventBus), }; }; const useGetAllByParentId = ( relation: HasMany, eventBus: EventTopic, ) => (parentId: Id): UseAsyncResult => { const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync( relation.getAll.bind(relation), ); async function handleChange() { const d = await relation.getLocalAll(parentId); setData(d); } useEffect(() => { handleChange(); }, []); useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }); useEffect(() => { if (gotten) { setData(gotten); } }, [gotten]); const exec = (...args: any[]) => fetch(parentId, ...args); return [data, exec, loading, error]; }; const useCreateByParentId = ( relation: HasMany, eventBus: EventTopic, ) => (parentId: Id): UseAsyncResult => { const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync( relation.create.bind(relation), ); async function handleChange() { if (gotten && gotten.id) { setData(await relation.getLocalById(gotten.id)); } } useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }, [gotten]); useEffect(() => { setData(gotten); }, [gotten]); const exec = (...args: any[]) => fetch(parentId, ...args); return [data, exec, loading, error]; }; const useUpdateAllByParentId = ( relation: HasMany, eventBus: EventTopic, ) => (parentId: Id): UseAsyncResult => { const [data, setData] = useState(); const [gotten, fetch, loading, error] = useAsync( relation.updateAll.bind(relation), ); async function handleChange() { setData(await relation.getLocalAll(parentId)); } useEffect(() => { eventBus.addEventListener(CHANGE_EVENT_TYPE, handleChange); return () => eventBus.removeEventListener(CHANGE_EVENT_TYPE, handleChange); }); useEffect(() => { if (gotten) { setData(gotten); } }, [gotten]); const exec = (...args: any[]) => fetch(parentId, ...args); return [data, exec, loading, error]; }; const useDelAllByParentId = ( relation: HasMany, eventBus: EventTopic, ) => (parentId: Id): UseDeleteResult => { const [ // @ts-ignore gotten, fetch, loading, error, ] = useAsync(relation.delAll.bind(relation)); const exec = (...args: any[]) => fetch(parentId, ...args); return [exec, loading, error]; };