mirror of
https://github.com/wassname/talk.git
synced 2026-06-27 19:01:24 +08:00
feat: transitioned to vanilla apollo-server-express
This commit is contained in:
Generated
+191
-145
@@ -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
@@ -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";
|
||||
|
||||
+1
-3
@@ -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;
|
||||
@@ -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";
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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";
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
+83
-24
@@ -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)
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from "./error";
|
||||
export * from "./logger";
|
||||
export * from "./metrics";
|
||||
export * from "./helpers";
|
||||
+25
-40
@@ -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());
|
||||
};
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user