source: trip-planner-front/node_modules/npm-bundled/index.js@ 59329aa

Last change on this file since 59329aa was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 6.3 KB
Line 
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
10const fs = require('fs')
11const path = require('path')
12const 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.
15const normalizePackageBin = require('npm-normalize-package-bin')
16
17class 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 return this
81 }
82
83 readPackageJson (pj) {
84 fs.readFile(pj, (er, data) =>
85 er ? this.done() : this.onPackageJson(pj, data))
86 }
87
88 onPackageJson (pj, data) {
89 try {
90 this.package = normalizePackageBin(JSON.parse(data + ''))
91 } catch (er) {
92 return this.done()
93 }
94 this.packageJsonCache.set(pj, this.package)
95 this.onPackage(this.package)
96 }
97
98 allDepsBundled (pkg) {
99 return Object.keys(pkg.dependencies || {}).concat(
100 Object.keys(pkg.optionalDependencies || {}))
101 }
102
103 onPackage (pkg) {
104 // all deps are bundled if we got here as a child.
105 // otherwise, only bundle bundledDeps
106 // Get a unique-ified array with a short-lived Set
107 const bdRaw = this.parent ? this.allDepsBundled(pkg)
108 : pkg.bundleDependencies || pkg.bundledDependencies || []
109
110 const bd = Array.from(new Set(
111 Array.isArray(bdRaw) ? bdRaw
112 : bdRaw === true ? this.allDepsBundled(pkg)
113 : Object.keys(bdRaw)))
114
115 if (!bd.length)
116 return this.done()
117
118 this.bundle = bd
119 const nm = this.path + '/node_modules'
120 this.readModules()
121 }
122
123 readModules () {
124 readdirNodeModules(this.path + '/node_modules', (er, nm) =>
125 er ? this.onReaddir([]) : this.onReaddir(nm))
126 }
127
128 onReaddir (nm) {
129 // keep track of what we have, in case children need it
130 this.node_modules = nm
131
132 this.bundle.forEach(dep => this.childDep(dep))
133 if (this.children === 0)
134 this.done()
135 }
136
137 childDep (dep) {
138 if (this.node_modules.indexOf(dep) !== -1) {
139 if (!this.seen.has(dep)) {
140 this.seen.add(dep)
141 this.child(dep)
142 }
143 } else if (this.parent) {
144 this.parent.childDep(dep)
145 }
146 }
147
148 child (dep) {
149 const p = this.path + '/node_modules/' + dep
150 this.children += 1
151 const child = new BundleWalker({
152 path: p,
153 parent: this
154 })
155 child.on('done', _ => {
156 if (--this.children === 0)
157 this.done()
158 })
159 child.start()
160 }
161}
162
163class BundleWalkerSync extends BundleWalker {
164 constructor (opt) {
165 super(opt)
166 }
167
168 start () {
169 super.start()
170 this.done()
171 return this
172 }
173
174 readPackageJson (pj) {
175 try {
176 this.onPackageJson(pj, fs.readFileSync(pj))
177 } catch (er) {}
178 return this
179 }
180
181 readModules () {
182 try {
183 this.onReaddir(readdirNodeModulesSync(this.path + '/node_modules'))
184 } catch (er) {
185 this.onReaddir([])
186 }
187 }
188
189 child (dep) {
190 new BundleWalkerSync({
191 path: this.path + '/node_modules/' + dep,
192 parent: this
193 }).start()
194 }
195}
196
197const readdirNodeModules = (nm, cb) => {
198 fs.readdir(nm, (er, set) => {
199 if (er)
200 cb(er)
201 else {
202 const scopes = set.filter(f => /^@/.test(f))
203 if (!scopes.length)
204 cb(null, set)
205 else {
206 const unscoped = set.filter(f => !/^@/.test(f))
207 let count = scopes.length
208 scopes.forEach(scope => {
209 fs.readdir(nm + '/' + scope, (er, pkgs) => {
210 if (er || !pkgs.length)
211 unscoped.push(scope)
212 else
213 unscoped.push.apply(unscoped, pkgs.map(p => scope + '/' + p))
214 if (--count === 0)
215 cb(null, unscoped)
216 })
217 })
218 }
219 }
220 })
221}
222
223const readdirNodeModulesSync = nm => {
224 const set = fs.readdirSync(nm)
225 const unscoped = set.filter(f => !/^@/.test(f))
226 const scopes = set.filter(f => /^@/.test(f)).map(scope => {
227 try {
228 const pkgs = fs.readdirSync(nm + '/' + scope)
229 return pkgs.length ? pkgs.map(p => scope + '/' + p) : [scope]
230 } catch (er) {
231 return [scope]
232 }
233 }).reduce((a, b) => a.concat(b), [])
234 return unscoped.concat(scopes)
235}
236
237const walk = (options, callback) => {
238 const p = new Promise((resolve, reject) => {
239 new BundleWalker(options).on('done', resolve).on('error', reject).start()
240 })
241 return callback ? p.then(res => callback(null, res), callback) : p
242}
243
244const walkSync = options => {
245 return new BundleWalkerSync(options).start().result
246}
247
248module.exports = walk
249walk.sync = walkSync
250walk.BundleWalker = BundleWalker
251walk.BundleWalkerSync = BundleWalkerSync
Note: See TracBrowser for help on using the repository browser.