Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import { useCallback, useEffect, useState } from 'react'
  2. import produce from 'immer'
  3. import useVarList from '../_base/hooks/use-var-list'
  4. import useOutputVarList from '../_base/hooks/use-output-var-list'
  5. import { BlockEnum, VarType } from '../../types'
  6. import type { Var, Variable } from '../../types'
  7. import { useStore } from '../../store'
  8. import type { CodeNodeType, OutputVar } from './types'
  9. import { CodeLanguage } from './types'
  10. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  11. import {
  12. fetchNodeDefault,
  13. fetchPipelineNodeDefault,
  14. } from '@/service/workflow'
  15. import {
  16. useNodesReadOnly,
  17. } from '@/app/components/workflow/hooks'
  18. const useConfig = (id: string, payload: CodeNodeType) => {
  19. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  20. const appId = useStore(s => s.appId)
  21. const pipelineId = useStore(s => s.pipelineId)
  22. const [allLanguageDefault, setAllLanguageDefault] = useState<Record<CodeLanguage, CodeNodeType> | null>(null)
  23. useEffect(() => {
  24. if (appId) {
  25. (async () => {
  26. const { config: javaScriptConfig } = await fetchNodeDefault(appId, BlockEnum.Code, { code_language: CodeLanguage.javascript }) as any
  27. const { config: pythonConfig } = await fetchNodeDefault(appId, BlockEnum.Code, { code_language: CodeLanguage.python3 }) as any
  28. setAllLanguageDefault({
  29. [CodeLanguage.javascript]: javaScriptConfig as CodeNodeType,
  30. [CodeLanguage.python3]: pythonConfig as CodeNodeType,
  31. } as any)
  32. })()
  33. }
  34. }, [appId])
  35. useEffect(() => {
  36. if (pipelineId) {
  37. (async () => {
  38. const { config: javaScriptConfig } = await fetchPipelineNodeDefault(pipelineId, BlockEnum.Code, { code_language: CodeLanguage.javascript }) as any
  39. const { config: pythonConfig } = await fetchPipelineNodeDefault(pipelineId, BlockEnum.Code, { code_language: CodeLanguage.python3 }) as any
  40. setAllLanguageDefault({
  41. [CodeLanguage.javascript]: javaScriptConfig as CodeNodeType,
  42. [CodeLanguage.python3]: pythonConfig as CodeNodeType,
  43. } as any)
  44. })()
  45. }
  46. }, [pipelineId])
  47. const defaultConfig = useStore(s => s.nodesDefaultConfigs)?.[payload.type]
  48. const { inputs, setInputs } = useNodeCrud<CodeNodeType>(id, payload)
  49. const { handleVarListChange, handleAddVariable } = useVarList<CodeNodeType>({
  50. inputs,
  51. setInputs,
  52. })
  53. const [outputKeyOrders, setOutputKeyOrders] = useState<string[]>([])
  54. const syncOutputKeyOrders = useCallback((outputs: OutputVar) => {
  55. setOutputKeyOrders(Object.keys(outputs))
  56. }, [])
  57. useEffect(() => {
  58. if (inputs.code) {
  59. if (inputs.outputs && Object.keys(inputs.outputs).length > 0)
  60. syncOutputKeyOrders(inputs.outputs)
  61. return
  62. }
  63. const isReady = defaultConfig && Object.keys(defaultConfig).length > 0
  64. if (isReady) {
  65. setInputs({
  66. ...inputs,
  67. ...defaultConfig,
  68. })
  69. syncOutputKeyOrders(defaultConfig.outputs)
  70. }
  71. }, [defaultConfig])
  72. const handleCodeChange = useCallback((code: string) => {
  73. const newInputs = produce(inputs, (draft) => {
  74. draft.code = code
  75. })
  76. setInputs(newInputs)
  77. }, [inputs, setInputs])
  78. const handleCodeLanguageChange = useCallback((codeLanguage: CodeLanguage) => {
  79. const currDefaultConfig = allLanguageDefault?.[codeLanguage]
  80. const newInputs = produce(inputs, (draft) => {
  81. draft.code_language = codeLanguage
  82. if (!currDefaultConfig)
  83. return
  84. draft.code = currDefaultConfig.code
  85. draft.variables = currDefaultConfig.variables
  86. draft.outputs = currDefaultConfig.outputs
  87. })
  88. setInputs(newInputs)
  89. }, [allLanguageDefault, inputs, setInputs])
  90. const handleSyncFunctionSignature = useCallback(() => {
  91. const generateSyncSignatureCode = (code: string) => {
  92. let mainDefRe
  93. let newMainDef
  94. if (inputs.code_language === CodeLanguage.javascript) {
  95. mainDefRe = /function\s+main\b\s*\([\s\S]*?\)/g
  96. newMainDef = 'function main({{var_list}})'
  97. let param_list = inputs.variables?.map(item => item.variable).join(', ') || ''
  98. param_list = param_list ? `{${param_list}}` : ''
  99. newMainDef = newMainDef.replace('{{var_list}}', param_list)
  100. }
  101. else if (inputs.code_language === CodeLanguage.python3) {
  102. mainDefRe = /def\s+main\b\s*\([\s\S]*?\)/g
  103. const param_list = []
  104. for (const item of inputs.variables) {
  105. let param = item.variable
  106. let param_type = ''
  107. switch (item.value_type) {
  108. case VarType.string:
  109. param_type = ': str'
  110. break
  111. case VarType.number:
  112. param_type = ': float'
  113. break
  114. case VarType.object:
  115. param_type = ': dict'
  116. break
  117. case VarType.array:
  118. param_type = ': list'
  119. break
  120. case VarType.arrayNumber:
  121. param_type = ': list[float]'
  122. break
  123. case VarType.arrayString:
  124. param_type = ': list[str]'
  125. break
  126. case VarType.arrayObject:
  127. param_type = ': list[dict]'
  128. break
  129. }
  130. param += param_type
  131. param_list.push(`${param}`)
  132. }
  133. newMainDef = `def main(${param_list.join(', ')})`
  134. }
  135. else { return code }
  136. const newCode = code.replace(mainDefRe, newMainDef)
  137. return newCode
  138. }
  139. const newInputs = produce(inputs, (draft) => {
  140. draft.code = generateSyncSignatureCode(draft.code)
  141. })
  142. setInputs(newInputs)
  143. }, [inputs, setInputs])
  144. const {
  145. handleVarsChange,
  146. handleAddVariable: handleAddOutputVariable,
  147. handleRemoveVariable,
  148. isShowRemoveVarConfirm,
  149. hideRemoveVarConfirm,
  150. onRemoveVarConfirm,
  151. } = useOutputVarList<CodeNodeType>({
  152. id,
  153. inputs,
  154. setInputs,
  155. outputKeyOrders,
  156. onOutputKeyOrdersChange: setOutputKeyOrders,
  157. })
  158. const filterVar = useCallback((varPayload: Var) => {
  159. return [VarType.string, VarType.number, VarType.boolean, VarType.secret, VarType.object, VarType.array, VarType.arrayNumber, VarType.arrayString, VarType.arrayObject, VarType.arrayBoolean, VarType.file, VarType.arrayFile].includes(varPayload.type)
  160. }, [])
  161. const handleCodeAndVarsChange = useCallback((code: string, inputVariables: Variable[], outputVariables: OutputVar) => {
  162. const newInputs = produce(inputs, (draft) => {
  163. draft.code = code
  164. draft.variables = inputVariables
  165. draft.outputs = outputVariables
  166. })
  167. setInputs(newInputs)
  168. syncOutputKeyOrders(outputVariables)
  169. }, [inputs, setInputs, syncOutputKeyOrders])
  170. return {
  171. readOnly,
  172. inputs,
  173. outputKeyOrders,
  174. handleVarListChange,
  175. handleAddVariable,
  176. handleRemoveVariable,
  177. handleSyncFunctionSignature,
  178. handleCodeChange,
  179. handleCodeLanguageChange,
  180. handleVarsChange,
  181. filterVar,
  182. handleAddOutputVariable,
  183. isShowRemoveVarConfirm,
  184. hideRemoveVarConfirm,
  185. onRemoveVarConfirm,
  186. handleCodeAndVarsChange,
  187. }
  188. }
  189. export default useConfig