Skip to content

Instantly share code, notes, and snippets.

View AlecAivazis's full-sized avatar
💭
I may be slow to respond.

Alec Aivazis AlecAivazis

💭
I may be slow to respond.
View GitHub Profile
@AlecAivazis
AlecAivazis / move.txt
Last active September 23, 2023 16:35
This has been moved to: https://github.com/HoudiniGraphql/houdini/issues/1166

Proposal

I think we should approach this from the perspective of two discrete packages: graphiql and graphql-ide. Doing this allows us to design different APIs that cater to the distinct sets of users would be interested in using graphiql directly. The break down of the two libraries is outlined below with motivations further down.

The actual names and API here couldn't be further from final. They were just what came to mind first.

GraphiQL

This library is meant for simple users who have already bought into the GraphiQL experience and are looking to customize it. These customizations would include things like a custom fetcher, themes, etc. They explicitly do not include any modification of the internal UI. If the user cares about modifying the internals of the UI they should go to graphql-ide. If/when plugins and presets exist, they are implemented here - not in graphql-ide.

mutation {
login(input: {username: "1", password: "1"}) {
authToken
}
}
gw, err := gateway.New(schemas,
gateway.WithMiddlewares(forwardUserID),
gateway.WithQueryFields(viewerField)
)
import "github.com/vektah/gqlparser/ast"
var viewerField = &gateway.QueryField{
Name: "viewer",
Type: ast.NamedType("User", &ast.Position{}),
// this function must return the ID of the object that the field resolves to
Resolver: func(ctx context.Context, args map[string]interface{}) (string, error) {
// for now just return the value in context
return ctx.Value("user-id").(string), nil
},
{
viewer {
photoGallery {
url
}
}
}
{
node(id: "VXNlcjoy") {
... on User {
photoGallery {
url
}
}
}
}
User: {
...otherResolvers,
photoGallery: (user, _, { headers }) => {
// if the USER_ID header is not the same ID as the user
if (user.id !== headers.USER_ID) {
throw new Error("Sorry, you cannot view someone else's photo gallery.")
}
// the current user can see this user's photo gallery
return root.photoGallery.map(id => photos[id])
// create the gateway instance
gw, err := gateway.New(schemas, gateway.WithMiddlewares(forwardUserID))
var forwardUserID = gateway.RequestMiddleware(func(r *http.Request) error {
// the initial context of the request is set to match the one we modified earlier
// we are safe to extract the value we saved in context
if userID := r.Context().Value("user-id"); userID != nil {
// set the header with the value we pulled out of context
r.Header.Set("USER_ID", userID.(string))
}
// there was no error