graphql-http 1.19.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -61,7 +61,7 @@ import { schema } from './previous-step';
61
61
  // Create the GraphQL over HTTP Node request handler
62
62
  const handler = createHandler({ schema });
63
63
 
64
- // Create a HTTP server using the listner on `/graphql`
64
+ // Create a HTTP server using the listener on `/graphql`
65
65
  const server = http.createServer((req, res) => {
66
66
  if (req.url.startsWith('/graphql')) {
67
67
  handler(req, res);
@@ -222,6 +222,16 @@ export default {
222
222
  };
223
223
  ```
224
224
 
225
+ ##### With [`Netlify Functions`](https://docs.netlify.com/functions/overview/)
226
+
227
+ ```js
228
+ import { createHandler } from 'graphql-http/lib/use/@netlify/functions'; // yarn add @netlify/functions
229
+ import { schema } from './previous-step';
230
+
231
+ // Create the GraphQL over HTTP native fetch handler
232
+ export const handler = createHandler({ schema });
233
+ ```
234
+
225
235
  #### Use the client
226
236
 
227
237
  ```js
@@ -560,8 +570,8 @@ const client = createClient({
560
570
 
561
571
  </details>
562
572
 
563
- <details id="migrating-express-grpahql">
564
- <summary><a href="#migrating-express-grpahql">🔗</a> Server handler migration from <a href="https://github.com/graphql/express-graphql">express-graphql</a></summary>
573
+ <details id="migrating-express-graphql">
574
+ <summary><a href="#migrating-express-graphql">🔗</a> Server handler migration from <a href="https://github.com/graphql/express-graphql">express-graphql</a></summary>
565
575
 
566
576
  ```diff
567
577
  import express from 'express';
@@ -630,7 +640,7 @@ const handler = createHandler({
630
640
  context: async (req, args) => {
631
641
  return getDynamicContext(req, args);
632
642
  },
633
- // or static context by supplying the value direcly
643
+ // or static context by supplying the value directly
634
644
  });
635
645
  ```
636
646
 
@@ -725,6 +735,78 @@ console.log('Listening to port 4000');
725
735
 
726
736
  </details>
727
737
 
738
+ <details id="graphql-upload-http">
739
+ <summary><a href="#graphql-upload-http">🔗</a> Server handler usage with <a href="https://github.com/jaydenseric/graphql-upload">graphql-upload</a> and <a href="https://nodejs.org/api/http.html">http</a></summary>
740
+
741
+ ```js
742
+ import http from 'http';
743
+ import { createHandler } from 'graphql-http/lib/use/http';
744
+ import processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload
745
+ import { schema } from './my-graphql';
746
+
747
+ const handler = createHandler({
748
+ schema,
749
+ async parseRequestParams(req) {
750
+ const params = await processRequest(req.raw, req.context.res);
751
+ if (Array.isArray(params)) {
752
+ throw new Error('Batching is not supported');
753
+ }
754
+ return {
755
+ ...params,
756
+ // variables must be an object as per the GraphQL over HTTP spec
757
+ variables: Object(params.variables),
758
+ };
759
+ },
760
+ });
761
+
762
+ const server = http.createServer((req, res) => {
763
+ if (req.url.startsWith('/graphql')) {
764
+ handler(req, res);
765
+ } else {
766
+ res.writeHead(404).end();
767
+ }
768
+ });
769
+
770
+ server.listen(4000);
771
+ console.log('Listening to port 4000');
772
+ ```
773
+
774
+ </details>
775
+
776
+ <details id="graphql-upload-express">
777
+ <summary><a href="#graphql-upload-express">🔗</a> Server handler usage with <a href="https://github.com/jaydenseric/graphql-upload">graphql-upload</a> and <a href="https://expressjs.com/">express</a></summary>
778
+
779
+ ```js
780
+ import express from 'express'; // yarn add express
781
+ import { createHandler } from 'graphql-http/lib/use/express';
782
+ import processRequest from 'graphql-upload/processRequest.mjs'; // yarn add graphql-upload
783
+ import { schema } from './my-graphql';
784
+
785
+ const app = express();
786
+ app.all(
787
+ '/graphql',
788
+ createHandler({
789
+ schema,
790
+ async parseRequestParams(req) {
791
+ const params = await processRequest(req.raw, req.context.res);
792
+ if (Array.isArray(params)) {
793
+ throw new Error('Batching is not supported');
794
+ }
795
+ return {
796
+ ...params,
797
+ // variables must be an object as per the GraphQL over HTTP spec
798
+ variables: Object(params.variables),
799
+ };
800
+ },
801
+ }),
802
+ );
803
+
804
+ app.listen({ port: 4000 });
805
+ console.log('Listening to port 4000');
806
+ ```
807
+
808
+ </details>
809
+
728
810
  <details id="audit-jest">
729
811
  <summary><a href="#audit-jest">🔗</a> Audit for servers usage in <a href="https://jestjs.io">Jest</a> environment</summary>
730
812
 
package/lib/client.d.mts CHANGED
@@ -76,7 +76,7 @@ export interface ClientOptions {
76
76
  *
77
77
  * You may implement your own waiting strategy by timing the resolution of the returned promise.
78
78
  *
79
- * Useful for retrying requests that failed because the service is temporarely unavailable.
79
+ * Useful for retrying requests that failed because the service is temporarily unavailable.
80
80
  *
81
81
  * `retries` argument counts actual retries, so it will begin with
82
82
  * 0 after the first failed request.
@@ -135,7 +135,7 @@ export declare function createClient(options: ClientOptions): Client;
135
135
  */
136
136
  export declare class NetworkError<Response extends ResponseLike = ResponseLike> extends Error {
137
137
  /**
138
- * The underlyig response thats considered an error.
138
+ * The underlying response thats considered an error.
139
139
  *
140
140
  * Will be undefined when no response is received,
141
141
  * instead an unexpected network error.
package/lib/client.d.ts CHANGED
@@ -76,7 +76,7 @@ export interface ClientOptions {
76
76
  *
77
77
  * You may implement your own waiting strategy by timing the resolution of the returned promise.
78
78
  *
79
- * Useful for retrying requests that failed because the service is temporarely unavailable.
79
+ * Useful for retrying requests that failed because the service is temporarily unavailable.
80
80
  *
81
81
  * `retries` argument counts actual retries, so it will begin with
82
82
  * 0 after the first failed request.
@@ -135,7 +135,7 @@ export declare function createClient(options: ClientOptions): Client;
135
135
  */
136
136
  export declare class NetworkError<Response extends ResponseLike = ResponseLike> extends Error {
137
137
  /**
138
- * The underlyig response thats considered an error.
138
+ * The underlying response thats considered an error.
139
139
  *
140
140
  * Will be undefined when no response is received,
141
141
  * instead an unexpected network error.
package/lib/common.d.mts CHANGED
@@ -11,10 +11,10 @@
11
11
  * @category Common
12
12
  */
13
13
  export interface RequestParams {
14
- operationName?: string | undefined;
14
+ operationName?: string | null | undefined;
15
15
  query: string;
16
- variables?: Record<string, unknown> | undefined;
17
- extensions?: Record<string, unknown> | undefined;
16
+ variables?: Record<string, unknown> | null | undefined;
17
+ extensions?: Record<string, unknown> | null | undefined;
18
18
  }
19
19
  /**
20
20
  * A representation of any set of values over any amount of time.
@@ -24,7 +24,7 @@ export interface RequestParams {
24
24
  export interface Sink<T = unknown> {
25
25
  /** Next value arriving. */
26
26
  next(value: T): void;
27
- /** An error that has occured. This function "closes" the sink. */
27
+ /** An error that has occurred. This function "closes" the sink. */
28
28
  error(error: unknown): void;
29
29
  /** The sink has completed. This function "closes" the sink. */
30
30
  complete(): void;
package/lib/common.d.ts CHANGED
@@ -11,10 +11,10 @@
11
11
  * @category Common
12
12
  */
13
13
  export interface RequestParams {
14
- operationName?: string | undefined;
14
+ operationName?: string | null | undefined;
15
15
  query: string;
16
- variables?: Record<string, unknown> | undefined;
17
- extensions?: Record<string, unknown> | undefined;
16
+ variables?: Record<string, unknown> | null | undefined;
17
+ extensions?: Record<string, unknown> | null | undefined;
18
18
  }
19
19
  /**
20
20
  * A representation of any set of values over any amount of time.
@@ -24,7 +24,7 @@ export interface RequestParams {
24
24
  export interface Sink<T = unknown> {
25
25
  /** Next value arriving. */
26
26
  next(value: T): void;
27
- /** An error that has occured. This function "closes" the sink. */
27
+ /** An error that has occurred. This function "closes" the sink. */
28
28
  error(error: unknown): void;
29
29
  /** The sink has completed. This function "closes" the sink. */
30
30
  complete(): void;
package/lib/handler.d.mts CHANGED
@@ -84,16 +84,10 @@ export interface ResponseInit {
84
84
  * @category Server
85
85
  */
86
86
  export type Response = readonly [body: ResponseBody | null, init: ResponseInit];
87
- /**
88
- * Checks whether the passed value is the `graphql-http` server agnostic response.
89
- *
90
- * @category Server
91
- */
92
- export declare function isResponse(val: unknown): val is Response;
93
87
  /**
94
88
  * A concrete GraphQL execution context value type.
95
89
  *
96
- * Mainly used because TypeScript collapes unions
90
+ * Mainly used because TypeScript collapses unions
97
91
  * with `any` or `unknown` to `any` or `unknown`. So,
98
92
  * we use a custom type to allow definitions such as
99
93
  * the `context` server option.
@@ -107,6 +101,25 @@ export type OperationContext = Record<PropertyKey, unknown> | symbol | number |
107
101
  * @category Server
108
102
  */
109
103
  export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError | Error;
104
+ /**
105
+ * The request parser for an incoming GraphQL request. It parses and validates the
106
+ * request itself, including the request method and the content-type of the body.
107
+ *
108
+ * In case you are extending the server to handle more request types, this is the
109
+ * perfect place to do so.
110
+ *
111
+ * If an error is thrown, it will be formatted using the provided {@link FormatError}
112
+ * and handled following the spec to be gracefully reported to the client.
113
+ *
114
+ * Throwing an instance of `Error` will _always_ have the client respond with a `400: Bad Request`
115
+ * and the error's message in the response body; however, if an instance of `GraphQLError` is thrown,
116
+ * it will be reported depending on the accepted content-type.
117
+ *
118
+ * If you return nothing, the default parser will be used instead.
119
+ *
120
+ * @category Server
121
+ */
122
+ export type ParseRequestParams<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<RequestParams | Response | void> | RequestParams | Response | void;
110
123
  /** @category Server */
111
124
  export type OperationArgs<Context extends OperationContext = undefined> = ExecutionArgs & {
112
125
  contextValue?: Context;
@@ -223,15 +236,21 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
223
236
  onOperation?: (req: Request<RequestRaw, RequestContext>, args: OperationArgs<Context>, result: ExecutionResult) => Promise<ExecutionResult | Response | void> | ExecutionResult | Response | void;
224
237
  /**
225
238
  * Format handled errors to your satisfaction. Either GraphQL errors
226
- * or safe request processing errors are meant by "handleded errors".
239
+ * or safe request processing errors are meant by "handled errors".
227
240
  *
228
- * If multiple errors have occured, all of them will be mapped using
241
+ * If multiple errors have occurred, all of them will be mapped using
229
242
  * this formatter.
230
243
  */
231
244
  formatError?: FormatError;
245
+ /**
246
+ * The request parser for an incoming GraphQL request.
247
+ *
248
+ * Read more about it in {@link ParseRequestParams}.
249
+ */
250
+ parseRequestParams?: ParseRequestParams<RequestRaw, RequestContext>;
232
251
  }
233
252
  /**
234
- * The ready-to-use handler. Simply plug it in your favourite HTTP framework
253
+ * The ready-to-use handler. Simply plug it in your favorite HTTP framework
235
254
  * and enjoy.
236
255
  *
237
256
  * Errors thrown from **any** of the provided options or callbacks (or even due to
@@ -243,7 +262,7 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
243
262
  export type Handler<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<Response>;
244
263
  /**
245
264
  * Makes a GraphQL over HTTP spec compliant server handler. The handler can
246
- * be used with your favourite server library.
265
+ * be used with your favorite server library.
247
266
  *
248
267
  * Beware that the handler resolves only after the whole operation completes.
249
268
  *
@@ -297,30 +316,3 @@ export type Handler<RequestRaw = unknown, RequestContext = unknown> = (req: Requ
297
316
  * @category Server
298
317
  */
299
318
  export declare function createHandler<RequestRaw = unknown, RequestContext = unknown, Context extends OperationContext = undefined>(options: HandlerOptions<RequestRaw, RequestContext, Context>): Handler<RequestRaw, RequestContext>;
300
- /**
301
- * Request's Media-Type that the server accepts.
302
- *
303
- * @category Server
304
- */
305
- export type AcceptableMediaType = 'application/graphql-response+json' | 'application/json';
306
- /**
307
- * Inspects the request and detects the appropriate/acceptable Media-Type
308
- * looking at the `Accept` header while complying with the GraphQL over HTTP spec.
309
- *
310
- * @category Server
311
- */
312
- export declare function getAcceptableMediaType(acceptHeader: string | null | undefined): AcceptableMediaType | null;
313
- /**
314
- * Creates an appropriate GraphQL over HTTP response following the provided arguments.
315
- *
316
- * If the first argument is an `ExecutionResult`, the operation will be treated as "successful".
317
- *
318
- * If the first argument is (an array of) `GraphQLError`, or an `ExecutionResult` without the `data` field, it will be treated
319
- * the response will be constructed with the help of `acceptedMediaType` complying with the GraphQL over HTTP spec.
320
- *
321
- * If the first argument is an `Error`, the operation will be treated as a bad request responding with `400: Bad Request` and the
322
- * error will be present in the `ExecutionResult` style.
323
- *
324
- * @category Server
325
- */
326
- export declare function makeResponse(resultOrErrors: Readonly<ExecutionResult> | Readonly<GraphQLError[]> | Readonly<GraphQLError> | Readonly<Error>, acceptedMediaType: AcceptableMediaType, formatError: FormatError): Response;
package/lib/handler.d.ts CHANGED
@@ -84,16 +84,10 @@ export interface ResponseInit {
84
84
  * @category Server
85
85
  */
86
86
  export type Response = readonly [body: ResponseBody | null, init: ResponseInit];
87
- /**
88
- * Checks whether the passed value is the `graphql-http` server agnostic response.
89
- *
90
- * @category Server
91
- */
92
- export declare function isResponse(val: unknown): val is Response;
93
87
  /**
94
88
  * A concrete GraphQL execution context value type.
95
89
  *
96
- * Mainly used because TypeScript collapes unions
90
+ * Mainly used because TypeScript collapses unions
97
91
  * with `any` or `unknown` to `any` or `unknown`. So,
98
92
  * we use a custom type to allow definitions such as
99
93
  * the `context` server option.
@@ -107,6 +101,25 @@ export type OperationContext = Record<PropertyKey, unknown> | symbol | number |
107
101
  * @category Server
108
102
  */
109
103
  export type FormatError = (err: Readonly<GraphQLError | Error>) => GraphQLError | Error;
104
+ /**
105
+ * The request parser for an incoming GraphQL request. It parses and validates the
106
+ * request itself, including the request method and the content-type of the body.
107
+ *
108
+ * In case you are extending the server to handle more request types, this is the
109
+ * perfect place to do so.
110
+ *
111
+ * If an error is thrown, it will be formatted using the provided {@link FormatError}
112
+ * and handled following the spec to be gracefully reported to the client.
113
+ *
114
+ * Throwing an instance of `Error` will _always_ have the client respond with a `400: Bad Request`
115
+ * and the error's message in the response body; however, if an instance of `GraphQLError` is thrown,
116
+ * it will be reported depending on the accepted content-type.
117
+ *
118
+ * If you return nothing, the default parser will be used instead.
119
+ *
120
+ * @category Server
121
+ */
122
+ export type ParseRequestParams<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<RequestParams | Response | void> | RequestParams | Response | void;
110
123
  /** @category Server */
111
124
  export type OperationArgs<Context extends OperationContext = undefined> = ExecutionArgs & {
112
125
  contextValue?: Context;
@@ -223,15 +236,21 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
223
236
  onOperation?: (req: Request<RequestRaw, RequestContext>, args: OperationArgs<Context>, result: ExecutionResult) => Promise<ExecutionResult | Response | void> | ExecutionResult | Response | void;
224
237
  /**
225
238
  * Format handled errors to your satisfaction. Either GraphQL errors
226
- * or safe request processing errors are meant by "handleded errors".
239
+ * or safe request processing errors are meant by "handled errors".
227
240
  *
228
- * If multiple errors have occured, all of them will be mapped using
241
+ * If multiple errors have occurred, all of them will be mapped using
229
242
  * this formatter.
230
243
  */
231
244
  formatError?: FormatError;
245
+ /**
246
+ * The request parser for an incoming GraphQL request.
247
+ *
248
+ * Read more about it in {@link ParseRequestParams}.
249
+ */
250
+ parseRequestParams?: ParseRequestParams<RequestRaw, RequestContext>;
232
251
  }
233
252
  /**
234
- * The ready-to-use handler. Simply plug it in your favourite HTTP framework
253
+ * The ready-to-use handler. Simply plug it in your favorite HTTP framework
235
254
  * and enjoy.
236
255
  *
237
256
  * Errors thrown from **any** of the provided options or callbacks (or even due to
@@ -243,7 +262,7 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
243
262
  export type Handler<RequestRaw = unknown, RequestContext = unknown> = (req: Request<RequestRaw, RequestContext>) => Promise<Response>;
244
263
  /**
245
264
  * Makes a GraphQL over HTTP spec compliant server handler. The handler can
246
- * be used with your favourite server library.
265
+ * be used with your favorite server library.
247
266
  *
248
267
  * Beware that the handler resolves only after the whole operation completes.
249
268
  *
@@ -297,30 +316,3 @@ export type Handler<RequestRaw = unknown, RequestContext = unknown> = (req: Requ
297
316
  * @category Server
298
317
  */
299
318
  export declare function createHandler<RequestRaw = unknown, RequestContext = unknown, Context extends OperationContext = undefined>(options: HandlerOptions<RequestRaw, RequestContext, Context>): Handler<RequestRaw, RequestContext>;
300
- /**
301
- * Request's Media-Type that the server accepts.
302
- *
303
- * @category Server
304
- */
305
- export type AcceptableMediaType = 'application/graphql-response+json' | 'application/json';
306
- /**
307
- * Inspects the request and detects the appropriate/acceptable Media-Type
308
- * looking at the `Accept` header while complying with the GraphQL over HTTP spec.
309
- *
310
- * @category Server
311
- */
312
- export declare function getAcceptableMediaType(acceptHeader: string | null | undefined): AcceptableMediaType | null;
313
- /**
314
- * Creates an appropriate GraphQL over HTTP response following the provided arguments.
315
- *
316
- * If the first argument is an `ExecutionResult`, the operation will be treated as "successful".
317
- *
318
- * If the first argument is (an array of) `GraphQLError`, or an `ExecutionResult` without the `data` field, it will be treated
319
- * the response will be constructed with the help of `acceptedMediaType` complying with the GraphQL over HTTP spec.
320
- *
321
- * If the first argument is an `Error`, the operation will be treated as a bad request responding with `400: Bad Request` and the
322
- * error will be present in the `ExecutionResult` style.
323
- *
324
- * @category Server
325
- */
326
- export declare function makeResponse(resultOrErrors: Readonly<ExecutionResult> | Readonly<GraphQLError[]> | Readonly<GraphQLError> | Readonly<Error>, acceptedMediaType: AcceptableMediaType, formatError: FormatError): Response;