recker 1.0.14 → 1.0.15-next.0dab95d
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/README.md +78 -100
- package/dist/ai/client.d.ts +2 -3
- package/dist/ai/client.d.ts.map +1 -1
- package/dist/ai/client.js +5 -6
- package/dist/ai/index.d.ts +1 -1
- package/dist/ai/index.d.ts.map +1 -1
- package/dist/ai/index.js +1 -1
- package/dist/bench/generator.d.ts.map +1 -1
- package/dist/bench/generator.js +2 -1
- package/dist/bench/stats.d.ts +15 -1
- package/dist/bench/stats.d.ts.map +1 -1
- package/dist/bench/stats.js +84 -5
- package/dist/cli/index.js +21 -0
- package/dist/cli/tui/ai-chat.js +2 -2
- package/dist/cli/tui/load-dashboard.d.ts.map +1 -1
- package/dist/cli/tui/load-dashboard.js +62 -8
- package/dist/cli/tui/scroll-buffer.d.ts +43 -0
- package/dist/cli/tui/scroll-buffer.d.ts.map +1 -0
- package/dist/cli/tui/scroll-buffer.js +162 -0
- package/dist/cli/tui/search-panel.d.ts +41 -0
- package/dist/cli/tui/search-panel.d.ts.map +1 -0
- package/dist/cli/tui/search-panel.js +419 -0
- package/dist/cli/tui/shell.d.ts +11 -0
- package/dist/cli/tui/shell.d.ts.map +1 -1
- package/dist/cli/tui/shell.js +242 -46
- package/dist/contract/index.js +3 -2
- package/dist/dns/index.d.ts +36 -0
- package/dist/dns/index.d.ts.map +1 -0
- package/dist/dns/index.js +125 -0
- package/dist/dns/propagation.d.ts +19 -0
- package/dist/dns/propagation.d.ts.map +1 -0
- package/dist/dns/propagation.js +129 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/mcp/embeddings-loader.d.ts +18 -0
- package/dist/mcp/embeddings-loader.d.ts.map +1 -0
- package/dist/mcp/embeddings-loader.js +152 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +1 -0
- package/dist/mcp/search/hybrid-search.d.ts.map +1 -1
- package/dist/mcp/search/hybrid-search.js +7 -21
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +8 -1
- package/dist/recker.d.ts +47 -0
- package/dist/recker.d.ts.map +1 -0
- package/dist/recker.js +99 -0
- package/dist/transport/base-udp.d.ts.map +1 -1
- package/dist/transport/base-udp.js +1 -0
- package/dist/transport/udp-response.d.ts +2 -2
- package/dist/transport/udp-response.d.ts.map +1 -1
- package/dist/transport/udp-response.js +2 -2
- package/dist/transport/udp.d.ts +4 -3
- package/dist/transport/udp.d.ts.map +1 -1
- package/dist/transport/udp.js +16 -7
- package/dist/types/udp.d.ts +1 -0
- package/dist/types/udp.d.ts.map +1 -1
- package/dist/udp/index.d.ts +2 -2
- package/dist/udp/index.d.ts.map +1 -1
- package/dist/udp/index.js +2 -2
- package/dist/utils/colors.d.ts +16 -0
- package/dist/utils/colors.d.ts.map +1 -1
- package/dist/utils/colors.js +16 -0
- package/dist/utils/tls-inspector.d.ts +6 -0
- package/dist/utils/tls-inspector.d.ts.map +1 -1
- package/dist/utils/tls-inspector.js +35 -1
- package/dist/utils/whois.d.ts +18 -0
- package/dist/utils/whois.d.ts.map +1 -1
- package/dist/utils/whois.js +63 -0
- package/dist/webrtc/index.d.ts +80 -0
- package/dist/webrtc/index.d.ts.map +1 -0
- package/dist/webrtc/index.js +311 -0
- package/dist/websocket/client.d.ts +1 -1
- package/dist/websocket/client.d.ts.map +1 -1
- package/dist/websocket/client.js +1 -1
- package/package.json +2 -2
- package/dist/mcp/data/embeddings.json +0 -1
package/dist/cli/tui/shell.d.ts
CHANGED
|
@@ -10,6 +10,9 @@ export declare class RekShell {
|
|
|
10
10
|
private initialized;
|
|
11
11
|
private currentDoc;
|
|
12
12
|
private currentDocUrl;
|
|
13
|
+
private scrollBuffer;
|
|
14
|
+
private originalStdoutWrite;
|
|
15
|
+
private inScrollMode;
|
|
13
16
|
constructor();
|
|
14
17
|
private ensureInitialized;
|
|
15
18
|
private getPrompt;
|
|
@@ -17,6 +20,13 @@ export declare class RekShell {
|
|
|
17
20
|
private getRootDomain;
|
|
18
21
|
private completer;
|
|
19
22
|
start(): Promise<void>;
|
|
23
|
+
private setupScrollCapture;
|
|
24
|
+
private cleanupScrollCapture;
|
|
25
|
+
private setupScrollKeyHandler;
|
|
26
|
+
private handleScrollKey;
|
|
27
|
+
private enterScrollMode;
|
|
28
|
+
private exitScrollMode;
|
|
29
|
+
private renderScrollView;
|
|
20
30
|
private prompt;
|
|
21
31
|
private handleCommand;
|
|
22
32
|
private runInteractiveMode;
|
|
@@ -33,6 +43,7 @@ export declare class RekShell {
|
|
|
33
43
|
private runWhois;
|
|
34
44
|
private runTLS;
|
|
35
45
|
private runDNS;
|
|
46
|
+
private runDNSPropagation;
|
|
36
47
|
private runRDAP;
|
|
37
48
|
private runPing;
|
|
38
49
|
private runScrap;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/cli/tui/shell.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../src/cli/tui/shell.ts"],"names":[],"mappings":"AAsCA,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAAsB;IAChC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,mBAAmB,CAA4C;IACvE,OAAO,CAAC,YAAY,CAAkB;;YAgBxB,iBAAiB;IAe/B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,SAAS;IAcJ,KAAK;IA8ClB,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,qBAAqB;IAuC7B,OAAO,CAAC,eAAe;IAmEvB,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,cAAc;IA0BtB,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,MAAM;YAKA,aAAa;YAoMb,kBAAkB;YAkBlB,SAAS;YAkBT,WAAW;IA0DzB,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,QAAQ;IAoCV,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM;IA6CnC,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,UAAU;YAeJ,cAAc;YAyEd,QAAQ;YA8GR,MAAM;YA4FN,MAAM;YA2EN,iBAAiB;YAuBjB,OAAO;YA+DP,OAAO;YA0CP,QAAQ;YAoER,SAAS;YAsCT,aAAa;YA8Bb,aAAa;YA+Bb,aAAa;YA6Bb,cAAc;YAkCd,eAAe;YA+Ef,gBAAgB;YAmEhB,YAAY;YAiEZ,mBAAmB;YAsFnB,QAAQ;YA0FR,YAAY;YAoCZ,YAAY;YA6CZ,WAAW;IA6CzB,OAAO,CAAC,UAAU;IA4GlB,OAAO,CAAC,WAAW;YAgFL,eAAe;YAkBf,cAAc;YAgDd,SAAS;YAgBT,UAAU;YAuBV,UAAU;IAwBxB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,SAAS;CA8ElB"}
|
package/dist/cli/tui/shell.js
CHANGED
|
@@ -12,6 +12,8 @@ import { rdap } from '../../utils/rdap.js';
|
|
|
12
12
|
import { ScrapeDocument } from '../../scrape/document.js';
|
|
13
13
|
import colors from '../../utils/colors.js';
|
|
14
14
|
import { getShellSearch } from './shell-search.js';
|
|
15
|
+
import { openSearchPanel } from './search-panel.js';
|
|
16
|
+
import { ScrollBuffer, parseScrollKey, parseMouseScroll, enableMouseReporting, disableMouseReporting } from './scroll-buffer.js';
|
|
15
17
|
let highlight;
|
|
16
18
|
async function initDependencies() {
|
|
17
19
|
if (!highlight) {
|
|
@@ -36,11 +38,16 @@ export class RekShell {
|
|
|
36
38
|
initialized = false;
|
|
37
39
|
currentDoc = null;
|
|
38
40
|
currentDocUrl = '';
|
|
41
|
+
scrollBuffer;
|
|
42
|
+
originalStdoutWrite = null;
|
|
43
|
+
inScrollMode = false;
|
|
39
44
|
constructor() {
|
|
40
45
|
this.client = createClient({
|
|
41
46
|
baseUrl: 'http://localhost',
|
|
42
|
-
checkHooks: false
|
|
47
|
+
checkHooks: false,
|
|
48
|
+
http2: true
|
|
43
49
|
});
|
|
50
|
+
this.scrollBuffer = new ScrollBuffer({ maxLines: 10000 });
|
|
44
51
|
}
|
|
45
52
|
async ensureInitialized() {
|
|
46
53
|
if (this.initialized)
|
|
@@ -85,7 +92,7 @@ export class RekShell {
|
|
|
85
92
|
const commands = [
|
|
86
93
|
'get', 'post', 'put', 'delete', 'patch', 'head', 'options',
|
|
87
94
|
'ws', 'udp', 'load', 'chat', 'ai',
|
|
88
|
-
'whois', 'tls', 'ssl', 'dns', 'rdap', 'ping',
|
|
95
|
+
'whois', 'tls', 'ssl', 'dns', 'dns:propagate', 'rdap', 'ping',
|
|
89
96
|
'scrap', '$', '$text', '$attr', '$html', '$links', '$images', '$scripts', '$css', '$sourcemaps', '$unmap', '$unmap:view', '$unmap:save', '$beautify', '$beautify:save', '$table',
|
|
90
97
|
'?', 'search', 'suggest', 'example',
|
|
91
98
|
'help', 'clear', 'exit', 'set', 'url', 'vars', 'env'
|
|
@@ -95,9 +102,11 @@ export class RekShell {
|
|
|
95
102
|
}
|
|
96
103
|
async start() {
|
|
97
104
|
await this.ensureInitialized();
|
|
105
|
+
this.setupScrollCapture();
|
|
98
106
|
console.clear();
|
|
99
107
|
console.log(colors.bold(colors.cyan('Rek Console')));
|
|
100
108
|
console.log(colors.gray('Chat with your APIs. Type "help" for magic.'));
|
|
109
|
+
console.log(colors.gray('Page Up/Down or mouse scroll to view history.'));
|
|
101
110
|
console.log(colors.gray('--------------------------------------------\n'));
|
|
102
111
|
this.prompt();
|
|
103
112
|
this.rl.on('line', async (line) => {
|
|
@@ -112,15 +121,165 @@ export class RekShell {
|
|
|
112
121
|
this.rl.close();
|
|
113
122
|
});
|
|
114
123
|
this.rl.on('close', () => {
|
|
124
|
+
this.cleanupScrollCapture();
|
|
115
125
|
console.log(colors.gray('\nSee ya.'));
|
|
116
126
|
process.exit(0);
|
|
117
127
|
});
|
|
128
|
+
process.stdout.on('resize', () => {
|
|
129
|
+
this.scrollBuffer.updateViewport();
|
|
130
|
+
});
|
|
131
|
+
this.setupScrollKeyHandler();
|
|
132
|
+
}
|
|
133
|
+
setupScrollCapture() {
|
|
134
|
+
this.originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
135
|
+
const self = this;
|
|
136
|
+
process.stdout.write = function (chunk, encodingOrCallback, callback) {
|
|
137
|
+
const content = typeof chunk === 'string' ? chunk : chunk.toString();
|
|
138
|
+
self.scrollBuffer.write(content);
|
|
139
|
+
if (!self.inScrollMode && self.originalStdoutWrite) {
|
|
140
|
+
return self.originalStdoutWrite(chunk, encodingOrCallback, callback);
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
cleanupScrollCapture() {
|
|
146
|
+
if (this.originalStdoutWrite) {
|
|
147
|
+
process.stdout.write = this.originalStdoutWrite;
|
|
148
|
+
this.originalStdoutWrite = null;
|
|
149
|
+
}
|
|
150
|
+
disableMouseReporting();
|
|
151
|
+
}
|
|
152
|
+
setupScrollKeyHandler() {
|
|
153
|
+
enableMouseReporting();
|
|
154
|
+
if (process.stdin.isTTY) {
|
|
155
|
+
const originalEmit = process.stdin.emit.bind(process.stdin);
|
|
156
|
+
const self = this;
|
|
157
|
+
process.stdin.emit = function (event, ...args) {
|
|
158
|
+
if (event === 'data') {
|
|
159
|
+
const data = args[0];
|
|
160
|
+
const mouseScroll = parseMouseScroll(data);
|
|
161
|
+
if (mouseScroll) {
|
|
162
|
+
self.handleScrollKey(mouseScroll);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
const scrollKey = parseScrollKey(data);
|
|
166
|
+
if (scrollKey) {
|
|
167
|
+
self.handleScrollKey(scrollKey);
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return originalEmit(event, ...args);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
handleScrollKey(key) {
|
|
176
|
+
let needsRedraw = false;
|
|
177
|
+
switch (key) {
|
|
178
|
+
case 'pageUp':
|
|
179
|
+
if (!this.inScrollMode) {
|
|
180
|
+
this.enterScrollMode();
|
|
181
|
+
}
|
|
182
|
+
needsRedraw = this.scrollBuffer.pageUp();
|
|
183
|
+
break;
|
|
184
|
+
case 'pageDown':
|
|
185
|
+
needsRedraw = this.scrollBuffer.pageDown();
|
|
186
|
+
if (!this.scrollBuffer.isScrolledUp && this.inScrollMode) {
|
|
187
|
+
this.exitScrollMode();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case 'scrollUp':
|
|
192
|
+
if (!this.inScrollMode) {
|
|
193
|
+
this.enterScrollMode();
|
|
194
|
+
}
|
|
195
|
+
needsRedraw = this.scrollBuffer.scrollUp(3);
|
|
196
|
+
break;
|
|
197
|
+
case 'scrollDown':
|
|
198
|
+
needsRedraw = this.scrollBuffer.scrollDown(3);
|
|
199
|
+
if (!this.scrollBuffer.isScrolledUp && this.inScrollMode) {
|
|
200
|
+
this.exitScrollMode();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
break;
|
|
204
|
+
case 'home':
|
|
205
|
+
if (!this.inScrollMode) {
|
|
206
|
+
this.enterScrollMode();
|
|
207
|
+
}
|
|
208
|
+
this.scrollBuffer.scrollToTop();
|
|
209
|
+
needsRedraw = true;
|
|
210
|
+
break;
|
|
211
|
+
case 'end':
|
|
212
|
+
this.scrollBuffer.scrollToBottom();
|
|
213
|
+
if (this.inScrollMode) {
|
|
214
|
+
this.exitScrollMode();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
case 'escape':
|
|
219
|
+
if (this.inScrollMode) {
|
|
220
|
+
this.exitScrollMode();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
if (needsRedraw && this.inScrollMode) {
|
|
226
|
+
this.renderScrollView();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
enterScrollMode() {
|
|
230
|
+
if (this.inScrollMode)
|
|
231
|
+
return;
|
|
232
|
+
this.inScrollMode = true;
|
|
233
|
+
this.rl.pause();
|
|
234
|
+
if (this.originalStdoutWrite) {
|
|
235
|
+
this.originalStdoutWrite('\x1b[?25l');
|
|
236
|
+
}
|
|
237
|
+
this.renderScrollView();
|
|
238
|
+
}
|
|
239
|
+
exitScrollMode() {
|
|
240
|
+
if (!this.inScrollMode)
|
|
241
|
+
return;
|
|
242
|
+
this.inScrollMode = false;
|
|
243
|
+
if (this.originalStdoutWrite) {
|
|
244
|
+
this.originalStdoutWrite('\x1b[?25h');
|
|
245
|
+
this.originalStdoutWrite('\x1b[2J\x1b[H');
|
|
246
|
+
}
|
|
247
|
+
const recentLines = this.scrollBuffer.getVisibleLines();
|
|
248
|
+
if (this.originalStdoutWrite) {
|
|
249
|
+
this.originalStdoutWrite(recentLines.join('\n') + '\n');
|
|
250
|
+
}
|
|
251
|
+
this.rl.resume();
|
|
252
|
+
this.prompt();
|
|
253
|
+
}
|
|
254
|
+
renderScrollView() {
|
|
255
|
+
if (!this.originalStdoutWrite)
|
|
256
|
+
return;
|
|
257
|
+
const rows = process.stdout.rows || 24;
|
|
258
|
+
const cols = process.stdout.columns || 80;
|
|
259
|
+
const visibleLines = this.scrollBuffer.getVisibleLines();
|
|
260
|
+
const info = this.scrollBuffer.getScrollInfo();
|
|
261
|
+
this.originalStdoutWrite('\x1b[2J\x1b[H');
|
|
262
|
+
for (let i = 0; i < visibleLines.length && i < rows - 1; i++) {
|
|
263
|
+
const line = visibleLines[i] || '';
|
|
264
|
+
const truncated = line.length > cols ? line.slice(0, cols - 1) + '…' : line;
|
|
265
|
+
this.originalStdoutWrite(truncated + '\n');
|
|
266
|
+
}
|
|
267
|
+
const scrollInfo = this.scrollBuffer.isScrolledUp
|
|
268
|
+
? colors.yellow(`↑ ${this.scrollBuffer.position} lines | ${info.percent}% | `)
|
|
269
|
+
: '';
|
|
270
|
+
const helpText = colors.gray('Page Up/Down • Home/End • Esc to exit');
|
|
271
|
+
const statusBar = `\x1b[${rows};1H\x1b[7m ${scrollInfo}${helpText} \x1b[0m`;
|
|
272
|
+
this.originalStdoutWrite(statusBar);
|
|
118
273
|
}
|
|
119
274
|
prompt() {
|
|
120
275
|
this.rl.setPrompt(this.getPrompt());
|
|
121
276
|
this.rl.prompt();
|
|
122
277
|
}
|
|
123
278
|
async handleCommand(input) {
|
|
279
|
+
if (input.endsWith('?') && !input.startsWith('?') && input.length > 1) {
|
|
280
|
+
await this.runSearch(input.slice(0, -1).trim());
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
124
283
|
if (input.includes('=') && !input.includes(' ') && !input.startsWith('http')) {
|
|
125
284
|
}
|
|
126
285
|
const parts = this.parseLine(input);
|
|
@@ -165,6 +324,9 @@ export class RekShell {
|
|
|
165
324
|
case 'dns':
|
|
166
325
|
await this.runDNS(parts[1]);
|
|
167
326
|
return;
|
|
327
|
+
case 'dns:propagate':
|
|
328
|
+
await this.runDNSPropagation(parts[1], parts[2]);
|
|
329
|
+
return;
|
|
168
330
|
case 'rdap':
|
|
169
331
|
await this.runRDAP(parts[1]);
|
|
170
332
|
return;
|
|
@@ -650,25 +812,56 @@ export class RekShell {
|
|
|
650
812
|
const duration = Math.round(performance.now() - startTime);
|
|
651
813
|
const statusIcon = info.valid ? colors.green('✔') : colors.red('✖');
|
|
652
814
|
const statusText = info.valid ? colors.green('Valid') : colors.red('Invalid/Expired');
|
|
653
|
-
console.log(`${statusIcon} Certificate ${statusText}` + colors.gray(` (${duration}ms)\n`));
|
|
654
|
-
console.log(colors.bold(' Certificate:'));
|
|
655
|
-
console.log(` ${colors.cyan('Subject')}: ${info.subject?.CN || info.subject?.O || 'N/A'}`);
|
|
656
|
-
console.log(` ${colors.cyan('Issuer')}: ${info.issuer?.CN || info.issuer?.O || 'N/A'}`);
|
|
657
|
-
console.log(` ${colors.cyan('Valid From')}: ${info.validFrom.toISOString()}`);
|
|
658
|
-
console.log(` ${colors.cyan('Valid To')}: ${info.validTo.toISOString()}`);
|
|
659
815
|
const daysColor = info.daysRemaining < 30 ? colors.red : info.daysRemaining < 90 ? colors.yellow : colors.green;
|
|
660
|
-
console.log(
|
|
661
|
-
console.log(colors.
|
|
662
|
-
console.log(
|
|
663
|
-
console.log(`
|
|
664
|
-
|
|
816
|
+
console.log(`\n${colors.bold(colors.cyan('🔒 TLS/SSL Report'))}`);
|
|
817
|
+
console.log(`${statusIcon} Certificate ${statusText}` + colors.gray(` (${duration}ms)\n`));
|
|
818
|
+
console.log(colors.bold('Certificate:'));
|
|
819
|
+
console.log(` ${colors.gray('Subject:')}`);
|
|
820
|
+
for (const key of Object.keys(info.subject || {})) {
|
|
821
|
+
console.log(` ${colors.gray(key.padEnd(10))}: ${info.subject[key]}`);
|
|
822
|
+
}
|
|
823
|
+
console.log(` ${colors.gray('Issuer:')}`);
|
|
824
|
+
for (const key of Object.keys(info.issuer || {})) {
|
|
825
|
+
console.log(` ${colors.gray(key.padEnd(10))}: ${info.issuer[key]}`);
|
|
826
|
+
}
|
|
827
|
+
console.log(` ${colors.gray('Expires:')} ${daysColor(info.daysRemaining + ' days')} (${info.validTo.toISOString().split('T')[0]})`);
|
|
828
|
+
console.log(` ${colors.gray('Valid From:')} ${info.validFrom.toISOString().split('T')[0]}`);
|
|
829
|
+
console.log(` ${colors.gray('Valid To:')} ${info.validTo.toISOString().split('T')[0]}`);
|
|
830
|
+
console.log(` ${colors.gray('Valid:')} ${info.valid ? colors.green('Yes') : colors.red('No')}`);
|
|
831
|
+
if (info.altNames && info.altNames.length > 0) {
|
|
832
|
+
console.log(colors.bold('\nSubject Alternative Names (SANs):'));
|
|
833
|
+
for (const name of info.altNames) {
|
|
834
|
+
console.log(` ${colors.cyan('→')} ${name}`);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
console.log(colors.bold('\nPublic Key:'));
|
|
838
|
+
if (info.pubkey) {
|
|
839
|
+
console.log(` ${colors.gray('Algorithm:')} ${info.pubkey.algo}`);
|
|
840
|
+
console.log(` ${colors.gray('Size:')} ${info.pubkey.size} bits`);
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
console.log(' Not available');
|
|
844
|
+
}
|
|
845
|
+
console.log(colors.bold('\nExtended Key Usage:'));
|
|
846
|
+
if (info.extKeyUsage && info.extKeyUsage.length > 0) {
|
|
847
|
+
for (const oid of info.extKeyUsage) {
|
|
848
|
+
console.log(` ${colors.cyan('→')} ${oid}`);
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
console.log(' None');
|
|
853
|
+
}
|
|
854
|
+
console.log(colors.bold('\nConnection:'));
|
|
855
|
+
console.log(` ${colors.gray('Protocol:')} ${info.protocol || 'N/A'}`);
|
|
856
|
+
console.log(` ${colors.gray('Cipher:')} ${info.cipher?.name || 'N/A'}`);
|
|
857
|
+
console.log(` ${colors.gray('Auth:')} ${info.authorized ? colors.green('Trusted') : colors.red('Untrusted')}`);
|
|
665
858
|
if (info.authorizationError) {
|
|
666
|
-
console.log(`
|
|
859
|
+
console.log(` ${colors.gray('Auth Error:')} ${colors.red(String(info.authorizationError))}`);
|
|
667
860
|
}
|
|
668
|
-
console.log(colors.bold('\
|
|
669
|
-
console.log(`
|
|
670
|
-
console.log(`
|
|
671
|
-
console.log(`
|
|
861
|
+
console.log(colors.bold('\nFingerprints:'));
|
|
862
|
+
console.log(` ${colors.gray('SHA1:')} ${info.fingerprint}`);
|
|
863
|
+
console.log(` ${colors.gray('SHA256:')} ${info.fingerprint256}`);
|
|
864
|
+
console.log(` ${colors.gray('Serial:')} ${info.serialNumber}`);
|
|
672
865
|
this.lastResponse = info;
|
|
673
866
|
}
|
|
674
867
|
catch (error) {
|
|
@@ -736,6 +929,27 @@ export class RekShell {
|
|
|
736
929
|
}
|
|
737
930
|
console.log('');
|
|
738
931
|
}
|
|
932
|
+
async runDNSPropagation(domain, type = 'A') {
|
|
933
|
+
if (!domain) {
|
|
934
|
+
domain = this.getBaseDomain() || '';
|
|
935
|
+
if (!domain) {
|
|
936
|
+
console.log(colors.yellow('Usage: dns:propagate <domain> [type]'));
|
|
937
|
+
console.log(colors.gray(' Examples: dns:propagate google.com | dns:propagate github.com TXT'));
|
|
938
|
+
console.log(colors.gray(' Or set a base URL first: url https://example.com'));
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
console.log(colors.gray(`Checking DNS propagation for ${domain} (${type})...`));
|
|
943
|
+
try {
|
|
944
|
+
const { checkPropagation, formatPropagationReport } = await import('../../dns/propagation.js');
|
|
945
|
+
const results = await checkPropagation(domain, type);
|
|
946
|
+
console.log(formatPropagationReport(results, domain, type));
|
|
947
|
+
this.lastResponse = results;
|
|
948
|
+
}
|
|
949
|
+
catch (error) {
|
|
950
|
+
console.error(colors.red(`Propagation check failed: ${error.message}`));
|
|
951
|
+
}
|
|
952
|
+
}
|
|
739
953
|
async runRDAP(domain) {
|
|
740
954
|
if (!domain) {
|
|
741
955
|
domain = this.getRootDomain() || '';
|
|
@@ -1660,38 +1874,14 @@ export class RekShell {
|
|
|
1660
1874
|
console.log('');
|
|
1661
1875
|
}
|
|
1662
1876
|
async runSearch(query) {
|
|
1663
|
-
if (!query.trim()) {
|
|
1664
|
-
console.log(colors.yellow('Usage: ? <query> or search <query>'));
|
|
1665
|
-
console.log(colors.gray(' Examples:'));
|
|
1666
|
-
console.log(colors.gray(' ? retry exponential backoff'));
|
|
1667
|
-
console.log(colors.gray(' search cache configuration'));
|
|
1668
|
-
return;
|
|
1669
|
-
}
|
|
1670
|
-
console.log(colors.gray('Searching documentation...'));
|
|
1671
1877
|
try {
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
console.log(colors.yellow(`No results for: "${query}"`));
|
|
1676
|
-
console.log(colors.gray('Try different keywords like: retry, cache, streaming, websocket, pagination'));
|
|
1677
|
-
return;
|
|
1678
|
-
}
|
|
1679
|
-
console.log(colors.bold(colors.cyan(`\nFound ${results.length} results for "${query}":\n`)));
|
|
1680
|
-
for (let i = 0; i < results.length; i++) {
|
|
1681
|
-
const result = results[i];
|
|
1682
|
-
const score = Math.round(result.score * 100);
|
|
1683
|
-
console.log(` ${colors.green(`${i + 1}.`)} ${colors.bold(result.title)} ${colors.gray(`(${score}%)`)}`);
|
|
1684
|
-
console.log(` ${colors.gray(result.path)}`);
|
|
1685
|
-
if (result.snippet) {
|
|
1686
|
-
const snippet = result.snippet.slice(0, 120).replace(/\n/g, ' ');
|
|
1687
|
-
console.log(` ${colors.gray(snippet)}${result.snippet.length > 120 ? '...' : ''}`);
|
|
1688
|
-
}
|
|
1689
|
-
console.log('');
|
|
1690
|
-
}
|
|
1691
|
-
console.log(colors.gray(' Tip: Use "get_doc <path>" to read full documentation'));
|
|
1878
|
+
this.rl.pause();
|
|
1879
|
+
await openSearchPanel(query.trim() || undefined);
|
|
1880
|
+
this.rl.resume();
|
|
1692
1881
|
}
|
|
1693
1882
|
catch (error) {
|
|
1694
1883
|
console.error(colors.red(`Search failed: ${error.message}`));
|
|
1884
|
+
this.rl.resume();
|
|
1695
1885
|
}
|
|
1696
1886
|
}
|
|
1697
1887
|
async runSuggest(useCase) {
|
|
@@ -1834,6 +2024,12 @@ export class RekShell {
|
|
|
1834
2024
|
${colors.green('suggest <use-case>')} Get implementation suggestions.
|
|
1835
2025
|
${colors.green('example <feature>')} Get code examples for a feature.
|
|
1836
2026
|
|
|
2027
|
+
${colors.bold('Navigation:')}
|
|
2028
|
+
${colors.green('Page Up/Down')} Scroll through command history.
|
|
2029
|
+
${colors.green('Home/End')} Jump to top/bottom of history.
|
|
2030
|
+
${colors.green('Mouse Scroll')} Scroll with mouse wheel.
|
|
2031
|
+
${colors.green('Escape')} Exit scroll mode.
|
|
2032
|
+
|
|
1837
2033
|
${colors.bold('Examples:')}
|
|
1838
2034
|
› url httpbin.org
|
|
1839
2035
|
› get /json
|
package/dist/contract/index.js
CHANGED
|
@@ -49,14 +49,15 @@ export function createContract(client, contract) {
|
|
|
49
49
|
if (endpoint.errors && err instanceof HttpError && err.response) {
|
|
50
50
|
const schema = endpoint.errors[err.status];
|
|
51
51
|
if (schema) {
|
|
52
|
+
let parsedError;
|
|
52
53
|
try {
|
|
53
54
|
const errorBody = await err.response.json();
|
|
54
|
-
|
|
55
|
-
throw new ContractError(err.status, parsedError, err);
|
|
55
|
+
parsedError = schema.parse(errorBody);
|
|
56
56
|
}
|
|
57
57
|
catch (parseErr) {
|
|
58
58
|
throw err;
|
|
59
59
|
}
|
|
60
|
+
throw new ContractError(err.status, parsedError, err);
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
throw err;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type DnsSecurityRecords } from '../utils/dns-toolkit.js';
|
|
2
|
+
export { createLookupFunction, customDNSLookup } from '../utils/dns.js';
|
|
3
|
+
export { createDoHLookup } from '../utils/doh.js';
|
|
4
|
+
export { getSecurityRecords, type DnsSecurityRecords } from '../utils/dns-toolkit.js';
|
|
5
|
+
export { checkPropagation, type PropagationResult, type DnsRecord, formatPropagationReport } from './propagation.js';
|
|
6
|
+
export type { DNSOptions } from '../types/index.js';
|
|
7
|
+
export type RecordType = 'A' | 'AAAA' | 'CNAME' | 'MX' | 'TXT' | 'NS' | 'SOA' | 'SRV' | 'CAA' | 'PTR';
|
|
8
|
+
export type DoHProvider = 'cloudflare' | 'google' | 'quad9' | 'system';
|
|
9
|
+
export interface DNSClientOptions {
|
|
10
|
+
provider?: DoHProvider;
|
|
11
|
+
timeout?: number;
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
servers?: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare class DNSClient {
|
|
16
|
+
private options;
|
|
17
|
+
constructor(options?: DNSClientOptions);
|
|
18
|
+
private log;
|
|
19
|
+
resolve(hostname: string, type?: RecordType): Promise<string[]>;
|
|
20
|
+
resolve4(hostname: string): Promise<string[]>;
|
|
21
|
+
resolve6(hostname: string): Promise<string[]>;
|
|
22
|
+
resolveMx(hostname: string): Promise<{
|
|
23
|
+
priority: number;
|
|
24
|
+
exchange: string;
|
|
25
|
+
}[]>;
|
|
26
|
+
resolveTxt(hostname: string): Promise<string[]>;
|
|
27
|
+
resolveNs(hostname: string): Promise<string[]>;
|
|
28
|
+
resolveSoa(hostname: string): Promise<import("dns").SoaRecord>;
|
|
29
|
+
resolveSrv(hostname: string): Promise<import("dns").SrvRecord[]>;
|
|
30
|
+
resolveCaa(hostname: string): Promise<import("dns").CaaRecord[]>;
|
|
31
|
+
reverse(ip: string): Promise<string[]>;
|
|
32
|
+
resolveAll(hostname: string): Promise<Record<string, unknown[]>>;
|
|
33
|
+
getSecurityRecords(domain: string): Promise<DnsSecurityRecords>;
|
|
34
|
+
}
|
|
35
|
+
export declare function createDNS(options?: DNSClientOptions): DNSClient;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dns/index.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAgD,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGhH,OAAO,EAAE,oBAAoB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,KAAK,SAAS,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACrH,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAKpD,MAAM,MAAM,UAAU,GAAG,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;AAKtG,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAKvE,MAAM,WAAW,gBAAgB;IAK/B,QAAQ,CAAC,EAAE,WAAW,CAAC;IAMvB,OAAO,CAAC,EAAE,MAAM,CAAC;IAMjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAKhB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAqBD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;gBAEhC,OAAO,GAAE,gBAAqB;IAc1C,OAAO,CAAC,GAAG;IASL,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAE,UAAgB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiD1E,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAO7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAO7C,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAOxE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAQrD,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAO9C,UAAU,CAAC,QAAQ,EAAE,MAAM;IAO3B,UAAU,CAAC,QAAQ,EAAE,MAAM;IAO3B,UAAU,CAAC,QAAQ,EAAE,MAAM;IAO3B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAOhC,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IA4BhE,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAItE;AA0BD,wBAAgB,SAAS,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAE/D"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { promises as nodeDns } from 'node:dns';
|
|
2
|
+
import { getSecurityRecords as getSecurityRecordsUtil } from '../utils/dns-toolkit.js';
|
|
3
|
+
export { createLookupFunction, customDNSLookup } from '../utils/dns.js';
|
|
4
|
+
export { createDoHLookup } from '../utils/doh.js';
|
|
5
|
+
export { getSecurityRecords } from '../utils/dns-toolkit.js';
|
|
6
|
+
export { checkPropagation, formatPropagationReport } from './propagation.js';
|
|
7
|
+
export class DNSClient {
|
|
8
|
+
options;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.options = {
|
|
11
|
+
provider: options.provider ?? 'system',
|
|
12
|
+
timeout: options.timeout ?? 5000,
|
|
13
|
+
debug: options.debug ?? false,
|
|
14
|
+
servers: options.servers ?? [],
|
|
15
|
+
};
|
|
16
|
+
if (this.options.servers.length > 0 && this.options.provider === 'system') {
|
|
17
|
+
nodeDns.setServers(this.options.servers);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
log(message, ...args) {
|
|
21
|
+
if (this.options.debug) {
|
|
22
|
+
console.log(`[DNS] ${message}`, ...args);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async resolve(hostname, type = 'A') {
|
|
26
|
+
this.log(`Resolving ${hostname} (${type})`);
|
|
27
|
+
const start = Date.now();
|
|
28
|
+
try {
|
|
29
|
+
let result;
|
|
30
|
+
switch (type) {
|
|
31
|
+
case 'A':
|
|
32
|
+
result = await nodeDns.resolve4(hostname);
|
|
33
|
+
break;
|
|
34
|
+
case 'AAAA':
|
|
35
|
+
result = await nodeDns.resolve6(hostname);
|
|
36
|
+
break;
|
|
37
|
+
case 'CNAME':
|
|
38
|
+
result = await nodeDns.resolveCname(hostname);
|
|
39
|
+
break;
|
|
40
|
+
case 'NS':
|
|
41
|
+
result = await nodeDns.resolveNs(hostname);
|
|
42
|
+
break;
|
|
43
|
+
case 'PTR':
|
|
44
|
+
result = await nodeDns.resolvePtr(hostname);
|
|
45
|
+
break;
|
|
46
|
+
case 'TXT': {
|
|
47
|
+
const txt = await nodeDns.resolveTxt(hostname);
|
|
48
|
+
result = txt.map(chunks => chunks.join(''));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
default: {
|
|
52
|
+
const records = await nodeDns.resolve(hostname, type);
|
|
53
|
+
if (Array.isArray(records)) {
|
|
54
|
+
result = records.map(r => typeof r === 'string' ? r : JSON.stringify(r));
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
result = [JSON.stringify(records)];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
this.log(`Resolved ${hostname} in ${Date.now() - start}ms:`, result);
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
this.log(`Failed to resolve ${hostname}:`, error);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
resolve4(hostname) {
|
|
70
|
+
return nodeDns.resolve4(hostname);
|
|
71
|
+
}
|
|
72
|
+
resolve6(hostname) {
|
|
73
|
+
return nodeDns.resolve6(hostname);
|
|
74
|
+
}
|
|
75
|
+
resolveMx(hostname) {
|
|
76
|
+
return nodeDns.resolveMx(hostname);
|
|
77
|
+
}
|
|
78
|
+
async resolveTxt(hostname) {
|
|
79
|
+
const records = await nodeDns.resolveTxt(hostname);
|
|
80
|
+
return records.map(chunks => chunks.join(''));
|
|
81
|
+
}
|
|
82
|
+
resolveNs(hostname) {
|
|
83
|
+
return nodeDns.resolveNs(hostname);
|
|
84
|
+
}
|
|
85
|
+
resolveSoa(hostname) {
|
|
86
|
+
return nodeDns.resolveSoa(hostname);
|
|
87
|
+
}
|
|
88
|
+
resolveSrv(hostname) {
|
|
89
|
+
return nodeDns.resolveSrv(hostname);
|
|
90
|
+
}
|
|
91
|
+
resolveCaa(hostname) {
|
|
92
|
+
return nodeDns.resolveCaa(hostname);
|
|
93
|
+
}
|
|
94
|
+
reverse(ip) {
|
|
95
|
+
return nodeDns.reverse(ip);
|
|
96
|
+
}
|
|
97
|
+
async resolveAll(hostname) {
|
|
98
|
+
this.log(`Resolving all records for ${hostname}`);
|
|
99
|
+
const results = {};
|
|
100
|
+
const tryResolve = async (type, fn) => {
|
|
101
|
+
try {
|
|
102
|
+
results[type] = await fn();
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
await Promise.all([
|
|
108
|
+
tryResolve('A', () => nodeDns.resolve4(hostname)),
|
|
109
|
+
tryResolve('AAAA', () => nodeDns.resolve6(hostname)),
|
|
110
|
+
tryResolve('MX', () => nodeDns.resolveMx(hostname)),
|
|
111
|
+
tryResolve('TXT', () => nodeDns.resolveTxt(hostname)),
|
|
112
|
+
tryResolve('NS', () => nodeDns.resolveNs(hostname)),
|
|
113
|
+
tryResolve('CAA', () => nodeDns.resolveCaa(hostname)),
|
|
114
|
+
]);
|
|
115
|
+
this.log(`Resolved all for ${hostname}:`, Object.keys(results));
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
118
|
+
async getSecurityRecords(domain) {
|
|
119
|
+
this.log(`Getting security records for ${domain}`);
|
|
120
|
+
return getSecurityRecordsUtil(domain);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export function createDNS(options) {
|
|
124
|
+
return new DNSClient(options);
|
|
125
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface DnsRecord {
|
|
2
|
+
name: string;
|
|
3
|
+
type: number;
|
|
4
|
+
TTL: number;
|
|
5
|
+
data: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PropagationResult {
|
|
8
|
+
id: string;
|
|
9
|
+
provider: string;
|
|
10
|
+
status: 'ok' | 'error';
|
|
11
|
+
records: string[];
|
|
12
|
+
rawRecords: DnsRecord[];
|
|
13
|
+
latency: number;
|
|
14
|
+
error?: string;
|
|
15
|
+
location?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function checkPropagation(domain: string, type?: string): Promise<PropagationResult[]>;
|
|
18
|
+
export declare function formatPropagationReport(results: PropagationResult[], domain: string, type: string): string;
|
|
19
|
+
//# sourceMappingURL=propagation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propagation.d.ts","sourceRoot":"","sources":["../../src/dns/propagation.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA8BD,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,MAAY,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAyEvG;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAqD1G"}
|