recker 1.0.14 → 1.0.15-next.0e216c0

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 (79) hide show
  1. package/README.md +78 -100
  2. package/dist/ai/client.d.ts +2 -3
  3. package/dist/ai/client.d.ts.map +1 -1
  4. package/dist/ai/client.js +5 -6
  5. package/dist/ai/index.d.ts +1 -1
  6. package/dist/ai/index.d.ts.map +1 -1
  7. package/dist/ai/index.js +1 -1
  8. package/dist/bench/generator.d.ts.map +1 -1
  9. package/dist/bench/generator.js +2 -1
  10. package/dist/bench/stats.d.ts +15 -1
  11. package/dist/bench/stats.d.ts.map +1 -1
  12. package/dist/bench/stats.js +84 -5
  13. package/dist/cli/index.js +21 -0
  14. package/dist/cli/tui/ai-chat.js +2 -2
  15. package/dist/cli/tui/load-dashboard.d.ts.map +1 -1
  16. package/dist/cli/tui/load-dashboard.js +62 -8
  17. package/dist/cli/tui/scroll-buffer.d.ts +43 -0
  18. package/dist/cli/tui/scroll-buffer.d.ts.map +1 -0
  19. package/dist/cli/tui/scroll-buffer.js +162 -0
  20. package/dist/cli/tui/search-panel.d.ts +41 -0
  21. package/dist/cli/tui/search-panel.d.ts.map +1 -0
  22. package/dist/cli/tui/search-panel.js +419 -0
  23. package/dist/cli/tui/shell.d.ts +11 -0
  24. package/dist/cli/tui/shell.d.ts.map +1 -1
  25. package/dist/cli/tui/shell.js +236 -46
  26. package/dist/contract/index.js +3 -2
  27. package/dist/dns/index.d.ts +36 -0
  28. package/dist/dns/index.d.ts.map +1 -0
  29. package/dist/dns/index.js +125 -0
  30. package/dist/dns/propagation.d.ts +19 -0
  31. package/dist/dns/propagation.d.ts.map +1 -0
  32. package/dist/dns/propagation.js +129 -0
  33. package/dist/index.d.ts +2 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -0
  36. package/dist/mcp/embeddings-loader.d.ts +18 -0
  37. package/dist/mcp/embeddings-loader.d.ts.map +1 -0
  38. package/dist/mcp/embeddings-loader.js +152 -0
  39. package/dist/mcp/index.d.ts +1 -0
  40. package/dist/mcp/index.d.ts.map +1 -1
  41. package/dist/mcp/index.js +1 -0
  42. package/dist/mcp/search/hybrid-search.d.ts.map +1 -1
  43. package/dist/mcp/search/hybrid-search.js +7 -21
  44. package/dist/mcp/server.d.ts +2 -0
  45. package/dist/mcp/server.d.ts.map +1 -1
  46. package/dist/mcp/server.js +8 -1
  47. package/dist/recker.d.ts +47 -0
  48. package/dist/recker.d.ts.map +1 -0
  49. package/dist/recker.js +99 -0
  50. package/dist/transport/base-udp.d.ts.map +1 -1
  51. package/dist/transport/base-udp.js +1 -0
  52. package/dist/transport/udp-response.d.ts +2 -2
  53. package/dist/transport/udp-response.d.ts.map +1 -1
  54. package/dist/transport/udp-response.js +2 -2
  55. package/dist/transport/udp.d.ts +4 -3
  56. package/dist/transport/udp.d.ts.map +1 -1
  57. package/dist/transport/udp.js +16 -7
  58. package/dist/types/udp.d.ts +1 -0
  59. package/dist/types/udp.d.ts.map +1 -1
  60. package/dist/udp/index.d.ts +2 -2
  61. package/dist/udp/index.d.ts.map +1 -1
  62. package/dist/udp/index.js +2 -2
  63. package/dist/utils/colors.d.ts +16 -0
  64. package/dist/utils/colors.d.ts.map +1 -1
  65. package/dist/utils/colors.js +16 -0
  66. package/dist/utils/tls-inspector.d.ts +6 -0
  67. package/dist/utils/tls-inspector.d.ts.map +1 -1
  68. package/dist/utils/tls-inspector.js +35 -1
  69. package/dist/utils/whois.d.ts +18 -0
  70. package/dist/utils/whois.d.ts.map +1 -1
  71. package/dist/utils/whois.js +63 -0
  72. package/dist/webrtc/index.d.ts +80 -0
  73. package/dist/webrtc/index.d.ts.map +1 -0
  74. package/dist/webrtc/index.js +311 -0
  75. package/dist/websocket/client.d.ts +1 -1
  76. package/dist/websocket/client.d.ts.map +1 -1
  77. package/dist/websocket/client.js +1 -1
  78. package/package.json +2 -2
  79. package/dist/mcp/data/embeddings.json +0 -1
@@ -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":"AAoCA,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;;YAWrB,iBAAiB;IAe/B,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,SAAS;IAcJ,KAAK;IA8BlB,OAAO,CAAC,MAAM;YAKA,aAAa;YAwLb,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;YA2DN,MAAM;YA2EN,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;YA2CT,UAAU;YAuBV,UAAU;IAwBxB,OAAO,CAAC,aAAa;IAuCrB,OAAO,CAAC,SAAS;CAwElB"}
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;IA2B7B,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"}
@@ -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,159 @@ 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
+ process.stdin.on('data', (data) => {
156
+ const scrollKey = parseScrollKey(data);
157
+ if (scrollKey) {
158
+ this.handleScrollKey(scrollKey);
159
+ return;
160
+ }
161
+ const mouseScroll = parseMouseScroll(data);
162
+ if (mouseScroll) {
163
+ this.handleScrollKey(mouseScroll);
164
+ return;
165
+ }
166
+ });
167
+ }
168
+ }
169
+ handleScrollKey(key) {
170
+ let needsRedraw = false;
171
+ switch (key) {
172
+ case 'pageUp':
173
+ if (!this.inScrollMode) {
174
+ this.enterScrollMode();
175
+ }
176
+ needsRedraw = this.scrollBuffer.pageUp();
177
+ break;
178
+ case 'pageDown':
179
+ needsRedraw = this.scrollBuffer.pageDown();
180
+ if (!this.scrollBuffer.isScrolledUp && this.inScrollMode) {
181
+ this.exitScrollMode();
182
+ return;
183
+ }
184
+ break;
185
+ case 'scrollUp':
186
+ if (!this.inScrollMode) {
187
+ this.enterScrollMode();
188
+ }
189
+ needsRedraw = this.scrollBuffer.scrollUp(3);
190
+ break;
191
+ case 'scrollDown':
192
+ needsRedraw = this.scrollBuffer.scrollDown(3);
193
+ if (!this.scrollBuffer.isScrolledUp && this.inScrollMode) {
194
+ this.exitScrollMode();
195
+ return;
196
+ }
197
+ break;
198
+ case 'home':
199
+ if (!this.inScrollMode) {
200
+ this.enterScrollMode();
201
+ }
202
+ this.scrollBuffer.scrollToTop();
203
+ needsRedraw = true;
204
+ break;
205
+ case 'end':
206
+ this.scrollBuffer.scrollToBottom();
207
+ if (this.inScrollMode) {
208
+ this.exitScrollMode();
209
+ return;
210
+ }
211
+ break;
212
+ case 'escape':
213
+ if (this.inScrollMode) {
214
+ this.exitScrollMode();
215
+ return;
216
+ }
217
+ break;
218
+ }
219
+ if (needsRedraw && this.inScrollMode) {
220
+ this.renderScrollView();
221
+ }
222
+ }
223
+ enterScrollMode() {
224
+ if (this.inScrollMode)
225
+ return;
226
+ this.inScrollMode = true;
227
+ this.rl.pause();
228
+ if (this.originalStdoutWrite) {
229
+ this.originalStdoutWrite('\x1b[?25l');
230
+ }
231
+ this.renderScrollView();
232
+ }
233
+ exitScrollMode() {
234
+ if (!this.inScrollMode)
235
+ return;
236
+ this.inScrollMode = false;
237
+ if (this.originalStdoutWrite) {
238
+ this.originalStdoutWrite('\x1b[?25h');
239
+ this.originalStdoutWrite('\x1b[2J\x1b[H');
240
+ }
241
+ const recentLines = this.scrollBuffer.getVisibleLines();
242
+ if (this.originalStdoutWrite) {
243
+ this.originalStdoutWrite(recentLines.join('\n') + '\n');
244
+ }
245
+ this.rl.resume();
246
+ this.prompt();
247
+ }
248
+ renderScrollView() {
249
+ if (!this.originalStdoutWrite)
250
+ return;
251
+ const rows = process.stdout.rows || 24;
252
+ const cols = process.stdout.columns || 80;
253
+ const visibleLines = this.scrollBuffer.getVisibleLines();
254
+ const info = this.scrollBuffer.getScrollInfo();
255
+ this.originalStdoutWrite('\x1b[2J\x1b[H');
256
+ for (let i = 0; i < visibleLines.length && i < rows - 1; i++) {
257
+ const line = visibleLines[i] || '';
258
+ const truncated = line.length > cols ? line.slice(0, cols - 1) + '…' : line;
259
+ this.originalStdoutWrite(truncated + '\n');
260
+ }
261
+ const scrollInfo = this.scrollBuffer.isScrolledUp
262
+ ? colors.yellow(`↑ ${this.scrollBuffer.position} lines | ${info.percent}% | `)
263
+ : '';
264
+ const helpText = colors.gray('Page Up/Down • Home/End • Esc to exit');
265
+ const statusBar = `\x1b[${rows};1H\x1b[7m ${scrollInfo}${helpText} \x1b[0m`;
266
+ this.originalStdoutWrite(statusBar);
118
267
  }
119
268
  prompt() {
120
269
  this.rl.setPrompt(this.getPrompt());
121
270
  this.rl.prompt();
122
271
  }
123
272
  async handleCommand(input) {
273
+ if (input.endsWith('?') && !input.startsWith('?') && input.length > 1) {
274
+ await this.runSearch(input.slice(0, -1).trim());
275
+ return;
276
+ }
124
277
  if (input.includes('=') && !input.includes(' ') && !input.startsWith('http')) {
125
278
  }
126
279
  const parts = this.parseLine(input);
@@ -165,6 +318,9 @@ export class RekShell {
165
318
  case 'dns':
166
319
  await this.runDNS(parts[1]);
167
320
  return;
321
+ case 'dns:propagate':
322
+ await this.runDNSPropagation(parts[1], parts[2]);
323
+ return;
168
324
  case 'rdap':
169
325
  await this.runRDAP(parts[1]);
170
326
  return;
@@ -650,25 +806,56 @@ export class RekShell {
650
806
  const duration = Math.round(performance.now() - startTime);
651
807
  const statusIcon = info.valid ? colors.green('✔') : colors.red('✖');
652
808
  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
809
  const daysColor = info.daysRemaining < 30 ? colors.red : info.daysRemaining < 90 ? colors.yellow : colors.green;
660
- console.log(` ${colors.cyan('Days Remaining')}: ${daysColor(String(info.daysRemaining))}`);
661
- console.log(colors.bold('\n Connection:'));
662
- console.log(` ${colors.cyan('Protocol')}: ${info.protocol || 'N/A'}`);
663
- console.log(` ${colors.cyan('Cipher')}: ${info.cipher?.name || 'N/A'}`);
664
- console.log(` ${colors.cyan('Authorized')}: ${info.authorized ? colors.green('Yes') : colors.red('No')}`);
810
+ console.log(`\n${colors.bold(colors.cyan('🔒 TLS/SSL Report'))}`);
811
+ console.log(`${statusIcon} Certificate ${statusText}` + colors.gray(` (${duration}ms)\n`));
812
+ console.log(colors.bold('Certificate:'));
813
+ console.log(` ${colors.gray('Subject:')}`);
814
+ for (const key of Object.keys(info.subject || {})) {
815
+ console.log(` ${colors.gray(key.padEnd(10))}: ${info.subject[key]}`);
816
+ }
817
+ console.log(` ${colors.gray('Issuer:')}`);
818
+ for (const key of Object.keys(info.issuer || {})) {
819
+ console.log(` ${colors.gray(key.padEnd(10))}: ${info.issuer[key]}`);
820
+ }
821
+ console.log(` ${colors.gray('Expires:')} ${daysColor(info.daysRemaining + ' days')} (${info.validTo.toISOString().split('T')[0]})`);
822
+ console.log(` ${colors.gray('Valid From:')} ${info.validFrom.toISOString().split('T')[0]}`);
823
+ console.log(` ${colors.gray('Valid To:')} ${info.validTo.toISOString().split('T')[0]}`);
824
+ console.log(` ${colors.gray('Valid:')} ${info.valid ? colors.green('Yes') : colors.red('No')}`);
825
+ if (info.altNames && info.altNames.length > 0) {
826
+ console.log(colors.bold('\nSubject Alternative Names (SANs):'));
827
+ for (const name of info.altNames) {
828
+ console.log(` ${colors.cyan('→')} ${name}`);
829
+ }
830
+ }
831
+ console.log(colors.bold('\nPublic Key:'));
832
+ if (info.pubkey) {
833
+ console.log(` ${colors.gray('Algorithm:')} ${info.pubkey.algo}`);
834
+ console.log(` ${colors.gray('Size:')} ${info.pubkey.size} bits`);
835
+ }
836
+ else {
837
+ console.log(' Not available');
838
+ }
839
+ console.log(colors.bold('\nExtended Key Usage:'));
840
+ if (info.extKeyUsage && info.extKeyUsage.length > 0) {
841
+ for (const oid of info.extKeyUsage) {
842
+ console.log(` ${colors.cyan('→')} ${oid}`);
843
+ }
844
+ }
845
+ else {
846
+ console.log(' None');
847
+ }
848
+ console.log(colors.bold('\nConnection:'));
849
+ console.log(` ${colors.gray('Protocol:')} ${info.protocol || 'N/A'}`);
850
+ console.log(` ${colors.gray('Cipher:')} ${info.cipher?.name || 'N/A'}`);
851
+ console.log(` ${colors.gray('Auth:')} ${info.authorized ? colors.green('Trusted') : colors.red('Untrusted')}`);
665
852
  if (info.authorizationError) {
666
- console.log(` ${colors.cyan('Auth Error')}: ${colors.red(String(info.authorizationError))}`);
853
+ console.log(` ${colors.gray('Auth Error:')} ${colors.red(String(info.authorizationError))}`);
667
854
  }
668
- console.log(colors.bold('\n Fingerprints:'));
669
- console.log(` ${colors.cyan('SHA1')}: ${info.fingerprint}`);
670
- console.log(` ${colors.cyan('SHA256')}: ${info.fingerprint256}`);
671
- console.log(` ${colors.cyan('Serial')}: ${info.serialNumber}`);
855
+ console.log(colors.bold('\nFingerprints:'));
856
+ console.log(` ${colors.gray('SHA1:')} ${info.fingerprint}`);
857
+ console.log(` ${colors.gray('SHA256:')} ${info.fingerprint256}`);
858
+ console.log(` ${colors.gray('Serial:')} ${info.serialNumber}`);
672
859
  this.lastResponse = info;
673
860
  }
674
861
  catch (error) {
@@ -736,6 +923,27 @@ export class RekShell {
736
923
  }
737
924
  console.log('');
738
925
  }
926
+ async runDNSPropagation(domain, type = 'A') {
927
+ if (!domain) {
928
+ domain = this.getBaseDomain() || '';
929
+ if (!domain) {
930
+ console.log(colors.yellow('Usage: dns:propagate <domain> [type]'));
931
+ console.log(colors.gray(' Examples: dns:propagate google.com | dns:propagate github.com TXT'));
932
+ console.log(colors.gray(' Or set a base URL first: url https://example.com'));
933
+ return;
934
+ }
935
+ }
936
+ console.log(colors.gray(`Checking DNS propagation for ${domain} (${type})...`));
937
+ try {
938
+ const { checkPropagation, formatPropagationReport } = await import('../../dns/propagation.js');
939
+ const results = await checkPropagation(domain, type);
940
+ console.log(formatPropagationReport(results, domain, type));
941
+ this.lastResponse = results;
942
+ }
943
+ catch (error) {
944
+ console.error(colors.red(`Propagation check failed: ${error.message}`));
945
+ }
946
+ }
739
947
  async runRDAP(domain) {
740
948
  if (!domain) {
741
949
  domain = this.getRootDomain() || '';
@@ -1660,38 +1868,14 @@ export class RekShell {
1660
1868
  console.log('');
1661
1869
  }
1662
1870
  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
1871
  try {
1672
- const search = getShellSearch();
1673
- const results = await search.search(query, { limit: 5 });
1674
- if (results.length === 0) {
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'));
1872
+ this.rl.pause();
1873
+ await openSearchPanel(query.trim() || undefined);
1874
+ this.rl.resume();
1692
1875
  }
1693
1876
  catch (error) {
1694
1877
  console.error(colors.red(`Search failed: ${error.message}`));
1878
+ this.rl.resume();
1695
1879
  }
1696
1880
  }
1697
1881
  async runSuggest(useCase) {
@@ -1834,6 +2018,12 @@ export class RekShell {
1834
2018
  ${colors.green('suggest <use-case>')} Get implementation suggestions.
1835
2019
  ${colors.green('example <feature>')} Get code examples for a feature.
1836
2020
 
2021
+ ${colors.bold('Navigation:')}
2022
+ ${colors.green('Page Up/Down')} Scroll through command history.
2023
+ ${colors.green('Home/End')} Jump to top/bottom of history.
2024
+ ${colors.green('Mouse Scroll')} Scroll with mouse wheel.
2025
+ ${colors.green('Escape')} Exit scroll mode.
2026
+
1837
2027
  ${colors.bold('Examples:')}
1838
2028
  › url httpbin.org
1839
2029
  › get /json
@@ -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
- const parsedError = schema.parse(errorBody);
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"}