# Translation strategy

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

### Steps

Creating a custom data source will require you to work on the 3 following steps:

1. Declare the structure of the data
2. Declare the API capabilities
3. Code a translation layer

### Minimal example

```javascript
const {
  BaseCollection,
  BaseDataSource,
} = require('@forestadmin/datasource-toolkit');
const axios = require('axios'); // client for the target API

// The real work is in writing this module
// Expect a full featured query translation module to be over 1000 LOCs
const QueryGenerator = require('./forest-query-translation');

/** Minimal implementation of a readonly data source */
class MyCollection extends BaseCollection {
  constructor(dataSource) {
    // Set name of the collection once imported
    super('myCollection', dataSource);

    this.addField('id', {
      // Structure
      type: 'Column',
      columnType: 'Number',
      isPrimaryKey: true,
      isReadOnly: true, // field is readonly

      // As we are using the query translation strategy => define capabilities
      filterOperators: new Set(), // field is not filterable
      isSortable: false, // field is not sortable
    });

    this.addField('title', {
      type: 'Column',
      columnType: 'String',
      isReadOnly: true,
      filterOperators: new Set(),
      isSortable: false,
    });
  }

  async list(caller, filter, projection) {
    const params = QueryGenerator.generateListQueryString(filter, projection);
    const response = axios.get('https://my-api/my-collection', { params });

    return response.body.items;
  }

  async aggregate(caller, filter, aggregation, limit) {
    const params = QueryGenerator.generateAggregateQueryString(
      filter,
      aggregation,
      limit,
    );
    const response = axios.get('https://my-api/my-collection', { params });

    return response.body.items;
  }
}

class MyDataSource extends BaseDataSource {
  constructor() {
    super();
    this.addCollection(new MyCollection(this)); // For all your collections
  }
}

module.exports = MyDataSource;
```

```javascript
const MyDataSource = require('./datasource');

const myDataSourceFactory = async () => new MyDataSource();

const agent = createAgent(options).addDataSource(myDataSourceFactory);
```

### Read more

Implementing a data source using the "query translation" strategy is an advanced concept: you will need to have a deep understanding of Forest Admin internals.

This strategy is a good match when writing data sources for full-featured databases.

Before starting, it is highly advised to read and understand the following sections:

* [Data Model Typing](https://docs.forestadmin.com/developer-guide-agents-nodejs/under-the-hood/data-model/typing)
* [Data Model Relationships](https://docs.forestadmin.com/developer-guide-agents-nodejs/under-the-hood/data-model/relationships)
* [Query interface](https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/getting-started/queries)
* [Fields and projections](https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/getting-started/queries/fields-projections)
* [Filters](https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/getting-started/queries/filters)
* [Aggregations](https://docs.forestadmin.com/developer-guide-agents-nodejs/data-sources/getting-started/queries/aggregations)
