node-graphql-server

A nearly zero-conf GraphQL layer builder. Automatically builds GQL layer from any number of REST APIs with OpenAPI spec.

Usage no npm install needed!

<script type="module">
  import nodeGraphqlServer from 'https://cdn.skypack.dev/node-graphql-server';
</script>

README

I-Cell GraphQL Server

A nearly zero conf GraphQL layer generator, GraphQL server and NodeJS REST API service in one. It has a dual purpose:

  • It can generate a fully functional GraphQL layer from any number of OpenAPI specs, providing a single endpoint for all your REST APIs.
  • It is also able to run as a standalone NodeJS service which can be used as a foundation for building secure REST APIs.

The goal of the project is to provide a minimalist, "out-of-the-box" solution for the above problems. This is a tool that requires very little config and builds zero coding GraphQL layers.

Features

General:

  • Protected against many security threats
  • Runs on HTTP or HTTPS
  • Can be configured via command line args or ENV vars, no config files needed
  • Requires very little effort to run in prod.

GraphQL server:

  • Can generate GQL layer from any OpenAPI Schema
  • Supports OpeanAPI v2 and v3
  • Can read OpeanAPI spec in YAML and JSON formats
  • Can read schemas from any number of URLs or files.
  • Supports combining multiple schemas
  • Automatically generates resolvers
  • Comes with built-in GraphQL dev tool (GraphiQL)

NodeJS service:

  • A Loopack 4 & Express server (both can be used)
  • Can use any Express middleware
  • Automatically generates OpenAPI v3 schema
  • Can provide REST enpoints
  • Has GraphQL endpoint
  • Comes with pre-configured Swagger UI

Coming soon

  • Containerization (Docker)
  • Better logging
  • Feature requests are welcome! :)

Prerequisites

This requires NodeJS 11+, but installing NodeJS LTS is recommended.

Install

Git clone this repo, then run:

git clone https://github.com/icellmobilsoft/graphqlserver.git /some/dir
cd /some/dir
npm install

Usage - General

The easiest way to run this is:

npm start --  --baseUrl http://127.0.0.1:3000/api

By default, the server will run on host 127.0.0.1 and port 3000. You may change this using the -host and --port flags, respectively. It's gonna run on HTTP unless you supply a valid certificate and a key file via the --cert and --key flags.

Once it's started, the following paths are available:

Once

URL Description
GET / Health check
/api The API root. All REST endoints live under this
GET /api/explorer Swagger UI for REST endpoints
GET, POST /graphql GraphQL query endpoint, GraphiQL UI (in dev mode)
GET /openapi OpenAPI 3.x spec (YAML)
GET /openapi.json OpenAPI 3.x spec (JSON)
GET /openapi.yaml OpenAPI 3.x spec (YAML)

Usage - as GraphQL layer

General info

In order to set up a GraphQL layer, simply execute the following command.

npm start -- --oas http://domain.com:10001/openapi.json  --baseUrl http://domain.com

This will fire up a GraphQL layer which is able to query the service running at port 10001 via GQL. However, you may supply multiple OAS arguments! fFr example, the following would generate a combined GQL layer for services running at port 10001 and 10002.

npm start -- --oas http://domain.com:10001/openapi.json --oas http://domain.com:10002/openapi.json  --baseUrl http://domain.com

Passing parameters at startup

You may pass one or more --header flags at startup time, as shown in the example below:

npm start -- --oas http://domain.com:10001/openapi.json   --baseUrl http://domain.com --header secretId:aba2332

Each flag represents a HTTP header which will be passed to each request GraphQL makes to your REST API(s). This is a great way of defining values that don't change after startup (like constants). A header should be formatted like this: name:value.

If you need to pass data as part of the query string instead, use the --queryStr flag. It works the same way as --header.

Passing parameters at runtime

Another flag you may find useful is --param. This allows you to define runtime parameters. Since this is stuff that may change after startup, it's up to the user to provide values of these parameters at runtime. The format is type:schema:name where type is one of "path, query, header, cookie", schema is the OpenAPI schema data type, such as "string" and name is the name of the parameter. For example, check this out:

npm start -- --oas http://domain.com:10001/openapi.json   --baseUrl http://domain.com --param header:string:login --param header:string:accessToken

This defines two runtime parameters, "login" and "accessToken". These will be available in all OAS operations (as OP params) and will be passed to the generated HTTP requests as headers (hence type=header), allowing you to write queries like this:

  customerResponse(login: "someUser", sessionToken: "someToken") {
    customer {
      email
    }
  }

To learn more about OpenAPI parameter objects, see this page.

Transforming OAS operations

When building the GraphQL layer, this tool will "convert" each OpenAPI operation to a GQL operation, either a mutation or a query. By default, only GET requests will be turned into queries. You may change this via the --query and --mutation flags. These will explicitly instruct the server to treat a certain OP as mutation or query, overriding the default behavior. The format is httpMethod:path. For instance:

npm start -- --oas http://domain.com:10001/openapi.json --oas http://domain.com:10002/openapi.jso --baseUrl http://domain.com --param header:string:login --param header:string:sessionToken --query post:/some/ep  --query post:/other/thing

This would convert the POST /some/ep and POST /other/thing to query ops. This does not mean that the requests will be called using GET, they gonna still use POST and whatever parameters they have defined in the OpenAPI schema. But now you can use these OPs in GraphQL queries.

Usage - as NodeJS server

In order to run this as a normal NodeJS service, just execute the command:

npm start -- --baseUrl http://127.0.0.1:3000/api

You may have to replace "127.0.0.1" with your host and "3000" with your port number.

This will fire up a Loopback 4 + Express server, a NodeJS service. Using the Loopback 4 framework, you can add as many endpoints as you need. You may also extend the server's functionality using any Express-compatible middleware.

The /graphql endpoint will be still available, but now it's gonna query the server's own endpoints.

Additional help

The GQL server has various other options. You might or might not need these, depending on how do you wish to use this product. For a list of all available options and their descriptions please run the following:

node . --help

Running in production

Good news! This does not require any special config. However, before you start the server, you should set the following environment variable:

export ICGQL_ENV=prod
npm start [options]

This will trigger "production mode", with the following effects:

  • /api/explorer will be disabled (no swagger UI)
  • /graphql will produce JSON responses only and GraphiQL will be unavailable.
  • /api/openapi endpoints can be disabled by setting the "ICGQL_NO_SCHEMA" env var.
  • The server won't respond to GraphQL introspection requests.
  • Opening any URL in a browser, it won't be possible to execute JS code, CSS, request any media file or any external resource.
  • All important security related headers will be injected into server responses, preventing a series of attacks.

Additionally, instead of starting the server using command line, you should define the required flags as environment variables with the "ICGQL" prefix. So for example, you should set base URL this way:

export ICGQL_BASE_URL=http://some.url

The server will parse all env vars and will transform the ones with the ICGQL prefix into config options, allowing you to pass config data in a secure way.