domain-search-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +52 -0
- package/Dockerfile +15 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/SECURITY.md +252 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +117 -0
- package/dist/config.js.map +1 -0
- package/dist/fallbacks/index.d.ts +6 -0
- package/dist/fallbacks/index.d.ts.map +1 -0
- package/dist/fallbacks/index.js +14 -0
- package/dist/fallbacks/index.js.map +1 -0
- package/dist/fallbacks/rdap.d.ts +18 -0
- package/dist/fallbacks/rdap.d.ts.map +1 -0
- package/dist/fallbacks/rdap.js +339 -0
- package/dist/fallbacks/rdap.js.map +1 -0
- package/dist/fallbacks/whois.d.ts +27 -0
- package/dist/fallbacks/whois.d.ts.map +1 -0
- package/dist/fallbacks/whois.js +219 -0
- package/dist/fallbacks/whois.js.map +1 -0
- package/dist/registrars/base.d.ts +89 -0
- package/dist/registrars/base.d.ts.map +1 -0
- package/dist/registrars/base.js +203 -0
- package/dist/registrars/base.js.map +1 -0
- package/dist/registrars/index.d.ts +7 -0
- package/dist/registrars/index.d.ts.map +1 -0
- package/dist/registrars/index.js +15 -0
- package/dist/registrars/index.js.map +1 -0
- package/dist/registrars/namecheap.d.ts +69 -0
- package/dist/registrars/namecheap.d.ts.map +1 -0
- package/dist/registrars/namecheap.js +307 -0
- package/dist/registrars/namecheap.js.map +1 -0
- package/dist/registrars/porkbun.d.ts +63 -0
- package/dist/registrars/porkbun.d.ts.map +1 -0
- package/dist/registrars/porkbun.js +299 -0
- package/dist/registrars/porkbun.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +209 -0
- package/dist/server.js.map +1 -0
- package/dist/services/domain-search.d.ts +40 -0
- package/dist/services/domain-search.d.ts.map +1 -0
- package/dist/services/domain-search.js +438 -0
- package/dist/services/domain-search.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +11 -0
- package/dist/services/index.js.map +1 -0
- package/dist/tools/bulk_search.d.ts +72 -0
- package/dist/tools/bulk_search.d.ts.map +1 -0
- package/dist/tools/bulk_search.js +108 -0
- package/dist/tools/bulk_search.js.map +1 -0
- package/dist/tools/check_socials.d.ts +71 -0
- package/dist/tools/check_socials.d.ts.map +1 -0
- package/dist/tools/check_socials.js +357 -0
- package/dist/tools/check_socials.js.map +1 -0
- package/dist/tools/compare_registrars.d.ts +80 -0
- package/dist/tools/compare_registrars.d.ts.map +1 -0
- package/dist/tools/compare_registrars.js +116 -0
- package/dist/tools/compare_registrars.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +31 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/search_domain.d.ts +61 -0
- package/dist/tools/search_domain.d.ts.map +1 -0
- package/dist/tools/search_domain.js +81 -0
- package/dist/tools/search_domain.js.map +1 -0
- package/dist/tools/suggest_domains.d.ts +82 -0
- package/dist/tools/suggest_domains.d.ts.map +1 -0
- package/dist/tools/suggest_domains.js +227 -0
- package/dist/tools/suggest_domains.js.map +1 -0
- package/dist/tools/tld_info.d.ts +56 -0
- package/dist/tools/tld_info.d.ts.map +1 -0
- package/dist/tools/tld_info.js +273 -0
- package/dist/tools/tld_info.js.map +1 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +81 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +192 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/errors.d.ts +87 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +191 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +24 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/premium-analyzer.d.ts +33 -0
- package/dist/utils/premium-analyzer.d.ts.map +1 -0
- package/dist/utils/premium-analyzer.js +273 -0
- package/dist/utils/premium-analyzer.js.map +1 -0
- package/dist/utils/validators.d.ts +53 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +159 -0
- package/dist/utils/validators.js.map +1 -0
- package/docs/marketing/devto-post.md +135 -0
- package/docs/marketing/hackernews.md +42 -0
- package/docs/marketing/producthunt.md +109 -0
- package/docs/marketing/reddit-post.md +59 -0
- package/docs/marketing/twitter-thread.md +105 -0
- package/examples/bulk-search-50-domains.ts +131 -0
- package/examples/cli-interactive.ts +280 -0
- package/examples/compare-registrars.ts +78 -0
- package/examples/search-single-domain.ts +54 -0
- package/examples/suggest-names.ts +110 -0
- package/glama.json +6 -0
- package/jest.config.js +35 -0
- package/package.json +62 -0
- package/smithery.yaml +36 -0
- package/src/config.ts +121 -0
- package/src/fallbacks/index.ts +6 -0
- package/src/fallbacks/rdap.ts +407 -0
- package/src/fallbacks/whois.ts +250 -0
- package/src/registrars/base.ts +264 -0
- package/src/registrars/index.ts +7 -0
- package/src/registrars/namecheap.ts +378 -0
- package/src/registrars/porkbun.ts +380 -0
- package/src/server.ts +276 -0
- package/src/services/domain-search.ts +567 -0
- package/src/services/index.ts +9 -0
- package/src/tools/bulk_search.ts +142 -0
- package/src/tools/check_socials.ts +467 -0
- package/src/tools/compare_registrars.ts +162 -0
- package/src/tools/index.ts +45 -0
- package/src/tools/search_domain.ts +93 -0
- package/src/tools/suggest_domains.ts +284 -0
- package/src/tools/tld_info.ts +294 -0
- package/src/types.ts +289 -0
- package/src/utils/cache.ts +238 -0
- package/src/utils/errors.ts +262 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logger.ts +162 -0
- package/src/utils/premium-analyzer.ts +303 -0
- package/src/utils/validators.ts +193 -0
- package/tests/premium-analyzer.test.ts +310 -0
- package/tests/unit/cache.test.ts +123 -0
- package/tests/unit/errors.test.ts +190 -0
- package/tests/unit/tld-info.test.ts +62 -0
- package/tests/unit/tools.test.ts +200 -0
- package/tests/unit/validators.test.ts +146 -0
- package/tsconfig.json +25 -0
package/SECURITY.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Security Audit Report
|
|
2
|
+
|
|
3
|
+
**Project:** Domain Search MCP
|
|
4
|
+
**Audit Date:** December 2024
|
|
5
|
+
**Audit Type:** Comprehensive Security Review
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Executive Summary
|
|
10
|
+
|
|
11
|
+
This codebase has undergone multiple layers of security analysis using both AI-powered code review tools and static analysis security scanners. All identified vulnerabilities have been addressed, and the remaining findings have been analyzed and documented as acceptable risks.
|
|
12
|
+
|
|
13
|
+
| Category | Tools Used | Critical | High | Medium | Low |
|
|
14
|
+
|----------|-----------|----------|------|--------|-----|
|
|
15
|
+
| AI Code Review | 2 platforms | 0 | 0 | 0 | 2 (false positives) |
|
|
16
|
+
| Static Analysis (SAST) | Pattern-based scanner | 0 | 0 | 1 (mitigated) | 0 |
|
|
17
|
+
| Dependency Scan (SCA) | Package vulnerability scanner | 0 | 0 | 0 | 0 |
|
|
18
|
+
|
|
19
|
+
**Overall Security Posture: PRODUCTION READY**
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Vulnerabilities Found & Fixed
|
|
24
|
+
|
|
25
|
+
### 1.1 IP Address Disclosure (P1 - Critical)
|
|
26
|
+
|
|
27
|
+
**Location:** `src/registrars/namecheap.ts`
|
|
28
|
+
**Issue:** External service call to determine client IP exposed user's IP address to third-party service.
|
|
29
|
+
**CWE:** CWE-200 (Exposure of Sensitive Information)
|
|
30
|
+
|
|
31
|
+
**Resolution:**
|
|
32
|
+
- Removed external IP lookup dependency
|
|
33
|
+
- IP now configured via `NAMECHEAP_CLIENT_IP` environment variable
|
|
34
|
+
- Added IP format validation (IPv4/IPv6)
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Before (vulnerable)
|
|
38
|
+
const ip = await axios.get('https://external-ip-service.com');
|
|
39
|
+
|
|
40
|
+
// After (secure)
|
|
41
|
+
const ip = config.namecheap.clientIp; // User-configured, no external call
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### 1.2 Unbounded Cache Growth (P2 - High)
|
|
47
|
+
|
|
48
|
+
**Location:** `src/utils/cache.ts`
|
|
49
|
+
**Issue:** Cache had no size limit, allowing potential memory exhaustion through repeated unique queries.
|
|
50
|
+
**CWE:** CWE-400 (Uncontrolled Resource Consumption)
|
|
51
|
+
|
|
52
|
+
**Resolution:**
|
|
53
|
+
- Implemented LRU (Least Recently Used) eviction policy
|
|
54
|
+
- Added configurable maximum cache size (default: 10,000 entries)
|
|
55
|
+
- Added `lastAccessedAt` tracking for intelligent eviction
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Cache now implements size limits with LRU eviction
|
|
59
|
+
const DEFAULT_MAX_CACHE_SIZE = 10000; // ~10MB max memory
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### 1.3 Missing API Response Validation (P2 - High)
|
|
65
|
+
|
|
66
|
+
**Location:** `src/registrars/porkbun.ts`, `src/registrars/namecheap.ts`, `src/fallbacks/rdap.ts`
|
|
67
|
+
**Issue:** External API responses were used without schema validation, risking type confusion or injection.
|
|
68
|
+
**CWE:** CWE-20 (Improper Input Validation)
|
|
69
|
+
|
|
70
|
+
**Resolution:**
|
|
71
|
+
- Added Zod schema validation for all external API responses
|
|
72
|
+
- Implemented strict type inference from schemas
|
|
73
|
+
- Added safe parsing with `.safeParse()` for graceful error handling
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// All external responses now validated
|
|
77
|
+
const parseResult = ResponseSchema.safeParse(response.data);
|
|
78
|
+
if (!parseResult.success) {
|
|
79
|
+
throw new RegistrarApiError('Invalid API response format');
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### 1.4 Unsafe vCard Array Access (P2 - Medium)
|
|
86
|
+
|
|
87
|
+
**Location:** `src/fallbacks/rdap.ts`
|
|
88
|
+
**Issue:** RDAP vCard arrays accessed without bounds checking, risking crashes on malformed data.
|
|
89
|
+
**CWE:** CWE-129 (Improper Validation of Array Index)
|
|
90
|
+
|
|
91
|
+
**Resolution:**
|
|
92
|
+
- Added comprehensive bounds checking before array access
|
|
93
|
+
- Wrapped extraction in try-catch for defensive error handling
|
|
94
|
+
- Validated array structure at each nesting level
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// Safe extraction with bounds checking
|
|
98
|
+
if (!Array.isArray(vcardArray) || vcardArray.length < 2) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 2. Findings Analyzed & Accepted
|
|
106
|
+
|
|
107
|
+
### 2.1 Dynamic RegExp Construction
|
|
108
|
+
|
|
109
|
+
**Location:** `src/registrars/namecheap.ts:77,94`
|
|
110
|
+
**Scanner Finding:** "Potential ReDoS via dynamic RegExp"
|
|
111
|
+
**Severity Reported:** Medium
|
|
112
|
+
|
|
113
|
+
**Analysis:**
|
|
114
|
+
| Factor | Assessment |
|
|
115
|
+
|--------|------------|
|
|
116
|
+
| Input source | Hardcoded whitelist (`ALLOWED_XML_TAGS`) |
|
|
117
|
+
| User control | None - parameters are literal strings in code |
|
|
118
|
+
| Regex complexity | Simple pattern, no nested quantifiers |
|
|
119
|
+
| Backtracking risk | None - `[^<]*` cannot cause catastrophic backtracking |
|
|
120
|
+
|
|
121
|
+
**Conclusion:** FALSE POSITIVE
|
|
122
|
+
The scanner cannot determine that the `tag` parameter is constrained by a compile-time whitelist. The regex pattern itself is mathematically immune to ReDoS attacks.
|
|
123
|
+
|
|
124
|
+
**Mitigation:** Whitelist validation occurs before RegExp construction:
|
|
125
|
+
```typescript
|
|
126
|
+
const ALLOWED_XML_TAGS = new Set(['Error', 'Errors', 'DomainCheckResult']);
|
|
127
|
+
|
|
128
|
+
if (!ALLOWED_XML_TAGS.has(tag)) {
|
|
129
|
+
return undefined; // Reject non-whitelisted tags
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
### 2.2 Format String in Example Files
|
|
136
|
+
|
|
137
|
+
**Location:** `examples/*.ts`
|
|
138
|
+
**Scanner Finding:** "Unsafe format string concatenation"
|
|
139
|
+
**Severity Reported:** Info
|
|
140
|
+
|
|
141
|
+
**Analysis:**
|
|
142
|
+
- Located in example/demo files only
|
|
143
|
+
- Not part of production server code
|
|
144
|
+
- No user input reaches these code paths
|
|
145
|
+
- Examples run locally by developers only
|
|
146
|
+
|
|
147
|
+
**Conclusion:** ACCEPTABLE - Example code, not production
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 3. Dependency Security
|
|
152
|
+
|
|
153
|
+
### 3.1 Package Vulnerability Scan
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
Scan Date: December 2024
|
|
157
|
+
Vulnerabilities Found: 0
|
|
158
|
+
|
|
159
|
+
Dependencies Analyzed:
|
|
160
|
+
├── @modelcontextprotocol/sdk (runtime)
|
|
161
|
+
├── axios (runtime)
|
|
162
|
+
├── zod (runtime)
|
|
163
|
+
├── dotenv (runtime)
|
|
164
|
+
├── winston (runtime)
|
|
165
|
+
└── [dev dependencies excluded from production]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### 3.2 Outdated Packages
|
|
169
|
+
|
|
170
|
+
| Package | Current | Latest | Risk Assessment |
|
|
171
|
+
|---------|---------|--------|-----------------|
|
|
172
|
+
| zod | 3.x | 4.x | Major version, breaking changes - defer upgrade |
|
|
173
|
+
| dotenv | 16.x | 17.x | No security implications |
|
|
174
|
+
| @types/* | Various | Various | Dev-only, no runtime impact |
|
|
175
|
+
|
|
176
|
+
**Recommendation:** No immediate action required. Schedule major version upgrades during planned maintenance windows.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 4. Security Architecture
|
|
181
|
+
|
|
182
|
+
### 4.1 Defense in Depth
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
┌─────────────────────────────────────────────────────────┐
|
|
186
|
+
│ MCP Protocol Layer │
|
|
187
|
+
│ (Zod schema validation at entry) │
|
|
188
|
+
├─────────────────────────────────────────────────────────┤
|
|
189
|
+
│ Input Validation │
|
|
190
|
+
│ (Domain/TLD validators with sanitization) │
|
|
191
|
+
├─────────────────────────────────────────────────────────┤
|
|
192
|
+
│ Rate Limiting │
|
|
193
|
+
│ (Token bucket per registrar adapter) │
|
|
194
|
+
├─────────────────────────────────────────────────────────┤
|
|
195
|
+
│ Response Validation │
|
|
196
|
+
│ (Zod schemas for all external APIs) │
|
|
197
|
+
├─────────────────────────────────────────────────────────┤
|
|
198
|
+
│ Resource Limits │
|
|
199
|
+
│ (LRU cache eviction, request timeouts) │
|
|
200
|
+
└─────────────────────────────────────────────────────────┘
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 4.2 Security Controls Summary
|
|
204
|
+
|
|
205
|
+
| Control | Implementation | Status |
|
|
206
|
+
|---------|---------------|--------|
|
|
207
|
+
| Input validation | Zod schemas + custom validators | ✅ |
|
|
208
|
+
| Output encoding | N/A (JSON only) | ✅ |
|
|
209
|
+
| Authentication | API keys via environment variables | ✅ |
|
|
210
|
+
| Rate limiting | Per-adapter token bucket | ✅ |
|
|
211
|
+
| Error handling | Custom error types, no stack traces to clients | ✅ |
|
|
212
|
+
| Logging | Winston with configurable levels | ✅ |
|
|
213
|
+
| Secrets management | Environment variables, no hardcoding | ✅ |
|
|
214
|
+
| Dependency security | 0 known vulnerabilities | ✅ |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 5. Recommendations for Future Development
|
|
219
|
+
|
|
220
|
+
1. **Before adding new external APIs:** Add Zod schema validation for responses
|
|
221
|
+
2. **Before adding user-facing inputs:** Validate and sanitize at entry point
|
|
222
|
+
3. **When modifying cache logic:** Maintain size limits and eviction policies
|
|
223
|
+
4. **When updating dependencies:** Run vulnerability scan before merging
|
|
224
|
+
5. **For sensitive configurations:** Use environment variables, never commit secrets
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## 6. Audit Methodology
|
|
229
|
+
|
|
230
|
+
This security review employed a multi-layer approach:
|
|
231
|
+
|
|
232
|
+
1. **AI-Powered Code Review** - Semantic analysis for logic flaws, security anti-patterns, and architectural issues
|
|
233
|
+
2. **Static Application Security Testing (SAST)** - Pattern-based scanning for OWASP Top 10, CWE vulnerabilities
|
|
234
|
+
3. **Software Composition Analysis (SCA)** - Dependency vulnerability database matching
|
|
235
|
+
4. **Manual Code Review** - Verification of automated findings, false positive elimination
|
|
236
|
+
|
|
237
|
+
Each finding was triaged using:
|
|
238
|
+
- **Exploitability assessment** - Can this actually be exploited?
|
|
239
|
+
- **Data flow analysis** - Where does the data come from?
|
|
240
|
+
- **Framework context** - What protections exist at other layers?
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Approval
|
|
245
|
+
|
|
246
|
+
This codebase has been reviewed and approved for production deployment.
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
Security Review: PASSED
|
|
250
|
+
Last Updated: December 2024
|
|
251
|
+
Next Review: Recommended before major version releases
|
|
252
|
+
```
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loader for Domain Search MCP.
|
|
3
|
+
*
|
|
4
|
+
* Loads environment variables with sensible defaults.
|
|
5
|
+
* The server works without any API keys (falls back to RDAP/WHOIS).
|
|
6
|
+
*/
|
|
7
|
+
import type { Config } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Load and validate configuration from environment.
|
|
10
|
+
*/
|
|
11
|
+
export declare function loadConfig(): Config;
|
|
12
|
+
/**
|
|
13
|
+
* Global config instance.
|
|
14
|
+
* Loaded once at startup.
|
|
15
|
+
*/
|
|
16
|
+
export declare const config: Config;
|
|
17
|
+
/**
|
|
18
|
+
* Check if any registrar APIs are configured.
|
|
19
|
+
*/
|
|
20
|
+
export declare function hasRegistrarApi(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Get a summary of available data sources.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getAvailableSources(): string[];
|
|
25
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAoCzC;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAiDnC;AAED;;;GAGG;AACH,eAAO,MAAM,MAAM,QAAe,CAAC;AAEnC;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAM9C"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration loader for Domain Search MCP.
|
|
4
|
+
*
|
|
5
|
+
* Loads environment variables with sensible defaults.
|
|
6
|
+
* The server works without any API keys (falls back to RDAP/WHOIS).
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.config = void 0;
|
|
10
|
+
exports.loadConfig = loadConfig;
|
|
11
|
+
exports.hasRegistrarApi = hasRegistrarApi;
|
|
12
|
+
exports.getAvailableSources = getAvailableSources;
|
|
13
|
+
const dotenv_1 = require("dotenv");
|
|
14
|
+
// Load .env file if present
|
|
15
|
+
(0, dotenv_1.config)();
|
|
16
|
+
/**
|
|
17
|
+
* Parse a comma-separated string into an array.
|
|
18
|
+
*/
|
|
19
|
+
function parseList(value, defaults) {
|
|
20
|
+
if (!value)
|
|
21
|
+
return defaults;
|
|
22
|
+
return value
|
|
23
|
+
.split(',')
|
|
24
|
+
.map((s) => s.trim().toLowerCase())
|
|
25
|
+
.filter((s) => s.length > 0);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse an integer with a fallback default.
|
|
29
|
+
*/
|
|
30
|
+
function parseIntWithDefault(value, defaultValue) {
|
|
31
|
+
if (!value)
|
|
32
|
+
return defaultValue;
|
|
33
|
+
const parsed = parseInt(value, 10);
|
|
34
|
+
return isNaN(parsed) ? defaultValue : parsed;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse a boolean from environment variable.
|
|
38
|
+
*/
|
|
39
|
+
function parseBool(value, defaultValue) {
|
|
40
|
+
if (!value)
|
|
41
|
+
return defaultValue;
|
|
42
|
+
return value.toLowerCase() === 'true' || value === '1';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Load and validate configuration from environment.
|
|
46
|
+
*/
|
|
47
|
+
function loadConfig() {
|
|
48
|
+
const env = process.env;
|
|
49
|
+
// Check for API keys
|
|
50
|
+
const hasPorkbun = !!(env.PORKBUN_API_KEY && env.PORKBUN_API_SECRET);
|
|
51
|
+
const hasNamecheap = !!(env.NAMECHEAP_API_KEY && env.NAMECHEAP_API_USER);
|
|
52
|
+
const config = {
|
|
53
|
+
porkbun: {
|
|
54
|
+
apiKey: env.PORKBUN_API_KEY,
|
|
55
|
+
apiSecret: env.PORKBUN_API_SECRET,
|
|
56
|
+
enabled: hasPorkbun,
|
|
57
|
+
},
|
|
58
|
+
namecheap: {
|
|
59
|
+
apiKey: env.NAMECHEAP_API_KEY,
|
|
60
|
+
apiUser: env.NAMECHEAP_API_USER,
|
|
61
|
+
clientIp: env.NAMECHEAP_CLIENT_IP,
|
|
62
|
+
enabled: hasNamecheap,
|
|
63
|
+
},
|
|
64
|
+
logLevel: env.LOG_LEVEL || 'info',
|
|
65
|
+
cache: {
|
|
66
|
+
availabilityTtl: parseIntWithDefault(env.CACHE_TTL_AVAILABILITY, 300),
|
|
67
|
+
pricingTtl: parseIntWithDefault(env.CACHE_TTL_PRICING, 3600),
|
|
68
|
+
},
|
|
69
|
+
rateLimitPerMinute: parseIntWithDefault(env.RATE_LIMIT_PER_MINUTE, 60),
|
|
70
|
+
allowedTlds: parseList(env.ALLOWED_TLDS, [
|
|
71
|
+
'com',
|
|
72
|
+
'io',
|
|
73
|
+
'dev',
|
|
74
|
+
'app',
|
|
75
|
+
'co',
|
|
76
|
+
'net',
|
|
77
|
+
'org',
|
|
78
|
+
'xyz',
|
|
79
|
+
'ai',
|
|
80
|
+
'sh',
|
|
81
|
+
'me',
|
|
82
|
+
'cc',
|
|
83
|
+
]),
|
|
84
|
+
denyTlds: parseList(env.DENY_TLDS, [
|
|
85
|
+
'localhost',
|
|
86
|
+
'internal',
|
|
87
|
+
'test',
|
|
88
|
+
'local',
|
|
89
|
+
]),
|
|
90
|
+
dryRun: parseBool(env.DRY_RUN, false),
|
|
91
|
+
};
|
|
92
|
+
return config;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Global config instance.
|
|
96
|
+
* Loaded once at startup.
|
|
97
|
+
*/
|
|
98
|
+
exports.config = loadConfig();
|
|
99
|
+
/**
|
|
100
|
+
* Check if any registrar APIs are configured.
|
|
101
|
+
*/
|
|
102
|
+
function hasRegistrarApi() {
|
|
103
|
+
return exports.config.porkbun.enabled || exports.config.namecheap.enabled;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get a summary of available data sources.
|
|
107
|
+
*/
|
|
108
|
+
function getAvailableSources() {
|
|
109
|
+
const sources = [];
|
|
110
|
+
if (exports.config.porkbun.enabled)
|
|
111
|
+
sources.push('porkbun');
|
|
112
|
+
if (exports.config.namecheap.enabled)
|
|
113
|
+
sources.push('namecheap');
|
|
114
|
+
sources.push('rdap', 'whois'); // Always available as fallbacks
|
|
115
|
+
return sources;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fallbacks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fallback Exports.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getWhoisServer = exports.isWhoisAvailable = exports.checkWhois = exports.isRdapAvailable = exports.checkRdap = void 0;
|
|
7
|
+
var rdap_js_1 = require("./rdap.js");
|
|
8
|
+
Object.defineProperty(exports, "checkRdap", { enumerable: true, get: function () { return rdap_js_1.checkRdap; } });
|
|
9
|
+
Object.defineProperty(exports, "isRdapAvailable", { enumerable: true, get: function () { return rdap_js_1.isRdapAvailable; } });
|
|
10
|
+
var whois_js_1 = require("./whois.js");
|
|
11
|
+
Object.defineProperty(exports, "checkWhois", { enumerable: true, get: function () { return whois_js_1.checkWhois; } });
|
|
12
|
+
Object.defineProperty(exports, "isWhoisAvailable", { enumerable: true, get: function () { return whois_js_1.isWhoisAvailable; } });
|
|
13
|
+
Object.defineProperty(exports, "getWhoisServer", { enumerable: true, get: function () { return whois_js_1.getWhoisServer; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fallbacks/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,qCAAuD;AAA9C,oGAAA,SAAS,OAAA;AAAE,0GAAA,eAAe,OAAA;AACnC,uCAA0E;AAAjE,sGAAA,UAAU,OAAA;AAAE,4GAAA,gBAAgB,OAAA;AAAE,0GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RDAP (Registration Data Access Protocol) Fallback.
|
|
3
|
+
*
|
|
4
|
+
* RFC 7480 - Modern replacement for WHOIS.
|
|
5
|
+
* Provides availability status only (no pricing).
|
|
6
|
+
* Public API - no authentication required.
|
|
7
|
+
*/
|
|
8
|
+
import type { DomainResult } from '../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Check domain availability using RDAP.
|
|
11
|
+
*/
|
|
12
|
+
export declare function checkRdap(domain: string, tld: string): Promise<DomainResult>;
|
|
13
|
+
/**
|
|
14
|
+
* Check if RDAP is available for a TLD (synchronous check).
|
|
15
|
+
* Uses hardcoded servers only for quick check.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isRdapAvailable(tld: string): boolean;
|
|
18
|
+
//# sourceMappingURL=rdap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rdap.d.ts","sourceRoot":"","sources":["../../src/fallbacks/rdap.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAwQhD;;GAEG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,YAAY,CAAC,CAiEvB;AAqDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIpD"}
|