graphql-mysql-app.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. const express = require('express');
  2. const app = express();
  3. const graphqlHTTP = require('express-graphql');
  4. const escape = require('escape-html');
  5. const dateFormat = require('dateformat');
  6. const bodyParser = require('body-parser');
  7. const port = 8080;
  8. const { makeExecutableSchema } = require('graphql-tools');
  9. const typeDefs = require('./schema');
  10. const resolvers = require('./resolver');
  11. const schema = makeExecutableSchema({
  12. typeDefs,
  13. resolvers
  14. });
  15. app.use(bodyParser.urlencoded({ extended:false }));
  16. app.use(bodyParser.json());
  17. // Routes
  18. app.get('/json', async(req, res) => {
  19. const graphql = await graphqlHTTP((req, res, graphQLParams) => {
  20. graphQLParams.query = "{ helloWorld }";
  21. graphQLParams.operationName = null;
  22. graphQLParams.variables = {};
  23. return graphqlOpts()
  24. });
  25. res.real_end = res.end;
  26. res.end = (data) => {
  27. let toRet;
  28. const json = JSON.parse(data.toString('utf8'));
  29. if(json.data.helloWorld) {
  30. toRet = json.data.helloWorld;
  31. } else {
  32. toRet = { helloWorld: null };
  33. }
  34. setResponseHeaders(res, toRet.length);
  35. res.real_end(toRet);
  36. }
  37. await graphql(req, res);
  38. });
  39. app.get('/db', async (req, res) => {
  40. const graphql = await graphqlHTTP((req, res, graphQLParams) => {
  41. graphQLParams.query = "{ singleDatabaseQuery { id, randomNumber }}";
  42. graphQLParams.variables = {};
  43. graphQLParams.operationName = null;
  44. return graphqlOpts();
  45. });
  46. formatResData(res, "singleDatabaseQuery");
  47. await graphql(req, res);
  48. });
  49. app.get('/queries', async (req, res) => {
  50. const graphql = await graphqlHTTP((req, res, graphQLParams) => {
  51. let totalNumOfQueries = ensureQueryIsAnInt(req.query.queries);
  52. graphQLParams.query = `{ multipleDatabaseQueries(total: ${totalNumOfQueries}) { id, randomNumber }}`
  53. graphQLParams.variables = {};
  54. graphQLParams.operationName = null;
  55. return graphqlOpts();
  56. });
  57. formatResData(res, "multipleDatabaseQueries");
  58. await graphql(req, res);
  59. });
  60. app.get('/fortunes', async (req, res) => {
  61. const graphql = await graphqlHTTP((req, res, graphQLParams) => {
  62. graphQLParams.query = "{ getAllFortunes { id, message } }"
  63. graphQLParams.operationName = null;
  64. graphQLParams.variables = {};
  65. return graphqlOpts();
  66. });
  67. retrieveAndFormatAllFortunes(res);
  68. await graphql(req, res);
  69. });
  70. app.get('/updates', async (req, res) => {
  71. const totalNumOfQueries = ensureQueryIsAnInt(req.query.queries);
  72. const graphql = await graphqlHTTP((req, res, graphQLParams) => {
  73. graphQLParams.query = `{ getRandomAndUpdate(total: ${totalNumOfQueries}) { id, randomNumber } }`
  74. graphQLParams.operationName = null;
  75. graphQLParams.variables = {};
  76. return graphqlOpts();
  77. });
  78. formatResData(res, 'getRandomAndUpdate');
  79. await graphql(req, res);
  80. });
  81. app.get('/plaintext', (req, res) => {
  82. const responseTxt = "Hello, World!";
  83. res.setHeader('Content-Length', responseTxt.length);
  84. res.setHeader('Server', 'Express-GraphQL-MySQL');
  85. res.contentType('text/plain');
  86. res.status(200);
  87. res.send(responseTxt);
  88. });
  89. // Helper Functions
  90. const ensureQueryIsAnInt = (queryString) => {
  91. if(queryString === undefined) return 1;
  92. const possibleInt = parseInt(queryString);
  93. if(!possibleInt) return 1;
  94. return possibleInt;
  95. };
  96. const graphqlOpts = (params) => {
  97. return {
  98. schema,
  99. graphiql: false,
  100. context: params || {}
  101. }
  102. };
  103. const retrieveAndFormatAllFortunes = res => {
  104. res.real_end = res.end;
  105. res.end = async (data) => {
  106. let toRet;
  107. const json = JSON.parse(data.toString('utf8'));
  108. if(json.data.getAllFortunes) {
  109. toRet = json.data.getAllFortunes;
  110. } else {
  111. toRet = [];
  112. }
  113. const newFortune = { "id": 0, "message": "Additional fortune added at request time." };
  114. toRet.push(newFortune);
  115. toRet.sort((a, b) => (a.message < b.message) ? -1 : 1);
  116. const htmlToRet = await spoofHTML(toRet);
  117. res.contentType('html');
  118. res.setHeader('Server', 'GraphQL-MySQL');
  119. res.setHeader('Content-Length', htmlToRet.length + 32);
  120. res.status(200);
  121. res.real_end(htmlToRet);
  122. }
  123. };
  124. const spoofHTML = arr => {
  125. return new Promise((resolve, reject) => {
  126. let count = 0;
  127. let htmlToRet = `<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>`;
  128. for (let fortune of arr) {
  129. htmlToRet += `<tr><td>${escape(fortune.id)}</td><td>${escape(fortune.message)}</td></tr>`;
  130. count++;
  131. }
  132. htmlToRet += '</table></body></html>';
  133. if(count == arr.length)resolve(htmlToRet);
  134. });
  135. };
  136. const formatResData = (res, queryName) => {
  137. res.real_end = res.end;
  138. res.end = (data) => {
  139. const json = JSON.parse(data.toString('utf8'));
  140. let toRet = formatJson(queryName, json);
  141. const jsonToRet = JSON.stringify(toRet);
  142. setResponseHeaders(res, jsonToRet.length);
  143. res.real_end(jsonToRet);
  144. };
  145. };
  146. const formatJson = (queryName, jsonData) => {
  147. const isQueryReturningAnArray = {
  148. singleDatabaseQuery: false,
  149. multipleDatabaseQueries: true,
  150. getRandomAndUpdate: true
  151. };
  152. if (isQueryReturningAnArray[queryName] == false) {
  153. if(jsonData.data[`${queryName}`]) {
  154. return {
  155. id: jsonData.data[`${queryName}`].id,
  156. randomNumber: jsonData.data[`${queryName}`].randomNumber
  157. };
  158. } else {
  159. return {
  160. id: null,
  161. randomNumber: null
  162. }
  163. }
  164. } else {
  165. return jsonData.data[`${queryName}`] || [];
  166. }
  167. };
  168. const setResponseHeaders = (res, jsonLength) => {
  169. let now = new Date();
  170. res.status(200);
  171. res.contentType('application/json', 'charset=UTF-8');
  172. res.setHeader('Date', dateFormat(now, "ddd, dd mmm yyyy hh:MM:ss Z"));
  173. res.setHeader('Server', 'GraphQL-Express-MySQL');
  174. res.setHeader('Content-Length', jsonLength);
  175. };
  176. app.listen(port, () => {
  177. console.log(`Listening on localhost:${port}`);
  178. });