Files
picoGraph/scripts/nodes/library/localVariables.js
Max Litruv Boonzaayer e64f3e881e Initial commit
moved from private version control
2025-10-19 21:12:41 +11:00

170 lines
4.9 KiB
JavaScript

import { createNodeModule } from "../nodeTypes.js";
const LOCAL_TYPES = [
{ value: "number", label: "Number" },
{ value: "string", label: "String" },
{ value: "boolean", label: "Boolean" },
{ value: "table", label: "Table" },
];
const DEFAULT_LOCAL_TYPE = LOCAL_TYPES[0]?.value ?? "number";
const sanitizeType = (raw) => {
const candidate = typeof raw === "string" ? raw.toLowerCase() : DEFAULT_LOCAL_TYPE;
return LOCAL_TYPES.some((entry) => entry.value === candidate)
? candidate
: DEFAULT_LOCAL_TYPE;
};
const ensureName = (raw, fallback = "localVar") => {
const value = typeof raw === "string" ? raw.trim() : "";
return value.length ? value : fallback;
};
const resolveValuePropertyKey = (type) => {
switch (type) {
case "string":
return "valueString";
case "boolean":
return "valueBoolean";
case "table":
return "valueTable";
case "number":
default:
return "valueNumber";
}
};
const defaultValueForType = (type) => {
switch (type) {
case "string":
return "";
case "boolean":
return false;
case "table":
return "{}";
case "number":
default:
return 0;
}
};
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 (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];