-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
101 lines (91 loc) · 2.26 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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'use strict'
const graphql = require('./lib/graphql')
const semver = require('semver')
const universalModuleTree = require('universal-module-tree')
const analyze = async ({
dir,
tree,
token,
pageSize: pageSize = 50,
concurrency: concurrency = 5,
onPkgs: onPkgs = () => {},
filter: filter = () => true,
url
}) => {
if (!tree) tree = await readUniversalTree(dir)
const pkgs = filterPkgs(tree, filter)
onPkgs(pkgs)
let data = new Set()
const pages = splitSet(pkgs, pageSize)
const batches = splitSet(pages, concurrency)
for (const batch of batches) {
await Promise.all([...batch].map(async page => {
for (const datum of await fetchData({ pkgs: page, token, url })) {
data.add(datum)
}
}))
}
return data
}
const filterPkgs = (pkgs, fn) => {
const map = new Map()
for (const pkg of pkgs) {
const id = `${pkg.name}${pkg.version}`
if (semver.valid(pkg.version) && !map.get(id) && fn(pkg)) {
map.set(id, pkg)
}
}
const clean = new Set()
for (const [, pkg] of map) clean.add(pkg)
return clean
}
const readUniversalTree = async dir => {
const tree = await universalModuleTree(dir)
const list = universalModuleTree.flatten(tree)
return new Set(list)
}
const fetchData = async ({ pkgs, token, url }) => {
const query = `
query getPackageVersions($packageVersions: [PackageVersionInput!]!) {
packageVersions(packageVersions: $packageVersions) {
name
version
published
publishedAt
scores {
group
name
pass
severity
title
data
}
}
}
`
const variables = {
packageVersions: [...pkgs].map(({ name, version }) => ({ name, version }))
}
const res = await graphql({ token, url }, query, variables)
const data = new Set()
for (const [i, datum] of Object.entries(res.packageVersions)) {
datum.paths = [...pkgs][i].paths
data.add(datum)
}
return data
}
const splitSet = (set, n) => {
const buckets = new Set()
let bucket
for (const member of set) {
if (!bucket) bucket = new Set()
bucket.add(member)
if (bucket.size === n) {
buckets.add(bucket)
bucket = null
}
}
if (bucket) buckets.add(bucket)
return buckets
}
module.exports = analyze