Note: This is a work in progress.
Build self contained TypeScript friendly scripts that can be modified with a no-code node editor.
- 0 dependencies (TypeScript is an assumed peer dependency)
- No middle layer format. TS files are the source of truth.
Node editors are generally used when visual dipiction of a flow of events would be better understood. Examples include:
- Describing dialog interaction with various branching.
- Since these may loop back the nodes can be easier followed.
- Data processing flows where nodes process data.
npm install ts-node-editor
In the package.json
add a line in scripts
: "editor": "ts-node-editor"
npm run editor
Any file starting with
import type { Node }
is assumed to be a function defining a node or a script.
The node editor is split into Nodes and Scripts TypeScript files.
- Nodes are modular self contained functions.
- Scripts are a braching of nodes and the TypeScript files are what your parent application will execute.
Generated scripts can either be imported normally or dynamically. The Hello World example adds a message
to the state.
const { run } = await import('./scripts/helloWorld');
const state = await run({
name: 'John'
});
console.log(state);
// Map(2) {'name' => 'John', 'message' => 'Hello John!'}
This simple example makes use of the setState
function to update or set a variable's state.
npm run editor src/scripts/helloWorld.ts
In the editor the Hello ${name}!
gets transformed into a string literal pulling the state.get('name')
value.
Every node script starts with the same line importing the Node
type (an alias for number
);
import type { Node } from './node';
Define a node by exporting a named function.
myNode
- The name of the method can be anything.state
- An optionalMap
type of shared state passed between nodes.nodes
- An optional list of nodes connect to the top right of the node
/**
* My Node Name
*/
export function myNode({ state, nodes }: {
state: Map<string, any>
nodes: Node[]
}): Node[] {
}
All node functions must return an array of nodes. Always return [0]
instead of an empty array to ensure noop
correctly loop back.
return nodes;
get api/
{
comments: [
{ $x: 1, $y: 10, $width: 10, $height: 10, text: 'Describe the script use here.' },
],
nodes: [
{ $type: 'entry', $x: 1, $y: 1, $width: 2, $height: 2, nodes: [1] },
{ $type: 'function', $name: 'coinFlip', $x: 3, $y: 2, $width: 6, $height: 6, t: [2], f: [3] },
{ $type: 'function', $name: 'log', $x: 10, $y: 2, $width: 6, $height: 6, text: 'Heads' },
{ $type: 'function', $name: 'log', $x: 10, $y: 7, $width: 6, $height: 6, text: 'Tails' }
{ $type: 'import', $x: 10, $y: 7, $width: 6, $height: 6, src: 'helloWorld.ts', path: ['src', 'scripts'] }
]
}
delete api/comment/0
patch api/comment/0 { text: 'Updated value.' }
delete api/comment/0
post api/comment
get api/node/2
delete api/node/2
post api/node/2 { $x: 1, $y, 2, $width: 10, $height: 10 }
patch api/node/2 { nodes: [2, 4] }
get api/scripts
[{
name: 'src', directory: [{
name: 'script', directory: [{
name: 'script1.ts'
}]
}]
}]
post api/script
{
path: ['src', 'scripts']
file: 'filename.ts'
}
Editing scripts outside of the UI can be done with the node utility.
import { Script } from 'ts-node-editor';
const script = new Script();
// script.fromString();
script.fromFile('filename.ts');
const comments = script.getComments();
const index = script.addComment({
$x: 1,
$y: 2,
$width: 10,
$height: 10,
text: 'Awesome!'
});
script.updateComment(1, {
text: 'New comment text'
});
script.removeComment(2);
const nodes = script.getNodes();
const index = script.addNode({
$name: 'coinFlip',
$x: 1,
$y: 2,
$width: 10,
$height: 10,
t: [2, 4],
f: [5]
});
script.updateNode(2, {
$x: 1,
$y: 2
});
script.removeNode(2);
// script.toString();
script.toFile('filename.ts');