GraphQL works with Mongoose

This commit is contained in:
Riccardo
2021-01-03 10:31:08 +01:00
parent c752e3ec80
commit b5129342e3
17 changed files with 3588 additions and 261 deletions

12
server/.babelrc Normal file
View File

@@ -0,0 +1,12 @@
{
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
]
]
}

6
server/.babelrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"singleQuote": true
}

48
server/.eslintrc.json Normal file
View File

@@ -0,0 +1,48 @@
{
"plugins": [
"babel"
],
"extends": [
"eslint:recommended"
],
"rules": {
"no-console": 0,
"no-mixed-spaces-and-tabs": 1,
"comma-dangle": 0,
"no-unused-vars": 1,
"eqeqeq": [
2,
"smart"
],
"no-useless-concat": 2,
"default-case": 2,
"no-self-compare": 2,
"prefer-const": 2,
"object-shorthand": 1,
"array-callback-return": 2,
"valid-typeof": 2,
"arrow-body-style": 2,
"require-await": 2,
"react/prop-types": 0,
"no-var": 2,
"linebreak-style": [
2,
"unix"
],
"semi": [
1,
"always"
]
},
"env": {
"node": true
},
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2018,
"ecmaFeatures": {
"modules": true
}
}
}

5
server/husky.json Normal file
View File

@@ -0,0 +1,5 @@
"husky": {
"hooks": {
"pre-commit": "yarn lint"
}
}

View File

@@ -2,29 +2,53 @@
"name": "server",
"version": "1.0.0",
"license": "MIT",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js"
},
"dependencies": {
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"apollo-engine": "^1.1.2",
"apollo-server": "^2.19.0",
"apollo-server-express": "^2.19.1",
"bcryptjs": "2.4.3",
"body-parser": "^1.19.0",
"chai": "^4.2.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"esm": "^3.2.25",
"express": "^4.17.1",
"express-graphql": "^0.12.0",
"graphql": "^14.7.0",
"graphql": "^15.4.0",
"graphql-compose": "^7.23.0",
"graphql-compose-connection": "^8.0.1",
"graphql-compose-mongoose": "^9.0.0",
"graphql-middleware": "^6.0.0",
"graphql-tools": "^7.0.2",
"jsonwebtoken": "8.5.1",
"migrate": "^1.7.0",
"mocha": "^8.2.1",
"mongodb": "^3.6.3",
"mongoose": "^5.11.9",
"mongoose-bcrypt": "^1.9.0",
"mongoose-timestamp": "^0.6.0",
"node-migrate": "^0.1.0"
},
"devDependencies": {
"nodemon": "^2.0.6"
"babel-eslint": "^10.1.0",
"babel-loader": "^8.2.2",
"babel-preset-env": "^1.7.0",
"eslint": "^7.17.0",
"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"fs-extra": "^9.0.1",
"nodemon": "^2.0.6",
"prettier": "^2.2.1"
}
}

10
server/scripts.js Normal file
View File

@@ -0,0 +1,10 @@
"scripts": {
"build": "babel src --out-dir dist",
"start": "node dist/index.js",
"dev": "nodemon --exec npx babel-node src/index.js",
"prettier": "prettier --config ./.prettierrc --write \"**/*.js\"",
"pretest": "eslint --ignore-path .gitignore .",
"postinstall": "rm -rf dist && yarn run build",
"lint": "yarn prettier --write --check --config ./.prettierrc \"**/*.js\" && eslint --fix ./src",
"release": "release-it patch --no-npm.publish"
}

View File

@@ -1,148 +1,203 @@
const { ApolloServer, PubSub } = require('apollo-server');
// const { Cors } = require('cors');
// const { Express } = require('express');
const express = require("express");
const { graphqlHTTP } = require('express-graphql');
const mongoose = require("mongoose");
const graphqlSchema = require("./graphql/schema/schema")
const appointmentResolvers = require("./graphql/resolvers/appointment")
const userResolvers = require("./graphql/resolvers/user")
import dotenv from 'dotenv';
import express from 'express';
// const express = require("express");
// const { ApolloServer, PubSub } = require('apollo-server');
import { ApolloServer } from 'apollo-server-express';
// const mongoose = require("mongoose");
import mongoose from 'mongoose';
var MongoClient = require('mongodb', { useUnifiedTopology: true }).MongoClient;
// import { MongoClient } from 'mongodb'
const Query = require('./resolvers/Query');
const Mutation = require('./resolvers/Mutation');
const Subscription = require('./resolvers/Subscription');
const User = require('./resolvers/User');
const Appointment = require('./resolvers/Appointment');
const Follow = require('./resolvers/Follow');
const fs = require('fs');
const path = require('path');
const { getUserId } = require('./utils');
const pubsub = new PubSub();
const app = express()
const graphqlResolvers = {
appointmentResolvers,
userResolvers
};
import './utils/db.js';
// require('./utils/db')
import schema from './schema/index.js';
// require('./schema')
app.use(
"/graphql",
graphqlHTTP({
schema: graphqlSchema,
rootValue: appointmentResolvers,
graphiql: true,
})
)
const uri = `mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority`
const options = { useNewUrlParser: true, useUnifiedTopology: true }
let db = mongoose
.connect(uri, options)
.then(() => app.listen(4000, console.log("Server is running")))
.catch(error => {
throw error
})
// const app = new Express();
// app.use(Cors());
dotenv.config();
// const mongo = new MongoClient({
// errorFormat: 'minimal'
// });
const app = express();
// const mongo = MongoClient.connect("mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority", function (err, db) {
const server = new ApolloServer({
schema,
cors: true,
playground: process.env.NODE_ENV === 'development' ? true : false,
introspection: true,
tracing: true,
path: '/',
});
// if (err) throw err;
// console.log("ALL good");
// //Write databse Insert/Update/Query code here..
server.applyMiddleware({
app,
path: '/',
cors: true,
onHealthCheck: () =>
// eslint-disable-next-line no-undef
new Promise((resolve, reject) => {
if (mongoose.connection.readyState > 0) {
resolve();
} else {
reject();
}
}),
});
// });
app.listen({ port: process.env.PORT }, () => {
console.log(`🚀 Server listening on port ${process.env.PORT}`);
console.log(`😷 Health checks available at ${process.env.HEALTH_ENDPOINT}`);
});
// const dbClient = new MongoClient(
// 'mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority',
// {
// useNewUrlParser: true,
// useUnifiedTopology: true,
// }
// )
// const resolvers = {
// Query,
// Mutation,
// Subscription,
// User,
// Appointment,
// Follow
// const { ApolloServer, PubSub } = require('apollo-server');
// // const { Cors } = require('cors');
// // const { Express } = require('express');
// const express = require("express");
// const { graphqlHTTP } = require('express-graphql');
// const mongoose = require("mongoose");
// const graphqlSchema = require("./graphql/schema/schema")
// const appointmentResolvers = require("./graphql/resolvers/appointment")
// const userResolvers = require("./graphql/resolvers/user")
// var MongoClient = require('mongodb', { useUnifiedTopology: true }).MongoClient;
// // import { MongoClient } from 'mongodb'
// const Query = require('./resolvers/Query');
// const Mutation = require('./resolvers/Mutation');
// const Subscription = require('./resolvers/Subscription');
// const User = require('./resolvers/User');
// const Appointment = require('./resolvers/Appointment');
// const Follow = require('./resolvers/Follow');
// const fs = require('fs');
// const path = require('path');
// const { getUserId } = require('./utils');
// const pubsub = new PubSub();
// const app = express()
// const graphqlResolvers = {
// appointmentResolvers,
// userResolvers
// };
// let db;
// const server = new ApolloServer({
// typeDefs: fs.readFileSync(
// path.join(__dirname, 'schema.graphql'),
// 'utf8'
// ),
// resolvers,
// context: async ({ req }) => {
// if (!db) {
// try {
// if (!dbClient.isConnected()) await dbClient.connect()
// mongo = dbClient.db('Calendar') // database name
// console.log(db);
// } catch (e) {
// console.log('--->error while connecting with graphql context (db)', e)
// }
// }
// app.use(
// "/graphql",
// graphqlHTTP({
// schema: graphqlSchema,
// rootValue: appointmentResolvers,
// graphiql: true,
// })
// )
// const uri = `mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority`
// const options = { useNewUrlParser: true, useUnifiedTopology: true }
// let db = mongoose
// .connect(uri, options)
// .then(() => app.listen(4000, console.log("Server is running")))
// .catch(error => {
// throw error
// })
// return {
// ...req,
// mongo,
// pubsub,
// userId:
// req && req.headers.authorization
// ? getUserId(req)
// : null
// }
// },
// // context: ({ req }) => {
// // return {
// // ...req,
// // mongo,
// // pubsub,
// // userId:
// // req && req.headers.authorization
// // ? getUserId(req)
// // : null
// // };
// // },
// // subscriptions: {
// // onConnect: (connectionParams) => {
// // if (connectionParams.authToken) {
// // return {
// // mongo,
// // userId: getUserId(
// // null,
// // connectionParams.authToken
// // )
// // };
// // } else {
// // return {
// // mongo
// // };
// // }
// // }
// // }
// });
// // const app = new Express();
// // app.use(Cors());
// // server.applyMiddleware({ app });
// // const mongo = new MongoClient({
// // errorFormat: 'minimal'
// // });
// server
// .listen()
// .then(({ url }) =>
// console.log(`Server is running on ${url}`)
// );
// // const mongo = MongoClient.connect("mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority", function (err, db) {
// // if (err) throw err;
// // console.log("ALL good");
// // //Write databse Insert/Update/Query code here..
// // });
// // const dbClient = new MongoClient(
// // 'mongodb+srv://admin:hEbAjhvkrFDHAP3@cluster0.0hjtt.mongodb.net/Calendar?retryWrites=true&w=majority',
// // {
// // useNewUrlParser: true,
// // useUnifiedTopology: true,
// // }
// // )
// // const resolvers = {
// // Query,
// // Mutation,
// // Subscription,
// // User,
// // Appointment,
// // Follow
// // };
// // let db;
// // const server = new ApolloServer({
// // typeDefs: fs.readFileSync(
// // path.join(__dirname, 'schema.graphql'),
// // 'utf8'
// // ),
// // resolvers,
// // context: async ({ req }) => {
// // if (!db) {
// // try {
// // if (!dbClient.isConnected()) await dbClient.connect()
// // mongo = dbClient.db('Calendar') // database name
// // console.log(db);
// // } catch (e) {
// // console.log('--->error while connecting with graphql context (db)', e)
// // }
// // }
// // return {
// // ...req,
// // mongo,
// // pubsub,
// // userId:
// // req && req.headers.authorization
// // ? getUserId(req)
// // : null
// // }
// // },
// // // context: ({ req }) => {
// // // return {
// // // ...req,
// // // mongo,
// // // pubsub,
// // // userId:
// // // req && req.headers.authorization
// // // ? getUserId(req)
// // // : null
// // // };
// // // },
// // // subscriptions: {
// // // onConnect: (connectionParams) => {
// // // if (connectionParams.authToken) {
// // // return {
// // // mongo,
// // // userId: getUserId(
// // // null,
// // // connectionParams.authToken
// // // )
// // // };
// // // } else {
// // // return {
// // // mongo
// // // };
// // // }
// // // }
// // // }
// // });
// // // server.applyMiddleware({ app });
// // server
// // .listen()
// // .then(({ url }) =>
// // console.log(`Server is running on ${url}`)
// // );

34
server/src/models/task.js Normal file
View File

@@ -0,0 +1,34 @@
import mongoose from 'mongoose';
const { Schema } = mongoose;
import timestamps from 'mongoose-timestamp';
import { composeWithMongoose } from 'graphql-compose-mongoose';
export const TaskSchema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
task: {
type: String,
trim: true,
required: true,
},
description: {
type: String,
trim: true,
required: true,
},
},
{
collection: 'tasks',
}
);
TaskSchema.plugin(timestamps);
TaskSchema.index({ createdAt: 1, updatedAt: 1 });
export const Task = mongoose.model('Task', TaskSchema);
export const TaskTC = composeWithMongoose(Task);

31
server/src/models/user.js Normal file
View File

@@ -0,0 +1,31 @@
import mongoose from 'mongoose';
const { Schema } = mongoose
import timestamps from 'mongoose-timestamp';
import { composeWithMongoose } from 'graphql-compose-mongoose';
export const UserSchema = new Schema(
{
name: {
type: String,
trim: true,
required: true,
},
email: {
type: String,
lowercase: true,
trim: true,
unique: true,
required: true,
},
},
{
collection: 'users',
}
);
UserSchema.plugin(timestamps);
UserSchema.index({ createdAt: 1, updatedAt: 1 });
export const User = mongoose.model('User', UserSchema);
export const UserTC = composeWithMongoose(User);

View File

@@ -8,7 +8,7 @@ async function feed(parent, args, context, info) {
]
}
: {};
console.log(context.mongo);
const appointments = await context.mongo.appointment.findMany({
where,
skip: args.skip,

View File

@@ -0,0 +1,20 @@
import { SchemaComposer } from 'graphql-compose';
import db from '../utils/db.js';
const schemaComposer = new SchemaComposer();
import { UserQuery, UserMutation } from './user.js';
import { TaskQuery, TaskMutation } from './task.js';
schemaComposer.Query.addFields({
...UserQuery,
...TaskQuery,
});
schemaComposer.Mutation.addFields({
...UserMutation,
...TaskMutation,
});
export default schemaComposer.buildSchema();

24
server/src/schema/task.js Normal file
View File

@@ -0,0 +1,24 @@
import { Task, TaskTC } from '../models/task.js';
const TaskQuery = {
taskById: TaskTC.getResolver('findById'),
taskByIds: TaskTC.getResolver('findByIds'),
taskOne: TaskTC.getResolver('findOne'),
taskMany: TaskTC.getResolver('findMany'),
taskCount: TaskTC.getResolver('count'),
taskConnection: TaskTC.getResolver('connection'),
taskPagination: TaskTC.getResolver('pagination'),
};
const TaskMutation = {
taskCreateOne: TaskTC.getResolver('createOne'),
taskCreateMany: TaskTC.getResolver('createMany'),
taskUpdateById: TaskTC.getResolver('updateById'),
taskUpdateOne: TaskTC.getResolver('updateOne'),
taskUpdateMany: TaskTC.getResolver('updateMany'),
taskRemoveById: TaskTC.getResolver('removeById'),
taskRemoveOne: TaskTC.getResolver('removeOne'),
taskRemoveMany: TaskTC.getResolver('removeMany'),
};
export { TaskQuery, TaskMutation };

24
server/src/schema/user.js Normal file
View File

@@ -0,0 +1,24 @@
import { User, UserTC } from '../models/user.js';
const UserQuery = {
userById: UserTC.getResolver('findById'),
userByIds: UserTC.getResolver('findByIds'),
userOne: UserTC.getResolver('findOne'),
userMany: UserTC.getResolver('findMany'),
userCount: UserTC.getResolver('count'),
userConnection: UserTC.getResolver('connection'),
userPagination: UserTC.getResolver('pagination'),
};
const UserMutation = {
userCreateOne: UserTC.getResolver('createOne'),
userCreateMany: UserTC.getResolver('createMany'),
userUpdateById: UserTC.getResolver('updateById'),
userUpdateOne: UserTC.getResolver('updateOne'),
userUpdateMany: UserTC.getResolver('updateMany'),
userRemoveById: UserTC.getResolver('removeById'),
userRemoveOne: UserTC.getResolver('removeOne'),
userRemoveMany: UserTC.getResolver('removeMany'),
};
export { UserQuery, UserMutation };

View File

@@ -0,0 +1,31 @@
import fs from 'fs-extra';
import path from 'path';
import { graphql } from 'graphql';
import { introspectionQuery, printSchema } from 'graphql/utilities';
import Schema from '../schema';
async function buildSchema() {
await fs.ensureFile('../data/schema.graphql.json');
await fs.ensureFile('../data/schema.graphql');
fs.writeFileSync(
path.join(__dirname, '../data/schema.graphql.json'),
JSON.stringify(await graphql(Schema, introspectionQuery), null, 2)
);
fs.writeFileSync(
path.join(__dirname, '../data/schema.graphql.txt'),
printSchema(Schema)
);
}
async function run() {
await buildSchema();
console.log('Schema build complete!');
}
run().catch(e => {
console.log(e);
process.exit(0);
});

29
server/src/utils/db.js Normal file
View File

@@ -0,0 +1,29 @@
// const mongoose = require("mongoose");
import mongoose from 'mongoose';
// const dotenv = require("../../.env");
import dotenv from 'dotenv';
dotenv.config();
mongoose.Promise = global.Promise;
const connection = mongoose.connect(process.env.MONGODB_URI, {
autoIndex: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
poolSize: 50,
bufferMaxEntries: 0,
keepAlive: 120,
useNewUrlParser: true,
});
mongoose.set('useCreateIndex', true);
connection
.then(db => db)
.catch(err => {
console.log(err);
});
export default connection;

File diff suppressed because it is too large Load Diff