domain-search-mcp 1.0.0 → 1.1.1
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/context7.json +4 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +11 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/check_socials.d.ts.map +1 -1
- package/dist/tools/check_socials.js +7 -6
- package/dist/tools/check_socials.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +5 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/suggest_domains_smart.d.ts +113 -0
- package/dist/tools/suggest_domains_smart.d.ts.map +1 -0
- package/dist/tools/suggest_domains_smart.js +311 -0
- package/dist/tools/suggest_domains_smart.js.map +1 -0
- package/dist/utils/semantic-engine.d.ts +59 -0
- package/dist/utils/semantic-engine.d.ts.map +1 -0
- package/dist/utils/semantic-engine.js +427 -0
- package/dist/utils/semantic-engine.js.map +1 -0
- package/package.json +1 -1
- package/src/server.ts +16 -0
- package/src/tools/check_socials.ts +7 -6
- package/src/tools/index.ts +7 -0
- package/src/tools/suggest_domains_smart.ts +392 -0
- package/src/utils/semantic-engine.ts +483 -0
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Engine for AI-like Domain Suggestions.
|
|
3
|
+
*
|
|
4
|
+
* Provides intelligent domain name generation without external AI dependencies.
|
|
5
|
+
* Uses linguistic algorithms, word databases, and pattern matching.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Common word synonyms for domain name variations.
|
|
10
|
+
*/
|
|
11
|
+
const SYNONYMS: Record<string, string[]> = {
|
|
12
|
+
// Tech terms
|
|
13
|
+
app: ['application', 'software', 'tool', 'platform', 'service'],
|
|
14
|
+
tech: ['technology', 'digital', 'cyber', 'smart', 'intelligent'],
|
|
15
|
+
code: ['coding', 'dev', 'developer', 'programming', 'software'],
|
|
16
|
+
dev: ['developer', 'development', 'code', 'build', 'create'],
|
|
17
|
+
web: ['online', 'internet', 'digital', 'cloud', 'net'],
|
|
18
|
+
cloud: ['sky', 'air', 'vapor', 'hosted', 'saas'],
|
|
19
|
+
data: ['info', 'analytics', 'metrics', 'insights', 'stats'],
|
|
20
|
+
ai: ['intelligent', 'smart', 'ml', 'brain', 'neural', 'cognitive'],
|
|
21
|
+
api: ['connect', 'integrate', 'link', 'bridge', 'hub'],
|
|
22
|
+
|
|
23
|
+
// Business terms
|
|
24
|
+
shop: ['store', 'market', 'mart', 'outlet', 'bazaar', 'emporium'],
|
|
25
|
+
buy: ['purchase', 'get', 'acquire', 'order', 'shop'],
|
|
26
|
+
sell: ['trade', 'market', 'vend', 'deal', 'offer'],
|
|
27
|
+
pay: ['payment', 'checkout', 'billing', 'invoice', 'finance'],
|
|
28
|
+
money: ['cash', 'funds', 'finance', 'capital', 'wealth'],
|
|
29
|
+
business: ['biz', 'enterprise', 'company', 'corp', 'venture'],
|
|
30
|
+
|
|
31
|
+
// Action terms
|
|
32
|
+
get: ['grab', 'fetch', 'obtain', 'acquire', 'access'],
|
|
33
|
+
find: ['search', 'discover', 'locate', 'seek', 'explore'],
|
|
34
|
+
make: ['create', 'build', 'craft', 'forge', 'generate'],
|
|
35
|
+
send: ['deliver', 'ship', 'dispatch', 'transmit', 'share'],
|
|
36
|
+
connect: ['link', 'join', 'unite', 'bridge', 'sync'],
|
|
37
|
+
|
|
38
|
+
// Descriptive terms
|
|
39
|
+
fast: ['quick', 'rapid', 'swift', 'speedy', 'instant', 'turbo'],
|
|
40
|
+
smart: ['clever', 'intelligent', 'bright', 'wise', 'genius'],
|
|
41
|
+
easy: ['simple', 'effortless', 'smooth', 'breeze', 'snap'],
|
|
42
|
+
free: ['gratis', 'open', 'libre', 'zero', 'complimentary'],
|
|
43
|
+
pro: ['professional', 'expert', 'premium', 'elite', 'master'],
|
|
44
|
+
|
|
45
|
+
// Size/Scale
|
|
46
|
+
big: ['large', 'mega', 'giant', 'huge', 'vast', 'grand'],
|
|
47
|
+
small: ['mini', 'tiny', 'micro', 'little', 'compact', 'lite'],
|
|
48
|
+
|
|
49
|
+
// Quality
|
|
50
|
+
best: ['top', 'prime', 'premier', 'superior', 'ultimate', 'optimal'],
|
|
51
|
+
good: ['great', 'awesome', 'excellent', 'superb', 'stellar'],
|
|
52
|
+
new: ['fresh', 'novel', 'modern', 'next', 'neo', 'latest'],
|
|
53
|
+
|
|
54
|
+
// Food & Lifestyle
|
|
55
|
+
food: ['eats', 'cuisine', 'kitchen', 'chef', 'meal', 'dish'],
|
|
56
|
+
coffee: ['cafe', 'brew', 'bean', 'roast', 'espresso', 'java'],
|
|
57
|
+
health: ['wellness', 'fit', 'vital', 'care', 'med', 'life'],
|
|
58
|
+
home: ['house', 'living', 'nest', 'haven', 'dwelling', 'abode'],
|
|
59
|
+
|
|
60
|
+
// Creative
|
|
61
|
+
design: ['creative', 'art', 'studio', 'craft', 'pixel', 'visual'],
|
|
62
|
+
media: ['content', 'channel', 'stream', 'broadcast', 'press'],
|
|
63
|
+
photo: ['image', 'pic', 'snap', 'shot', 'lens', 'capture'],
|
|
64
|
+
video: ['film', 'motion', 'clip', 'reel', 'stream', 'watch'],
|
|
65
|
+
music: ['audio', 'sound', 'tune', 'beat', 'melody', 'sonic'],
|
|
66
|
+
|
|
67
|
+
// Social
|
|
68
|
+
social: ['community', 'network', 'connect', 'share', 'together'],
|
|
69
|
+
team: ['crew', 'squad', 'group', 'tribe', 'collective', 'guild'],
|
|
70
|
+
chat: ['talk', 'message', 'speak', 'convo', 'discuss', 'voice'],
|
|
71
|
+
|
|
72
|
+
// Nature
|
|
73
|
+
green: ['eco', 'earth', 'nature', 'leaf', 'organic', 'bio'],
|
|
74
|
+
blue: ['ocean', 'sky', 'azure', 'aqua', 'marine', 'wave'],
|
|
75
|
+
sun: ['solar', 'bright', 'light', 'ray', 'shine', 'glow'],
|
|
76
|
+
star: ['stellar', 'astro', 'cosmic', 'nova', 'galaxy', 'orbit'],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Industry-specific vocabulary for contextual suggestions.
|
|
81
|
+
*/
|
|
82
|
+
const INDUSTRY_TERMS: Record<string, string[]> = {
|
|
83
|
+
tech: [
|
|
84
|
+
'stack', 'node', 'byte', 'pixel', 'logic', 'algo', 'kernel', 'cache',
|
|
85
|
+
'sync', 'async', 'stream', 'flux', 'vector', 'tensor', 'quantum', 'cyber',
|
|
86
|
+
],
|
|
87
|
+
startup: [
|
|
88
|
+
'launch', 'venture', 'scale', 'pivot', 'disrupt', 'iterate', 'mvp', 'seed',
|
|
89
|
+
'growth', 'unicorn', 'rocket', 'boost', 'accelerate', 'incubate',
|
|
90
|
+
],
|
|
91
|
+
finance: [
|
|
92
|
+
'capital', 'wealth', 'invest', 'fund', 'equity', 'asset', 'profit', 'yield',
|
|
93
|
+
'trade', 'market', 'stock', 'bond', 'crypto', 'defi', 'fintech',
|
|
94
|
+
],
|
|
95
|
+
health: [
|
|
96
|
+
'vital', 'wellness', 'care', 'heal', 'med', 'clinic', 'therapy', 'fit',
|
|
97
|
+
'nutrition', 'balance', 'mind', 'body', 'pulse', 'life', 'cure',
|
|
98
|
+
],
|
|
99
|
+
food: [
|
|
100
|
+
'kitchen', 'chef', 'bistro', 'grill', 'bake', 'fresh', 'organic', 'farm',
|
|
101
|
+
'harvest', 'plate', 'taste', 'flavor', 'spice', 'savory', 'delish',
|
|
102
|
+
],
|
|
103
|
+
creative: [
|
|
104
|
+
'studio', 'canvas', 'palette', 'brush', 'ink', 'craft', 'artisan', 'muse',
|
|
105
|
+
'vision', 'imagine', 'dream', 'inspire', 'spark', 'bloom', 'hue',
|
|
106
|
+
],
|
|
107
|
+
ecommerce: [
|
|
108
|
+
'cart', 'checkout', 'order', 'ship', 'deal', 'offer', 'sale', 'mart',
|
|
109
|
+
'bazaar', 'outlet', 'depot', 'warehouse', 'supply', 'merchant',
|
|
110
|
+
],
|
|
111
|
+
education: [
|
|
112
|
+
'learn', 'teach', 'course', 'class', 'academy', 'scholar', 'study', 'tutor',
|
|
113
|
+
'mentor', 'skill', 'knowledge', 'wisdom', 'genius', 'brain', 'mind',
|
|
114
|
+
],
|
|
115
|
+
gaming: [
|
|
116
|
+
'play', 'game', 'quest', 'level', 'arena', 'battle', 'guild', 'raid',
|
|
117
|
+
'loot', 'spawn', 'realm', 'world', 'epic', 'legend', 'hero',
|
|
118
|
+
],
|
|
119
|
+
social: [
|
|
120
|
+
'connect', 'share', 'follow', 'friend', 'community', 'tribe', 'circle',
|
|
121
|
+
'network', 'gather', 'meetup', 'hangout', 'squad', 'crew', 'vibe',
|
|
122
|
+
],
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Modern domain naming patterns and suffixes.
|
|
127
|
+
*/
|
|
128
|
+
const MODERN_SUFFIXES = [
|
|
129
|
+
'ly', 'ify', 'io', 'ai', 'app', 'hq', 'labs', 'hub', 'now', 'go',
|
|
130
|
+
'up', 'me', 'co', 'so', 'to', 'it', 'os', 'js', 'py', 'dev',
|
|
131
|
+
'cloud', 'base', 'stack', 'flow', 'space', 'zone', 'spot', 'pad',
|
|
132
|
+
'box', 'kit', 'way', 'path', 'link', 'sync', 'dash', 'tap', 'pop',
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Modern domain naming prefixes.
|
|
137
|
+
*/
|
|
138
|
+
const MODERN_PREFIXES = [
|
|
139
|
+
'get', 'try', 'use', 'go', 'hey', 'hi', 'my', 'our', 'the', 'be',
|
|
140
|
+
'on', 'in', 'up', 'do', 'we', 'all', 'one', 'super', 'ultra', 'mega',
|
|
141
|
+
'hyper', 'meta', 'neo', 'pro', 'open', 'true', 'real', 'next', 'ever',
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Word segmentation - detect words in concatenated strings.
|
|
146
|
+
* Uses a dictionary-based approach with common words.
|
|
147
|
+
*/
|
|
148
|
+
const COMMON_WORDS = new Set([
|
|
149
|
+
// Tech
|
|
150
|
+
'app', 'api', 'web', 'dev', 'code', 'tech', 'data', 'cloud', 'ai', 'ml',
|
|
151
|
+
'bot', 'net', 'hub', 'lab', 'labs', 'io', 'bit', 'byte', 'node', 'stack',
|
|
152
|
+
'soft', 'ware', 'software', 'cyber', 'auto', 'smart', 'intel', 'assist',
|
|
153
|
+
// Actions
|
|
154
|
+
'get', 'set', 'put', 'run', 'go', 'do', 'make', 'find', 'buy', 'pay',
|
|
155
|
+
'send', 'sync', 'link', 'chat', 'call', 'meet', 'play', 'work', 'ship',
|
|
156
|
+
'build', 'create', 'start', 'launch', 'grow', 'scale', 'track', 'save',
|
|
157
|
+
// Descriptors
|
|
158
|
+
'big', 'fast', 'easy', 'free', 'new', 'hot', 'cool', 'top', 'best', 'pro',
|
|
159
|
+
'smart', 'super', 'ultra', 'mega', 'mini', 'lite', 'plus', 'prime', 'max',
|
|
160
|
+
'quick', 'rapid', 'swift', 'safe', 'secure', 'clean', 'clear', 'fresh',
|
|
161
|
+
// Business
|
|
162
|
+
'shop', 'store', 'mart', 'deal', 'sale', 'cash', 'pay', 'bill', 'trade',
|
|
163
|
+
'biz', 'corp', 'inc', 'co', 'company', 'brand', 'agency', 'firm',
|
|
164
|
+
// General
|
|
165
|
+
'my', 'our', 'the', 'one', 'all', 'now', 'here', 'next', 'just', 'only',
|
|
166
|
+
'vibe', 'flow', 'wave', 'spark', 'boost', 'dash', 'snap', 'pop', 'buzz',
|
|
167
|
+
'zone', 'spot', 'point', 'base', 'core', 'edge', 'peak', 'rise', 'up',
|
|
168
|
+
// Longer common words
|
|
169
|
+
'hello', 'world', 'cloud', 'space', 'time', 'team', 'group', 'social',
|
|
170
|
+
'media', 'video', 'photo', 'audio', 'music', 'sound', 'voice', 'chat',
|
|
171
|
+
'market', 'money', 'health', 'food', 'home', 'life', 'love', 'star',
|
|
172
|
+
'coding', 'design', 'studio', 'creative', 'digital', 'mobile', 'online',
|
|
173
|
+
// Food & Beverage
|
|
174
|
+
'coffee', 'cafe', 'brew', 'bean', 'tea', 'juice', 'pizza', 'burger', 'taco',
|
|
175
|
+
'chef', 'cook', 'kitchen', 'bakery', 'grill', 'diner', 'bistro', 'eatery',
|
|
176
|
+
// Common compound parts
|
|
177
|
+
'assistant', 'manager', 'finder', 'maker', 'builder', 'tracker', 'planner',
|
|
178
|
+
]);
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Attempt to segment a concatenated string into words.
|
|
182
|
+
*/
|
|
183
|
+
export function segmentWords(input: string): string[] {
|
|
184
|
+
const normalized = input.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
185
|
+
const result: string[] = [];
|
|
186
|
+
let remaining = normalized;
|
|
187
|
+
|
|
188
|
+
while (remaining.length > 0) {
|
|
189
|
+
let found = false;
|
|
190
|
+
|
|
191
|
+
// Try longest match first (up to 12 chars)
|
|
192
|
+
for (let len = Math.min(12, remaining.length); len >= 2; len--) {
|
|
193
|
+
const candidate = remaining.slice(0, len);
|
|
194
|
+
if (COMMON_WORDS.has(candidate)) {
|
|
195
|
+
result.push(candidate);
|
|
196
|
+
remaining = remaining.slice(len);
|
|
197
|
+
found = true;
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// If no word found, take single char and continue
|
|
203
|
+
if (!found) {
|
|
204
|
+
// Try to find a word starting from next position
|
|
205
|
+
let skipCount = 1;
|
|
206
|
+
for (let skip = 1; skip < Math.min(4, remaining.length); skip++) {
|
|
207
|
+
const subRemaining = remaining.slice(skip);
|
|
208
|
+
for (let len = Math.min(12, subRemaining.length); len >= 2; len--) {
|
|
209
|
+
if (COMMON_WORDS.has(subRemaining.slice(0, len))) {
|
|
210
|
+
skipCount = skip;
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Add the prefix as a potential word fragment
|
|
217
|
+
const fragment = remaining.slice(0, skipCount);
|
|
218
|
+
if (fragment.length >= 2) {
|
|
219
|
+
result.push(fragment);
|
|
220
|
+
}
|
|
221
|
+
remaining = remaining.slice(skipCount);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Get synonyms for a word.
|
|
230
|
+
*/
|
|
231
|
+
export function getSynonyms(word: string): string[] {
|
|
232
|
+
const normalized = word.toLowerCase();
|
|
233
|
+
return SYNONYMS[normalized] || [];
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get industry-specific terms.
|
|
238
|
+
*/
|
|
239
|
+
export function getIndustryTerms(industry: string): string[] {
|
|
240
|
+
const normalized = industry.toLowerCase();
|
|
241
|
+
return INDUSTRY_TERMS[normalized] || [];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Detect likely industry from keywords.
|
|
246
|
+
*/
|
|
247
|
+
export function detectIndustry(words: string[]): string | null {
|
|
248
|
+
const wordSet = new Set(words.map(w => w.toLowerCase()));
|
|
249
|
+
|
|
250
|
+
const industryIndicators: Record<string, string[]> = {
|
|
251
|
+
tech: ['app', 'code', 'coding', 'dev', 'tech', 'software', 'api', 'web', 'cloud', 'ai', 'data', 'cyber', 'digital'],
|
|
252
|
+
startup: ['launch', 'venture', 'startup', 'founder', 'scale', 'growth', 'mvp', 'disrupt'],
|
|
253
|
+
finance: ['pay', 'money', 'bank', 'invest', 'trade', 'crypto', 'fund', 'capital', 'finance', 'fintech'],
|
|
254
|
+
health: ['health', 'fit', 'wellness', 'med', 'care', 'clinic', 'therapy', 'vital', 'nutrition'],
|
|
255
|
+
food: ['food', 'eat', 'coffee', 'kitchen', 'chef', 'restaurant', 'cafe', 'bistro', 'brew', 'cook'],
|
|
256
|
+
creative: ['design', 'art', 'studio', 'creative', 'photo', 'video', 'media', 'pixel', 'visual'],
|
|
257
|
+
ecommerce: ['shop', 'store', 'buy', 'sell', 'cart', 'order', 'deal', 'market', 'commerce'],
|
|
258
|
+
education: ['learn', 'teach', 'course', 'academy', 'school', 'tutor', 'study', 'edu', 'skill'],
|
|
259
|
+
gaming: ['game', 'play', 'quest', 'arena', 'guild', 'level', 'gamer', 'esport'],
|
|
260
|
+
social: ['social', 'connect', 'share', 'community', 'network', 'friend', 'chat', 'vibe'],
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
for (const [industry, indicators] of Object.entries(industryIndicators)) {
|
|
264
|
+
for (const indicator of indicators) {
|
|
265
|
+
if (wordSet.has(indicator)) {
|
|
266
|
+
return industry;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Generate portmanteau (blended word) from two words.
|
|
276
|
+
*/
|
|
277
|
+
export function generatePortmanteau(word1: string, word2: string): string[] {
|
|
278
|
+
const results: string[] = [];
|
|
279
|
+
|
|
280
|
+
// Overlap blend: find common letter sequence
|
|
281
|
+
for (let i = 1; i < Math.min(word1.length, 4); i++) {
|
|
282
|
+
const suffix = word1.slice(-i);
|
|
283
|
+
if (word2.toLowerCase().startsWith(suffix.toLowerCase())) {
|
|
284
|
+
results.push(word1 + word2.slice(i));
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Truncation blend: first part + second part
|
|
289
|
+
if (word1.length >= 3 && word2.length >= 3) {
|
|
290
|
+
const blend1 = word1.slice(0, Math.ceil(word1.length * 0.6)) + word2.slice(Math.floor(word2.length * 0.4));
|
|
291
|
+
const blend2 = word1.slice(0, Math.ceil(word1.length * 0.5)) + word2.slice(Math.floor(word2.length * 0.5));
|
|
292
|
+
results.push(blend1, blend2);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return [...new Set(results)].filter(r => r.length >= 4 && r.length <= 15);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Generate creative domain name suggestions.
|
|
300
|
+
*/
|
|
301
|
+
export interface SmartSuggestionOptions {
|
|
302
|
+
maxSuggestions?: number;
|
|
303
|
+
includePortmanteau?: boolean;
|
|
304
|
+
includeSynonyms?: boolean;
|
|
305
|
+
includeIndustryTerms?: boolean;
|
|
306
|
+
industry?: string;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export function generateSmartSuggestions(
|
|
310
|
+
input: string,
|
|
311
|
+
options: SmartSuggestionOptions = {},
|
|
312
|
+
): string[] {
|
|
313
|
+
const {
|
|
314
|
+
maxSuggestions = 50,
|
|
315
|
+
includePortmanteau = true,
|
|
316
|
+
includeSynonyms = true,
|
|
317
|
+
includeIndustryTerms = true,
|
|
318
|
+
industry,
|
|
319
|
+
} = options;
|
|
320
|
+
|
|
321
|
+
const suggestions = new Set<string>();
|
|
322
|
+
const normalized = input.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
323
|
+
|
|
324
|
+
// Add original
|
|
325
|
+
suggestions.add(normalized);
|
|
326
|
+
|
|
327
|
+
// Segment into words
|
|
328
|
+
const words = segmentWords(normalized);
|
|
329
|
+
|
|
330
|
+
// Detect or use provided industry
|
|
331
|
+
const detectedIndustry = industry || detectIndustry(words);
|
|
332
|
+
|
|
333
|
+
// 1. Modern prefix variations
|
|
334
|
+
for (const prefix of MODERN_PREFIXES.slice(0, 15)) {
|
|
335
|
+
suggestions.add(prefix + normalized);
|
|
336
|
+
for (const word of words) {
|
|
337
|
+
if (word.length >= 3) {
|
|
338
|
+
suggestions.add(prefix + word);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// 2. Modern suffix variations
|
|
344
|
+
for (const suffix of MODERN_SUFFIXES.slice(0, 15)) {
|
|
345
|
+
suggestions.add(normalized + suffix);
|
|
346
|
+
for (const word of words) {
|
|
347
|
+
if (word.length >= 3) {
|
|
348
|
+
suggestions.add(word + suffix);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// 3. Synonym-based suggestions
|
|
354
|
+
if (includeSynonyms) {
|
|
355
|
+
for (const word of words) {
|
|
356
|
+
const synonyms = getSynonyms(word);
|
|
357
|
+
for (const synonym of synonyms.slice(0, 3)) {
|
|
358
|
+
// Replace word with synonym
|
|
359
|
+
const newName = words.map(w => w === word ? synonym : w).join('');
|
|
360
|
+
suggestions.add(newName);
|
|
361
|
+
|
|
362
|
+
// Add prefix/suffix to synonym
|
|
363
|
+
suggestions.add('get' + synonym);
|
|
364
|
+
suggestions.add(synonym + 'hub');
|
|
365
|
+
suggestions.add(synonym + 'app');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// 4. Industry-specific suggestions
|
|
371
|
+
if (includeIndustryTerms && detectedIndustry) {
|
|
372
|
+
const industryTerms = getIndustryTerms(detectedIndustry);
|
|
373
|
+
for (const term of industryTerms.slice(0, 8)) {
|
|
374
|
+
suggestions.add(normalized + term);
|
|
375
|
+
suggestions.add(term + normalized);
|
|
376
|
+
for (const word of words) {
|
|
377
|
+
if (word.length >= 3) {
|
|
378
|
+
suggestions.add(word + term);
|
|
379
|
+
suggestions.add(term + word);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// 5. Portmanteau suggestions
|
|
386
|
+
if (includePortmanteau && words.length >= 2) {
|
|
387
|
+
for (let i = 0; i < words.length - 1; i++) {
|
|
388
|
+
const blends = generatePortmanteau(words[i]!, words[i + 1]!);
|
|
389
|
+
for (const blend of blends) {
|
|
390
|
+
suggestions.add(blend);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// 6. Word reordering
|
|
396
|
+
if (words.length >= 2) {
|
|
397
|
+
suggestions.add(words.slice().reverse().join(''));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// 7. Abbreviation suggestions
|
|
401
|
+
if (words.length >= 2) {
|
|
402
|
+
// First letters
|
|
403
|
+
const initials = words.map(w => w[0]).join('');
|
|
404
|
+
if (initials.length >= 2) {
|
|
405
|
+
suggestions.add(initials + 'hub');
|
|
406
|
+
suggestions.add(initials + 'app');
|
|
407
|
+
suggestions.add('go' + initials);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// 8. Vowel removal (modern style)
|
|
412
|
+
const noVowels = normalized.replace(/[aeiou]/g, '');
|
|
413
|
+
if (noVowels.length >= 3 && noVowels !== normalized) {
|
|
414
|
+
suggestions.add(noVowels);
|
|
415
|
+
suggestions.add(noVowels + 'io');
|
|
416
|
+
suggestions.add(noVowels + 'app');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// 9. Double letter simplification
|
|
420
|
+
const simplified = normalized.replace(/(.)\1+/g, '$1');
|
|
421
|
+
if (simplified !== normalized && simplified.length >= 3) {
|
|
422
|
+
suggestions.add(simplified);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// 10. Creative endings
|
|
426
|
+
const creativeEndings = ['ster', 'ery', 'ful', 'ness', 'ize', 'able'];
|
|
427
|
+
for (const ending of creativeEndings) {
|
|
428
|
+
if (!normalized.endsWith(ending)) {
|
|
429
|
+
suggestions.add(normalized + ending);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Filter and return
|
|
434
|
+
return Array.from(suggestions)
|
|
435
|
+
.filter(s => s.length >= 3 && s.length <= 20 && /^[a-z0-9]+$/.test(s))
|
|
436
|
+
.slice(0, maxSuggestions);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Score a domain name based on quality metrics.
|
|
441
|
+
*/
|
|
442
|
+
export function scoreDomainName(name: string, originalInput: string): number {
|
|
443
|
+
let score = 50;
|
|
444
|
+
|
|
445
|
+
// Length preference (shorter is better, but not too short)
|
|
446
|
+
if (name.length <= 6) score += 15;
|
|
447
|
+
else if (name.length <= 8) score += 10;
|
|
448
|
+
else if (name.length <= 10) score += 5;
|
|
449
|
+
else if (name.length > 15) score -= 10;
|
|
450
|
+
|
|
451
|
+
// Exact match bonus
|
|
452
|
+
if (name === originalInput.toLowerCase().replace(/[^a-z0-9]/g, '')) {
|
|
453
|
+
score += 20;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Pronounceability (alternating consonants and vowels is good)
|
|
457
|
+
const vowels = (name.match(/[aeiou]/g) || []).length;
|
|
458
|
+
const ratio = vowels / name.length;
|
|
459
|
+
if (ratio >= 0.25 && ratio <= 0.5) score += 10;
|
|
460
|
+
|
|
461
|
+
// No triple letters
|
|
462
|
+
if (/(.)\1\1/.test(name)) score -= 10;
|
|
463
|
+
|
|
464
|
+
// Starts with common word bonus
|
|
465
|
+
if (COMMON_WORDS.has(name.slice(0, 3)) || COMMON_WORDS.has(name.slice(0, 4))) {
|
|
466
|
+
score += 5;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Modern suffix bonus
|
|
470
|
+
for (const suffix of ['io', 'ai', 'ly', 'ify', 'app', 'hub']) {
|
|
471
|
+
if (name.endsWith(suffix)) {
|
|
472
|
+
score += 5;
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// No numbers (usually cleaner)
|
|
478
|
+
if (!/\d/.test(name)) score += 5;
|
|
479
|
+
|
|
480
|
+
return score;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export { MODERN_SUFFIXES, MODERN_PREFIXES, INDUSTRY_TERMS, SYNONYMS };
|