mirror of
https://github.com/vale981/apollo-server
synced 2025-03-06 02:01:40 -05:00
* feat(fastify) Apollo Fastify server integration resolve #626 * feat(fastify) Use createHandler instead of applyMiddleware #626 * feat(fastify) Fix integration test for node 10 #626 * feat(fastify) Update README's with fastify createHandler interface #626 * feat(fastify) Implement the fastify createHandler as a synchronous method #626 * (fastify) Tweaks to re-align with the parallel work in #2054. * (fastify): Use port 9999 rather than 8888 for tests. Because Gatsby. This specific port per integration is pretty brittle to begin with, but it does work. Currently, the fact that it works is facilitated by the fact that most people don't use 5555 (Hapi) and 6666 (Express) for anything. That said, the ever-popular Gatsby uses 8888 by default, so let's use 9999! * (fastify) Remove duplicative assertion in upload initialization. * (fastify) Implement fastify upload middleware * (fastify) Fix linting issues * (fastify) Update package-lock
This commit is contained in:
parent
7d5468800f
commit
069110b353
18 changed files with 1847 additions and 22 deletions
|
@ -44,6 +44,7 @@ client reference ID, Apollo Server will now default to the values present in the
|
||||||
of the request (`apollographql-client-name`, `apollographql-client-reference-id` and
|
of the request (`apollographql-client-name`, `apollographql-client-reference-id` and
|
||||||
`apollographql-client-version` respectively). As a last resort, when those headers are not set,
|
`apollographql-client-version` respectively). As a last resort, when those headers are not set,
|
||||||
the query extensions' `clientInfo` values will be used. [PR #1960](https://github.com/apollographql/apollo-server/pull/1960)
|
the query extensions' `clientInfo` values will be used. [PR #1960](https://github.com/apollographql/apollo-server/pull/1960)
|
||||||
|
- Added `apollo-server-fastify` integration ([@rkorrelboom](https://github.com/rkorrelboom) in [#1971](https://github.com/apollostack/apollo-server/pull/1971))
|
||||||
|
|
||||||
### v2.2.2
|
### v2.2.2
|
||||||
|
|
||||||
|
|
20
README.md
20
README.md
|
@ -86,6 +86,7 @@ Often times, Apollo Server needs to be run with a particular integration. To sta
|
||||||
- `apollo-server-express`
|
- `apollo-server-express`
|
||||||
- `apollo-server-koa`
|
- `apollo-server-koa`
|
||||||
- `apollo-server-hapi`
|
- `apollo-server-hapi`
|
||||||
|
- `apollo-server-fastify`
|
||||||
- `apollo-server-lambda`
|
- `apollo-server-lambda`
|
||||||
- `apollo-server-azure-functions`
|
- `apollo-server-azure-functions`
|
||||||
- `apollo-server-cloud-functions`
|
- `apollo-server-cloud-functions`
|
||||||
|
@ -235,6 +236,25 @@ new ApolloServer({
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Fastify
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { ApolloServer, gql } = require('apollo-server-fastify');
|
||||||
|
const { typeDefs, resolvers } = require('./module');
|
||||||
|
|
||||||
|
const server = new ApolloServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = require('fastify')();
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen(3000);
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
### AWS Lambda
|
### AWS Lambda
|
||||||
|
|
||||||
Apollo Server can be run on Lambda and deployed with AWS Serverless Application Model (SAM). It requires an API Gateway with Lambda Proxy Integration.
|
Apollo Server can be run on Lambda and deployed with AWS Serverless Application Model (SAM). It requires an API Gateway with Lambda Proxy Integration.
|
||||||
|
|
438
package-lock.json
generated
438
package-lock.json
generated
|
@ -77,7 +77,7 @@
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -1501,6 +1501,16 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/pino": {
|
||||||
|
"version": "4.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/pino/-/pino-4.16.1.tgz",
|
||||||
|
"integrity": "sha512-uYEhZ3jsuiYFsPcR34fbxVlrqzqphc+QQ3fU4rWR6PXH8ka2TKvPBjtkNqj8oBHouVGf4GCRfyPb7FG2TEtPZA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/events": "*",
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/podium": {
|
"@types/podium": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/podium/-/podium-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/podium/-/podium-1.0.0.tgz",
|
||||||
|
@ -1616,6 +1626,12 @@
|
||||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"abstract-logging": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-i33q/TEFWbwo93ck3RuzAXcnjBs=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"accept": {
|
"accept": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/accept/-/accept-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/accept/-/accept-3.0.2.tgz",
|
||||||
|
@ -2246,6 +2262,17 @@
|
||||||
"type-is": "^1.6.16"
|
"type-is": "^1.6.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"apollo-server-fastify": {
|
||||||
|
"version": "file:packages/apollo-server-fastify",
|
||||||
|
"requires": {
|
||||||
|
"@apollographql/graphql-playground-html": "^1.6.6",
|
||||||
|
"apollo-server-core": "file:packages/apollo-server-core",
|
||||||
|
"fastify-accepts": "^0.5.0",
|
||||||
|
"fastify-cors": "^0.2.0",
|
||||||
|
"graphql-subscriptions": "^1.0.0",
|
||||||
|
"graphql-tools": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"apollo-server-hapi": {
|
"apollo-server-hapi": {
|
||||||
"version": "file:packages/apollo-server-hapi",
|
"version": "file:packages/apollo-server-hapi",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -2554,6 +2581,33 @@
|
||||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"avvio": {
|
||||||
|
"version": "5.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/avvio/-/avvio-5.9.0.tgz",
|
||||||
|
"integrity": "sha512-bzgrSPRdU1T/AkhEuXWAA6cJCFA3zApLk+5fkpcQt4US9YAI52AFYnsGX1HSCF2bHSltEYfk7fbffYu4WnazmA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"debug": "^3.1.0",
|
||||||
|
"fastq": "^1.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "3.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||||
|
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"aws-sign2": {
|
"aws-sign2": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
|
@ -3342,7 +3396,7 @@
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -4105,6 +4159,12 @@
|
||||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"deepmerge": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-a8z8bkgHsAML+uHLqmMS83HHlpy3PvZOOuiTQqaa3wu8ZVg3h0hqHk6aCsGdOnZV2XMM/FRimNGjUh0KCcmHBw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"default-require-extensions": {
|
"default-require-extensions": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
|
||||||
|
@ -4200,7 +4260,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"globby": {
|
"globby": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
"resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
||||||
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -4213,7 +4273,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pify": {
|
"pify": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
|
@ -4748,6 +4808,12 @@
|
||||||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fast-decode-uri-component": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-WQSYVKn6tDW/3htASeUkrx5LcnuTENQIZQPCVlwdnvIJ7bYtSpoJYq38MgUJnx1CQIR1gjZ8HJxAEcN4gqugBg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||||
|
@ -5080,17 +5146,157 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fast-json-parse": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||||
},
|
},
|
||||||
|
"fast-json-stringify": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-qO+GSdwCQHXJjoRbS/pYJzzz8BNUrCk0jdPhDg68mdIG/hOC0k66PUKFz300LAH42vNQkuPFvpwa0JV44ZG3Uw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.5.4",
|
||||||
|
"deepmerge": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"fast-levenshtein": {
|
"fast-levenshtein": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"fast-safe-stringify": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"fastify": {
|
||||||
|
"version": "1.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastify/-/fastify-1.13.0.tgz",
|
||||||
|
"integrity": "sha512-0aqsHEk2WtgGxPVDTOqDLv5XLHQE2EuH7eCq4XRLLnktLehNvr3/Afi/nEn6pPoLiVGMrbWHv4l1+wDhiSIFoA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/pino": "^4.16.0",
|
||||||
|
"abstract-logging": "^1.0.0",
|
||||||
|
"ajv": "^6.5.4",
|
||||||
|
"avvio": "^5.8.0",
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"fast-json-stringify": "^1.8.0",
|
||||||
|
"find-my-way": "^1.15.3",
|
||||||
|
"flatstr": "^1.0.8",
|
||||||
|
"light-my-request": "^3.0.0",
|
||||||
|
"middie": "^3.1.0",
|
||||||
|
"pino": "^4.17.3",
|
||||||
|
"proxy-addr": "^2.0.3",
|
||||||
|
"tiny-lru": "^1.6.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fastify-accepts": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastify-accepts/-/fastify-accepts-0.5.0.tgz",
|
||||||
|
"integrity": "sha1-wXwgEnjyv8Ub+5P/5I78T8QP02M=",
|
||||||
|
"requires": {
|
||||||
|
"accepts": "^1.3.3",
|
||||||
|
"fastify-plugin": "^0.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fastify-cors": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastify-cors/-/fastify-cors-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-bw14FmjHm8oF4TDLkwj2TpssH6O2gE0NpsRqLe7F1Gh9Jf30Lx9ZzIznhqaAKOYS+LJqLIt5snurv7urgqYntA==",
|
||||||
|
"requires": {
|
||||||
|
"fastify-plugin": "^1.2.0",
|
||||||
|
"vary": "^1.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"fastify-plugin": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-l6uqDyBp3gBjLQRAi3j2NwSvlbe9LuqULZugnO9iRFfYHWd2SpsZBLI1l4Jakk0VMGfYlB322JPIPYh/2qSHig==",
|
||||||
|
"requires": {
|
||||||
|
"semver": "^5.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fastify-plugin": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "http://registry.npmjs.org/fastify-plugin/-/fastify-plugin-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-oRJdjdudgCkQQUARNeh2rkbxFAmj2OhCJSVBNBLUbhS0orF+IMQ4u/bc661N1jh/wDI2J+YKmXmmHSVFQI4e7A==",
|
||||||
|
"requires": {
|
||||||
|
"semver": "^5.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fastq": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"reusify": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fb-watchman": {
|
"fb-watchman": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.0.tgz",
|
||||||
|
@ -5179,6 +5385,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"find-my-way": {
|
||||||
|
"version": "1.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-1.17.0.tgz",
|
||||||
|
"integrity": "sha512-V/ROUAESJakNZXmvgJmaCwhB8d4M79/RgWWiKn4tu/6FGjiySYfJuYXip1rV7fORWEzbL0pmfg9smkRQ+tmXjg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-decode-uri-component": "^1.0.0",
|
||||||
|
"safe-regex": "^1.1.0",
|
||||||
|
"semver-store": "^0.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"find-npm-prefix": {
|
"find-npm-prefix": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz",
|
||||||
|
@ -5200,6 +5417,12 @@
|
||||||
"locate-path": "^3.0.0"
|
"locate-path": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"flatstr": {
|
||||||
|
"version": "1.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.9.tgz",
|
||||||
|
"integrity": "sha512-qFlJnOBWDfIaunF54/lBqNKmXOI0HqNhu+mHkLmbaBXlS71PUd9OjFOdyevHt/aHoHB1+eW7eKHgRKOG5aHSpw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"flush-write-stream": {
|
"flush-write-stream": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz",
|
||||||
|
@ -5423,7 +5646,8 @@
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
@ -5447,13 +5671,15 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -5470,19 +5696,22 @@
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -5613,7 +5842,8 @@
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
|
@ -5627,6 +5857,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -5643,6 +5874,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
@ -5651,13 +5883,15 @@
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.2.4",
|
"version": "2.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz",
|
||||||
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
|
"integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
|
@ -5678,6 +5912,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
|
@ -5766,7 +6001,8 @@
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
|
@ -5780,6 +6016,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
|
@ -5875,7 +6112,8 @@
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
|
||||||
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
|
@ -5917,6 +6155,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
|
@ -5938,6 +6177,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -5986,13 +6226,15 @@
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
|
||||||
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
|
"integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -8807,6 +9049,62 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"light-my-request": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZSFO3XnQNSKsHR/E2ZMga5btdiIa3sNoT6CZIZ8Hr1VHJWBNcRRurVYpQlaJqvQqwg3aOl09QpVOnjB9ajnYHQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.0.0",
|
||||||
|
"readable-stream": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.0.tgz",
|
||||||
|
@ -9216,7 +9514,7 @@
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -9248,7 +9546,7 @@
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -9828,6 +10126,24 @@
|
||||||
"regex-cache": "^0.4.2"
|
"regex-cache": "^0.4.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"middie": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/middie/-/middie-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-anXJ0QJfQcgneQvcWAJBwVvNckRLI68zWNEUv/7/7z/Wb/UMFTHmugpM93T4Q75+DclC9FHdms8cTseDQEV3yA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"path-to-regexp": "^2.0.0",
|
||||||
|
"reusify": "^1.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"path-to-regexp": {
|
||||||
|
"version": "2.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz",
|
||||||
|
"integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"mime": {
|
"mime": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
|
||||||
|
@ -10877,6 +11193,41 @@
|
||||||
"pinkie": "^2.0.0"
|
"pinkie": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"pino": {
|
||||||
|
"version": "4.17.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino/-/pino-4.17.6.tgz",
|
||||||
|
"integrity": "sha512-LFDwmhyWLBnmwO/2UFbWu1jEGVDzaPupaVdx0XcZ3tIAx1EDEBauzxXf2S0UcFK7oe+X9MApjH0hx9U1XMgfCA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"chalk": "^2.4.1",
|
||||||
|
"fast-json-parse": "^1.0.3",
|
||||||
|
"fast-safe-stringify": "^1.2.3",
|
||||||
|
"flatstr": "^1.0.5",
|
||||||
|
"pino-std-serializers": "^2.0.0",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"quick-format-unescaped": "^1.1.2",
|
||||||
|
"split2": "^2.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": {
|
||||||
|
"version": "2.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
||||||
|
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi-styles": "^3.2.1",
|
||||||
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
"supports-color": "^5.3.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pino-std-serializers": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-klfGoOsP6sJH7ON796G4xoUSx2fkpFgKHO4YVVO2zmz31jR+etzc/QzGJILaOIiCD6HTCFgkPx+XN8nk+ruqPw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"pkg-dir": {
|
"pkg-dir": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
|
||||||
|
@ -11160,6 +11511,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"quick-format-unescaped": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-safe-stringify": "^1.0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"quick-lru": {
|
"quick-lru": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz",
|
||||||
|
@ -11552,6 +11912,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||||
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
|
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs="
|
||||||
},
|
},
|
||||||
|
"reusify": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"rimraf": {
|
"rimraf": {
|
||||||
"version": "2.6.2",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||||
|
@ -11927,8 +12293,7 @@
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "5.6.0",
|
"version": "5.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
|
||||||
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==",
|
"integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"semver-compare": {
|
"semver-compare": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -11936,6 +12301,12 @@
|
||||||
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"semver-store": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.16.2",
|
"version": "0.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
|
||||||
|
@ -12080,7 +12451,7 @@
|
||||||
},
|
},
|
||||||
"slice-ansi": {
|
"slice-ansi": {
|
||||||
"version": "0.0.4",
|
"version": "0.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
|
"resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
|
||||||
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
|
"integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -12760,6 +13131,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"tiny-lru": {
|
||||||
|
"version": "1.6.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-1.6.4.tgz",
|
||||||
|
"integrity": "sha512-Et+J3Css66XPSLWjLF9wmgbECsGiExlEL+jxsFerTQF6N6dpxswDTPAfIrAbQKO5c1uhgq2xvo5zMk1W+kBDNA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"tmp": {
|
"tmp": {
|
||||||
"version": "0.0.33",
|
"version": "0.0.33",
|
||||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||||
|
@ -12907,7 +13284,7 @@
|
||||||
},
|
},
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
@ -13161,6 +13538,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"uri-js": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"punycode": "^2.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"urijs": {
|
"urijs": {
|
||||||
"version": "1.19.1",
|
"version": "1.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz",
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
"apollo-server-env": "file:packages/apollo-server-env",
|
"apollo-server-env": "file:packages/apollo-server-env",
|
||||||
"apollo-server-errors": "file:packages/apollo-server-errors",
|
"apollo-server-errors": "file:packages/apollo-server-errors",
|
||||||
"apollo-server-express": "file:packages/apollo-server-express",
|
"apollo-server-express": "file:packages/apollo-server-express",
|
||||||
|
"apollo-server-fastify": "file:packages/apollo-server-fastify",
|
||||||
"apollo-server-hapi": "file:packages/apollo-server-hapi",
|
"apollo-server-hapi": "file:packages/apollo-server-hapi",
|
||||||
"apollo-server-integration-testsuite": "file:packages/apollo-server-integration-testsuite",
|
"apollo-server-integration-testsuite": "file:packages/apollo-server-integration-testsuite",
|
||||||
"apollo-server-koa": "file:packages/apollo-server-koa",
|
"apollo-server-koa": "file:packages/apollo-server-koa",
|
||||||
|
@ -94,6 +95,7 @@
|
||||||
"codecov": "3.1.0",
|
"codecov": "3.1.0",
|
||||||
"connect": "3.6.6",
|
"connect": "3.6.6",
|
||||||
"express": "4.16.4",
|
"express": "4.16.4",
|
||||||
|
"fastify": "1.13.0",
|
||||||
"fibers": "3.1.1",
|
"fibers": "3.1.1",
|
||||||
"form-data": "2.3.3",
|
"form-data": "2.3.3",
|
||||||
"graphql": "14.1.1",
|
"graphql": "14.1.1",
|
||||||
|
|
6
packages/apollo-server-fastify/.npmignore
Normal file
6
packages/apollo-server-fastify/.npmignore
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
*
|
||||||
|
!src/**/*
|
||||||
|
!dist/**/*
|
||||||
|
dist/**/*.test.*
|
||||||
|
!package.json
|
||||||
|
!README.md
|
41
packages/apollo-server-fastify/README.md
Normal file
41
packages/apollo-server-fastify/README.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
---
|
||||||
|
title: Fastify
|
||||||
|
description: Setting up Apollo Server with Fastify
|
||||||
|
---
|
||||||
|
|
||||||
|
[](https://badge.fury.io/js/apollo-server-fastify) [](https://circleci.com/gh/apollographql/apollo-server) [](https://coveralls.io/github/apollographql/apollo-server?branch=master) [](https://www.apollographql.com/#slack)
|
||||||
|
|
||||||
|
This is the Fastify integration of GraphQL Server. Apollo Server is a community-maintained open-source GraphQL server that works with many Node.js HTTP server frameworks. [Read the docs](https://www.apollographql.com/docs/apollo-server/). [Read the CHANGELOG.](https://github.com/apollographql/apollo-server/blob/master/CHANGELOG.md)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install apollo-server-fastify
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fastify
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { ApolloServer, gql } = require('apollo-server-fastify');
|
||||||
|
const { typeDefs, resolvers } = require('./module');
|
||||||
|
|
||||||
|
const server = new ApolloServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
});
|
||||||
|
|
||||||
|
const app = require('fastify')();
|
||||||
|
|
||||||
|
(async function () {
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen(3000);
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Principles
|
||||||
|
|
||||||
|
GraphQL Server is built with the following principles in mind:
|
||||||
|
|
||||||
|
* **By the community, for the community**: GraphQL Server's development is driven by the needs of developers
|
||||||
|
* **Simplicity**: by keeping things simple, GraphQL Server is easier to use, easier to contribute to, and more secure
|
||||||
|
* **Performance**: GraphQL Server is well-tested and production-ready - no modifications needed
|
||||||
|
|
||||||
|
Anyone is welcome to contribute to GraphQL Server, just read [CONTRIBUTING.md](https://github.com/apollographql/apollo-server/blob/master/CONTRIBUTING.md), take a look at the [roadmap](https://github.com/apollographql/apollo-server/blob/master/ROADMAP.md) and make your first PR!
|
3
packages/apollo-server-fastify/jest.config.js
Normal file
3
packages/apollo-server-fastify/jest.config.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
const config = require('../../jest.config.base');
|
||||||
|
|
||||||
|
module.exports = Object.assign(Object.create(null), config);
|
41
packages/apollo-server-fastify/package.json
Normal file
41
packages/apollo-server-fastify/package.json
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "apollo-server-fastify",
|
||||||
|
"version": "2.2.2",
|
||||||
|
"description": "Production-ready Node.js GraphQL server for Fastify",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"types": "dist/index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-fastify"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"GraphQL",
|
||||||
|
"Apollo",
|
||||||
|
"Server",
|
||||||
|
"Fastify",
|
||||||
|
"Javascript"
|
||||||
|
],
|
||||||
|
"author": "opensource@apollographql.com",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/apollographql/apollo-server/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/apollographql/apollo-server#readme",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@apollographql/graphql-playground-html": "^1.6.6",
|
||||||
|
"apollo-server-core": "file:../apollo-server-core",
|
||||||
|
"fastify-accepts": "^0.5.0",
|
||||||
|
"fastify-cors": "^0.2.0",
|
||||||
|
"graphql-subscriptions": "^1.0.0",
|
||||||
|
"graphql-tools": "^4.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"apollo-server-integration-testsuite": "file:../apollo-server-integration-testsuite"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"graphql": "^0.12.0 || ^0.13.0 || ^14.0.0"
|
||||||
|
}
|
||||||
|
}
|
191
packages/apollo-server-fastify/src/ApolloServer.ts
Normal file
191
packages/apollo-server-fastify/src/ApolloServer.ts
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
import { renderPlaygroundPage } from '@apollographql/graphql-playground-html';
|
||||||
|
import { Accepts } from 'accepts';
|
||||||
|
import {
|
||||||
|
ApolloServerBase,
|
||||||
|
FileUploadOptions,
|
||||||
|
formatApolloErrors,
|
||||||
|
PlaygroundRenderPageOptions,
|
||||||
|
processFileUploads,
|
||||||
|
} from 'apollo-server-core';
|
||||||
|
import { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';
|
||||||
|
import { IncomingMessage, OutgoingMessage, Server } from 'http';
|
||||||
|
import { graphqlFastify } from './fastifyApollo';
|
||||||
|
|
||||||
|
const kMultipart = Symbol('multipart');
|
||||||
|
const fastJson = require('fast-json-stringify');
|
||||||
|
|
||||||
|
export interface ServerRegistration {
|
||||||
|
path?: string;
|
||||||
|
cors?: object | boolean;
|
||||||
|
onHealthCheck?: (req: FastifyRequest<IncomingMessage>) => Promise<any>;
|
||||||
|
disableHealthCheck?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stringifyHealthCheck = fastJson({
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
status: {
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fileUploadMiddleware = (
|
||||||
|
uploadsConfig: FileUploadOptions,
|
||||||
|
server: ApolloServerBase,
|
||||||
|
) => (
|
||||||
|
req: FastifyRequest<IncomingMessage>,
|
||||||
|
reply: FastifyReply<OutgoingMessage>,
|
||||||
|
done: (err: Error | null, body?: any) => void,
|
||||||
|
) => {
|
||||||
|
if (
|
||||||
|
(req.req as any)[kMultipart] &&
|
||||||
|
typeof processFileUploads === 'function'
|
||||||
|
) {
|
||||||
|
processFileUploads(req.req, reply.res, uploadsConfig)
|
||||||
|
.then(body => {
|
||||||
|
req.body = body;
|
||||||
|
done(null);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
if (error.status && error.expose) reply.status(error.status);
|
||||||
|
|
||||||
|
throw formatApolloErrors([error], {
|
||||||
|
formatter: server.requestOptions.formatError,
|
||||||
|
debug: server.requestOptions.debug,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
done(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export class ApolloServer extends ApolloServerBase {
|
||||||
|
protected supportsSubscriptions(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected supportsUploads(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public createHandler({
|
||||||
|
path,
|
||||||
|
cors,
|
||||||
|
disableHealthCheck,
|
||||||
|
onHealthCheck,
|
||||||
|
}: ServerRegistration = {}) {
|
||||||
|
this.graphqlPath = path ? path : '/graphql';
|
||||||
|
const promiseWillStart = this.willStart();
|
||||||
|
|
||||||
|
return async (
|
||||||
|
app: FastifyInstance<Server, IncomingMessage, OutgoingMessage>,
|
||||||
|
) => {
|
||||||
|
await promiseWillStart;
|
||||||
|
|
||||||
|
if (!disableHealthCheck) {
|
||||||
|
app.get('/.well-known/apollo/server-health', async (req, res) => {
|
||||||
|
// Response follows https://tools.ietf.org/html/draft-inadarei-api-health-check-01
|
||||||
|
res.type('application/health+json');
|
||||||
|
|
||||||
|
if (onHealthCheck) {
|
||||||
|
try {
|
||||||
|
await onHealthCheck(req);
|
||||||
|
res.send(stringifyHealthCheck({ status: 'pass' }));
|
||||||
|
} catch (e) {
|
||||||
|
res.status(503).send(stringifyHealthCheck({ status: 'fail' }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.send(stringifyHealthCheck({ status: 'pass' }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
app.register(
|
||||||
|
async instance => {
|
||||||
|
instance.register(require('fastify-accepts'));
|
||||||
|
|
||||||
|
if (cors === true) {
|
||||||
|
instance.register(require('fastify-cors'));
|
||||||
|
} else if (cors !== false) {
|
||||||
|
instance.register(require('fastify-cors'), cors);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.setNotFoundHandler((_request, reply) => {
|
||||||
|
reply.code(405);
|
||||||
|
reply.header('allow', 'GET, POST');
|
||||||
|
reply.send();
|
||||||
|
});
|
||||||
|
|
||||||
|
const beforeHandlers = [
|
||||||
|
(
|
||||||
|
req: FastifyRequest<IncomingMessage>,
|
||||||
|
reply: FastifyReply<OutgoingMessage>,
|
||||||
|
done: () => void,
|
||||||
|
) => {
|
||||||
|
// Note: if you enable playground in production and expect to be able to see your
|
||||||
|
// schema, you'll need to manually specify `introspection: true` in the
|
||||||
|
// ApolloServer constructor; by default, the introspection query is only
|
||||||
|
// enabled in dev.
|
||||||
|
if (this.playgroundOptions && req.req.method === 'GET') {
|
||||||
|
// perform more expensive content-type check only if necessary
|
||||||
|
const accept = (req as any).accepts() as Accepts;
|
||||||
|
const types = accept.types() as string[];
|
||||||
|
const prefersHTML =
|
||||||
|
types.find(
|
||||||
|
(x: string) =>
|
||||||
|
x === 'text/html' || x === 'application/json',
|
||||||
|
) === 'text/html';
|
||||||
|
|
||||||
|
if (prefersHTML) {
|
||||||
|
const playgroundRenderPageOptions: PlaygroundRenderPageOptions = {
|
||||||
|
endpoint: this.graphqlPath,
|
||||||
|
subscriptionEndpoint: this.subscriptionsPath,
|
||||||
|
...this.playgroundOptions,
|
||||||
|
};
|
||||||
|
reply.type('text/html');
|
||||||
|
const playground = renderPlaygroundPage(
|
||||||
|
playgroundRenderPageOptions,
|
||||||
|
);
|
||||||
|
reply.send(playground);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
if (typeof processFileUploads === 'function' && this.uploadsConfig) {
|
||||||
|
instance.addContentTypeParser(
|
||||||
|
'multipart',
|
||||||
|
(
|
||||||
|
request: IncomingMessage,
|
||||||
|
done: (err: Error | null, body?: any) => void,
|
||||||
|
) => {
|
||||||
|
(request as any)[kMultipart] = true;
|
||||||
|
done(null);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
beforeHandlers.push(fileUploadMiddleware(this.uploadsConfig, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.route({
|
||||||
|
method: ['GET', 'POST'],
|
||||||
|
url: '/',
|
||||||
|
beforeHandler: beforeHandlers,
|
||||||
|
handler: await graphqlFastify(this.graphQLServerOptions.bind(this)),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prefix: this.graphqlPath,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const registerServer = () => {
|
||||||
|
throw new Error(
|
||||||
|
'Please use server.createHandler instead of registerServer. This warning will be removed in the next release',
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,836 @@
|
||||||
|
import { FastifyInstance } from 'fastify';
|
||||||
|
import fastify from 'fastify';
|
||||||
|
|
||||||
|
import http from 'http';
|
||||||
|
|
||||||
|
import request from 'request';
|
||||||
|
import FormData from 'form-data';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { createApolloFetch } from 'apollo-fetch';
|
||||||
|
|
||||||
|
import { gql, AuthenticationError, Config } from 'apollo-server-core';
|
||||||
|
import { ApolloServer, ServerRegistration } from '../ApolloServer';
|
||||||
|
|
||||||
|
import {
|
||||||
|
NODE_MAJOR_VERSION,
|
||||||
|
testApolloServer,
|
||||||
|
createServerInfo,
|
||||||
|
} from 'apollo-server-integration-testsuite';
|
||||||
|
|
||||||
|
const typeDefs = gql`
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
hello: () => 'hi',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const port = 9999;
|
||||||
|
|
||||||
|
describe('apollo-server-fastify', () => {
|
||||||
|
let server: ApolloServer;
|
||||||
|
let httpServer: http.Server;
|
||||||
|
let app: FastifyInstance;
|
||||||
|
|
||||||
|
testApolloServer(
|
||||||
|
async options => {
|
||||||
|
server = new ApolloServer(options);
|
||||||
|
app = fastify();
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen(port);
|
||||||
|
return createServerInfo(server, app.server);
|
||||||
|
},
|
||||||
|
async () => {
|
||||||
|
if (server) await server.stop();
|
||||||
|
if (app) await new Promise(resolve => app.close(() => resolve()));
|
||||||
|
if (httpServer && httpServer.listening) await httpServer.close();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('apollo-server-fastify', () => {
|
||||||
|
let server: ApolloServer;
|
||||||
|
let app: FastifyInstance;
|
||||||
|
let httpServer: http.Server;
|
||||||
|
|
||||||
|
async function createServer(
|
||||||
|
serverOptions: Config,
|
||||||
|
options: Partial<ServerRegistration> = {},
|
||||||
|
) {
|
||||||
|
server = new ApolloServer(serverOptions);
|
||||||
|
app = fastify();
|
||||||
|
|
||||||
|
app.register(server.createHandler(options));
|
||||||
|
await app.listen(port);
|
||||||
|
|
||||||
|
return createServerInfo(server, app.server);
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
if (server) await server.stop();
|
||||||
|
if (app) await new Promise(resolve => app.close(() => resolve()));
|
||||||
|
if (httpServer) await httpServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('constructor', async () => {
|
||||||
|
it('accepts typeDefs and resolvers', () => {
|
||||||
|
return createServer({ typeDefs, resolvers });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('applyMiddleware', async () => {
|
||||||
|
it('can be queried', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
});
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const result = await apolloFetch({ query: '{hello}' });
|
||||||
|
|
||||||
|
expect(result.data).toEqual({ hello: 'hi' });
|
||||||
|
expect(result.errors).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX Unclear why this would be something somebody would want (vs enabling
|
||||||
|
// introspection without graphql-playground, which seems reasonable, eg you
|
||||||
|
// have your own graphql-playground setup with a custom link)
|
||||||
|
it('can enable playground separately from introspection during production', async () => {
|
||||||
|
const INTROSPECTION_QUERY = `
|
||||||
|
{
|
||||||
|
__schema {
|
||||||
|
directives {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
introspection: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const result = await apolloFetch({ query: INTROSPECTION_QUERY });
|
||||||
|
|
||||||
|
expect(result.errors.length).toEqual(1);
|
||||||
|
expect(result.errors[0].extensions.code).toEqual(
|
||||||
|
'GRAPHQL_VALIDATION_FAILED',
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise<http.Server>((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url: uri,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
accept:
|
||||||
|
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).toMatch('GraphQLPlayground');
|
||||||
|
expect(response.statusCode).toEqual(200);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders GraphQL playground by default when browser requests', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
|
||||||
|
const { url } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise<http.Server>((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
accept:
|
||||||
|
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).toMatch('GraphQLPlayground');
|
||||||
|
expect(body).not.toMatch('settings');
|
||||||
|
expect(response.statusCode).toEqual(200);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const playgroundPartialOptionsTest = async () => {
|
||||||
|
const defaultQuery = 'query { foo { bar } }';
|
||||||
|
const endpoint = '/fumanchupacabra';
|
||||||
|
const { url } = await createServer(
|
||||||
|
{
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
playground: {
|
||||||
|
// https://github.com/apollographql/graphql-playground/blob/0e452d2005fcd26f10fbdcc4eed3b2e2af935e3a/packages/graphql-playground-html/src/render-playground-page.ts#L16-L24
|
||||||
|
// must be made partial
|
||||||
|
settings: {
|
||||||
|
'editor.theme': 'light',
|
||||||
|
} as any,
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
query: defaultQuery,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
endpoint,
|
||||||
|
} as any,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise<http.Server>((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
accept:
|
||||||
|
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
|
||||||
|
Folo: 'bar',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).toMatch('GraphQLPlayground');
|
||||||
|
expect(body).toMatch(`"editor.theme": "light"`);
|
||||||
|
expect(body).toMatch(defaultQuery);
|
||||||
|
expect(body).toMatch(endpoint);
|
||||||
|
expect(response.statusCode).toEqual(200);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
it('accepts partial GraphQL Playground Options in production', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
await playgroundPartialOptionsTest();
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it(
|
||||||
|
'accepts partial GraphQL Playground Options when an environment is ' +
|
||||||
|
'not specified',
|
||||||
|
async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
await playgroundPartialOptionsTest();
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
it('accepts playground options as a boolean', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
|
||||||
|
const { url } = await createServer(
|
||||||
|
{
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
playground: false,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise<http.Server>((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url,
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
accept:
|
||||||
|
'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).not.toMatch('GraphQLPlayground');
|
||||||
|
expect(response.statusCode).not.toEqual(200);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts cors configuration', async () => {
|
||||||
|
const { url: uri } = await createServer(
|
||||||
|
{
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cors: { origin: 'apollographql.com' },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(
|
||||||
|
response.response.headers.get('access-control-allow-origin'),
|
||||||
|
).toEqual('apollographql.com');
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await apolloFetch({ query: '{hello}' });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('healthchecks', () => {
|
||||||
|
afterEach(async () => {
|
||||||
|
await server.stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a healthcheck endpoint', async () => {
|
||||||
|
const { port } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url: `http://localhost:${port}/.well-known/apollo/server-health`,
|
||||||
|
method: 'GET',
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).toEqual(JSON.stringify({ status: 'pass' }));
|
||||||
|
expect(response.statusCode).toEqual(200);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('provides a callback for the healthcheck', async () => {
|
||||||
|
const { port } = await createServer(
|
||||||
|
{
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onHealthCheck: async () => {
|
||||||
|
throw Error("can't connect to DB");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url: `http://localhost:${port}/.well-known/apollo/server-health`,
|
||||||
|
method: 'GET',
|
||||||
|
},
|
||||||
|
(error, response, body) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(body).toEqual(JSON.stringify({ status: 'fail' }));
|
||||||
|
expect(response.statusCode).toEqual(503);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can disable the healthCheck', async () => {
|
||||||
|
const { port } = await createServer(
|
||||||
|
{
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
disableHealthCheck: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request(
|
||||||
|
{
|
||||||
|
url: `http://localhost:${port}/.well-known/apollo/server-health`,
|
||||||
|
method: 'GET',
|
||||||
|
},
|
||||||
|
(error, response) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
expect(response.statusCode).toEqual(404);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// NODE: Skip Node.js 6, but only because `graphql-upload`
|
||||||
|
// doesn't support it.
|
||||||
|
(NODE_MAJOR_VERSION === 6 ? describe.skip : describe)(
|
||||||
|
'file uploads',
|
||||||
|
() => {
|
||||||
|
it('enabled uploads', async () => {
|
||||||
|
const { port } = await createServer({
|
||||||
|
typeDefs: gql`
|
||||||
|
type File {
|
||||||
|
filename: String!
|
||||||
|
mimetype: String!
|
||||||
|
encoding: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
uploads: [File]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
singleUpload(file: Upload!): File!
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
resolvers: {
|
||||||
|
Query: {
|
||||||
|
uploads: () => {},
|
||||||
|
},
|
||||||
|
Mutation: {
|
||||||
|
singleUpload: async (_, args) => {
|
||||||
|
expect((await args.file).stream).toBeDefined();
|
||||||
|
return args.file;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = new FormData();
|
||||||
|
|
||||||
|
body.append(
|
||||||
|
'operations',
|
||||||
|
JSON.stringify({
|
||||||
|
query: `
|
||||||
|
mutation($file: Upload!) {
|
||||||
|
singleUpload(file: $file) {
|
||||||
|
filename
|
||||||
|
encoding
|
||||||
|
mimetype
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables: {
|
||||||
|
file: null,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
body.append('map', JSON.stringify({ 1: ['variables.file'] }));
|
||||||
|
body.append('1', fs.createReadStream('package.json'));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resolved = await fetch(`http://localhost:${port}/graphql`, {
|
||||||
|
method: 'POST',
|
||||||
|
body: body as any,
|
||||||
|
});
|
||||||
|
const text = await resolved.text();
|
||||||
|
const response = JSON.parse(text);
|
||||||
|
|
||||||
|
expect(response.data.singleUpload).toEqual({
|
||||||
|
filename: 'package.json',
|
||||||
|
encoding: '7bit',
|
||||||
|
mimetype: 'application/json',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
// This error began appearing randomly and seems to be a dev dependency bug.
|
||||||
|
// https://github.com/jaydenseric/apollo-upload-server/blob/18ecdbc7a1f8b69ad51b4affbd986400033303d4/test.js#L39-L42
|
||||||
|
if (error.code !== 'EPIPE') throw error;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('errors', () => {
|
||||||
|
it('returns thrown context error as a valid graphql result', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
const typeDefs = gql`
|
||||||
|
type Query {
|
||||||
|
hello: String
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
hello: () => {
|
||||||
|
throw Error('never get here');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
context: () => {
|
||||||
|
throw new AuthenticationError('valid result');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
|
||||||
|
const result = await apolloFetch({ query: '{hello}' });
|
||||||
|
expect(result.errors.length).toEqual(1);
|
||||||
|
expect(result.data).toBeUndefined();
|
||||||
|
|
||||||
|
const e = result.errors[0];
|
||||||
|
expect(e.message).toMatch('valid result');
|
||||||
|
expect(e.extensions).toBeDefined();
|
||||||
|
expect(e.extensions.code).toEqual('UNAUTHENTICATED');
|
||||||
|
expect(e.extensions.exception.stacktrace).toBeDefined();
|
||||||
|
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('propogates error codes in dev mode', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
delete process.env.NODE_ENV;
|
||||||
|
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs: gql`
|
||||||
|
type Query {
|
||||||
|
error: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
resolvers: {
|
||||||
|
Query: {
|
||||||
|
error: () => {
|
||||||
|
throw new AuthenticationError('we the best music');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
|
||||||
|
const result = await apolloFetch({ query: `{error}` });
|
||||||
|
expect(result.data).toBeDefined();
|
||||||
|
expect(result.data).toEqual({ error: null });
|
||||||
|
|
||||||
|
expect(result.errors).toBeDefined();
|
||||||
|
expect(result.errors.length).toEqual(1);
|
||||||
|
expect(result.errors[0].extensions.code).toEqual('UNAUTHENTICATED');
|
||||||
|
expect(result.errors[0].extensions.exception).toBeDefined();
|
||||||
|
expect(result.errors[0].extensions.exception.stacktrace).toBeDefined();
|
||||||
|
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('propogates error codes in production', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs: gql`
|
||||||
|
type Query {
|
||||||
|
error: String
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
resolvers: {
|
||||||
|
Query: {
|
||||||
|
error: () => {
|
||||||
|
throw new AuthenticationError('we the best music');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
|
||||||
|
const result = await apolloFetch({ query: `{error}` });
|
||||||
|
expect(result.data).toBeDefined();
|
||||||
|
expect(result.data).toEqual({ error: null });
|
||||||
|
|
||||||
|
expect(result.errors).toBeDefined();
|
||||||
|
expect(result.errors.length).toEqual(1);
|
||||||
|
expect(result.errors[0].extensions.code).toEqual('UNAUTHENTICATED');
|
||||||
|
expect(result.errors[0].extensions.exception).toBeUndefined();
|
||||||
|
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('propogates error codes with null response in production', async () => {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs: gql`
|
||||||
|
type Query {
|
||||||
|
error: String!
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
resolvers: {
|
||||||
|
Query: {
|
||||||
|
error: () => {
|
||||||
|
throw new AuthenticationError('we the best music');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
|
||||||
|
const result = await apolloFetch({ query: `{error}` });
|
||||||
|
expect(result.data).toBeNull();
|
||||||
|
|
||||||
|
expect(result.errors).toBeDefined();
|
||||||
|
expect(result.errors.length).toEqual(1);
|
||||||
|
expect(result.errors[0].extensions.code).toEqual('UNAUTHENTICATED');
|
||||||
|
expect(result.errors[0].extensions.exception).toBeUndefined();
|
||||||
|
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('extensions', () => {
|
||||||
|
const books = [
|
||||||
|
{
|
||||||
|
title: 'H',
|
||||||
|
author: 'J',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const typeDefs = gql`
|
||||||
|
type Book {
|
||||||
|
title: String
|
||||||
|
author: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cook @cacheControl(maxAge: 200) {
|
||||||
|
title: String
|
||||||
|
author: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Pook @cacheControl(maxAge: 200) {
|
||||||
|
title: String
|
||||||
|
books: [Book] @cacheControl(maxAge: 20, scope: PRIVATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
books: [Book]
|
||||||
|
cooks: [Cook]
|
||||||
|
pooks: [Pook]
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
books: () => books,
|
||||||
|
cooks: () => books,
|
||||||
|
pooks: () => [{ title: 'pook', books }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Cache Control Headers', () => {
|
||||||
|
it('applies cacheControl Headers and strips out extension', async () => {
|
||||||
|
const { url: uri } = await createServer({ typeDefs, resolvers });
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(response.response.headers.get('cache-control')).toEqual(
|
||||||
|
'max-age=200, public',
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ cooks { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ cooks: books });
|
||||||
|
expect(result.extensions).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains no cacheControl Headers and keeps extension with engine proxy', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
cacheControl: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(response.response.headers.get('cache-control')).toBeNull();
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ cooks { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ cooks: books });
|
||||||
|
expect(result.extensions).toBeDefined();
|
||||||
|
expect(result.extensions.cacheControl).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains no cacheControl Headers when uncachable', async () => {
|
||||||
|
const { url: uri } = await createServer({ typeDefs, resolvers });
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(response.response.headers.get('cache-control')).toBeNull();
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ books { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ books });
|
||||||
|
expect(result.extensions).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains private cacheControl Headers when scoped', async () => {
|
||||||
|
const { url: uri } = await createServer({ typeDefs, resolvers });
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(response.response.headers.get('cache-control')).toEqual(
|
||||||
|
'max-age=20, private',
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ pooks { title books { title author } } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({
|
||||||
|
pooks: [{ title: 'pook', books }],
|
||||||
|
});
|
||||||
|
expect(result.extensions).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('runs when cache-control is false', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
cacheControl: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri }).useAfter(
|
||||||
|
(response, next) => {
|
||||||
|
expect(response.response.headers.get('cache-control')).toBeNull();
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ pooks { title books { title author } } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({
|
||||||
|
pooks: [{ title: 'pook', books }],
|
||||||
|
});
|
||||||
|
expect(result.extensions).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Tracing', () => {
|
||||||
|
const typeDefs = gql`
|
||||||
|
type Book {
|
||||||
|
title: String
|
||||||
|
author: String
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
books: [Book]
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
books: () => books,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
it('applies tracing extension', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
tracing: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ books { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ books });
|
||||||
|
expect(result.extensions).toBeDefined();
|
||||||
|
expect(result.extensions.tracing).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('applies tracing extension with cache control enabled', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
tracing: true,
|
||||||
|
cacheControl: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ books { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ books });
|
||||||
|
expect(result.extensions).toBeDefined();
|
||||||
|
expect(result.extensions.tracing).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
xit('applies tracing extension with engine enabled', async () => {
|
||||||
|
const { url: uri } = await createServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
tracing: true,
|
||||||
|
engine: {
|
||||||
|
apiKey: 'service:my-app:secret',
|
||||||
|
maxAttempts: 0,
|
||||||
|
endpointUrl: 'l',
|
||||||
|
reportErrorFunction: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const result = await apolloFetch({
|
||||||
|
query: `{ books { title author } }`,
|
||||||
|
});
|
||||||
|
expect(result.data).toEqual({ books });
|
||||||
|
expect(result.extensions).toBeDefined();
|
||||||
|
expect(result.extensions.tracing).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
140
packages/apollo-server-fastify/src/__tests__/datasource.test.ts
Normal file
140
packages/apollo-server-fastify/src/__tests__/datasource.test.ts
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
import fastify, { FastifyInstance } from 'fastify';
|
||||||
|
|
||||||
|
import { RESTDataSource } from 'apollo-datasource-rest';
|
||||||
|
|
||||||
|
import { createApolloFetch } from 'apollo-fetch';
|
||||||
|
import { ApolloServer } from '../ApolloServer';
|
||||||
|
|
||||||
|
import { createServerInfo } from 'apollo-server-integration-testsuite';
|
||||||
|
import { gql } from '../index';
|
||||||
|
|
||||||
|
const restPort = 4001;
|
||||||
|
|
||||||
|
export class IdAPI extends RESTDataSource {
|
||||||
|
baseURL = `http://localhost:${restPort}/`;
|
||||||
|
|
||||||
|
async getId(id: string) {
|
||||||
|
return this.get(`id/${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getStringId(id: string) {
|
||||||
|
return this.get(`str/${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeDefs = gql`
|
||||||
|
type Query {
|
||||||
|
id: String
|
||||||
|
stringId: String
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
id: async (_source, _args, { dataSources }) => {
|
||||||
|
return (await dataSources.id.getId('hi')).id;
|
||||||
|
},
|
||||||
|
stringId: async (_source, _args, { dataSources }) => {
|
||||||
|
return dataSources.id.getStringId('hi');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let restCalls = 0;
|
||||||
|
const restAPI = fastify();
|
||||||
|
|
||||||
|
restAPI.get('/id/:id', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
restCalls++;
|
||||||
|
res.header('Content-Type', 'application/json');
|
||||||
|
res.header('Cache-Control', 'max-age=2000, public');
|
||||||
|
res.send({ id });
|
||||||
|
});
|
||||||
|
|
||||||
|
restAPI.get('/str/:id', (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
restCalls++;
|
||||||
|
res.header('Content-Type', 'text/plain');
|
||||||
|
res.header('Cache-Control', 'max-age=2000, public');
|
||||||
|
res.send(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('apollo-server-fastify', () => {
|
||||||
|
let restServer: FastifyInstance;
|
||||||
|
let app: FastifyInstance;
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await restAPI.listen(restPort);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await new Promise(resolve => restServer.close(() => resolve()));
|
||||||
|
});
|
||||||
|
|
||||||
|
let server: ApolloServer;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
restCalls = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await server.stop();
|
||||||
|
await new Promise(resolve => app.close(() => resolve()));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses the cache', async () => {
|
||||||
|
server = new ApolloServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
dataSources: () => ({
|
||||||
|
id: new IdAPI(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
app = fastify();
|
||||||
|
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen(6667);
|
||||||
|
const { url: uri } = createServerInfo(server, app.server);
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const firstResult = await apolloFetch({ query: '{ id }' });
|
||||||
|
|
||||||
|
expect(firstResult.data).toEqual({ id: 'hi' });
|
||||||
|
expect(firstResult.errors).toBeUndefined();
|
||||||
|
expect(restCalls).toEqual(1);
|
||||||
|
|
||||||
|
const secondResult = await apolloFetch({ query: '{ id }' });
|
||||||
|
|
||||||
|
expect(secondResult.data).toEqual({ id: 'hi' });
|
||||||
|
expect(secondResult.errors).toBeUndefined();
|
||||||
|
expect(restCalls).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can cache a string from the backend', async () => {
|
||||||
|
server = new ApolloServer({
|
||||||
|
typeDefs,
|
||||||
|
resolvers,
|
||||||
|
dataSources: () => ({
|
||||||
|
id: new IdAPI(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
app = fastify();
|
||||||
|
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen(6668);
|
||||||
|
const { url: uri } = createServerInfo(server, app.server);
|
||||||
|
|
||||||
|
const apolloFetch = createApolloFetch({ uri });
|
||||||
|
const firstResult = await apolloFetch({ query: '{ id: stringId }' });
|
||||||
|
|
||||||
|
expect(firstResult.data).toEqual({ id: 'hi' });
|
||||||
|
expect(firstResult.errors).toBeUndefined();
|
||||||
|
expect(restCalls).toEqual(1);
|
||||||
|
|
||||||
|
const secondResult = await apolloFetch({ query: '{ id: stringId }' });
|
||||||
|
|
||||||
|
expect(secondResult.data).toEqual({ id: 'hi' });
|
||||||
|
expect(secondResult.errors).toBeUndefined();
|
||||||
|
expect(restCalls).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import fastify from 'fastify';
|
||||||
|
import { Server } from 'http';
|
||||||
|
import { ApolloServer } from '../ApolloServer';
|
||||||
|
import testSuite, {
|
||||||
|
schema as Schema,
|
||||||
|
CreateAppOptions,
|
||||||
|
} from 'apollo-server-integration-testsuite';
|
||||||
|
import { GraphQLOptions, Config } from 'apollo-server-core';
|
||||||
|
|
||||||
|
async function createApp(options: CreateAppOptions = {}) {
|
||||||
|
const app = fastify();
|
||||||
|
|
||||||
|
const server = new ApolloServer(
|
||||||
|
(options.graphqlOptions as Config) || { schema: Schema },
|
||||||
|
);
|
||||||
|
|
||||||
|
app.register(server.createHandler());
|
||||||
|
await app.listen();
|
||||||
|
|
||||||
|
return app.server;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function destroyApp(app: Server) {
|
||||||
|
if (!app || !app.close) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await new Promise(resolve => app.close(resolve));
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('fastifyApollo', () => {
|
||||||
|
it('throws error if called without schema', function() {
|
||||||
|
expect(() => new ApolloServer(undefined as GraphQLOptions)).toThrow(
|
||||||
|
'ApolloServer requires options.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('integration:Fastify', () => {
|
||||||
|
testSuite(createApp, destroyApp);
|
||||||
|
});
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"extends": "../../../../tsconfig.test.base",
|
||||||
|
"include": ["**/*"],
|
||||||
|
"references": [
|
||||||
|
{ "path": "../../" },
|
||||||
|
{ "path": "../../../apollo-server-integration-testsuite" }
|
||||||
|
]
|
||||||
|
}
|
59
packages/apollo-server-fastify/src/fastifyApollo.ts
Normal file
59
packages/apollo-server-fastify/src/fastifyApollo.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import {
|
||||||
|
convertNodeHttpToRequest,
|
||||||
|
GraphQLOptions,
|
||||||
|
runHttpQuery,
|
||||||
|
} from 'apollo-server-core';
|
||||||
|
import { FastifyReply, FastifyRequest, RequestHandler } from 'fastify';
|
||||||
|
import { IncomingMessage, OutgoingMessage } from 'http';
|
||||||
|
|
||||||
|
export async function graphqlFastify(
|
||||||
|
options: (
|
||||||
|
req?: FastifyRequest<IncomingMessage>,
|
||||||
|
res?: FastifyReply<OutgoingMessage>,
|
||||||
|
) => GraphQLOptions | Promise<GraphQLOptions>,
|
||||||
|
): Promise<RequestHandler<IncomingMessage, OutgoingMessage>> {
|
||||||
|
if (!options) {
|
||||||
|
throw new Error('Apollo Server requires options.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return async (
|
||||||
|
request: FastifyRequest<IncomingMessage>,
|
||||||
|
reply: FastifyReply<OutgoingMessage>,
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const { graphqlResponse, responseInit } = await runHttpQuery(
|
||||||
|
[request, reply],
|
||||||
|
{
|
||||||
|
method: request.req.method as string,
|
||||||
|
options,
|
||||||
|
query: request.req.method === 'POST' ? request.body : request.query,
|
||||||
|
request: convertNodeHttpToRequest(request.raw),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (responseInit.headers) {
|
||||||
|
for (const [name, value] of Object.entries<string>(
|
||||||
|
responseInit.headers,
|
||||||
|
)) {
|
||||||
|
reply.header(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply.serializer((payload: string) => payload);
|
||||||
|
reply.send(graphqlResponse);
|
||||||
|
} catch (error) {
|
||||||
|
if ('HttpQueryError' !== error.name) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error.headers) {
|
||||||
|
Object.keys(error.headers).forEach(header => {
|
||||||
|
reply.header(header, error.headers[header]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
reply.code(error.statusCode);
|
||||||
|
reply.serializer((payload: string) => payload);
|
||||||
|
reply.send(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
29
packages/apollo-server-fastify/src/index.ts
Normal file
29
packages/apollo-server-fastify/src/index.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
export {
|
||||||
|
GraphQLUpload,
|
||||||
|
GraphQLOptions,
|
||||||
|
GraphQLExtension,
|
||||||
|
Config,
|
||||||
|
gql,
|
||||||
|
// Errors
|
||||||
|
ApolloError,
|
||||||
|
toApolloError,
|
||||||
|
SyntaxError,
|
||||||
|
ValidationError,
|
||||||
|
AuthenticationError,
|
||||||
|
ForbiddenError,
|
||||||
|
UserInputError,
|
||||||
|
// playground
|
||||||
|
defaultPlaygroundOptions,
|
||||||
|
PlaygroundConfig,
|
||||||
|
PlaygroundRenderPageOptions,
|
||||||
|
} from 'apollo-server-core';
|
||||||
|
|
||||||
|
export * from 'graphql-tools';
|
||||||
|
export * from 'graphql-subscriptions';
|
||||||
|
|
||||||
|
// ApolloServer integration.
|
||||||
|
export {
|
||||||
|
ApolloServer,
|
||||||
|
registerServer,
|
||||||
|
ServerRegistration,
|
||||||
|
} from './ApolloServer';
|
12
packages/apollo-server-fastify/tsconfig.json
Normal file
12
packages/apollo-server-fastify/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base",
|
||||||
|
"compilerOptions": {
|
||||||
|
"rootDir": "./src",
|
||||||
|
"outDir": "./dist",
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["**/__tests__", "**/__mocks__"],
|
||||||
|
"references": [
|
||||||
|
{ "path": "../apollo-server-core" },
|
||||||
|
]
|
||||||
|
}
|
|
@ -19,6 +19,7 @@
|
||||||
{ "path": "./packages/apollo-server-core" },
|
{ "path": "./packages/apollo-server-core" },
|
||||||
{ "path": "./packages/apollo-server-errors" },
|
{ "path": "./packages/apollo-server-errors" },
|
||||||
{ "path": "./packages/apollo-server-express" },
|
{ "path": "./packages/apollo-server-express" },
|
||||||
|
{ "path": "./packages/apollo-server-fastify" },
|
||||||
{ "path": "./packages/apollo-server-hapi" },
|
{ "path": "./packages/apollo-server-hapi" },
|
||||||
{ "path": "./packages/apollo-server-koa" },
|
{ "path": "./packages/apollo-server-koa" },
|
||||||
{ "path": "./packages/apollo-server-lambda" },
|
{ "path": "./packages/apollo-server-lambda" },
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
{ "path": "./packages/apollo-server-cloud-functions/src/__tests__/" },
|
{ "path": "./packages/apollo-server-cloud-functions/src/__tests__/" },
|
||||||
{ "path": "./packages/apollo-server-core/src/__tests__/" },
|
{ "path": "./packages/apollo-server-core/src/__tests__/" },
|
||||||
{ "path": "./packages/apollo-server-express/src/__tests__/" },
|
{ "path": "./packages/apollo-server-express/src/__tests__/" },
|
||||||
|
{ "path": "./packages/apollo-server-fastify/src/__tests__/" },
|
||||||
{ "path": "./packages/apollo-server-hapi/src/__tests__/" },
|
{ "path": "./packages/apollo-server-hapi/src/__tests__/" },
|
||||||
{ "path": "./packages/apollo-server-koa/src/__tests__/" },
|
{ "path": "./packages/apollo-server-koa/src/__tests__/" },
|
||||||
{ "path": "./packages/apollo-server-lambda/src/__tests__/" },
|
{ "path": "./packages/apollo-server-lambda/src/__tests__/" },
|
||||||
|
|
Loading…
Add table
Reference in a new issue