graphile / graphile/crystal

Planned module: @dataplan/graphql

Open
#2,037 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
12.9k
Forks
625
Avg merge
5h 23m
Merged PRs (30d)
24

Description

### Summary
**Grafast Question: What is the best way to get or assemble the accessed fields from the finalized plan?**

HI @benjie, awesome work here! I'm excited for the future of grafast, its a novel solution to the continual pains of graphql resolution.

#### Example Case Question
Our team is writing a small service-specific graphql api wrapping our larger core graphql api. The schema will largely be a subset of the core schema, but with many fields filtered out and others added for denormalization / business logic. We've explored delegation, federation, and stitching, but all those seem rather bloated for our use case.

I was wondering if you have suggestions on using grafast steps to build up a dynamic query to another graphql server. I suspect this is theoretically very similar to pg planning.

Here is a somewhat contrived example schema for the service-specific api using grafast:

```typescript
const typeDefs = /* GraphQL */ `
type Query {
order(id: Int): Order
}

type Order {
id: Int
name: String
customer: Customer
}

type Customer {
id: Int
name: String
displayName: String
}
`

const plans: GrafastPlans = {
Order: {
id: ($order: ObjectLikeStep) => {
return $order.get('id')
},
name: ($order: ObjectLikeStep) => {
return lambda([$order.get('id')], ([id]) => {
return `Order #${id}`
})
},
customer($order: ObjectLikeStep) {
return $order.get('customer')
},
},
Customer: {
id: ($customer: ObjectLikeStep) => {
return $customer.get('id')
},
name: ($customer: ObjectLikeStep) => {
return $customer.get('name')
},
displayName: ($customer: ObjectLikeStep) => {
const $name = $customer.get('name')
const $region = $customer.get('region')
return lambda([$name, $region], ([name, region]) => {
return `${name} (${region})`
})
},
},
Query: {
order(_, fieldArgs, _builder) {
const $id = fieldArgs.get('id')
return loadOne($id, async (specs, options) => {
const someSelectFromAccessedFieldsInDag = {
// How to fetch full select here?
}
const query = jsonToGraphQLQuery({
query: {
order: {
__args: {
id: $id,
},
...someSelectFromAccessedFieldsInDag,
},
},
})
return client.execute(query)
})
},
},
}
```

And given the following example query to the grafast api:
```graphql
query order($id: Int) {
order(id: $id) {
name
customer {
name
displayName
}
}
}
```
That query assembles a plan with `$order.id`, `$order.customer`, `$customer.name` and `$customer.region`.

Given that, the desired query to the core graphql api would be:
```graphql
query order($id: Int) {
order(id: $id) {
id
customer {
name
region
}
}
}
```

What would be the best way to assemble the full set of fields accessed from the `Query.order` step? Can that be done by walking the plan itself, or do we need to use a custom step class to track and assemble the core api query?

Thanks!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.