Skip to content

Commit

Permalink
add inject item node (#491)
Browse files Browse the repository at this point in the history
  • Loading branch information
mck authored Aug 7, 2024
1 parent a18068c commit 83abbb5
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-wolves-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tokens-studio/graph-engine": minor
---

Add Inject Item into Array node, this allows you to add a new item to the array at a given index, also allowing negative index to go last to first
2 changes: 1 addition & 1 deletion packages/graph-engine/src/nodes/array/arraySubgraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface IArraySubgraph extends INodeDefinition {
}

export default class ArraySubgraph<T, V> extends Node {
static title = 'Array Map (iterate over list) ';
static title = 'Array Map';
static type = 'tokens.studio.array.map';
static description =
"Execute a graph for every item in an Array (list of items). The output is an array of the same length as the input array. The inner graph is executed for each item in the array (list). The inner graph automatically has an input node with the name 'value' and an output node with the name 'value' as well. The inner graph also has an input node with the name 'index' and an input node with the name 'length' to get the current index and length of the array.";
Expand Down
8 changes: 5 additions & 3 deletions packages/graph-engine/src/nodes/array/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import filter from './filter.js';
import find from './find.js';
import flatten from './flatten.js';
import indexArray from './indexArray.js';
import inject from './inject.js';
import push from './push.js';
import reverse from './reverse.js';
import slice from './slice.js';
Expand All @@ -17,9 +18,10 @@ export const nodes = [
filter,
find,
flatten,
sort,
push,
indexArray,
inject,
push,
reverse,
slice
slice,
sort
];
58 changes: 58 additions & 0 deletions packages/graph-engine/src/nodes/array/inject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
AnyArraySchema,
AnySchema,
NumberSchema
} from '../../schemas/index.js';
import { INodeDefinition, ToInput, ToOutput } from '../../index.js';
import { Node } from '../../programmatic/node.js';

export default class NodeDefinition<T> extends Node {
static title = 'Inject Item';
static type = 'studio.tokens.array.inject';
static description = 'Injects an item into an array at a specified index.';

declare inputs: ToInput<{
array: T[];
item: T;
index: number;
}>;

declare outputs: ToOutput<{
value: T[];
}>;

constructor(props: INodeDefinition) {
super(props);
this.addInput('array', {
type: AnyArraySchema
});
this.addInput('item', {
type: AnySchema
});
this.addInput('index', {
type: NumberSchema
});
this.addOutput('array', {
type: AnyArraySchema
});
}

execute(): void | Promise<void> {
const { item, index } = this.getAllInputs();
const array = this.getRawInput('array');
this.inputs.item.setType(array.type.items);

// Create a copy of the array value
const result = [...array.value];

if (index >= 0) {
result.splice(index, 0, item);
} else {
const insertIndex = Math.max(0, result.length + index + 1);
result.splice(insertIndex, 0, item);
}

// Set the output using the modified result and the original array type
this.setOutput('array', result, array.type);
}
}
7 changes: 6 additions & 1 deletion packages/graph-engine/src/programmatic/port.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ export class Port<T = any> {
value: computed,
isConnected: computed,
dynamicType: computed,
setVisible: action
setVisible: action,
setType: action
});
}

Expand Down Expand Up @@ -80,4 +81,8 @@ export class Port<T = any> {
setNode(node: Node) {
this.node = node;
}

setType(type: GraphSchema) {
this._dynamicType = type;
}
}
84 changes: 84 additions & 0 deletions packages/graph-engine/tests/suites/nodes/array/inject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Graph } from '../../../../src/graph/graph.js';
import { describe, expect, test } from 'vitest';
import Node from '../../../../src/nodes/array/inject.js';

describe('array/inject', () => {
test('injects an item at a positive index', async () => {
const graph = new Graph();
const node = new Node({ graph });

node.inputs.array.setValue([1, 2, 3]);
node.inputs.item.setValue(4);
node.inputs.index.setValue(1);

await node.execute();

expect(node.outputs.array.value).to.eql([1, 4, 2, 3]);
});

test('injects an item at the beginning with index 0', async () => {
const graph = new Graph();
const node = new Node({ graph });

node.inputs.array.setValue([1, 2, 3]);
node.inputs.item.setValue(0);
node.inputs.index.setValue(0);

await node.execute();

expect(node.outputs.array.value).to.eql([0, 1, 2, 3]);
});

test('injects an item at the end with index equal to array length', async () => {
const graph = new Graph();
const node = new Node({ graph });

node.inputs.array.setValue([1, 2, 3]);
node.inputs.item.setValue(4);
node.inputs.index.setValue(3);

await node.execute();

expect(node.outputs.array.value).to.eql([1, 2, 3, 4]);
});

test('injects an item at a negative index', async () => {
const graph = new Graph();
const node = new Node({ graph });

node.inputs.array.setValue([1, 2, 3]);
node.inputs.item.setValue(4);
node.inputs.index.setValue(-2);

await node.execute();

expect(node.outputs.array.value).to.eql([1, 2, 4, 3]);
});

test('injects an item at the beginning with a large negative index', async () => {
const graph = new Graph();
const node = new Node({ graph });

node.inputs.array.setValue([1, 2, 3]);
node.inputs.item.setValue(0);
node.inputs.index.setValue(-10);

await node.execute();

expect(node.outputs.array.value).to.eql([0, 1, 2, 3]);
});

test('does not mutate the original array', async () => {
const graph = new Graph();
const node = new Node({ graph });

const originalArray = [1, 2, 3];
node.inputs.array.setValue(originalArray);
node.inputs.item.setValue(4);
node.inputs.index.setValue(1);

await node.execute();

expect(originalArray).to.eql([1, 2, 3]);
});
});

0 comments on commit 83abbb5

Please sign in to comment.