Skip to content

Commit 943b848

Browse files
committedDec 23, 2017
Add first draft of thanc
1 parent d92c951 commit 943b848

File tree

5 files changed

+1174
-0
lines changed

5 files changed

+1174
-0
lines changed
 

‎.gitignore

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Node template
3+
# Logs
4+
logs
5+
*.log
6+
npm-debug.log*
7+
yarn-debug.log*
8+
yarn-error.log*
9+
10+
# Runtime data
11+
pids
12+
*.pid
13+
*.seed
14+
*.pid.lock
15+
16+
# Directory for instrumented libs generated by jscoverage/JSCover
17+
lib-cov
18+
19+
# Coverage directory used by tools like istanbul
20+
coverage
21+
22+
# nyc test coverage
23+
.nyc_output
24+
25+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26+
.grunt
27+
28+
# Bower dependency directory (https://bower.io/)
29+
bower_components
30+
31+
# node-waf configuration
32+
.lock-wscript
33+
34+
# Compiled binary addons (http://nodejs.org/api/addons.html)
35+
build/Release
36+
37+
# Dependency directories
38+
node_modules/
39+
jspm_packages/
40+
41+
# Typescript v1 declaration files
42+
typings/
43+
44+
# Optional npm cache directory
45+
.npm
46+
47+
# Optional eslint cache
48+
.eslintcache
49+
50+
# Optional REPL history
51+
.node_repl_history
52+
53+
# Output of 'npm pack'
54+
*.tgz
55+
56+
# Yarn Integrity file
57+
.yarn-integrity
58+
59+
# dotenv environment variables file
60+
.env
61+
62+
.idea/

‎Dockerfile

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM node:9.3.0-alpine
2+
3+
WORKDIR /opt/app
4+
5+
CMD ["node", "index.js"]

‎index.js

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
const RegistryClient = require('npm-registry-client')
2+
const client = new RegistryClient()
3+
const NPM_REGISTRY_URL = 'https://registry.npmjs.org'
4+
const GITHUB_API_URL = 'https://api.github.com'
5+
const GITHUB_STAR_URL = `${GITHUB_API_URL}/user/starred`
6+
const axios = require('axios')
7+
const prompt = require('prompt')
8+
const fs = require('fs')
9+
const util = require('util')
10+
const asyncReadFile = util.promisify(fs.readFile)
11+
const EXIT_FAILURE = 1
12+
const DEFAULT_PACKAGE_LOCK_PATH = `${__dirname}/package-lock.json`
13+
14+
const schema = {
15+
properties: {
16+
username: {
17+
description: 'Your github username',
18+
type: 'string',
19+
required: true
20+
},
21+
password: {
22+
description: 'Your github password',
23+
type: 'string',
24+
hidden: true,
25+
required: true
26+
},
27+
packageLockPath: {
28+
description: 'Your package-lock.json path',
29+
type: 'string',
30+
default: DEFAULT_PACKAGE_LOCK_PATH
31+
}
32+
}
33+
}
34+
35+
// get user info
36+
const getUserInfo = schema => {
37+
return new Promise((resolve, reject) => {
38+
prompt.get(schema, function (err, data) {
39+
if (err) reject(err)
40+
else resolve(data)
41+
})
42+
})
43+
}
44+
45+
(async () => {
46+
prompt.start()
47+
48+
// getting credentials from the user
49+
let userInfo
50+
try {
51+
console.log('Requesting user info...')
52+
userInfo = await getUserInfo(schema)
53+
console.log('done!')
54+
} catch (err) {
55+
console.log('Cannot fetch github user credentials')
56+
console.error(err)
57+
58+
process.exit(EXIT_FAILURE)
59+
}
60+
61+
// testing credentials
62+
const auth = {username: userInfo.username, password: userInfo.password}
63+
try {
64+
console.log('Testing github credentials...')
65+
await axios({url: GITHUB_API_URL, method: 'get', auth})
66+
console.log('done!')
67+
} catch (err) {
68+
console.log('Invalid credentials or maximum number of login attempts exceeded')
69+
console.error(err)
70+
71+
process.exit(EXIT_FAILURE)
72+
}
73+
74+
// reading package-lock.json
75+
let pkg
76+
try {
77+
console.log('Reading package-lock.json...')
78+
const rawPackageLock = await asyncReadFile(userInfo.packageLockPath, 'utf-8')
79+
pkg = JSON.parse(rawPackageLock)
80+
console.log('done!')
81+
} catch (err) {
82+
console.log('Cannot read package-lock.json')
83+
console.error(err)
84+
85+
process.exit(EXIT_FAILURE)
86+
}
87+
88+
// generating deps repos promises
89+
const depsPromises = Object.keys(pkg.dependencies).map(dep => {
90+
return new Promise((resolve, reject) => {
91+
client.get(`${NPM_REGISTRY_URL}/${dep}`, {}, (err, data) => {
92+
if (err) reject(err)
93+
else resolve(data.versions[pkg.dependencies[dep].version])
94+
})
95+
})
96+
})
97+
98+
// getting deps repos
99+
let deps = []
100+
try {
101+
console.log('Getting dependencies...')
102+
deps = await Promise.all(depsPromises)
103+
console.log('done!')
104+
} catch (err) {
105+
console.log('Cannot fetch dependencies\' repos')
106+
console.error(err)
107+
108+
process.exit(EXIT_FAILURE)
109+
}
110+
111+
// generating repos object: keys are repos and values are owners
112+
const repos = {}
113+
deps.forEach((detail) => {
114+
if (!detail.repository) return
115+
116+
const splitUrl = detail.repository.url.split('/')
117+
repos[splitUrl[splitUrl.length - 1].replace('.git', '')] = splitUrl[splitUrl.length - 2]
118+
})
119+
120+
// starring repos
121+
try {
122+
console.log('Starring dependencies...')
123+
await Promise.all(Object.keys(repos).map(repo => axios({url: `${GITHUB_STAR_URL}/${repos[repo]}/${repo}`, method: 'put', auth})))
124+
console.log('done!')
125+
} catch (err) {
126+
console.log('Cannot star dependencies')
127+
console.error(err)
128+
129+
process.exit(EXIT_FAILURE)
130+
}
131+
})()

‎package-lock.json

+960
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "thanc",
3+
"version": "1.0.0",
4+
"description": "Thanc: a smart way to thank NPM packages authors by starring their repos",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"author": "",
10+
"license": "MIT",
11+
"dependencies": {
12+
"axios": "^0.17.1",
13+
"npm-registry-client": "^8.5.0",
14+
"prompt": "^1.0.0"
15+
}
16+
}

0 commit comments

Comments
 (0)
Please sign in to comment.