-
-
Notifications
You must be signed in to change notification settings - Fork 458
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(set-context): create set context exchange (#2610)
* create set context exchange * typo * add tests * Update exchanges/context/README.md
- Loading branch information
1 parent
c5c6cf0
commit e79b8ab
Showing
7 changed files
with
281 additions
and
0 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 @@ | ||
# Changelog | ||
|
||
## v0.1.0 | ||
|
||
**Initial Release** |
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,41 @@ | ||
<h2 align="center">@urql/exchange-context</h2> | ||
|
||
<p align="center"><strong>An exchange for setting operation context in <code>urql</code></strong></p> | ||
|
||
`@urql/exchange-context` is an exchange for the [`urql`](https://github.com/FormidableLabs/urql) GraphQL client which can set the operation context both synchronously as well as asynchronously | ||
|
||
## Quick Start Guide | ||
|
||
First install `@urql/exchange-context` alongside `urql`: | ||
|
||
```sh | ||
yarn add @urql/exchange-context | ||
# or | ||
npm install --save @urql/exchange-context | ||
``` | ||
|
||
You'll then need to add the `contextExchange`, that this package exposes, to your `urql` Client, the positioning of this exchange depends on whether you set an async setter or not. If you set an async context-setter it's best placed after all the synchronous exchanges (in front of the fetchExchange). | ||
|
||
```js | ||
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql'; | ||
import { contextExchange } from '@urql/exchange-context'; | ||
|
||
const client = createClient({ | ||
url: 'http://localhost:1234/graphql', | ||
exchanges: [ | ||
dedupExchange, | ||
cacheExchange, | ||
contextExchange({ | ||
getContext: async (operation) => { | ||
const token = await getToken(); | ||
return { ...operation.context, headers: { authorization: token } } | ||
}, | ||
}), | ||
fetchExchange, | ||
], | ||
}); | ||
``` | ||
|
||
## Maintenance Status | ||
|
||
**Active:** Formidable is actively working on this project, and we expect to continue for work for the foreseeable future. Bug reports, feature requests and pull requests are welcome. |
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,65 @@ | ||
{ | ||
"name": "@urql/exchange-context", | ||
"version": "0.1.0", | ||
"description": "An exchange for setting (a)synchronous operation-context in urql", | ||
"sideEffects": false, | ||
"homepage": "https://formidable.com/open-source/urql/docs/", | ||
"bugs": "https://github.com/FormidableLabs/urql/issues", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/FormidableLabs/urql.git", | ||
"directory": "exchanges/context" | ||
}, | ||
"keywords": [ | ||
"urql", | ||
"exchange", | ||
"context", | ||
"formidablelabs", | ||
"exchanges" | ||
], | ||
"main": "dist/urql-exchange-context", | ||
"module": "dist/urql-exchange-context.mjs", | ||
"types": "dist/types/index.d.ts", | ||
"source": "src/index.ts", | ||
"exports": { | ||
".": { | ||
"import": "./dist/urql-exchange-context.mjs", | ||
"require": "./dist/urql-exchange-context.js", | ||
"types": "./dist/types/index.d.ts", | ||
"source": "./src/index.ts" | ||
}, | ||
"./package.json": "./package.json" | ||
}, | ||
"files": [ | ||
"LICENSE", | ||
"CHANGELOG.md", | ||
"README.md", | ||
"dist/" | ||
], | ||
"scripts": { | ||
"test": "jest", | ||
"clean": "rimraf dist extras", | ||
"check": "tsc --noEmit", | ||
"lint": "eslint --ext=js,jsx,ts,tsx .", | ||
"build": "rollup -c ../../scripts/rollup/config.js", | ||
"prepare": "node ../../scripts/prepare/index.js", | ||
"prepublishOnly": "run-s clean build" | ||
}, | ||
"jest": { | ||
"preset": "../../scripts/jest/preset" | ||
}, | ||
"dependencies": { | ||
"@urql/core": ">=2.3.6", | ||
"wonka": "^6.0.0" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" | ||
}, | ||
"devDependencies": { | ||
"graphql": "^16.0.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
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,117 @@ | ||
import { pipe, map, makeSubject, publish, tap } from 'wonka'; | ||
|
||
import { | ||
gql, | ||
createClient, | ||
Operation, | ||
OperationResult, | ||
ExchangeIO, | ||
} from '@urql/core'; | ||
|
||
import { contextExchange } from './context'; | ||
|
||
const queryOne = gql` | ||
{ | ||
author { | ||
id | ||
name | ||
} | ||
} | ||
`; | ||
|
||
const queryOneData = { | ||
__typename: 'Query', | ||
author: { | ||
__typename: 'Author', | ||
id: '123', | ||
name: 'Author', | ||
}, | ||
}; | ||
|
||
const dispatchDebug = jest.fn(); | ||
let client, op, ops$, next; | ||
beforeEach(() => { | ||
client = createClient({ url: 'http://0.0.0.0' }); | ||
op = client.createRequestOperation('query', { | ||
key: 1, | ||
query: queryOne, | ||
}); | ||
|
||
({ source: ops$, next } = makeSubject<Operation>()); | ||
}); | ||
|
||
it(`calls getContext`, () => { | ||
const response = jest.fn( | ||
(forwardOp: Operation): OperationResult => { | ||
return { | ||
operation: forwardOp, | ||
data: queryOneData, | ||
}; | ||
} | ||
); | ||
|
||
const result = jest.fn(); | ||
const forward: ExchangeIO = ops$ => { | ||
return pipe(ops$, map(response)); | ||
}; | ||
|
||
const headers = { hello: 'world' }; | ||
pipe( | ||
contextExchange({ | ||
getContext: op => ({ ...op.context, headers }), | ||
})({ | ||
forward, | ||
client, | ||
dispatchDebug, | ||
})(ops$), | ||
tap(result), | ||
publish | ||
); | ||
|
||
next(op); | ||
|
||
expect(response).toHaveBeenCalledTimes(1); | ||
expect(response.mock.calls[0][0].context.headers).toEqual(headers); | ||
expect(result).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it(`calls getContext async`, done => { | ||
const response = jest.fn( | ||
(forwardOp: Operation): OperationResult => { | ||
return { | ||
operation: forwardOp, | ||
data: queryOneData, | ||
}; | ||
} | ||
); | ||
|
||
const result = jest.fn(); | ||
const forward: ExchangeIO = ops$ => { | ||
return pipe(ops$, map(response)); | ||
}; | ||
|
||
const headers = { hello: 'world' }; | ||
pipe( | ||
contextExchange({ | ||
getContext: async op => { | ||
await Promise.resolve(); | ||
return { ...op.context, headers }; | ||
}, | ||
})({ | ||
forward, | ||
client, | ||
dispatchDebug, | ||
})(ops$), | ||
tap(result), | ||
publish | ||
); | ||
|
||
next(op); | ||
|
||
setTimeout(() => { | ||
expect(response).toHaveBeenCalledTimes(1); | ||
expect(response.mock.calls[0][0].context.headers).toEqual(headers); | ||
expect(result).toHaveBeenCalledTimes(1); | ||
done(); | ||
}, 10); | ||
}); |
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,39 @@ | ||
import { | ||
Exchange, | ||
makeOperation, | ||
Operation, | ||
OperationContext, | ||
} from '@urql/core'; | ||
import { fromPromise, fromValue, mergeMap, pipe } from 'wonka'; | ||
|
||
export interface ContextExchangeArgs { | ||
getContext: ( | ||
operation: Operation | ||
) => OperationContext | Promise<OperationContext>; | ||
} | ||
|
||
export const contextExchange = ({ | ||
getContext, | ||
}: ContextExchangeArgs): Exchange => ({ forward }) => { | ||
return ops$ => { | ||
return pipe( | ||
ops$, | ||
mergeMap(operation => { | ||
const result = getContext(operation); | ||
const isPromise = 'then' in result; | ||
if (isPromise) { | ||
return fromPromise( | ||
result.then((ctx: OperationContext) => | ||
makeOperation(operation.kind, operation, ctx) | ||
) | ||
); | ||
} else { | ||
return fromValue( | ||
makeOperation(operation.kind, operation, result as OperationContext) | ||
); | ||
} | ||
}), | ||
forward | ||
); | ||
}; | ||
}; |
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 @@ | ||
export { contextExchange, ContextExchangeArgs } from './context'; |
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,13 @@ | ||
{ | ||
"extends": "../../tsconfig.json", | ||
"include": ["src"], | ||
"compilerOptions": { | ||
"baseUrl": "./", | ||
"paths": { | ||
"urql": ["../../node_modules/urql/src"], | ||
"*-urql": ["../../node_modules/*-urql/src"], | ||
"@urql/core/*": ["../../node_modules/@urql/core/src/*"], | ||
"@urql/*": ["../../node_modules/@urql/*/src"] | ||
} | ||
} | ||
} |