use-config.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { useCallback, useEffect, useMemo, useState } from 'react'
  2. import produce from 'immer'
  3. import { useBoolean } from 'ahooks'
  4. import useVarList from '../_base/hooks/use-var-list'
  5. import { VarType } from '../../types'
  6. import type { Var } from '../../types'
  7. import { useStore } from '../../store'
  8. import { type Authorization, type Body, BodyType, type HttpNodeType, type Method, type Timeout } from './types'
  9. import useKeyValueList from './hooks/use-key-value-list'
  10. import { transformToBodyPayload } from './utils'
  11. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  12. import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run'
  13. import {
  14. useNodesReadOnly,
  15. } from '@/app/components/workflow/hooks'
  16. const useConfig = (id: string, payload: HttpNodeType) => {
  17. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  18. const defaultConfig = useStore(s => s.nodesDefaultConfigs)[payload.type]
  19. const { inputs, setInputs } = useNodeCrud<HttpNodeType>(id, payload)
  20. const { handleVarListChange, handleAddVariable } = useVarList<HttpNodeType>({
  21. inputs,
  22. setInputs,
  23. })
  24. const [isDataReady, setIsDataReady] = useState(false)
  25. useEffect(() => {
  26. const isReady = defaultConfig && Object.keys(defaultConfig).length > 0
  27. if (isReady) {
  28. const newInputs = {
  29. ...defaultConfig,
  30. ...inputs,
  31. }
  32. const bodyData = newInputs.body.data
  33. if (typeof bodyData === 'string')
  34. newInputs.body.data = transformToBodyPayload(bodyData, [BodyType.formData, BodyType.xWwwFormUrlencoded].includes(newInputs.body.type))
  35. setInputs(newInputs)
  36. setIsDataReady(true)
  37. }
  38. // eslint-disable-next-line react-hooks/exhaustive-deps
  39. }, [defaultConfig])
  40. const handleMethodChange = useCallback((method: Method) => {
  41. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  42. draft.method = method
  43. })
  44. setInputs(newInputs)
  45. }, [inputs, setInputs])
  46. const handleUrlChange = useCallback((url: string) => {
  47. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  48. draft.url = url
  49. })
  50. setInputs(newInputs)
  51. }, [inputs, setInputs])
  52. const handleFieldChange = useCallback((field: string) => {
  53. return (value: string) => {
  54. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  55. (draft as any)[field] = value
  56. })
  57. setInputs(newInputs)
  58. }
  59. }, [inputs, setInputs])
  60. const {
  61. list: headers,
  62. setList: setHeaders,
  63. addItem: addHeader,
  64. isKeyValueEdit: isHeaderKeyValueEdit,
  65. toggleIsKeyValueEdit: toggleIsHeaderKeyValueEdit,
  66. } = useKeyValueList(inputs.headers, handleFieldChange('headers'))
  67. const {
  68. list: params,
  69. setList: setParams,
  70. addItem: addParam,
  71. isKeyValueEdit: isParamKeyValueEdit,
  72. toggleIsKeyValueEdit: toggleIsParamKeyValueEdit,
  73. } = useKeyValueList(inputs.params, handleFieldChange('params'))
  74. const setBody = useCallback((data: Body) => {
  75. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  76. draft.body = data
  77. })
  78. setInputs(newInputs)
  79. }, [inputs, setInputs])
  80. // authorization
  81. const [isShowAuthorization, {
  82. setTrue: showAuthorization,
  83. setFalse: hideAuthorization,
  84. }] = useBoolean(false)
  85. const setAuthorization = useCallback((authorization: Authorization) => {
  86. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  87. draft.authorization = authorization
  88. })
  89. setInputs(newInputs)
  90. }, [inputs, setInputs])
  91. const setTimeout = useCallback((timeout: Timeout) => {
  92. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  93. draft.timeout = timeout
  94. })
  95. setInputs(newInputs)
  96. }, [inputs, setInputs])
  97. const filterVar = useCallback((varPayload: Var) => {
  98. return [VarType.string, VarType.number, VarType.secret].includes(varPayload.type)
  99. }, [])
  100. // single run
  101. const {
  102. isShowSingleRun,
  103. hideSingleRun,
  104. getInputVars,
  105. runningStatus,
  106. handleRun,
  107. handleStop,
  108. runInputData,
  109. setRunInputData,
  110. runResult,
  111. } = useOneStepRun<HttpNodeType>({
  112. id,
  113. data: inputs,
  114. defaultRunInputData: {},
  115. })
  116. const fileVarInputs = useMemo(() => {
  117. if (!Array.isArray(inputs.body.data))
  118. return ''
  119. const res = inputs.body.data
  120. .filter(item => item.file?.length)
  121. .map(item => item.file ? `{{#${item.file.join('.')}#}}` : '')
  122. .join(' ')
  123. return res
  124. }, [inputs.body.data])
  125. const varInputs = getInputVars([
  126. inputs.url,
  127. inputs.headers,
  128. inputs.params,
  129. typeof inputs.body.data === 'string' ? inputs.body.data : inputs.body.data.map(item => item.value).join(''),
  130. fileVarInputs,
  131. ])
  132. const inputVarValues = (() => {
  133. const vars: Record<string, any> = {}
  134. Object.keys(runInputData)
  135. .forEach((key) => {
  136. vars[key] = runInputData[key]
  137. })
  138. return vars
  139. })()
  140. const setInputVarValues = useCallback((newPayload: Record<string, any>) => {
  141. setRunInputData(newPayload)
  142. }, [setRunInputData])
  143. // curl import panel
  144. const [isShowCurlPanel, {
  145. setTrue: showCurlPanel,
  146. setFalse: hideCurlPanel,
  147. }] = useBoolean(false)
  148. const handleCurlImport = useCallback((newNode: HttpNodeType) => {
  149. const newInputs = produce(inputs, (draft: HttpNodeType) => {
  150. draft.method = newNode.method
  151. draft.url = newNode.url
  152. draft.headers = newNode.headers
  153. draft.params = newNode.params
  154. draft.body = newNode.body
  155. })
  156. setInputs(newInputs)
  157. }, [inputs, setInputs])
  158. return {
  159. readOnly,
  160. isDataReady,
  161. inputs,
  162. handleVarListChange,
  163. handleAddVariable,
  164. filterVar,
  165. handleMethodChange,
  166. handleUrlChange,
  167. // headers
  168. headers,
  169. setHeaders,
  170. addHeader,
  171. isHeaderKeyValueEdit,
  172. toggleIsHeaderKeyValueEdit,
  173. // params
  174. params,
  175. setParams,
  176. addParam,
  177. isParamKeyValueEdit,
  178. toggleIsParamKeyValueEdit,
  179. // body
  180. setBody,
  181. // authorization
  182. isShowAuthorization,
  183. showAuthorization,
  184. hideAuthorization,
  185. setAuthorization,
  186. setTimeout,
  187. // single run
  188. isShowSingleRun,
  189. hideSingleRun,
  190. runningStatus,
  191. handleRun,
  192. handleStop,
  193. varInputs,
  194. inputVarValues,
  195. setInputVarValues,
  196. runResult,
  197. // curl import
  198. isShowCurlPanel,
  199. showCurlPanel,
  200. hideCurlPanel,
  201. handleCurlImport,
  202. }
  203. }
  204. export default useConfig