SkillAgentSearch skills...

Graphql2rest

GraphQL to REST converter: automatically generate a RESTful API from your existing GraphQL API

Install / Use

/learn @sisense/Graphql2rest

README

GraphQL2REST

Automatically generate a RESTful API from your existing GraphQL API

Sisense-open-source License: MIT ![npm-image] Tweet

GraphQL2REST is a Node.js library that reads your GraphQL schema and a user-provided manifest file and automatically generates an Express router with fully RESTful HTTP routes — a full-fledged REST API.

Author: Roy Mor

Why?

  • You have an existing GraphQL API, but need to expose it as REST because that's what your API users want

  • You want to develop a new GraphQL API and get REST on top of it, for free

  • You want to benefit from GraphQL internally while exposing REST externally as a public API

GraphQL2REST allows you to fully configure and customize your REST API, which may sit on top of a very different GraphQL layer (see features).

<br>

Table of Contents

Installation

npm:

npm i graphql2rest

yarn:

yarn add graphql2rest

Usage

Basic example:

Given a simple GraphQL schema:

type Query {
	getUser(userId: UUID!): User
}

type Mutation {
	createUser(name: String!, userData: UserDataInput): User
	removeUser(userId: UUID!): Boolean
}

Add REST endpoints to the manifest.json file:

{
	"endpoints": {
		"/users/:userId": {
			"get": {
				"operation": "getUser"
			},
			"delete": {
				"operation": "removeUser",
				"successStatusCode": 202
			}
		},
		"/users": {
			"post": {
				"operation": "createUser",
				"successStatusCode": 201
			}
		}
	}
}

In your code:

import GraphQL2REST from 'graphql2rest';
import { execute } from 'graphql'; // or any GraphQL execute function (assumes apollo-link by default)
import { schema } from './myGraphQLSchema.js'; 

const gqlGeneratorOutputFolder = path.resolve(__dirname, './gqlFilesFolder'); 
const manifestFile = path.resolve(__dirname, './manifest.json');

GraphQL2REST.generateGqlQueryFiles(schema, gqlGeneratorOutputFolder); // a one time pre-processing step

const restRouter = GraphQL2REST.init(schema, execute, { gqlGeneratorOutputFolder, manifestFile });

// restRouter now has our REST API attached
const app = express();
app.use('/api', restRouter);

(Actual route prefix, file paths etc should be set first via options object or in config/defaults.json)

Resulting API:

POST /api/users              --> 201 CREATED
GET /api/users/{userId}      --> 200 OK
DELETE /api/users/{userId}   --> 202 ACCEPTED

// Example:

GET /api/users/1234?fields=name,role

Will invoke getUser query and return only 'name' and 'role' fields in the REST response.
The name of the filter query param ("fields" here) can be changed via configuration. 

For more examples and usage, please refer to the Tutorial.

<hr>

Features

  • Use any type of GraphQL server - you provide the execute() function
  • Default "RESTful" logic for error identification, determining status codes and response formatting
  • Customize response format (and error responses format too, separately)
  • Custom parameter mapping (REST params can be different than GraphQL parameter names)
  • Customize success status codes for each REST endpoint
  • Map custom GraphQL error codes to HTTP response status codes
  • Map a single REST endpoint to multiple GraphQL operations, with conditional logic to determine mapping
  • Hide specific fields from responses
  • Run custom middleware function on incoming requests before they are sent to GraphQL
  • Client can filter on all fields of a response, in all REST endpoints, using built-in filter
  • Built-in JMESPath support (JSON query language) for client filter queries
  • GraphQL server can be local or remote (supports apollo-link and fetch to forward request to a remote server)
  • Embed your own winston-based logger

How GraphQL2REST works

GraphQL2REST exposes two public functions:

  • generateGqlQueryFiles() - GraphQL schema pre-processing
  • init() - generate Express router at runtime

First, GraphQL2REST needs to do some one-time preprocessing. It reads your GraphQL schema and generates .gql files containing all client operations (queries and mutations). These are "fully-exploded" GraphQL client queries which expand all fields in all nesting levels and all possible variables, per each Query or Mutation type.

This is achieved by running the generateGqlQueryFiles() function:

GraphQL2REST.generateGqlQueryFiles(schema, '/gqlFilesFolder');

Now the /gqlFilesFolder contains an index.js file and subfolders for queries and mutations, containing .gql files corresponding to GraphQL operations. Use path.resolve(__dirname, <PATH>) for relative paths.

generateGqlQueryFiles() has to be executed just once, or when the GraphQL schema changes (it can be executed offline by a separate script or at "build time").


After generateGqlQueryFiles() has been executed once, GraphQL2REST init() can be invoked to create REST endpoints dynamically at runtime.

init() loads all .gql files into memory, reads the manifest.json file and uses Express router to generate REST endpoint routes associated with the GraphQL operations and rules defines in the manifest. init() returns an Express router mounted with all REST API endpoints.


The init() function

GraphQL2REST.init() is the entry point that creates REST routes at runtime.

It only takes two mandatory parameters: your GraphQL schema and the GraphQL server execute function (whatever your specific GraphQL server implementation provides, or an Apollo Link function).

GraphQL2REST.init(
	schema: GraphQLSchema,
	executeFn: Function,

	options?: Object,
	formatErrorFn?: Function,
	formatDataFn?: Function,
	expressRouter?: Function)
<br>

GraphQL arguments are passed to executeFn() in Apollo Link/fetch style, meaning one object as argument: { query, variables, context, operationName }.

options defines various settings (see below). If undefined, default values will be used.

formatErrorFn is an optional function to custom format GraphQL error responses.

formatDataFn is an optional function to custom format non-error GraphQL responses (data). If not provided, default behavior is to strip the encapsulating 'data:' property and the name of the GraphQL operation, and omit the 'errors' array from successful responses.

expressRouter is an express.Router() instance to attach new routes on. If not provided, a new Express instance will be returned.

The Manifest File

REST API endpoints and their behavior are defined in the manifest file (normally manifest.json ). It is used to map HTTP REST routes to GraphQL operations and define error code mappings. See a full example here.

The endpoints section

The endpoints object lists the REST endpoints to generate:

"endpoints": {
	"/tweets/:id": {  // <--- HTTP route path; path parameters in Express notation
		"get": {      // <--- HTTP method (get, post, patch, put, delete)
			"operation": "getTweetById", // <--- name of GraphQL query or mutation
		}
	}
}

Route path, HTTP method and operation name are mandatory.

GraphQL2REST lets you map a single REST endpoint to multiple GraphQL operations by using an array of operations (operations[] array instead of the operation field).

Additional optional fields:

  • "params": Used to map parameters in the REST request to GraphQL arguments in the corresponding query or mutation. Lets you rename parameters so the REST API can use different naming than the underlying GraphQL layer. If omitted, parameters will be passed as is by default. [Learn more]

  • "successStatusCode": Success status code. If omitted, success status code is 200 OK by default. [Learn more]

  • "condition": Conditions on the request parameters. GraphQL operation will be invoked only if the condition is satisfied. Condition is expressed using MongoDB query language query operators. [Learn more]

  • "hide": Array of fields in response to hide. These fields in the GraphQL response will always be filtered out in the REST response. [Learn more]

  • "wrapRequestBodyWith": Wrap the request body with this property (or multiple nested objects expressed in dot notation) before passing the REST request to GraphQL. Lets you map the entire HTTP body to a specific GraphQL Input argument. Helpful when we want the REST body to be flat, but the GraphQL operation expects the input to be wrapped within an object. [Learn more]

  • "`requestM

View on GitHub
GitHub Stars333
CategoryDevelopment
Updated1mo ago
Forks35

Languages

JavaScript

Security Score

100/100

Audited on Feb 16, 2026

No findings