recker 1.0.2-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 (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +109 -0
  3. package/dist/cache/file-storage.d.ts +13 -0
  4. package/dist/cache/file-storage.d.ts.map +1 -0
  5. package/dist/cache/file-storage.js +50 -0
  6. package/dist/cache/memory-storage.d.ts +10 -0
  7. package/dist/cache/memory-storage.d.ts.map +1 -0
  8. package/dist/cache/memory-storage.js +29 -0
  9. package/dist/cache/redis-storage.d.ts +16 -0
  10. package/dist/cache/redis-storage.d.ts.map +1 -0
  11. package/dist/cache/redis-storage.js +25 -0
  12. package/dist/constants.d.ts +19 -0
  13. package/dist/constants.d.ts.map +1 -0
  14. package/dist/constants.js +18 -0
  15. package/dist/contract/index.d.ts +32 -0
  16. package/dist/contract/index.d.ts.map +1 -0
  17. package/dist/contract/index.js +67 -0
  18. package/dist/core/client.d.ts +107 -0
  19. package/dist/core/client.d.ts.map +1 -0
  20. package/dist/core/client.js +475 -0
  21. package/dist/core/errors.d.ts +19 -0
  22. package/dist/core/errors.d.ts.map +1 -0
  23. package/dist/core/errors.js +34 -0
  24. package/dist/core/request-promise.d.ts +24 -0
  25. package/dist/core/request-promise.d.ts.map +1 -0
  26. package/dist/core/request-promise.js +77 -0
  27. package/dist/core/request.d.ts +15 -0
  28. package/dist/core/request.d.ts.map +1 -0
  29. package/dist/core/request.js +44 -0
  30. package/dist/core/response.d.ts +33 -0
  31. package/dist/core/response.d.ts.map +1 -0
  32. package/dist/core/response.js +154 -0
  33. package/dist/index.d.ts +40 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +39 -0
  36. package/dist/mcp/client.d.ts +59 -0
  37. package/dist/mcp/client.d.ts.map +1 -0
  38. package/dist/mcp/client.js +195 -0
  39. package/dist/mcp/index.d.ts +3 -0
  40. package/dist/mcp/index.d.ts.map +1 -0
  41. package/dist/mcp/index.js +2 -0
  42. package/dist/mcp/types.d.ts +151 -0
  43. package/dist/mcp/types.d.ts.map +1 -0
  44. package/dist/mcp/types.js +1 -0
  45. package/dist/plugins/cache.d.ts +10 -0
  46. package/dist/plugins/cache.d.ts.map +1 -0
  47. package/dist/plugins/cache.js +72 -0
  48. package/dist/plugins/circuit-breaker.d.ts +14 -0
  49. package/dist/plugins/circuit-breaker.d.ts.map +1 -0
  50. package/dist/plugins/circuit-breaker.js +100 -0
  51. package/dist/plugins/compression.d.ts +5 -0
  52. package/dist/plugins/compression.d.ts.map +1 -0
  53. package/dist/plugins/compression.js +128 -0
  54. package/dist/plugins/cookie-jar.d.ts +6 -0
  55. package/dist/plugins/cookie-jar.d.ts.map +1 -0
  56. package/dist/plugins/cookie-jar.js +72 -0
  57. package/dist/plugins/dedup.d.ts +6 -0
  58. package/dist/plugins/dedup.d.ts.map +1 -0
  59. package/dist/plugins/dedup.js +34 -0
  60. package/dist/plugins/graphql.d.ts +13 -0
  61. package/dist/plugins/graphql.d.ts.map +1 -0
  62. package/dist/plugins/graphql.js +39 -0
  63. package/dist/plugins/har-player.d.ts +7 -0
  64. package/dist/plugins/har-player.d.ts.map +1 -0
  65. package/dist/plugins/har-player.js +53 -0
  66. package/dist/plugins/har-recorder.d.ts +7 -0
  67. package/dist/plugins/har-recorder.d.ts.map +1 -0
  68. package/dist/plugins/har-recorder.js +67 -0
  69. package/dist/plugins/logger.d.ts +11 -0
  70. package/dist/plugins/logger.d.ts.map +1 -0
  71. package/dist/plugins/logger.js +72 -0
  72. package/dist/plugins/pagination.d.ts +17 -0
  73. package/dist/plugins/pagination.d.ts.map +1 -0
  74. package/dist/plugins/pagination.js +105 -0
  75. package/dist/plugins/proxy-rotator.d.ts +8 -0
  76. package/dist/plugins/proxy-rotator.d.ts.map +1 -0
  77. package/dist/plugins/proxy-rotator.js +35 -0
  78. package/dist/plugins/rate-limit.d.ts +8 -0
  79. package/dist/plugins/rate-limit.d.ts.map +1 -0
  80. package/dist/plugins/rate-limit.js +57 -0
  81. package/dist/plugins/retry.d.ts +14 -0
  82. package/dist/plugins/retry.d.ts.map +1 -0
  83. package/dist/plugins/retry.js +92 -0
  84. package/dist/plugins/server-timing.d.ts +8 -0
  85. package/dist/plugins/server-timing.d.ts.map +1 -0
  86. package/dist/plugins/server-timing.js +24 -0
  87. package/dist/plugins/xsrf.d.ts +10 -0
  88. package/dist/plugins/xsrf.d.ts.map +1 -0
  89. package/dist/plugins/xsrf.js +48 -0
  90. package/dist/runner/request-runner.d.ts +47 -0
  91. package/dist/runner/request-runner.d.ts.map +1 -0
  92. package/dist/runner/request-runner.js +89 -0
  93. package/dist/transport/fetch.d.ts +6 -0
  94. package/dist/transport/fetch.d.ts.map +1 -0
  95. package/dist/transport/fetch.js +153 -0
  96. package/dist/transport/undici.d.ts +23 -0
  97. package/dist/transport/undici.d.ts.map +1 -0
  98. package/dist/transport/undici.js +218 -0
  99. package/dist/types/index.d.ts +251 -0
  100. package/dist/types/index.d.ts.map +1 -0
  101. package/dist/types/index.js +1 -0
  102. package/dist/utils/agent-manager.d.ts +29 -0
  103. package/dist/utils/agent-manager.d.ts.map +1 -0
  104. package/dist/utils/agent-manager.js +133 -0
  105. package/dist/utils/body.d.ts +11 -0
  106. package/dist/utils/body.d.ts.map +1 -0
  107. package/dist/utils/body.js +136 -0
  108. package/dist/utils/cert.d.ts +12 -0
  109. package/dist/utils/cert.d.ts.map +1 -0
  110. package/dist/utils/cert.js +32 -0
  111. package/dist/utils/concurrency.d.ts +21 -0
  112. package/dist/utils/concurrency.d.ts.map +1 -0
  113. package/dist/utils/concurrency.js +116 -0
  114. package/dist/utils/dns.d.ts +7 -0
  115. package/dist/utils/dns.d.ts.map +1 -0
  116. package/dist/utils/dns.js +26 -0
  117. package/dist/utils/doh.d.ts +3 -0
  118. package/dist/utils/doh.d.ts.map +1 -0
  119. package/dist/utils/doh.js +35 -0
  120. package/dist/utils/header-parser.d.ts +81 -0
  121. package/dist/utils/header-parser.d.ts.map +1 -0
  122. package/dist/utils/header-parser.js +457 -0
  123. package/dist/utils/html-cleaner.d.ts +2 -0
  124. package/dist/utils/html-cleaner.d.ts.map +1 -0
  125. package/dist/utils/html-cleaner.js +21 -0
  126. package/dist/utils/logger.d.ts +33 -0
  127. package/dist/utils/logger.d.ts.map +1 -0
  128. package/dist/utils/logger.js +160 -0
  129. package/dist/utils/progress.d.ts +4 -0
  130. package/dist/utils/progress.d.ts.map +1 -0
  131. package/dist/utils/progress.js +49 -0
  132. package/dist/utils/request-pool.d.ts +23 -0
  133. package/dist/utils/request-pool.d.ts.map +1 -0
  134. package/dist/utils/request-pool.js +100 -0
  135. package/dist/utils/sse.d.ts +8 -0
  136. package/dist/utils/sse.d.ts.map +1 -0
  137. package/dist/utils/sse.js +62 -0
  138. package/dist/utils/streaming.d.ts +18 -0
  139. package/dist/utils/streaming.d.ts.map +1 -0
  140. package/dist/utils/streaming.js +83 -0
  141. package/dist/utils/task-pool.d.ts +38 -0
  142. package/dist/utils/task-pool.js +104 -0
  143. package/dist/utils/try-fn.d.ts +4 -0
  144. package/dist/utils/try-fn.d.ts.map +1 -0
  145. package/dist/utils/try-fn.js +53 -0
  146. package/dist/utils/upload.d.ts +10 -0
  147. package/dist/utils/upload.d.ts.map +1 -0
  148. package/dist/utils/upload.js +45 -0
  149. package/dist/utils/user-agent.d.ts +45 -0
  150. package/dist/utils/user-agent.d.ts.map +1 -0
  151. package/dist/utils/user-agent.js +100 -0
  152. package/dist/utils/whois.d.ts +15 -0
  153. package/dist/utils/whois.d.ts.map +1 -0
  154. package/dist/utils/whois.js +159 -0
  155. package/dist/websocket/client.d.ts +38 -0
  156. package/dist/websocket/client.d.ts.map +1 -0
  157. package/dist/websocket/client.js +184 -0
  158. package/package.json +100 -0
@@ -0,0 +1,45 @@
1
+ export declare function getDefaultUserAgent(): string;
2
+ export declare const USER_AGENT_PRESETS: {
3
+ readonly chrome_windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
4
+ readonly chrome_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
5
+ readonly chrome_linux: "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36";
6
+ readonly firefox_windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0";
7
+ readonly firefox_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0";
8
+ readonly firefox_linux: "Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0";
9
+ readonly safari_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15";
10
+ readonly edge_windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0";
11
+ readonly edge_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0";
12
+ readonly opera_windows: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/105.0.0.0";
13
+ readonly opera_mac: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/105.0.0.0";
14
+ readonly safari_iphone: "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
15
+ readonly safari_ipad: "Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1";
16
+ readonly chrome_ios: "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/120.0.6099.119 Mobile/15E148 Safari/604.1";
17
+ readonly chrome_android: "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36";
18
+ readonly chrome_android_tablet: "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Safari/537.36";
19
+ readonly firefox_android: "Mozilla/5.0 (Android 14; Mobile; rv:121.0) Gecko/121.0 Firefox/121.0";
20
+ readonly samsung_browser: "Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36";
21
+ readonly googlebot: "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
22
+ readonly googlebot_mobile: "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)";
23
+ readonly recker: string;
24
+ };
25
+ export type UserAgentPreset = keyof typeof USER_AGENT_PRESETS;
26
+ export declare function getUserAgent(preset: UserAgentPreset): string;
27
+ export declare const USER_AGENT_CATEGORIES: {
28
+ readonly desktop: {
29
+ readonly chrome: readonly ["chrome_windows", "chrome_mac", "chrome_linux"];
30
+ readonly firefox: readonly ["firefox_windows", "firefox_mac", "firefox_linux"];
31
+ readonly safari: readonly ["safari_mac"];
32
+ readonly edge: readonly ["edge_windows", "edge_mac"];
33
+ readonly opera: readonly ["opera_windows", "opera_mac"];
34
+ };
35
+ readonly mobile: {
36
+ readonly ios: readonly ["safari_iphone", "safari_ipad", "chrome_ios"];
37
+ readonly android: readonly ["chrome_android", "chrome_android_tablet", "firefox_android", "samsung_browser"];
38
+ };
39
+ readonly bot: readonly ["googlebot", "googlebot_mobile"];
40
+ readonly default: readonly ["recker"];
41
+ };
42
+ export declare function getRandomUserAgent(category: string): string;
43
+ export declare function detectDeviceType(userAgent: string): 'desktop' | 'mobile' | 'tablet' | 'bot' | 'unknown';
44
+ export declare function isMobile(userAgent: string): boolean;
45
+ //# sourceMappingURL=user-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"user-agent.d.ts","sourceRoot":"","sources":["../../src/utils/user-agent.ts"],"names":[],"mappings":"AAuBA,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAMD,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;CAmCrB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAW9D,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAE5D;AAKD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;CAcxB,CAAC;AAWX,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA0B3D;AAKD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAqBvG;AAKD,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAGnD"}
@@ -0,0 +1,100 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ let RECKER_VERSION = '1.0.0';
4
+ try {
5
+ const pkgPath = join(process.cwd(), 'package.json');
6
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
7
+ if (pkg.name === 'recker' && pkg.version) {
8
+ RECKER_VERSION = pkg.version;
9
+ }
10
+ }
11
+ catch {
12
+ }
13
+ export function getDefaultUserAgent() {
14
+ return `recker/${RECKER_VERSION}`;
15
+ }
16
+ export const USER_AGENT_PRESETS = {
17
+ chrome_windows: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
18
+ chrome_mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
19
+ chrome_linux: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
20
+ firefox_windows: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
21
+ firefox_mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
22
+ firefox_linux: 'Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0',
23
+ safari_mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15',
24
+ edge_windows: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
25
+ edge_mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
26
+ opera_windows: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/105.0.0.0',
27
+ opera_mac: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 OPR/105.0.0.0',
28
+ safari_iphone: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
29
+ safari_ipad: 'Mozilla/5.0 (iPad; CPU OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
30
+ chrome_ios: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/120.0.6099.119 Mobile/15E148 Safari/604.1',
31
+ chrome_android: 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36',
32
+ chrome_android_tablet: 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Safari/537.36',
33
+ firefox_android: 'Mozilla/5.0 (Android 14; Mobile; rv:121.0) Gecko/121.0 Firefox/121.0',
34
+ samsung_browser: 'Mozilla/5.0 (Linux; Android 14) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/23.0 Chrome/115.0.0.0 Mobile Safari/537.36',
35
+ googlebot: 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
36
+ googlebot_mobile: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.144 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
37
+ recker: getDefaultUserAgent(),
38
+ };
39
+ export function getUserAgent(preset) {
40
+ return USER_AGENT_PRESETS[preset];
41
+ }
42
+ export const USER_AGENT_CATEGORIES = {
43
+ desktop: {
44
+ chrome: ['chrome_windows', 'chrome_mac', 'chrome_linux'],
45
+ firefox: ['firefox_windows', 'firefox_mac', 'firefox_linux'],
46
+ safari: ['safari_mac'],
47
+ edge: ['edge_windows', 'edge_mac'],
48
+ opera: ['opera_windows', 'opera_mac'],
49
+ },
50
+ mobile: {
51
+ ios: ['safari_iphone', 'safari_ipad', 'chrome_ios'],
52
+ android: ['chrome_android', 'chrome_android_tablet', 'firefox_android', 'samsung_browser'],
53
+ },
54
+ bot: ['googlebot', 'googlebot_mobile'],
55
+ default: ['recker'],
56
+ };
57
+ export function getRandomUserAgent(category) {
58
+ const parts = category.split('.');
59
+ let presets = [];
60
+ if (parts.length === 1) {
61
+ const cat = USER_AGENT_CATEGORIES[parts[0]];
62
+ if (Array.isArray(cat)) {
63
+ presets = cat;
64
+ }
65
+ else if (typeof cat === 'object') {
66
+ presets = Object.values(cat).flat();
67
+ }
68
+ }
69
+ else if (parts.length === 2) {
70
+ const cat = USER_AGENT_CATEGORIES[parts[0]];
71
+ if (typeof cat === 'object' && parts[1] in cat) {
72
+ presets = cat[parts[1]];
73
+ }
74
+ }
75
+ if (presets.length === 0) {
76
+ return getDefaultUserAgent();
77
+ }
78
+ const randomIndex = Math.floor(Math.random() * presets.length);
79
+ return getUserAgent(presets[randomIndex]);
80
+ }
81
+ export function detectDeviceType(userAgent) {
82
+ const ua = userAgent.toLowerCase();
83
+ if (ua.includes('bot') || ua.includes('crawler') || ua.includes('spider')) {
84
+ return 'bot';
85
+ }
86
+ if (ua.includes('ipad') || (ua.includes('tablet')) || (ua.includes('android') && !ua.includes('mobile'))) {
87
+ return 'tablet';
88
+ }
89
+ if (ua.includes('mobile') || ua.includes('iphone')) {
90
+ return 'mobile';
91
+ }
92
+ if (ua.includes('windows') || ua.includes('macintosh') || (ua.includes('linux') && !ua.includes('android'))) {
93
+ return 'desktop';
94
+ }
95
+ return 'unknown';
96
+ }
97
+ export function isMobile(userAgent) {
98
+ const type = detectDeviceType(userAgent);
99
+ return type === 'mobile' || type === 'tablet';
100
+ }
@@ -0,0 +1,15 @@
1
+ export interface WhoisOptions {
2
+ server?: string;
3
+ port?: number;
4
+ timeout?: number;
5
+ follow?: boolean;
6
+ }
7
+ export interface WhoisResult {
8
+ raw: string;
9
+ query: string;
10
+ server: string;
11
+ data: Record<string, string | string[]>;
12
+ }
13
+ export declare function whois(query: string, options?: WhoisOptions): Promise<WhoisResult>;
14
+ export declare function isDomainAvailable(domain: string, options?: WhoisOptions): Promise<boolean>;
15
+ //# sourceMappingURL=whois.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whois.d.ts","sourceRoot":"","sources":["../../src/utils/whois.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,YAAY;IAK3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAKhB,IAAI,CAAC,EAAE,MAAM,CAAC;IAMd,OAAO,CAAC,EAAE,MAAM,CAAC;IAMjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAI1B,GAAG,EAAE,MAAM,CAAC;IAKZ,KAAK,EAAE,MAAM,CAAC;IAKd,MAAM,EAAE,MAAM,CAAC;IAKf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;CACzC;AA4KD,wBAAsB,KAAK,CACzB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAmCtB;AAMD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,YAAY,GACrB,OAAO,CAAC,OAAO,CAAC,CAoBlB"}
@@ -0,0 +1,159 @@
1
+ import { createConnection } from 'net';
2
+ const DEFAULT_SERVERS = {
3
+ 'com': 'whois.verisign-grs.com',
4
+ 'net': 'whois.verisign-grs.com',
5
+ 'org': 'whois.pir.org',
6
+ 'info': 'whois.afilias.net',
7
+ 'biz': 'whois.biz',
8
+ 'us': 'whois.nic.us',
9
+ 'uk': 'whois.nic.uk',
10
+ 'ca': 'whois.cira.ca',
11
+ 'de': 'whois.denic.de',
12
+ 'fr': 'whois.afnic.fr',
13
+ 'au': 'whois.aunic.net',
14
+ 'jp': 'whois.jprs.jp',
15
+ 'cn': 'whois.cnnic.cn',
16
+ 'ru': 'whois.tcinet.ru',
17
+ 'br': 'whois.registro.br',
18
+ 'eu': 'whois.eu',
19
+ 'io': 'whois.nic.io',
20
+ 'co': 'whois.nic.co',
21
+ 'me': 'whois.nic.me',
22
+ 'tv': 'whois.nic.tv',
23
+ 'cc': 'whois.nic.cc',
24
+ 'ws': 'whois.website.ws',
25
+ 'mobi': 'whois.dotmobiregistry.net',
26
+ 'asia': 'whois.nic.asia',
27
+ 'tel': 'whois.nic.tel',
28
+ 'pro': 'whois.registrypro.pro',
29
+ 'aero': 'whois.aero',
30
+ 'cat': 'whois.cat',
31
+ 'coop': 'whois.nic.coop',
32
+ 'jobs': 'whois.nic.jobs',
33
+ 'museum': 'whois.museum',
34
+ 'travel': 'whois.nic.travel',
35
+ 'xxx': 'whois.nic.xxx',
36
+ 'app': 'whois.nic.google',
37
+ 'dev': 'whois.nic.google',
38
+ 'ai': 'whois.nic.ai',
39
+ };
40
+ function extractTLD(domain) {
41
+ const parts = domain.toLowerCase().split('.');
42
+ return parts[parts.length - 1];
43
+ }
44
+ function getWhoisServer(query, customServer) {
45
+ if (customServer) {
46
+ return customServer;
47
+ }
48
+ const ipv4Pattern = /^(\d{1,3}\.){3}\d{1,3}$/;
49
+ const ipv6Pattern = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/;
50
+ if (ipv4Pattern.test(query) || ipv6Pattern.test(query)) {
51
+ return 'whois.arin.net';
52
+ }
53
+ const tld = extractTLD(query);
54
+ return DEFAULT_SERVERS[tld] || 'whois.iana.org';
55
+ }
56
+ function parseWhoisData(raw) {
57
+ const data = {};
58
+ const lines = raw.split('\n');
59
+ for (const line of lines) {
60
+ if (line.startsWith('%') || line.startsWith('#') || !line.trim()) {
61
+ continue;
62
+ }
63
+ const colonIndex = line.indexOf(':');
64
+ if (colonIndex === -1) {
65
+ continue;
66
+ }
67
+ const key = line.substring(0, colonIndex).trim().toLowerCase();
68
+ const value = line.substring(colonIndex + 1).trim();
69
+ if (!key || !value) {
70
+ continue;
71
+ }
72
+ if (data[key]) {
73
+ if (Array.isArray(data[key])) {
74
+ data[key].push(value);
75
+ }
76
+ else {
77
+ data[key] = [data[key], value];
78
+ }
79
+ }
80
+ else {
81
+ data[key] = value;
82
+ }
83
+ }
84
+ return data;
85
+ }
86
+ function extractReferralServer(raw) {
87
+ const lines = raw.toLowerCase().split('\n');
88
+ for (const line of lines) {
89
+ if (line.includes('whois server:') || line.includes('referral url:')) {
90
+ const match = line.match(/whois\.[\w.-]+/);
91
+ if (match) {
92
+ return match[0];
93
+ }
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+ async function queryWhoisServer(server, query, port, timeout) {
99
+ return new Promise((resolve, reject) => {
100
+ let response = '';
101
+ let socket = null;
102
+ const timeoutId = setTimeout(() => {
103
+ socket?.destroy();
104
+ reject(new Error(`WHOIS query timed out after ${timeout}ms`));
105
+ }, timeout);
106
+ socket = createConnection({ host: server, port }, () => {
107
+ socket.write(query + '\r\n');
108
+ });
109
+ socket.on('data', (chunk) => {
110
+ response += chunk.toString('utf-8');
111
+ });
112
+ socket.on('end', () => {
113
+ clearTimeout(timeoutId);
114
+ resolve(response);
115
+ });
116
+ socket.on('error', (error) => {
117
+ clearTimeout(timeoutId);
118
+ reject(new Error(`WHOIS query failed: ${error.message}`));
119
+ });
120
+ });
121
+ }
122
+ export async function whois(query, options = {}) {
123
+ const { server: customServer, port = 43, timeout = 10000, follow = true, } = options;
124
+ const cleanQuery = query.trim().toLowerCase();
125
+ let server = getWhoisServer(cleanQuery, customServer);
126
+ let raw = await queryWhoisServer(server, cleanQuery, port, timeout);
127
+ if (follow && !customServer) {
128
+ const referralServer = extractReferralServer(raw);
129
+ if (referralServer && referralServer !== server) {
130
+ server = referralServer;
131
+ raw = await queryWhoisServer(server, cleanQuery, port, timeout);
132
+ }
133
+ }
134
+ const data = parseWhoisData(raw);
135
+ return {
136
+ raw,
137
+ query: cleanQuery,
138
+ server,
139
+ data,
140
+ };
141
+ }
142
+ export async function isDomainAvailable(domain, options) {
143
+ try {
144
+ const result = await whois(domain, options);
145
+ const rawLower = result.raw.toLowerCase();
146
+ const notFoundIndicators = [
147
+ 'no match',
148
+ 'not found',
149
+ 'no entries found',
150
+ 'no data found',
151
+ 'status: available',
152
+ 'status: free',
153
+ ];
154
+ return notFoundIndicators.some(indicator => rawLower.includes(indicator));
155
+ }
156
+ catch (error) {
157
+ return false;
158
+ }
159
+ }
@@ -0,0 +1,38 @@
1
+ import { EventEmitter } from 'events';
2
+ export interface WebSocketOptions {
3
+ protocols?: string | string[];
4
+ headers?: Record<string, string>;
5
+ reconnect?: boolean;
6
+ reconnectDelay?: number;
7
+ maxReconnectAttempts?: number;
8
+ heartbeatInterval?: number;
9
+ }
10
+ export interface WebSocketMessage {
11
+ data: string | Buffer;
12
+ isBinary: boolean;
13
+ }
14
+ export declare class ReckerWebSocket extends EventEmitter {
15
+ private ws;
16
+ private url;
17
+ private options;
18
+ private reconnectAttempts;
19
+ private reconnectTimer?;
20
+ private heartbeatTimer?;
21
+ private isClosed;
22
+ private isReconnecting;
23
+ constructor(url: string, options?: WebSocketOptions);
24
+ connect(): Promise<void>;
25
+ send(data: string | Buffer | ArrayBuffer): void;
26
+ sendJSON(data: any): void;
27
+ close(code?: number, reason?: string): void;
28
+ ping(): void;
29
+ get readyState(): number;
30
+ get isConnected(): boolean;
31
+ [Symbol.asyncIterator](): AsyncGenerator<WebSocketMessage>;
32
+ private attemptReconnect;
33
+ private clearReconnectTimer;
34
+ private startHeartbeat;
35
+ private stopHeartbeat;
36
+ }
37
+ export declare function websocket(url: string, options?: WebSocketOptions): ReckerWebSocket;
38
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/websocket/client.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtC,MAAM,WAAW,gBAAgB;IAI/B,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAK9B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAMjC,SAAS,CAAC,EAAE,OAAO,CAAC;IAMpB,cAAc,CAAC,EAAE,MAAM,CAAC;IAMxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAO9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAKD,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,cAAc,CAAC,CAAiB;IACxC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAAS;gBAEnB,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB;IAgBjD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA4C9B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI;IAU/C,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI;IAOzB,KAAK,CAAC,IAAI,SAAO,EAAE,MAAM,SAAK,GAAG,IAAI;IAerC,IAAI,IAAI,IAAI;IAeZ,IAAI,UAAU,IAAI,MAAM,CAEvB;IAKD,IAAI,WAAW,IAAI,OAAO,CAEzB;IAKM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,gBAAgB,CAAC;IAoDjE,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,mBAAmB;IAO3B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,aAAa;CAMtB;AAKD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,eAAe,CAMlF"}
@@ -0,0 +1,184 @@
1
+ import { WebSocket } from 'undici';
2
+ import { EventEmitter } from 'events';
3
+ export class ReckerWebSocket extends EventEmitter {
4
+ ws = null;
5
+ url;
6
+ options;
7
+ reconnectAttempts = 0;
8
+ reconnectTimer;
9
+ heartbeatTimer;
10
+ isClosed = false;
11
+ isReconnecting = false;
12
+ constructor(url, options = {}) {
13
+ super();
14
+ this.url = url;
15
+ this.options = {
16
+ protocols: options.protocols || [],
17
+ headers: options.headers || {},
18
+ reconnect: options.reconnect ?? false,
19
+ reconnectDelay: options.reconnectDelay ?? 1000,
20
+ maxReconnectAttempts: options.maxReconnectAttempts ?? 5,
21
+ heartbeatInterval: options.heartbeatInterval ?? 30000,
22
+ };
23
+ }
24
+ async connect() {
25
+ return new Promise((resolve, reject) => {
26
+ try {
27
+ this.ws = new WebSocket(this.url, this.options.protocols);
28
+ this.ws.addEventListener('open', () => {
29
+ this.reconnectAttempts = 0;
30
+ this.isReconnecting = false;
31
+ this.startHeartbeat();
32
+ this.emit('open');
33
+ resolve();
34
+ });
35
+ this.ws.addEventListener('message', (event) => {
36
+ const message = {
37
+ data: event.data,
38
+ isBinary: event.data instanceof Buffer
39
+ };
40
+ this.emit('message', message);
41
+ });
42
+ this.ws.addEventListener('close', (event) => {
43
+ this.stopHeartbeat();
44
+ this.emit('close', event.code, event.reason);
45
+ if (!this.isClosed && this.options.reconnect) {
46
+ this.attemptReconnect();
47
+ }
48
+ });
49
+ this.ws.addEventListener('error', (event) => {
50
+ this.emit('error', event.error || new Error('WebSocket error'));
51
+ reject(event.error || new Error('WebSocket connection failed'));
52
+ });
53
+ }
54
+ catch (error) {
55
+ reject(error);
56
+ }
57
+ });
58
+ }
59
+ send(data) {
60
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
61
+ throw new Error('WebSocket is not connected');
62
+ }
63
+ this.ws.send(data);
64
+ }
65
+ sendJSON(data) {
66
+ this.send(JSON.stringify(data));
67
+ }
68
+ close(code = 1000, reason = '') {
69
+ this.isClosed = true;
70
+ this.stopHeartbeat();
71
+ this.clearReconnectTimer();
72
+ if (this.ws) {
73
+ this.ws.close(code, reason);
74
+ this.ws = null;
75
+ }
76
+ }
77
+ ping() {
78
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
79
+ try {
80
+ this.ws.send('__heartbeat__');
81
+ }
82
+ catch (e) {
83
+ }
84
+ }
85
+ }
86
+ get readyState() {
87
+ return this.ws?.readyState ?? WebSocket.CLOSED;
88
+ }
89
+ get isConnected() {
90
+ return this.ws?.readyState === WebSocket.OPEN;
91
+ }
92
+ async *[Symbol.asyncIterator]() {
93
+ const queue = [];
94
+ let resolveNext = null;
95
+ let closed = false;
96
+ const messageHandler = (msg) => {
97
+ if (resolveNext) {
98
+ resolveNext(msg);
99
+ resolveNext = null;
100
+ }
101
+ else {
102
+ queue.push(msg);
103
+ }
104
+ };
105
+ const closeHandler = () => {
106
+ closed = true;
107
+ if (resolveNext) {
108
+ resolveNext(null);
109
+ resolveNext = null;
110
+ }
111
+ };
112
+ this.on('message', messageHandler);
113
+ this.on('close', closeHandler);
114
+ try {
115
+ while (true) {
116
+ if (queue.length > 0) {
117
+ yield queue.shift();
118
+ }
119
+ else {
120
+ if (closed)
121
+ break;
122
+ const msg = await new Promise((resolve) => {
123
+ resolveNext = resolve;
124
+ });
125
+ if (msg) {
126
+ yield msg;
127
+ }
128
+ else {
129
+ break;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ finally {
135
+ this.off('message', messageHandler);
136
+ this.off('close', closeHandler);
137
+ }
138
+ }
139
+ attemptReconnect() {
140
+ if (this.isReconnecting)
141
+ return;
142
+ if (this.options.maxReconnectAttempts > 0 &&
143
+ this.reconnectAttempts >= this.options.maxReconnectAttempts) {
144
+ this.emit('max-reconnect-attempts');
145
+ return;
146
+ }
147
+ this.isReconnecting = true;
148
+ this.reconnectAttempts++;
149
+ const delay = this.options.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
150
+ this.emit('reconnecting', this.reconnectAttempts, delay);
151
+ this.reconnectTimer = setTimeout(() => {
152
+ this.connect().catch((error) => {
153
+ this.emit('reconnect-error', error);
154
+ });
155
+ }, delay);
156
+ }
157
+ clearReconnectTimer() {
158
+ if (this.reconnectTimer) {
159
+ clearTimeout(this.reconnectTimer);
160
+ this.reconnectTimer = undefined;
161
+ }
162
+ }
163
+ startHeartbeat() {
164
+ if (this.options.heartbeatInterval <= 0)
165
+ return;
166
+ this.heartbeatTimer = setInterval(() => {
167
+ if (this.isConnected) {
168
+ this.ping();
169
+ }
170
+ }, this.options.heartbeatInterval);
171
+ }
172
+ stopHeartbeat() {
173
+ if (this.heartbeatTimer) {
174
+ clearInterval(this.heartbeatTimer);
175
+ this.heartbeatTimer = undefined;
176
+ }
177
+ }
178
+ }
179
+ export function websocket(url, options) {
180
+ const ws = new ReckerWebSocket(url, options);
181
+ ws.connect().catch(() => {
182
+ });
183
+ return ws;
184
+ }
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "recker",
3
+ "version": "1.0.2-0",
4
+ "description": "AI & DevX focused HTTP client for Node.js 18+",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "keywords": [
10
+ "http",
11
+ "client",
12
+ "fetch",
13
+ "axios",
14
+ "ky",
15
+ "got",
16
+ "undici",
17
+ "typescript",
18
+ "promise",
19
+ "retry",
20
+ "cache",
21
+ "hooks",
22
+ "http2",
23
+ "http3",
24
+ "sse",
25
+ "websocket",
26
+ "whois",
27
+ "dns",
28
+ "proxy",
29
+ "ai"
30
+ ],
31
+ "author": "Forattini Dev",
32
+ "license": "MIT",
33
+ "homepage": "https://forattini-dev.github.io/recker",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/forattini-dev/recker.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/forattini-dev/recker/issues"
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "README.md",
44
+ "LICENSE"
45
+ ],
46
+ "exports": {
47
+ ".": {
48
+ "types": "./dist/index.d.ts",
49
+ "import": "./dist/index.js",
50
+ "default": "./dist/index.js"
51
+ },
52
+ "./client": {
53
+ "types": "./dist/core/client.d.ts",
54
+ "import": "./dist/core/client.js"
55
+ },
56
+ "./plugins/*": {
57
+ "types": "./dist/plugins/*.d.ts",
58
+ "import": "./dist/plugins/*.js"
59
+ },
60
+ "./utils/*": {
61
+ "types": "./dist/utils/*.d.ts",
62
+ "import": "./dist/utils/*.js"
63
+ },
64
+ "./package.json": "./package.json"
65
+ },
66
+ "engines": {
67
+ "node": ">=18"
68
+ },
69
+ "publishConfig": {
70
+ "access": "public"
71
+ },
72
+ "dependencies": {
73
+ "undici": "^7.16.0",
74
+ "zod": "^4.1.13"
75
+ },
76
+ "devDependencies": {
77
+ "@types/node": "^24.10.1",
78
+ "@vitest/coverage-v8": "^3.2.4",
79
+ "axios": "^1.13.2",
80
+ "docsify-darklight-theme": "^3.2.0",
81
+ "docsify-mermaid": "^2.0.1",
82
+ "got": "^14.6.5",
83
+ "husky": "^9.1.7",
84
+ "ky": "^1.14.0",
85
+ "mermaid": "^11.12.1",
86
+ "mitata": "^1.0.34",
87
+ "tsx": "^4.20.6",
88
+ "typescript": "^5.9.3",
89
+ "vitest": "^3.2.4"
90
+ },
91
+ "scripts": {
92
+ "build": "tsc",
93
+ "test": "vitest run",
94
+ "test:coverage": "vitest run --coverage",
95
+ "bench": "tsx benchmark/index.ts",
96
+ "bench:all": "tsx benchmark/run-all.ts",
97
+ "docs:dev": "npx -y docsify-cli serve docs --port 3000",
98
+ "docs:preview": "npx -y docsify-cli serve docs --port 3000 --open"
99
+ }
100
+ }