Skip to content

Commit

Permalink
Move cache declarations to @apollo/cache-control-types (#6764)
Browse files Browse the repository at this point in the history
(This package temporarily resides in the apollo-utils repo so that we
can publish it as non-alpha during the AS4 alpha process, eg for use in
`@apollo/subgraph`.)

Notably, this removes the `declare module` declaration. This does mean
that TypeScript users will have to work a tad harder (as shown in the
migration guide) to access dynamic cacheControl, but it also means that
we no longer have to worry about multiple copies of `declare module` in
a TypeScript build conflicting with each other, which has been a serious
source of pain in this past.

Co-authored-by: Rose M Koron <32436232+rkoron007@users.noreply.github.com>
  • Loading branch information
glasser and rkoron007 committed Aug 4, 2022
1 parent a92ef7a commit c4115e9
Show file tree
Hide file tree
Showing 17 changed files with 107 additions and 97 deletions.
7 changes: 7 additions & 0 deletions .changeset/pink-eggs-draw.md
@@ -0,0 +1,7 @@
---
"@apollo/server-integration-testsuite": patch
"@apollo/server-plugin-response-cache": patch
"@apollo/server": patch
---

Get cache-control types from @apollo/cache-control-types; no more `declare module` for info.cacheControl
36 changes: 35 additions & 1 deletion docs/source/migration.mdx
Expand Up @@ -1090,6 +1090,7 @@ In Apollo Server 4, if your server _hasn't_ set up draining and it receives an o
If you are using the `startStandaloneServer` function, your server drains automatically. If you are using `expressMiddleware` or another `http.Server`-based web server, you can add draining using the [`ApolloServerPluginDrainHttpServer` plugin](/apollo-server/api/plugin/drain-http-server/#using-the-plugin).
### `CacheScope` type
In Apollo Server 4, `CacheScope` is now a union of strings (`PUBLIC` or `PRIVATE`) rather than an enum:
```ts
Expand All @@ -1098,7 +1099,7 @@ export type CacheScope = 'PUBLIC' | 'PRIVATE';
You can no longer type `CacheScope.Public` or `CacheScope.Private`. Instead, just use the string `'PUBLIC'` or `'PRIVATE'`. Values defined as `CacheScope` will only accept those two values, so any typos are still caught at compile time.
You can now import `CacheScope` from the new `@apollo/cache-control-types` package (instead of importing it from an Apollo Server package). This enables libraries that work with multiple GraphQL servers (such as `@apollo/subgraph`) to refer to `CacheScope` without depending on `@apollo/server`.
## Plugin API changes
Expand Down Expand Up @@ -1322,6 +1323,39 @@ In Apollo Server 3, the `apollo-server-env` package primarily provides TypeScrip
Apollo Server 4 introduces `@apollo/utils.fetcher`, which defines a minimal fetch API (`Fetcher`) that provides Fetch API TypeScript typings. It is similar to `apollo-server-env` but has a clearer name and only supports argument structures that are likely to be compatible across many implementations of the Fetch API. (Specifically, it does not allow you to pass `Request` or `Headers` objects to `fetch`, because libraries often only know how to recognize their own implementations of these interfaces.)
### `@apollo/cache-control-types`
In Apollo Server 3, you could import the `CacheScope`, `CacheHint`, `CacheAnnotation`, `CachePolicy`, and `ResolveInfoCacheControl` types from your chosen Apollo Server package.
In Apollo Server 4, the new `@apollo/cache-control-types` package exports the [`CacheScope`](#cachescope-type), `CacheHint`, `CacheAnnotation`, `CachePolicy`, and `ResolveInfoCacheControl` types. This enables libraries that work with multiple GraphQL servers (such as `@apollo/subgraph`) to refer to these types without depending on `@apollo/server`.
Apollo Server 4 no longer uses the `declare module` TypeScript feature to declare that all `GraphQLResolveInfo` objects (i.e., the `info` argument to resolvers) have a `cacheControl` field. Instead, `@apollo/cache-control-types` provides a `GraphQLResolveInfoWithCacheControl` interface that you can cast `info` to (if you don't want run-time validation), or if you do want runtime validation, you can use the `maybeCacheControlFromInfo` and `cacheControlFromInfo` functions.
For example, if you had this resolver in Apollo Server 3:
```ts
someField(parent, args, context, { cacheControl }) {
cacheControl.setCacheHint({ maxAge: 100 });
}
```
you can write this in Apollo Server 4:
```ts
import { cacheControlFromInfo } from '@apollo/cache-control-types';

// ...
someField(parent, args, context, info) {
cacheControlFromInfo(info).setCacheHint({ maxAge: 100 });
}
```
Alternatively, you can declare `info` to be of type `GraphQLResolveInfoWithCacheControl`. For example, if using `graphql-code-generator` with `typescript-resolvers`, you can use the `customResolveInfo` option.
Note: this is a TypeScript-specific change. The runtime representation hasn't changed, and JavaScript code can continue to access `info.cacheControl` directly.
The `CacheAnnotation` type is no longer exported from any package.
### Renamed types
This section lists the TypeScript-only types (i.e., interfaces, not classes) whose names changed in Apollo Server 4 (not including those mentioned elsewhere in this guide).
Expand Down
19 changes: 19 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -40,6 +40,7 @@
"npm": "^8.5.0"
},
"devDependencies": {
"@apollo/cache-control-types": "1.0.2",
"@apollo/client": "3.6.9",
"@apollo/utils.createhash": "1.1.0",
"@changesets/changelog-github": "0.4.6",
Expand Down
1 change: 1 addition & 0 deletions packages/integration-testsuite/package.json
Expand Up @@ -27,6 +27,7 @@
"node": ">=14.0"
},
"dependencies": {
"@apollo/cache-control-types": "^1.0.2",
"@apollo/client": "^3.6.9",
"@apollo/utils.keyvaluecache": "^1.0.1",
"@apollo/utils.createhash": "^1.1.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/integration-testsuite/src/httpServerTests.ts
Expand Up @@ -46,6 +46,7 @@ import {
afterEach,
} from '@jest/globals';
import type { Mock, SpyInstance } from 'jest-mock';
import { cacheControlFromInfo } from '@apollo/cache-control-types';

const QueryRootType = new GraphQLObjectType({
name: 'QueryRoot',
Expand Down Expand Up @@ -132,7 +133,7 @@ const queryType = new GraphQLObjectType({
testPersonWithCacheControl: {
type: personType,
resolve(_source, _args, _context, info) {
info.cacheControl.setCacheHint({ maxAge: 11 });
cacheControlFromInfo(info).setCacheHint({ maxAge: 11 });
return { firstName: 'Jane', lastName: 'Doe' };
},
},
Expand Down
@@ -1,7 +1,7 @@
import type { CacheHint } from '@apollo/cache-control-types';
import type {
ApolloServerPlugin,
BaseContext,
CacheHint,
GraphQLRequestContext,
GraphQLRequestListener,
GraphQLResponse,
Expand Down
1 change: 1 addition & 0 deletions packages/server/package.json
Expand Up @@ -89,6 +89,7 @@
"node": ">=12.0"
},
"dependencies": {
"@apollo/cache-control-types": "^1.0.2",
"@apollo/usage-reporting-protobuf": "^4.0.0-alpha.1",
"@apollo/utils.createhash": "^1.1.0",
"@apollo/utils.fetcher": "^1.0.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/__tests__/cachePolicy.test.ts
@@ -1,4 +1,4 @@
import type { CachePolicy } from '..';
import type { CachePolicy } from '@apollo/cache-control-types';
import { newCachePolicy } from '../cachePolicy.js';

describe('newCachePolicy', () => {
Expand Down
Expand Up @@ -3,7 +3,8 @@ import {
ApolloServerPluginCacheControl,
ApolloServerPluginCacheControlOptions,
} from '../../../plugin/cacheControl';
import { ApolloServer, CacheHint, HTTPGraphQLResponse } from '../../..';
import { ApolloServer, HTTPGraphQLResponse } from '../../..';
import type { CacheHint } from '@apollo/cache-control-types';

describe('plugin', () => {
describe('willSendResponse', () => {
Expand Down
@@ -1,5 +1,6 @@
import type { CacheHint } from '@apollo/cache-control-types';
import type { GraphQLSchema } from 'graphql';
import { ApolloServer, CacheHint } from '../../..';
import { ApolloServer } from '../../..';
import {
ApolloServerPluginCacheControl,
ApolloServerPluginCacheControlOptions,
Expand Down
@@ -1,3 +1,4 @@
import { cacheControlFromInfo } from '@apollo/cache-control-types';
import type {
GraphQLScalarType,
GraphQLFieldResolver,
Expand Down Expand Up @@ -38,8 +39,8 @@ describe('dynamic cache control', () => {

const resolvers: GraphQLResolvers = {
Query: {
droid: (_source, _args, _context, { cacheControl }) => {
cacheControl.setCacheHint({ maxAge: 60 });
droid: (_source, _args, _context, info) => {
cacheControlFromInfo(info).setCacheHint({ maxAge: 60 });
return {
id: 2001,
name: 'R2-D2',
Expand Down Expand Up @@ -82,8 +83,8 @@ describe('dynamic cache control', () => {

const resolvers: GraphQLResolvers = {
Query: {
droid: (_source, _args, _context, { cacheControl }) => {
cacheControl.cacheHint.restrict({ maxAge: 60 });
droid: (_source, _args, _context, info) => {
cacheControlFromInfo(info).cacheHint.restrict({ maxAge: 60 });
return {
id: 2001,
name: 'R2-D2',
Expand Down Expand Up @@ -126,8 +127,8 @@ describe('dynamic cache control', () => {

const resolvers: GraphQLResolvers = {
Query: {
droid: (_source, _args, _context, { cacheControl }) => {
cacheControl.setCacheHint({ scope: 'PRIVATE' });
droid: (_source, _args, _context, info) => {
cacheControlFromInfo(info).setCacheHint({ scope: 'PRIVATE' });
return {
id: 2001,
name: 'R2-D2',
Expand Down Expand Up @@ -172,8 +173,8 @@ describe('dynamic cache control', () => {

const resolvers: GraphQLResolvers = {
Query: {
droid: (_source, _args, _context, { cacheControl }) => {
cacheControl.setCacheHint({ maxAge: 120 });
droid: (_source, _args, _context, info) => {
cacheControlFromInfo(info).setCacheHint({ maxAge: 120 });
return {
id: 2001,
name: 'R2-D2',
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/cachePolicy.ts
@@ -1,4 +1,4 @@
import type { CacheHint, CachePolicy } from './externalTypes';
import type { CacheHint, CachePolicy } from '@apollo/cache-control-types';

export function newCachePolicy(): CachePolicy {
return {
Expand Down
66 changes: 0 additions & 66 deletions packages/server/src/externalTypes/cacheControl.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/server/src/externalTypes/graphql.ts
Expand Up @@ -6,7 +6,7 @@ import type {
GraphQLSchema,
OperationDefinitionNode,
} from 'graphql';
import type { CachePolicy } from './cacheControl';
import type { CachePolicy } from '@apollo/cache-control-types';
import type { BaseContext } from './context';
import type { HTTPGraphQLHead, HTTPGraphQLRequest } from './http';
import type { ApolloServer } from '../ApolloServer';
Expand Down
6 changes: 0 additions & 6 deletions packages/server/src/externalTypes/index.ts
Expand Up @@ -4,12 +4,6 @@
* is re-exported by the root (via * export), so add exports to this file with
* intention (it's public API).
*/
export type {
CacheAnnotation,
CacheHint,
CachePolicy,
CacheScope,
} from './cacheControl.js';
export type { BaseContext, ContextFunction, ContextThunk } from './context.js';
export type {
GraphQLRequest,
Expand Down

0 comments on commit c4115e9

Please sign in to comment.