Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions content/docs/products/lattice/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,44 @@ subgraphs:
Authorization: "Bearer ${SUBGRAPH_TOKEN}"
```

## REST Connectors

Federate a REST API as a subgraph. Declare the subgraph's GraphQL shape with a `schema` (used by `lattice compose`) and map its root fields to HTTP requests under `rest`. A REST subgraph needs no `url`:

```yaml
subgraphs:
petstore:
schema: ./schemas/petstore.graphql
rest:
base_url: https://petstore.example.com
headers:
Authorization: "Bearer ${PETSTORE_TOKEN}"
fields:
pet:
path: /pets/{id} # {id} is filled from the field arguments
select: /data # optional JSON Pointer into the response body
pets:
method: GET # defaults to GET
path: /pets
query:
status: state # ?status=<value of the `state` argument>
```

At runtime the planner routes fetches to `petstore` like any subgraph. The connector interpolates arguments into `path`, adds the mapped `query` parameters, attaches `headers`, calls the upstream, and returns the JSON (optionally narrowed by `select`) as the field result.

| Field | Purpose |
| --- | --- |
| `base_url` | Prepended to every field `path`. |
| `headers` | Static headers sent on every request. |
| `fields.<name>.method` | HTTP method (defaults to `GET`). |
| `fields.<name>.path` | Path template; `{arg}` placeholders come from the field arguments. |
| `fields.<name>.query` | Query parameters, mapping a parameter name to an argument name. |
| `fields.<name>.select` | Optional JSON Pointer selecting a sub-value of the response body. |
| `fields.<name>.body` | For write methods, the argument sent as the JSON request body. |
| `entities.<Type>` | Resolver that fetches one `<Type>` by its `@key` fields, for federated `_entities` resolution. |

REST connectors cover query fields, mutations, and entity resolution. See [REST Connectors](./rest-connectors) for the full guide. OpenAPI schema generation is on the roadmap.

## Caching

Response caching via Valkey/Redis:
Expand Down
5 changes: 3 additions & 2 deletions content/docs/products/lattice/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ import { FaNetworkWired, FaProjectDiagram } from "react-icons/fa";
alerts={[
{
title: "💡 What is Lattice?",
description: "GraphQL Federation gateway for composing multiple services into a unified API",
description: "Federation gateway that composes GraphQL and REST services into one unified API",
},
]}
/>

**Omni Lattice** is a GraphQL Federation gateway that composes multiple subgraph services into a unified supergraph API. Built from the ground up in Rust with an Apache 2.0 license.
**Omni Lattice** is a federation gateway that composes multiple services, GraphQL subgraphs and REST APIs alike, into a unified supergraph API. Built from the ground up in Rust with an Apache 2.0 license.

## Quick Start

Expand Down Expand Up @@ -104,6 +104,7 @@ docker run -p 4000:4000 \
## Key Features

- **GraphQL Federation v2**: Query planning and execution across subgraphs
- **REST Connectors**: Federate REST APIs as subgraphs, mapping GraphQL fields to HTTP endpoints
- **`@defer` Support**: Incremental delivery via `multipart/mixed` responses
- **Request Deduplication**: Coalesce identical in-flight subgraph fetches
- **Directive-Based Authorization**: Enforce `@requiresScopes` and `@requiresAuthentication`
Expand Down
2 changes: 2 additions & 0 deletions content/docs/products/lattice/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"title": "🔲 Lattice",
"pages": [
"configuration",
"---Sources---",
"rest-connectors",
"---Features---",
"authentication",
"plugins",
Expand Down
145 changes: 145 additions & 0 deletions content/docs/products/lattice/rest-connectors.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
title: REST Connectors
description: Federate REST APIs as subgraphs in a Lattice supergraph
---

Lattice federates more than GraphQL. A **REST connector** exposes a REST API to the graph as a subgraph: map its fields to HTTP requests, and Lattice plans and executes queries across it alongside your GraphQL subgraphs.

## How it works

A subgraph is backed by REST when it carries a `rest` block instead of a GraphQL `url`:

- **Composition.** `lattice compose` reads the subgraph's `schema` (its SDL) and composes it into the supergraph, so the planner knows the REST subgraph's types and fields.
- **Execution.** At query time the planner routes fetches to the subgraph like any other. The connector translates each subquery into HTTP calls: it interpolates field arguments into the path, adds query parameters, attaches headers, and shapes the JSON response back into GraphQL.

No HTTP introspection happens for a REST subgraph; its shape comes entirely from the `schema` you provide.

## Example

Describe the subgraph's shape in SDL:

```graphql
# schemas/petstore.graphql
type Pet {
id: ID!
name: String!
status: String!
}

type Query {
pet(id: ID!): Pet
pets(status: String): [Pet!]!
}
```

Map its fields to the REST API:

```yaml
# lattice.yaml
supergraph:
path: ./supergraph.graphql

subgraphs:
petstore:
schema: ./schemas/petstore.graphql
rest:
base_url: https://petstore.example.com
headers:
Authorization: "Bearer ${PETSTORE_TOKEN}"
fields:
pet:
path: /pets/{id}
select: /data
pets:
path: /pets
query:
status: status
```

Compose and run:

```bash
lattice compose --config lattice.yaml --output supergraph.graphql
lattice serve --config lattice.yaml
```

A client query now resolves over REST:

```graphql
query {
pet(id: "7") {
name
status
}
}
```

Lattice calls `GET https://petstore.example.com/pets/7`, reads `/data` from the response body, and returns it as `pet`.

## Mutations

Map a GraphQL mutation to a write method and send a JSON body with `body`, naming the argument whose value is the payload:

```yaml
subgraphs:
petstore:
schema: ./schemas/petstore.graphql
rest:
base_url: https://petstore.example.com
fields:
createPet:
method: POST
path: /pets
body: input # the `input` argument is sent as the JSON body
```

```graphql
mutation {
createPet(input: { name: "Rex" }) {
id
}
}
```

Lattice sends `POST /pets` with `{"name":"Rex"}` and returns the response as `createPet`.

## Entity resolution

A REST source can resolve entities that other subgraphs reference by `@key`. Declare an `entities` resolver per type; the representation's key fields fill the resolver `path`:

```yaml
subgraphs:
petstore:
schema: ./schemas/petstore.graphql
rest:
base_url: https://petstore.example.com
entities:
Pet:
path: /pets/{id} # {id} comes from the entity's @key fields
select: /data
```

When another subgraph yields a `Pet` by its key, Lattice calls `GET /pets/{id}` for each referenced entity and merges the result into the graph. A single `_entities` fetch resolves its representations in order, one REST call each.

## Mapping reference

| Field | Purpose |
| --- | --- |
| `base_url` | Base URL prepended to every field `path`. |
| `headers` | Static headers sent on every request. |
| `fields.<name>.method` | HTTP method. Defaults to `GET`. |
| `fields.<name>.path` | Path template appended to `base_url`. `{arg}` placeholders are filled from the field arguments. |
| `fields.<name>.query` | Query-string parameters, mapping a parameter name to a field argument name. A parameter is omitted when its argument is absent. |
| `fields.<name>.select` | Optional [JSON Pointer](https://datatracker.ietf.org/doc/html/rfc6901) selecting a sub-value of the response body as the field result. |
| `fields.<name>.body` | For write methods, the argument whose value is sent as the JSON request body. |
| `entities.<Type>` | An entity resolver (same shape as a field mapping) that fetches one `<Type>` by its `@key` fields. |

Arguments may be literals or GraphQL variables; variables are resolved before the request is built.

## Scope

REST connectors cover query fields, mutations, and federated entity resolution. On the roadmap:

- OpenAPI ingestion to generate the subgraph SDL and mappings from a spec.
- Response field mapping for upstreams whose JSON shape differs from the schema.
- Additional upstream protocols.
Loading