Skip to content

Commit 8f7abbe

Browse files
committed
deps: npm-packlist@5.1.3
1 parent b12ac01 commit 8f7abbe

File tree

16 files changed

+821
-10
lines changed

16 files changed

+821
-10
lines changed

DEPENDENCIES.md

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ graph LR;
106106
npm-->npm-audit-report;
107107
npm-->npm-install-checks;
108108
npm-->npm-package-arg;
109+
npm-->npm-packlist;
109110
npm-->npm-profile;
110111
npm-->npm-registry-fetch;
111112
npm-->npm-user-validate;
@@ -510,6 +511,7 @@ graph LR;
510511
npm-->npm-audit-report;
511512
npm-->npm-install-checks;
512513
npm-->npm-package-arg;
514+
npm-->npm-packlist;
513515
npm-->npm-pick-manifest;
514516
npm-->npm-profile;
515517
npm-->npm-registry-fetch;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The ISC License
2+
3+
Copyright (c) npm, Inc. and Contributors
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
'use strict'
2+
3+
// walk the tree of deps starting from the top level list of bundled deps
4+
// Any deps at the top level that are depended on by a bundled dep that
5+
// does not have that dep in its own node_modules folder are considered
6+
// bundled deps as well. This list of names can be passed to npm-packlist
7+
// as the "bundled" argument. Additionally, packageJsonCache is shared so
8+
// packlist doesn't have to re-read files already consumed in this pass
9+
10+
const fs = require('fs')
11+
const path = require('path')
12+
const EE = require('events').EventEmitter
13+
// we don't care about the package bins, but we share a pj cache
14+
// with other modules that DO care about it, so keep it nice.
15+
const normalizePackageBin = require('npm-normalize-package-bin')
16+
17+
class BundleWalker extends EE {
18+
constructor (opt) {
19+
opt = opt || {}
20+
super(opt)
21+
this.path = path.resolve(opt.path || process.cwd())
22+
23+
this.parent = opt.parent || null
24+
if (this.parent) {
25+
this.result = this.parent.result
26+
// only collect results in node_modules folders at the top level
27+
// since the node_modules in a bundled dep is included always
28+
if (!this.parent.parent) {
29+
const base = path.basename(this.path)
30+
const scope = path.basename(path.dirname(this.path))
31+
this.result.add(/^@/.test(scope) ? scope + '/' + base : base)
32+
}
33+
this.root = this.parent.root
34+
this.packageJsonCache = this.parent.packageJsonCache
35+
} else {
36+
this.result = new Set()
37+
this.root = this.path
38+
this.packageJsonCache = opt.packageJsonCache || new Map()
39+
}
40+
41+
this.seen = new Set()
42+
this.didDone = false
43+
this.children = 0
44+
this.node_modules = []
45+
this.package = null
46+
this.bundle = null
47+
}
48+
49+
addListener (ev, fn) {
50+
return this.on(ev, fn)
51+
}
52+
53+
on (ev, fn) {
54+
const ret = super.on(ev, fn)
55+
if (ev === 'done' && this.didDone) {
56+
this.emit('done', this.result)
57+
}
58+
return ret
59+
}
60+
61+
done () {
62+
if (!this.didDone) {
63+
this.didDone = true
64+
if (!this.parent) {
65+
const res = Array.from(this.result)
66+
this.result = res
67+
this.emit('done', res)
68+
} else {
69+
this.emit('done')
70+
}
71+
}
72+
}
73+
74+
start () {
75+
const pj = path.resolve(this.path, 'package.json')
76+
if (this.packageJsonCache.has(pj)) {
77+
this.onPackage(this.packageJsonCache.get(pj))
78+
} else {
79+
this.readPackageJson(pj)
80+
}
81+
return this
82+
}
83+
84+
readPackageJson (pj) {
85+
fs.readFile(pj, (er, data) =>
86+
er ? this.done() : this.onPackageJson(pj, data))
87+
}
88+
89+
onPackageJson (pj, data) {
90+
try {
91+
this.package = normalizePackageBin(JSON.parse(data + ''))
92+
} catch (er) {
93+
return this.done()
94+
}
95+
this.packageJsonCache.set(pj, this.package)
96+
this.onPackage(this.package)
97+
}
98+
99+
allDepsBundled (pkg) {
100+
return Object.keys(pkg.dependencies || {}).concat(
101+
Object.keys(pkg.optionalDependencies || {}))
102+
}
103+
104+
onPackage (pkg) {
105+
// all deps are bundled if we got here as a child.
106+
// otherwise, only bundle bundledDeps
107+
// Get a unique-ified array with a short-lived Set
108+
const bdRaw = this.parent ? this.allDepsBundled(pkg)
109+
: pkg.bundleDependencies || pkg.bundledDependencies || []
110+
111+
const bd = Array.from(new Set(
112+
Array.isArray(bdRaw) ? bdRaw
113+
: bdRaw === true ? this.allDepsBundled(pkg)
114+
: Object.keys(bdRaw)))
115+
116+
if (!bd.length) {
117+
return this.done()
118+
}
119+
120+
this.bundle = bd
121+
this.readModules()
122+
}
123+
124+
readModules () {
125+
readdirNodeModules(this.path + '/node_modules', (er, nm) =>
126+
er ? this.onReaddir([]) : this.onReaddir(nm))
127+
}
128+
129+
onReaddir (nm) {
130+
// keep track of what we have, in case children need it
131+
this.node_modules = nm
132+
133+
this.bundle.forEach(dep => this.childDep(dep))
134+
if (this.children === 0) {
135+
this.done()
136+
}
137+
}
138+
139+
childDep (dep) {
140+
if (this.node_modules.indexOf(dep) !== -1) {
141+
if (!this.seen.has(dep)) {
142+
this.seen.add(dep)
143+
this.child(dep)
144+
}
145+
} else if (this.parent) {
146+
this.parent.childDep(dep)
147+
}
148+
}
149+
150+
child (dep) {
151+
const p = this.path + '/node_modules/' + dep
152+
this.children += 1
153+
const child = new BundleWalker({
154+
path: p,
155+
parent: this,
156+
})
157+
child.on('done', _ => {
158+
if (--this.children === 0) {
159+
this.done()
160+
}
161+
})
162+
child.start()
163+
}
164+
}
165+
166+
class BundleWalkerSync extends BundleWalker {
167+
start () {
168+
super.start()
169+
this.done()
170+
return this
171+
}
172+
173+
readPackageJson (pj) {
174+
try {
175+
this.onPackageJson(pj, fs.readFileSync(pj))
176+
} catch {
177+
// empty catch
178+
}
179+
return this
180+
}
181+
182+
readModules () {
183+
try {
184+
this.onReaddir(readdirNodeModulesSync(this.path + '/node_modules'))
185+
} catch {
186+
this.onReaddir([])
187+
}
188+
}
189+
190+
child (dep) {
191+
new BundleWalkerSync({
192+
path: this.path + '/node_modules/' + dep,
193+
parent: this,
194+
}).start()
195+
}
196+
}
197+
198+
const readdirNodeModules = (nm, cb) => {
199+
fs.readdir(nm, (er, set) => {
200+
if (er) {
201+
cb(er)
202+
} else {
203+
const scopes = set.filter(f => /^@/.test(f))
204+
if (!scopes.length) {
205+
cb(null, set)
206+
} else {
207+
const unscoped = set.filter(f => !/^@/.test(f))
208+
let count = scopes.length
209+
scopes.forEach(scope => {
210+
fs.readdir(nm + '/' + scope, (readdirEr, pkgs) => {
211+
if (readdirEr || !pkgs.length) {
212+
unscoped.push(scope)
213+
} else {
214+
unscoped.push.apply(unscoped, pkgs.map(p => scope + '/' + p))
215+
}
216+
if (--count === 0) {
217+
cb(null, unscoped)
218+
}
219+
})
220+
})
221+
}
222+
}
223+
})
224+
}
225+
226+
const readdirNodeModulesSync = nm => {
227+
const set = fs.readdirSync(nm)
228+
const unscoped = set.filter(f => !/^@/.test(f))
229+
const scopes = set.filter(f => /^@/.test(f)).map(scope => {
230+
try {
231+
const pkgs = fs.readdirSync(nm + '/' + scope)
232+
return pkgs.length ? pkgs.map(p => scope + '/' + p) : [scope]
233+
} catch (er) {
234+
return [scope]
235+
}
236+
}).reduce((a, b) => a.concat(b), [])
237+
return unscoped.concat(scopes)
238+
}
239+
240+
const walk = (options, callback) => {
241+
const p = new Promise((resolve, reject) => {
242+
new BundleWalker(options).on('done', resolve).on('error', reject).start()
243+
})
244+
return callback ? p.then(res => callback(null, res), callback) : p
245+
}
246+
247+
const walkSync = options => {
248+
return new BundleWalkerSync(options).start().result
249+
}
250+
251+
module.exports = walk
252+
walk.sync = walkSync
253+
walk.BundleWalker = BundleWalker
254+
walk.BundleWalkerSync = BundleWalkerSync
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The ISC License
2+
3+
Copyright (c) npm, Inc.
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// pass in a manifest with a 'bin' field here, and it'll turn it
2+
// into a properly santized bin object
3+
const {join, basename} = require('path')
4+
5+
const normalize = pkg =>
6+
!pkg.bin ? removeBin(pkg)
7+
: typeof pkg.bin === 'string' ? normalizeString(pkg)
8+
: Array.isArray(pkg.bin) ? normalizeArray(pkg)
9+
: typeof pkg.bin === 'object' ? normalizeObject(pkg)
10+
: removeBin(pkg)
11+
12+
const normalizeString = pkg => {
13+
if (!pkg.name)
14+
return removeBin(pkg)
15+
pkg.bin = { [pkg.name]: pkg.bin }
16+
return normalizeObject(pkg)
17+
}
18+
19+
const normalizeArray = pkg => {
20+
pkg.bin = pkg.bin.reduce((acc, k) => {
21+
acc[basename(k)] = k
22+
return acc
23+
}, {})
24+
return normalizeObject(pkg)
25+
}
26+
27+
const removeBin = pkg => {
28+
delete pkg.bin
29+
return pkg
30+
}
31+
32+
const normalizeObject = pkg => {
33+
const orig = pkg.bin
34+
const clean = {}
35+
let hasBins = false
36+
Object.keys(orig).forEach(binKey => {
37+
const base = join('/', basename(binKey.replace(/\\|:/g, '/'))).substr(1)
38+
39+
if (typeof orig[binKey] !== 'string' || !base)
40+
return
41+
42+
const binTarget = join('/', orig[binKey])
43+
.replace(/\\/g, '/').substr(1)
44+
45+
if (!binTarget)
46+
return
47+
48+
clean[base] = binTarget
49+
hasBins = true
50+
})
51+
52+
if (hasBins)
53+
pkg.bin = clean
54+
else
55+
delete pkg.bin
56+
57+
return pkg
58+
}
59+
60+
module.exports = normalize
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "npm-normalize-package-bin",
3+
"version": "1.0.1",
4+
"description": "Turn any flavor of allowable package.json bin into a normalized object",
5+
"repository": "git+https://github.com/npm/npm-normalize-package-bin",
6+
"author": "Isaac Z. Schlueter <i@izs.me> (https://izs.me)",
7+
"license": "ISC",
8+
"scripts": {
9+
"test": "tap",
10+
"snap": "tap",
11+
"preversion": "npm test",
12+
"postversion": "npm publish",
13+
"postpublish": "git push origin --follow-tags"
14+
},
15+
"tap": {
16+
"check-coverage": true
17+
},
18+
"devDependencies": {
19+
"tap": "^14.10.2"
20+
}
21+
}

0 commit comments

Comments
 (0)