The frontend/UI server, written in JS using the MarkoJS library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.0 KiB

6 years ago
  1. const EventEmitter = require("events")
  2. const fetch = require("isomorphic-fetch")
  3. const config = require("../config")
  4. const compressQuery = require("graphql-query-compress")
  5. /**
  6. * Run a GraphQL query against the rpdata backend
  7. *
  8. * @param {string} query The query to run
  9. * @param {{[x:string]: any}} variables
  10. * @param {{operationName:string, token: string, permissions: string[]}} options
  11. */
  12. function query(query, variables = {}, options = {}) {
  13. return fetch(config.graphqlEndpoint, {
  14. method: "POST",
  15. headers: {
  16. "Content-Type": "application/json",
  17. "Authorization": options.token ? `Bearer ${options.token}` : null,
  18. "X-Permissions": options.permissions ? options.permissions.join(",") : null,
  19. },
  20. body: JSON.stringify({query: query.length > 256 ? compressQuery(query || "") : query, variables, operationName: options.operationName}),
  21. credentials: "include",
  22. }).then(res => {
  23. return res.json()
  24. }).then(json => {
  25. if (json.errors != null && json.errors.length > 0) {
  26. return Promise.reject(json.errors)
  27. }
  28. return json.data
  29. })
  30. }
  31. class Subscription extends EventEmitter {
  32. constructor(query, variables) {
  33. super()
  34. this.query = query
  35. this.variables = Object.assign({}, variables)
  36. this.websocket = null
  37. this.verboseLogging = false
  38. }
  39. connect() {
  40. const baseUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host
  41. let id = 1
  42. this.websocket = new WebSocket(baseUrl + config.graphqlEndpoint, "graphql-ws")
  43. this.websocket.onopen = () => {
  44. this.websocket.send(JSON.stringify({type: "connection_init", payload: {}}));
  45. this.websocket.send(JSON.stringify({id: (id++).toFixed(0), type: "start", payload: {
  46. query: this.query,
  47. variables: this.variables,
  48. extensions: {},
  49. }}));
  50. console.log("WS Open")
  51. }
  52. this.websocket.onmessage = (ev) => {
  53. let data = {}
  54. try {
  55. data = JSON.parse(ev.data)
  56. } catch (err) {
  57. console.warn("Error", err, ev)
  58. return
  59. }
  60. if (this.verboseLogging) {
  61. console.log("WS Data:", data)
  62. }
  63. switch (data.type) {
  64. case "connection_ack": {
  65. this.emit("connect")
  66. break;
  67. }
  68. case "connection_error": {
  69. console.warn("WS Connection Error", data.payload.message)
  70. this.websocket.close()
  71. this.emit("error", new Error(data.payload.message))
  72. break;
  73. }
  74. case "data": {
  75. if (data.payload.errors != null && data.payload.errors.length > 0) {
  76. this.emit("error", data.payload.errors)
  77. } else {
  78. this.emit("data", data.payload.data)
  79. }
  80. break;
  81. }
  82. }
  83. }
  84. this.websocket.onerror = (err) => {
  85. console.warn("WS Error", err)
  86. }
  87. this.websocket.onclose = () => {
  88. this.emit("disconnect")
  89. }
  90. }
  91. disconnect() {
  92. if (this.websocket != null) {
  93. this.websocket.close();
  94. }
  95. }
  96. }
  97. module.exports = { query, Subscription }