Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/danishsiraj/mongoose-graphql-server
https://github.com/danishsiraj/mongoose-graphql-server
graphql hacktoberfest mongoose
Last synced: about 1 month ago
JSON representation
- Host: GitHub
- URL: https://github.com/danishsiraj/mongoose-graphql-server
- Owner: DanishSiraj
- License: gpl-3.0
- Created: 2022-10-01T10:44:32.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2023-10-07T16:51:13.000Z (about 1 year ago)
- Last Synced: 2024-10-11T12:20:35.790Z (about 1 month ago)
- Topics: graphql, hacktoberfest, mongoose
- Language: TypeScript
- Homepage:
- Size: 323 KB
- Stars: 7
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Automatically generates a GraphQL Server from mongoose models. Provides all the basic CRUD operations for all models on both native mongoose connection as well as created connections. Supports deep nested populations for queries.
Uses [graphql-compose-mongooose](https://github.com/graphql-compose/graphql-compose-mongoose) and [Apollo Server](https://www.apollographql.com/docs/apollo-server/) under the hood.
- [Installation](#installation)
- [Example](#example)
- [Running with Mongoose](#running-with-mongoose)
- [Nested Populations](#nested-populations)
- [With Model Names](#with-model-names)
- [With Virtuals](#with-virtuals)
- [Using Express Server](#using-express-server)
- [As Express Middleware](#as-express-middleware)
- [From GraphQL Server](#from-graphql-server)
- [Using Existing Instance](#using-existing-instance)
- [Adding Custom Query and Mutations](#adding-custom-query-and-mutations)
- [Configuration](#configuration)
- [Configuring Apollo Server](#configuring-apollo-server)
- [Known Issues](#issues)
- [ToDo List](#todo)## Installation
Install with npm
```console
$ npm i mongoose-graphql-server --save
```Install with yarn
```console
$ yarn add mongoose-graphql-server
```## Example
Use the endpoint `/graphql` to open graphQL studio. The examples to implement can also be found here at [examples repository](https://github.com/DanishSiraj/mongoose-graphql-examples)
#### Running with Mongoose
```
const mongoose = require('mongoose');
const {
generateSchema,
createGraphQLServer,
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
const Cat = mongoose.model('Cat', { name: String });
// Build the schema
const schema = generateSchema(mongoose);
// Create the graphQL server
const app = await createGraphQLServer(schema);
// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open',init);
```### Nested Populations
This package supports deep nested populations if using model names as refs or defining virtual fields on the models.
#### With Model Names
Define the first `User` model in `user.model.js` file
```
const {model, Schema, Types} = require('mongoose');const userSchema = new Schema(
{
name: {
type: String,
},
username: {
type: String,
required: true,
indexed: true
},
isActive: {
type: Boolean,
default: true,
}
,
posts:[{
type: Types.ObjectId,
ref: "post",
}]},
{
timestamps: true,
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
}
);const userModel = model('user', userSchema);
module.exports = userModel;
```Define the second `Post` model in `post.model.js` file
```
const {model, Schema,Types} = require('mongoose');const postSchema = new Schema(
{
title: {
type: String,
required: true,
},description: {
type: String,
},status: {
type: String,
enum: ['CREATED', 'DRAFT', 'PUBLISHED'],
required: true,
},
creator: {
type: Types.ObjectId,
ref:"user"
},
},
{
timestamps: true,
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
}
);const postModel = model('post', postSchema);
module.exports = postModel;
```Create the server file `index.js`
```
const mongoose = require('mongoose');
const {
generateSchema,
createGraphQLServer,
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test1');
const db = mongoose.connection;const init = async () => {
// Register models
require('./user.model.js');
require('./post.model.js');// Build the schema
const schema = generateSchema(mongoose);// Create the graphQL server
const app = await createGraphQLServer(schema);// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open',init);
```Run the server
```console
$ node index.js
```#### With Virtuals
Define the first `User` model in `user.model.js` file
```
const {model, Schema} = require('mongoose');const userSchema = new Schema(
{
name: {
type: String,
},
isActive: {
type: Boolean,
default: true,
},
},
{
timestamps: true,
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
}
);userSchema.virtual('posts', {
ref: 'post',
foreignField: 'author_id',
localField: '_id',
});const userModel = model('user', userSchema);
module.exports = userModel;```
Define the second `Post` model in `post.model.js` file
```
const {model, Schema} = require('mongoose');const postSchema = new Schema(
{
title: {
type: String,
required: true,
},description: {
type: String,
},status: {
type: String,
enum: ['CREATED', 'DRAFT', 'PUBLISHED'],
required: true,
},
author_id: {
type: String,
required: true,
},
},
{
timestamps: true,
toObject: {
virtuals: true,
},
toJSON: {
virtuals: true,
},
}
);postSchema.virtual('author', {
ref: 'user',
foreignField: '_id',
localField: 'author_id',
justOne: true,
});const postModel = model('post', postSchema);
module.exports = postModel;```
Create the server file `index.js`
```
const mongoose = require('mongoose');
const {
generateSchema,
createGraphQLServer,
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
require('./user.model.js');
require('./post.model.js');// Build the schema
const schema = generateSchema(mongoose);// Create the graphQL server
const app = await createGraphQLServer(schema);// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open',init);
```
Run the server
```console
$ node index.js
```### Using Express Server
This package uses express as the default server to serve the graphQl endpoint, the `createGraphQLServer` method returns an Express app instance. Further the server can be used as an express app middleware by using `createGraphQLMiddleware`.
#### As Express Middleware
```
const mongoose = require('mongoose');
const express = require('express');const {
generateSchema,
createGraphQLMiddleware
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
const Cat = mongoose.model('Cat', { name: String });
// Build the schema
const schema = generateSchema(mongoose);let app = express();
const middleware = await createGraphQLMiddleware(schema);
app.use("/", middleware);
// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open', init);
```#### From GraphQL Server
```
const mongoose = require('mongoose');
const {
generateSchema,
createGraphQLServer,
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
const Cat = mongoose.model('Cat', { name: String });
// Build the schema
const schema = generateSchema(mongoose);// Create the graphQL server
const app = await createGraphQLServer(schema);app.get("/",(req,res) => {
res.send("hello");
})// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open',init);
```Run the server
```console
$ node index.js
```#### Using Existing Instance
```
const mongoose = require('mongoose');
const express = require('express');const {
generateSchema,
createGraphQLServer,
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
const Cat = mongoose.model('Cat', { name: String });
// Build the schema
const schema = generateSchema(mongoose);let app = express();
app.get("/", (req, res) => {
res.send(`GrahpQL running on http://localhost:${PORT}/graphql`);
})// Create the graphQL server
app = await createGraphQLServer(schema, app);app.get("/test", (req, res) => {
res.send("ok")
})// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open', init);
```Run the server
```console
$ node index.js
```## Adding Custom Query and Mutations
When needed custom Query and Mutation fields can be defined in the GraphQl schema by using ```addQueryFields``` and ```addMutationFields``` functions. Additional types can also be defined using the ```schemaComposer``` which is an instance of SchemaComposer from [graqhql-compose](graphql-compose.github.io). Full documentation for customization can be found on their official [docs](https://graphql-compose.github.io/docs/basics/understanding-types.html) page.
```
const mongoose = require('mongoose');
const {
generateSchema,
createGraphQLServer,
addQueryFields,
addMutationFields,
schemaComposer
} = require('mongoose-graphql-server');
const PORT = process.env.port || 3000;mongoose.connect('mongodb://localhost/test');
const db = mongoose.connection;const init = async () => {
// Register models
const Cat = mongoose.model('Cat', { name: String });// Build the schema
let schema = generateSchema(mongoose);// Add custom types and input types
const Test = schemaComposer.createObjectTC(`
type Test {
name: String
age: Int
}
`);const TestInput = schemaComposer.createInputTC(`
input TestInput {
name: String
}`);// Add custom query fields
addQueryFields({
"testQuery": {
type: [Test],
args: { input: TestInput },
resolve: (source, args, context, info) => {
return [{ "name": "test", "age": 1 }];
},
}
})// Add custom mutation fields
addMutationFields({
"testMutation": {
type: [Test],
args: { input: TestInput },
resolve: (source, args, context, info) => {
return [{ "name": "test", "age": 1 }];
},
}
})//rebuild the schema
schema = schemaComposer.buildSchema();// Create the graphQL server
const app = await createGraphQLServer(schema);// Start the server
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}/`);
console.log(`GraphQL is running at http://localhost:${PORT}/graphql`);
})}
db.once('open', init);
```## Configuration
### Configuring Apollo Server
Features like schema introspection, cache, csrfPrevention can be configured by passing in the Apollo Server Configuration Object in the `createGraphQLServer` method.
```
const app = await createGraphQLServer({
schema,
introspection: false
});
```The full list of customization options can be found at [Apollo Server Docs](https://www.apollographql.com/docs/apollo-server/api/apollo-server)
## Issues
- At the moment populations are supported only on virtual fields and model names.
- Supports sort and filter only on indexed fields at the moment.
- Populating key needs to be present for deep nested populations of virtual fields.## ToDo
- [x] Write the documentation
- [ ] Write Tests
- [ ] Fix issues
- [x] Support custom field generator on genrated schema
- [x] Addition of custom query and mutation resolvers
- [x] Converting this project to typescript