Validation - Rete.js

Validation

Chatbot

The framework provides a flexible plugin and message system, which enables you to extend the functionality of various components and manage their behavior. This can be achieved by using pipes for specific message types.

Nodes validation

Validation will be implemented for adding nodes, where nodes of a certain type will be prevented until the starting node is added

ts
editor.addPipe(context => {
  if (context.type === 'nodecreate') {
    if (context.data instanceof EndNode) {
      const hasBeginNode = editor.getNodes().some(n => n instanceof BeginNode)

      if (!hasBeginNode) {
        alert('cannot add EndNode until BeginNode is added')
        return
      }
    }
  }
  return context
})

where EndNode and BeginNode are classes that extend ClassicPreset.Node.

This particular case utilized a method of preventing message propagation by specifying return with no value. This technique is appropriate for types like nodecreate, noderemove, connectioncreate and connectionremove.

Connections validation

The same principle can be used to prevent messages of connectioncreate type.

ts
editor.addPipe((context) => {
  if (context.type === "connectioncreate") {
    if (!canCreateConnection(editor, context.data)) {
      alert("Sockets are not compatible");
      return;
    }
  }
  return context;
});

where canCreateConnection is any function that takes a connection instance context.data and returns a boolean.

Let's take the Chatbot example, particularly the modules chatbot/utils.ts and chatbot/sockets.ts, and apply the same approach to our canCreateConnection function. First, we'll implement advanced sockets:

ts
import { ClassicPreset } from "rete";

export class ActionSocket extends ClassicPreset.Socket {
  constructor() {
    super("Action");
  }

  isCompatibleWith(socket: ClassicPreset.Socket) {
    return socket instanceof ActionSocket;
  }
}

export class TextSocket extends ClassicPreset.Socket {
  constructor() {
    super("Text");
  }

  isCompatibleWith(socket: ClassicPreset.Socket) {
    return socket instanceof TextSocket;
  }
}

by using isCompatibleWith method, socket types are able to specify which other socket types they are compatible.

After that, we will implement our function which takes a connection as an argument, returns the corresponding sockets from the nodes, and checks them for compatibility.

ts
export function canCreateConnection(editor: NodeEditor<Schemes>, connection: Schemes["Connection"]) {
  const { source, target } = getConnectionSockets(editor, connection);

  return source && target && source.isCompatibleWith(target)
}

where getConnectionSockets function was taken from the aforementioned example.