Skip to content

Commit

Permalink
fix(handler): Don't export makeResponse, getAcceptableMediaType o…
Browse files Browse the repository at this point in the history
…r `isResponse` (#98)
  • Loading branch information
enisdenjo authored Jul 6, 2023
1 parent c08d4f4 commit a638cb4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 135 deletions.
77 changes: 0 additions & 77 deletions docs/modules/handler.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

### Type Aliases

- [AcceptableMediaType](handler.md#acceptablemediatype)
- [FormatError](handler.md#formaterror)
- [Handler](handler.md#handler)
- [OperationArgs](handler.md#operationargs)
Expand All @@ -25,20 +24,9 @@
### Functions

- [createHandler](handler.md#createhandler)
- [getAcceptableMediaType](handler.md#getacceptablemediatype)
- [isResponse](handler.md#isresponse)
- [makeResponse](handler.md#makeresponse)

## Server

### AcceptableMediaType

Ƭ **AcceptableMediaType**: ``"application/graphql-response+json"`` \| ``"application/json"``

Request's Media-Type that the server accepts.

___

### FormatError

Ƭ **FormatError**: (`err`: `Readonly`<`GraphQLError` \| `Error`\>) => `GraphQLError` \| `Error`
Expand Down Expand Up @@ -227,68 +215,3 @@ console.log('Listening to port 4000');
#### Returns

[`Handler`](handler.md#handler)<`RequestRaw`, `RequestContext`\>

___

### getAcceptableMediaType

**getAcceptableMediaType**(`acceptHeader`): [`AcceptableMediaType`](handler.md#acceptablemediatype) \| ``null``

Inspects the request and detects the appropriate/acceptable Media-Type
looking at the `Accept` header while complying with the GraphQL over HTTP spec.

#### Parameters

| Name | Type |
| :------ | :------ |
| `acceptHeader` | `undefined` \| ``null`` \| `string` |

#### Returns

[`AcceptableMediaType`](handler.md#acceptablemediatype) \| ``null``

___

### isResponse

**isResponse**(`val`): val is Response

Checks whether the passed value is the `graphql-http` server agnostic response.

#### Parameters

| Name | Type |
| :------ | :------ |
| `val` | `unknown` |

#### Returns

val is Response

___

### makeResponse

**makeResponse**(`resultOrErrors`, `acceptedMediaType`, `formatError`): [`Response`](handler.md#response)

Creates an appropriate GraphQL over HTTP response following the provided arguments.

If the first argument is an `ExecutionResult`, the operation will be treated as "successful".

If the first argument is (an array of) `GraphQLError`, or an `ExecutionResult` without the `data` field, it will be treated
the response will be constructed with the help of `acceptedMediaType` complying with the GraphQL over HTTP spec.

If the first argument is an `Error`, the operation will be treated as a bad request responding with `400: Bad Request` and the
error will be present in the `ExecutionResult` style.

#### Parameters

| Name | Type |
| :------ | :------ |
| `resultOrErrors` | readonly `GraphQLError`[] \| `Readonly`<`ExecutionResult`<`ObjMap`<`unknown`\>, `ObjMap`<`unknown`\>\>\> \| `Readonly`<`GraphQLError`\> \| `Readonly`<`Error`\> |
| `acceptedMediaType` | [`AcceptableMediaType`](handler.md#acceptablemediatype) |
| `formatError` | [`FormatError`](handler.md#formaterror) |

#### Returns

[`Response`](handler.md#response)
94 changes: 36 additions & 58 deletions src/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,8 @@ export interface ResponseInit {
*/
export type Response = readonly [body: ResponseBody | null, init: ResponseInit];

/**
* Checks whether the passed value is the `graphql-http` server agnostic response.
*
* @category Server
*/
export function isResponse(val: unknown): val is Response {
/** Checks whether the passed value is the `graphql-http` server agnostic response. */
function isResponse(val: unknown): val is Response {
// TODO: make sure the contents of init match ResponseInit
return (
Array.isArray(val) &&
Expand Down Expand Up @@ -437,7 +433,37 @@ export function createHandler<
];
}

const acceptedMediaType = getAcceptableMediaType(getHeader(req, 'accept'));
let acceptedMediaType: AcceptableMediaType | null = null;
const accepts = (getHeader(req, 'accept') || '*/*')
.replace(/\s/g, '')
.toLowerCase()
.split(',');
for (const accept of accepts) {
// accept-charset became obsolete, shouldnt be used (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset)
// TODO: handle the weight parameter "q"
const [mediaType, ...params] = accept.split(';');
const charset =
params?.find((param) => param.includes('charset=')) || 'charset=utf8'; // utf-8 is assumed when not specified;

if (
mediaType === 'application/graphql-response+json' &&
charset === 'charset=utf8'
) {
acceptedMediaType = 'application/graphql-response+json';
break;
}

// application/json should be the default until watershed
if (
(mediaType === 'application/json' ||
mediaType === 'application/*' ||
mediaType === '*/*') &&
charset === 'charset=utf8'
) {
acceptedMediaType = 'application/json';
break;
}
}
if (!acceptedMediaType) {
return [
null,
Expand Down Expand Up @@ -670,57 +696,11 @@ export function createHandler<
};
}

/**
* Request's Media-Type that the server accepts.
*
* @category Server
*/
export type AcceptableMediaType =
/** Request's Media-Type that the server accepted. */
type AcceptableMediaType =
| 'application/graphql-response+json'
| 'application/json';

/**
* Inspects the request and detects the appropriate/acceptable Media-Type
* looking at the `Accept` header while complying with the GraphQL over HTTP spec.
*
* @category Server
*/
export function getAcceptableMediaType(
acceptHeader: string | null | undefined,
): AcceptableMediaType | null {
let acceptedMediaType: AcceptableMediaType | null = null;
const accepts = (acceptHeader || '*/*')
.replace(/\s/g, '')
.toLowerCase()
.split(',');
for (const accept of accepts) {
// accept-charset became obsolete, shouldnt be used (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Charset)
// TODO: handle the weight parameter "q"
const [mediaType, ...params] = accept.split(';');
const charset =
params?.find((param) => param.includes('charset=')) || 'charset=utf8'; // utf-8 is assumed when not specified;

if (
mediaType === 'application/graphql-response+json' &&
charset === 'charset=utf8'
) {
acceptedMediaType = 'application/graphql-response+json';
break;
}

if (
(mediaType === 'application/json' ||
mediaType === 'application/*' ||
mediaType === '*/*') &&
charset === 'charset=utf8'
) {
acceptedMediaType = 'application/json';
break;
}
}
return acceptedMediaType;
}

/**
* Creates an appropriate GraphQL over HTTP response following the provided arguments.
*
Expand All @@ -731,10 +711,8 @@ export function getAcceptableMediaType(
*
* If the first argument is an `Error`, the operation will be treated as a bad request responding with `400: Bad Request` and the
* error will be present in the `ExecutionResult` style.
*
* @category Server
*/
export function makeResponse(
function makeResponse(
resultOrErrors:
| Readonly<ExecutionResult>
| Readonly<GraphQLError[]>
Expand Down

0 comments on commit a638cb4

Please sign in to comment.