在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):aichbauer/express-graphql-boilerplate开源软件地址(OpenSource Url):https://github.com/aichbauer/express-graphql-boilerplate开源编程语言(OpenSource Language):JavaScript 100.0%开源软件介绍(OpenSource Introduction):express-graphql-boilerplate
Quick IntroGraphQL is a Query Language where your REST API can co-exist directly beside your GraphQL API in harmony. To demonstrate this we have two REST endpoints for # clone repository
$ git clone https://github.com/aichbauer/express-graphql-boilerplate.git
# cd into project root
$ cd express-graphql-boilerplate
# install dependencies
$ npm i
# start application
$ npm start
# create a User via the REST API
$ curl -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"pw","password2":"pw"}' http://localhost:2017/rest/register
# login a User via the REST API
# you will get a JSON with a token and this is your token to get access to the GraphQL API
$ curl -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"pw"}' http://localhost:2017/rest/login
# requesting a User via the GraphQL API
$ curl -i -H "Content-Type:application/json" -H "Authorization: Bearer <token>" -X POST -d '{"query": "{user{id, username}}"}' http://localhost:2017/graphql
# creating a Note for a user via the GraphQL API
$ curl -i -H "Content-Type:application/json" -H "Authorization: Bearer <token>" -X POST -d '{"query": "mutation{createNote(userId:1,note:\"this is a note\"){id,userId,note}}"}' http://localhost:2017/graphql
# requesting a User with its Notes via the GraphQL API (nested Query)
$ curl -i -H "Content-Type:application/json" -H "Authorization: Bearer <token>" -X POST -d '{"query": "{user{id, username, notes{id, note}}}"}' http://localhost:2017/graphql Table of Contents
Install and UseStart by cloning this repository # HTTPS
$ git clone https://github.com/aichbauer/express-graphql-boilerplate.git then # change directory to project root
$ cd express-graphql-boilerplate
# install dependencies
$ npm i
# to use mysql
$ npm i mysql2 -S
# to use postgresql
$ npm i pg pg-hstore -S or # change directory to project root
$ cd express-graphql-boilerplate
# install dependencies
$ yarn
# to use mysql
$ yarn add mysql2
# to use postgresql
$ yarn add pg pg-hstore SQLite is supported out of the box as it is the default database. Folder StructureThis boilerplate has four main directories:
ControllersControllers in this boilerplate have a naming convention: Create a ControllerFor an example with all CRUD operations visit the express-rest-api-boilerplate GraphQLThis directory holds all files that are related to GraphQL (mutations, queries, types, ...). Create a Query
Example query for a User which lets you request all different fields which are defined in // import the required GraphQL Types
const {
GraphQLInt,
GraphQLString,
GraphQLList,
} = require('graphql');
// import the Model and the Type
const { UserType } = require('../types');
const { User } = require('../../models');
// create the query
const userQuery = {
type: new GraphQLList(UserType), // the Type which it returns (an array of Users)
args: {
// arguments you are able to Query
// notice no password field
// so the password will not be send as respond
// neither can you Query for it
id: {
name: 'id',
type: GraphQLInt,
},
username: {
name: 'username',
type: GraphQLString,
},
email: {
name: 'email',
type: GraphQLString,
},
notes: {
name: 'notes',
type: GraphQLString,
},
createdAt: {
name: 'createdAt',
type: GraphQLString,
},
updatedAt: {
name: 'updatedAt',
type: GraphQLString,
},
},
// how to get the respond
// DB call
resolve: (user, args) => User.findAll({ where: args }),
};
module.exports = { userQuery }; Do not forget to Create a Mutation
// import the rqeuired GraphQL Types
const {
GraphQLString,
GraphQLInt,
GraphQLNonNull,
} = require('graphql');
const merge = require('lodash.merge');
// import the Model and the Type
const { UserType } = require('../types');
const { User } = require('../../models');
// create the mutation
const updateUser = {
// the Type which it returns (one user)
type: UserType,
description: 'The mutation that allows you to update an existing User by Id',
// arguments you can use
// have to be fields that are
// resolvable by the UserType
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLInt),
},
username: {
name: 'username',
type: GraphQLString,
},
email: {
name: 'email',
type: GraphQLString,
},
},
// find the User in the DB
// update the fields for this user
resolve: async (user, { id, username, email }) => {
const foundUser = await User.findByPk(id);
if (!foundUser) {
throw new Error(`User with id: ${id} not found!`);
}
const updatedUser = merge(foundUser, {
username,
email,
});
return foundUser.update(updatedUser);
},
};
// the delete mutation
const deleteUser = {
// the Type which it returns (one user)
type: UserType,
description: 'The mutation that allows you to delete a existing User by Id',
// arguments you can use
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLInt),
},
},
resolve: async (user, { id }) => {
const foundUser = await User.findByPk(id);
if (!foundUser) {
throw new Error(`User with id: ${id} not found!`);
}
await User.destroy({
where: {
id,
},
});
return foundUser;
},
};
module.exports = {
updateUser,
deleteUser,
}; Do not forget to Create a TypeTypes are necessary to let GraphQL know, how to resolve the different fields you provide in your queries and mutations. // import the required GraphQL Types
const {
GraphQLObjectType,
GraphQLInt,
GraphQLString,
GraphQLList,
} = require('graphql');
// our UserType definition
const UserType = new GraphQLObjectType({
name: 'User',
description: 'This represents a User',
// all the fields a User can have
fields: () => ({
id: {
type: GraphQLInt,
resolve: (user) => user.id,
},
username: {
type: GraphQLString,
resolve: (user) => user.username,
},
email: {
type: GraphQLString,
resolve: (user) => user.email,
},
createdAt: {
type: GraphQLString,
resolve: (user) => user.createdAt,
},
updatedAt: {
type: GraphQLString,
resolve: (user) => user.updatedAt,
},
}),
});
module.exports = { UserType }; Do not forget to Create an InputTypeInputTypes are a way to simplify your arguments on a mutation or a query. You may not need to implement InputTypes, but it is common that some kind of mutations or queries accept the same input types, what makes them pretty handy. The simpliest version would of a InputType could look like this: // import the GraphQL types
// that you need for your
// input type
const {
GraphQLInputObjectType,
GraphQLInt,
GraphQLNonNull,
GraphQLString,
} = require('graphql');
// create a InputType
const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'This represents a UserInputType',
fields: {
id: {
type: new GraphQLNonNull(GraphQLInt),
},
username: {
type: GraphQLString,
},
email: {
type: GraphQLString,
},
},
});
module.exports = { UserInputType }; But you can reuse the same implementation for multiple purposes of the same InputType, e.g. // import the GraphQL types
// that you need for your
// input type
const {
GraphQLInputObjectType,
GraphQLInt,
GraphQLNonNull,
GraphQLString,
} = require('graphql');
// the function that accepts a
// string, specifying the type
// e.g. 'create', 'update', or 'delete'
const UserInputType = (type) => {
let allGraphFields = {};
const standardGraphFields = {
id: {
type: new GraphQLNonNull(GraphQLInt),
},
};
// add args for different mutations
switch (type) {
case 'delete':
allGraphFields = {
...standardGraphFields,
};
break;
case 'update':
allGraphFields = {
...standardGraphFields,
username: {
type: GraphQLString,
},
email: {
type: GraphQLString,
},
};
break;
default:
allGraphFields = {
...standardGraphFields,
};
}
// create a InputType
// keep in mind that
// one name can only
// exist once in a schema
const userInputType = new GraphQLInputObjectType({
name: `UserInputType${type[0].toUpperCase() + type.slice(1, type.length - 1)}`,
description: 'This represents a UserInputType',
fields: allGraphFields,
});
return userInputType;
};
module.exports = { UserInputType }; Now you can use this on a mutation or a query like: const updateUser = {
type: UserType,
description: 'The mutation that allows you to update an existing User by Id',
args: {
user: {
name: 'user',
// use the InputType
type: UserInputType('update'),
},
},
resolve: async (_, { user }) => {
const foundUser = await User.findByPk(user.id);
if (!foundUser) {
throw new Error(`User with id: ${user.id} not found!`);
}
const updatedUser = merge(foundUser, {
username: user.username,
email: user.email,
});
return foundUser.update(updatedUser);
},
};
const deleteUser = {
type: UserType,
description: 'The mutation that allows you to delete a existing User by Id',
args: {
user: {
name: 'user',
// use the InputType
type: UserInputType('delete'),
},
},
resolve: async (_, { user }) => {
const foundUser = await User.findByPk(user.id);
if (!foundUser) {
throw new Error(`User with id: ${user.id} not found!`);
}
await User.destroy({
where: {
id: user.id,
},
});
return foundUser;
},
}; RootQuery, RootMutation and SchemaThe schema holds the // import required GraphQL Types
const {
GraphQLSchema,
GraphQLObjectType,
} = require('graphql');
// import Query and Mutations
const { userQuery } = require('./queries');
const {
updateUser,
deleteUser,
} = require('./mutations');
// add Queries to RootQuery
const RootQuery = new GraphQLObjectType({
name: 'rootQuery',
description: 'This is the RootQuery which holds all possible READ entrypoints for the GraphQL API',
fields: () => ({
user: userQuery,
}),
});
// add Mutations to RootMutations
const RootMutation = new GraphQLObjectType
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论