feat: variable node
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user