Gathering detailed insights and metrics for @brysgo/graphql-anywhere
Gathering detailed insights and metrics for @brysgo/graphql-anywhere
Gathering detailed insights and metrics for @brysgo/graphql-anywhere
Gathering detailed insights and metrics for @brysgo/graphql-anywhere
🍦 Run a GraphQL query anywhere, against any data, with no schema.
npm install @brysgo/graphql-anywhere
Typescript
Module System
75.2
Supply Chain
99
Quality
74.9
Maintenance
100
Vulnerability
100
License
TypeScript (99.12%)
JavaScript (0.88%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
2 Stars
192 Commits
2 Forks
1 Watchers
6 Branches
1 Contributors
Updated on Aug 07, 2024
Minified
Minified + Gzipped
Latest Version
3.1.0
Package Id
@brysgo/graphql-anywhere@3.1.0
Unpacked Size
143.04 kB
Size
39.28 kB
File Count
38
Cumulative downloads
Total Downloads
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
I think there are a lot of potentially exciting use cases for a completely standalone and schema-less GraphQL execution engine. We use it in Apollo Client to read data from a Redux store with GraphQL.
Let's come up with some more ideas - below are some use cases to get you started!
1import graphql from 'graphql-anywhere' 2 3graphql(resolver, document, rootValue?, context?, variables?, options?)
resolver
: A single resolver, called for every field on the query.
(fieldName, rootValue, args, context, info) => 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 queryoptions
: Options for executionThe last argument to the graphql
function is a set of graphql-anywhere
-specific options.
resultMapper
: Transform field results after execution.
(resultFields, resultRoot) => any
fragmentMatcher
: Decide whether to execute a fragment. Default is to always execute all fragments.
(rootValue, typeCondition, context) => boolean
info
, the 5th argument to the resolver, is an object with supplementary information about execution. Send a PR or open an issue if you need additional information here.
isLeaf
: A boolean that is true
if this resolver is for a leaf field of the query, i.e. one that doesn't have a sub-selection.resultKey
: The key the result of this field will be put under. It's either the field name from the query, or the field alias.directives
: An object with information about all directives on this field. It's an object of the format { [directiveName]: { [argumentName]: value }}
. So for example a field with @myDirective(hello: "world")
will be passed as { myDirective: { hello: 'world' }}
. Note that fields can't have multiple directives with the same name, as written in the GraphQL spec.See http://dev.apollodata.com/react/fragments.html for examples of how you might use these.
1import { filter } from 'graphql-anywhere' 2 3filter(doc, data);
doc
: a GraphQL document, as generated by the template literal from graphql-tag
, typically either a query or a fragment.data
: an object of data to be filtered by the doc
Filter data
according to doc
.
1import { check } from 'graphql-anywhere' 2 3check(doc, data);
doc
: a GraphQL document, as generated by the template literal from graphql-tag
, typically either a query or a fragment.data
: an object of data, as may have been filtered by doc
.Check that data
is of the form defined by the query or fragment. Throw an exception if not.
1import { propType } from 'graphql-anywhere'
2
3X.propTypes = {
4 foo: propType(doc),
5 bar: propType(doc).isRequired,
6}
7
doc
: a GraphQL document, as generated by the template literal from graphql-tag
, typically either a query or a fragment.Generate a React propType
checking function to ensure that the passed prop is in the right form.
Why do you even need a library for this? Well, running a GraphQL query isn't as simple as just traversing the AST, since there are some pretty neat features that make the language a bit more complex to execute.
@skip
and @include
directivesIf you come across a GraphQL feature not supported here, please file an issue.
1import gql from 'graphql-tag'; 2import graphql from 'graphql-anywhere'; 3 4// I don't need all this stuff! 5const gitHubAPIResponse = { 6 "url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", 7 "title": "Found a bug", 8 "body": "I'm having a problem with this.", 9 "user": { 10 "login": "octocat", 11 "avatar_url": "https://github.com/images/error/octocat_happy.gif", 12 "url": "https://api.github.com/users/octocat", 13 }, 14 "labels": [ 15 { 16 "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug", 17 "name": "bug", 18 "color": "f29513" 19 } 20 ], 21}; 22 23// Write a query that gets just the fields we want 24const query = gql` 25 { 26 title 27 user { 28 login 29 } 30 labels { 31 name 32 } 33 } 34`; 35 36// Define a resolver that just returns a property 37const resolver = (fieldName, root) => root[fieldName]; 38 39// Filter the data! 40const result = graphql( 41 resolver, 42 query, 43 gitHubAPIResponse 44); 45 46assert.deepEqual(result, { 47 "title": "Found a bug", 48 "user": { 49 "login": "octocat", 50 }, 51 "labels": [ 52 { 53 "name": "bug", 54 } 55 ], 56});
1// Write a query where the fields are types, but we alias them
2const query = gql`
3 {
4 author {
5 name: string
6 age: int
7 address {
8 state: string
9 }
10 }
11 }
12`;
13
14// Define a resolver that uses the field name to determine the type
15// Note that we get the actual name, not the alias, but the alias
16// is used to determine the location in the response
17const resolver = (fieldName) => ({
18 string: 'This is a string',
19 int: 5,
20}[fieldName] || 'continue');
21
22// Generate the object!
23const result = graphql(
24 resolver,
25 query
26);
27
28assert.deepEqual(result, {
29 author: {
30 name: 'This is a string',
31 age: 5,
32 address: {
33 state: 'This is a string',
34 },
35 },
36});
1const data = { 2 result: [1, 2], 3 entities: { 4 articles: { 5 1: { id: 1, title: 'Some Article', author: 1 }, 6 2: { id: 2, title: 'Other Article', author: 1 }, 7 }, 8 users: { 9 1: { id: 1, name: 'Dan' }, 10 }, 11 }, 12}; 13 14const query = gql` 15 { 16 result { 17 title 18 author { 19 name 20 } 21 } 22 } 23`; 24 25const schema = { 26 articles: { 27 author: 'users', 28 }, 29}; 30 31// This resolver is a bit more complex than others, since it has to 32// correctly handle the root object, values by ID, and scalar leafs. 33const resolver = (fieldName, rootValue, args, context): any => { 34 if (!rootValue) { 35 return context.result.map((id) => assign({}, context.entities.articles[id], { 36 __typename: 'articles', 37 })); 38 } 39 40 const typename = rootValue.__typename; 41 // If this field is a reference according to the schema 42 if (typename && schema[typename] && schema[typename][fieldName]) { 43 // Get the target type, and get it from entities by ID 44 const targetType: string = schema[typename][fieldName]; 45 return assign({}, context.entities[targetType][rootValue[fieldName]], { 46 __typename: targetType, 47 }); 48 } 49 50 // This field is just a scalar 51 return rootValue[fieldName]; 52}; 53 54const result = graphql( 55 resolver, 56 query, 57 null, 58 data // pass data as context since we have to access it all the time 59); 60 61// This is the non-normalized data, with only the fields we asked for in our query! 62assert.deepEqual(result, { 63 result: [ 64 { 65 title: 'Some Article', 66 author: { 67 name: 'Dan', 68 }, 69 }, 70 { 71 title: 'Other Article', 72 author: { 73 name: 'Dan', 74 }, 75 }, 76 ], 77});
You can use the resultMapper
option to convert your results into anything you like. In this case, we convert the result fields into children for a React component:
1const resolver = (fieldName, root, args) => { 2 if (fieldName === 'text') { 3 return args.value; 4 } 5 6 return createElement(fieldName, args); 7}; 8 9const reactMapper = (childObj, root) => { 10 const reactChildren = Object.keys(childObj).map(key => childObj[key]); 11 12 if (root) { 13 return cloneElement(root, root.props, ...reactChildren); 14 } 15 16 return reactChildren[0]; 17}; 18 19function gqlToReact(query): any { 20 return graphql( 21 resolver, 22 query, 23 '', 24 null, 25 null, 26 { resultMapper: reactMapper }, 27 ); 28} 29 30const query = gql` 31 { 32 div { 33 s1: span(id: "my-id") { 34 text(value: "This is text") 35 } 36 s2: span 37 } 38 } 39`; 40 41assert.equal( 42 renderToStaticMarkup(gqlToReact(query)), 43 '<div><span id="my-id">This is text</span><span></span></div>' 44);
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
Reason
Found 1/15 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-06-23
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreLast Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year