# Validation

::references
  :::ref-example{link="/examples/chatbot" title="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](https://retejs.org/examples/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.