mirror of
https://github.com/litruv/picoGraph.git
synced 2026-07-24 02:36:04 +10:00
170 lines
4.9 KiB
JavaScript
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];
|