graphql-http 1.12.0 → 1.14.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.
@@ -15,7 +15,7 @@ export function serverAudits(opts) {
15
15
  // Media Types
16
16
  audit(
17
17
  // TODO: convert to MUST after watershed
18
- 'SHOULD accept application/graphql-response+json and match the content-type', async () => {
18
+ '22EB', 'SHOULD accept application/graphql-response+json and match the content-type', async () => {
19
19
  const res = await fetchFn(await getUrl(opts.url), {
20
20
  method: 'POST',
21
21
  headers: {
@@ -29,7 +29,7 @@ export function serverAudits(opts) {
29
29
  .header('content-type')
30
30
  .toContain('application/graphql-response+json');
31
31
  }),
32
- audit('MUST accept application/json and match the content-type', async () => {
32
+ audit('4655', 'MUST accept application/json and match the content-type', async () => {
33
33
  const res = await fetchFn(await getUrl(opts.url), {
34
34
  method: 'POST',
35
35
  headers: {
@@ -41,7 +41,7 @@ export function serverAudits(opts) {
41
41
  ressert(res).status.toBe(200);
42
42
  ressert(res).header('content-type').toContain('application/json');
43
43
  }),
44
- audit('SHOULD accept */* and use application/json for the content-type', async () => {
44
+ audit('47DE', 'SHOULD accept */* and use application/json for the content-type', async () => {
45
45
  const res = await fetchFn(await getUrl(opts.url), {
46
46
  method: 'POST',
47
47
  headers: {
@@ -53,14 +53,14 @@ export function serverAudits(opts) {
53
53
  ressert(res).status.toBe(200);
54
54
  ressert(res).header('content-type').toContain('application/json');
55
55
  }),
56
- audit('SHOULD assume application/json content-type when accept is missing', async () => {
56
+ audit('80D8', 'SHOULD assume application/json content-type when accept is missing', async () => {
57
57
  const url = new URL(await getUrl(opts.url));
58
58
  url.searchParams.set('query', '{ __typename }');
59
59
  const res = await fetchFn(url.toString());
60
60
  ressert(res).status.toBe(200);
61
61
  ressert(res).header('content-type').toContain('application/json');
62
62
  }),
63
- audit('MUST use utf-8 encoding when responding', async () => {
63
+ audit('82A3', 'MUST use utf-8 encoding when responding', async () => {
64
64
  const res = await fetchFn(await getUrl(opts.url), {
65
65
  method: 'POST',
66
66
  headers: {
@@ -77,7 +77,7 @@ export function serverAudits(opts) {
77
77
  throw new AuditError(res, 'Response body is not UTF-8 encoded');
78
78
  }
79
79
  }),
80
- audit('MUST accept utf-8 encoded request', async () => {
80
+ audit('BF61', 'MUST accept utf-8 encoded request', async () => {
81
81
  const res = await fetchFn(await getUrl(opts.url), {
82
82
  method: 'POST',
83
83
  headers: {
@@ -87,7 +87,7 @@ export function serverAudits(opts) {
87
87
  });
88
88
  ressert(res).status.toBe(200);
89
89
  }),
90
- audit('MUST assume utf-8 in request if encoding is unspecified', async () => {
90
+ audit('78D5', 'MUST assume utf-8 in request if encoding is unspecified', async () => {
91
91
  const res = await fetchFn(await getUrl(opts.url), {
92
92
  method: 'POST',
93
93
  headers: {
@@ -98,7 +98,7 @@ export function serverAudits(opts) {
98
98
  ressert(res).status.toBe(200);
99
99
  }),
100
100
  // Request
101
- audit('MUST accept POST requests', async () => {
101
+ audit('2C94', 'MUST accept POST requests', async () => {
102
102
  const res = await fetchFn(await getUrl(opts.url), {
103
103
  method: 'POST',
104
104
  headers: { 'content-type': 'application/json' },
@@ -106,7 +106,7 @@ export function serverAudits(opts) {
106
106
  });
107
107
  ressert(res).status.toBe(200);
108
108
  }),
109
- audit('MAY accept application/x-www-form-urlencoded formatted GET requests', async () => {
109
+ audit('5A70', 'MAY accept application/x-www-form-urlencoded formatted GET requests', async () => {
110
110
  const url = new URL(await getUrl(opts.url));
111
111
  url.searchParams.set('query', '{ __typename }');
112
112
  const res = await fetchFn(url.toString());
@@ -114,7 +114,7 @@ export function serverAudits(opts) {
114
114
  }),
115
115
  // Request GET
116
116
  // TODO: this is a MUST if the server supports GET requests
117
- audit('MAY NOT allow executing mutations on GET requests', async () => {
117
+ audit('9C48', 'MAY NOT allow executing mutations on GET requests', async () => {
118
118
  const url = new URL(await getUrl(opts.url));
119
119
  url.searchParams.set('query', 'mutation { __typename }');
120
120
  const res = await fetchFn(url.toString(), {
@@ -125,13 +125,13 @@ export function serverAudits(opts) {
125
125
  ressert(res).status.toBeBetween(400, 499);
126
126
  }),
127
127
  // Request POST
128
- audit('SHOULD respond with 4xx status code if content-type is not supplied on POST requests', async () => {
128
+ audit('9ABE', 'SHOULD respond with 4xx status code if content-type is not supplied on POST requests', async () => {
129
129
  const res = await fetchFn(await getUrl(opts.url), {
130
130
  method: 'POST',
131
131
  });
132
132
  ressert(res).status.toBeBetween(400, 499);
133
133
  }),
134
- audit('MUST accept application/json POST requests', async () => {
134
+ audit('03D4', 'MUST accept application/json POST requests', async () => {
135
135
  const res = await fetchFn(await getUrl(opts.url), {
136
136
  method: 'POST',
137
137
  headers: { 'content-type': 'application/json' },
@@ -139,7 +139,7 @@ export function serverAudits(opts) {
139
139
  });
140
140
  ressert(res).status.toBe(200);
141
141
  }),
142
- audit('MUST require a request body on POST', async () => {
142
+ audit('7267', 'MUST require a request body on POST', async () => {
143
143
  var _a;
144
144
  const res = await fetchFn(await getUrl(opts.url), {
145
145
  method: 'POST',
@@ -155,7 +155,7 @@ export function serverAudits(opts) {
155
155
  // Request Parameters
156
156
  audit(
157
157
  // TODO: convert to MUST after watershed
158
- 'SHOULD use 400 status code on missing {query} parameter when accepting application/graphql-response+json', async () => {
158
+ '6610', 'SHOULD use 400 status code on missing {query} parameter when accepting application/graphql-response+json', async () => {
159
159
  const res = await fetchFn(await getUrl(opts.url), {
160
160
  method: 'POST',
161
161
  headers: {
@@ -166,7 +166,7 @@ export function serverAudits(opts) {
166
166
  });
167
167
  ressert(res).status.toBe(400);
168
168
  }),
169
- audit('SHOULD use 200 status code with errors field on missing {query} parameter when accepting application/json', async () => {
169
+ audit('3715', 'SHOULD use 200 status code with errors field on missing {query} parameter when accepting application/json', async () => {
170
170
  const res = await fetchFn(await getUrl(opts.url), {
171
171
  method: 'POST',
172
172
  headers: {
@@ -178,7 +178,7 @@ export function serverAudits(opts) {
178
178
  ressert(res).status.toBe(200);
179
179
  await ressert(res).bodyAsExecutionResult.toHaveProperty('errors');
180
180
  }),
181
- ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(
181
+ ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => audit(`4F5${index}`,
182
182
  // TODO: convert to MUST after watershed
183
183
  `SHOULD use 400 status code on ${extendedTypeof(invalid)} {query} parameter when accepting application/graphql-response+json`, async () => {
184
184
  const res = await fetchFn(await getUrl(opts.url), {
@@ -193,7 +193,7 @@ export function serverAudits(opts) {
193
193
  });
194
194
  ressert(res).status.toBe(400);
195
195
  })),
196
- ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {query} parameter when accepting application/json`, async () => {
196
+ ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => audit(`9FE${index}`, `SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {query} parameter when accepting application/json`, async () => {
197
197
  const res = await fetchFn(await getUrl(opts.url), {
198
198
  method: 'POST',
199
199
  headers: {
@@ -209,7 +209,7 @@ export function serverAudits(opts) {
209
209
  })),
210
210
  audit(
211
211
  // TODO: convert to MUST after watershed
212
- 'SHOULD allow string {query} parameter when accepting application/graphql-response+json', async () => {
212
+ '34A2', 'SHOULD allow string {query} parameter when accepting application/graphql-response+json', async () => {
213
213
  const res = await fetchFn(await getUrl(opts.url), {
214
214
  method: 'POST',
215
215
  headers: {
@@ -222,7 +222,7 @@ export function serverAudits(opts) {
222
222
  });
223
223
  ressert(res).status.toBe(200);
224
224
  }),
225
- audit('MUST allow string {query} parameter when accepting application/json', async () => {
225
+ audit('13EE', 'MUST allow string {query} parameter when accepting application/json', async () => {
226
226
  const res = await fetchFn(await getUrl(opts.url), {
227
227
  method: 'POST',
228
228
  headers: {
@@ -236,7 +236,7 @@ export function serverAudits(opts) {
236
236
  ressert(res).status.toBe(200);
237
237
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
238
238
  }),
239
- ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(
239
+ ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => audit(`E3E${index}`,
240
240
  // TODO: convert to MUST after watershed
241
241
  `SHOULD use 400 status code on ${extendedTypeof(invalid)} {operationName} parameter when accepting application/graphql-response+json`, async () => {
242
242
  const res = await fetchFn(await getUrl(opts.url), {
@@ -252,7 +252,7 @@ export function serverAudits(opts) {
252
252
  });
253
253
  ressert(res).status.toBe(400);
254
254
  })),
255
- ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {operationName} parameter when accepting application/json`, async () => {
255
+ ...[{ obj: 'ect' }, 0, false, ['array']].map((invalid, index) => audit(`FB9${index}`, `SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {operationName} parameter when accepting application/json`, async () => {
256
256
  const res = await fetchFn(await getUrl(opts.url), {
257
257
  method: 'POST',
258
258
  headers: {
@@ -269,7 +269,7 @@ export function serverAudits(opts) {
269
269
  })),
270
270
  audit(
271
271
  // TODO: convert to MUST after watershed
272
- 'SHOULD allow string {operationName} parameter when accepting application/graphql-response+json', async () => {
272
+ '8161', 'SHOULD allow string {operationName} parameter when accepting application/graphql-response+json', async () => {
273
273
  const res = await fetchFn(await getUrl(opts.url), {
274
274
  method: 'POST',
275
275
  headers: {
@@ -283,7 +283,7 @@ export function serverAudits(opts) {
283
283
  });
284
284
  ressert(res).status.toBe(200);
285
285
  }),
286
- audit('MUST allow string {operationName} parameter when accepting application/json', async () => {
286
+ audit('B8B3', 'MUST allow string {operationName} parameter when accepting application/json', async () => {
287
287
  const res = await fetchFn(await getUrl(opts.url), {
288
288
  method: 'POST',
289
289
  headers: {
@@ -298,8 +298,8 @@ export function serverAudits(opts) {
298
298
  ressert(res).status.toBe(200);
299
299
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
300
300
  }),
301
- ...['variables', 'operationName', 'extensions'].flatMap((parameter) => [
302
- audit(
301
+ ...['variables', 'operationName', 'extensions'].flatMap((parameter, index) => [
302
+ audit(`94B${index}`,
303
303
  // TODO: convert to MUST after watershed
304
304
  `SHOULD allow null {${parameter}} parameter when accepting application/graphql-response+json`, async () => {
305
305
  const res = await fetchFn(await getUrl(opts.url), {
@@ -316,7 +316,7 @@ export function serverAudits(opts) {
316
316
  ressert(res).status.toBe(200);
317
317
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
318
318
  }),
319
- audit(`MUST allow null {${parameter}} parameter when accepting application/json`, async () => {
319
+ audit(`022${index}`, `MUST allow null {${parameter}} parameter when accepting application/json`, async () => {
320
320
  const res = await fetchFn(await getUrl(opts.url), {
321
321
  method: 'POST',
322
322
  headers: {
@@ -332,7 +332,7 @@ export function serverAudits(opts) {
332
332
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
333
333
  }),
334
334
  ]),
335
- ...['string', 0, false, ['array']].map((invalid) => audit(
335
+ ...['string', 0, false, ['array']].map((invalid, index) => audit(`69B${index}`,
336
336
  // TODO: convert to MUST after watershed
337
337
  `SHOULD use 400 status code on ${extendedTypeof(invalid)} {variables} parameter when accepting application/graphql-response+json`, async () => {
338
338
  const res = await fetchFn(await getUrl(opts.url), {
@@ -348,7 +348,7 @@ export function serverAudits(opts) {
348
348
  });
349
349
  ressert(res).status.toBe(400);
350
350
  })),
351
- ...['string', 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {variables} parameter when accepting application/json`, async () => {
351
+ ...['string', 0, false, ['array']].map((invalid, index) => audit(`F05${index}`, `SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {variables} parameter when accepting application/json`, async () => {
352
352
  const res = await fetchFn(await getUrl(opts.url), {
353
353
  method: 'POST',
354
354
  headers: {
@@ -365,7 +365,7 @@ export function serverAudits(opts) {
365
365
  })),
366
366
  audit(
367
367
  // TODO: convert to MUST after watershed
368
- 'SHOULD allow map {variables} parameter when accepting application/graphql-response+json', async () => {
368
+ '2EA1', 'SHOULD allow map {variables} parameter when accepting application/graphql-response+json', async () => {
369
369
  const res = await fetchFn(await getUrl(opts.url), {
370
370
  method: 'POST',
371
371
  headers: {
@@ -379,7 +379,7 @@ export function serverAudits(opts) {
379
379
  });
380
380
  ressert(res).status.toBe(200);
381
381
  }),
382
- audit('MUST allow map {variables} parameter when accepting application/json', async () => {
382
+ audit('28B9', 'MUST allow map {variables} parameter when accepting application/json', async () => {
383
383
  const res = await fetchFn(await getUrl(opts.url), {
384
384
  method: 'POST',
385
385
  headers: {
@@ -394,7 +394,7 @@ export function serverAudits(opts) {
394
394
  ressert(res).status.toBe(200);
395
395
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
396
396
  }),
397
- audit('MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/graphql-response+json', async () => {
397
+ audit('D6D5', 'MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/graphql-response+json', async () => {
398
398
  const url = new URL(await getUrl(opts.url));
399
399
  url.searchParams.set('query', 'query Type($name: String!) { __type(name: $name) { name } }');
400
400
  url.searchParams.set('variables', JSON.stringify({ name: 'sometype' }));
@@ -406,7 +406,7 @@ export function serverAudits(opts) {
406
406
  });
407
407
  ressert(res).status.toBe(200);
408
408
  }),
409
- audit('MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/json', async () => {
409
+ audit('6A70', 'MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/json', async () => {
410
410
  const url = new URL(await getUrl(opts.url));
411
411
  url.searchParams.set('query', 'query Type($name: String!) { __type(name: $name) { name } }');
412
412
  url.searchParams.set('variables', JSON.stringify({ name: 'sometype' }));
@@ -419,7 +419,7 @@ export function serverAudits(opts) {
419
419
  ressert(res).status.toBe(200);
420
420
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
421
421
  }),
422
- ...['string', 0, false, ['array']].map((invalid) => audit(
422
+ ...['string', 0, false, ['array']].map((invalid, index) => audit(`904${index}`,
423
423
  // TODO: convert to MUST after watershed
424
424
  `SHOULD use 400 status code on ${extendedTypeof(invalid)} {extensions} parameter when accepting application/graphql-response+json`, async () => {
425
425
  const res = await fetchFn(await getUrl(opts.url), {
@@ -435,7 +435,7 @@ export function serverAudits(opts) {
435
435
  });
436
436
  ressert(res).status.toBe(400);
437
437
  })),
438
- ...['string', 0, false, ['array']].map((invalid) => audit(`SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {extensions} parameter when accepting application/json`, async () => {
438
+ ...['string', 0, false, ['array']].map((invalid, index) => audit(`368${index}`, `SHOULD use 200 status code with errors field on ${extendedTypeof(invalid)} {extensions} parameter when accepting application/json`, async () => {
439
439
  const res = await fetchFn(await getUrl(opts.url), {
440
440
  method: 'POST',
441
441
  headers: {
@@ -452,7 +452,7 @@ export function serverAudits(opts) {
452
452
  })),
453
453
  audit(
454
454
  // TODO: convert to MUST after watershed
455
- 'SHOULD allow map {extensions} parameter when accepting application/graphql-response+json', async () => {
455
+ '428F', 'SHOULD allow map {extensions} parameter when accepting application/graphql-response+json', async () => {
456
456
  const res = await fetchFn(await getUrl(opts.url), {
457
457
  method: 'POST',
458
458
  headers: {
@@ -466,7 +466,7 @@ export function serverAudits(opts) {
466
466
  });
467
467
  ressert(res).status.toBe(200);
468
468
  }),
469
- audit('MUST allow map {extensions} parameter when accepting application/json', async () => {
469
+ audit('1B7A', 'MUST allow map {extensions} parameter when accepting application/json', async () => {
470
470
  const res = await fetchFn(await getUrl(opts.url), {
471
471
  method: 'POST',
472
472
  headers: {
@@ -481,9 +481,9 @@ export function serverAudits(opts) {
481
481
  ressert(res).status.toBe(200);
482
482
  await ressert(res).bodyAsExecutionResult.notToHaveProperty('errors');
483
483
  }),
484
- // TODO: audit('MUST accept a map for the {extensions} parameter'),
484
+ // TODO: audit('39AA', 'MUST accept a map for the {extensions} parameter'),
485
485
  // Response application/json
486
- audit('SHOULD use 200 status code on JSON parsing failure when accepting application/json', async () => {
486
+ audit('D477', 'SHOULD use 200 status code on JSON parsing failure when accepting application/json', async () => {
487
487
  const res = await fetchFn(await getUrl(opts.url), {
488
488
  method: 'POST',
489
489
  headers: {
@@ -494,7 +494,7 @@ export function serverAudits(opts) {
494
494
  });
495
495
  ressert(res).status.toBe(200);
496
496
  }),
497
- audit('SHOULD use 200 status code if parameters are invalid when accepting application/json', async () => {
497
+ audit('F5AF', 'SHOULD use 200 status code if parameters are invalid when accepting application/json', async () => {
498
498
  const res = await fetchFn(await getUrl(opts.url), {
499
499
  method: 'POST',
500
500
  headers: {
@@ -507,7 +507,7 @@ export function serverAudits(opts) {
507
507
  });
508
508
  ressert(res).status.toBe(200);
509
509
  }),
510
- audit('SHOULD use 200 status code on document parsing failure when accepting application/json', async () => {
510
+ audit('572B', 'SHOULD use 200 status code on document parsing failure when accepting application/json', async () => {
511
511
  const res = await fetchFn(await getUrl(opts.url), {
512
512
  method: 'POST',
513
513
  headers: {
@@ -518,7 +518,7 @@ export function serverAudits(opts) {
518
518
  });
519
519
  ressert(res).status.toBe(200);
520
520
  }),
521
- audit('SHOULD use 200 status code on document validation failure when accepting application/json', async () => {
521
+ audit('FDE2', 'SHOULD use 200 status code on document validation failure when accepting application/json', async () => {
522
522
  const res = await fetchFn(await getUrl(opts.url), {
523
523
  method: 'POST',
524
524
  headers: {
@@ -534,7 +534,7 @@ export function serverAudits(opts) {
534
534
  // Response application/graphql-response+json
535
535
  audit(
536
536
  // TODO: convert to MUST after watershed
537
- 'SHOULD use 4xx or 5xx status codes on JSON parsing failure when accepting application/graphql-response+json', async () => {
537
+ '60AA', 'SHOULD use 4xx or 5xx status codes on JSON parsing failure when accepting application/graphql-response+json', async () => {
538
538
  const res = await fetchFn(await getUrl(opts.url), {
539
539
  method: 'POST',
540
540
  headers: {
@@ -545,7 +545,7 @@ export function serverAudits(opts) {
545
545
  });
546
546
  ressert(res).status.toBeBetween(400, 499);
547
547
  }),
548
- audit('SHOULD use 400 status code on JSON parsing failure when accepting application/graphql-response+json', async () => {
548
+ audit('2163', 'SHOULD use 400 status code on JSON parsing failure when accepting application/graphql-response+json', async () => {
549
549
  const res = await fetchFn(await getUrl(opts.url), {
550
550
  method: 'POST',
551
551
  headers: {
@@ -556,20 +556,9 @@ export function serverAudits(opts) {
556
556
  });
557
557
  ressert(res).status.toBe(400);
558
558
  }),
559
- audit('SHOULD not contain the data entry on JSON parsing failure when accepting application/graphql-response+json', async () => {
560
- const res = await fetchFn(await getUrl(opts.url), {
561
- method: 'POST',
562
- headers: {
563
- 'content-type': 'application/json',
564
- accept: 'application/graphql-response+json',
565
- },
566
- body: '{ "not a JSON',
567
- });
568
- await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
569
- }),
570
559
  audit(
571
560
  // TODO: convert to MUST after watershed
572
- 'SHOULD use 4xx or 5xx status codes if parameters are invalid when accepting application/graphql-response+json', async () => {
561
+ '3E36', 'SHOULD use 4xx or 5xx status codes if parameters are invalid when accepting application/graphql-response+json', async () => {
573
562
  const res = await fetchFn(await getUrl(opts.url), {
574
563
  method: 'POST',
575
564
  headers: {
@@ -582,7 +571,7 @@ export function serverAudits(opts) {
582
571
  });
583
572
  ressert(res).status.toBeBetween(400, 599);
584
573
  }),
585
- audit('SHOULD use 400 status code if parameters are invalid when accepting application/graphql-response+json', async () => {
574
+ audit('17C5', 'SHOULD use 400 status code if parameters are invalid when accepting application/graphql-response+json', async () => {
586
575
  const res = await fetchFn(await getUrl(opts.url), {
587
576
  method: 'POST',
588
577
  headers: {
@@ -595,7 +584,7 @@ export function serverAudits(opts) {
595
584
  });
596
585
  ressert(res).status.toBe(400);
597
586
  }),
598
- audit('SHOULD not contain the data entry if parameters are invalid when accepting application/graphql-response+json', async () => {
587
+ audit('34D6', 'SHOULD not contain the data entry if parameters are invalid when accepting application/graphql-response+json', async () => {
599
588
  const res = await fetchFn(await getUrl(opts.url), {
600
589
  method: 'POST',
601
590
  headers: {
@@ -610,7 +599,7 @@ export function serverAudits(opts) {
610
599
  }),
611
600
  audit(
612
601
  // TODO: convert to MUST after watershed
613
- 'SHOULD use 4xx or 5xx status codes on document parsing failure when accepting application/graphql-response+json', async () => {
602
+ '865D', 'SHOULD use 4xx or 5xx status codes on document parsing failure when accepting application/graphql-response+json', async () => {
614
603
  const res = await fetchFn(await getUrl(opts.url), {
615
604
  method: 'POST',
616
605
  headers: {
@@ -623,7 +612,7 @@ export function serverAudits(opts) {
623
612
  });
624
613
  ressert(res).status.toBeBetween(400, 599);
625
614
  }),
626
- audit('SHOULD use 400 status code on document parsing failure when accepting application/graphql-response+json', async () => {
615
+ audit('556A', 'SHOULD use 400 status code on document parsing failure when accepting application/graphql-response+json', async () => {
627
616
  const res = await fetchFn(await getUrl(opts.url), {
628
617
  method: 'POST',
629
618
  headers: {
@@ -636,7 +625,7 @@ export function serverAudits(opts) {
636
625
  });
637
626
  ressert(res).status.toBe(400);
638
627
  }),
639
- audit('SHOULD not contain the data entry on document parsing failure when accepting application/graphql-response+json', async () => {
628
+ audit('D586', 'SHOULD not contain the data entry on document parsing failure when accepting application/graphql-response+json', async () => {
640
629
  const res = await fetchFn(await getUrl(opts.url), {
641
630
  method: 'POST',
642
631
  headers: {
@@ -651,7 +640,7 @@ export function serverAudits(opts) {
651
640
  }),
652
641
  audit(
653
642
  // TODO: convert to MUST after watershed
654
- 'SHOULD use 4xx or 5xx status codes on document validation failure when accepting application/graphql-response+json', async () => {
643
+ '51FE', 'SHOULD use 4xx or 5xx status codes on document validation failure when accepting application/graphql-response+json', async () => {
655
644
  const res = await fetchFn(await getUrl(opts.url), {
656
645
  method: 'POST',
657
646
  headers: {
@@ -664,7 +653,7 @@ export function serverAudits(opts) {
664
653
  });
665
654
  ressert(res).status.toBeBetween(400, 599);
666
655
  }),
667
- audit('SHOULD use 400 status code on document validation failure when accepting application/graphql-response+json', async () => {
656
+ audit('74FF', 'SHOULD use 400 status code on document validation failure when accepting application/graphql-response+json', async () => {
668
657
  const res = await fetchFn(await getUrl(opts.url), {
669
658
  method: 'POST',
670
659
  headers: {
@@ -677,7 +666,7 @@ export function serverAudits(opts) {
677
666
  });
678
667
  ressert(res).status.toBe(400);
679
668
  }),
680
- audit('SHOULD not contain the data entry on document validation failure when accepting application/graphql-response+json', async () => {
669
+ audit('5E5B', 'SHOULD not contain the data entry on document validation failure when accepting application/graphql-response+json', async () => {
681
670
  const res = await fetchFn(await getUrl(opts.url), {
682
671
  method: 'POST',
683
672
  headers: {
@@ -691,10 +680,10 @@ export function serverAudits(opts) {
691
680
  await ressert(res).bodyAsExecutionResult.data.toBe(undefined);
692
681
  }),
693
682
  // TODO: how to fail and have the data entry?
694
- // audit('MUST use 2xx status code if response contains the data entry and it is not null when accepting application/graphql-response+json'),
683
+ // audit('EE52', 'MUST use 2xx status code if response contains the data entry and it is not null when accepting application/graphql-response+json'),
695
684
  // TODO: how to make an unauthorized request?
696
685
  // https://graphql.github.io/graphql-over-http/draft/#sel-EANNNDTAAEVBAAqqc
697
- // audit('SHOULD use 401 or 403 status codes when the request is not permitted')
686
+ // audit('BC58', 'SHOULD use 401 or 403 status codes when the request is not permitted')
698
687
  ];
699
688
  }
700
689
  /**
@@ -11,7 +11,7 @@ export * from '../utils';
11
11
  *
12
12
  * @private
13
13
  */
14
- export declare function audit(name: AuditName, fn: () => Promise<void>): Audit;
14
+ export declare function audit(id: string, name: AuditName, fn: () => Promise<void>): Audit;
15
15
  /**
16
16
  * Error thrown when an assertion test fails.
17
17
  *
@@ -11,7 +11,7 @@ export * from '../utils';
11
11
  *
12
12
  * @private
13
13
  */
14
- export declare function audit(name: AuditName, fn: () => Promise<void>): Audit;
14
+ export declare function audit(id: string, name: AuditName, fn: () => Promise<void>): Audit;
15
15
  /**
16
16
  * Error thrown when an assertion test fails.
17
17
  *
@@ -26,13 +26,15 @@ __exportStar(require("../utils"), exports);
26
26
  *
27
27
  * @private
28
28
  */
29
- function audit(name, fn) {
29
+ function audit(id, name, fn) {
30
30
  return {
31
+ id,
31
32
  name,
32
33
  fn: async () => {
33
34
  try {
34
35
  await fn();
35
36
  return {
37
+ id,
36
38
  name,
37
39
  status: 'ok',
38
40
  };
@@ -43,6 +45,7 @@ function audit(name, fn) {
43
45
  throw err;
44
46
  }
45
47
  return {
48
+ id,
46
49
  name,
47
50
  status: name.startsWith('MUST')
48
51
  ? // only failing MUSTs are considered errors
@@ -9,13 +9,15 @@ export * from '../utils.mjs';
9
9
  *
10
10
  * @private
11
11
  */
12
- export function audit(name, fn) {
12
+ export function audit(id, name, fn) {
13
13
  return {
14
+ id,
14
15
  name,
15
16
  fn: async () => {
16
17
  try {
17
18
  await fn();
18
19
  return {
20
+ id,
19
21
  name,
20
22
  status: 'ok',
21
23
  };
@@ -26,6 +28,7 @@ export function audit(name, fn) {
26
28
  throw err;
27
29
  }
28
30
  return {
31
+ id,
29
32
  name,
30
33
  status: name.startsWith('MUST')
31
34
  ? // only failing MUSTs are considered errors
package/lib/handler.d.mts CHANGED
@@ -3,7 +3,7 @@
3
3
  * handler
4
4
  *
5
5
  */
6
- import { ExecutionArgs, ExecutionResult, GraphQLSchema, validate as graphqlValidate, execute as graphqlExecute, parse as graphqlParse, getOperationAST as graphqlGetOperationAST, GraphQLError } from 'graphql';
6
+ import { ExecutionArgs, ExecutionResult, GraphQLSchema, validate as graphqlValidate, ValidationRule, execute as graphqlExecute, parse as graphqlParse, getOperationAST as graphqlGetOperationAST, GraphQLError } from 'graphql';
7
7
  import { RequestParams } from './common';
8
8
  /**
9
9
  * The incoming request headers the implementing server should provide.
@@ -137,6 +137,19 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
137
137
  * Will not be used when implementing a custom `onSubscribe`.
138
138
  */
139
139
  validate?: typeof graphqlValidate;
140
+ /**
141
+ * The validation rules for running GraphQL validate.
142
+ *
143
+ * When providing an array, the rules will be APPENDED to the default
144
+ * `specifiedRules` array provided by the graphql-js module.
145
+ *
146
+ * Alternatively, providing a function instead will OVERWRITE the defaults
147
+ * and use exclusively the rules returned by the function. The third (last)
148
+ * argument of the function are the default `specifiedRules` array provided
149
+ * by the graphql-js module, you're free to prepend/append the defaults to
150
+ * your rule set, or omit them altogether.
151
+ */
152
+ validationRules?: readonly ValidationRule[] | ((req: Request<RequestRaw, RequestContext>, args: OperationArgs<Context>, specifiedRules: readonly ValidationRule[]) => Promise<readonly ValidationRule[]> | readonly ValidationRule[]);
140
153
  /**
141
154
  * Is the `execute` function from GraphQL which is
142
155
  * used to execute the query and mutation operations.
package/lib/handler.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  * handler
4
4
  *
5
5
  */
6
- import { ExecutionArgs, ExecutionResult, GraphQLSchema, validate as graphqlValidate, execute as graphqlExecute, parse as graphqlParse, getOperationAST as graphqlGetOperationAST, GraphQLError } from 'graphql';
6
+ import { ExecutionArgs, ExecutionResult, GraphQLSchema, validate as graphqlValidate, ValidationRule, execute as graphqlExecute, parse as graphqlParse, getOperationAST as graphqlGetOperationAST, GraphQLError } from 'graphql';
7
7
  import { RequestParams } from './common';
8
8
  /**
9
9
  * The incoming request headers the implementing server should provide.
@@ -137,6 +137,19 @@ export interface HandlerOptions<RequestRaw = unknown, RequestContext = unknown,
137
137
  * Will not be used when implementing a custom `onSubscribe`.
138
138
  */
139
139
  validate?: typeof graphqlValidate;
140
+ /**
141
+ * The validation rules for running GraphQL validate.
142
+ *
143
+ * When providing an array, the rules will be APPENDED to the default
144
+ * `specifiedRules` array provided by the graphql-js module.
145
+ *
146
+ * Alternatively, providing a function instead will OVERWRITE the defaults
147
+ * and use exclusively the rules returned by the function. The third (last)
148
+ * argument of the function are the default `specifiedRules` array provided
149
+ * by the graphql-js module, you're free to prepend/append the defaults to
150
+ * your rule set, or omit them altogether.
151
+ */
152
+ validationRules?: readonly ValidationRule[] | ((req: Request<RequestRaw, RequestContext>, args: OperationArgs<Context>, specifiedRules: readonly ValidationRule[]) => Promise<readonly ValidationRule[]> | readonly ValidationRule[]);
140
153
  /**
141
154
  * Is the `execute` function from GraphQL which is
142
155
  * used to execute the query and mutation operations.
package/lib/handler.js CHANGED
@@ -76,7 +76,7 @@ exports.isResponse = isResponse;
76
76
  * @category Server
77
77
  */
78
78
  function createHandler(options) {
79
- const { schema, context, validate = graphql_1.validate, execute = graphql_1.execute, parse = graphql_1.parse, getOperationAST = graphql_1.getOperationAST, rootValue, onSubscribe, onOperation, } = options;
79
+ const { schema, context, validate = graphql_1.validate, validationRules = [], execute = graphql_1.execute, parse = graphql_1.parse, getOperationAST = graphql_1.getOperationAST, rootValue, onSubscribe, onOperation, } = options;
80
80
  return async function handler(req) {
81
81
  var _a, _b;
82
82
  const method = req.method;
@@ -226,7 +226,14 @@ function createHandler(options) {
226
226
  else {
227
227
  args = Object.assign(Object.assign({}, argsWithoutSchema), { schema });
228
228
  }
229
- const validationErrs = validate(args.schema, args.document);
229
+ let rules = graphql_1.specifiedRules;
230
+ if (typeof validationRules === 'function') {
231
+ rules = await validationRules(req, args, graphql_1.specifiedRules);
232
+ }
233
+ else {
234
+ rules = [...rules, ...validationRules];
235
+ }
236
+ const validationErrs = validate(args.schema, args.document, rules);
230
237
  if (validationErrs.length) {
231
238
  return makeResponse(validationErrs, acceptedMediaType);
232
239
  }