mirror of
https://github.com/litruv/picoGraph.git
synced 2026-07-24 10:46:06 +10:00
Initial commit
moved from private version control
This commit is contained in:
169
scripts/nodes/library/localVariables.js
Normal file
169
scripts/nodes/library/localVariables.js
Normal file
@@ -0,0 +1,169 @@
|
||||
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];
|
||||
Reference in New Issue
Block a user