@tokens-studio/graph-engine
Version:
An execution engine to handle Token Studios generators and resolvers
159 lines • 5.57 kB
JavaScript
import { Port } from './port.js';
import { action, makeObservable } from 'mobx';
import getDefaults from 'json-schema-defaults-esm';
export class Input extends Port {
/**
* Expects to have connections to this node done by enqueing the edge
*/
variadic;
constructor(props) {
super(props);
this.variadic = props.variadic || false;
makeObservable(this, {
setValue: action,
reset: action,
deserialize: action
});
}
/**
* Sets the value without a side effect. This should only be used internally
* @param value
*/
setValue(value, opts) {
if (this.isConnected && !this.variadic && !opts?.forceStore) {
if (opts?.type !== undefined) {
this.handleTypeUpdate(opts.type);
}
if (!opts?.noPropagate) {
this.node.getGraph()?.update(this.node.id);
}
return;
}
this._value = value;
if (opts?.type !== undefined) {
this.handleTypeUpdate(opts.type);
}
if (!opts?.noPropagate) {
this.node.getGraph()?.update(this.node.id);
}
}
handleTypeUpdate(type) {
if (this._type?.$id !== undefined) {
if (this._type?.$id !== type.$id) {
this._dynamicType = type;
}
}
//Otherwise do a structural comparison
else if (JSON.stringify(this._type) !== JSON.stringify(type)) {
const { variadic, _dynamicType } = this;
// for variadic ports, we need to set the dynamic type depending on all the other connected types
if (variadic &&
_dynamicType &&
JSON.stringify(_dynamicType) !== JSON.stringify(type)) {
const graph = this.node.getGraph();
const sourceNodesOutputTypes = this._edges.map(edge => {
const outputs = graph.getNode(edge.source).outputs;
return outputs[edge.sourceHandle].type;
});
const firstNodeTypeStringValue = JSON.stringify(sourceNodesOutputTypes[0]);
if (sourceNodesOutputTypes.every(type => JSON.stringify(type) === firstNodeTypeStringValue)) {
this._dynamicType = {
type: 'array',
items: sourceNodesOutputTypes[0]
};
}
else {
this._dynamicType = null;
}
}
else {
this._dynamicType = type;
}
}
}
/**
* Resets the value of the input to the default value
*/
reset() {
this._dynamicType = null;
return (this._value = getDefaults(this._type));
}
/**
* Returns the underlying class of the input.
* @returns
*/
get factory() {
//@ts-ignore
return this.constructor;
}
clone() {
const clonedInput = new this.factory({
name: this.name,
type: this.type,
visible: this.visible,
node: this.node,
variadic: this.variadic,
annotations: { ...this.annotations },
value: this.value
});
return clonedInput;
}
fullType() {
return {
type: this._type,
visible: this.visible,
variadic: this.variadic
};
}
serialize() {
const type = this.fullType();
const serialized = {
name: this.name,
type: type.type
};
// Only include value in serialization if not a connected non-variadic input
// This prevents redundant data storage in the serialized format
if (!this.isConnected || this.variadic) {
serialized.value = this.value;
}
if (this._dynamicType) {
serialized.dynamicType = this._dynamicType;
}
//Try compact the serialization by omitting the value if its the default
if (type.variadic) {
serialized.variadic = true;
}
// ignore SQ warning to refactor "== false", because visible could be undefined,
// and we only want to store if it's explicitly not visible
if (type.visible == false) {
serialized.visible = false;
}
if (Object.keys(this.annotations).length > 0) {
serialized.annotations = this.annotations;
}
return serialized;
}
deserialize(serialized) {
this.visible = serialized.visible ?? true;
this._dynamicType = serialized.dynamicType || null;
this.annotations = serialized.annotations || {};
// Only set the value if it's explicitly defined in the serialized data
// This maintains compatibility with our optimization to not store values for connected inputs
if ('value' in serialized) {
this._value = serialized.value;
}
}
get value() {
// for connected non-variadic inputs, values should come from connected outputs
if (this.isConnected && !this.variadic && this._edges.length > 0) {
const graph = this.node.getGraph();
if (graph) {
const edge = this._edges[0];
return (graph.getNode(edge.source)?.outputs?.[edge.sourceHandle]?.value ??
this._value);
}
}
return this._value;
}
}
//# sourceMappingURL=input.js.map