@depup/express-graphql 0.12.0-depup.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/LICENSE +21 -0
- package/README.md +34 -0
- package/changes.json +22 -0
- package/index.d.ts +146 -0
- package/index.js +285 -0
- package/package.json +76 -0
- package/parseBody.d.ts +13 -0
- package/parseBody.js +110 -0
- package/renderGraphiQL.d.ts +30 -0
- package/renderGraphiQL.js +171 -0
- package/ts3.4/index.d.ts +146 -0
- package/ts3.4/parseBody.d.ts +13 -0
- package/ts3.4/renderGraphiQL.d.ts +30 -0
package/parseBody.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseBody = void 0;
|
|
7
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
8
|
+
const querystring_1 = __importDefault(require("querystring"));
|
|
9
|
+
const raw_body_1 = __importDefault(require("raw-body"));
|
|
10
|
+
const http_errors_1 = __importDefault(require("http-errors"));
|
|
11
|
+
const content_type_1 = __importDefault(require("content-type"));
|
|
12
|
+
/**
|
|
13
|
+
* Provided a "Request" provided by express or connect (typically a node style
|
|
14
|
+
* HTTPClientRequest), Promise the body data contained.
|
|
15
|
+
*/
|
|
16
|
+
async function parseBody(req) {
|
|
17
|
+
const { body } = req;
|
|
18
|
+
// If express has already parsed a body as a keyed object, use it.
|
|
19
|
+
if (typeof body === 'object' && !(body instanceof Buffer)) {
|
|
20
|
+
return body;
|
|
21
|
+
}
|
|
22
|
+
// Skip requests without content types.
|
|
23
|
+
if (req.headers['content-type'] === undefined) {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
const typeInfo = content_type_1.default.parse(req);
|
|
27
|
+
// If express has already parsed a body as a string, and the content-type
|
|
28
|
+
// was application/graphql, parse the string body.
|
|
29
|
+
if (typeof body === 'string' && typeInfo.type === 'application/graphql') {
|
|
30
|
+
return { query: body };
|
|
31
|
+
}
|
|
32
|
+
// Already parsed body we didn't recognise? Parse nothing.
|
|
33
|
+
if (body != null) {
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
const rawBody = await readBody(req, typeInfo);
|
|
37
|
+
// Use the correct body parser based on Content-Type header.
|
|
38
|
+
switch (typeInfo.type) {
|
|
39
|
+
case 'application/graphql':
|
|
40
|
+
return { query: rawBody };
|
|
41
|
+
case 'application/json':
|
|
42
|
+
if (jsonObjRegex.test(rawBody)) {
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(rawBody);
|
|
45
|
+
}
|
|
46
|
+
catch (_a) {
|
|
47
|
+
// Do nothing
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw http_errors_1.default(400, 'POST body sent invalid JSON.');
|
|
51
|
+
case 'application/x-www-form-urlencoded':
|
|
52
|
+
return querystring_1.default.parse(rawBody);
|
|
53
|
+
}
|
|
54
|
+
// If no Content-Type header matches, parse nothing.
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
57
|
+
exports.parseBody = parseBody;
|
|
58
|
+
/**
|
|
59
|
+
* RegExp to match an Object-opening brace "{" as the first non-space
|
|
60
|
+
* in a string. Allowed whitespace is defined in RFC 7159:
|
|
61
|
+
*
|
|
62
|
+
* ' ' Space
|
|
63
|
+
* '\t' Horizontal tab
|
|
64
|
+
* '\n' Line feed or New line
|
|
65
|
+
* '\r' Carriage return
|
|
66
|
+
*/
|
|
67
|
+
const jsonObjRegex = /^[ \t\n\r]*\{/;
|
|
68
|
+
// Read and parse a request body.
|
|
69
|
+
async function readBody(req, typeInfo) {
|
|
70
|
+
var _a, _b;
|
|
71
|
+
const charset = (_b = (_a = typeInfo.parameters.charset) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'utf-8';
|
|
72
|
+
// Assert charset encoding per JSON RFC 7159 sec 8.1
|
|
73
|
+
if (!charset.startsWith('utf-')) {
|
|
74
|
+
throw http_errors_1.default(415, `Unsupported charset "${charset.toUpperCase()}".`);
|
|
75
|
+
}
|
|
76
|
+
// Get content-encoding (e.g. gzip)
|
|
77
|
+
const contentEncoding = req.headers['content-encoding'];
|
|
78
|
+
const encoding = typeof contentEncoding === 'string'
|
|
79
|
+
? contentEncoding.toLowerCase()
|
|
80
|
+
: 'identity';
|
|
81
|
+
const length = encoding === 'identity' ? req.headers['content-length'] : null;
|
|
82
|
+
const limit = 100 * 1024; // 100kb
|
|
83
|
+
const stream = decompressed(req, encoding);
|
|
84
|
+
// Read body from stream.
|
|
85
|
+
try {
|
|
86
|
+
return await raw_body_1.default(stream, { encoding: charset, length, limit });
|
|
87
|
+
}
|
|
88
|
+
catch (rawError) {
|
|
89
|
+
const error = http_errors_1.default(400,
|
|
90
|
+
/* istanbul ignore next: Thrown by underlying library. */
|
|
91
|
+
rawError instanceof Error ? rawError : String(rawError));
|
|
92
|
+
error.message =
|
|
93
|
+
error.type === 'encoding.unsupported'
|
|
94
|
+
? `Unsupported charset "${charset.toUpperCase()}".`
|
|
95
|
+
: `Invalid body: ${error.message}.`;
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Return a decompressed stream, given an encoding.
|
|
100
|
+
function decompressed(req, encoding) {
|
|
101
|
+
switch (encoding) {
|
|
102
|
+
case 'identity':
|
|
103
|
+
return req;
|
|
104
|
+
case 'deflate':
|
|
105
|
+
return req.pipe(zlib_1.default.createInflate());
|
|
106
|
+
case 'gzip':
|
|
107
|
+
return req.pipe(zlib_1.default.createGunzip());
|
|
108
|
+
}
|
|
109
|
+
throw http_errors_1.default(415, `Unsupported content-encoding "${encoding}".`);
|
|
110
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { FormattedExecutionResult } from 'graphql';
|
|
2
|
+
export interface GraphiQLData {
|
|
3
|
+
query?: string | null;
|
|
4
|
+
variables?: {
|
|
5
|
+
readonly [name: string]: unknown;
|
|
6
|
+
} | null;
|
|
7
|
+
operationName?: string | null;
|
|
8
|
+
result?: FormattedExecutionResult;
|
|
9
|
+
}
|
|
10
|
+
export interface GraphiQLOptions {
|
|
11
|
+
/**
|
|
12
|
+
* An optional GraphQL string to use when no query is provided and no stored
|
|
13
|
+
* query exists from a previous session. If undefined is provided, GraphiQL
|
|
14
|
+
* will use its own default query.
|
|
15
|
+
*/
|
|
16
|
+
defaultQuery?: string;
|
|
17
|
+
/**
|
|
18
|
+
* An optional boolean which enables the header editor when true.
|
|
19
|
+
* Defaults to false.
|
|
20
|
+
*/
|
|
21
|
+
headerEditorEnabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* When express-graphql receives a request which does not Accept JSON, but does
|
|
25
|
+
* Accept HTML, it may present GraphiQL, the in-browser GraphQL explorer IDE.
|
|
26
|
+
*
|
|
27
|
+
* When shown, it will be pre-populated with the result of having executed the
|
|
28
|
+
* requested query.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderGraphiQL(data: GraphiQLData, options?: GraphiQLOptions): string;
|