## GraphQL Practices

After discussion with the Apollo team, we have arrived at the following uses 
for the different facets of GraphQL.

### Query

Queries are unique to the source of the data and define the parameters 
needed by the client to define the context of the results. In this scenario, 
you know what you're asking for and where you want it from.

#### Examples

```
async allProductsSearch(parent, { sortOrder, limit, offset }, { dataSources }) {
    return dataSources.owsSearch.searchProducts({ sortOrder, limit, offset }); 
}
```

### Resolvers

Resolvers are responsible for populating individual fields by delegating to 
connectors (or returning data they already have from previous calls).

#### Example

```
async format({ productId, format }, params, { dataSources }) {
    if (format)
        return format;
    const doc = await dataSources.owsProduct.getProductDocument(productId);
    return doc.format;
}
```

### Connectors

Connectors are responsible for encapsulating data retrieval from microservices 
and shaping the data to the schema format. For example, our connector for 
`ows-search` communicates with the `ows-search` microservice, which returns:

```
{
  results:
   { rel2539039:
      { release_id: '2539039',
        vendor_id: '6971',
        release_name: 'dfgj',
        ...
      }
   }
}
```

Our schema definition for a product, however, does not use camel-case fields. 
Additionally, `ows-search` refers to `productId` as `release_id`. Since we 
need these fields to be consistent with the structure of our GraphQL schema, 
we will need to map these values to the correct object structure before they're
returned from the connector (see 
[/src/connectors/ows-search/formatters/product.js](/src/connectors/ows-search/formatters/product.js)
as an example).

### Schema

Schema defines the shape of the data and the method signatures for queries. All 
data should ultimately conform to the schema regardless of which connector and 
data source it was retrieved from.
