Skip to content

Commit

Permalink
Support @apollo/server
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilkisiela committed Feb 8, 2023
1 parent 74eb101 commit f59860c
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 233 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-windows-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-hive/client': minor
---

Add @apollo/server and @envelop/types as optional dependencies
5 changes: 5 additions & 0 deletions .changeset/soft-gifts-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-hive/client': minor
---

Support @apollo/server
7 changes: 5 additions & 2 deletions packages/libraries/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@
"axios": "^1.2.1",
"tiny-lru": "8.0.2"
},
"optionalDependencies": {
"@apollo/server": "^4.0.0",
"@envelop/types": "^3.0.0"
},
"devDependencies": {
"@apollo/federation": "0.38.1",
"@apollo/server": "4.3.3",
"@envelop/types": "3.0.1",
"@types/async-retry": "1.4.5",
"apollo-server-core": "3.11.1",
"apollo-server-plugin-base": "3.7.1",
"graphql-yoga": "3.5.1",
"nock": "13.3.0"
},
Expand Down
27 changes: 24 additions & 3 deletions packages/libraries/client/src/apollo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createHash } from 'crypto';
import type { ApolloServerPlugin } from 'apollo-server-plugin-base';
import axios from 'axios';
import type { DocumentNode } from 'graphql';
import type { ApolloServerPlugin } from '@apollo/server';
import { createHive } from './client.js';
import type {
HiveClient,
Expand Down Expand Up @@ -149,6 +149,8 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
requestDidStart(context) {
// `overallCachePolicy` does not exist in v0
const isLegacyV0 = !('overallCachePolicy' in context);
// `context` does not exist in v4, it is `contextValue` instead
const isLegacyV3 = 'context' in context;

let doc: DocumentNode;
const complete = hive.collectUsage({
Expand All @@ -157,7 +159,7 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
return doc;
},
operationName: context.operationName,
contextValue: context.context,
contextValue: isLegacyV3 ? context.context : context.contextValue,
variableValues: context.request.variables,
});

Expand All @@ -170,10 +172,27 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
} as any;
}

if (isLegacyV3) {
return Promise.resolve({
async willSendResponse(ctx) {
doc = ctx.document!;
complete(ctx.response as any);
},
});
}

// v4
return Promise.resolve({
async willSendResponse(ctx) {
doc = ctx.document!;
complete(ctx.response);
if (ctx.response.body.kind === 'incremental') {
complete({
action: 'abort',
reason: '@defer and @stream is not supported by Hive',
});
} else {
complete(ctx.response.body.singleResult);
}
},
});
},
Expand All @@ -191,6 +210,8 @@ export function hiveApollo(clientOrOptions: HiveClient | HivePluginOptions): Apo
} as any;
}

// Works on v3 and v4

return Promise.resolve({
async serverWillStop() {
await hive.dispose();
Expand Down
10 changes: 9 additions & 1 deletion packages/libraries/client/src/internal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@ export interface HiveClient {
}

export type AsyncIterableIteratorOrValue<T> = AsyncIterableIterator<T> | T;
export type AsyncIterableOrValue<T> = AsyncIterable<T> | T;
export type AbortAction = {
action: 'abort';
reason: string;
};

export type CollectUsageCallback = (
result: AsyncIterableIteratorOrValue<GraphQLErrorsResult>,
result:
| AsyncIterableIteratorOrValue<GraphQLErrorsResult>
| AsyncIterableOrValue<GraphQLErrorsResult>
| AbortAction,
) => void;
export interface ClientInfo {
name: string;
Expand Down
14 changes: 13 additions & 1 deletion packages/libraries/client/src/internal/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { version } from '../version.js';
import { createAgent } from './agent.js';
import { randomSampling } from './sampling.js';
import type {
AbortAction,
ClientInfo,
CollectUsageCallback,
HivePluginOptions,
Expand All @@ -37,6 +38,7 @@ import type {
import {
cache,
cacheDocumentKey,
isAsyncIterable,
isAsyncIterableIterator,
logIf,
measureDuration,
Expand All @@ -48,6 +50,10 @@ interface UsageCollector {
dispose(): Promise<void>;
}

function isAbortAction(result: Parameters<CollectUsageCallback>[0]): result is AbortAction {
return 'action' in result && result.action === 'abort';
}

export function createUsage(pluginOptions: HivePluginOptions): UsageCollector {
if (!pluginOptions.usage || pluginOptions.enabled === false) {
return {
Expand Down Expand Up @@ -150,7 +156,13 @@ export function createUsage(pluginOptions: HivePluginOptions): UsageCollector {

return function complete(result) {
try {
if (isAsyncIterableIterator(result)) {
if (isAbortAction(result)) {
logger.info(result.reason);
finish();
return;
}

if (isAsyncIterableIterator(result) || isAsyncIterable(result)) {
logger.info('@stream @defer is not supported');
finish();
return;
Expand Down
11 changes: 10 additions & 1 deletion packages/libraries/client/src/internal/utils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { createHash } from 'crypto';
import type { AsyncIterableIteratorOrValue, HiveClient, HivePluginOptions } from './types.js';
import type {
AsyncIterableIteratorOrValue,
AsyncIterableOrValue,
HiveClient,
HivePluginOptions,
} from './types.js';

export function isAsyncIterableIterator<T>(
value: AsyncIterableIteratorOrValue<T>,
): value is AsyncIterableIterator<T> {
return typeof (value as any)?.[Symbol.asyncIterator] === 'function';
}

export function isAsyncIterable<T>(value: AsyncIterableOrValue<T>): value is AsyncIterable<T> {
return typeof (value as any)?.[Symbol.asyncIterator] === 'function';
}

export function memo<R, A, K>(fn: (arg: A) => R, cacheKeyFn: (arg: A) => K): (arg: A) => R {
let memoizedResult: R | null = null;
let memoizedKey: K | null = null;
Expand Down
Loading

0 comments on commit f59860c

Please sign in to comment.