import { computed, reactive, ref } from 'vue' import { useCall } from '../index' import { docStore } from '../docStore' import { listStore } from '../useList/listStore' interface UseDoctypeOptions { baseUrl?: string } export function useDoctype( doctype: string, options: UseDoctypeOptions = {}, ) { const insert = useInsert(doctype, options) const delete_ = useDelete(doctype, options) const setValue = useSetValue(doctype, options) const runDocMethod = useRunDocMethod(doctype, options) const runMethod = useRunMethod(doctype, options) return reactive({ insert, delete: delete_, setValue, runDocMethod, runMethod, }) } function useInsert(doctype: string, options: UseDoctypeOptions = {}) { let { baseUrl = '' } = options let out = useCall>({ url: `/api/v2/document/${doctype}`, method: 'POST', immediate: false, baseUrl, }) return { ...out, submit: (params: Partial) => out.submit(params).then(() => out.data), } } function useDelete(doctype: string, options: UseDoctypeOptions = {}) { let { baseUrl = '' } = options let url = ref(`/api/v2/document/${doctype}/`) type DeleteResponse = 'ok' type DeleteParams = { name: string } let delete_ = useCall({ url, method: 'DELETE', immediate: false, baseUrl, onSuccess() { if (delete_.params.name) { let { name } = delete_.params docStore.removeDoc(doctype, name) listStore.removeRow(doctype, name) } }, }) return reactive({ ...delete_, submit: ({ name }: DeleteParams) => { url.value = `/api/v2/document/${doctype}/${name}` return delete_.submit({ name }) }, }) } function useRunDocMethod(doctype: string, options: UseDoctypeOptions = {}) { let { baseUrl = '' } = options let url = ref(`/api/v2/document/${doctype}//method/`) interface RunDocMethodParams { name: string method: string validate?: () => string | void params?: Record } type RunDocMethodReturnValue = ReturnType & { submit: (params: RunDocMethodParams) => Promise isLoading: (name: string, method: string) => boolean } let runDocMethod = useCall({ url, method: 'POST', immediate: false, baseUrl, }) let validateError = ref(null) return reactive({ ...runDocMethod, error: computed(() => validateError.value || runDocMethod.error), submit: ({ name, method, validate, params }: RunDocMethodParams) => { url.value = `/api/v2/document/${doctype}/${name}/method/${method}` if (validate) { const errorMessage = validate() if (errorMessage) { validateError.value = new Error(errorMessage) return Promise.reject(validateError.value) } else { validateError.value = null } } return runDocMethod.submit(params) }, isLoading: (name: string, method: string) => { return ( runDocMethod.loading && url.value === `/api/v2/document/${doctype}/${name}/method/${method}` ) }, } as RunDocMethodReturnValue) } function useRunMethod(doctype: string, options: UseDoctypeOptions = {}) { let { baseUrl = '' } = options let url = ref(`/api/v2/method/${doctype}/`) interface RunMethodParams { method: string validate?: () => string | void params?: Record } type RunMethodReturnValue = ReturnType & { submit: (params: RunMethodParams) => Promise isLoading: (method: string) => boolean } let runMethod = useCall({ url, method: 'POST', immediate: false, baseUrl, }) let validateError = ref(null) return reactive({ ...runMethod, error: computed(() => validateError.value || runMethod.error), submit: ({ method, validate, params }: RunMethodParams) => { url.value = `/api/v2/method/${doctype}/${method}` if (validate) { const errorMessage = validate() if (errorMessage) { validateError.value = new Error(errorMessage) return Promise.reject(validateError.value) } else { validateError.value = null } } return runMethod.submit(params) }, isLoading: (method: string) => { return ( runMethod.loading && url.value === `/api/v2/method/${doctype}/${method}` ) }, } as RunMethodReturnValue) } function useSetValue(doctype: string, options: UseDoctypeOptions = {}) { let { baseUrl = '' } = options let url = ref(`/api/v2/document/${doctype}/`) type SetValueResponse = T & { name: string } type SetValueParams = { name: string } & { [K in keyof Partial]: T[K] } let setValue = useCall({ url, method: 'PUT', immediate: false, baseUrl, onSuccess(data) { docStore.setDoc({ doctype, ...data }) listStore.updateRow(doctype, data) }, }) return { ...setValue, submit: ({ name, ...values }: SetValueParams) => { url.value = `/api/v2/document/${doctype}/${name}` return setValue.submit({ name, ...values }) }, } }