add hello-world remote-schema boilerplates for major serverless providers (#1694)

A hello world schema is provided with local dev and deployment instructions for AWS Lambda, Google Cloud Functions and Azure Functions.

Older boilerplates are cleaned up.
This commit is contained in:
Tirumarai Selvan 2019-03-05 21:45:39 +05:30 committed by Shahidh K Muhammed
parent 98405fdc0c
commit d6a3cf337f
45 changed files with 506 additions and 1970 deletions

View File

@ -1 +0,0 @@
Moved to [zeit-now](../zeit-now)

View File

@ -1,3 +1,3 @@
# (MOVED) GraphQL server using NodeJS and Apollo # (MOVED) GraphQL server using NodeJS and Apollo
**This folder has been moved to [remote-schemas/zeit-now/nodejs/apollo-sequelize](../../remote-schemas/zeit-now/nodejs/apollo-sequelize)** **This folder has been moved to [remote-schemas/aws-lambda/nodejs](../../remote-schemas/aws-lambda/nodejs)**

View File

@ -1,3 +1,3 @@
# (MOVED) GraphQL server using NodeJS-Express # (MOVED) GraphQL server using NodeJS-Express
**This folder has been moved to [remote-schemas/zeit-now/nodejs/express-graphqljs-sequelize](../../remote-schemas/zeit-now/nodejs/express-graphqljs-sequelize)** **This folder has been moved to [remote-schemas/aws-lambda/nodejs](../../remote-schemas/aws-lambda/nodejs)**

View File

@ -0,0 +1,3 @@
node_modules/
*.zip
package-lock.json

View File

@ -0,0 +1,76 @@
# AWS Lambda + NodeJS + Apollo
This is a GraphQL backend boilerplate in nodejs that can be deployed on AWS Lambda.
## Stack
node 8.10
AWS Lambda
#### Frameworks/Libraries
Apollo Server (GraphQL framework)
## Schema
```
type Query {
hello: String
}
```
## Local Development
The sample source code is present in `index.js`.
```bash
$ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/aws-lambda/nodejs
```
Start a local development server (you may need to install dependencies from npm):
```bash
$ npm i --no-save apollo-server express
$ node localDev.js
Output:
Server ready at http://localhost:4000/
```
This will start a local server on `localhost:4000`. You can hit the graphql service at `localhost:4000`. This opens a graphql playground where you can query your schema.
## Deployment
Now that you have run the graphql service locally and made any required changes, it's time to deploy your service to AWS Lambda and get an endpoint. The easiest way to do this is through the AWS console.
1) Create a Lambda function by clicking on Create Function on your Lambda console. Choose the `NodeJS 8.10` runtime and `lambda_basic_execution` role.
![create-lambda](../../_assets/create-lambda.png)
2) In the next page (or Lambda instance page), select API Gateway as the trigger.
![create-api-gateway](../../_assets/create-api-gateway.png)
3) Configure the API Gateway as you wish. The simplest configuration is shown below.
![configure-api-gateway](../../_assets/configure-api-gateway.png)
Save your changes. You will receive a HTTPS endpoint for your lambda.
![output-api-gateway](../../_assets/output-api-gateway.png)
If you go to the endpoint, you will receive a "Hello from Lambda!" message. This is because we haven't uploaded any code yet!
4) Zip and upload code. Make sure the handler is set as `lambdaCtx.handler`:
```bash
$ zip -r graphql.zip *
```
And that's it. Hit save and visit the endpoint again. You will see the graphql playground again.
**IMPORTANT NOTE:** You may have to edit the GraphQL URL in the Playground to reflect the right endpoint ( same as the URL created by the API Gateway ).

View File

@ -1,3 +0,0 @@
node_modules
build
*.zip

View File

@ -1,104 +0,0 @@
# AWS Lambda + NodeJS + Apollo + Sequelize
This is a GraphQL backend boilerplate in nodejs that can be deployed on AWS Lambda.
## Stack
node 8.10
Postgres
AWS Lambda
#### Frameworks/Libraries
Apollo Server (GraphQL framework)
Sequelize (Postgres ORM)
## Schema
We consider a user schema where a user can be added only if a custom validation passes. The custom validation involves fetching a min amount from a table and checking if the user balance is greater than the min amount. This will be done in a transaction.
```
type Query {
hello: String
}
type Mutation {
validateAndAddUser(name: String, balance: Int): User
}
type User {
id: Int
name: String
balance: Int
}
```
## Local Development
The sample source code is present in `index.js`. Clone the repo and go to `community/boilerplates/remote-schemas/aws-lambda/nodejs/apollo-sequelize` folder:
```bash
$ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/aws-lambda/nodejs/apollo-sequelize
```
1) First, let's set the environment variable for connecting to the postgres instance. This can be a local postgres instance or some managed postgres instance like AWS RDS.
```bash
$ export POSTGRES_CONNECTION_STRING='postgres://username:password@rds-database-endpoint.us-east-1.rds.amazonaws.com:5432/mydb'
```
2) Next, lets create the tables required for our schema.
```bash
psql $POSTGRES_CONNECTION_STRING -c "create table users(id serial primary key, name text, balance integer); create table min_amount(amount integer); insert into min_amount values (100)"
```
3) Now, you can start a development environment by setting an environment variable and running the server:
```bash
$ LAMBDA_LOCAL_DEVELOPMENT=1 node index.js
Output:
Server ready at http://localhost:4000/
```
This will start a local server on `localhost:4000`. You can hit the graphql service at `localhost:4000`. This opens a graphql playground where you can query your schema.
Now, you can play with the schema and make any changes in the source code for additional functionalities as you desire.
## Deployment
Now that you have run the graphql service locally and made any required changes, it's time to deploy your service to AWS Lambda and get an endpoint. The easiest way to do this is through the AWS console.
1) Create a Lambda function by clicking on Create Function on your Lambda console. Choose the `NodeJS 8.10` runtime and `lambda_basic_execution` role.
![create-lambda](../../../_assets/create-lambda.png)
2) In the next page (or Lambda instance page), select API Gateway as the trigger.
![create-api-gateway](../../../_assets/create-api-gateway.png)
3) Configure the API Gateway as you wish. The simplest configuration is shown below.
![configure-api-gateway](../../../_assets/configure-api-gateway.png)
Save your changes. You will receive a HTTPS endpoint for your lambda.
![output-api-gateway](../../../_assets/output-api-gateway.png)
If you go to the endpoint, you will receive a "Hello from Lambda!" message. This is because we haven't uploaded any code yet!
4) Zip and upload code. Make sure to set the handler as `index.handler` and add the `POSTGRES_CONNECTION_STRING` environment variable:
```bash
$ zip -r graphql.zip *
```
And that's it. Hit save and visit the endpoint again. You will see the graphql playground again.
**IMPORTANT NOTE:** You may have to edit the GraphQL URL in the Playground to reflect the right endpoint ( same as the URL created by the API Gateway ).

View File

@ -1,85 +0,0 @@
const { ApolloServer, gql } = require('apollo-server');
const ApolloServerLambda = require('apollo-server-lambda').ApolloServer;
const Sequelize = require("sequelize");
const {User, MinAmount, sequelize} = require('./models.js');
const typeDefs = gql`
type Query {
hello: String
}
type Mutation {
validateAndAddUser(name: String, balance: Int): User
}
type User {
id: Int
name: String
balance: Int
}
`;
// We consider a user schema where a user can be added only if a custom validation passes.
// The custom validation involves fetching a min amount from a table
// and checking if the user balance is greater than the min amount.
// This will be done in a transaction.
const resolvers = {
Query: {
hello: () => "world",
},
Mutation: {
validateAndAddUser: async (_, { name, balance }) => {
//begin transaction
return await sequelize.transaction(async (t) => {
try {
//fetch min amount
const minAmount = await MinAmount.findOne({}, {transaction: t});
//check balance
if (balance >= minAmount.amount) {
//create user if balance is greater
const user = await User.create({
name: name,
balance: balance
});
return user;
} else {
throw new Error("balance too low, required atleast " + minAmount.amount);
}
} catch (e) {
console.log(e);
throw new Error(e);
}
});
}
}
};
const server = new ApolloServerLambda({
typeDefs,
resolvers,
context: ({ event, context }) => ({
headers: event.headers,
functionName: context.functionName,
event,
context,
}),
});
exports.handler = server.createHandler({
cors: {
origin: '*',
credentials: true,
allowedHeaders: 'Content-Type, Authorization'
},
});
// For local development
if( process.env.LAMBDA_LOCAL_DEVELOPMENT == "1") {
const serverLocal = new ApolloServer({ typeDefs, resolvers });
serverLocal.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
}

View File

@ -1,37 +0,0 @@
const Sequelize = require("sequelize");
const POSTGRES_CONNECTION_STRING = process.env.POSTGRES_CONNECTION_STRING || "postgres://postgres:password@localhost:6432/postgres";
const sequelize = new Sequelize(
POSTGRES_CONNECTION_STRING, {}
);
const User = sequelize.define(
'user',
{
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
name: Sequelize.TEXT,
balance: Sequelize.INTEGER
},
{
timestamps: false
}
);
const MinAmount = sequelize.define(
'min_amount',
{
amount: Sequelize.INTEGER
},
{
freezeTableName: true,
timestamps: false
}
);
MinAmount.removeAttribute('id');
exports.sequelize = sequelize;
exports.User = User;
exports.MinAmount = MinAmount;

View File

@ -0,0 +1,16 @@
const gql = require('graphql-tag');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world",
},
};
exports.typeDefs = typeDefs;
exports.resolvers = resolvers;

View File

@ -0,0 +1,22 @@
const ApolloServerLambda = require('apollo-server-lambda').ApolloServer;
const { typeDefs, resolvers } = require('./index');
const server = new ApolloServerLambda({
typeDefs,
resolvers,
context: ({ event, context }) => ({
headers: event.headers,
functionName: context.functionName,
event,
context,
}),
});
exports.handler = server.createHandler({
cors: {
origin: '*',
credentials: true,
allowedHeaders: 'Content-Type, Authorization'
},
});

View File

@ -0,0 +1,11 @@
const { ApolloServer } = require('apollo-server');
const express = require('express');
const app = express();
const { typeDefs, resolvers } = require('./index');
const helloSchema = new ApolloServer({ typeDefs, resolvers });
helloSchema.listen().then(({ url }) => {
console.log(`schema ready at ${url}`);
});

View File

@ -2,7 +2,7 @@
"name": "aws-lambda-nodejs", "name": "aws-lambda-nodejs",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "graphql.js", "main": "lambdaCtx.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
@ -10,11 +10,8 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"apollo-server": "^2.2.2",
"apollo-server-lambda": "^2.1.0", "apollo-server-lambda": "^2.1.0",
"graphql": "^0.13.1", "graphql": "^0.13.1",
"pg": "^7.6.0", "graphql-tag": "^2.10.1"
"pg-hstore": "^2.3.2",
"sequelize": "^4.41.0"
} }
} }

View File

@ -0,0 +1,3 @@
node_modules/
*.zip
package-lock.json

View File

@ -0,0 +1,83 @@
# Azure Functions + NodeJS + Apollo
This is a GraphQL backend boilerplate in nodejs that can be deployed on Azure Functions.
## Stack
node 8.10
Azure Functions
#### Frameworks/Libraries
Apollo Server (GraphQL framework)
## Schema
```
type Query {
hello: String
}
```
## Local Development
The sample source code is present in `graphql` folder.
```bash
$ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/azure-functions/nodejs
```
Start a local development server (you may need to install dependencies from npm):
```bash
$ cd graphql
$ npm i --no-save apollo-server express
$ node localDev.js
Output:
Server ready at http://localhost:4000/
```
This will start a local server on `localhost:4000`. You can hit the graphql service at `localhost:4000`. This opens a graphql playground where you can query your schema.
## Deployment
1. Install `az` cli.
2. Create a zip of all resources (from the current directory):
```bash
$ zip -r graphql.zip *
```
2. Run the following commands to deploy:
```bash
$ az group create --name 'my-functions-group' --location southindia
$ az storage account create --name 'myfunctionsstorage' --location southindia --resource-group 'my-functions-group' --sku Standard_LRS
$ az functionapp create --name 'hello-graphql' --storage-account 'myfunctionsstorage' --resource-group 'my-functions-group' --consumption-plan-location southindia
$ az functionapp deployment source config-zip -g "my-functions-group" -n "hello-graphql" --src graphql.zip
```
4. Get the HTTP Url:
```bash
$ az functionapp show -g "my-functions-group" -n "hello-graphql"
```
Output:
```json
"hostNames": [
"hello-graphql.azurewebsites.net"
],
```
The url of the function is \<hostname\>/\<function\> e.g. in our case: `https://hello-graphql.azurewebsites.net/graphql`

View File

@ -0,0 +1,3 @@
node_modules/
*.zip
package-lock.json

View File

@ -0,0 +1,20 @@
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}

View File

@ -0,0 +1,11 @@
const { ApolloServer } = require('apollo-server');
const express = require('express');
const app = express();
const { typeDefs, resolvers } = require('./server');
const helloSchema = new ApolloServer({ typeDefs, resolvers });
helloSchema.listen().then(({ url }) => {
console.log(`schema ready at ${url}`);
});

View File

@ -0,0 +1,17 @@
{
"name": "azure-functions-nodejs",
"version": "1.0.0",
"description": "",
"main": "run.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-azure-functions": "^2.4.8",
"graphql": "^0.13.1",
"graphql-tag": "^2.10.1"
}
}

View File

@ -0,0 +1,16 @@
const { ApolloServer } = require("apollo-server-azure-functions");
const { typeDefs, resolvers } = require('./server');
const server = new ApolloServer({
typeDefs,
resolvers,
});
module.exports = server.createHandler({
cors: {
origin: '*',
credentials: true,
allowedHeaders: 'Content-Type, Authorization'
},
});

View File

@ -0,0 +1,16 @@
const gql = require('graphql-tag');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world",
},
};
exports.typeDefs = typeDefs;
exports.resolvers = resolvers;

View File

@ -0,0 +1,19 @@
{
"version": "2.0",
"functions": [ "graphql" ],
"functionTimeout": "00:00:30",
"extensions": {
"http": {
"routePrefix": ""
}
},
"logging": {
"fileLoggingMode": "always",
"logLevel": {
"default": "Information"
},
"console": {
"isEnabled": "false"
}
}
}

View File

@ -0,0 +1,17 @@
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
node_modules
#!include:.gitignore

View File

@ -0,0 +1,3 @@
node_modules/
*.zip
package-lock.json

View File

@ -0,0 +1,62 @@
# Google Cloud Functions + NodeJS + Apollo
This is a GraphQL backend boilerplate in nodejs that can be deployed on Google Cloud Functions.
## Stack
node 8.10
Google Cloud Functions
#### Frameworks/Libraries
Apollo Server (GraphQL framework)
## Schema
```
type Query {
hello: String
}
```
## Local Development
The sample source code is present in `index.js`.
```bash
$ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/google-cloud-functions/nodejs
```
Start a local development server (you may need to install dependencies from npm):
```bash
$ npm i --no-save apollo-server express
$ node localDev.js
Output:
Server ready at http://localhost:4000/
```
This will start a local server on `localhost:4000`. You can hit the graphql service at `localhost:4000`. This opens a graphql playground where you can query your schema.
## Deployment
1. Install `gcloud` cli.
2. From the current directory, run the following command to deploy the function:
```bash
$ gcloud functions deploy hello-graphql --entry-point handler --runtime nodejs8 --trigger-http
```
3. Get the trigger URL from the above output:
```yaml
httpsTrigger:
url: https://us-central1-hasura-test.cloudfunctions.net/hello-graphql
```

View File

@ -0,0 +1,23 @@
const { ApolloServer } = require("apollo-server-cloud-functions");
const { typeDefs, resolvers } = require('./index');
const server = new ApolloServer({
typeDefs,
resolvers,
playground: true,
introspection: true,
context: ({ req, res }) => ({
headers: req.headers,
req,
res,
}),
});
exports.handler = server.createHandler({
cors: {
origin: '*',
credentials: true,
allowedHeaders: 'Content-Type, Authorization'
},
});

View File

@ -0,0 +1,16 @@
const gql = require('graphql-tag');
const typeDefs = gql`
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world",
},
};
exports.typeDefs = typeDefs;
exports.resolvers = resolvers;

View File

@ -0,0 +1,11 @@
const { ApolloServer } = require('apollo-server');
const express = require('express');
const app = express();
const { typeDefs, resolvers } = require('./index');
const helloSchema = new ApolloServer({ typeDefs, resolvers });
helloSchema.listen().then(({ url }) => {
console.log(`schema ready at ${url}`);
});

View File

@ -0,0 +1,17 @@
{
"name": "google-cloud-functions-nodejs",
"version": "1.0.0",
"description": "",
"main": "googleCtx.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-cloud-functions": "^2.4.8",
"graphql": "^0.13.1",
"graphql-tag": "^2.10.1"
}
}

View File

@ -1,43 +1,27 @@
# Zeit + NodeJS + Apollo + Sequelize GraphQL boilerplate # Zeit (1.0) + NodeJS + Apollo
A boilerplate using nodejs and [Apollo Server](https://www.apollographql.com/docs/apollo-server/) that can be deployed on Zeit. A boilerplate using Nodejs and [Apollo Server](https://www.apollographql.com/docs/apollo-server/) that can be deployed on Zeit.
## Stack ## Stack
node 8.10 node 8.10
Postgres Zeit 1.0
Zeit Now
#### Frameworks/Libraries #### Frameworks/Libraries
Apollo Server (GraphQL framework) Apollo Server (GraphQL framework)
Sequelize (Postgres ORM)
## Local Development ## Local Development
The sample source code is present in `server.js`. Clone the repo and go to `community/boilerplates/remote-schemas/zeit-now/nodejs/apollo-sequelize` folder: The sample source code is present in `server.js`.
```bash ```bash
$ git clone git@github.com:hasura/graphql-engine $ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/zeit-now/nodejs/apollo-sequelize $ cd graphql-engine/community/boilerplates/remote-schemas/zeit-now/nodejs
``` ```
1) First, let's set the environment variable for connecting to the postgres instance. This can be a local postgres instance or some managed postgres instance like AWS RDS. Run the server locally:
```bash
$ export POSTGRES_CONNECTION_STRING='postgres://username:password@rds-database-endpoint.us-east-1.rds.amazonaws.com:5432/mydb'
```
2) Next, lets create the tables required for our schema.
```bash
psql $POSTGRES_CONNECTION_STRING -c "create table users(id serial primary key, name text, balance integer); create table min_amount(amount integer); insert into min_amount values (100)"
```
3) Now, you can run the server locally:
```bash ```bash
npm install npm install

View File

@ -1,37 +0,0 @@
const Sequelize = require("sequelize");
const POSTGRES_CONNECTION_STRING = process.env.POSTGRES_CONNECTION_STRING || "postgres://postgres:password@localhost:6432/postgres";
const sequelize = new Sequelize(
POSTGRES_CONNECTION_STRING, {}
);
const User = sequelize.define(
'user',
{
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
name: Sequelize.TEXT,
balance: Sequelize.INTEGER
},
{
timestamps: false
}
);
const MinAmount = sequelize.define(
'min_amount',
{
amount: Sequelize.INTEGER
},
{
freezeTableName: true,
timestamps: false
}
);
MinAmount.removeAttribute('id');
exports.sequelize = sequelize;
exports.User = User;
exports.MinAmount = MinAmount;

View File

@ -1,71 +0,0 @@
const { ApolloServer } = require('apollo-server');
const { makeExecutableSchema } = require('graphql-tools');
const Sequelize = require("sequelize");
const {User, MinAmount, sequelize} = require('./models.js');
const port = process.env.PORT || 4000;
const typeDefs = `
type Query {
hello: String
}
type Mutation {
validateAndAddUser(name: String, balance: Int): User
}
type User {
id: Int
name: String
balance: Int
}
`;
// We consider a user schema where a user can be added only if a custom validation passes.
// The custom validation involves fetching a min amount from a table
// and checking if the user balance is greater than the min amount.
// This will be done in a transaction.
const resolvers = {
Query: {
hello: () => "world",
},
Mutation: {
validateAndAddUser: async (_, { name, balance }) => {
//begin transaction
return await sequelize.transaction(async (t) => {
try {
//fetch min amount
const minAmount = await MinAmount.findOne({}, {transaction: t});
//check balance
if (balance >= minAmount.amount) {
//create user if balance is greater
const user = await User.create({
name: name,
balance: balance
});
return user;
} else {
throw new Error("balance too low, required atleast " + minAmount.amount);
}
} catch (e) {
console.log(e);
throw new Error(e);
}
});
}
}
};
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
const server = new ApolloServer({
schema
});
server.listen({ port }).then(({url}) => {
console.log(`GraphQL server running at ${url}`);
});

View File

@ -1,2 +0,0 @@
node_modules
package-lock.json

View File

@ -1,11 +0,0 @@
FROM node:8
WORKDIR /server
COPY ./package.json /server/
RUN npm install
COPY . /server/
CMD ["npm", "start"]

View File

@ -1,80 +0,0 @@
# Zeit + NodeJS + Express + GraphQL.js + Sequelize GraphQL boilerplate
A boilerplate using nodejs, express and [GraphQL.js](https://graphql.github.io/graphql-js/running-an-express-graphql-server/) that can be deployed on Zeit.
## Stack
node 8.10
Postgres
Zeit Now
#### Frameworks/Libraries
Express (NodeJS framework)
GraphQL.js (GraphQL framework)
Sequelize (Postgres ORM)
## Local Development
The sample source code is present in `server.js`. Clone the repo and go to `community/boilerplates/remote-schemas/zeit-now/nodejs/express-graphqljs-sequelize` folder:
```bash
$ git clone git@github.com:hasura/graphql-engine
$ cd graphql-engine/community/boilerplates/remote-schemas/zeit-now/nodejs/express-graphqljs-sequelize
```
1) First, let's set the environment variable for connecting to the postgres instance. This can be a local postgres instance or some managed postgres instance like AWS RDS.
```bash
$ export POSTGRES_CONNECTION_STRING='postgres://username:password@rds-database-endpoint.us-east-1.rds.amazonaws.com:5432/mydb'
```
2) Next, lets create the tables required for our schema.
```bash
psql $POSTGRES_CONNECTION_STRING -c "create table users(id serial primary key, name text, balance integer); create table min_amount(amount integer); insert into min_amount values (100)"
```
3) Now, you can run the server locally:
```bash
npm install
npm start
```
Running the server using Docker:
```bash
docker build -t graphql .
docker run -p 4000:4000 graphql
```
This will start a local server on `localhost:4000`. You can hit the graphql service at `localhost:4000/graphql` which opens GraphiQL.
## Deployment
Install the [Zeit Now](https://zeit.co/now) CLI:
```bash
npm install -g now
```
Deploy the server:
```bash
now
```
Get the URL and make a sample query:
```bash
curl https://app-name-something.now.sh/graphql \
-H 'Content-Type:application/json' \
-d'{"query":"{ hello }"}'
{"data":{"hello":"Hello World!"}}
```
You can also visit the now url to open GraphiQL.

View File

@ -1,37 +0,0 @@
const Sequelize = require("sequelize");
const POSTGRES_CONNECTION_STRING = process.env.POSTGRES_CONNECTION_STRING || "postgres://postgres:password@localhost:6432/postgres";
const sequelize = new Sequelize(
POSTGRES_CONNECTION_STRING, {}
);
const User = sequelize.define(
'user',
{
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
name: Sequelize.TEXT,
balance: Sequelize.INTEGER
},
{
timestamps: false
}
);
const MinAmount = sequelize.define(
'min_amount',
{
amount: Sequelize.INTEGER
},
{
freezeTableName: true,
timestamps: false
}
);
MinAmount.removeAttribute('id');
exports.sequelize = sequelize;
exports.User = User;
exports.MinAmount = MinAmount;

View File

@ -1,22 +0,0 @@
{
"name": "nodejs-express-gql-server",
"version": "1.0.0",
"description": "A GraphQL server boilerplate for NodeJS-Express using graphql-js library",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node -r esm server.js"
},
"author": "Hasura",
"license": "MIT",
"dependencies": {
"express": "^4.16.4",
"express-graphql": "^0.7.1",
"graphql": "^14.0.2",
"pg": "^7.7.1",
"sequelize": "^4.42.0"
},
"devDependencies": {
"esm": "^3.0.84"
}
}

View File

@ -1,67 +0,0 @@
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const Sequelize = require("sequelize");
const {User, MinAmount, sequelize} = require('./models.js');
const port = process.env.port || 4000;
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
type Query {
hello: String
}
type Mutation {
validateAndAddUser(name: String, balance: Int): User
}
type User {
id: Int
name: String
balance: Int
}
`);
// We consider a user schema where a user can be added only if a custom validation passes.
// The custom validation involves fetching a min amount from a table
// and checking if the user balance is greater than the min amount.
// This will be done in a transaction.
const root = {
hello: () => {
return 'Hello world!';
},
validateAndAddUser: async ({ name, balance }) => {
//begin transaction
return await sequelize.transaction(async (t) => {
try {
//fetch min amount
const minAmount = await MinAmount.findOne({}, {transaction: t});
//check balance
if (balance >= minAmount.amount) {
//create user if balance is greater
const user = await User.create({
name: name,
balance: balance
});
return user;
} else {
throw new Error("balance too low, required atleast " + minAmount.amount);
}
} catch (e) {
console.log(e);
throw new Error(e);
}
});
}
};
var app = express();
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
app.listen(port);
console.log(`Running a GraphQL API server at localhost:${port}/graphql`);

View File

@ -4,18 +4,13 @@
"description": "A GraphQL server boilerplate written in NodeJS using and Apollo Server", "description": "A GraphQL server boilerplate written in NodeJS using and Apollo Server",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {
"start": "node -r esm server.js" "start": "node server.js"
}, },
"author": "Hasura", "author": "Hasura",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"apollo-server": "^2.2.1", "apollo-server": "^2.2.1",
"graphql": "^14.0.2", "graphql": "^14.0.2",
"graphql-tools": "^4.0.3", "graphql-tools": "^4.0.3"
"pg": "^7.7.1",
"sequelize": "^4.42.0"
},
"devDependencies": {
"esm": "^3.0.84"
} }
} }

View File

@ -0,0 +1,29 @@
const { ApolloServer } = require('apollo-server');
const { makeExecutableSchema } = require('graphql-tools');
const port = process.env.PORT || 4000;
const typeDefs = `
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => "world",
}
};
const schema = makeExecutableSchema({
typeDefs,
resolvers
});
const server = new ApolloServer({
schema
});
server.listen({ port }).then(({url}) => {
console.log(`GraphQL server running at ${url}`);
});