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