-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
74 lines (57 loc) · 1.89 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"use strict"
const { readFileSync } = require("fs")
const muse = require("datamuse")
const isAvailable = require("npm-name")
const slugify = require("slugify")
const getCachedFile = require("./cache")
const { floor, random } = Math
const wordListUrl =
"https://raw.githubusercontent.com/dwyl/english-words/master/words.txt"
const randomElement = array =>
array[floor(random() * array.length)]
const getRandomWord = () =>
getCachedFile(wordListUrl, "./word-list.txt")
.then(file => readFileSync(file, "utf8").split("\n"))
.then(randomElement)
const toPackageName = word =>
slugify(word, { strict: true }).toLowerCase()
const ensureWord = word =>
word && typeof word === "string"
? Promise.resolve(word)
: getRandomWord().then(ensureWord)
const getWordList = (starter, max = 500) =>
ensureWord(starter)
.then(word => muse.words({ ml: word, max }))
.then(data =>
data && data.length
? data.map(o => toPackageName(o.word))
// try again if we received no data
: getWordList()
)
const getAvailableNames = (keyword, max) =>
getWordList(keyword, max).then(words =>
Promise.all(words.map(isAvailable)).then(availables =>
words.filter((_, i) => availables[i])
)
)
const shuffle = array => {
const clone = array.slice()
let { length } = array
let i
while (length) {
i = floor(random() * length--)
;[clone[i], clone[length]] = [clone[length], clone[i]]
}
return clone
}
module.exports = (keyword, { limit = 50 } = {}) => {
// the actual number of words requested is higher
// than the max set by the user, so that once
// unavailable names are filtered out the user
// will receive a number closer to their set limit
const max = Math.min(1000, limit + 250)
return getAvailableNames(keyword, max).then(names => {
const shuffled = shuffle(names)
return limit ? shuffled.slice(0, limit) : shuffled
})
}