-
Notifications
You must be signed in to change notification settings - Fork 564
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Urql Exchange & Apollo Client Link (#1448)
- Loading branch information
Showing
12 changed files
with
716 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@graphql-yoga/urql-exchange': major | ||
--- | ||
|
||
New URQL Exchange |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@graphql-yoga/apollo-link': major | ||
--- | ||
|
||
New Apollo Link |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
{ | ||
"name": "@graphql-yoga/apollo-link", | ||
"version": "0.0.0", | ||
"description": "", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/dotansimha/graphql-yoga.git", | ||
"directory": "packages/apollo-link" | ||
}, | ||
"main": "dist/cjs/index.js", | ||
"module": "dist/esm/index.js", | ||
"scripts": { | ||
"check": "tsc --pretty --noEmit" | ||
}, | ||
"keywords": [ | ||
"graphql", | ||
"server", | ||
"graphql-yoga", | ||
"apollo" | ||
], | ||
"author": "Arda TANRIKULU <ardatanrikulu@gmail.com>", | ||
"license": "MIT", | ||
"buildOptions": { | ||
"input": "./src/index.ts" | ||
}, | ||
"exports": { | ||
".": { | ||
"require": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/cjs/index.js" | ||
}, | ||
"import": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
}, | ||
"default": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
} | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"typings": "dist/typings/index.d.ts", | ||
"typescript": { | ||
"definition": "dist/typings/index.d.ts" | ||
}, | ||
"publishConfig": { | ||
"directory": "dist", | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@graphql-tools/url-loader": "7.12.4", | ||
"@graphql-tools/utils": "8.8.0", | ||
"tslib": "^2.3.1" | ||
}, | ||
"devDependencies": { | ||
"@apollo/client": "3.6.9" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^15.2.0 || ^16.0.0", | ||
"@apollo/client": "^3.5.9" | ||
}, | ||
"type": "module" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import * as apolloImport from '@apollo/client' | ||
import { | ||
LoadFromUrlOptions, | ||
SubscriptionProtocol, | ||
UrlLoader, | ||
} from '@graphql-tools/url-loader' | ||
import { ExecutionRequest, isAsyncIterable } from '@graphql-tools/utils' | ||
|
||
export type YogaLinkOptions = LoadFromUrlOptions & { endpoint: string } | ||
|
||
const apollo: typeof apolloImport = | ||
(apolloImport as any)?.default ?? apolloImport | ||
|
||
function createYogaApolloRequestHandler( | ||
options: YogaLinkOptions, | ||
): apolloImport.RequestHandler { | ||
const urlLoader = new UrlLoader() | ||
const executor = urlLoader.getExecutorAsync(options.endpoint, { | ||
subscriptionsProtocol: SubscriptionProtocol.SSE, | ||
multipart: true, | ||
...options, | ||
}) | ||
return function graphQLYogaApolloRequestHandler( | ||
operation: apolloImport.Operation, | ||
): apolloImport.Observable<apolloImport.FetchResult> { | ||
return new apollo.Observable((observer) => { | ||
const executionRequest: ExecutionRequest = { | ||
document: operation.query, | ||
variables: operation.variables, | ||
operationName: operation.operationName, | ||
extensions: operation.extensions, | ||
context: operation.getContext(), | ||
} | ||
executor(executionRequest) | ||
.then(async (results) => { | ||
if (isAsyncIterable(results)) { | ||
for await (const result of results) { | ||
if (observer.closed) { | ||
return | ||
} | ||
observer.next(result) | ||
} | ||
observer.complete() | ||
} else { | ||
if (!observer.closed) { | ||
observer.next(results) | ||
observer.complete() | ||
} | ||
} | ||
}) | ||
.catch((error) => { | ||
if (!observer.closed) { | ||
observer.error(error) | ||
} | ||
}) | ||
}) | ||
} | ||
} | ||
|
||
export class YogaLink extends apollo.ApolloLink { | ||
constructor(options: YogaLinkOptions) { | ||
super(createYogaApolloRequestHandler(options)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { ApolloClient, FetchResult, InMemoryCache } from '@apollo/client/core' | ||
import { createYoga } from 'graphql-yoga' | ||
import { createServer } from 'http' | ||
import { parse } from 'graphql' | ||
import { observableToAsyncIterable } from '@graphql-tools/utils' | ||
import { YogaLink } from '../src' | ||
import { File } from '@whatwg-node/fetch' | ||
|
||
describe('Yoga Apollo Link', () => { | ||
const port = 4000 + Math.floor(Math.random() * 1000) | ||
const endpoint = '/graphql' | ||
const hostname = '127.0.0.1' | ||
const yoga = createYoga({ | ||
endpoint, | ||
logging: false, | ||
maskedErrors: false, | ||
schema: { | ||
typeDefs: /* GraphQL */ ` | ||
scalar File | ||
type Query { | ||
hello: String | ||
} | ||
type Mutation { | ||
readFile(file: File!): String! | ||
} | ||
type Subscription { | ||
time: String | ||
} | ||
`, | ||
resolvers: { | ||
Query: { | ||
hello: () => 'Hello Apollo Client!', | ||
}, | ||
Mutation: { | ||
readFile: (_, args: { file: File }) => args.file.text(), | ||
}, | ||
Subscription: { | ||
time: { | ||
async *subscribe() { | ||
while (true) { | ||
await new Promise((resolve) => setTimeout(resolve, 1000)) | ||
yield new Date().toISOString() | ||
} | ||
}, | ||
resolve: (str) => str, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}) | ||
const server = createServer(yoga) | ||
const url = `http://${hostname}:${port}${endpoint}` | ||
const client = new ApolloClient({ | ||
link: new YogaLink({ | ||
endpoint: url, | ||
}), | ||
cache: new InMemoryCache(), | ||
}) | ||
beforeAll(async () => { | ||
await new Promise<void>((resolve) => server.listen(port, hostname, resolve)) | ||
}) | ||
afterAll(async () => { | ||
await new Promise((resolve) => server.close(resolve)) | ||
}) | ||
it('should handle queries correctly', async () => { | ||
const result = await client.query({ | ||
query: parse(/* GraphQL */ ` | ||
query Greetings { | ||
hello | ||
} | ||
`), | ||
}) | ||
expect(result.error).toBeUndefined() | ||
expect(result.errors?.length).toBeFalsy() | ||
expect(result.data).toEqual({ | ||
hello: 'Hello Apollo Client!', | ||
}) | ||
}) | ||
it('should handle subscriptions correctly', async () => { | ||
const observable = client.subscribe({ | ||
query: parse(/* GraphQL */ ` | ||
subscription Time { | ||
time | ||
} | ||
`), | ||
}) | ||
const asyncIterable = | ||
observableToAsyncIterable< | ||
FetchResult<any, Record<string, any>, Record<string, any>> | ||
>(observable) | ||
let i = 0 | ||
for await (const result of asyncIterable) { | ||
i++ | ||
if (i === 2) { | ||
break | ||
} | ||
expect(result.errors?.length).toBeFalsy() | ||
const date = new Date(result?.data?.time) | ||
expect(date.getFullYear()).toBe(new Date().getFullYear()) | ||
} | ||
expect(i).toBe(2) | ||
}) | ||
it('should handle file uploads correctly', async () => { | ||
const result = await client.mutate({ | ||
mutation: parse(/* GraphQL */ ` | ||
mutation readFile($file: File!) { | ||
readFile(file: $file) | ||
} | ||
`), | ||
variables: { | ||
file: new File(['Hello World'], 'file.txt', { type: 'text/plain' }), | ||
}, | ||
}) | ||
expect(result.errors?.length).toBeFalsy() | ||
expect(result.data).toEqual({ | ||
readFile: 'Hello World', | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
{ | ||
"name": "@graphql-yoga/urql-exchange", | ||
"version": "0.0.0", | ||
"description": "", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/dotansimha/graphql-yoga.git", | ||
"directory": "packages/urql-exchange" | ||
}, | ||
"main": "dist/cjs/index.js", | ||
"module": "dist/esm/index.js", | ||
"scripts": { | ||
"check": "tsc --pretty --noEmit" | ||
}, | ||
"keywords": [ | ||
"graphql", | ||
"server", | ||
"graphql-yoga", | ||
"apollo" | ||
], | ||
"author": "Arda TANRIKULU <ardatanrikulu@gmail.com>", | ||
"license": "MIT", | ||
"buildOptions": { | ||
"input": "./src/index.ts" | ||
}, | ||
"exports": { | ||
".": { | ||
"require": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/cjs/index.js" | ||
}, | ||
"import": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
}, | ||
"default": { | ||
"types": "./dist/typings/index.d.ts", | ||
"default": "./dist/esm/index.js" | ||
} | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"typings": "dist/typings/index.d.ts", | ||
"typescript": { | ||
"definition": "dist/typings/index.d.ts" | ||
}, | ||
"publishConfig": { | ||
"directory": "dist", | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@graphql-tools/url-loader": "7.12.4", | ||
"@graphql-tools/utils": "8.8.0", | ||
"tslib": "^2.4.0" | ||
}, | ||
"devDependencies": { | ||
"@urql/core": "2.6.0", | ||
"wonka": "4.0.15" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^15.2.0 || ^16.0.0", | ||
"@urql/core": "^2.4.3", | ||
"wonka": "^4.0.15" | ||
}, | ||
"type": "module" | ||
} |
Oops, something went wrong.