!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlHttpAudits={})}(this,(function(e){"use strict";function t(e){return null===e?"null":Array.isArray(e)?"array":typeof e}function a(e,t,a){return{id:e,name:t,fn:async()=>{try{return await a(),{id:e,name:t,status:"ok"}}catch(a){if(!(a instanceof n))throw a;return{id:e,name:t,status:t.startsWith("MUST")?"error":t.startsWith("SHOULD")?"warn":"notice",reason:a.reason,response:a.response}}}}}class n{constructor(e,t){this.response=e,this.reason=t}}function o(e){return{status:{toBe(t){if(e.status!==t)throw new n(e,`Response status code is not ${t}`)},toBeBetween:(t,a)=>{if(!(t<=e.status&&e.status<=a))throw new n(e,`Response status is not between ${t} and ${a}`)}},header:t=>({toContain(a){var o;if(!(null===(o=e.headers.get(t))||void 0===o?void 0:o.includes(a)))throw new n(e,`Response header ${t} does not contain ${a}`)},notToContain(a){var o;if(null===(o=e.headers.get(t))||void 0===o?void 0:o.includes(a))throw new n(e,`Response header ${t} contains ${a}`)}}),bodyAsExecutionResult:{data:{async toBe(t){const a=e.clone();if((await s(e)).data!==t)throw new n(a,`Response body execution result data is not "${t}"`)}},async toHaveProperty(t){const a=e.clone();if(!(t in await s(e)))throw new n(a,`Response body execution result does not have a property "${t}"`)},async notToHaveProperty(t){const a=e.clone();if(t in await s(e))throw new n(a,`Response body execution result has a property "${t}"`)}}}}async function s(e){let t,a;try{const a=new TextDecoder("utf-8"),n=await e.arrayBuffer();t=a.decode(n)}catch(t){throw new n(e,"Response body is not UTF-8 encoded")}try{a=JSON.parse(t)}catch(t){throw new n(e,"Response body is not valid JSON")}return a}function i(e){const s=e.fetchFn||fetch;return[a("22EB","SHOULD accept application/graphql-response+json and match the content-type",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200),o(t).header("content-type").toContain("application/graphql-response+json")})),a("4655","MUST accept application/json and match the content-type",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200),o(t).header("content-type").toContain("application/json")})),a("47DE","SHOULD accept */* and use application/json for the content-type",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"*/*"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200),o(t).header("content-type").toContain("application/json")})),a("80D8","SHOULD assume application/json content-type when accept is missing",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200),o(t).header("content-type").toContain("application/json")})),a("82A3","MUST use utf-8 encoding when responding",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200);try{new TextDecoder("utf-8").decode(await t.arrayBuffer())}catch(e){throw new n(t,"Response body is not UTF-8 encoded")}})),a("BF61","MUST accept utf-8 encoded request",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json; charset=utf-8"},body:JSON.stringify({query:'{ __type(name: "Run🏃Swim🏊") { name } }'})})).status.toBe(200)})),a("78D5","MUST assume utf-8 in request if encoding is unspecified",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"})})).status.toBe(200)})),a("2C94","MUST accept POST requests",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"})})).status.toBe(200)})),a("5A70","MAY accept application/x-www-form-urlencoded formatted GET requests",(async()=>{const t=new URL(await r(e.url));t.searchParams.set("query","{ __typename }");o(await s(t.toString())).status.toBe(200)})),a("9C48","MAY NOT allow executing mutations on GET requests",(async()=>{const t=new URL(await r(e.url));t.searchParams.set("query","mutation { __typename }");o(await s(t.toString(),{headers:{accept:"application/graphql-response+json"}})).status.toBeBetween(400,499)})),a("9ABE","MAY respond with 4xx status code if content-type is not supplied on POST requests",(async()=>{o(await s(await r(e.url),{method:"POST"})).status.toBeBetween(400,499)})),a("03D4","MUST accept application/json POST requests",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }"})})).status.toBe(200)})),a("A5BF","MAY use 400 status code when request body is missing on POST",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"}})).status.toBe(400)})),a("423L","MAY use 400 status code on missing {query} parameter",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({notquery:"{ __typename }"})})).status.toBe(400)})),...[{obj:"ect"},0,!1,["array"]].map(((n,i)=>a(`LKJ${i}`,`MAY use 400 status code on ${t(n)} {query} parameter`,(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:n})})).status.toBe(400)})))),a("34A2","SHOULD allow string {query} parameter when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ __typename }"})})).status.toBe(200)})),a("13EE","MUST allow string {query} parameter when accepting application/json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{ __typename }"})});o(t).status.toBe(200),await o(t).bodyAsExecutionResult.notToHaveProperty("errors")})),...[{obj:"ect"},0,!1,["array"]].map(((n,i)=>a(`6C0${i}`,`MAY use 400 status code on ${t(n)} {operationName} parameter`,(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({operationName:n,query:"{ __typename }"})})).status.toBe(400)})))),a("8161","SHOULD allow string {operationName} parameter when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({operationName:"Query",query:"query Query { __typename }"})})).status.toBe(200)})),a("B8B3","MUST allow string {operationName} parameter when accepting application/json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({operationName:"Query",query:"query Query { __typename }"})});o(t).status.toBe(200),await o(t).bodyAsExecutionResult.notToHaveProperty("errors")})),...["variables","operationName","extensions"].flatMap(((t,n)=>[a(`94B${n}`,`SHOULD allow null {${t}} parameter when accepting application/graphql-response+json`,(async()=>{const a=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ __typename }",[t]:null})});o(a).status.toBe(200),await o(a).bodyAsExecutionResult.notToHaveProperty("errors")})),a(`022${n}`,`MUST allow null {${t}} parameter when accepting application/json`,(async()=>{const a=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{ __typename }",[t]:null})});o(a).status.toBe(200),await o(a).bodyAsExecutionResult.notToHaveProperty("errors")}))])),...["string",0,!1,["array"]].map(((n,i)=>a(`476${i}`,`MAY use 400 status code on ${t(n)} {variables} parameter`,(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }",variables:n})})).status.toBe(400)})))),a("2EA1","SHOULD allow map {variables} parameter when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"query Type($name: String!) { __type(name: $name) { name } }",variables:{name:"sometype"}})})).status.toBe(200)})),a("28B9","MUST allow map {variables} parameter when accepting application/json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"query Type($name: String!) { __type(name: $name) { name } }",variables:{name:"sometype"}})});o(t).status.toBe(200),await o(t).bodyAsExecutionResult.notToHaveProperty("errors")})),a("D6D5","MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/graphql-response+json",(async()=>{const t=new URL(await r(e.url));t.searchParams.set("query","query Type($name: String!) { __type(name: $name) { name } }"),t.searchParams.set("variables",JSON.stringify({name:"sometype"}));o(await s(t.toString(),{method:"GET",headers:{accept:"application/graphql-response+json"}})).status.toBe(200)})),a("6A70","MAY allow URL-encoded JSON string {variables} parameter in GETs when accepting application/json",(async()=>{const t=new URL(await r(e.url));t.searchParams.set("query","query Type($name: String!) { __type(name: $name) { name } }"),t.searchParams.set("variables",JSON.stringify({name:"sometype"}));const a=await s(t.toString(),{method:"GET",headers:{accept:"application/json"}});o(a).status.toBe(200),await o(a).bodyAsExecutionResult.notToHaveProperty("errors")})),...["string",0,!1,["array"]].map(((n,i)=>a(`58B${i}`,`MAY use 400 status code on ${t(n)} {extensions} parameter`,(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({query:"{ __typename }",extensions:n})})).status.toBe(400)})))),a("428F","SHOULD allow map {extensions} parameter when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ __typename }",extensions:{some:"value"}})})).status.toBe(200)})),a("1B7A","MUST allow map {extensions} parameter when accepting application/json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{ __typename }",extensions:{some:"value"}})});o(t).status.toBe(200),await o(t).bodyAsExecutionResult.notToHaveProperty("errors")})),a("B6DC","MAY use 4xx or 5xx status codes on JSON parsing failure",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:'{ "not a JSON'})).status.toBeBetween(400,499)})),a("BCF8","MAY use 400 status code on JSON parsing failure",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:'{ "not a JSON'})).status.toBe(400)})),a("8764","MAY use 4xx or 5xx status codes if parameters are invalid",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({qeury:"{ __typename }"})})).status.toBeBetween(400,599)})),a("3E3A","MAY use 400 status code if parameters are invalid",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({qeury:"{ __typename }"})})).status.toBe(400)})),a("572B","SHOULD use 200 status code on document parsing failure when accepting application/json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{"})})).status.toBe(200)})),a("FDE2","SHOULD use 200 status code on document validation failure when accepting application/json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"{ 8f31403dfe404bccbb0e835f2629c6a7 }"})})).status.toBe(200)})),a("7B9B","SHOULD use a status code of 200 on variable coercion failure when accepting application/json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/json"},body:JSON.stringify({query:"query CoerceFailure($id: ID!){ __typename }",variables:{id:null}})})).status.toBe(200)})),a("865D","SHOULD use 4xx or 5xx status codes on document parsing failure when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{"})})).status.toBeBetween(400,599)})),a("556A","SHOULD use 400 status code on document parsing failure when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{"})})).status.toBe(400)})),a("D586","SHOULD not contain the data entry on document parsing failure when accepting application/graphql-response+json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{"})});await o(t).bodyAsExecutionResult.data.toBe(void 0)})),a("51FE","SHOULD use 4xx or 5xx status codes on document validation failure when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ 8f31403dfe404bccbb0e835f2629c6a7 }"})})).status.toBeBetween(400,599)})),a("74FF","SHOULD use 400 status code on document validation failure when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ 8f31403dfe404bccbb0e835f2629c6a7 }"})})).status.toBe(400)})),a("5E5B","SHOULD not contain the data entry on document validation failure when accepting application/graphql-response+json",(async()=>{const t=await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"{ 8f31403dfe404bccbb0e835f2629c6a7 }"})});await o(t).bodyAsExecutionResult.data.toBe(void 0)})),a("86EE","SHOULD use a status code of 400 on variable coercion failure when accepting application/graphql-response+json",(async()=>{o(await s(await r(e.url),{method:"POST",headers:{"content-type":"application/json",accept:"application/graphql-response+json"},body:JSON.stringify({query:"query CoerceFailure($id: ID!){ __typename }",variables:{id:null}})})).status.toBe(400)}))]}async function r(e){return"function"==typeof e?await e():e}async function p(e){var t;let a="";a+=`
  • ${e.id} ${e.name}\n`,a+="
    \n",a+=`${function(e,t=1024){if(e.length>t)return e.substring(0,t)+"...";return e}(e.reason)}\n`,a+='
    ';const n=e.response,o={};for(const[e,t]of n.headers.entries())"date"===e?o[e]="":["cf-ray","server-timing","set-cookie"].includes(e)?o[e]="":o[e]=t;let s,i="";try{i=await n.text(),s=JSON.parse(i)}catch(e){(null===(t=n.headers.get("content-type"))||void 0===t?void 0:t.includes("text/html"))&&(i="")}return a+=JSON.stringify({status:n.status,statusText:n.statusText,headers:o,body:s||((null==i?void 0:i.length)>5120?"":i)||null},((e,t)=>{if(null!=t&&"object"==typeof t&&!Array.isArray(t)){const e={};return Object.keys(t).sort().reverse().reduce(((e,a)=>(e[a]=t[a],e)),e)}return t}),2)+"\n",a+="
    \n",a+="
    \n",a+="
  • \n",a}e.auditServer=async function(e){const t=i(e);return await Promise.all(t.map((({fn:e})=>e())))},e.renderAuditResultsToHTML=async function(e){const t={total:0,ok:[],notice:[],warn:[],error:[]};for(const a of e)t.total++,a.status,t[a.status].push(a);let a="* This report was auto-generated by graphql-http\n";if(a+="\n",a+="

    GraphQL over HTTP audit report

    \n",a+="\n",a+="\n",a+="\n",t.ok.length){a+="

    Passing

    \n",a+="
      \n";for(const[,e]of t.ok.entries())a+=`
    1. ${e.id} ${e.name}
    2. \n`;a+="
    \n",a+="\n"}if(t.notice.length){a+="

    Notices

    \n",a+="The server MAY support these, but are truly optional. These are suggestions following recommended conventions.\n",a+="
      \n";for(const[,e]of t.notice.entries())a+=await p(e);a+="
    \n",a+="\n"}if(t.warn.length){a+="

    Warnings

    \n",a+="The server SHOULD support these, but is not required.\n",a+="
      \n";for(const[,e]of t.warn.entries())a+=await p(e);a+="
    \n",a+="\n"}if(t.error.length){a+="

    Errors

    \n",a+="The server MUST support these.\n",a+="
      \n";for(const[,e]of t.error.entries())a+=await p(e);a+="
    \n"}return a},e.serverAudits=i}));