@traffic-twin/sdk 0.0.0-stage → 0.1.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 +202 -0
- package/README.md +171 -2
- package/dist/cjs/agent.d.ts +143 -0
- package/dist/cjs/agent.js +927 -0
- package/dist/cjs/capture/body.d.ts +11 -0
- package/dist/cjs/capture/body.js +73 -0
- package/dist/cjs/capture/common.d.ts +75 -0
- package/dist/cjs/capture/common.js +180 -0
- package/dist/cjs/capture/context.d.ts +28 -0
- package/dist/cjs/capture/context.js +92 -0
- package/dist/cjs/capture/inbound.d.ts +12 -0
- package/dist/cjs/capture/inbound.js +195 -0
- package/dist/cjs/capture/outbound-http.d.ts +4 -0
- package/dist/cjs/capture/outbound-http.js +200 -0
- package/dist/cjs/capture/outbound-undici.d.ts +2 -0
- package/dist/cjs/capture/outbound-undici.js +242 -0
- package/dist/cjs/capture/wire.d.ts +27 -0
- package/dist/cjs/capture/wire.js +68 -0
- package/dist/cjs/export/event.d.ts +46 -0
- package/dist/cjs/export/event.js +91 -0
- package/dist/cjs/export/exporter.d.ts +50 -0
- package/dist/cjs/export/exporter.js +192 -0
- package/dist/cjs/export/pipeline.d.ts +20 -0
- package/dist/cjs/export/pipeline.js +40 -0
- package/dist/cjs/fleet/asn1.d.ts +44 -0
- package/dist/cjs/fleet/asn1.js +150 -0
- package/dist/cjs/fleet/client.d.ts +84 -0
- package/dist/cjs/fleet/client.js +216 -0
- package/dist/cjs/fleet/http.d.ts +17 -0
- package/dist/cjs/fleet/http.js +80 -0
- package/dist/cjs/fleet/store.d.ts +18 -0
- package/dist/cjs/fleet/store.js +115 -0
- package/dist/cjs/index.d.ts +14 -0
- package/dist/cjs/index.js +69 -0
- package/dist/cjs/log.d.ts +4 -0
- package/dist/cjs/log.js +30 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/register.d.ts +1 -0
- package/dist/cjs/register.js +18 -0
- package/dist/cjs/sanitizer/bodies.d.ts +55 -0
- package/dist/cjs/sanitizer/bodies.js +710 -0
- package/dist/cjs/sanitizer/formats.d.ts +26 -0
- package/dist/cjs/sanitizer/formats.js +110 -0
- package/dist/cjs/sanitizer/graphql.d.ts +23 -0
- package/dist/cjs/sanitizer/graphql.js +478 -0
- package/dist/cjs/sanitizer/hostpat.d.ts +15 -0
- package/dist/cjs/sanitizer/hostpat.js +129 -0
- package/dist/cjs/sanitizer/json.d.ts +60 -0
- package/dist/cjs/sanitizer/json.js +460 -0
- package/dist/cjs/sanitizer/policy.d.ts +224 -0
- package/dist/cjs/sanitizer/policy.js +820 -0
- package/dist/cjs/sanitizer/sanitizer.d.ts +149 -0
- package/dist/cjs/sanitizer/sanitizer.js +1473 -0
- package/dist/cjs/sanitizer/utf8.d.ts +22 -0
- package/dist/cjs/sanitizer/utf8.js +180 -0
- package/dist/cjs/sanitizer/vectors.d.ts +22 -0
- package/dist/cjs/sanitizer/vectors.js +130 -0
- package/dist/cjs/version.d.ts +2 -0
- package/dist/cjs/version.js +5 -0
- package/dist/cjs/worker/dir.d.ts +1 -0
- package/dist/cjs/worker/dir.js +8 -0
- package/dist/cjs/worker/pool.d.ts +47 -0
- package/dist/cjs/worker/pool.js +179 -0
- package/dist/cjs/worker/protocol.d.ts +37 -0
- package/dist/cjs/worker/protocol.js +3 -0
- package/dist/cjs/worker/sanitizer-worker.d.ts +1 -0
- package/dist/cjs/worker/sanitizer-worker.js +53 -0
- package/dist/esm/agent.d.ts +143 -0
- package/dist/esm/agent.js +921 -0
- package/dist/esm/capture/body.d.ts +11 -0
- package/dist/esm/capture/body.js +69 -0
- package/dist/esm/capture/common.d.ts +75 -0
- package/dist/esm/capture/common.js +166 -0
- package/dist/esm/capture/context.d.ts +28 -0
- package/dist/esm/capture/context.js +84 -0
- package/dist/esm/capture/inbound.d.ts +12 -0
- package/dist/esm/capture/inbound.js +187 -0
- package/dist/esm/capture/outbound-http.d.ts +4 -0
- package/dist/esm/capture/outbound-http.js +193 -0
- package/dist/esm/capture/outbound-undici.d.ts +2 -0
- package/dist/esm/capture/outbound-undici.js +236 -0
- package/dist/esm/capture/wire.d.ts +27 -0
- package/dist/esm/capture/wire.js +65 -0
- package/dist/esm/export/event.d.ts +46 -0
- package/dist/esm/export/event.js +85 -0
- package/dist/esm/export/exporter.d.ts +50 -0
- package/dist/esm/export/exporter.js +188 -0
- package/dist/esm/export/pipeline.d.ts +20 -0
- package/dist/esm/export/pipeline.js +37 -0
- package/dist/esm/fleet/asn1.d.ts +44 -0
- package/dist/esm/fleet/asn1.js +128 -0
- package/dist/esm/fleet/client.d.ts +84 -0
- package/dist/esm/fleet/client.js +204 -0
- package/dist/esm/fleet/http.d.ts +17 -0
- package/dist/esm/fleet/http.js +73 -0
- package/dist/esm/fleet/store.d.ts +18 -0
- package/dist/esm/fleet/store.js +110 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.js +48 -0
- package/dist/esm/log.d.ts +4 -0
- package/dist/esm/log.js +25 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/register.d.ts +1 -0
- package/dist/esm/register.js +16 -0
- package/dist/esm/sanitizer/bodies.d.ts +55 -0
- package/dist/esm/sanitizer/bodies.js +694 -0
- package/dist/esm/sanitizer/formats.d.ts +26 -0
- package/dist/esm/sanitizer/formats.js +101 -0
- package/dist/esm/sanitizer/graphql.d.ts +23 -0
- package/dist/esm/sanitizer/graphql.js +472 -0
- package/dist/esm/sanitizer/hostpat.d.ts +15 -0
- package/dist/esm/sanitizer/hostpat.js +122 -0
- package/dist/esm/sanitizer/json.d.ts +60 -0
- package/dist/esm/sanitizer/json.js +447 -0
- package/dist/esm/sanitizer/policy.d.ts +224 -0
- package/dist/esm/sanitizer/policy.js +800 -0
- package/dist/esm/sanitizer/sanitizer.d.ts +149 -0
- package/dist/esm/sanitizer/sanitizer.js +1459 -0
- package/dist/esm/sanitizer/utf8.d.ts +22 -0
- package/dist/esm/sanitizer/utf8.js +166 -0
- package/dist/esm/sanitizer/vectors.d.ts +22 -0
- package/dist/esm/sanitizer/vectors.js +125 -0
- package/dist/esm/version.d.ts +2 -0
- package/dist/esm/version.js +2 -0
- package/dist/esm/worker/dir.d.ts +1 -0
- package/dist/esm/worker/dir.js +5 -0
- package/dist/esm/worker/pool.d.ts +47 -0
- package/dist/esm/worker/pool.js +175 -0
- package/dist/esm/worker/protocol.d.ts +37 -0
- package/dist/esm/worker/protocol.js +2 -0
- package/dist/esm/worker/sanitizer-worker.d.ts +1 -0
- package/dist/esm/worker/sanitizer-worker.js +51 -0
- package/package.json +75 -4
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare function lenClass(n: number): string;
|
|
2
|
+
export declare const RE_UUID: RegExp;
|
|
3
|
+
export declare const RE_JWT: RegExp;
|
|
4
|
+
export declare const RE_EMAIL: RegExp;
|
|
5
|
+
export declare const RE_DATETIME: RegExp;
|
|
6
|
+
export declare const RE_DATE: RegExp;
|
|
7
|
+
export declare const RE_URL: RegExp;
|
|
8
|
+
export declare const RE_IPV4: RegExp;
|
|
9
|
+
export declare const RE_PHONE: RegExp;
|
|
10
|
+
export declare const RE_DIGITS: RegExp;
|
|
11
|
+
export declare const RE_HEX: RegExp;
|
|
12
|
+
export declare function isPrintableAscii(s: string): boolean;
|
|
13
|
+
/** First matching format of 6.3, or null. Only printable ASCII strings are considered. */
|
|
14
|
+
export declare function detectFormat(s: string): string | null;
|
|
15
|
+
/** drop form of a well-formed string. */
|
|
16
|
+
export declare function strShape(s: string): string;
|
|
17
|
+
/** 9.3.3: a JSON key, query, cookie or form name leaves as a literal only if this holds. */
|
|
18
|
+
export declare function isLiteralName(s: string): boolean;
|
|
19
|
+
/** 8.0.2: output name of a lowercased header name. */
|
|
20
|
+
export declare function headerOutName(lower: string): string;
|
|
21
|
+
export declare const PATH_TOKEN_RE: RegExp;
|
|
22
|
+
/** Code shape of the code action (sanitizer.md 5.6, spec v1.11): ASCII letters, `_`, `-`, 2 to 32 bytes. */
|
|
23
|
+
export declare const CODE_RE: RegExp;
|
|
24
|
+
/** Shape `alnum` of the code action (sanitizer.md 5.6, spec v1.19): letters, digits, `_`, `-`, `.`, 1 to 16 bytes. */
|
|
25
|
+
export declare const CODE_ALNUM_RE: RegExp;
|
|
26
|
+
export declare const AUTO_WORD_RE: RegExp;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Shapes (6.2), recognized formats (6.3), length classes (0.3) and the name rule (9.3.3).
|
|
3
|
+
//
|
|
4
|
+
// All regular expressions are whole-string, ASCII-only matches (0.1). JavaScript `$`
|
|
5
|
+
// without the `m` flag only matches at the end of the input, so "x\n" never matches.
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.AUTO_WORD_RE = exports.CODE_ALNUM_RE = exports.CODE_RE = exports.PATH_TOKEN_RE = exports.RE_HEX = exports.RE_DIGITS = exports.RE_PHONE = exports.RE_IPV4 = exports.RE_URL = exports.RE_DATE = exports.RE_DATETIME = exports.RE_EMAIL = exports.RE_JWT = exports.RE_UUID = void 0;
|
|
8
|
+
exports.lenClass = lenClass;
|
|
9
|
+
exports.isPrintableAscii = isPrintableAscii;
|
|
10
|
+
exports.detectFormat = detectFormat;
|
|
11
|
+
exports.strShape = strShape;
|
|
12
|
+
exports.isLiteralName = isLiteralName;
|
|
13
|
+
exports.headerOutName = headerOutName;
|
|
14
|
+
const utf8_js_1 = require("./utf8.js");
|
|
15
|
+
function lenClass(n) {
|
|
16
|
+
if (n <= 8)
|
|
17
|
+
return 'l8';
|
|
18
|
+
if (n <= 32)
|
|
19
|
+
return 'l32';
|
|
20
|
+
if (n <= 128)
|
|
21
|
+
return 'l128';
|
|
22
|
+
if (n <= 1024)
|
|
23
|
+
return 'l1024';
|
|
24
|
+
return 'lmax';
|
|
25
|
+
}
|
|
26
|
+
const PRINTABLE = /^[\x20-\x7e]*$/;
|
|
27
|
+
exports.RE_UUID = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/;
|
|
28
|
+
exports.RE_JWT = /^eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/;
|
|
29
|
+
exports.RE_EMAIL = /^[A-Za-z0-9._%+-]{1,64}@[A-Za-z0-9-]{1,63}(\.[A-Za-z0-9-]{1,63})+$/;
|
|
30
|
+
exports.RE_DATETIME = /^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt ][0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]{1,9})?([Zz]|[+-][0-9]{2}:[0-9]{2})$/;
|
|
31
|
+
exports.RE_DATE = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
|
|
32
|
+
exports.RE_URL = /^[A-Za-z][A-Za-z0-9+.-]{0,15}:\/\/[!-~]+$/;
|
|
33
|
+
exports.RE_IPV4 = /^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])){3}$/;
|
|
34
|
+
exports.RE_PHONE = /^\+[1-9][0-9]{6,14}$/;
|
|
35
|
+
exports.RE_DIGITS = /^-?[0-9]{1,19}$/;
|
|
36
|
+
exports.RE_HEX = /^[0-9A-Fa-f]{16,}$/;
|
|
37
|
+
const FORMATS = [
|
|
38
|
+
['uuid', exports.RE_UUID],
|
|
39
|
+
['jwt', exports.RE_JWT],
|
|
40
|
+
['email', exports.RE_EMAIL],
|
|
41
|
+
['datetime', exports.RE_DATETIME],
|
|
42
|
+
['date', exports.RE_DATE],
|
|
43
|
+
['url', exports.RE_URL],
|
|
44
|
+
['ipv4', exports.RE_IPV4],
|
|
45
|
+
['phone', exports.RE_PHONE],
|
|
46
|
+
['digits', exports.RE_DIGITS],
|
|
47
|
+
['hex', exports.RE_HEX],
|
|
48
|
+
];
|
|
49
|
+
function isPrintableAscii(s) {
|
|
50
|
+
return PRINTABLE.test(s);
|
|
51
|
+
}
|
|
52
|
+
/** First matching format of 6.3, or null. Only printable ASCII strings are considered. */
|
|
53
|
+
function detectFormat(s) {
|
|
54
|
+
if (!PRINTABLE.test(s))
|
|
55
|
+
return null;
|
|
56
|
+
for (const [name, re] of FORMATS) {
|
|
57
|
+
if (re.test(s))
|
|
58
|
+
return name;
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
/** drop form of a well-formed string. */
|
|
63
|
+
function strShape(s) {
|
|
64
|
+
const f = detectFormat(s);
|
|
65
|
+
if (f !== null)
|
|
66
|
+
return 'drop:str:' + f;
|
|
67
|
+
return 'drop:str:' + lenClass((0, utf8_js_1.utf8Length)(s));
|
|
68
|
+
}
|
|
69
|
+
const KEY_RE = /^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/;
|
|
70
|
+
const SIX_DIGITS = /[0-9]{6}/;
|
|
71
|
+
const HEADER_NAME_RE = /^[a-z0-9!#$%&'*+.^_`|~-]{1,64}$/;
|
|
72
|
+
function looksLikeValue(s) {
|
|
73
|
+
return exports.RE_UUID.test(s) || exports.RE_EMAIL.test(s) || exports.RE_HEX.test(s) || exports.RE_DIGITS.test(s) || exports.RE_JWT.test(s) || SIX_DIGITS.test(s);
|
|
74
|
+
}
|
|
75
|
+
/** 9.3.3: a JSON key, query, cookie or form name leaves as a literal only if this holds. */
|
|
76
|
+
function isLiteralName(s) {
|
|
77
|
+
const hit = literalMemo.get(s);
|
|
78
|
+
if (hit !== undefined)
|
|
79
|
+
return hit;
|
|
80
|
+
const r = KEY_RE.test(s) && !looksLikeValue(s);
|
|
81
|
+
// Names repeat (JSON keys, header and query names): remember the answer, bounded.
|
|
82
|
+
if (s.length <= 64) {
|
|
83
|
+
if (literalMemo.size >= MEMO_MAX)
|
|
84
|
+
literalMemo.clear();
|
|
85
|
+
literalMemo.set(s, r);
|
|
86
|
+
}
|
|
87
|
+
return r;
|
|
88
|
+
}
|
|
89
|
+
const MEMO_MAX = 2048;
|
|
90
|
+
const literalMemo = new Map();
|
|
91
|
+
const headerMemo = new Map();
|
|
92
|
+
/** 8.0.2: output name of a lowercased header name. */
|
|
93
|
+
function headerOutName(lower) {
|
|
94
|
+
const hit = headerMemo.get(lower);
|
|
95
|
+
if (hit !== undefined)
|
|
96
|
+
return hit;
|
|
97
|
+
const r = !HEADER_NAME_RE.test(lower) || looksLikeValue(lower) ? '{*}' : lower;
|
|
98
|
+
if (lower.length <= 64) {
|
|
99
|
+
if (headerMemo.size >= MEMO_MAX)
|
|
100
|
+
headerMemo.clear();
|
|
101
|
+
headerMemo.set(lower, r);
|
|
102
|
+
}
|
|
103
|
+
return r;
|
|
104
|
+
}
|
|
105
|
+
exports.PATH_TOKEN_RE = /^[A-Za-z0-9._~-]{1,64}$/;
|
|
106
|
+
/** Code shape of the code action (sanitizer.md 5.6, spec v1.11): ASCII letters, `_`, `-`, 2 to 32 bytes. */
|
|
107
|
+
exports.CODE_RE = /^[A-Za-z_-]{2,32}$/;
|
|
108
|
+
/** Shape `alnum` of the code action (sanitizer.md 5.6, spec v1.19): letters, digits, `_`, `-`, `.`, 1 to 16 bytes. */
|
|
109
|
+
exports.CODE_ALNUM_RE = /^[A-Za-z0-9_.-]{1,16}$/;
|
|
110
|
+
exports.AUTO_WORD_RE = /^([a-z]+([-_][a-z]+)*|v[0-9]{1,3})$/;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** Largest number of open brackets ({, ( and [ together). */
|
|
2
|
+
export declare const GQL_MAX_NESTING = 64;
|
|
3
|
+
/** Largest shape; a longer one is not emitted. */
|
|
4
|
+
export declare const GQL_MAX_SHAPE_BYTES = 32768;
|
|
5
|
+
/** Longest name emitted as written. */
|
|
6
|
+
export declare const GQL_MAX_NAME_BYTES = 64;
|
|
7
|
+
/** Array limit of a response body when the introspection gate is open (5.7.2). */
|
|
8
|
+
export declare const GQL_INTROSPECTION_MAX_ARRAY = 4096;
|
|
9
|
+
export interface GqlShape {
|
|
10
|
+
/** Canonical shape, without the `gql:` prefix. */
|
|
11
|
+
shape: string;
|
|
12
|
+
/** Every operation selects only __schema, __type, __typename at its root, without aliases. */
|
|
13
|
+
introspection: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** The key rule of 9.3 on a GraphQL name (5.7.1). */
|
|
16
|
+
export declare function gqlNameSafe(name: string): boolean;
|
|
17
|
+
/** True if s is a GraphQL name (any length). */
|
|
18
|
+
export declare function gqlIsName(s: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Shape of an executable document (5.7.1), or null when `src` is not an executable
|
|
21
|
+
* document within the limits (the caller then emits the drop form of the string).
|
|
22
|
+
*/
|
|
23
|
+
export declare function gqlShape(src: string): GqlShape | null;
|
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// GraphQL document shape, sanitizer.md 5.7 (spec v1.14): the same algorithm as the Go
|
|
3
|
+
// reference (internal/graphql) and conformance/ref/gqlshape.py, step by step.
|
|
4
|
+
//
|
|
5
|
+
// The input is a well-formed JavaScript string (no lone surrogates: the caller checks).
|
|
6
|
+
// Everything outside strings and comments is ASCII, so code units and bytes coincide
|
|
7
|
+
// wherever the algorithm looks; any other character there is an error.
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.GQL_INTROSPECTION_MAX_ARRAY = exports.GQL_MAX_NAME_BYTES = exports.GQL_MAX_SHAPE_BYTES = exports.GQL_MAX_NESTING = void 0;
|
|
10
|
+
exports.gqlNameSafe = gqlNameSafe;
|
|
11
|
+
exports.gqlIsName = gqlIsName;
|
|
12
|
+
exports.gqlShape = gqlShape;
|
|
13
|
+
/** Largest number of open brackets ({, ( and [ together). */
|
|
14
|
+
exports.GQL_MAX_NESTING = 64;
|
|
15
|
+
/** Largest shape; a longer one is not emitted. */
|
|
16
|
+
exports.GQL_MAX_SHAPE_BYTES = 32768;
|
|
17
|
+
/** Longest name emitted as written. */
|
|
18
|
+
exports.GQL_MAX_NAME_BYTES = 64;
|
|
19
|
+
/** Array limit of a response body when the introspection gate is open (5.7.2). */
|
|
20
|
+
exports.GQL_INTROSPECTION_MAX_ARRAY = 4096;
|
|
21
|
+
class GqlError extends Error {
|
|
22
|
+
}
|
|
23
|
+
const ERR = new GqlError('graphql');
|
|
24
|
+
function isNameStart(c) {
|
|
25
|
+
return c === 0x5f || (c >= 0x41 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a);
|
|
26
|
+
}
|
|
27
|
+
function isNameCont(c) {
|
|
28
|
+
return isNameStart(c) || (c >= 0x30 && c <= 0x39);
|
|
29
|
+
}
|
|
30
|
+
function isDigit(c) {
|
|
31
|
+
return c >= 0x30 && c <= 0x39;
|
|
32
|
+
}
|
|
33
|
+
function isHex(c) {
|
|
34
|
+
return (c >= 0x30 && c <= 0x39) || (c >= 0x61 && c <= 0x66) || (c >= 0x41 && c <= 0x46);
|
|
35
|
+
}
|
|
36
|
+
function lex(src) {
|
|
37
|
+
const toks = [];
|
|
38
|
+
const n = src.length;
|
|
39
|
+
let i = 0;
|
|
40
|
+
let open = 0;
|
|
41
|
+
while (i < n) {
|
|
42
|
+
const c = src.charCodeAt(i);
|
|
43
|
+
switch (c) {
|
|
44
|
+
case 0x20:
|
|
45
|
+
case 0x09:
|
|
46
|
+
case 0x0a:
|
|
47
|
+
case 0x0d:
|
|
48
|
+
case 0x2c:
|
|
49
|
+
case 0xfeff:
|
|
50
|
+
i++;
|
|
51
|
+
continue;
|
|
52
|
+
case 0x23: // #
|
|
53
|
+
while (i < n && src.charCodeAt(i) !== 0x0a && src.charCodeAt(i) !== 0x0d)
|
|
54
|
+
i++;
|
|
55
|
+
continue;
|
|
56
|
+
case 0x21:
|
|
57
|
+
case 0x24:
|
|
58
|
+
case 0x26:
|
|
59
|
+
case 0x3a:
|
|
60
|
+
case 0x3d:
|
|
61
|
+
case 0x40:
|
|
62
|
+
case 0x7c: // ! $ & : = @ |
|
|
63
|
+
toks.push({ k: 'punct', s: src[i], value: false });
|
|
64
|
+
i++;
|
|
65
|
+
continue;
|
|
66
|
+
case 0x28:
|
|
67
|
+
case 0x5b:
|
|
68
|
+
case 0x7b: // ( [ {
|
|
69
|
+
if (++open > exports.GQL_MAX_NESTING)
|
|
70
|
+
throw ERR;
|
|
71
|
+
toks.push({ k: 'punct', s: src[i], value: false });
|
|
72
|
+
i++;
|
|
73
|
+
continue;
|
|
74
|
+
case 0x29:
|
|
75
|
+
case 0x5d:
|
|
76
|
+
case 0x7d: // ) ] }
|
|
77
|
+
if (--open < 0)
|
|
78
|
+
throw ERR;
|
|
79
|
+
toks.push({ k: 'punct', s: src[i], value: false });
|
|
80
|
+
i++;
|
|
81
|
+
continue;
|
|
82
|
+
case 0x2e: // .
|
|
83
|
+
if (src.startsWith('...', i)) {
|
|
84
|
+
toks.push({ k: 'punct', s: '...', value: false });
|
|
85
|
+
i += 3;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
throw ERR;
|
|
89
|
+
case 0x22: // "
|
|
90
|
+
i = lexString(src, i);
|
|
91
|
+
toks.push({ k: 'str', s: '', value: false });
|
|
92
|
+
continue;
|
|
93
|
+
default:
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (isNameStart(c)) {
|
|
97
|
+
let j = i + 1;
|
|
98
|
+
while (j < n && isNameCont(src.charCodeAt(j)))
|
|
99
|
+
j++;
|
|
100
|
+
toks.push({ k: 'name', s: src.slice(i, j), value: false });
|
|
101
|
+
i = j;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (c === 0x2d || isDigit(c)) {
|
|
105
|
+
const [j, k] = lexNumber(src, i);
|
|
106
|
+
toks.push({ k, s: '', value: false });
|
|
107
|
+
i = j;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
throw ERR;
|
|
111
|
+
}
|
|
112
|
+
if (open !== 0)
|
|
113
|
+
throw ERR;
|
|
114
|
+
return toks;
|
|
115
|
+
}
|
|
116
|
+
function lexNumber(src, i) {
|
|
117
|
+
const n = src.length;
|
|
118
|
+
let j = i;
|
|
119
|
+
if (src.charCodeAt(j) === 0x2d)
|
|
120
|
+
j++;
|
|
121
|
+
if (j >= n || !isDigit(src.charCodeAt(j)))
|
|
122
|
+
throw ERR;
|
|
123
|
+
if (src.charCodeAt(j) === 0x30) {
|
|
124
|
+
j++;
|
|
125
|
+
if (j < n && isDigit(src.charCodeAt(j)))
|
|
126
|
+
throw ERR; // leading zero
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
while (j < n && isDigit(src.charCodeAt(j)))
|
|
130
|
+
j++;
|
|
131
|
+
}
|
|
132
|
+
let k = 'int';
|
|
133
|
+
if (j < n && src.charCodeAt(j) === 0x2e) {
|
|
134
|
+
j++;
|
|
135
|
+
if (j >= n || !isDigit(src.charCodeAt(j)))
|
|
136
|
+
throw ERR;
|
|
137
|
+
while (j < n && isDigit(src.charCodeAt(j)))
|
|
138
|
+
j++;
|
|
139
|
+
k = 'float';
|
|
140
|
+
}
|
|
141
|
+
if (j < n && (src.charCodeAt(j) === 0x65 || src.charCodeAt(j) === 0x45)) {
|
|
142
|
+
j++;
|
|
143
|
+
if (j < n && (src.charCodeAt(j) === 0x2b || src.charCodeAt(j) === 0x2d))
|
|
144
|
+
j++;
|
|
145
|
+
if (j >= n || !isDigit(src.charCodeAt(j)))
|
|
146
|
+
throw ERR;
|
|
147
|
+
while (j < n && isDigit(src.charCodeAt(j)))
|
|
148
|
+
j++;
|
|
149
|
+
k = 'float';
|
|
150
|
+
}
|
|
151
|
+
// A number is not followed by '.' or a NameStart.
|
|
152
|
+
if (j < n && (src.charCodeAt(j) === 0x2e || isNameStart(src.charCodeAt(j))))
|
|
153
|
+
throw ERR;
|
|
154
|
+
return [j, k];
|
|
155
|
+
}
|
|
156
|
+
/** Index after the string or block string starting at the quote at i. */
|
|
157
|
+
function lexString(src, i) {
|
|
158
|
+
const n = src.length;
|
|
159
|
+
if (src.startsWith('"""', i)) {
|
|
160
|
+
let j = i + 3;
|
|
161
|
+
while (j < n) {
|
|
162
|
+
const c = src.charCodeAt(j);
|
|
163
|
+
if (c === 0x5c && src.startsWith('"""', j + 1))
|
|
164
|
+
j += 4;
|
|
165
|
+
else if (c === 0x22 && src.startsWith('"""', j))
|
|
166
|
+
return j + 3;
|
|
167
|
+
else if (c < 0x20 && c !== 0x09 && c !== 0x0a && c !== 0x0d)
|
|
168
|
+
throw ERR;
|
|
169
|
+
else
|
|
170
|
+
j++;
|
|
171
|
+
}
|
|
172
|
+
throw ERR;
|
|
173
|
+
}
|
|
174
|
+
let j = i + 1;
|
|
175
|
+
while (j < n) {
|
|
176
|
+
const c = src.charCodeAt(j);
|
|
177
|
+
if (c === 0x22)
|
|
178
|
+
return j + 1;
|
|
179
|
+
if (c === 0x5c) {
|
|
180
|
+
if (j + 1 >= n)
|
|
181
|
+
throw ERR;
|
|
182
|
+
switch (src[j + 1]) {
|
|
183
|
+
case '"':
|
|
184
|
+
case '\\':
|
|
185
|
+
case '/':
|
|
186
|
+
case 'b':
|
|
187
|
+
case 'f':
|
|
188
|
+
case 'n':
|
|
189
|
+
case 'r':
|
|
190
|
+
case 't':
|
|
191
|
+
j += 2;
|
|
192
|
+
break;
|
|
193
|
+
case 'u':
|
|
194
|
+
if (j + 5 >= n)
|
|
195
|
+
throw ERR;
|
|
196
|
+
for (let h = j + 2; h < j + 6; h++)
|
|
197
|
+
if (!isHex(src.charCodeAt(h)))
|
|
198
|
+
throw ERR;
|
|
199
|
+
j += 6;
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
throw ERR;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (c < 0x20 && c !== 0x09) {
|
|
206
|
+
throw ERR; // line terminators and control characters
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
j++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
throw ERR;
|
|
213
|
+
}
|
|
214
|
+
class Parser {
|
|
215
|
+
t;
|
|
216
|
+
p = 0;
|
|
217
|
+
/** Root selections of every operation (fragments excluded). */
|
|
218
|
+
ops = [];
|
|
219
|
+
constructor(t) {
|
|
220
|
+
this.t = t;
|
|
221
|
+
}
|
|
222
|
+
isPunct(s) {
|
|
223
|
+
const t = this.t[this.p];
|
|
224
|
+
return t !== undefined && t.k === 'punct' && t.s === s;
|
|
225
|
+
}
|
|
226
|
+
isName(s) {
|
|
227
|
+
const t = this.t[this.p];
|
|
228
|
+
return t !== undefined && t.k === 'name' && (s === undefined || t.s === s);
|
|
229
|
+
}
|
|
230
|
+
expect(s) {
|
|
231
|
+
if (!this.isPunct(s))
|
|
232
|
+
throw ERR;
|
|
233
|
+
this.p++;
|
|
234
|
+
}
|
|
235
|
+
name() {
|
|
236
|
+
if (!this.isName())
|
|
237
|
+
throw ERR;
|
|
238
|
+
return this.t[this.p++].s;
|
|
239
|
+
}
|
|
240
|
+
document() {
|
|
241
|
+
if (this.t.length === 0)
|
|
242
|
+
throw ERR;
|
|
243
|
+
while (this.p < this.t.length) {
|
|
244
|
+
if (this.isPunct('{')) {
|
|
245
|
+
this.ops.push(this.selectionSet());
|
|
246
|
+
}
|
|
247
|
+
else if (this.isName('query') || this.isName('mutation') || this.isName('subscription')) {
|
|
248
|
+
this.p++;
|
|
249
|
+
if (this.isName())
|
|
250
|
+
this.p++;
|
|
251
|
+
if (this.isPunct('(')) {
|
|
252
|
+
this.p++;
|
|
253
|
+
if (this.isPunct(')'))
|
|
254
|
+
throw ERR;
|
|
255
|
+
while (!this.isPunct(')'))
|
|
256
|
+
this.varDef();
|
|
257
|
+
this.p++;
|
|
258
|
+
}
|
|
259
|
+
this.directives();
|
|
260
|
+
this.ops.push(this.selectionSet());
|
|
261
|
+
}
|
|
262
|
+
else if (this.isName('fragment')) {
|
|
263
|
+
this.p++;
|
|
264
|
+
if (this.name() === 'on')
|
|
265
|
+
throw ERR;
|
|
266
|
+
if (!this.isName('on'))
|
|
267
|
+
throw ERR;
|
|
268
|
+
this.p++;
|
|
269
|
+
this.name();
|
|
270
|
+
this.directives();
|
|
271
|
+
this.selectionSet();
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
throw ERR;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
varDef() {
|
|
279
|
+
this.expect('$');
|
|
280
|
+
this.name();
|
|
281
|
+
this.expect(':');
|
|
282
|
+
this.typeRef();
|
|
283
|
+
if (this.isPunct('=')) {
|
|
284
|
+
this.p++;
|
|
285
|
+
this.value();
|
|
286
|
+
}
|
|
287
|
+
this.directives();
|
|
288
|
+
}
|
|
289
|
+
typeRef() {
|
|
290
|
+
if (this.isPunct('[')) {
|
|
291
|
+
this.p++;
|
|
292
|
+
this.typeRef();
|
|
293
|
+
this.expect(']');
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
this.name();
|
|
297
|
+
}
|
|
298
|
+
if (this.isPunct('!'))
|
|
299
|
+
this.p++;
|
|
300
|
+
}
|
|
301
|
+
selectionSet() {
|
|
302
|
+
this.expect('{');
|
|
303
|
+
const out = [];
|
|
304
|
+
while (!this.isPunct('}'))
|
|
305
|
+
out.push(this.selection());
|
|
306
|
+
if (out.length === 0)
|
|
307
|
+
throw ERR;
|
|
308
|
+
this.p++;
|
|
309
|
+
return out;
|
|
310
|
+
}
|
|
311
|
+
selection() {
|
|
312
|
+
if (this.isPunct('...')) {
|
|
313
|
+
this.p++;
|
|
314
|
+
if (this.isName() && !this.isName('on')) {
|
|
315
|
+
this.p++;
|
|
316
|
+
this.directives();
|
|
317
|
+
return { field: false, alias: false, name: '' };
|
|
318
|
+
}
|
|
319
|
+
if (this.isName()) {
|
|
320
|
+
this.p++; // on
|
|
321
|
+
this.name();
|
|
322
|
+
}
|
|
323
|
+
this.directives();
|
|
324
|
+
this.selectionSet();
|
|
325
|
+
return { field: false, alias: false, name: '' };
|
|
326
|
+
}
|
|
327
|
+
let name = this.name();
|
|
328
|
+
let alias = false;
|
|
329
|
+
if (this.isPunct(':')) {
|
|
330
|
+
this.p++;
|
|
331
|
+
name = this.name();
|
|
332
|
+
alias = true;
|
|
333
|
+
}
|
|
334
|
+
if (this.isPunct('('))
|
|
335
|
+
this.arguments();
|
|
336
|
+
this.directives();
|
|
337
|
+
if (this.isPunct('{'))
|
|
338
|
+
this.selectionSet();
|
|
339
|
+
return { field: true, alias, name };
|
|
340
|
+
}
|
|
341
|
+
arguments() {
|
|
342
|
+
this.expect('(');
|
|
343
|
+
if (this.isPunct(')'))
|
|
344
|
+
throw ERR;
|
|
345
|
+
while (!this.isPunct(')')) {
|
|
346
|
+
this.name();
|
|
347
|
+
this.expect(':');
|
|
348
|
+
this.value();
|
|
349
|
+
}
|
|
350
|
+
this.p++;
|
|
351
|
+
}
|
|
352
|
+
directives() {
|
|
353
|
+
while (this.isPunct('@')) {
|
|
354
|
+
this.p++;
|
|
355
|
+
this.name();
|
|
356
|
+
if (this.isPunct('('))
|
|
357
|
+
this.arguments();
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
value() {
|
|
361
|
+
const t = this.t[this.p];
|
|
362
|
+
if (t === undefined)
|
|
363
|
+
throw ERR;
|
|
364
|
+
if (t.k === 'punct') {
|
|
365
|
+
if (t.s === '$') {
|
|
366
|
+
this.p++;
|
|
367
|
+
this.name();
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (t.s === '[') {
|
|
371
|
+
this.p++;
|
|
372
|
+
while (!this.isPunct(']'))
|
|
373
|
+
this.value();
|
|
374
|
+
this.p++;
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (t.s === '{') {
|
|
378
|
+
this.p++;
|
|
379
|
+
while (!this.isPunct('}')) {
|
|
380
|
+
this.name();
|
|
381
|
+
this.expect(':');
|
|
382
|
+
this.value();
|
|
383
|
+
}
|
|
384
|
+
this.p++;
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
throw ERR;
|
|
388
|
+
}
|
|
389
|
+
if (t.k === 'name')
|
|
390
|
+
t.value = true;
|
|
391
|
+
this.p++;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/** The key rule of 9.3 on a GraphQL name (5.7.1). */
|
|
395
|
+
function gqlNameSafe(name) {
|
|
396
|
+
const n = name.length;
|
|
397
|
+
if (n === 0 || n > exports.GQL_MAX_NAME_BYTES || !isNameStart(name.charCodeAt(0)))
|
|
398
|
+
return false;
|
|
399
|
+
let allHex = n >= 16;
|
|
400
|
+
let run = 0;
|
|
401
|
+
for (let i = 0; i < n; i++) {
|
|
402
|
+
const c = name.charCodeAt(i);
|
|
403
|
+
if (!isNameCont(c))
|
|
404
|
+
return false;
|
|
405
|
+
if (!isHex(c))
|
|
406
|
+
allHex = false;
|
|
407
|
+
if (isDigit(c)) {
|
|
408
|
+
if (++run >= 6)
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
run = 0;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return !allHex;
|
|
416
|
+
}
|
|
417
|
+
/** True if s is a GraphQL name (any length). */
|
|
418
|
+
function gqlIsName(s) {
|
|
419
|
+
if (s.length === 0 || !isNameStart(s.charCodeAt(0)))
|
|
420
|
+
return false;
|
|
421
|
+
for (let i = 1; i < s.length; i++)
|
|
422
|
+
if (!isNameCont(s.charCodeAt(i)))
|
|
423
|
+
return false;
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
function isWord(c) {
|
|
427
|
+
return isNameCont(c) || c === 0x3f || c === 0x2a; // ? *
|
|
428
|
+
}
|
|
429
|
+
/**
|
|
430
|
+
* Shape of an executable document (5.7.1), or null when `src` is not an executable
|
|
431
|
+
* document within the limits (the caller then emits the drop form of the string).
|
|
432
|
+
*/
|
|
433
|
+
function gqlShape(src) {
|
|
434
|
+
let toks;
|
|
435
|
+
let p;
|
|
436
|
+
try {
|
|
437
|
+
toks = lex(src);
|
|
438
|
+
p = new Parser(toks);
|
|
439
|
+
p.document();
|
|
440
|
+
}
|
|
441
|
+
catch (e) {
|
|
442
|
+
if (e instanceof GqlError)
|
|
443
|
+
return null;
|
|
444
|
+
throw e;
|
|
445
|
+
}
|
|
446
|
+
let out = '';
|
|
447
|
+
let prevWord = false;
|
|
448
|
+
for (const t of toks) {
|
|
449
|
+
let s;
|
|
450
|
+
switch (t.k) {
|
|
451
|
+
case 'punct':
|
|
452
|
+
s = t.s;
|
|
453
|
+
break;
|
|
454
|
+
case 'name':
|
|
455
|
+
if (t.value)
|
|
456
|
+
s = t.s === 'true' || t.s === 'false' ? '?b' : t.s === 'null' ? '?n' : '?e';
|
|
457
|
+
else
|
|
458
|
+
s = gqlNameSafe(t.s) ? t.s : '*';
|
|
459
|
+
break;
|
|
460
|
+
case 'int':
|
|
461
|
+
s = '?i';
|
|
462
|
+
break;
|
|
463
|
+
case 'float':
|
|
464
|
+
s = '?f';
|
|
465
|
+
break;
|
|
466
|
+
default:
|
|
467
|
+
s = '?s';
|
|
468
|
+
}
|
|
469
|
+
if (prevWord && isWord(s.charCodeAt(0)))
|
|
470
|
+
out += ' ';
|
|
471
|
+
out += s;
|
|
472
|
+
prevWord = isWord(s.charCodeAt(s.length - 1));
|
|
473
|
+
if (out.length > exports.GQL_MAX_SHAPE_BYTES)
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
const introspection = p.ops.length > 0 && p.ops.every((sel) => sel.every((r) => r.field && !r.alias && (r.name === '__schema' || r.name === '__type' || r.name === '__typename')));
|
|
477
|
+
return { shape: out, introspection };
|
|
478
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** 3.5: a host label stays literal only if every rule holds. */
|
|
2
|
+
export declare function hostLabelSafe(label: string): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* 3.1 point 5: RFC 4291 2.2 text form of an already lowercased string. 1-4 hex digits per
|
|
5
|
+
* group, at most one `::` standing for at least one group, an optional dotted IPv4 (6.3
|
|
6
|
+
* `ipv4`) as the last 32 bits, no zone. Returns the 16 address bytes or null.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseIpv6(s: string): Uint8Array | null;
|
|
9
|
+
export declare function ipv4Private(a: ArrayLike<number>): boolean;
|
|
10
|
+
export declare function ipv6Private(a: Uint8Array): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* 3.5: pattern of a valid host (3.1), without the `host:` prefix, or null when a label is
|
|
13
|
+
* empty (`host:invalid`). `port` is the normalized port (null when absent or default).
|
|
14
|
+
*/
|
|
15
|
+
export declare function hostPattern(host: string, port: string | null, ip6: Uint8Array | null): string | null;
|