What is graphql-anywhere?
The graphql-anywhere package is a flexible utility for running GraphQL queries against any arbitrary data structure. It allows you to execute GraphQL queries on client-side data, making it useful for scenarios where you need to filter or transform data based on a GraphQL query.
What are graphql-anywhere's main functionalities?
Executing GraphQL queries on client-side data
This feature allows you to execute GraphQL queries on client-side data. The code sample demonstrates how to filter a data object based on a GraphQL query, returning only the fields specified in the query.
const { graphql } = require('graphql-anywhere');
const { filter } = require('graphql-anywhere/lib/async');
const query = `{
user {
name
age
}
}`;
const resolver = (fieldName, root, args, context, info) => {
return root[fieldName];
};
const data = {
user: {
name: 'John Doe',
age: 30,
email: 'john.doe@example.com'
}
};
filter(resolver, query, data).then(result => {
console.log(result);
// Output: { user: { name: 'John Doe', age: 30 } }
});
Custom resolvers for handling data
This feature allows you to define custom resolvers to handle data in a specific way. The code sample shows how to use a custom resolver to modify the 'age' field before returning the result.
const { graphql } = require('graphql-anywhere');
const { filter } = require('graphql-anywhere/lib/async');
const query = `{
user {
name
age
}
}`;
const customResolver = (fieldName, root, args, context, info) => {
if (fieldName === 'age') {
return root[fieldName] + 1; // Custom logic to modify the age
}
return root[fieldName];
};
const data = {
user: {
name: 'John Doe',
age: 30,
email: 'john.doe@example.com'
}
};
filter(customResolver, query, data).then(result => {
console.log(result);
// Output: { user: { name: 'John Doe', age: 31 } }
});
Other packages similar to graphql-anywhere
graphql-tools
The graphql-tools package provides a set of utilities to build and manipulate GraphQL schemas in JavaScript. It includes features for schema stitching, mocking, and more. While graphql-tools focuses on schema creation and manipulation, graphql-anywhere is more about executing queries on arbitrary data structures.
apollo-client
Apollo Client is a comprehensive state management library for JavaScript that enables you to manage both local and remote data with GraphQL. It includes features for caching, query batching, and more. While Apollo Client is a full-fledged GraphQL client, graphql-anywhere is a lightweight utility for executing queries on arbitrary data.
graphql-anywhere
Run a GraphQL query anywhere, without a GraphQL server or a schema. Just pass in one resolver. Use it together with graphql-tag.
npm install graphql-anywhere graphql-tag
This isn't necessarily meant to be a useful thing, but I think there are a lot of potentially exciting use cases for a completely standalone, schema-less, GraphQL execution engine. One of the best ones is if you're building a GraphQL client, and don't want to load graphql-js or a schema.
Let's come up with some more ideas - below are some use cases to get you started!
API
import graphql from 'graphql-anywhere'
graphql(resolver, document, rootValue?, context?, variables?)
resolver
: A single resolver, called for every field on the query. Signature is: (fieldName, rootValue, args, context) => any
document
: A GraphQL document, as generated by the template literal from graphql-tag
rootValue
: The root value passed to the resolver when executing the root fieldscontext
: A context object passed to the resolver for every fieldvariables
: A dictionary of variables for the query
Example: Filter a nested object
import gql from 'graphql-tag';
import graphql from 'graphql-anywhere';
const gitHubAPIResponse = {
"url": "https://api.github.com/repos/octocat/Hello-World/issues/1347",
"title": "Found a bug",
"body": "I'm having a problem with this.",
"user": {
"login": "octocat",
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"url": "https://api.github.com/users/octocat",
},
"labels": [
{
"url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
"name": "bug",
"color": "f29513"
}
],
};
const query = gql`
{
title
user {
login
}
labels {
name
}
}
`;
const resolver = (fieldName, root) => root[fieldName];
const result = graphql(
resolver,
query,
gitHubAPIResponse
);
assert.deepEqual(result, {
"title": "Found a bug",
"user": {
"login": "octocat",
},
"labels": [
{
"name": "bug",
}
],
});
Example: Generate mock data
const query = gql`
{
author {
name: string
age: int
address {
state: string
}
}
}
`;
const resolver = (fieldName) => ({
string: 'This is a string',
int: 5,
}[fieldName]);
const result = graphql(
resolver,
query
);
assert.deepEqual(result, {
author: {
name: 'This is a string',
age: 5,
address: {
state: 'This is a string',
},
},
});
What does this support?
Every GraphQL syntax feature I can think of is supported, as far as I know, including aliases, arguments, variables, inline fragments, named fragments, and skip
/include
directives.
Known limitations:
- The execution engine is synchronous, so you probably shouldn't use this to query your API. Please submit a PR to add promise functionality, and ideally batching support, like
graphql-js
has! Wouldn't it be cool if you could use this to dynamically query a REST API via GraphQL?