# Route overrides

{% hint style="success" %}
This is the official documentation of the `@forestadmin/agent` Node.js agent.
{% endhint %}

[Route overrides](https://docs.forestadmin.com/documentation/reference-guide/routes/override-a-route) allowed customizing the behavior of the routes exposed by the agent.

This very low-level feature was used to implement many use cases:

* Attach handlers to events in the UI
* Customize filtering, search and sort behaviors
* Other advanced use cases.

Because our new agent API is higher-level, the protocol used to communicate between the agent and the application can no longer be manipulated.

## Code cheatsheet

| What was the route override used for?   | How to migrate it?                                                                                                                                                                    |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Add custom permissions                  | Use [.addHook()](/developer-guide-agents-nodejs/agent-customization/hooks.md) and throw `forbidden errors`                                                                            |
| Add validation to fields                | Use [.addFieldValidation()](/developer-guide-agents-nodejs/agent-customization/fields/validation.md) instead                                                                          |
| Add validation to whole records         | Use [.addHook()](/developer-guide-agents-nodejs/agent-customization/hooks.md) and throw `validation errors`                                                                           |
| Run code on UI events                   | Use [.addHook()](/developer-guide-agents-nodejs/agent-customization/hooks.md) to perform custom logic                                                                                 |
| Change the search behavior              | Use [.replaceSearch()](/developer-guide-agents-nodejs/agent-customization/search.md) to implement your custom search logic                                                            |
| Change the filtering behavior of fields | Use [.replaceFieldOperator()](/developer-guide-agents-nodejs/agent-customization/fields/filter.md)                                                                                    |
| Change the sort behavior of fields      | Use [.replaceFieldSorting()](/developer-guide-agents-nodejs/agent-customization/fields/sort.md)                                                                                       |
| Other use case                          | If you are stuck or think that this guide can be improved, please [expose your use case in the community forums](https://community.forestadmin.com/) and we will be happy to help you |

## Examples

### Add custom permissions

{% hint style="warning" %}
Custom permissions would better be implemented by using the [Roles](https://docs.forestadmin.com/user-guide/project-settings/teams-and-users/manage-roles) feature from the UI.
{% endhint %}

{% tabs %}
{% tab title="Before" %}

```javascript
router.delete(
  '/companies/:recordId',
  permissionMiddlewareCreator.delete(),
  (request, response, next) => {
    const { params, query, user } = request;

    if (user.email !== 'sandro.munda@forestadmin.com') {
      response
        .status(403)
        .send('This collection is protected, you cannot remove from it.');
      return;
    }

    next();
  },
);
```

{% endtab %}

{% tab title="After" %}

```javascript
agent.customizeCollection('customers', companies => {
  // Add a hook to the "customers" collection
  companies.addHook('Before', 'Delete', async context => {
    if (context.caller.email !== 'sandro.munda@forestadmin.com')
      context.throwForbiddenError(
        'This collection is protected, you cannot remove from it.',
      );
  });
});
```

{% endtab %}
{% endtabs %}

### Add validation to fields

{% tabs %}
{% tab title="Before" %}

```javascript
function handler(request, response, next) {
  const patch = request.body.data.attributes;

  if (path.name && /^Forest/.test(path.name)) {
    return "All company names should begin with 'Forest'.";
  }

  if (error) {
    response.status(400).send(error);
  } else {
    next();
  }
}

router.post('/companies', permissionMiddlewareCreator.create(), handler);
router.put('/companies/:id', permissionMiddlewareCreator.update(), handler);
```

{% endtab %}

{% tab title="After" %}

```javascript
agent.customizeCollection('companies', companies => {
  companies.addFieldValidation('name', 'Match', /^Forest/);
});
```

{% endtab %}
{% endtabs %}

### Run code on UI events

{% tabs %}
{% tab title="Before" %}

```javascript
// Override the POST /customers route
router.post(
  '/customers',
  permissionMiddlewareCreator.create(),
  async (req, res, next) => {
    try {
      // Call an external API.
      await superagent
        .post('https://my-company/create-card')
        .set('X-API-Key', '**********')
        .end();

      // Calls next() to executes Forest Admin's default behavior
      next();
    } catch (err) {
      next(err);
    }
  },
);
```

{% endtab %}

{% tab title="After" %}

```javascript
agent.customizeCollection('customers', companies => {
  // Add a hook to the "customers" collection
  companies.addHook('Before', 'Create', async context => {
    await superagent
      .post('https://my-company/create-card')
      .set('X-API-Key', '**********')
      .end();
  });
});
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestadmin.com/developer-guide-agents-nodejs/getting-started/migrating/steps/code-transformations/route-overrides.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
