README
@inc/gotql
Write GraphQL queries as objects instead of strings
Forked from khaosdoctor/gotql because I did not feel like waiting nearly four months for my PR to be accepted and I had things to do.
This is a better implementation of the GraphQL query API via NodeJS, created as a wrapper of Got. It works like a transpiler, with a built in HTTPRequest Client (Got), allowing you to write your GraphQL queries as Javascript Objects instead of strings.
Built because manipulating strings is a real pain.
Table of Contents
Install
$ npm i @inc/gotql
Basic Usage
import gotQL from "gotql";
const query = {
operation: {
name: "users",
fields: [
"age",
"id",
"name"
]
}
};
const options = {
debug: false,
headers: {
"Authorization": "Bearer <token>"
}
};
gotQL.query("mygraphqlendpoint.com.br/api", query, options)
.then(response => console.log(response.data))
.catch(error => console.error(error));
What is it?
GotQL is a better interface for GraphQL queries. It provides a way for developers to run queries using JSON instead of strings. Which is a way more usable data format than the string itself.
Motivation
Manipulating strings is very smelly, even on dynamically typed languages. So, in order to avoid things such as this:
Which can be translated to something more readable in a JSON format like this:
const mutation = {
operation: {
name: "addLog",
args: {
fromState: variables.fromState,
idCampaign: variables.idCampaign,
idUser: variables.idUser,
logType: {
escape: false,
value: "status_change"
}, // Enum Value
owner: {
id: variables.id,
name: variables.name,
ownerType: variables.ownerType,
picture: variables.picture,
username: variables.username
},
toState: variables.toState
},
fields: [
"uuid"
]
}
};
This is why GotQL was created.
API
gotQL.query(graphQLEndpoint, query, [options]);
- Description: Performs a graphQL query
GraphQLEndpoint
- Type:
string
- Description: The GraphQL endpoint to query on
query
- Type:
object
- Description: The JSON-typed query following the json-query format
options
- Type:
object
- Description: The option object with the following properties.
- debug: Activates debug logging
- Type:
boolean
- Type:
- errorStatusCode: Default HTTP status code to be returned on error
- Type:
number
- Type:
- headers: Additional headers to be sent
- Type:
object
, in the form of[headerName: string]: headerValue: string
- Type:
- debug: Activates debug logging
gotQL.mutation(graphQLEndpoint, query, [options]);
- Description: Performs a graphQL mutation
GraphQLEndpoint
- Type:
string
- Description: The GraphQL endpoint to query on
query
- Type:
object
- Description: The JSON-typed query following the json-query format
options
- Type:
object
- Description: The option object with the following properties.
- debug: Activates debug logging
- Type:
boolean
- Type:
- errorStatusCode: Default HTTP status code to be returned on error
- Type:
number
- Type:
- headers: Additional headers to be sent
- Type:
object
, in the form of[headerName: string]: headerValue: string
- Type:
- debug: Activates debug logging
gotQL.parser(query, type);
- Description: Parses a JSON-Like query and returns the query"s string
query
- Type:
object
- Description: The JSON-typed query following the json-query format
type
- Type:
string
- Description: Must be either
"query"
or"mutation"
Returns
All methods return a string
like this:
const response = "query { test { name args } }";
The JSON query format
The JSON format gotQL uses is a simple and intuitive description based on the anatomy of a GraphQL query blog post.
This is a generic model of a JSONLike query:
const query = {
name?: string;
operation: {
name: string;
alias?: string;
args?: {
[argName: string]: any;
} | {
[argName: string]: {
escape: boolean;
value: string;
};
};
fields: (string | {
[fieldName: string]: [{
fields?: (string | {
[fieldName: string]: [any];
})[];
}];
})[];
};
variables?: {
[varName: string]: {
type: string;
value: string;
};
};
};
Description
- Query:
- Type:
object
- Description: The full query object
- Properties:
- name: [optional]: Query name
- Type:
string
- Type:
- variables: [optional] Query variable declaration
- Type:
object
with signature like[varName: string]: { type: string, value: string }
- Properties:
- varName: Variable name
- Type:
string
- Type:
- type: Variable type. Can be a GraphQL definition of type (i.e:
string!
)- Type:
string
- Type:
- value: Variable value
- Type:
any
- Type:
- varName: Variable name
- Type:
- operation: The query operation (action that will be executed)
- Type:
object
- Properties:
- name: The operation name
- Type:
string
- Type:
- alias: [optional] An alias to give the operation
- Type:
string
- Type:
- args: [optional] The operation args
- Type:
[argName: string]: any
or a detailed arg object- Simple args: An
object
where the key is the argument name and its value. Accepts variables in the format ofargName: "$value"
- Example:
args { name: "myName" }
- Example:
- Detailed args: An object with two properties. This will give more control over escaping (mostly to use enums). Argument name should be the key
- Type:
object
- Properties:
- value: The argument value
- Type:
any
- Type:
- escape: Whether the argument should be escaped or not (escaped means surrounded with double quotes
"argValue"
)- Type:
boolean
- Type:
- value: The argument value
- Examples:
args: { status: { value: "an_enum", escape: false } }
should outputoperation (status: an_enum)...
- Type:
- Simple args: An
- Type:
- fields: The field list to get back from the operation
- Type: An
array
ofobject
(to use nested fields) orstring
, or both. - Properties (for nested fields):
- Type:
object
where the field name is the key - fields: Recursive definition, accepts another array just like the fields above.
- Type:
- Type: An
- name: The operation name
- Type:
- name: [optional]: Query name
- Type:
Examples
Simple query
const query = {
operation: {
name: "users",
fields: [
"age",
"name"
]
}
};
Outputs:
query { users { name age }}
Named query
const query = {
name: "myQuery",
operation: {
name: "users",
fields: [
"age",
"name"
]
}
};
Outputs:
query myQuery { users { name age }}
Query with simple args
const query = {
operation: {
name: "user",
args: {
name: "T'Challa"
},
fields: [
"age",
"name"
]
}
};
Outputs:
query { user(name: "T'Challa") { name age }}
Query with variables
const query = {
operation: {
name: "user",
args: {
name: "$name"
},
fields: [
"age",
"name"
]
},
variables: {
name: {
type: "string!",
value: "T'Challa"
}
}
};
Outputs:
query ($name: string!) { users(name: $name) { name age }}
Variables are sent on a separate object to graphQL.
{
"variables": {
"name": "T'Challa"
}
}
Nested fields
const query = {
operation: {
name: "users",
fields: [
"age",
"name",
{
friends: {
fields: [
"age",
"name"
]
}
}
]
}
};
Outputs:
query { users { name age friends { name age }}}
Recursive fields can go forever.
Enum args
const query = {
operation: {
name: "user",
args: {
type: {
escape: false,
value: "internal"
}
},
fields: [
"age",
"name"
]
}
};
Outputs:
query { users(type: internal) { name age }}
If escape
is set to true
, the output would be:
query { users(type: "internal") { name age }}
Note: Variables such as described here will not be recognized. If the arg object is not an
[argName]: value
, variables will not pass through the definition check (GotQL warns if a variable is not declared but used on operation).