basic function
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
||||
BaseNodeHeader,
|
||||
BaseNodeHeaderTitle,
|
||||
} from './BaseNode'
|
||||
import { Rocket } from 'lucide-react'
|
||||
import { Sparkles } from 'lucide-react'
|
||||
import { InputHandle, OutputHandle } from './NodeHandles'
|
||||
|
||||
type Props = {
|
||||
@@ -61,6 +61,15 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
|
||||
[nodes]
|
||||
)
|
||||
|
||||
const functionsSignature = useMemo(
|
||||
() =>
|
||||
nodes
|
||||
.filter((n: any) => n.type === 'function')
|
||||
.map((n: any) => `${n.id}:${n.data?.body ?? ''}`)
|
||||
.join('|'),
|
||||
[nodes]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
// debug
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -139,10 +148,31 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
const resolveFunctionCalls = (text: string): string => {
|
||||
const fnCallRegex = /\$\{([\w-]+)\s*\(([^)]*)\)\}/g
|
||||
return text.replace(fnCallRegex, (match, funcId: string, argsStr: string) => {
|
||||
const fnNode = nodes.find((n: any) => n.id === funcId && n.type === 'function')
|
||||
if (!fnNode) return match
|
||||
const body = fnNode.data?.body ?? 'return args[0];'
|
||||
const argIds = argsStr.split(',').map((s: string) => s.trim()).filter(Boolean)
|
||||
const argValues = argIds.map((argId: string) => varMap[argId] ?? '')
|
||||
try {
|
||||
const fn = new Function('args', body)
|
||||
const result = fn(argValues)
|
||||
if (result === undefined || result === null) return ''
|
||||
if (typeof result === 'string' || typeof result === 'number' || typeof result === 'boolean') return String(result)
|
||||
return String(result)
|
||||
} catch (err) {
|
||||
return match
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const resolveVariables = (text: string): string =>
|
||||
text.replace(/\$\{([^}]+)\}/g, (_, varId: string) => varMap[varId.trim()] ?? '')
|
||||
|
||||
const resolvedWithVars = resolveVariables(resolvedYaml)
|
||||
const afterFunctions = resolveFunctionCalls(resolvedYaml)
|
||||
const resolvedWithVars = resolveVariables(afterFunctions)
|
||||
const parsed = yaml.load(resolvedWithVars)
|
||||
const newOutput = JSON.stringify(parsed, null, 2)
|
||||
setError(null)
|
||||
@@ -152,12 +182,12 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
|
||||
setOutput('')
|
||||
setError({ kind: 'parse', message: msg })
|
||||
}
|
||||
}, [id, incomingIds.join(','), yamlText, configSignature, edgesSignature, variablesSignature])
|
||||
}, [id, incomingIds.join(','), yamlText, configSignature, edgesSignature, variablesSignature, functionsSignature])
|
||||
|
||||
return (
|
||||
<BaseNode className="w-96">
|
||||
<BaseNodeHeader className="border-b">
|
||||
<Rocket className="size-4" />
|
||||
<Sparkles className="size-4" />
|
||||
<BaseNodeHeaderTitle>{id}</BaseNodeHeaderTitle>
|
||||
</BaseNodeHeader>
|
||||
|
||||
@@ -166,7 +196,7 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
|
||||
<Empty>
|
||||
<EmptyHeader>
|
||||
<EmptyMedia variant="icon">
|
||||
<Rocket className="size-6" />
|
||||
<Sparkles className="size-6" />
|
||||
</EmptyMedia>
|
||||
<EmptyTitle>No configuration connected</EmptyTitle>
|
||||
<EmptyDescription>Connect a Configuration node or create one. The renderer will display parsed YAML.</EmptyDescription>
|
||||
|
||||
Reference in New Issue
Block a user