basic function

This commit is contained in:
2026-03-06 23:03:42 +01:00
parent d690c94369
commit 49a6e5b4a3
4 changed files with 210 additions and 7 deletions

View File

@@ -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>