feat: variable node

This commit is contained in:
2026-03-06 22:31:24 +01:00
parent 17739de7bd
commit 97f6ead03b
4 changed files with 242 additions and 8 deletions

View File

@@ -52,6 +52,15 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
[edges]
)
const variablesSignature = useMemo(
() =>
nodes
.filter((n: any) => n.type === 'variable')
.map((n: any) => `${n.id}:${n.data?.value}`)
.join('|'),
[nodes]
)
useEffect(() => {
// debug
// eslint-disable-next-line no-console
@@ -73,6 +82,8 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
}
try {
const configIdsUsed = new Set<string>()
const resolveIncludes = (text: string, visited = new Set<string>()): string => {
const includeRegex = /^(\s*)!include\s+([^\s]+)\s*$/gm
return text.replace(includeRegex, (match: string, indent: string, ref: string) => {
@@ -100,6 +111,7 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
if (!isReachable(refNode.id, id)) throw new Error(`Included node not connected to renderer: ${ref}`)
visited.add(refNode.id)
if (refNode.type === 'config') configIdsUsed.add(refNode.id)
const includedRaw = String(refNode.data?.yaml ?? '')
const resolved = resolveIncludes(includedRaw, visited)
visited.delete(refNode.id)
@@ -112,8 +124,26 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
})
}
if (srcId && srcNode?.type === 'config') configIdsUsed.add(srcId)
const resolvedYaml = resolveIncludes(yamlText)
const parsed = yaml.load(resolvedYaml)
const varMap: Record<string, string> = {}
for (const e of edges) {
if (configIdsUsed.has(e.target)) {
const src = nodes.find((n: any) => n.id === e.source)
if (src?.type === 'variable') {
const v = src.data?.value
varMap[src.id] = v === undefined || v === null ? '' : String(v)
}
}
}
const resolveVariables = (text: string): string =>
text.replace(/\$\{([^}]+)\}/g, (_, varId: string) => varMap[varId.trim()] ?? '')
const resolvedWithVars = resolveVariables(resolvedYaml)
const parsed = yaml.load(resolvedWithVars)
const newOutput = JSON.stringify(parsed, null, 2)
setError(null)
setOutput((prev) => (prev === newOutput ? prev : newOutput))
@@ -122,7 +152,7 @@ export const RenderingNode = memo(function RenderingNode({ id }: Props) {
setOutput('')
setError({ kind: 'parse', message: msg })
}
}, [id, incomingIds.join(','), yamlText, configSignature, edgesSignature])
}, [id, incomingIds.join(','), yamlText, configSignature, edgesSignature, variablesSignature])
return (
<BaseNode className="w-96">