renamed
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
MONGODB_URI='mongodb+srv://admin:admin@cluster1.ciuxwxd.mongodb.net/libraryApp?retryWrites=true&w=majority'
|
||||
JWT_SECRET="lsdahlasjkdhalskjdhaslkjdhaslkjhdaslkjdhaskljdha"
|
||||
@@ -0,0 +1,111 @@
|
||||
const { ApolloServer } = require('@apollo/server')
|
||||
const { ApolloServerPluginDrainHttpServer } = require('@apollo/server/plugin/drainHttpServer')
|
||||
const { expressMiddleware } = require('@apollo/server/express4')
|
||||
const { makeExecutableSchema } = require('@graphql-tools/schema')
|
||||
|
||||
const { WebSocketServer } = require('ws')
|
||||
const { useServer } = require('graphql-ws/lib/use/ws')
|
||||
|
||||
const http = require('http')
|
||||
const express = require('express')
|
||||
const cors = require('cors')
|
||||
|
||||
const jwt = require('jsonwebtoken')
|
||||
const mongoose = require('mongoose')
|
||||
const User = require("./models/user");
|
||||
const typeDefs = require("./schema");
|
||||
const resolvers = require("./resolver");
|
||||
|
||||
require("dotenv").config();
|
||||
|
||||
mongoose.set("strictQuery", false);
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI;
|
||||
|
||||
console.log("connecting to ", MONGODB_URI);
|
||||
|
||||
mongoose
|
||||
.connect(MONGODB_URI)
|
||||
.then(() => {
|
||||
console.log("connect to MongoDB");
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log("error connecting to MONGODG:", err.message);
|
||||
});
|
||||
|
||||
const start = async () => {
|
||||
const app = express();
|
||||
const httpServer = http.createServer(app);
|
||||
|
||||
const schema = makeExecutableSchema({ typeDefs, resolvers });
|
||||
const wsServer = new WebSocketServer({
|
||||
server: httpServer,
|
||||
paht: "/",
|
||||
});
|
||||
|
||||
const serverCleanup = useServer({ schema }, wsServer);
|
||||
|
||||
const server = new ApolloServer({
|
||||
schema,
|
||||
plugins: [
|
||||
ApolloServerPluginDrainHttpServer({ httpServer }),
|
||||
{
|
||||
async serverWillStart() {
|
||||
return {
|
||||
async drainServer() {
|
||||
await serverCleanup.dispose();
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
await server.start();
|
||||
|
||||
app.use(
|
||||
"/",
|
||||
cors(),
|
||||
express.json(),
|
||||
expressMiddleware(server, {
|
||||
context: async ({ req }) => {
|
||||
const auth = req ? req.headers.authorization : null;
|
||||
if (auth && auth.startsWith("Bearer ")) {
|
||||
const decodedToken = jwt.verify(
|
||||
auth.substring(7),
|
||||
process.env.JWT_SECRET
|
||||
);
|
||||
const currentUser = await User.findById(decodedToken.id);
|
||||
return { currentUser };
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
const PORT = 4000;
|
||||
httpServer.listen(PORT, () =>
|
||||
console.log(`Server is now running on http://localhost:${PORT}`)
|
||||
);
|
||||
};
|
||||
start();
|
||||
/*
|
||||
const server = new ApolloServer({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
|
||||
startStandaloneServer(server, {
|
||||
listen: { port: 4000 },
|
||||
context: async ({ req, res }) => {
|
||||
const auth = req ? req.headers.authorization : null;
|
||||
if (auth && auth.startsWith("Bearer ")) {
|
||||
const decodedToken = jwt.verify(
|
||||
auth.substring(7),
|
||||
process.env.JWT_SECRET
|
||||
);
|
||||
const currentUser = await User.findById(decodedToken.id);
|
||||
return { currentUser };
|
||||
}
|
||||
},
|
||||
}).then(({ url }) => {
|
||||
console.log(`Server ready at ${url}`);
|
||||
});*/
|
||||
@@ -0,0 +1,18 @@
|
||||
const mongoose = require("mongoose");
|
||||
const uniqueValidator = require("mongoose-unique-validator");
|
||||
|
||||
const schema = mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
minlength: 5,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
born: {
|
||||
type: Number,
|
||||
},
|
||||
});
|
||||
|
||||
schema.plugin(uniqueValidator);
|
||||
|
||||
module.exports = mongoose.model("Author", schema);
|
||||
@@ -0,0 +1,26 @@
|
||||
const mongoose = require("mongoose");
|
||||
const uniqueValidator = require("mongoose-unique-validator");
|
||||
|
||||
const schema = mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
minlength: 5,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
published: {
|
||||
type: Number,
|
||||
},
|
||||
author: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Author",
|
||||
},
|
||||
genres: [
|
||||
{
|
||||
type: String,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
schema.plugin(uniqueValidator);
|
||||
module.exports = mongoose.model("Book", schema);
|
||||
@@ -0,0 +1,19 @@
|
||||
const mongoose = require("mongoose");
|
||||
const uniqueValidator = require("mongoose-unique-validator");
|
||||
|
||||
const schema = mongoose.Schema({
|
||||
username: {
|
||||
type: String,
|
||||
minlength: 5,
|
||||
required: true,
|
||||
unique: true,
|
||||
},
|
||||
favoriteGenre: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
schema.plugin(uniqueValidator);
|
||||
|
||||
module.exports = mongoose.model("User", schema);
|
||||
Generated
+3647
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "y",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "nodemon index.js"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@apollo/server": "^4.7.4",
|
||||
"@graphql-tools/schema": "^10.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"graphql": "^16.7.0",
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"graphql-ws": "^5.14.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"mongoose": "^7.3.1",
|
||||
"mongoose-unique-validator": "^4.0.0",
|
||||
"uuid": "^9.0.0",
|
||||
"ws": "^8.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.22"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
const { GraphQLError } = require("graphql");
|
||||
const { PubSub } = require("graphql-subscriptions");
|
||||
const Author = require("./models/author");
|
||||
const Book = require("./models/book");
|
||||
const User = require("./models/user");
|
||||
|
||||
const pubsub = new PubSub();
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
authorCount: (root, args) => Author.collection.countDocuments(),
|
||||
bookCount: (root, args) => Book.collection.countDocuments(),
|
||||
authors: async (root, args) => {
|
||||
return await Author.find({});
|
||||
},
|
||||
books: async (root, args) => {
|
||||
try {
|
||||
if (!args.genre && !args.author)
|
||||
return await Book.find({}).populate("author");
|
||||
if (args.author) {
|
||||
const author = await Author.findOne({ name: args.author });
|
||||
return await Book.find({ author: author._id }).populate("author");
|
||||
}
|
||||
return await Book.find({ genres: args.genre }).populate("author");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new GraphQLError("error quering books", {
|
||||
extensions: {
|
||||
code: "BAD_USER_INPUT",
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
me: (root, args, context) => context.currentUser,
|
||||
},
|
||||
Mutation: {
|
||||
addBook: async (root, args, context) => {
|
||||
try {
|
||||
if (!context.currentUser) throw new GraphQLError("User not authorized");
|
||||
let author = await Author.findOne({ name: args.author });
|
||||
if (!author) {
|
||||
const newAuthor = new Author({ name: args.author });
|
||||
author = await newAuthor.save();
|
||||
}
|
||||
const book = new Book({ ...args, author: author._id });
|
||||
await book.save();
|
||||
pubsub.publish("BOOK_ADDED", { bookAdded: book });
|
||||
return await Book.findOne({ title: book.title }).populate("author");
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
addAuthor: async (root, args) => {
|
||||
const author = new Author({ ...args });
|
||||
try {
|
||||
return await author.save();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
},
|
||||
editAuthor: async (root, { name, born }, context) => {
|
||||
if (!context.currentUser) throw new GraphQLError("User not authorized");
|
||||
const author = await Author.findOne({ name });
|
||||
author.born = born;
|
||||
return await author.save();
|
||||
},
|
||||
createUser: async (root, args) => {
|
||||
const user = new User({
|
||||
username: args.username,
|
||||
favoriteGenre: args.favoriteGenre,
|
||||
});
|
||||
return user.save();
|
||||
},
|
||||
login: async (root, { username, password }) => {
|
||||
const user = await User.findOne({ username });
|
||||
if (!user || password !== "secret") {
|
||||
throw new GraphQLError("wrong credentials", {
|
||||
extensions: {
|
||||
code: "BAD_USER_INPUT",
|
||||
},
|
||||
});
|
||||
}
|
||||
const userForToken = {
|
||||
username: user.username,
|
||||
id: user._id,
|
||||
};
|
||||
|
||||
return { value: jwt.sign(userForToken, process.env.JWT_SECRET) };
|
||||
},
|
||||
},
|
||||
Author: {
|
||||
bookCount: async (root) => {
|
||||
return await Book.count({ author: root._id }).populate("author");
|
||||
},
|
||||
},
|
||||
Subscription: {
|
||||
bookAdded: {
|
||||
subscribe: () => pubsub.asyncIterator("BOOK_ADDED"),
|
||||
},
|
||||
},
|
||||
};
|
||||
module.exports = resolvers;
|
||||
@@ -0,0 +1,50 @@
|
||||
const typeDefs = `
|
||||
type User {
|
||||
username: String!
|
||||
favoriteGenre: String!
|
||||
id: ID!
|
||||
}
|
||||
type Token {
|
||||
value: String!
|
||||
}
|
||||
type Author {
|
||||
name: String!
|
||||
born: Int
|
||||
id: ID!
|
||||
bookCount: Int!
|
||||
}
|
||||
type Book {
|
||||
title: String!
|
||||
published: Int
|
||||
id: ID!
|
||||
author: Author!
|
||||
genres: [String]
|
||||
}
|
||||
|
||||
type Query {
|
||||
authorCount: Int!
|
||||
bookCount: Int!
|
||||
books(genre:String, author:String): [Book]!
|
||||
authors: [Author]!
|
||||
me: User
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addBook(
|
||||
title: String!,
|
||||
author: String!,
|
||||
published: Int!,
|
||||
genres: [String!]!): Book!
|
||||
editAuthor(born: Int!,name: String!): Author!
|
||||
addAuthor(name: String!, born: Int): Author!
|
||||
createUser(username: String! favoriteGenre: String!): User
|
||||
login(username: String! password: String!): Token
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
bookAdded: Book!
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
module.exports = typeDefs;
|
||||
Reference in New Issue
Block a user