# Remote Read and Adapter

## Content

A remote table retrieves data through the `read` configuration.
The `read` option defines:

* Where to request data
* How to send the request
* How to interpret the response structure

By default, the response is treated as a standard JSON array.
If the response follows a structured protocol, an adapter can be specified.

## Basic HTTP Read (Default Behavior)

If no adapter is specified, the response is treated as the records array.
Example:

```javascript
const products = dataManager.addTable("products", {
    remote: {
        read: {
            url: "https://example.com/api/products",
            method: "GET"
        }
    }
});

products.fetch();
```

Expected response format:

```json
[
  { "ProductId": 1, "ProductName": "ItemA", "UnitPrice": 15 },
  { "ProductId": 2, "ProductName": "ItemB", "UnitPrice": 17 }
]
```

If the response is already an array, no adapter is required.

## REST Adapter

Some REST APIs return a wrapped structure.
Example response:

```json
{
  "status": "success",
  "data": [
    { "id": 1, "name": "Item A" },
    { "id": 2, "name": "Item B" }
  ]
}
```

Use the `rest` adapter to extract the `data` field:

```javascript
const products = dataManager.addTable("products", {
    remote: {
        read: {
            url: "https://example.com/api/products",
            adapter: "rest"
        }
    }
});
```

With the REST adapter:

* The `data` property is treated as the record collection.
* Other wrapper properties are ignored.

## OData Adapter

OData responses store records in the `value` property.
Example response:

```json
{
  "@odata.context": "...",
  "value": [
    { "ProductId": 1, "ProductName": "ItemA" }
  ]
}
```

Use:

```javascript
const products = dataManager.addTable("products", {
    remote: {
        read: {
            url: "https://example.com/api/products",
            adapter: "odata"
        }
    }
});
```

The adapter automatically extracts the `value` array.

## OData v4 Adapter

OData v4 follows the same `value` structure but may include additional metadata.

```javascript
const products = dataManager.addTable("products", {
    remote: {
        read: {
            url: "https://example.com/api/products",
            adapter: "odata4"
        }
    }
});
```

The `odata4` adapter handles v4-specific metadata automatically.

## GraphQL Adapter

GraphQL responses wrap records inside nested `data` objects.
Example response:

```json
{
  "data": {
    "users": {
      "data": [
        { "id": "1", "name": "Leanne Graham" }
      ]
    }
  }
}
```

Example configuration:

```javascript
const users = dataManager.addTable("users", {
    remote: {
        read: {
            url: "https://graphqlzero.almansi.me/api",
            adapter: "graphql",
            method: "POST",
            body: {
                query: `
                    query {
                        users {
                            data {
                                id
                                name
                                email
                            }
                        }
                    }
                `
            }
        }
    },
    schema: {
        dataPath: "users.data"
    }
});
```

Important:

* GraphQL usually requires `POST`.
* The query must be provided.
* `schema.dataPath` specifies where the record array resides.

Schema details are documented in the **Schema** section.

## Using Request Options

The `options` property corresponds to the standard `fetch` configuration.
Example:

```javascript
read: {
    url: "https://example.com/api/products",
    method: "POST",
    options: {
        headers: {
            "Content-Type": "application/json"
        }
    }
}
```

This allows:

* Custom headers
* Credentials
* Mode configuration
* Other fetch settings

## Using body

The `body` property is a simplified way to specify the request body.
Example:

```javascript
read: {
    url: "https://graphqlzero.almansi.me/api",
    adapter: "graphql",
    method: "POST",
    body: {
        query: "{ users { data { id name } } }"
    }
}
```

If both `body` and `options.body` are provided:

* `body` takes priority.
* Operation-specific bodies may override it.

## Custom Read Handler

Instead of providing a URL configuration, you can define a function:

```javascript
const products = dataManager.addTable("products", {
    remote: {
        read: function () {
            return Promise.resolve([
                { ProductId: 1, ProductName: "Chai" }
            ]);
        }
    }
});
```

This allows:

* Full control over data retrieval
* Integration with custom transport layers
* Mock implementations

>type=note
> **Note:**
> Function-based handlers cannot be serialized during export.