diff --git a/CHANGELOG.md b/CHANGELOG.md index ad27ddae..f58fce27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### v2.3.1 + +- Provide types for `graphql-upload` in a location where they can be accessed by TypeScript consumers of `apollo-server` packages. [ccf935f9](https://github.com/apollographql/apollo-server/commit/ccf935f9) [Issue #2092](https://github.com/apollographql/apollo-server/issues/2092) + ### v2.3.0 - **BREAKING FOR NODE.JS <= 8.5.0 ONLY**: To continue using Apollo Server 2.x in versions of Node.js prior to v8.5.0, file uploads must be disabled by setting `uploads: false` on the `ApolloServer` constructor options. Without explicitly disabling file-uploads, the server will `throw` at launch (with instructions and a link to our documentation). @@ -10,6 +14,8 @@ **We intend to drop support for Node.js 6.x in the next major version of Apollo Server.** + For more information, see [PR #2054](https://github.com/apollographql/apollo-server/pull/2054) and [our documentation](https://www.apollographql.com/docs/apollo-server/v2/migration-file-uploads.html). + ### v2.2.7 - `apollo-engine-reporting`: When multiple instances of `apollo-engine-reporting` are loaded (an uncommon edge case), ensure that `encodedTraces` are handled only once rather than once per loaded instance. [PR #2040](https://github.com/apollographql/apollo-server/pull/2040) diff --git a/docs/source/essentials/data.md b/docs/source/essentials/data.md index fb782efb..35835089 100644 --- a/docs/source/essentials/data.md +++ b/docs/source/essentials/data.md @@ -16,18 +16,18 @@ const { gql } = require('apollo-server'); const { find, filter } = require('lodash'); const schema = gql` -type Book { - title: String - author: Author -} + type Book { + title: String + author: Author + } -type Author { - books: [Book] -} + type Author { + books: [Book] + } -type Query { - author: Author -} + type Query { + author: Author + } `; const resolvers = { diff --git a/docs/source/features/creating-directives.md b/docs/source/features/creating-directives.md index 2979fdf5..6e390f74 100644 --- a/docs/source/features/creating-directives.md +++ b/docs/source/features/creating-directives.md @@ -53,10 +53,11 @@ In order to apply this implementation to a schema that contains `@deprecated` di const { ApolloServer, gql } = require("apollo-server"); const typeDefs = gql` -type ExampleType { - newField: String - oldField: String @deprecated(reason: "Use \`newField\`.") -}`; + type ExampleType { + newField: String + oldField: String @deprecated(reason: "Use \`newField\`.") + } +`; const server = new ApolloServer({ typeDefs, @@ -96,11 +97,12 @@ const { ApolloServer, gql, SchemaDirectiveVisitor } = require("apollo-server"); const { defaultFieldResolver } = require("graphql"); const typeDefs = gql` -directive @upper on FIELD_DEFINITION + directive @upper on FIELD_DEFINITION -type Query { - hello: String @upper -}`; + type Query { + hello: String @upper + } +`; class UpperCaseDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field) { @@ -138,11 +140,12 @@ Suppose you've defined an object type that corresponds to a [REST](https://en.wi const { ApolloServer, gql, SchemaDirectiveVisitor } = require("apollo-server"); const typeDefs = gql` -directive @rest(url: String) on FIELD_DEFINITION + directive @rest(url: String) on FIELD_DEFINITION -type Query { - people: [Person] @rest(url: "/api/v1/people") -}`; + type Query { + people: [Person] @rest(url: "/api/v1/people") + } +`; class RestDirective extends SchemaDirectiveVisitor { public visitFieldDefinition(field) { @@ -173,13 +176,14 @@ Suppose your resolver returns a `Date` object but you want to return a formatted const { ApolloServer, gql, SchemaDirectiveVisitor } = require("apollo-server"); const typeDefs = gql` -directive @date(format: String) on FIELD_DEFINITION + directive @date(format: String) on FIELD_DEFINITION -scalar Date + scalar Date -type Post { - published: Date @date(format: "mmmm d, yyyy") -}`; + type Post { + published: Date @date(format: "mmmm d, yyyy") + } +`; class DateFormatDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field) { @@ -214,15 +218,16 @@ const formatDate = require("dateformat"); const { defaultFieldResolver, GraphQLString } = require("graphql"); const typeDefs = gql` -directive @date( - defaultFormat: String = "mmmm d, yyyy" -) on FIELD_DEFINITION + directive @date( + defaultFormat: String = "mmmm d, yyyy" + ) on FIELD_DEFINITION -scalar Date + scalar Date -type Query { - today: Date @date -}`; + type Query { + today: Date @date + } +`; class FormattableDateDirective extends SchemaDirectiveVisitor { public visitFieldDefinition(field) { @@ -292,11 +297,12 @@ Here's how you might make sure `translate` is used to localize the `greeting` fi const { ApolloServer, gql, SchemaDirectiveVisitor } = require("apollo-server"); const typeDefs = gql` -directive @intl on FIELD_DEFINITION + directive @intl on FIELD_DEFINITION -type Query { - greeting: String @intl -}`; + type Query { + greeting: String @intl + } +`; class IntlDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field, details) { @@ -519,27 +525,28 @@ const { GraphQLID } = require("graphql"); const { createHash } = require("crypto"); const typeDefs = gql` -directive @uniqueID( - # The name of the new ID field, "uid" by default: - name: String = "uid" + directive @uniqueID( + # The name of the new ID field, "uid" by default: + name: String = "uid" - # Which fields to include in the new ID: - from: [String] = ["id"] -) on OBJECT + # Which fields to include in the new ID: + from: [String] = ["id"] + ) on OBJECT -# Since this type just uses the default values of name and from, -# we don't have to pass any arguments to the directive: -type Location @uniqueID { - id: Int - address: String -} + # Since this type just uses the default values of name and from, + # we don't have to pass any arguments to the directive: + type Location @uniqueID { + id: Int + address: String + } -# This type uses both the person's name and the personID field, -# in addition to the "Person" type name, to construct the ID: -type Person @uniqueID(from: ["name", "personID"]) { - personID: Int - name: String -}`; + # This type uses both the person's name and the personID field, + # in addition to the "Person" type name, to construct the ID: + type Person @uniqueID(from: ["name", "personID"]) { + personID: Int + name: String + } +`; class UniqueIdDirective extends SchemaDirectiveVisitor { visitObject(type) { diff --git a/docs/source/features/mocking.md b/docs/source/features/mocking.md index c8224b8d..bcc0b7a7 100644 --- a/docs/source/features/mocking.md +++ b/docs/source/features/mocking.md @@ -15,9 +15,9 @@ This example demonstrates mocking a GraphQL schema with just one line of code, u const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` -type Query { - hello: String -} + type Query { + hello: String + } `; const server = new ApolloServer({ @@ -32,7 +32,7 @@ server.listen().then(({ url }) => { > Note: If `typeDefs` has custom scalar types, `resolvers` must still contain the `serialize`, `parseValue`, and `parseLiteral` functions -Mocking logic simply looks at the type definitions and returns a string where a string is expected, a number for a number, etc. This provides the right shape of result. By default, when using mocks, any existing resolvers are ignored. See the ["Using existing resolvers with mocks"](#existing-resolvers) section below for more info on how to change this behavior. +Mocking logic simply looks at the type definitions and returns a string where a string is expected, a number for a number, etc. This provides the right shape of result. By default, when using mocks, any existing resolvers are ignored. See the ["Using existing resolvers with mocks"](#existing-resolvers) section below for more info on how to change this behavior. For more sophisticated testing, mocks can be customized to a particular data model. @@ -44,10 +44,10 @@ In addition to a boolean, `mocks` can be an object that describes custom mocking const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` -type Query { - hello: String - resolved: String -} + type Query { + hello: String + resolved: String + } `; const resolvers = { @@ -149,16 +149,16 @@ For some more background and flavor on this approach, read the ["Mocking your se The default behavior for mocks is to overwrite the resolvers already present in the schema. To keep the existing resolvers, set the `mockEntireSchema` option to false. -> Note: mocking resolvers will not work if the `mocks` option is `false`, even if `mockEntireSchema` is true. +> Note: mocking resolvers will not work if the `mocks` option is `false`, even if `mockEntireSchema` is true. ```js line=26 const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` -type Query { - hello: String - resolved: String -} + type Query { + hello: String + resolved: String + } `; const resolvers = { diff --git a/docs/source/features/scalars-enums.md b/docs/source/features/scalars-enums.md index 89bf845c..5ad0ee52 100644 --- a/docs/source/features/scalars-enums.md +++ b/docs/source/features/scalars-enums.md @@ -36,17 +36,15 @@ const { ApolloServer, gql } = require('apollo-server'); const GraphQLJSON = require('graphql-type-json'); const schemaString = gql` + scalar JSON -scalar JSON - -type Foo { - aField: JSON -} - -type Query { - foo: Foo -} + type Foo { + aField: JSON + } + type Query { + foo: Foo + } `; const resolveFunctions = { @@ -92,17 +90,15 @@ const myCustomScalarType = new GraphQLScalarType({ }); const schemaString = gql` + scalar MyCustomScalar -scalar MyCustomScalar - -type Foo { - aField: MyCustomScalar -} - -type Query { - foo: Foo -} + type Foo { + aField: MyCustomScalar + } + type Query { + foo: Foo + } `; const resolverFunctions = { @@ -127,11 +123,12 @@ The goal is to define a `Date` data type for returning `Date` values from the da The following is the implementation of the `Date` data type. First, the schema: ```js -const typeDefs = gql`scalar Date +const typeDefs = gql` + scalar Date -type MyType { - created: Date -} + type MyType { + created: Date + } ` ``` @@ -172,11 +169,12 @@ server.listen().then(({ url }) => { In this example, we follow the [official GraphQL documentation](http://graphql.org/docs/api-reference-type-system/) for the scalar datatype, which demonstrates how to validate a database field that should only contain odd numbers in GraphQL. First, the schema: ```js -const typeDefs = gql`scalar Odd +const typeDefs = gql` + scalar Odd -type MyType { + type MyType { oddValue: Odd -} + } ` ``` diff --git a/docs/source/features/subscriptions.md b/docs/source/features/subscriptions.md index 0c491da7..aeefac78 100644 --- a/docs/source/features/subscriptions.md +++ b/docs/source/features/subscriptions.md @@ -21,19 +21,22 @@ Subscriptions are another root level type, similar to Query and Mutation. To sta ```js line=2-4 const typeDefs = gql` -type Subscription { - postAdded: Post -} -type Query { - posts: [Post] -} -type Mutation { - addPost(author: String, comment: String): Post -} -type Post { - author: String - comment: String -} + type Subscription { + postAdded: Post + } + + type Query { + posts: [Post] + } + + type Mutation { + addPost(author: String, comment: String): Post + } + + type Post { + author: String + comment: String + } ` ``` @@ -84,7 +87,7 @@ const server = new ApolloServer({ }); ``` -> `connection` contains various metadata, found [here](https://github.com/apollographql/subscriptions-transport-ws/blob/88970eaf6d2e3f68f98696de00631acf4062c088/src/server.ts#L312-L321). +> `connection` contains various metadata, found [here](https://github.com/apollographql/subscriptions-transport-ws/blob/88970eaf6d2e3f68f98696de00631acf4062c088/src/server.ts#L312-L321). As you can see Apollo Server 2.0 allows realtime data without invasive changes to existing code. For a full working example please have a look to [this repo](https://github.com/daniele-zurico/apollo2-subscriptions-how-to) provided by [Daniele Zurico](https://github.com/daniele-zurico/apollo2-subscriptions-how-to) diff --git a/docs/source/features/unions-interfaces.md b/docs/source/features/unions-interfaces.md index 9993b639..6235259b 100644 --- a/docs/source/features/unions-interfaces.md +++ b/docs/source/features/unions-interfaces.md @@ -13,19 +13,20 @@ The `Union` type indicates that a field can return more than one object type, bu const { gql } = require('apollo-server'); const typeDefs = gql` -union Result = Book | Author + union Result = Book | Author -type Book { - title: String -} + type Book { + title: String + } -type Author { - name: String -} + type Author { + name: String + } -type Query { - search: [Result] -}`; + type Query { + search: [Result] + } +`; ``` Since a query requesting a union field, a query being made on a field which is union-typed must specify the object types containing the fields it wants. This ambiguity is solved by an extra `__resolveType` field in the resolver map. `__resolveType` defines the type of the result is out of the available options to GraphQL execution environment. diff --git a/docs/source/schemas/types.md b/docs/source/schemas/types.md index 36c55fff..62cc979e 100644 --- a/docs/source/schemas/types.md +++ b/docs/source/schemas/types.md @@ -92,9 +92,9 @@ In Apollo server, a resolver that returns an enum can use the direct string repr ```js const schema = gql` -type Query { - genre: Genre -} + type Query { + genre: Genre + } `; const resolvers = { @@ -110,9 +110,9 @@ Lists are defined with as type modifier that wraps object types, scalars, and en ```js const schema = gql` -type Query { - todos: [String] -} + type Query { + todos: [String] + } `; const resolvers = { @@ -132,9 +132,9 @@ Using the exclamation mark to declare a field as non-nullable simplifies the con ```js const schema = gql` -type Query { - genre: String! -} + type Query { + genre: String! + } `; const resolvers = { diff --git a/package-lock.json b/package-lock.json index abfa3b07..3a0e3c77 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1290,9 +1290,9 @@ "dev": true }, "@types/hapi": { - "version": "17.8.0", - "resolved": "https://registry.npmjs.org/@types/hapi/-/hapi-17.8.0.tgz", - "integrity": "sha512-hI713RUrMY4dn4Q1exYDg4RFYpWwgH5TLROsDFcH8j03mUqCJaorosq7OBegHFSZu0MC/W2fVqKCZ0JwT+nQ2A==", + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@types/hapi/-/hapi-17.8.1.tgz", + "integrity": "sha512-ruW5d7KiEHzkV97rzytHTgzG6zxKngx+6L+qdhYEX6qvILGX5knG/0kXNfseDhbaE7DzdS75Maf7gtgziy7i+w==", "dev": true, "requires": { "@types/boom": "*", @@ -1326,9 +1326,9 @@ "dev": true }, "@types/joi": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@types/joi/-/joi-14.0.0.tgz", - "integrity": "sha512-q3r+5QfNrthJL+5Pvb9MOP7rJniTfAV+cGbsO2a3ItGSuwmp2vdjjZ/VCWKwGT5lNx4eOvZI4O3IpSIXh3f4RA==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/@types/joi/-/joi-14.0.1.tgz", + "integrity": "sha512-0uZZ+nffpr480zwwUXsk0Z5O0szllffNW1EbkI+dDzKhNKhiX4QOwpwK37WpKIpaPLk9V8U9y2We/VOeD6zyhQ==", "dev": true }, "@types/json-stable-stringify": { @@ -1468,9 +1468,9 @@ } }, "@types/node": { - "version": "10.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.14.tgz", - "integrity": "sha512-0rVcFRhM93kRGAU88ASCjX9Y3FWDCh+33G5Z5evpKOea4xcpLqDGwmo64+DjgaSezTN5j9KdnUzvxhOw7fNciQ==" + "version": "10.12.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.15.tgz", + "integrity": "sha512-9kROxduaN98QghwwHmxXO2Xz3MaWf+I1sLVAA6KJDF5xix+IyXVhds0MAfdNwtcpSrzhaTsNB0/jnL86fgUhqA==" }, "@types/node-fetch": { "version": "2.1.4", @@ -2041,31 +2041,31 @@ } }, "apollo-link": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.4.tgz", - "integrity": "sha512-B1z+9H2nTyWEhMXRFSnoZ1vSuAYP+V/EdUJvRx9uZ8yuIBZMm6reyVtr1n0BWlKeSFyPieKJy2RLzmITAAQAMQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.6.tgz", + "integrity": "sha512-sUNlA20nqIF3gG3F8eyMD+mO80fmf3dPZX+GUOs3MI9oZR8ug09H3F0UsWJMcpEg6h55Yy5wZ+BMmAjrbenF/Q==", "requires": { "apollo-utilities": "^1.0.0", - "zen-observable-ts": "^0.8.11" + "zen-observable-ts": "^0.8.13" } }, "apollo-link-http": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.7.tgz", - "integrity": "sha512-EZ9nynHjwYCpGYP5IsRrZGTWidUVpshk7MuSG4joqGtJMwpFCgMQz+y3BHdUhowHtfAd9z60XmeOTG9FJolb8A==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.9.tgz", + "integrity": "sha512-9tJy2zGm4Cm/1ycScDNZJe51dgnTSfKx7pKIgPZmcxkdDpgUY2DZitDH6ZBv4yp9z8MC9Xr9wgwc29s6hcadUQ==", "dev": true, "requires": { - "apollo-link": "^1.2.4", - "apollo-link-http-common": "^0.2.6" + "apollo-link": "^1.2.6", + "apollo-link-http-common": "^0.2.8" } }, "apollo-link-http-common": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.6.tgz", - "integrity": "sha512-LUOMWvrZuBP1hyWLBXyaW0KyFeKo79j+k3N+Q4HSkXKbLibnllXQ+JxxoSKGhm0bhREygiLtJAG9JnGlhxGO/Q==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.8.tgz", + "integrity": "sha512-gGmXZN8mr7e9zjopzKQfZ7IKnh8H12NxBDzvp9nXI3U82aCVb72p+plgoYLcpMY8w6krvoYjgicFmf8LO20TCQ==", "dev": true, "requires": { - "apollo-link": "^1.2.4" + "apollo-link": "^1.2.6" } }, "apollo-link-persisted-queries": { @@ -3116,6 +3116,24 @@ "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", "dev": true }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + }, "callsites": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", @@ -6931,12 +6949,12 @@ } }, "husky": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/husky/-/husky-1.2.0.tgz", - "integrity": "sha512-/ib3+iycykXC0tYIxsyqierikVa9DA2DrT32UEirqNEFVqOj1bFMTgP3jAz8HM7FgC/C8pc/BTUa9MV2GEkZaA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.2.1.tgz", + "integrity": "sha512-4Ylal3HWhnDvIszuiyLoVrSGI7QLg/ogkNCoHE34c+yZYzb9kBZNrlTOsdw92cGi3cJT8pPb6CdVfxFkLnc8Dg==", "dev": true, "requires": { - "cosmiconfig": "^5.0.6", + "cosmiconfig": "^5.0.7", "execa": "^1.0.0", "find-up": "^3.0.0", "get-stdin": "^6.0.0", @@ -6948,41 +6966,16 @@ "slash": "^2.0.0" }, "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" } } } @@ -7016,6 +7009,16 @@ "minimatch": "^3.0.4" } }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, "import-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", @@ -13359,9 +13362,9 @@ } }, "ws": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.0.tgz", - "integrity": "sha512-H3dGVdGvW2H8bnYpIDc3u3LH8Wue3Qh+Zto6aXXFzvESkTVT6rAfKR6tR/+coaUvxs8yHtmNV0uioBF62ZGSTg==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.2.tgz", + "integrity": "sha512-rfUqzvz0WxmSXtJpPMX2EeASXabOrSMk1ruMOV3JBTBjo4ac2lDjGGsbQSyxj8Odhw5fBib8ZKEjDNvgouNKYw==", "requires": { "async-limiter": "~1.0.0" } @@ -13495,9 +13498,9 @@ "integrity": "sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==" }, "zen-observable-ts": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.11.tgz", - "integrity": "sha512-8bs7rgGV4kz5iTb9isudkuQjtWwPnQ8lXq6/T76vrepYZVMsDEv6BXaEA+DHdJSK3KVLduagi9jSpSAJ5NgKHw==", + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.13.tgz", + "integrity": "sha512-WDb8SM0tHCb6c0l1k60qXWlm1ok3zN9U4VkLdnBKQwIYwUoB9psH7LIFgR+JVCCMmBxUgOjskIid8/N02k/2Bg==", "requires": { "zen-observable": "^0.8.0" } diff --git a/package.json b/package.json index 85d09a4e..e9ad092f 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "@types/connect": "3.4.32", "@types/fibers": "0.0.30", "@types/graphql": "14.0.3", - "@types/hapi": "17.8.0", + "@types/hapi": "17.8.1", "@types/jest": "23.3.10", "@types/json-stable-stringify": "1.0.32", "@types/koa-multer": "1.0.0", @@ -78,7 +78,7 @@ "@types/memcached": "2.2.5", "@types/micro": "7.3.3", "@types/multer": "1.3.7", - "@types/node": "10.12.14", + "@types/node": "10.12.15", "@types/node-fetch": "2.1.4", "@types/redis": "2.8.8", "@types/request": "2.48.1", @@ -87,8 +87,8 @@ "@types/type-is": "1.6.2", "@types/ws": "6.0.1", "apollo-fetch": "0.7.0", - "apollo-link": "1.2.4", - "apollo-link-http": "1.5.7", + "apollo-link": "1.2.6", + "apollo-link-http": "1.5.9", "apollo-link-persisted-queries": "0.2.2", "body-parser": "1.18.3", "codecov": "3.1.0", @@ -101,7 +101,7 @@ "graphql-tag": "2.10.0", "graphql-tools": "4.0.3", "hapi": "17.8.1", - "husky": "1.2.0", + "husky": "1.2.1", "jest": "23.6.0", "jest-junit": "5.2.0", "jest-matcher-utils": "23.6.0", @@ -127,7 +127,7 @@ "ts-jest": "23.10.5", "tslint": "5.11.0", "typescript": "3.2.2", - "ws": "6.1.0", + "ws": "6.1.2", "yup": "0.26.5" }, "jest": { diff --git a/packages/apollo-server-azure-functions/package.json b/packages/apollo-server-azure-functions/package.json index 79c6cb53..1ddb9fec 100644 --- a/packages/apollo-server-azure-functions/package.json +++ b/packages/apollo-server-azure-functions/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-azure-functions", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Azure Functions", "keywords": [ "GraphQL", diff --git a/packages/apollo-server-cache-memcached/src/__tests__/Memcached.test.ts b/packages/apollo-server-cache-memcached/src/__tests__/Memcached.test.ts index cc769325..d3d7d20b 100644 --- a/packages/apollo-server-cache-memcached/src/__tests__/Memcached.test.ts +++ b/packages/apollo-server-cache-memcached/src/__tests__/Memcached.test.ts @@ -2,6 +2,13 @@ jest.mock('memcached', () => require('memcached-mock')); import { MemcachedCache } from '../index'; -import { testKeyValueCache } from '../../../apollo-server-caching/src/__tests__/testsuite'; +import { + testKeyValueCache_Basics, + testKeyValueCache_Expiration, +} from '../../../apollo-server-caching/src/__tests__/testsuite'; -testKeyValueCache(new MemcachedCache('localhost')); +describe('Memcached', () => { + const cache = new MemcachedCache('localhost'); + testKeyValueCache_Basics(cache); + testKeyValueCache_Expiration(cache); +}); diff --git a/packages/apollo-server-cache-memcached/src/index.ts b/packages/apollo-server-cache-memcached/src/index.ts index 45d53aac..e369be35 100644 --- a/packages/apollo-server-cache-memcached/src/index.ts +++ b/packages/apollo-server-cache-memcached/src/index.ts @@ -22,11 +22,11 @@ export class MemcachedCache implements KeyValueCache { async set( key: string, - data: string, + value: string, options?: { ttl?: number }, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); - await this.client.set(key, data, ttl); + await this.client.set(key, value, ttl); } async get(key: string): Promise { diff --git a/packages/apollo-server-cache-redis/src/__tests__/Redis.test.ts b/packages/apollo-server-cache-redis/src/__tests__/Redis.test.ts index 4e0ea455..d13f0d30 100644 --- a/packages/apollo-server-cache-redis/src/__tests__/Redis.test.ts +++ b/packages/apollo-server-cache-redis/src/__tests__/Redis.test.ts @@ -3,6 +3,13 @@ jest.mock('redis', () => require('redis-mock')); jest.useFakeTimers(); // mocks out setTimeout that is used in redis-mock import { RedisCache } from '../index'; -import { testKeyValueCache } from '../../../apollo-server-caching/src/__tests__/testsuite'; +import { + testKeyValueCache_Basics, + testKeyValueCache_Expiration, +} from '../../../apollo-server-caching/src/__tests__/testsuite'; -testKeyValueCache(new RedisCache({ host: 'localhost' })); +describe('Redis', () => { + const cache = new RedisCache({ host: 'localhost' }); + testKeyValueCache_Basics(cache); + testKeyValueCache_Expiration(cache); +}); diff --git a/packages/apollo-server-cache-redis/src/index.ts b/packages/apollo-server-cache-redis/src/index.ts index 8116c939..7c0b1b61 100644 --- a/packages/apollo-server-cache-redis/src/index.ts +++ b/packages/apollo-server-cache-redis/src/index.ts @@ -3,7 +3,7 @@ import Redis from 'redis'; import { promisify } from 'util'; import DataLoader from 'dataloader'; -export class RedisCache implements KeyValueCache { +export class RedisCache implements KeyValueCache { // FIXME: Replace any with proper promisified type readonly client: any; readonly defaultSetOptions = { @@ -31,11 +31,11 @@ export class RedisCache implements KeyValueCache { async set( key: string, - data: string, + value: string, options?: { ttl?: number }, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); - await this.client.set(key, data, 'EX', ttl); + await this.client.set(key, value, 'EX', ttl); } async get(key: string): Promise { diff --git a/packages/apollo-server-caching/README.md b/packages/apollo-server-caching/README.md index 5b9aaac8..26980ea6 100644 --- a/packages/apollo-server-caching/README.md +++ b/packages/apollo-server-caching/README.md @@ -16,7 +16,9 @@ export interface KeyValueCache { } ``` -## Running test suite +## Testing cache implementations + +### Test helpers You can export and run a jest test suite from `apollo-server-caching` to test your implementation: @@ -28,4 +30,15 @@ import { testKeyValueCache } from 'apollo-server-caching'; testKeyValueCache(new MemcachedCache('localhost')); ``` +The default `testKeyValueCache` helper will run all key-value store tests on the specified store, including basic `get` and `set` functionality, along with time-based expunging rules. + +Some key-value cache implementations may not be able to support the full suite of tests (for example, some tests might not be able to expire based on time). For those cases, there are more granular implementations which can be used: + +* `testKeyValueCache_Basic` +* `testKeyValueCache_Expiration` + +For more details, consult the [source for `apollo-server-caching`](./src/__tests__/testsuite.ts). + +### Running tests + Run tests with `jest --verbose` diff --git a/packages/apollo-server-caching/src/InMemoryLRUCache.ts b/packages/apollo-server-caching/src/InMemoryLRUCache.ts index 719db2ba..b75dfcb3 100644 --- a/packages/apollo-server-caching/src/InMemoryLRUCache.ts +++ b/packages/apollo-server-caching/src/InMemoryLRUCache.ts @@ -1,24 +1,46 @@ import LRU from 'lru-cache'; import { KeyValueCache } from './KeyValueCache'; -export class InMemoryLRUCache implements KeyValueCache { - private store: LRU.Cache; +export class InMemoryLRUCache implements KeyValueCache { + private store: LRU.Cache; // FIXME: Define reasonable default max size of the cache constructor({ maxSize = Infinity }: { maxSize?: number } = {}) { this.store = new LRU({ max: maxSize, - length: item => item.length, + length(item) { + if (Array.isArray(item) || typeof item === 'string') { + return item.length; + } + + // If it's an object, we'll use the length to get an approximate, + // relative size of what it would take to store it. It's certainly not + // 100% accurate, but it's a very, very fast implementation and it + // doesn't require bringing in other dependencies or logic which we need + // to maintain. In the future, we might consider something like: + // npm.im/object-sizeof, but this should be sufficient for now. + if (typeof item === 'object') { + return JSON.stringify(item).length; + } + + // Go with the lru-cache default "naive" size, in lieu anything better: + // https://github.com/isaacs/node-lru-cache/blob/a71be6cd/index.js#L17 + return 1; + }, }); } async get(key: string) { return this.store.get(key); } - async set(key: string, value: string) { - this.store.set(key, value); + async set(key: string, value: V, options?: { ttl?: number }) { + const maxAge = options && options.ttl && options.ttl * 1000; + this.store.set(key, value, maxAge); } async delete(key: string) { this.store.del(key); } + async flush(): Promise { + this.store.reset(); + } } diff --git a/packages/apollo-server-caching/src/KeyValueCache.ts b/packages/apollo-server-caching/src/KeyValueCache.ts index ff0a0d2c..86c3e136 100644 --- a/packages/apollo-server-caching/src/KeyValueCache.ts +++ b/packages/apollo-server-caching/src/KeyValueCache.ts @@ -1,5 +1,5 @@ -export interface KeyValueCache { - get(key: string): Promise; - set(key: string, value: string, options?: { ttl?: number }): Promise; +export interface KeyValueCache { + get(key: string): Promise; + set(key: string, value: V, options?: { ttl?: number }): Promise; delete(key: string): Promise; } diff --git a/packages/apollo-server-caching/src/__tests__/InMemoryLRUCache.test.ts b/packages/apollo-server-caching/src/__tests__/InMemoryLRUCache.test.ts new file mode 100644 index 00000000..f6dd0a1d --- /dev/null +++ b/packages/apollo-server-caching/src/__tests__/InMemoryLRUCache.test.ts @@ -0,0 +1,11 @@ +import { + testKeyValueCache_Basics, + testKeyValueCache_Expiration, +} from '../../../apollo-server-caching/src/__tests__/testsuite'; +import { InMemoryLRUCache } from '../InMemoryLRUCache'; + +describe('InMemoryLRUCache', () => { + const cache = new InMemoryLRUCache(); + testKeyValueCache_Basics(cache); + testKeyValueCache_Expiration(cache); +}); diff --git a/packages/apollo-server-caching/src/__tests__/testsuite.ts b/packages/apollo-server-caching/src/__tests__/testsuite.ts index 81dcb24c..3ee62aa2 100644 --- a/packages/apollo-server-caching/src/__tests__/testsuite.ts +++ b/packages/apollo-server-caching/src/__tests__/testsuite.ts @@ -1,21 +1,11 @@ import { advanceTimeBy, mockDate, unmockDate } from '__mocks__/date'; -export function testKeyValueCache(keyValueCache: any) { - describe('KeyValueCache Test Suite', () => { - beforeAll(() => { - mockDate(); - jest.useFakeTimers(); - }); - +export function testKeyValueCache_Basics(keyValueCache: any) { + describe('basic cache functionality', () => { beforeEach(() => { keyValueCache.flush(); }); - afterAll(() => { - unmockDate(); - keyValueCache.close(); - }); - it('can do a basic get and set', async () => { await keyValueCache.set('hello', 'world'); expect(await keyValueCache.get('hello')).toBe('world'); @@ -28,6 +18,24 @@ export function testKeyValueCache(keyValueCache: any) { await keyValueCache.delete('hello'); expect(await keyValueCache.get('hello')).toBeUndefined(); }); + }); +} + +export function testKeyValueCache_Expiration(keyValueCache: any) { + describe('time-based cache expunging', () => { + beforeAll(() => { + mockDate(); + jest.useFakeTimers(); + }); + + beforeEach(() => { + keyValueCache.flush(); + }); + + afterAll(() => { + unmockDate(); + keyValueCache.close(); + }); it('is able to expire keys based on ttl', async () => { await keyValueCache.set('short', 's', { ttl: 1 }); @@ -45,3 +53,10 @@ export function testKeyValueCache(keyValueCache: any) { }); }); } + +export function testKeyValueCache(keyValueCache: any) { + describe('KeyValueCache Test Suite', () => { + testKeyValueCache_Basics(keyValueCache); + testKeyValueCache_Expiration(keyValueCache); + }); +} diff --git a/packages/apollo-server-cloud-functions/package.json b/packages/apollo-server-cloud-functions/package.json index f202985d..869d2ab0 100644 --- a/packages/apollo-server-cloud-functions/package.json +++ b/packages/apollo-server-cloud-functions/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-cloud-functions", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Google Cloud Functions", "keywords": [ "GraphQL", diff --git a/packages/apollo-server-cloudflare/package.json b/packages/apollo-server-cloudflare/package.json index a9727806..1e222fba 100644 --- a/packages/apollo-server-cloudflare/package.json +++ b/packages/apollo-server-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-cloudflare", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Cloudflare workers", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-core/package.json b/packages/apollo-server-core/package.json index 20e051b2..605e524d 100644 --- a/packages/apollo-server-core/package.json +++ b/packages/apollo-server-core/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-core", - "version": "2.3.0", + "version": "2.3.1", "description": "Core engine for Apollo GraphQL server", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-core/src/__tests__/runQuery.test.ts b/packages/apollo-server-core/src/__tests__/runQuery.test.ts index 877384de..d18f1b25 100644 --- a/packages/apollo-server-core/src/__tests__/runQuery.test.ts +++ b/packages/apollo-server-core/src/__tests__/runQuery.test.ts @@ -9,8 +9,6 @@ import { GraphQLNonNull, parse, DocumentNode, - ValidationContext, - GraphQLFieldResolver, } from 'graphql'; import { @@ -19,10 +17,9 @@ import { GraphQLResponse, } from 'graphql-extensions'; -import { CacheControlExtensionOptions } from 'apollo-cache-control'; - import { processGraphQLRequest, GraphQLRequest } from '../requestPipeline'; import { Request } from 'apollo-server-env'; +import { GraphQLOptions, Context as GraphQLContext } from 'apollo-server-core'; // This is a temporary kludge to ensure we preserve runQuery behavior with the // GraphQLRequestProcessor refactoring. @@ -46,25 +43,26 @@ function runQuery(options: QueryOptions): Promise { }); } -interface QueryOptions { - schema: GraphQLSchema; - +interface QueryOptions + extends Pick< + GraphQLOptions>, + | 'cacheControl' + | 'context' + | 'debug' + | 'extensions' + | 'fieldResolver' + | 'formatError' + | 'formatResponse' + | 'rootValue' + | 'schema' + | 'tracing' + | 'validationRules' + > { queryString?: string; parsedQuery?: DocumentNode; - - rootValue?: any; - context?: any; variables?: { [key: string]: any }; operationName?: string; - validationRules?: Array<(context: ValidationContext) => any>; - fieldResolver?: GraphQLFieldResolver; - formatError?: Function; - formatResponse?: Function; - debug?: boolean; - tracing?: boolean; - cacheControl?: CacheControlExtensionOptions; request: Pick; - extensions?: Array<() => GraphQLExtension>; } const queryType = new GraphQLObjectType({ diff --git a/packages/apollo-server-core/src/processFileUploads.ts b/packages/apollo-server-core/src/processFileUploads.ts index bf5a323f..364848f4 100644 --- a/packages/apollo-server-core/src/processFileUploads.ts +++ b/packages/apollo-server-core/src/processFileUploads.ts @@ -1,3 +1,5 @@ +/// + import supportsUploadsInNode from './utils/supportsUploadsInNode'; // We'll memoize this function once at module load time since it should never diff --git a/packages/apollo-server-core/src/requestPipeline.ts b/packages/apollo-server-core/src/requestPipeline.ts index 7c3d672e..7c4429c3 100644 --- a/packages/apollo-server-core/src/requestPipeline.ts +++ b/packages/apollo-server-core/src/requestPipeline.ts @@ -22,6 +22,7 @@ import { } from 'apollo-cache-control'; import { TracingExtension } from 'apollo-tracing'; import { + ApolloError, fromGraphQLError, SyntaxError, ValidationError, @@ -135,15 +136,9 @@ export async function processGraphQLRequest( persistedQueryRegister = true; - // Store the query asynchronously so we don't block. - (async () => { - return ( - config.persistedQueries && - config.persistedQueries.cache.set(`apq:${queryHash}`, query) - ); - })().catch(error => { - console.warn(error); - }); + Promise.resolve( + config.persistedQueries.cache.set(`apq:${queryHash}`, query), + ).catch(console.warn); } } else if (query) { // FIXME: We'll compute the APQ query hash to use as our cache key for @@ -179,13 +174,7 @@ export async function processGraphQLRequest( parsingDidEnd(); } catch (syntaxError) { parsingDidEnd(syntaxError); - return sendResponse({ - errors: [ - fromGraphQLError(syntaxError, { - errorClass: SyntaxError, - }), - ], - }); + return sendErrorResponse(syntaxError, SyntaxError); } requestContext.document = document; @@ -197,19 +186,13 @@ export async function processGraphQLRequest( const validationErrors = validate(document); - if (validationErrors.length > 0) { + if (validationErrors.length === 0) { + validationDidEnd(); + } else { validationDidEnd(validationErrors); - return sendResponse({ - errors: validationErrors.map(validationError => - fromGraphQLError(validationError, { - errorClass: ValidationError, - }), - ), - }); + return sendErrorResponse(validationErrors, ValidationError); } - validationDidEnd(); - // FIXME: If we want to guarantee an operation has been set when invoking // `willExecuteOperation` and executionDidStart`, we need to throw an // error here and not leave this to `buildExecutionContext` in @@ -248,9 +231,7 @@ export async function processGraphQLRequest( executionDidEnd(); } catch (executionError) { executionDidEnd(executionError); - return sendResponse({ - errors: [fromGraphQLError(executionError)], - }); + return sendErrorResponse(executionError); } const formattedExtensions = extensionStack.format(); @@ -346,6 +327,27 @@ export async function processGraphQLRequest( return requestContext.response!; } + function sendErrorResponse( + errorOrErrors: ReadonlyArray | GraphQLError, + errorClass?: typeof ApolloError, + ) { + // If a single error is passed, it should still be encapsulated in an array. + const errors = Array.isArray(errorOrErrors) + ? errorOrErrors + : [errorOrErrors]; + + return sendResponse({ + errors: errors.map(err => + fromGraphQLError( + err, + errorClass && { + errorClass, + }, + ), + ), + }); + } + function initializeRequestListenerDispatcher(): Dispatcher< GraphQLRequestListener > { diff --git a/types/graphql-upload/index.d.ts b/packages/apollo-server-core/src/types/graphql-upload.d.ts similarity index 100% rename from types/graphql-upload/index.d.ts rename to packages/apollo-server-core/src/types/graphql-upload.d.ts diff --git a/packages/apollo-server-express/package.json b/packages/apollo-server-express/package.json index c5b5c928..06ff254a 100644 --- a/packages/apollo-server-express/package.json +++ b/packages/apollo-server-express/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-express", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Express and Connect", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-hapi/package.json b/packages/apollo-server-hapi/package.json index cec33f13..b04b2051 100644 --- a/packages/apollo-server-hapi/package.json +++ b/packages/apollo-server-hapi/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-hapi", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Hapi", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-integration-testsuite/package.json b/packages/apollo-server-integration-testsuite/package.json index d5d91ad6..1d81058b 100644 --- a/packages/apollo-server-integration-testsuite/package.json +++ b/packages/apollo-server-integration-testsuite/package.json @@ -1,7 +1,7 @@ { "name": "apollo-server-integration-testsuite", "private": true, - "version": "2.3.0", + "version": "2.3.1", "description": "Apollo Server Integrations testsuite", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-integration-testsuite/src/ApolloServer.ts b/packages/apollo-server-integration-testsuite/src/ApolloServer.ts index 4cd7156b..750e4a5b 100644 --- a/packages/apollo-server-integration-testsuite/src/ApolloServer.ts +++ b/packages/apollo-server-integration-testsuite/src/ApolloServer.ts @@ -978,7 +978,7 @@ export function testApolloServer( }); }); }); - it('disables subscritpions when option set to false', done => { + it('disables subscriptions when option set to false', done => { const typeDefs = gql` type Query { "graphql-js forces there to be a query type" @@ -1025,7 +1025,7 @@ export function testApolloServer( } const client = new SubscriptionClient( - `ws://localhost:${port}${server.subscriptionsPath}`, + `ws://localhost:${port}${server.subscriptionsPath || ''}`, {}, WebSocket, ); diff --git a/packages/apollo-server-koa/package.json b/packages/apollo-server-koa/package.json index a6b53794..d5daa7a2 100644 --- a/packages/apollo-server-koa/package.json +++ b/packages/apollo-server-koa/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-koa", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Koa", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-lambda/package.json b/packages/apollo-server-lambda/package.json index 01759ef5..e5bfa84a 100644 --- a/packages/apollo-server-lambda/package.json +++ b/packages/apollo-server-lambda/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-lambda", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for AWS Lambda", "keywords": [ "GraphQL", diff --git a/packages/apollo-server-micro/package.json b/packages/apollo-server-micro/package.json index 671acd60..66f68763 100644 --- a/packages/apollo-server-micro/package.json +++ b/packages/apollo-server-micro/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-micro", - "version": "2.3.0", + "version": "2.3.1", "description": "Production-ready Node.js GraphQL server for Micro", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-plugin-base/package.json b/packages/apollo-server-plugin-base/package.json index 386b1cef..c8e4590c 100644 --- a/packages/apollo-server-plugin-base/package.json +++ b/packages/apollo-server-plugin-base/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-plugin-base", - "version": "0.2.0", + "version": "0.2.1", "description": "Apollo Server plugin base classes", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server-testing/package.json b/packages/apollo-server-testing/package.json index ae004231..e56a2d0b 100644 --- a/packages/apollo-server-testing/package.json +++ b/packages/apollo-server-testing/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server-testing", - "version": "2.3.0", + "version": "2.3.1", "description": "Test utils for apollo-server", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/apollo-server/package.json b/packages/apollo-server/package.json index 728e5081..0f915e0e 100644 --- a/packages/apollo-server/package.json +++ b/packages/apollo-server/package.json @@ -1,6 +1,6 @@ { "name": "apollo-server", - "version": "2.3.0", + "version": "2.3.1", "description": "Production ready GraphQL Server", "author": "opensource@apollographql.com", "main": "dist/index.js", diff --git a/packages/graphql-extensions/package.json b/packages/graphql-extensions/package.json index faaf8277..a932e46f 100644 --- a/packages/graphql-extensions/package.json +++ b/packages/graphql-extensions/package.json @@ -1,6 +1,6 @@ { "name": "graphql-extensions", - "version": "0.4.0", + "version": "0.4.1", "description": "Add extensions to GraphQL servers", "main": "./dist/index.js", "types": "./dist/index.d.ts",