graphql-rest
Because programming with REST APIs is so boringly slow, and because GraphQL APIs are so Great!
This module allows you to GraphQL-ify any (json) REST API by writing only GraphQL. This is possible thanks to GraphQL directives (aka. GraphQL annotations), and made easy to implement by the graphql-tools module from the Apollo GraphQL project.
-- How it works --
1. Add the library to your JS / TS project
With yarn:
yarn add graphql-rest fetch graphql
With npm:
npm install --save graphql-rest fetch graphql
You might want to use apollo-server and nodemon for a greater GraphQL development experience. Use one of:
yarn add --dev apollo-server nodemonnpm install --save-dev apollo-server nodemon
2. Instantiate GraphqlRest
A. Create mySchema.gql
type Query { hello: Int}
B. Create server.js
B1. Import the dependencies:
- commonjs style, if you use vanilla node:
- es6 style:
B2. Start the server:
server.listen.then
C. Run the Apollo Server with nodemon (replace yarn
by npm run
if you use npm):
yarn nodemon --ext .gql server.js
You will get an output like:
[nodemon] 1.19.1[nodemon] to restart at any time, enter `rs`[nodemon] watching: *.*[nodemon] starting `node server.js`Serving the GraphQL Playground on http://localhost:4000/playground
Open your browser to http://localhost:4000/playground, where the GraphQL playground runs.
Note: If you are going to be using GraphqlRest in a web browser, consider using node while developing the GraphQL schaema for the API.
3. Develop your annotated GraphQL Schema
mySchema.gql
# This header declares the `from` directive that GraphqlRest implementsdirective @from( "Config" configUrlBase: String configQueryStringAdditions: [String] "Rename a REST result property" prop: String "REST calls" get: String delete: String patch: String post: String put: String "Specify a path to the property in the JSON result to use as field value" root: String) on OBJECT | FIELD_DEFINITION# Passing { addHeader: true } allows to omit the header, but is not recommended# if you are going to use any GraphQL linting tool, as the GraphQL specification# requires declaring the directives you use # Using @from(get) allows you to specify the URL and REST method to use for the# resolver. Any word preceded by `:` will undergo substitution# A word is /[A-Za-z_]+/type Query @from(configUrlBase: "https://myApiUrlBase.org/v2/") { image(id: ID!): Image @from(get: "/:id.json") user(name: ID!): User @from(get: "/profiles/:name.json") search( query: String! sort: SortFieldInput = created_at order: SortOrderInput = desc page: Int = 1 perpage: Int = 15 ): SearchPage! @from( get: "/search.json?q=:query&sf=:sort&sd=:order&page=:page&perpage=:perpage" )} scalar CommaSpaceSeparatedStringscalar Datescalar Extensionscalar Mimescalar Sha512scalar Url enum SortFieldInput { created_at score random} # Here things get interesting, see the substitution is not only possible with# GraphQL arguments, but also with the values returned from the REST API call.# If you are familiar with GraphQL resolvers, here `:uploader_id` is found in# the `parent` (or `source` ) field of the resolver. This is what enables the# nesting power of GraphQLtype Image { representations: Representations score: Int! updated_at: Date! uploader_id: ID uploader_info: User @from(get: "/profiles/:uploader_id.json")} type SearchPage { search: [Image!]! total: Int!} type User { id: ID name: String!}
-- Development --
Done
- Ability to rename a REST property via annotation
- Document the other useful properties of GraphqlRest instances
- Document the lesser useful properties of GraphqlRest instances
- Document the lesser useful features of GraphqlRest schemas
Coming soon
- Mutation queries
- End to end (functional) tests
- Unit tests
- Documented way to use the library outside of development context
- Documented way to make a GraphQL use as a library
- Support for custom annotations with altered behaviour
- Support for GraphQL resolving list types from argument lists stacked type modifier, such as
[[ID]]
,[ID!]
,[ID]!
,[[[ID!]!]!]!
- Ability to specify a property to use in the JSON response rather the JSON root
- Ability to specify a JSON path to a
root
field in the JSON response - Ability to access JSON nested properties when renaming a property