import { createNodeModule } from "../nodeTypes.js"; import { getLocalVariableTypeOptions, variablePropertyKey, localVariableDefault, LOCAL_VARIABLE_TYPE_IDS, } from "../../types/TypeRegistry.js"; const LOCAL_TYPES = getLocalVariableTypeOptions(); const DEFAULT_LOCAL_TYPE = LOCAL_TYPES[0]?.value ?? "number"; const sanitizeType = (raw) => { const candidate = typeof raw === "string" ? raw.trim().toLowerCase() : ""; return LOCAL_VARIABLE_TYPE_IDS.has(candidate) ? candidate : DEFAULT_LOCAL_TYPE; }; const ensureName = (raw, fallback = "localVar") => { const value = typeof raw === "string" ? raw.trim() : ""; return value.length ? value : fallback; }; const resolveValuePropertyKey = variablePropertyKey; const defaultValueForType = localVariableDefault; const initializeLocalProperties = (properties, { includeValue }) => { const type = sanitizeType(properties.variableType); properties.variableType = type; properties.name = ensureName(properties.name); if (typeof properties.valueNumber !== "number") { properties.valueNumber = Number.isFinite(Number(properties.valueNumber)) ? Number(properties.valueNumber) : 0; } if (typeof properties.valueString !== "string") { properties.valueString = String(properties.valueString ?? ""); } if (typeof properties.valueBoolean !== "boolean") { properties.valueBoolean = Boolean(properties.valueBoolean); } if (typeof properties.valueTable !== "string") { properties.valueTable = String(properties.valueTable ?? "{}"); } if ( typeof properties.valueColor !== "number" || !Number.isFinite(properties.valueColor) ) { const n = Number(properties.valueColor); properties.valueColor = Number.isFinite(n) ? Math.max(0, Math.min(15, Math.round(n))) : 7; } if (includeValue) { const key = resolveValuePropertyKey(type); const value = properties[key] ?? defaultValueForType(type); properties[key] = value; } }; const normalizeLocalProperties = (properties, { includeValue }) => { const type = sanitizeType(properties.variableType); properties.variableType = type; properties.name = ensureName(properties.name); if (includeValue) { const key = resolveValuePropertyKey(type); const value = properties[key] ?? defaultValueForType(type); properties[key] = value; } }; export const setLocalVariableNode = createNodeModule( { id: "set_local_var", title: "Set Local", category: "Logic", description: "Declare or assign a local variable with an inline literal.", searchTags: ["local", "set", "assign", "variable"], inputs: [ { id: "exec_in", name: "Exec", direction: "input", kind: "exec" }, { id: "value", name: "Value", direction: "input", kind: "any", description: "Optional override for the inline literal", }, ], outputs: [ { id: "exec_out", name: "Exec", direction: "output", kind: "exec" }, ], properties: [], initializeProperties: (properties) => { initializeLocalProperties(properties, { includeValue: true }); }, onPropertiesChanged: (properties) => { normalizeLocalProperties(properties, { includeValue: true }); }, }, { emitExec: ({ node, indent, indentLevel, resolveValueInput, sanitizeIdentifier, emitNextExec, formatLiteral, }) => { const type = sanitizeType(node.properties.variableType); const name = sanitizeIdentifier(ensureName(node.properties.name)); const valueKey = resolveValuePropertyKey(type); const inlineValue = node.properties[valueKey] ?? defaultValueForType(type); const fallbackLiteral = type === "table" ? String(inlineValue ?? "{}") || "{}" : formatLiteral(type, inlineValue); const valueExpression = resolveValueInput("value", fallbackLiteral); const statement = `${indent(indentLevel)}local ${name} = ${valueExpression}`; return [statement, ...emitNextExec("exec_out")]; }, } ); export const getLocalVariableNode = createNodeModule( { id: "get_local_var", title: "Get Local", category: "Logic", description: "Access a local variable declared earlier in the flow.", searchTags: ["local", "get", "variable", "read"], inputs: [], outputs: [ { id: "value", name: "Value", direction: "output", kind: "any" }, ], properties: [], initializeProperties: (properties) => { initializeLocalProperties(properties, { includeValue: false }); }, onPropertiesChanged: (properties) => { normalizeLocalProperties(properties, { includeValue: false }); }, }, { evaluateValue: ({ node, sanitizeIdentifier }) => { return sanitizeIdentifier(ensureName(node.properties.name)); }, } ); export const localVariableNodes = [setLocalVariableNode, getLocalVariableNode];