Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(handler): Don't export makeResponse, getAcceptableMediaType or isResponse #98

Merged
merged 3 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading