akarshanxyz 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/a11/q1.txt +266 -0
- package/a12/(NestedObjectPractice)graphql.txt +85 -0
- package/a12/CustomerSupportSystem(graphql).txt +313 -0
- package/a12/GraphQLReactFrontend.txt +363 -0
- package/a12/StudentInformationSystem(graphql).txt +69 -0
- package/a13/BookStoreManagementSystem.txt +236 -0
- package/package.json +2 -2
- /package/a1/{array → array.txt} +0 -0
package/a11/q1.txt
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const http = require("http");
|
|
3
|
+
const { Server } = require("socket.io");
|
|
4
|
+
|
|
5
|
+
const app = express();
|
|
6
|
+
const server = http.createServer(app);
|
|
7
|
+
const io = new Server(server);
|
|
8
|
+
|
|
9
|
+
let connectedUsers = 0;
|
|
10
|
+
|
|
11
|
+
app.get("/", (req, res) => {
|
|
12
|
+
res.send(`
|
|
13
|
+
<!DOCTYPE html>
|
|
14
|
+
<html>
|
|
15
|
+
<head>
|
|
16
|
+
<title>Real-Time Chat App</title>
|
|
17
|
+
<script src="/socket.io/socket.io.js"></script>
|
|
18
|
+
<style>
|
|
19
|
+
body{
|
|
20
|
+
font-family:Arial;
|
|
21
|
+
margin:20px;
|
|
22
|
+
}
|
|
23
|
+
nav button{
|
|
24
|
+
margin-right:10px;
|
|
25
|
+
padding:8px 15px;
|
|
26
|
+
}
|
|
27
|
+
.page{
|
|
28
|
+
display:none;
|
|
29
|
+
margin-top:20px;
|
|
30
|
+
}
|
|
31
|
+
.active{
|
|
32
|
+
display:block;
|
|
33
|
+
}
|
|
34
|
+
input{
|
|
35
|
+
margin:5px;
|
|
36
|
+
padding:5px;
|
|
37
|
+
}
|
|
38
|
+
#messages,#roomMessages{
|
|
39
|
+
border:1px solid black;
|
|
40
|
+
height:200px;
|
|
41
|
+
overflow-y:auto;
|
|
42
|
+
padding:10px;
|
|
43
|
+
margin-top:10px;
|
|
44
|
+
}
|
|
45
|
+
</style>
|
|
46
|
+
</head>
|
|
47
|
+
<body>
|
|
48
|
+
|
|
49
|
+
<h1>Real-Time Chat Application</h1>
|
|
50
|
+
|
|
51
|
+
<nav>
|
|
52
|
+
<button onclick="showPage('home')">Home</button>
|
|
53
|
+
<button onclick="showPage('private')">Private Chat</button>
|
|
54
|
+
<button onclick="showPage('room')">Room Chat</button>
|
|
55
|
+
</nav>
|
|
56
|
+
|
|
57
|
+
<!-- HOME -->
|
|
58
|
+
<div id="home" class="page active">
|
|
59
|
+
<h2>Home</h2>
|
|
60
|
+
|
|
61
|
+
<p><b>Your Socket ID:</b></p>
|
|
62
|
+
<p id="socketId"></p>
|
|
63
|
+
|
|
64
|
+
<p><b>Connected Users:</b></p>
|
|
65
|
+
<p id="userCount">0</p>
|
|
66
|
+
|
|
67
|
+
<h3>Notifications</h3>
|
|
68
|
+
<div id="notifications"></div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- PRIVATE CHAT -->
|
|
72
|
+
<div id="private" class="page">
|
|
73
|
+
<h2>Private Chat</h2>
|
|
74
|
+
|
|
75
|
+
<input id="receiverId" placeholder="Receiver Socket ID">
|
|
76
|
+
|
|
77
|
+
<input id="privateMessage" placeholder="Message">
|
|
78
|
+
|
|
79
|
+
<button onclick="sendPrivateMessage()">
|
|
80
|
+
Send
|
|
81
|
+
</button>
|
|
82
|
+
|
|
83
|
+
<div id="messages"></div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<!-- ROOM CHAT -->
|
|
87
|
+
<div id="room" class="page">
|
|
88
|
+
<h2>Room Chat</h2>
|
|
89
|
+
|
|
90
|
+
<input id="roomName" placeholder="Room Name">
|
|
91
|
+
|
|
92
|
+
<button onclick="joinRoom()">
|
|
93
|
+
Join Room
|
|
94
|
+
</button>
|
|
95
|
+
|
|
96
|
+
<br>
|
|
97
|
+
|
|
98
|
+
<input id="roomMessage" placeholder="Room Message">
|
|
99
|
+
|
|
100
|
+
<button onclick="sendRoomMessage()">
|
|
101
|
+
Send
|
|
102
|
+
</button>
|
|
103
|
+
|
|
104
|
+
<div id="roomMessages"></div>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<script>
|
|
108
|
+
|
|
109
|
+
const socket = io();
|
|
110
|
+
|
|
111
|
+
let currentRoom = "";
|
|
112
|
+
|
|
113
|
+
function showPage(page){
|
|
114
|
+
document.querySelectorAll(".page")
|
|
115
|
+
.forEach(p => p.classList.remove("active"));
|
|
116
|
+
|
|
117
|
+
document
|
|
118
|
+
.getElementById(page)
|
|
119
|
+
.classList.add("active");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
socket.on("connect",()=>{
|
|
123
|
+
document.getElementById("socketId").innerText = socket.id;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
socket.on("userCount",(count)=>{
|
|
127
|
+
document.getElementById("userCount").innerText = count;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
socket.on("welcome",(msg)=>{
|
|
131
|
+
const div = document.createElement("div");
|
|
132
|
+
div.innerText = msg;
|
|
133
|
+
document
|
|
134
|
+
.getElementById("notifications")
|
|
135
|
+
.appendChild(div);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
function sendPrivateMessage(){
|
|
139
|
+
|
|
140
|
+
const receiver =
|
|
141
|
+
document.getElementById("receiverId").value;
|
|
142
|
+
|
|
143
|
+
const message =
|
|
144
|
+
document.getElementById("privateMessage").value;
|
|
145
|
+
|
|
146
|
+
socket.emit("privateMessage",{
|
|
147
|
+
receiver,
|
|
148
|
+
message
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
socket.on("privateMessage",(data)=>{
|
|
153
|
+
|
|
154
|
+
const div = document.createElement("div");
|
|
155
|
+
|
|
156
|
+
div.innerText =
|
|
157
|
+
data.sender + ": " + data.message;
|
|
158
|
+
|
|
159
|
+
document
|
|
160
|
+
.getElementById("messages")
|
|
161
|
+
.appendChild(div);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
function joinRoom(){
|
|
165
|
+
|
|
166
|
+
currentRoom =
|
|
167
|
+
document.getElementById("roomName").value;
|
|
168
|
+
|
|
169
|
+
socket.emit("joinRoom", currentRoom);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function sendRoomMessage(){
|
|
173
|
+
|
|
174
|
+
const msg =
|
|
175
|
+
document.getElementById("roomMessage").value;
|
|
176
|
+
|
|
177
|
+
socket.emit("roomMessage",{
|
|
178
|
+
room: currentRoom,
|
|
179
|
+
message: msg
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
socket.on("roomMessage",(data)=>{
|
|
184
|
+
|
|
185
|
+
const div = document.createElement("div");
|
|
186
|
+
|
|
187
|
+
div.innerText =
|
|
188
|
+
data.sender + ": " + data.message;
|
|
189
|
+
|
|
190
|
+
document
|
|
191
|
+
.getElementById("roomMessages")
|
|
192
|
+
.appendChild(div);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
socket.on("roomNotification",(msg)=>{
|
|
196
|
+
|
|
197
|
+
const div = document.createElement("div");
|
|
198
|
+
|
|
199
|
+
div.innerText = msg;
|
|
200
|
+
|
|
201
|
+
document
|
|
202
|
+
.getElementById("roomMessages")
|
|
203
|
+
.appendChild(div);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
</script>
|
|
207
|
+
|
|
208
|
+
</body>
|
|
209
|
+
</html>
|
|
210
|
+
`);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
io.on("connection", (socket) => {
|
|
214
|
+
|
|
215
|
+
connectedUsers++;
|
|
216
|
+
|
|
217
|
+
io.emit("userCount", connectedUsers);
|
|
218
|
+
|
|
219
|
+
io.emit(
|
|
220
|
+
"welcome",
|
|
221
|
+
"User joined: " + socket.id
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
socket.on("privateMessage", (data) => {
|
|
225
|
+
|
|
226
|
+
io.to(data.receiver).emit(
|
|
227
|
+
"privateMessage",
|
|
228
|
+
{
|
|
229
|
+
sender: socket.id,
|
|
230
|
+
message: data.message
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
socket.on("joinRoom", (room) => {
|
|
236
|
+
|
|
237
|
+
socket.join(room);
|
|
238
|
+
|
|
239
|
+
socket.to(room).emit(
|
|
240
|
+
"roomNotification",
|
|
241
|
+
socket.id + " joined room " + room
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
socket.on("roomMessage", (data) => {
|
|
246
|
+
|
|
247
|
+
io.to(data.room).emit(
|
|
248
|
+
"roomMessage",
|
|
249
|
+
{
|
|
250
|
+
sender: socket.id,
|
|
251
|
+
message: data.message
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
socket.on("disconnect", () => {
|
|
257
|
+
|
|
258
|
+
connectedUsers--;
|
|
259
|
+
|
|
260
|
+
io.emit("userCount", connectedUsers);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
server.listen(3000, () => {
|
|
265
|
+
console.log("Server running on port 3000");
|
|
266
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { graphqlHTTP } from "express-graphql";
|
|
3
|
+
import {
|
|
4
|
+
GraphQLObjectType,
|
|
5
|
+
GraphQLSchema,
|
|
6
|
+
GraphQLString,
|
|
7
|
+
GraphQLInt
|
|
8
|
+
} from "graphql";
|
|
9
|
+
|
|
10
|
+
/* ---------------- Dummy Data ---------------- */
|
|
11
|
+
|
|
12
|
+
const user = {
|
|
13
|
+
name: "Amit Sharma",
|
|
14
|
+
age: 21,
|
|
15
|
+
course: {
|
|
16
|
+
courseName: "Full Stack Development",
|
|
17
|
+
duration: "6 Months"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/* ---------------- Course Type ---------------- */
|
|
22
|
+
|
|
23
|
+
const CourseType = new GraphQLObjectType({
|
|
24
|
+
name: "Course",
|
|
25
|
+
fields: () => ({
|
|
26
|
+
courseName: { type: GraphQLString },
|
|
27
|
+
duration: { type: GraphQLString }
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/* ---------------- User Type ---------------- */
|
|
32
|
+
|
|
33
|
+
const UserType = new GraphQLObjectType({
|
|
34
|
+
name: "User",
|
|
35
|
+
fields: () => ({
|
|
36
|
+
name: { type: GraphQLString },
|
|
37
|
+
age: { type: GraphQLInt },
|
|
38
|
+
|
|
39
|
+
// Nested Object
|
|
40
|
+
course: {
|
|
41
|
+
type: CourseType,
|
|
42
|
+
resolve(parent) {
|
|
43
|
+
return parent.course;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/* ---------------- Root Query ---------------- */
|
|
50
|
+
|
|
51
|
+
const RootQuery = new GraphQLObjectType({
|
|
52
|
+
name: "Query",
|
|
53
|
+
fields: {
|
|
54
|
+
user: {
|
|
55
|
+
type: UserType,
|
|
56
|
+
resolve() {
|
|
57
|
+
return user;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/* ---------------- Schema ---------------- */
|
|
64
|
+
|
|
65
|
+
const schema = new GraphQLSchema({
|
|
66
|
+
query: RootQuery
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
/* ---------------- Server ---------------- */
|
|
70
|
+
|
|
71
|
+
const app = express();
|
|
72
|
+
|
|
73
|
+
app.use(
|
|
74
|
+
"/graphql",
|
|
75
|
+
graphqlHTTP({
|
|
76
|
+
schema,
|
|
77
|
+
graphiql: true
|
|
78
|
+
})
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
app.listen(4000, () => {
|
|
82
|
+
console.log(
|
|
83
|
+
"Server running at http://localhost:4000/graphql"
|
|
84
|
+
);
|
|
85
|
+
});
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import graphql from "graphql";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
GraphQLObjectType,
|
|
5
|
+
GraphQLSchema,
|
|
6
|
+
GraphQLInt,
|
|
7
|
+
GraphQLString,
|
|
8
|
+
GraphQLList
|
|
9
|
+
} = graphql;
|
|
10
|
+
|
|
11
|
+
/* ------------------ Dummy Data ------------------ */
|
|
12
|
+
|
|
13
|
+
const users = [
|
|
14
|
+
{
|
|
15
|
+
id: 1,
|
|
16
|
+
name: "Amit Sharma",
|
|
17
|
+
email: "amit@gmail.com",
|
|
18
|
+
city: "Delhi"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: 2,
|
|
22
|
+
name: "Priya Verma",
|
|
23
|
+
email: "priya@gmail.com",
|
|
24
|
+
city: "Mumbai"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 3,
|
|
28
|
+
name: "Rahul Mehta",
|
|
29
|
+
email: "rahul@gmail.com",
|
|
30
|
+
city: "Bangalore"
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const queries = [
|
|
35
|
+
{
|
|
36
|
+
id: 1,
|
|
37
|
+
userId: 1,
|
|
38
|
+
title: "How to reset password?"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 2,
|
|
42
|
+
userId: 1,
|
|
43
|
+
title: "Unable to update profile"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 3,
|
|
47
|
+
userId: 2,
|
|
48
|
+
title: "Login authentication issue"
|
|
49
|
+
}
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
/* ------------------ Types ------------------ */
|
|
53
|
+
|
|
54
|
+
const QueryType = new GraphQLObjectType({
|
|
55
|
+
name: "SupportQuery",
|
|
56
|
+
fields: () => ({
|
|
57
|
+
id: { type: GraphQLInt },
|
|
58
|
+
userId: { type: GraphQLInt },
|
|
59
|
+
title: { type: GraphQLString }
|
|
60
|
+
})
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const UserType = new GraphQLObjectType({
|
|
64
|
+
name: "User",
|
|
65
|
+
fields: () => ({
|
|
66
|
+
id: { type: GraphQLInt },
|
|
67
|
+
name: { type: GraphQLString },
|
|
68
|
+
email: { type: GraphQLString },
|
|
69
|
+
city: { type: GraphQLString },
|
|
70
|
+
|
|
71
|
+
// Task 6
|
|
72
|
+
queries: {
|
|
73
|
+
type: new GraphQLList(QueryType),
|
|
74
|
+
resolve(parent) {
|
|
75
|
+
return queries.filter(q => q.userId === parent.id);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const UserQueryCountType = new GraphQLObjectType({
|
|
82
|
+
name: "UserQueryCount",
|
|
83
|
+
fields: () => ({
|
|
84
|
+
name: { type: GraphQLString },
|
|
85
|
+
totalQueries: { type: GraphQLInt }
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/* ------------------ Root Query ------------------ */
|
|
90
|
+
|
|
91
|
+
const RootQuery = new GraphQLObjectType({
|
|
92
|
+
name: "Query",
|
|
93
|
+
fields: {
|
|
94
|
+
// Task 2
|
|
95
|
+
users: {
|
|
96
|
+
type: new GraphQLList(UserType),
|
|
97
|
+
resolve() {
|
|
98
|
+
return users;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// Task 3
|
|
103
|
+
user: {
|
|
104
|
+
type: UserType,
|
|
105
|
+
args: {
|
|
106
|
+
id: { type: GraphQLInt }
|
|
107
|
+
},
|
|
108
|
+
resolve(_, args) {
|
|
109
|
+
return users.find(user => user.id === args.id);
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
// Task 4
|
|
114
|
+
supportQueries: {
|
|
115
|
+
type: new GraphQLList(QueryType),
|
|
116
|
+
resolve() {
|
|
117
|
+
return queries;
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// Task 5
|
|
122
|
+
usersByCity: {
|
|
123
|
+
type: new GraphQLList(UserType),
|
|
124
|
+
args: {
|
|
125
|
+
city: { type: GraphQLString }
|
|
126
|
+
},
|
|
127
|
+
resolve(_, args) {
|
|
128
|
+
return users.filter(
|
|
129
|
+
user =>
|
|
130
|
+
user.city.toLowerCase() === args.city.toLowerCase()
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
// Task 13
|
|
136
|
+
totalUsers: {
|
|
137
|
+
type: GraphQLInt,
|
|
138
|
+
resolve() {
|
|
139
|
+
return users.length;
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Task 14
|
|
144
|
+
totalSupportQueries: {
|
|
145
|
+
type: GraphQLInt,
|
|
146
|
+
resolve() {
|
|
147
|
+
return queries.length;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// Task 15
|
|
152
|
+
searchUser: {
|
|
153
|
+
type: new GraphQLList(UserType),
|
|
154
|
+
args: {
|
|
155
|
+
name: { type: GraphQLString }
|
|
156
|
+
},
|
|
157
|
+
resolve(_, args) {
|
|
158
|
+
return users.filter(user =>
|
|
159
|
+
user.name
|
|
160
|
+
.toLowerCase()
|
|
161
|
+
.includes(args.name.toLowerCase())
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
// Task 16
|
|
167
|
+
usersWithQueryCount: {
|
|
168
|
+
type: new GraphQLList(UserQueryCountType),
|
|
169
|
+
resolve() {
|
|
170
|
+
return users.map(user => ({
|
|
171
|
+
name: user.name,
|
|
172
|
+
totalQueries: queries.filter(
|
|
173
|
+
q => q.userId === user.id
|
|
174
|
+
).length
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
/* ------------------ Mutations ------------------ */
|
|
182
|
+
|
|
183
|
+
const Mutation = new GraphQLObjectType({
|
|
184
|
+
name: "Mutation",
|
|
185
|
+
fields: {
|
|
186
|
+
// Task 7
|
|
187
|
+
addUser: {
|
|
188
|
+
type: UserType,
|
|
189
|
+
args: {
|
|
190
|
+
name: { type: GraphQLString },
|
|
191
|
+
email: { type: GraphQLString },
|
|
192
|
+
city: { type: GraphQLString }
|
|
193
|
+
},
|
|
194
|
+
resolve(_, args) {
|
|
195
|
+
const user = {
|
|
196
|
+
id: users.length + 1,
|
|
197
|
+
name: args.name,
|
|
198
|
+
email: args.email,
|
|
199
|
+
city: args.city
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
users.push(user);
|
|
203
|
+
return user;
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
// Task 8
|
|
208
|
+
addSupportQuery: {
|
|
209
|
+
type: QueryType,
|
|
210
|
+
args: {
|
|
211
|
+
userId: { type: GraphQLInt },
|
|
212
|
+
title: { type: GraphQLString }
|
|
213
|
+
},
|
|
214
|
+
resolve(_, args) {
|
|
215
|
+
const query = {
|
|
216
|
+
id: queries.length + 1,
|
|
217
|
+
userId: args.userId,
|
|
218
|
+
title: args.title
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
queries.push(query);
|
|
222
|
+
return query;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
// Task 9
|
|
227
|
+
updateUserCity: {
|
|
228
|
+
type: UserType,
|
|
229
|
+
args: {
|
|
230
|
+
id: { type: GraphQLInt },
|
|
231
|
+
city: { type: GraphQLString }
|
|
232
|
+
},
|
|
233
|
+
resolve(_, args) {
|
|
234
|
+
const user = users.find(
|
|
235
|
+
user => user.id === args.id
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
if (user) {
|
|
239
|
+
user.city = args.city;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return user;
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
// Task 10
|
|
247
|
+
updateUserEmail: {
|
|
248
|
+
type: UserType,
|
|
249
|
+
args: {
|
|
250
|
+
id: { type: GraphQLInt },
|
|
251
|
+
email: { type: GraphQLString }
|
|
252
|
+
},
|
|
253
|
+
resolve(_, args) {
|
|
254
|
+
const user = users.find(
|
|
255
|
+
user => user.id === args.id
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (user) {
|
|
259
|
+
user.email = args.email;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return user;
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
// Task 11
|
|
267
|
+
deleteUser: {
|
|
268
|
+
type: UserType,
|
|
269
|
+
args: {
|
|
270
|
+
id: { type: GraphQLInt }
|
|
271
|
+
},
|
|
272
|
+
resolve(_, args) {
|
|
273
|
+
const index = users.findIndex(
|
|
274
|
+
user => user.id === args.id
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
if (index === -1) return null;
|
|
278
|
+
|
|
279
|
+
const deletedUser = users[index];
|
|
280
|
+
users.splice(index, 1);
|
|
281
|
+
|
|
282
|
+
return deletedUser;
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
// Task 12
|
|
287
|
+
deleteSupportQuery: {
|
|
288
|
+
type: QueryType,
|
|
289
|
+
args: {
|
|
290
|
+
id: { type: GraphQLInt }
|
|
291
|
+
},
|
|
292
|
+
resolve(_, args) {
|
|
293
|
+
const index = queries.findIndex(
|
|
294
|
+
query => query.id === args.id
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
if (index === -1) return null;
|
|
298
|
+
|
|
299
|
+
const deletedQuery = queries[index];
|
|
300
|
+
queries.splice(index, 1);
|
|
301
|
+
|
|
302
|
+
return deletedQuery;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
/* ------------------ Schema ------------------ */
|
|
309
|
+
|
|
310
|
+
export default new GraphQLSchema({
|
|
311
|
+
query: RootQuery,
|
|
312
|
+
mutation: Mutation
|
|
313
|
+
});
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
ApolloClient,
|
|
4
|
+
InMemoryCache,
|
|
5
|
+
ApolloProvider,
|
|
6
|
+
gql,
|
|
7
|
+
useQuery,
|
|
8
|
+
useMutation,
|
|
9
|
+
} from "@apollo/client";
|
|
10
|
+
|
|
11
|
+
/* ---------------- Apollo Setup ---------------- */
|
|
12
|
+
|
|
13
|
+
const client = new ApolloClient({
|
|
14
|
+
uri: "http://localhost:4000/graphql",
|
|
15
|
+
cache: new InMemoryCache(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/* ---------------- GraphQL Queries ---------------- */
|
|
19
|
+
|
|
20
|
+
const GET_PRODUCTS = gql`
|
|
21
|
+
query {
|
|
22
|
+
products {
|
|
23
|
+
id
|
|
24
|
+
title
|
|
25
|
+
price
|
|
26
|
+
category
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
const GET_PRODUCT = gql`
|
|
32
|
+
query ($id: Int!) {
|
|
33
|
+
product(id: $id) {
|
|
34
|
+
id
|
|
35
|
+
title
|
|
36
|
+
price
|
|
37
|
+
category
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
|
|
42
|
+
const GET_PRODUCTS_BY_CATEGORY = gql`
|
|
43
|
+
query ($category: String!) {
|
|
44
|
+
productsByCategory(category: $category) {
|
|
45
|
+
id
|
|
46
|
+
title
|
|
47
|
+
price
|
|
48
|
+
category
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
52
|
+
|
|
53
|
+
const TOTAL_PRODUCTS = gql`
|
|
54
|
+
query {
|
|
55
|
+
totalProducts
|
|
56
|
+
}
|
|
57
|
+
`;
|
|
58
|
+
|
|
59
|
+
/* ---------------- Mutations ---------------- */
|
|
60
|
+
|
|
61
|
+
const ADD_PRODUCT = gql`
|
|
62
|
+
mutation (
|
|
63
|
+
$title: String!
|
|
64
|
+
$price: Int!
|
|
65
|
+
$category: String!
|
|
66
|
+
) {
|
|
67
|
+
addProduct(
|
|
68
|
+
title: $title
|
|
69
|
+
price: $price
|
|
70
|
+
category: $category
|
|
71
|
+
) {
|
|
72
|
+
id
|
|
73
|
+
title
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
77
|
+
|
|
78
|
+
const UPDATE_PRICE = gql`
|
|
79
|
+
mutation ($id: Int!, $price: Int!) {
|
|
80
|
+
updateProductPrice(id: $id, price: $price) {
|
|
81
|
+
id
|
|
82
|
+
title
|
|
83
|
+
price
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
`;
|
|
87
|
+
|
|
88
|
+
const DELETE_PRODUCT = gql`
|
|
89
|
+
mutation ($id: Int!) {
|
|
90
|
+
deleteProduct(id: $id) {
|
|
91
|
+
id
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
`;
|
|
95
|
+
|
|
96
|
+
/* ---------------- Main Component ---------------- */
|
|
97
|
+
|
|
98
|
+
function ProductManager() {
|
|
99
|
+
const [productId, setProductId] = useState("");
|
|
100
|
+
const [categorySearch, setCategorySearch] = useState("");
|
|
101
|
+
|
|
102
|
+
const [title, setTitle] = useState("");
|
|
103
|
+
const [price, setPrice] = useState("");
|
|
104
|
+
const [category, setCategory] = useState("");
|
|
105
|
+
|
|
106
|
+
const [updateId, setUpdateId] = useState("");
|
|
107
|
+
const [newPrice, setNewPrice] = useState("");
|
|
108
|
+
|
|
109
|
+
/* Task 1 */
|
|
110
|
+
const {
|
|
111
|
+
loading,
|
|
112
|
+
error,
|
|
113
|
+
data,
|
|
114
|
+
refetch,
|
|
115
|
+
} = useQuery(GET_PRODUCTS);
|
|
116
|
+
|
|
117
|
+
/* Task 2 */
|
|
118
|
+
const {
|
|
119
|
+
data: singleProduct,
|
|
120
|
+
refetch: fetchSingleProduct,
|
|
121
|
+
} = useQuery(GET_PRODUCT, {
|
|
122
|
+
variables: { id: Number(productId) || 1 },
|
|
123
|
+
skip: true,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/* Task 3 */
|
|
127
|
+
const {
|
|
128
|
+
data: categoryProducts,
|
|
129
|
+
refetch: searchProducts,
|
|
130
|
+
} = useQuery(GET_PRODUCTS_BY_CATEGORY, {
|
|
131
|
+
variables: { category: categorySearch },
|
|
132
|
+
skip: true,
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
/* Task 7 */
|
|
136
|
+
const { data: totalData } = useQuery(TOTAL_PRODUCTS);
|
|
137
|
+
|
|
138
|
+
/* Task 4 */
|
|
139
|
+
const [addProduct] = useMutation(ADD_PRODUCT);
|
|
140
|
+
|
|
141
|
+
/* Task 5 */
|
|
142
|
+
const [updateProductPrice] =
|
|
143
|
+
useMutation(UPDATE_PRICE);
|
|
144
|
+
|
|
145
|
+
/* Task 6 */
|
|
146
|
+
const [deleteProduct] =
|
|
147
|
+
useMutation(DELETE_PRODUCT);
|
|
148
|
+
|
|
149
|
+
/* Loading & Error Handling */
|
|
150
|
+
if (loading) return <h2>Loading...</h2>;
|
|
151
|
+
if (error)
|
|
152
|
+
return <h2>Something went wrong!</h2>;
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<div style={{ padding: "20px" }}>
|
|
156
|
+
<h1>Product Management</h1>
|
|
157
|
+
|
|
158
|
+
{/* Task 7 */}
|
|
159
|
+
<h2>
|
|
160
|
+
Total Products: {totalData?.totalProducts}
|
|
161
|
+
</h2>
|
|
162
|
+
|
|
163
|
+
{/* Task 1 */}
|
|
164
|
+
<h2>All Products</h2>
|
|
165
|
+
|
|
166
|
+
{data.products.map((product) => (
|
|
167
|
+
<div
|
|
168
|
+
key={product.id}
|
|
169
|
+
style={{
|
|
170
|
+
border: "1px solid black",
|
|
171
|
+
padding: "10px",
|
|
172
|
+
margin: "10px",
|
|
173
|
+
}}
|
|
174
|
+
>
|
|
175
|
+
<h3>{product.title}</h3>
|
|
176
|
+
<p>₹{product.price}</p>
|
|
177
|
+
<p>{product.category}</p>
|
|
178
|
+
|
|
179
|
+
{/* Task 6 */}
|
|
180
|
+
<button
|
|
181
|
+
onClick={async () => {
|
|
182
|
+
await deleteProduct({
|
|
183
|
+
variables: {
|
|
184
|
+
id: product.id,
|
|
185
|
+
},
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
refetch(); // Task 9
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
Delete
|
|
192
|
+
</button>
|
|
193
|
+
</div>
|
|
194
|
+
))}
|
|
195
|
+
|
|
196
|
+
<hr />
|
|
197
|
+
|
|
198
|
+
{/* Task 2 */}
|
|
199
|
+
<h2>Get Product Details</h2>
|
|
200
|
+
|
|
201
|
+
<input
|
|
202
|
+
type="number"
|
|
203
|
+
placeholder="Enter Product ID"
|
|
204
|
+
value={productId}
|
|
205
|
+
onChange={(e) =>
|
|
206
|
+
setProductId(e.target.value)
|
|
207
|
+
}
|
|
208
|
+
/>
|
|
209
|
+
|
|
210
|
+
<button
|
|
211
|
+
onClick={() =>
|
|
212
|
+
fetchSingleProduct({
|
|
213
|
+
id: Number(productId),
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
>
|
|
217
|
+
Get Product Details
|
|
218
|
+
</button>
|
|
219
|
+
|
|
220
|
+
{singleProduct?.product && (
|
|
221
|
+
<div>
|
|
222
|
+
<h3>
|
|
223
|
+
{singleProduct.product.title}
|
|
224
|
+
</h3>
|
|
225
|
+
<p>
|
|
226
|
+
₹{singleProduct.product.price}
|
|
227
|
+
</p>
|
|
228
|
+
<p>
|
|
229
|
+
{singleProduct.product.category}
|
|
230
|
+
</p>
|
|
231
|
+
</div>
|
|
232
|
+
)}
|
|
233
|
+
|
|
234
|
+
<hr />
|
|
235
|
+
|
|
236
|
+
{/* Task 3 */}
|
|
237
|
+
<h2>Search By Category</h2>
|
|
238
|
+
|
|
239
|
+
<input
|
|
240
|
+
type="text"
|
|
241
|
+
placeholder="Electronics"
|
|
242
|
+
value={categorySearch}
|
|
243
|
+
onChange={(e) =>
|
|
244
|
+
setCategorySearch(e.target.value)
|
|
245
|
+
}
|
|
246
|
+
/>
|
|
247
|
+
|
|
248
|
+
<button
|
|
249
|
+
onClick={() =>
|
|
250
|
+
searchProducts({
|
|
251
|
+
category: categorySearch,
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
>
|
|
255
|
+
Search
|
|
256
|
+
</button>
|
|
257
|
+
|
|
258
|
+
{categoryProducts?.productsByCategory?.map(
|
|
259
|
+
(product) => (
|
|
260
|
+
<div key={product.id}>
|
|
261
|
+
<p>
|
|
262
|
+
{product.title} - ₹{product.price}
|
|
263
|
+
</p>
|
|
264
|
+
</div>
|
|
265
|
+
)
|
|
266
|
+
)}
|
|
267
|
+
|
|
268
|
+
<hr />
|
|
269
|
+
|
|
270
|
+
{/* Task 4 */}
|
|
271
|
+
<h2>Add Product</h2>
|
|
272
|
+
|
|
273
|
+
<input
|
|
274
|
+
placeholder="Title"
|
|
275
|
+
value={title}
|
|
276
|
+
onChange={(e) =>
|
|
277
|
+
setTitle(e.target.value)
|
|
278
|
+
}
|
|
279
|
+
/>
|
|
280
|
+
|
|
281
|
+
<input
|
|
282
|
+
placeholder="Price"
|
|
283
|
+
type="number"
|
|
284
|
+
value={price}
|
|
285
|
+
onChange={(e) =>
|
|
286
|
+
setPrice(e.target.value)
|
|
287
|
+
}
|
|
288
|
+
/>
|
|
289
|
+
|
|
290
|
+
<input
|
|
291
|
+
placeholder="Category"
|
|
292
|
+
value={category}
|
|
293
|
+
onChange={(e) =>
|
|
294
|
+
setCategory(e.target.value)
|
|
295
|
+
}
|
|
296
|
+
/>
|
|
297
|
+
|
|
298
|
+
<button
|
|
299
|
+
onClick={async () => {
|
|
300
|
+
await addProduct({
|
|
301
|
+
variables: {
|
|
302
|
+
title,
|
|
303
|
+
price: Number(price),
|
|
304
|
+
category,
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
refetch(); // Task 9
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
Add Product
|
|
312
|
+
</button>
|
|
313
|
+
|
|
314
|
+
<hr />
|
|
315
|
+
|
|
316
|
+
{/* Task 5 */}
|
|
317
|
+
<h2>Update Product Price</h2>
|
|
318
|
+
|
|
319
|
+
<input
|
|
320
|
+
type="number"
|
|
321
|
+
placeholder="Product ID"
|
|
322
|
+
value={updateId}
|
|
323
|
+
onChange={(e) =>
|
|
324
|
+
setUpdateId(e.target.value)
|
|
325
|
+
}
|
|
326
|
+
/>
|
|
327
|
+
|
|
328
|
+
<input
|
|
329
|
+
type="number"
|
|
330
|
+
placeholder="New Price"
|
|
331
|
+
value={newPrice}
|
|
332
|
+
onChange={(e) =>
|
|
333
|
+
setNewPrice(e.target.value)
|
|
334
|
+
}
|
|
335
|
+
/>
|
|
336
|
+
|
|
337
|
+
<button
|
|
338
|
+
onClick={async () => {
|
|
339
|
+
await updateProductPrice({
|
|
340
|
+
variables: {
|
|
341
|
+
id: Number(updateId),
|
|
342
|
+
price: Number(newPrice),
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
refetch(); // Task 9
|
|
347
|
+
}}
|
|
348
|
+
>
|
|
349
|
+
Update Price
|
|
350
|
+
</button>
|
|
351
|
+
</div>
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/* ---------------- App ---------------- */
|
|
356
|
+
|
|
357
|
+
export default function App() {
|
|
358
|
+
return (
|
|
359
|
+
<ApolloProvider client={client}>
|
|
360
|
+
<ProductManager />
|
|
361
|
+
</ApolloProvider>
|
|
362
|
+
);
|
|
363
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { graphqlHTTP } from "express-graphql";
|
|
3
|
+
import {
|
|
4
|
+
GraphQLObjectType,
|
|
5
|
+
GraphQLSchema,
|
|
6
|
+
GraphQLString,
|
|
7
|
+
GraphQLInt
|
|
8
|
+
} from "graphql";
|
|
9
|
+
|
|
10
|
+
/* ---------------- Dummy Data ---------------- */
|
|
11
|
+
|
|
12
|
+
const student = {
|
|
13
|
+
id: 1,
|
|
14
|
+
name: "Rahul Sharma",
|
|
15
|
+
age: 20,
|
|
16
|
+
course: "Computer Science"
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/* ---------------- Student Type ---------------- */
|
|
20
|
+
|
|
21
|
+
const StudentType = new GraphQLObjectType({
|
|
22
|
+
name: "Student",
|
|
23
|
+
fields: () => ({
|
|
24
|
+
id: { type: GraphQLInt },
|
|
25
|
+
name: { type: GraphQLString },
|
|
26
|
+
age: { type: GraphQLInt },
|
|
27
|
+
course: { type: GraphQLString }
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/* ---------------- Query ---------------- */
|
|
32
|
+
|
|
33
|
+
const RootQuery = new GraphQLObjectType({
|
|
34
|
+
name: "Query",
|
|
35
|
+
fields: {
|
|
36
|
+
student: {
|
|
37
|
+
type: StudentType,
|
|
38
|
+
resolve() {
|
|
39
|
+
return student;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/* ---------------- Schema ---------------- */
|
|
46
|
+
|
|
47
|
+
const schema = new GraphQLSchema({
|
|
48
|
+
query: RootQuery
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/* ---------------- Server ---------------- */
|
|
52
|
+
|
|
53
|
+
const app = express();
|
|
54
|
+
|
|
55
|
+
app.use(
|
|
56
|
+
"/graphql",
|
|
57
|
+
graphqlHTTP({
|
|
58
|
+
schema,
|
|
59
|
+
graphiql: true
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
const PORT = 4000;
|
|
64
|
+
|
|
65
|
+
app.listen(PORT, () => {
|
|
66
|
+
console.log(
|
|
67
|
+
`Server running at http://localhost:${PORT}/graphql`
|
|
68
|
+
);
|
|
69
|
+
});
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { graphqlHTTP } from "express-graphql";
|
|
3
|
+
import {
|
|
4
|
+
GraphQLObjectType,
|
|
5
|
+
GraphQLString,
|
|
6
|
+
GraphQLInt,
|
|
7
|
+
GraphQLList,
|
|
8
|
+
GraphQLSchema
|
|
9
|
+
} from "graphql";
|
|
10
|
+
|
|
11
|
+
/* ---------------- Dummy Data ---------------- */
|
|
12
|
+
|
|
13
|
+
let authors = [
|
|
14
|
+
{
|
|
15
|
+
id: 1,
|
|
16
|
+
name: "Chetan Bhagat",
|
|
17
|
+
age: 50
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 2,
|
|
21
|
+
name: "J.K. Rowling",
|
|
22
|
+
age: 58
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
let books = [
|
|
27
|
+
{
|
|
28
|
+
id: 1,
|
|
29
|
+
title: "Five Point Someone",
|
|
30
|
+
pages: 250,
|
|
31
|
+
authorId: 1
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 2,
|
|
35
|
+
title: "Harry Potter",
|
|
36
|
+
pages: 500,
|
|
37
|
+
authorId: 2
|
|
38
|
+
}
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/* ---------------- Types ---------------- */
|
|
42
|
+
|
|
43
|
+
const AuthorType = new GraphQLObjectType({
|
|
44
|
+
name: "Author",
|
|
45
|
+
fields: () => ({
|
|
46
|
+
id: { type: GraphQLInt },
|
|
47
|
+
name: { type: GraphQLString },
|
|
48
|
+
age: { type: GraphQLInt },
|
|
49
|
+
|
|
50
|
+
books: {
|
|
51
|
+
type: new GraphQLList(BookType),
|
|
52
|
+
resolve(parent) {
|
|
53
|
+
return books.filter(
|
|
54
|
+
book => book.authorId === parent.id
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const BookType = new GraphQLObjectType({
|
|
62
|
+
name: "Book",
|
|
63
|
+
fields: () => ({
|
|
64
|
+
id: { type: GraphQLInt },
|
|
65
|
+
title: { type: GraphQLString },
|
|
66
|
+
pages: { type: GraphQLInt },
|
|
67
|
+
|
|
68
|
+
author: {
|
|
69
|
+
type: AuthorType,
|
|
70
|
+
resolve(parent) {
|
|
71
|
+
return authors.find(
|
|
72
|
+
author => author.id === parent.authorId
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/* ---------------- Queries ---------------- */
|
|
80
|
+
|
|
81
|
+
const RootQuery = new GraphQLObjectType({
|
|
82
|
+
name: "Query",
|
|
83
|
+
fields: {
|
|
84
|
+
// View all books
|
|
85
|
+
books: {
|
|
86
|
+
type: new GraphQLList(BookType),
|
|
87
|
+
resolve() {
|
|
88
|
+
return books;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
// View single book
|
|
93
|
+
book: {
|
|
94
|
+
type: BookType,
|
|
95
|
+
args: {
|
|
96
|
+
id: { type: GraphQLInt }
|
|
97
|
+
},
|
|
98
|
+
resolve(_, args) {
|
|
99
|
+
return books.find(
|
|
100
|
+
book => book.id === args.id
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
// Search by title
|
|
106
|
+
searchBook: {
|
|
107
|
+
type: new GraphQLList(BookType),
|
|
108
|
+
args: {
|
|
109
|
+
title: { type: GraphQLString }
|
|
110
|
+
},
|
|
111
|
+
resolve(_, args) {
|
|
112
|
+
return books.filter(book =>
|
|
113
|
+
book.title
|
|
114
|
+
.toLowerCase()
|
|
115
|
+
.includes(args.title.toLowerCase())
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
// View authors
|
|
121
|
+
authors: {
|
|
122
|
+
type: new GraphQLList(AuthorType),
|
|
123
|
+
resolve() {
|
|
124
|
+
return authors;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// View author details
|
|
129
|
+
author: {
|
|
130
|
+
type: AuthorType,
|
|
131
|
+
args: {
|
|
132
|
+
id: { type: GraphQLInt }
|
|
133
|
+
},
|
|
134
|
+
resolve(_, args) {
|
|
135
|
+
return authors.find(
|
|
136
|
+
author => author.id === args.id
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
/* ---------------- Mutations ---------------- */
|
|
144
|
+
|
|
145
|
+
const Mutation = new GraphQLObjectType({
|
|
146
|
+
name: "Mutation",
|
|
147
|
+
fields: {
|
|
148
|
+
// Add Book
|
|
149
|
+
addBook: {
|
|
150
|
+
type: BookType,
|
|
151
|
+
args: {
|
|
152
|
+
title: { type: GraphQLString },
|
|
153
|
+
pages: { type: GraphQLInt },
|
|
154
|
+
authorId: { type: GraphQLInt }
|
|
155
|
+
},
|
|
156
|
+
resolve(_, args) {
|
|
157
|
+
const book = {
|
|
158
|
+
id: books.length + 1,
|
|
159
|
+
title: args.title,
|
|
160
|
+
pages: args.pages,
|
|
161
|
+
authorId: args.authorId
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
books.push(book);
|
|
165
|
+
return book;
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
// Update Book
|
|
170
|
+
updateBook: {
|
|
171
|
+
type: BookType,
|
|
172
|
+
args: {
|
|
173
|
+
id: { type: GraphQLInt },
|
|
174
|
+
title: { type: GraphQLString },
|
|
175
|
+
pages: { type: GraphQLInt }
|
|
176
|
+
},
|
|
177
|
+
resolve(_, args) {
|
|
178
|
+
const book = books.find(
|
|
179
|
+
b => b.id === args.id
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
if (book) {
|
|
183
|
+
if (args.title) book.title = args.title;
|
|
184
|
+
if (args.pages) book.pages = args.pages;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return book;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
// Delete Book
|
|
192
|
+
deleteBook: {
|
|
193
|
+
type: BookType,
|
|
194
|
+
args: {
|
|
195
|
+
id: { type: GraphQLInt }
|
|
196
|
+
},
|
|
197
|
+
resolve(_, args) {
|
|
198
|
+
const index = books.findIndex(
|
|
199
|
+
book => book.id === args.id
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
if (index === -1) return null;
|
|
203
|
+
|
|
204
|
+
const deletedBook = books[index];
|
|
205
|
+
books.splice(index, 1);
|
|
206
|
+
|
|
207
|
+
return deletedBook;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
/* ---------------- Schema ---------------- */
|
|
214
|
+
|
|
215
|
+
const schema = new GraphQLSchema({
|
|
216
|
+
query: RootQuery,
|
|
217
|
+
mutation: Mutation
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
/* ---------------- Server ---------------- */
|
|
221
|
+
|
|
222
|
+
const app = express();
|
|
223
|
+
|
|
224
|
+
app.use(
|
|
225
|
+
"/graphql",
|
|
226
|
+
graphqlHTTP({
|
|
227
|
+
schema,
|
|
228
|
+
graphiql: true
|
|
229
|
+
})
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
app.listen(4000, () => {
|
|
233
|
+
console.log(
|
|
234
|
+
"Server running at http://localhost:4000/graphql"
|
|
235
|
+
);
|
|
236
|
+
});
|
package/package.json
CHANGED
/package/a1/{array → array.txt}
RENAMED
|
File without changes
|