feat: transitioned to vanilla apollo-server-express

This commit is contained in:
Wyatt Johnson
2020-08-14 17:59:13 -06:00
parent 4a94b81230
commit 22fc1438f2
26 changed files with 530 additions and 537 deletions
+191 -145
View File
@@ -40,9 +40,12 @@
}
},
"@apollographql/graphql-playground-html": {
"version": "1.6.24",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz",
"integrity": "sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ=="
"version": "1.6.26",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
"integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
"requires": {
"xss": "^1.0.6"
}
},
"@ardatan/aggregate-error": {
"version": "0.0.1",
@@ -7987,7 +7990,7 @@
},
"@types/accepts": {
"version": "1.3.5",
"resolved": "http://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==",
"requires": {
"@types/node": "*"
@@ -10092,18 +10095,18 @@
}
},
"apollo-cache-control": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.0.tgz",
"integrity": "sha512-dmRnQ9AXGw2SHahVGLzB/p4UW/taFBAJxifxubp8hqY5p9qdlSu4MPRq8zvV2ULMYf50rBtZyC4C+dZLqmHuHQ==",
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.1.tgz",
"integrity": "sha512-6iHa8TkcKt4rx5SKRzDNjUIpCQX+7/FlZwD7vRh9JDnM4VH8SWhpj8fUR3CiEY8Kuc4ChXnOY8bCcMju5KPnIQ==",
"requires": {
"apollo-server-env": "^2.4.4",
"apollo-server-plugin-base": "^0.9.0"
"apollo-server-env": "^2.4.5",
"apollo-server-plugin-base": "^0.9.1"
},
"dependencies": {
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
@@ -10112,18 +10115,26 @@
}
},
"apollo-datasource": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.1.tgz",
"integrity": "sha512-h++/jQAY7GA+4TBM+7ezvctFmmGNLrAPf51KsagZj+NkT9qvxp585rdsuatynVbSl59toPK2EuVmc6ilmQHf+g==",
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.2.tgz",
"integrity": "sha512-ibnW+s4BMp4K2AgzLEtvzkjg7dJgCaw9M5b5N0YKNmeRZRnl/I/qBTQae648FsRKgMwTbRQIvBhQ0URUFAqFOw==",
"requires": {
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4"
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
},
"dependencies": {
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
"integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==",
"requires": {
"lru-cache": "^5.0.0"
}
},
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
@@ -10132,52 +10143,60 @@
}
},
"apollo-engine-reporting": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.0.1.tgz",
"integrity": "sha512-3OYYk7DqNuJ5xKYnyLy5O2n506jYSryim8WqzBTn9MRphRamwPFjHYQm+akPA60AubXrWnYa6A8euMAiQU0ttA==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting/-/apollo-engine-reporting-2.3.0.tgz",
"integrity": "sha512-SbcPLFuUZcRqDEZ6mSs8uHM9Ftr8yyt2IEu0JA8c3LNBmYXSLM7MHqFe80SVcosYSTBgtMz8mLJO8orhYoSYZw==",
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-graphql": "^0.4.0",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"apollo-engine-reporting-protobuf": "^0.5.2",
"apollo-graphql": "^0.5.0",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5",
"apollo-server-errors": "^2.4.2",
"apollo-server-plugin-base": "^0.9.1",
"apollo-server-types": "^0.5.1",
"async-retry": "^1.2.1",
"uuid": "^8.0.0"
},
"dependencies": {
"apollo-engine-reporting-protobuf": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.1.tgz",
"integrity": "sha512-TSfr9iAaInV8dhXkesdcmqsthRkVcJkzznmiM+1Ob/GScK7r6hBYCjVDt2613EHAg9SUzTOltIKlGD+N+GJRUw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz",
"integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==",
"requires": {
"@apollo/protobufjs": "^1.0.3"
}
},
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
"integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==",
"requires": {
"lru-cache": "^5.0.0"
}
},
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
}
},
"apollo-server-types": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.0.tgz",
"integrity": "sha512-zhtsqqqfdeoJQAfc41Sy6WnnBVxKNgZ34BKXf/Q+kXmw7rbZ/B5SG3SJMvj1iFsbzZxILmWdUsE9aD20lEr0bg==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz",
"integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==",
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4"
"apollo-engine-reporting-protobuf": "^0.5.2",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
}
},
"uuid": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.1.0.tgz",
"integrity": "sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg=="
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ=="
}
}
},
@@ -10201,9 +10220,9 @@
}
},
"apollo-graphql": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.4.5.tgz",
"integrity": "sha512-0qa7UOoq7E71kBYE7idi6mNQhHLVdMEDInWk6TNw3KsSWZE2/I68gARP84Mj+paFTO5NYuw1Dht66PVX76Cc2w==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.5.0.tgz",
"integrity": "sha512-YSdF/BKPbsnQpxWpmCE53pBJX44aaoif31Y22I/qKpB6ZSGzYijV5YBoCL5Q15H2oA/v/02Oazh9lbp4ek3eig==",
"requires": {
"apollo-env": "^0.6.5",
"lodash.sortby": "^4.7.0"
@@ -10289,25 +10308,25 @@
}
},
"apollo-server-core": {
"version": "2.14.4",
"resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.14.4.tgz",
"integrity": "sha512-aAfsvbJ2YrqAXDBgcBQocOmQJ5DkeOnEYQ6ADdkkDNU68V5yBRkAHLTOzPfbUlGHVrnOH8PT1FIVWwu5mBgkVA==",
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.16.1.tgz",
"integrity": "sha512-nuwn5ZBbmzPwDetb3FgiFFJlNK7ZBFg8kis/raymrjd3eBGdNcOyMTJDl6J9673X9Xqp+dXQmFYDW/G3G8S1YA==",
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/graphql-upload": "^8.0.0",
"@types/ws": "^7.0.0",
"apollo-cache-control": "^0.11.0",
"apollo-datasource": "^0.7.1",
"apollo-engine-reporting": "^2.0.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4",
"apollo-server-errors": "^2.4.1",
"apollo-server-plugin-base": "^0.9.0",
"apollo-server-types": "^0.5.0",
"apollo-tracing": "^0.11.0",
"apollo-cache-control": "^0.11.1",
"apollo-datasource": "^0.7.2",
"apollo-engine-reporting": "^2.3.0",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5",
"apollo-server-errors": "^2.4.2",
"apollo-server-plugin-base": "^0.9.1",
"apollo-server-types": "^0.5.1",
"apollo-tracing": "^0.11.1",
"fast-json-stable-stringify": "^2.0.0",
"graphql-extensions": "^0.12.3",
"graphql-extensions": "^0.12.4",
"graphql-tag": "^2.9.2",
"graphql-tools": "^4.0.0",
"graphql-upload": "^8.0.2",
@@ -10317,49 +10336,49 @@
"ws": "^6.0.0"
},
"dependencies": {
"@apollographql/graphql-playground-html": {
"version": "1.6.26",
"resolved": "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz",
"integrity": "sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ==",
"requires": {
"xss": "^1.0.6"
}
},
"apollo-engine-reporting-protobuf": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.1.tgz",
"integrity": "sha512-TSfr9iAaInV8dhXkesdcmqsthRkVcJkzznmiM+1Ob/GScK7r6hBYCjVDt2613EHAg9SUzTOltIKlGD+N+GJRUw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz",
"integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==",
"requires": {
"@apollo/protobufjs": "^1.0.3"
}
},
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
"integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==",
"requires": {
"lru-cache": "^5.0.0"
}
},
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
}
},
"apollo-server-types": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.0.tgz",
"integrity": "sha512-zhtsqqqfdeoJQAfc41Sy6WnnBVxKNgZ34BKXf/Q+kXmw7rbZ/B5SG3SJMvj1iFsbzZxILmWdUsE9aD20lEr0bg==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz",
"integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==",
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4"
"apollo-engine-reporting-protobuf": "^0.5.2",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
}
},
"graphql-extensions": {
"version": "0.12.3",
"resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.3.tgz",
"integrity": "sha512-W7iT0kzlwTiZU7fXfw9IgWnsqVj7EFLd0/wVcZZRAbR8L3f4+YsGls0oxKdsrvYBnbG347BXKQmIyo6GTEk4XA==",
"version": "0.12.4",
"resolved": "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.4.tgz",
"integrity": "sha512-GnR4LiWk3s2bGOqIh6V1JgnSXw2RCH4NOgbCFEWvB6JqWHXTlXnLZ8bRSkCiD4pltv7RHUPWqN/sGh8R6Ae/ag==",
"requires": {
"@apollographql/apollo-tools": "^0.4.3",
"apollo-server-env": "^2.4.4",
"apollo-server-types": "^0.5.0"
"apollo-server-env": "^2.4.5",
"apollo-server-types": "^0.5.1"
}
},
"ws": {
@@ -10382,23 +10401,23 @@
}
},
"apollo-server-errors": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.1.tgz",
"integrity": "sha512-7oEd6pUxqyWYUbQ9TA8tM0NU/3aGtXSEibo6+txUkuHe7QaxfZ2wHRp+pfT1LC1K3RXYjKj61/C2xEO19s3Kdg=="
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz",
"integrity": "sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ=="
},
"apollo-server-express": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.14.2.tgz",
"integrity": "sha512-iYyZm0kQqkM561i9l0WC9HbJsGZJbHP9bhnWaa1Itd+yNBS2AJFp6mRR3hQacsWXUw7ewaKAracMIggvfSH5Aw==",
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.16.1.tgz",
"integrity": "sha512-Oq5YNcaMYnRk6jDmA9LWf8oSd2KHDVe7jQ4wtooAvG9FVUD+FaFBgSkytXHMvtifQh2wdF07Ri8uDLMz6IQjTw==",
"requires": {
"@apollographql/graphql-playground-html": "1.6.24",
"@apollographql/graphql-playground-html": "1.6.26",
"@types/accepts": "^1.3.5",
"@types/body-parser": "1.19.0",
"@types/cors": "^2.8.4",
"@types/express": "4.17.4",
"@types/express": "4.17.7",
"accepts": "^1.3.5",
"apollo-server-core": "^2.14.2",
"apollo-server-types": "^0.5.0",
"apollo-server-core": "^2.16.1",
"apollo-server-types": "^0.5.1",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.17.1",
@@ -10409,68 +10428,95 @@
"type-is": "^1.6.16"
},
"dependencies": {
"@types/express": {
"version": "4.17.7",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz",
"integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"apollo-engine-reporting-protobuf": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.1.tgz",
"integrity": "sha512-TSfr9iAaInV8dhXkesdcmqsthRkVcJkzznmiM+1Ob/GScK7r6hBYCjVDt2613EHAg9SUzTOltIKlGD+N+GJRUw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz",
"integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==",
"requires": {
"@apollo/protobufjs": "^1.0.3"
}
},
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
"integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==",
"requires": {
"lru-cache": "^5.0.0"
}
},
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
}
},
"apollo-server-types": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.0.tgz",
"integrity": "sha512-zhtsqqqfdeoJQAfc41Sy6WnnBVxKNgZ34BKXf/Q+kXmw7rbZ/B5SG3SJMvj1iFsbzZxILmWdUsE9aD20lEr0bg==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz",
"integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==",
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4"
"apollo-engine-reporting-protobuf": "^0.5.2",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
}
}
}
},
"apollo-server-plugin-base": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.0.tgz",
"integrity": "sha512-LWcPrsy2+xqwlNseh/QaGa/MPNopS8c4qGgh0g0cAn0lZBRrJ9Yab7dq+iQ6vdUBwIhUWYN6s9dwUWCZw2SL8g==",
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.9.1.tgz",
"integrity": "sha512-kvrX4Z3FdpjrZdHkyl5iY2A1Wvp4b6KQp00DeZqss7GyyKNUBKr80/7RQgBLEw7EWM7WB19j459xM/TjvW0FKQ==",
"requires": {
"apollo-server-types": "^0.5.0"
"apollo-server-types": "^0.5.1"
},
"dependencies": {
"apollo-engine-reporting-protobuf": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.1.tgz",
"integrity": "sha512-TSfr9iAaInV8dhXkesdcmqsthRkVcJkzznmiM+1Ob/GScK7r6hBYCjVDt2613EHAg9SUzTOltIKlGD+N+GJRUw==",
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-engine-reporting-protobuf/-/apollo-engine-reporting-protobuf-0.5.2.tgz",
"integrity": "sha512-4wm9FR3B7UvJxcK/69rOiS5CAJPEYKufeRWb257ZLfX7NGFTMqvbc1hu4q8Ch7swB26rTpkzfsftLED9DqH9qg==",
"requires": {
"@apollo/protobufjs": "^1.0.3"
}
},
"apollo-server-caching": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.2.tgz",
"integrity": "sha512-HUcP3TlgRsuGgeTOn8QMbkdx0hLPXyEJehZIPrcof0ATz7j7aTPA4at7gaiFHCo8gk07DaWYGB3PFgjboXRcWQ==",
"requires": {
"lru-cache": "^5.0.0"
}
},
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
}
},
"apollo-server-types": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.0.tgz",
"integrity": "sha512-zhtsqqqfdeoJQAfc41Sy6WnnBVxKNgZ34BKXf/Q+kXmw7rbZ/B5SG3SJMvj1iFsbzZxILmWdUsE9aD20lEr0bg==",
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.5.1.tgz",
"integrity": "sha512-my2cPw+DAb2qVnIuBcsRKGyS28uIc2vjFxa1NpRoJZe9gK0BWUBk7wzXnIzWy3HZ5Er11e/40MPTUesNfMYNVA==",
"requires": {
"apollo-engine-reporting-protobuf": "^0.5.1",
"apollo-server-caching": "^0.5.1",
"apollo-server-env": "^2.4.4"
"apollo-engine-reporting-protobuf": "^0.5.2",
"apollo-server-caching": "^0.5.2",
"apollo-server-env": "^2.4.5"
}
}
}
@@ -10486,18 +10532,18 @@
}
},
"apollo-tracing": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.0.tgz",
"integrity": "sha512-I9IFb/8lkBW8ZwOAi4LEojfT7dMfUSkpnV8LHQI8Rcj0HtzL9HObQ3woBmzyGHdGHLFuD/6/VHyFD67SesSrJg==",
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.11.1.tgz",
"integrity": "sha512-l7g+uILw7v32GA46IRXIx5XXbZhFI96BhSqrGK9yyvfq+NMcvVZrj3kIhRImPGhAjMdV+5biA/jztabElAbDjg==",
"requires": {
"apollo-server-env": "^2.4.4",
"apollo-server-plugin-base": "^0.9.0"
"apollo-server-env": "^2.4.5",
"apollo-server-plugin-base": "^0.9.1"
},
"dependencies": {
"apollo-server-env": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.4.tgz",
"integrity": "sha512-c2oddDS3lwAl6QNCIKCLEzt/dF9M3/tjjYRVdxOVN20TidybI7rAbnT4QOzf4tORnGXtiznEAvr/Kc9ahhKADg==",
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-2.4.5.tgz",
"integrity": "sha512-nfNhmGPzbq3xCEWT8eRpoHXIPNcNy3QcEoBlzVMjeglrBGryLG2LXwBSPnVmTRRrzUYugX0ULBtgE3rBFNoUgA==",
"requires": {
"node-fetch": "^2.1.2",
"util.promisify": "^1.0.0"
@@ -29790,9 +29836,9 @@
}
},
"graphql-tag": {
"version": "2.10.3",
"resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.10.3.tgz",
"integrity": "sha512-4FOv3ZKfA4WdOKJeHdz6B3F/vxBLSgmBcGeAFPf4n1F64ltJUvOOerNj0rsJxONQGdhUMynQIvd6LzB+1J5oKA=="
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.11.0.tgz",
"integrity": "sha512-VmsD5pJqWJnQZMUeRwrDhfgoyqcfwEkvtpANqcoUG8/tOLkwNgU9mzub/Mc78OJMhHjx7gfAMTxzdG43VGg3bA=="
},
"graphql-tools": {
"version": "4.0.7",
@@ -29831,13 +29877,13 @@
},
"dependencies": {
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
"integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.1.1",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
@@ -29848,9 +29894,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"setprototypeof": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"statuses": {
"version": "1.5.0",
@@ -37904,9 +37950,9 @@
}
},
"loglevel": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz",
"integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A=="
"version": "1.6.8",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz",
"integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA=="
},
"long": {
"version": "4.0.0",
+2 -2
View File
@@ -70,8 +70,8 @@
"@sentry/node": "^5.21.1",
"abort-controller": "^3.0.0",
"akismet-api": "^5.0.0",
"apollo-server-core": "^2.14.4",
"apollo-server-express": "^2.14.2",
"apollo-server-express": "^2.16.1",
"apollo-server-plugin-base": "^0.9.1",
"archiver": "^3.1.1",
"basic-auth": "^2.0.1",
"bcryptjs": "^2.4.3",
@@ -1,80 +0,0 @@
import { generateSchemaHash } from "apollo-server-core/dist/utils/schemaHash";
import { CLIENT_ID_HEADER } from "coral-common/constants";
import { AppOptions } from "coral-server/app";
import { graphqlMiddleware } from "coral-server/app/middleware/graphql";
import GraphContext, { GraphContextOptions } from "coral-server/graph/context";
import {
Request,
RequestHandler,
TenantCoralRequest,
} from "coral-server/types/express";
export type GraphMiddlewareOptions = Pick<
AppOptions,
| "config"
| "i18n"
| "mailerQueue"
| "scraperQueue"
| "rejectorQueue"
| "notifierQueue"
| "webhookQueue"
| "mongo"
| "redis"
| "schema"
| "signingConfig"
| "pubsub"
| "tenantCache"
| "metrics"
| "broker"
| "reporter"
>;
export const graphQLHandler = ({
schema,
config,
metrics,
...options
}: GraphMiddlewareOptions): RequestHandler<TenantCoralRequest> => {
// Generate the schema hash.
const schemaHash = generateSchemaHash(schema);
return graphqlMiddleware(
config,
async (req: Request<TenantCoralRequest>) => {
// Pull out some useful properties from Coral.
const { id, now, tenant, logger, persisted } = req.coral;
// Create some new options to store the tenant context details inside.
const opts: GraphContextOptions = {
...options,
id,
now,
req,
persisted,
config,
tenant,
logger,
};
// Add the user if there is one.
if (req.user) {
opts.user = req.user;
}
// Add the clientID if there is one on the request.
const clientID = req.get(CLIENT_ID_HEADER);
if (clientID) {
// TODO: (wyattjoh) validate length
opts.clientID = clientID;
}
return {
schema,
schemaHash,
context: new GraphContext(opts),
};
},
metrics
);
};
@@ -1,6 +1,5 @@
export * from "./account";
export * from "./auth";
export * from "./graphql";
export * from "./health";
export * from "./install";
export * from "./version";
@@ -0,0 +1 @@
export * from "./tenant";
@@ -0,0 +1,110 @@
import { ApolloServer } from "apollo-server-express";
import { CLIENT_ID_HEADER } from "coral-common/constants";
import { AppOptions } from "coral-server/app";
import GraphContext, { GraphContextOptions } from "coral-server/graph/context";
import {
ErrorApolloServerPlugin,
LoggerApolloServerPlugin,
MetricsApolloServerPlugin,
} from "coral-server/graph/plugins";
import { Request, TenantCoralRequest } from "coral-server/types/express";
type ContextProviderOptions = Omit<AppOptions, "schema" | "metrics">;
function contextProvider(options: ContextProviderOptions) {
return ({ req }: { req: Request<TenantCoralRequest> }) => {
// Grab the details from the Coral request.
const { id, now, tenant, logger, persisted } = req.coral;
// Create some new options to store the tenant context details inside.
const opts: GraphContextOptions = {
...options,
id,
now,
req,
persisted,
tenant,
logger,
};
// Add the user if there is one.
if (req.user) {
opts.user = req.user;
}
// Add the clientID if there is one on the request.
const clientID = req.get(CLIENT_ID_HEADER);
if (clientID) {
// TODO: (wyattjoh) validate length
opts.clientID = clientID;
}
// Return the compiled context.
return new GraphContext(opts);
};
}
export const apolloGraphQLMiddleware = ({
schema,
metrics,
...options
}: AppOptions) => {
// Create the ApolloServer that we'll use to get the middleware from.
const server = new ApolloServer({
// Provide the executable schema that we assembled earlier.
schema,
// Create the context provider that'll create a new context for each
// request.
context: contextProvider(options),
// Introspection is enabled when we aren't in a production environment or if
// the GraphiQL is enabled.
introspection:
options.config.get("env") !== "production" ||
options.config.get("enable_graphiql"),
// Disable uploads, Coral doesn't handle any file uploads.
uploads: false,
// Disable the embedded playground, Coral provides it's own GraphiQL
// interface.
playground: false,
// Disable engine, Coral doesn't use it.
engine: false,
// Disable cache control, Coral doesn't use it yet.
cacheControl: false,
// Disable subscriptions as we'll be providing it seperatly.
subscriptions: false,
// Configure plugins to be ran on requests.
plugins: [
ErrorApolloServerPlugin,
LoggerApolloServerPlugin,
MetricsApolloServerPlugin(metrics),
],
// Disable the debug mode, as we already add in our logging function.
debug: false,
});
// Get the GraphQL middleware.
return server.getMiddleware({
// Disable the health check endpoint, Coral does not use this endpoint and
// instead uses the /api/health endpoint.
disableHealthCheck: true,
// Disable CORS, Coral does not allow cross origin requests.
cors: false,
// Disable the body parser, we will add our own.
bodyParserConfig: false,
// Configure the path.
path: "/graphql",
});
};
@@ -1,76 +0,0 @@
import { GraphQLExtension, GraphQLOptions } from "apollo-server-express";
// TODO: when https://github.com/apollographql/apollo-server/pull/1907 is merged, update this import path
import {
ExpressGraphQLOptionsFunction,
graphqlExpress,
} from "apollo-server-express/dist/expressApollo";
import { Handler } from "express";
import { FieldDefinitionNode, GraphQLError, ValidationContext } from "graphql";
import { Config } from "coral-server/config";
import {
ErrorWrappingExtension,
LoggerExtension,
MetricsExtension,
} from "coral-server/graph/extensions";
import { Metrics } from "coral-server/services/metrics";
// Sourced from: https://github.com/apollographql/apollo-server/blob/958846887598491fadea57b3f9373d129300f250/packages/apollo-server-core/src/ApolloServer.ts#L46-L57
const NoIntrospection = (context: ValidationContext) => ({
Field(node: FieldDefinitionNode) {
if (node.name.value === "__schema" || node.name.value === "__type") {
context.reportError(
new GraphQLError(
"GraphQL introspection is not allowed in production, but the query contained __schema or __type.",
[node]
)
);
}
},
});
/**
* graphqlMiddleware wraps the GraphQL middleware server with some custom
* extension management.
*
* @param config application configuration
* @param requestOptions options to pass to the graphql server
*/
const graphqlMiddleware = (
config: Config,
requestOptions: ExpressGraphQLOptionsFunction,
metrics: Metrics
): Handler => {
const extensions: Array<() => GraphQLExtension> = [
() => new ErrorWrappingExtension(),
() => new LoggerExtension(),
// Pass the metrics to the extension so it can increment.
() => new MetricsExtension(metrics),
];
// Create a new baseOptions that will be merged into the new options.
const baseOptions: Omit<GraphQLOptions, "schema" | "schemaHash"> = {
// Disable the debug mode, as we already add in our logging function.
debug: false,
extensions,
};
if (config.get("env") === "production" && !config.get("enable_graphiql")) {
// Disable introspection in production.
baseOptions.validationRules = [NoIntrospection];
}
// Generate the actual middleware.
return graphqlExpress(async (req, res) => {
// Resolve the options for the GraphQL middleware.
const options = await requestOptions(req, res);
// Provide the options.
return {
...options,
...baseOptions,
};
});
};
export default graphqlMiddleware;
@@ -1,2 +1,2 @@
export { default as graphqlMiddleware } from "./graphqlMiddleware";
export { default as persistedQueryMiddleware } from "./persistedQueryMiddleware";
export * from "./apolloServer";
export * from "./persistedQuery";
@@ -14,7 +14,7 @@ type PersistedQueryMiddlewareOptions = Pick<
"persistedQueryCache" | "persistedQueriesRequired"
>;
const persistedQueryMiddleware = ({
export const persistedQueryMiddleware = ({
persistedQueriesRequired,
persistedQueryCache,
}: PersistedQueryMiddlewareOptions): RequestHandler<
@@ -64,5 +64,3 @@ const persistedQueryMiddleware = ({
return next(err);
}
};
export default persistedQueryMiddleware;
+17
View File
@@ -0,0 +1,17 @@
export * from "./csp";
export * from "./graphql";
export * from "./passport";
export * from "./basicAuth";
export * from "./cacheHeaders";
export * from "./error";
export * from "./installed";
export * from "./json";
export * from "./loggedIn";
export * from "./logging";
export * from "./metrics";
export * from "./notFound";
export * from "./playground";
export * from "./role";
export * from "./serveStatic";
export * from "./tenant";
export * from "./userLimiter";
+5 -9
View File
@@ -1,24 +1,20 @@
import { isInstalled } from "coral-server/services/tenant";
import { RequestHandler } from "coral-server/types/express";
export interface InstalledMiddlewareOptions {
interface Options {
redirectURL?: string;
redirectIfInstalled?: boolean;
}
const DefaultInstalledMiddlewareOptions: Required<InstalledMiddlewareOptions> = {
const defaultOptions: Required<Options> = {
redirectIfInstalled: false,
redirectURL: "/install",
};
export const installedMiddleware = ({
redirectIfInstalled = DefaultInstalledMiddlewareOptions.redirectIfInstalled,
redirectURL = DefaultInstalledMiddlewareOptions.redirectURL,
}: InstalledMiddlewareOptions = DefaultInstalledMiddlewareOptions): RequestHandler => async (
req,
res,
next
) => {
redirectIfInstalled = defaultOptions.redirectIfInstalled,
redirectURL = defaultOptions.redirectURL,
}: Options = defaultOptions): RequestHandler => async (req, res, next) => {
const installed = await isInstalled(req.coral.cache.tenant, req.hostname);
// If Coral is installed, and redirectIfInstall is true, then it will
@@ -4,8 +4,6 @@ import { createTimer } from "coral-server/helpers";
import { Metrics } from "coral-server/services/metrics";
import { RequestHandler } from "coral-server/types/express";
export type MetricsRecorderOptions = Metrics;
export const metricsRecorder = ({
httpRequestsTotal,
httpRequestDurationMilliseconds,
@@ -32,14 +32,12 @@ export type VerifyCallback = (
info?: { message: string }
) => void;
export type PassportOptions = Pick<
type Options = Pick<
AppOptions,
"mongo" | "redis" | "config" | "tenantCache" | "signingConfig"
>;
export function createPassport(
options: PassportOptions
): passport.Authenticator {
export function createPassport(options: Options): passport.Authenticator {
// Create the authenticator.
const auth = new Authenticator();
+2 -2
View File
@@ -5,7 +5,7 @@ import logger from "coral-server/logger";
import { TenantCache } from "coral-server/services/tenant/cache";
import { RequestHandler } from "coral-server/types/express";
export interface MiddlewareOptions {
interface Options {
cache: TenantCache;
passNoTenant?: boolean;
}
@@ -13,7 +13,7 @@ export interface MiddlewareOptions {
export const tenantMiddleware = ({
cache,
passNoTenant = false,
}: MiddlewareOptions): RequestHandler => async (req, res, next) => {
}: Options): RequestHandler => async (req, res, next) => {
try {
if (!req.coral) {
const id = uuid();
@@ -4,7 +4,7 @@ import { RequestLimiter } from "coral-server/app/request/limiter";
import { Config } from "coral-server/config";
import { RequestHandler } from "coral-server/types/express";
export interface MiddlewareOptions {
interface Options {
redis: Redis;
config: Config;
}
@@ -12,7 +12,7 @@ export interface MiddlewareOptions {
export const userLimiterMiddleware = ({
redis,
config,
}: MiddlewareOptions): RequestHandler => {
}: Options): RequestHandler => {
const limiter = new RequestLimiter({
redis,
ttl: "1m",
+17 -13
View File
@@ -2,17 +2,19 @@ import express from "express";
import passport from "passport";
import { AppOptions } from "coral-server/app";
import { graphQLHandler } from "coral-server/app/handlers";
import { oembedHandler } from "coral-server/app/handlers/api/oembed/oembed";
import { cspSiteMiddleware } from "coral-server/app/middleware/csp/tenant";
import { JSONErrorHandler } from "coral-server/app/middleware/error";
import { persistedQueryMiddleware } from "coral-server/app/middleware/graphql";
import { jsonMiddleware } from "coral-server/app/middleware/json";
import { loggedInMiddleware } from "coral-server/app/middleware/loggedIn";
import { notFoundMiddleware } from "coral-server/app/middleware/notFound";
import { authenticate } from "coral-server/app/middleware/passport";
import { roleMiddleware } from "coral-server/app/middleware/role";
import { tenantMiddleware } from "coral-server/app/middleware/tenant";
import {
apolloGraphQLMiddleware,
authenticate,
cspSiteMiddleware,
JSONErrorHandler,
jsonMiddleware,
loggedInMiddleware,
notFoundMiddleware,
persistedQueryMiddleware,
roleMiddleware,
tenantMiddleware,
} from "coral-server/app/middleware";
import { STAFF_ROLES } from "coral-server/models/user/constants";
import { createNewAccountRouter } from "./account";
@@ -55,15 +57,17 @@ export function createAPIRouter(app: AppOptions, options: RouterOptions) {
router.get("/oembed", cspSiteMiddleware(app), oembedHandler(app));
// Configure the GraphQL route.
// Configure the GraphQL route middleware.
router.use(
"/graphql",
authenticate(options.passport),
jsonMiddleware(app.config.get("max_request_size")),
persistedQueryMiddleware(app),
graphQLHandler(app)
persistedQueryMiddleware(app)
);
// Attach the GraphQL router (which will be mounted on the same path).
router.use(apolloGraphQLMiddleware(app));
router.use(
"/dashboard",
authenticate(options.passport),
@@ -1,43 +0,0 @@
import { ExecutionArgs } from "graphql";
import { EndHandler, GraphQLExtension } from "graphql-extensions";
import GraphContext from "coral-server/graph/context";
import { createTimer } from "coral-server/helpers";
import { Metrics } from "coral-server/services/metrics";
import { getOperationMetadata } from "./helpers";
export class MetricsExtension implements GraphQLExtension<GraphContext> {
constructor(private metrics: Metrics) {}
public executionDidStart(o: {
executionArgs: ExecutionArgs;
}): EndHandler | void {
// Only try to log things if the context is provided.
if (o.executionArgs.contextValue) {
// Grab the start time so we can calculate the time it takes to execute
// the graph query.
const timer = createTimer();
return () => {
// Compute the end time.
const responseTime = timer();
// Get the request metadata.
const { operation, operationName } = getOperationMetadata(
o.executionArgs.document
);
if (operation && operationName) {
// Increment the graph query value, tagging with the name of the query.
this.metrics.executedGraphQueriesTotalCounter
.labels(operation, operationName)
.inc();
this.metrics.graphQLExecutionTimingsHistogram
.labels(operation, operationName)
.observe(responseTime);
}
};
}
}
}
@@ -1,82 +0,0 @@
import {
DocumentNode,
GraphQLFormattedError,
OperationDefinitionNode,
OperationTypeNode,
} from "graphql";
import { PersistedQuery } from "coral-server/models/queries";
export interface OperationMetadata {
operationName: string;
operation: OperationTypeNode;
}
/**
* getOperationMetadata will extract the operation metadata from the document
* node.
*
* @param doc the document node that can be used to extract operation metadata
* from
*/
export const getOperationMetadata = (
doc: DocumentNode
): Partial<OperationMetadata> => {
if (doc.kind === "Document") {
const operationDefinition = doc.definitions.find(
({ kind }) => kind === "OperationDefinition"
) as OperationDefinitionNode | undefined;
if (operationDefinition) {
let operationName: string | undefined;
if (operationDefinition.name) {
operationName = operationDefinition.name.value;
}
return {
operationName,
operation: operationDefinition.operation,
};
}
}
return {};
};
interface PersistedQueryOperationMetadata extends OperationMetadata {
persistedQueryID: string;
persistedQueryBundle: string;
persistedQueryVersion: string;
}
/**
* getPersistedQueryMetadata will remap the persisted query to the operation
* metadata.
*
* @param persisted persisted query to remap to operation metadata
*/
export const getPersistedQueryMetadata = ({
id: persistedQueryID,
operation,
operationName,
bundle: persistedQueryBundle,
version: persistedQueryVersion,
}: PersistedQuery): PersistedQueryOperationMetadata => ({
persistedQueryID,
persistedQueryBundle,
persistedQueryVersion,
operation,
operationName,
});
/**
* getOriginalError tries to return the original error from a
* formatted GraphQL error.
*
* @param err A GraphQL Formatted Error
*/
export const getOriginalError = (err: GraphQLFormattedError) => {
if ((err as any).originalError) {
return (err as any).originalError as Error;
}
return null;
};
@@ -1,3 +0,0 @@
export * from "./ErrorWrappingExtension";
export * from "./LoggerExtension";
export * from "./MetricsExtension";
+1 -1
View File
@@ -3,7 +3,7 @@ import { parse } from "graphql";
import path from "path";
import { version } from "coral-common/version";
import { getOperationMetadata } from "coral-server/graph/extensions/helpers";
import { getOperationMetadata } from "coral-server/graph/plugins";
import logger from "coral-server/logger";
import { PersistedQuery } from "coral-server/models/queries";
+22
View File
@@ -0,0 +1,22 @@
import { ApolloServerPlugin } from "apollo-server-plugin-base";
import GraphContext from "../context";
import { enrichError } from "./helpers";
export const ErrorApolloServerPlugin: ApolloServerPlugin<GraphContext> = {
requestDidStart() {
return {
willSendResponse({ response, context }) {
// If there's any errors on the response, we need to enrich their
// extensions with translated messages.
if (response.errors) {
response.errors = response.errors.map((err) =>
enrichError(context, err)
);
}
},
};
},
};
export default ErrorApolloServerPlugin;
@@ -1,6 +1,10 @@
import { ApolloError } from "apollo-server-core";
import { GraphQLFormattedError } from "graphql";
import { GraphQLExtension, GraphQLResponse } from "graphql-extensions";
import { ApolloError } from "apollo-server-express";
import {
DocumentNode,
GraphQLFormattedError,
OperationDefinitionNode,
OperationTypeNode,
} from "graphql";
import { merge } from "lodash";
import {
@@ -8,9 +12,83 @@ import {
InternalDevelopmentError,
WrappedInternalError,
} from "coral-server/errors";
import GraphContext from "coral-server/graph/context";
import { PersistedQuery } from "coral-server/models/queries";
import { getOriginalError } from "./helpers";
import GraphContext from "../context";
export interface OperationMetadata {
operationName: string;
operation: OperationTypeNode;
}
/**
* getOperationMetadata will extract the operation metadata from the document
* node.
*
* @param doc the document node that can be used to extract operation metadata
* from
*/
export const getOperationMetadata = (
doc: DocumentNode
): Partial<OperationMetadata> => {
if (doc.kind === "Document") {
const operationDefinition = doc.definitions.find(
({ kind }) => kind === "OperationDefinition"
) as OperationDefinitionNode | undefined;
if (operationDefinition) {
let operationName: string | undefined;
if (operationDefinition.name) {
operationName = operationDefinition.name.value;
}
return {
operationName,
operation: operationDefinition.operation,
};
}
}
return {};
};
interface PersistedQueryOperationMetadata extends OperationMetadata {
persistedQueryID: string;
persistedQueryBundle: string;
persistedQueryVersion: string;
}
/**
* getPersistedQueryMetadata will remap the persisted query to the operation
* metadata.
*
* @param persisted persisted query to remap to operation metadata
*/
export const getPersistedQueryMetadata = ({
id: persistedQueryID,
operation,
operationName,
bundle: persistedQueryBundle,
version: persistedQueryVersion,
}: PersistedQuery): PersistedQueryOperationMetadata => ({
persistedQueryID,
persistedQueryBundle,
persistedQueryVersion,
operation,
operationName,
});
/**
* getOriginalError tries to return the original error from a
* formatted GraphQL error.
*
* @param err A GraphQL Formatted Error
*/
export const getOriginalError = (err: GraphQLFormattedError) => {
if ((err as any).originalError) {
return (err as any).originalError as Error;
}
return null;
};
function hoistCoralErrorExtensions(
ctx: GraphContext,
@@ -100,22 +178,3 @@ export function enrichError(
return err;
}
export class ErrorWrappingExtension implements GraphQLExtension<GraphContext> {
public willSendResponse(o: {
graphqlResponse: GraphQLResponse;
context: GraphContext;
}): void | { graphqlResponse: GraphQLResponse; context: GraphContext } {
if (o.graphqlResponse.errors) {
return {
...o,
graphqlResponse: {
...o.graphqlResponse,
errors: o.graphqlResponse.errors.map((err) =>
enrichError(o.context, err)
),
},
};
}
}
}
+4
View File
@@ -0,0 +1,4 @@
export * from "./error";
export * from "./logger";
export * from "./metrics";
export * from "./helpers";
@@ -1,9 +1,5 @@
import { DocumentNode, ExecutionArgs, GraphQLFormattedError } from "graphql";
import {
EndHandler,
GraphQLExtension,
GraphQLResponse,
} from "graphql-extensions";
import { ApolloServerPlugin } from "apollo-server-plugin-base";
import { DocumentNode, GraphQLFormattedError } from "graphql";
import GraphContext from "coral-server/graph/context";
import { createTimer } from "coral-server/helpers";
@@ -16,10 +12,9 @@ export function logAndReportError(
ctx: GraphContext,
err: GraphQLFormattedError
) {
ctx.logger.error({ err }, "graphql query error");
// If there's no reporter active, then return now.
// If there's no reporter active, then just log what we got and return now.
if (!ctx.reporter) {
ctx.logger.error({ err }, "graphql query error");
return;
}
@@ -106,35 +101,25 @@ export function logQuery(
}
}
export class LoggerExtension implements GraphQLExtension<GraphContext> {
public executionDidStart(o: {
executionArgs: ExecutionArgs;
}): EndHandler | void {
// Only try to log things if the context is provided.
if (o.executionArgs.contextValue) {
// Grab the start time so we can calculate the time it takes to execute
// the graph query.
const timer = createTimer();
return () => {
// Log out the details of the request.
logQuery(
o.executionArgs.contextValue,
o.executionArgs.document,
undefined,
timer()
);
};
}
}
export const LoggerApolloServerPlugin: ApolloServerPlugin<GraphContext> = {
requestDidStart() {
return {
willSendResponse({ response, context }) {
if (response.errors) {
// Log out the errors on this request.
response.errors.forEach((err) => logAndReportError(context, err));
}
},
executionDidStart({ document, context }) {
// Grab the start time so we can calculate the time it takes to execute
// the graph query.
const timer = createTimer();
public willSendResponse(response: {
graphqlResponse: GraphQLResponse;
context: GraphContext;
}): void {
if (response.graphqlResponse.errors) {
response.graphqlResponse.errors.forEach((err) =>
logAndReportError(response.context, err)
);
}
}
}
return function executionDidEnd() {
// Log out the details of this request.
logQuery(context, document, context.persisted, timer());
};
},
};
},
};
+40
View File
@@ -0,0 +1,40 @@
import { ApolloServerPlugin } from "apollo-server-plugin-base";
import { createTimer } from "coral-server/helpers";
import { Metrics } from "coral-server/services/metrics";
import { getOperationMetadata } from "./helpers";
export const MetricsApolloServerPlugin = (
metrics: Metrics
): ApolloServerPlugin => ({
requestDidStart() {
return {
executionDidStart({ document }) {
// Grab the start time so we can calculate the time it takes to execute
// the graph query.
const timer = createTimer();
return function executionDidEnd() {
// Compute the end time.
const responseTime = timer();
// Get the request metadata.
const { operation, operationName } = getOperationMetadata(document);
if (operation && operationName) {
// Increment the graph query value, tagging with the name of the query.
metrics.executedGraphQueriesTotalCounter
.labels(operation, operationName)
.inc();
metrics.graphQLExecutionTimingsHistogram
.labels(operation, operationName)
.observe(responseTime);
}
};
},
};
},
});
export default MetricsApolloServerPlugin;
@@ -29,13 +29,13 @@ import {
TenantNotFoundError,
WrappedInternalError,
} from "coral-server/errors";
import { getPersistedQuery } from "coral-server/graph/persisted";
import {
enrichError,
getOperationMetadata,
logAndReportError,
logQuery,
} from "coral-server/graph/extensions";
import { getOperationMetadata } from "coral-server/graph/extensions/helpers";
import { getPersistedQuery } from "coral-server/graph/persisted";
} from "coral-server/graph/plugins";
import logger from "coral-server/logger";
import { PersistedQuery } from "coral-server/models/queries";
import { hasStaffRole } from "coral-server/models/user/helpers";