]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.maps.server/node/node-v4.8.0-win-x64/node_modules/npm/node_modules/read-installed/read-installed.js
Adding integrated tile server
[simantics/district.git] / org.simantics.maps.server / node / node-v4.8.0-win-x64 / node_modules / npm / node_modules / read-installed / read-installed.js
1
2 // Walk through the file-system "database" of installed
3 // packages, and create a data object related to the
4 // installed versions of each package.
5
6 /*
7 This will traverse through all node_modules folders,
8 resolving the dependencies object to the object corresponding to
9 the package that meets that dep, or just the version/range if
10 unmet.
11
12 Assuming that you had this folder structure:
13
14 /path/to
15 +-- package.json { name = "root" }
16 `-- node_modules
17     +-- foo {bar, baz, asdf}
18     | +-- node_modules
19     |   +-- bar { baz }
20     |   `-- baz
21     `-- asdf
22
23 where "foo" depends on bar, baz, and asdf, bar depends on baz,
24 and bar and baz are bundled with foo, whereas "asdf" is at
25 the higher level (sibling to foo), you'd get this object structure:
26
27 { <package.json data>
28 , path: "/path/to"
29 , parent: null
30 , dependencies:
31   { foo :
32     { version: "1.2.3"
33     , path: "/path/to/node_modules/foo"
34     , parent: <Circular: root>
35     , dependencies:
36       { bar:
37         { parent: <Circular: foo>
38         , path: "/path/to/node_modules/foo/node_modules/bar"
39         , version: "2.3.4"
40         , dependencies: { baz: <Circular: foo.dependencies.baz> }
41         }
42       , baz: { ... }
43       , asdf: <Circular: asdf>
44       }
45     }
46   , asdf: { ... }
47   }
48 }
49
50 Unmet deps are left as strings.
51 Extraneous deps are marked with extraneous:true
52 deps that don't meet a requirement are marked with invalid:true
53 deps that don't meet a peer requirement are marked with peerInvalid:true
54
55 to READ(packagefolder, parentobj, name, reqver)
56 obj = read package.json
57 installed = ./node_modules/*
58 if parentobj is null, and no package.json
59   obj = {dependencies:{<installed>:ANY}}
60 deps = Object.keys(obj.dependencies)
61 obj.path = packagefolder
62 obj.parent = parentobj
63 if name, && obj.name !== name, obj.invalid = true
64 if reqver, && obj.version !satisfies reqver, obj.invalid = true
65 if !reqver && parentobj, obj.extraneous = true
66 for each folder in installed
67   obj.dependencies[folder] = READ(packagefolder+node_modules+folder,
68                                   obj, folder, obj.dependencies[folder])
69 # walk tree to find unmet deps
70 for each dep in obj.dependencies not in installed
71   r = obj.parent
72   while r
73     if r.dependencies[dep]
74       if r.dependencies[dep].verion !satisfies obj.dependencies[dep]
75         WARN
76         r.dependencies[dep].invalid = true
77       obj.dependencies[dep] = r.dependencies[dep]
78       r = null
79     else r = r.parent
80 return obj
81
82
83 TODO:
84 1. Find unmet deps in parent directories, searching as node does up
85 as far as the left-most node_modules folder.
86 2. Ignore anything in node_modules that isn't a package folder.
87
88 */
89
90 try {
91   var fs = require("graceful-fs")
92 } catch (er) {
93   var fs = require("fs")
94 }
95
96 var path = require("path")
97 var asyncMap = require("slide").asyncMap
98 var semver = require("semver")
99 var readJson = require("read-package-json")
100 var url = require("url")
101 var util = require("util")
102 var extend = require("util-extend")
103
104 var debug = require("debuglog")("read-installed")
105
106 var readdir = require("readdir-scoped-modules")
107
108 // Sentinel catch-all version constraint used when a dependency is not
109 // listed in the package.json file.
110 var ANY = {}
111
112 module.exports = readInstalled
113
114 function readInstalled (folder, opts, cb) {
115   if (typeof opts === 'function') {
116     cb = opts
117     opts = {}
118   } else {
119     opts = extend({}, opts)
120   }
121
122   if (typeof opts.depth !== 'number')
123     opts.depth = Infinity
124
125   opts.depth = Math.max(0, opts.depth)
126
127   if (typeof opts.log !== 'function')
128     opts.log = function () {}
129
130   opts.dev = !!opts.dev
131   opts.realpathSeen = {}
132   opts.findUnmetSeen = []
133
134
135   readInstalled_(folder, null, null, null, 0, opts, function (er, obj) {
136     if (er) return cb(er)
137     // now obj has all the installed things, where they're installed
138     // figure out the inheritance links, now that the object is built.
139     resolveInheritance(obj, opts)
140     obj.root = true
141     unmarkExtraneous(obj, opts)
142     cb(null, obj)
143   })
144 }
145
146 function readInstalled_ (folder, parent, name, reqver, depth, opts, cb) {
147   var installed
148     , obj
149     , real
150     , link
151     , realpathSeen = opts.realpathSeen
152
153   readdir(path.resolve(folder, "node_modules"), function (er, i) {
154     // error indicates that nothing is installed here
155     if (er) i = []
156     installed = i.filter(function (f) { return f.charAt(0) !== "." })
157     next()
158   })
159
160   readJson(path.resolve(folder, "package.json"), function (er, data) {
161     obj = copy(data)
162
163     if (!parent) {
164       obj = obj || true
165       er = null
166     }
167     return next(er)
168   })
169
170   fs.lstat(folder, function (er, st) {
171     if (er) {
172       if (!parent) real = true
173       return next(er)
174     }
175     fs.realpath(folder, function (er, rp) {
176       debug("realpath(%j) = %j", folder, rp)
177       real = rp
178       if (st.isSymbolicLink()) link = rp
179       next(er)
180     })
181   })
182
183   var errState = null
184     , called = false
185   function next (er) {
186     if (errState) return
187     if (er) {
188       errState = er
189       return cb(null, [])
190     }
191     debug('next', installed, obj && typeof obj, name, real)
192     if (!installed || !obj || !real || called) return
193     called = true
194     if (realpathSeen[real]) return cb(null, realpathSeen[real])
195     if (obj === true) {
196       obj = {dependencies:{}, path:folder}
197       installed.forEach(function (i) { obj.dependencies[i] = ANY })
198     }
199     if (name && obj.name !== name) obj.invalid = true
200     obj.realName = name || obj.name
201     obj.dependencies = obj.dependencies || {}
202
203     // At this point, figure out what dependencies we NEED to get met
204     obj._dependencies = copy(obj.dependencies)
205
206     if (reqver === ANY) {
207       // We were unable to determine the required version of this
208       // dependency from the package.json file, but we now know its actual
209       // version, so treat that version as the required version to avoid
210       // marking the dependency as invalid below. See #40.
211       reqver = obj.version;
212     }
213
214     // "foo":"http://blah" and "foo":"latest" are always presumed valid
215     if (reqver
216         && semver.validRange(reqver, true)
217         && !semver.satisfies(obj.version, reqver, true)) {
218       obj.invalid = true
219     }
220
221     // Mark as extraneous at this point.
222     // This will be un-marked in unmarkExtraneous, where we mark as
223     // not-extraneous everything that is required in some way from
224     // the root object.
225     obj.extraneous = true
226
227     obj.path = obj.path || folder
228     obj.realPath = real
229     obj.link = link
230     if (parent && !obj.link) obj.parent = parent
231     realpathSeen[real] = obj
232     obj.depth = depth
233     //if (depth >= opts.depth) return cb(null, obj)
234     asyncMap(installed, function (pkg, cb) {
235       var rv = obj.dependencies[pkg]
236       if (!rv && obj.devDependencies && opts.dev)
237         rv = obj.devDependencies[pkg]
238
239       if (depth > opts.depth) {
240         obj.dependencies = {}
241         return cb(null, obj)
242       }
243
244       readInstalled_( path.resolve(folder, "node_modules/"+pkg)
245                     , obj, pkg, obj.dependencies[pkg], depth + 1, opts
246                     , cb )
247
248     }, function (er, installedData) {
249       if (er) return cb(er)
250       installedData.forEach(function (dep) {
251         obj.dependencies[dep.realName] = dep
252       })
253
254       // any strings here are unmet things.  however, if it's
255       // optional, then that's fine, so just delete it.
256       if (obj.optionalDependencies) {
257         Object.keys(obj.optionalDependencies).forEach(function (dep) {
258           if (typeof obj.dependencies[dep] === "string") {
259             delete obj.dependencies[dep]
260           }
261         })
262       }
263       return cb(null, obj)
264     })
265   }
266 }
267
268 // starting from a root object, call findUnmet on each layer of children
269 var riSeen = []
270 function resolveInheritance (obj, opts) {
271   if (typeof obj !== "object") return
272   if (riSeen.indexOf(obj) !== -1) return
273   riSeen.push(obj)
274   if (typeof obj.dependencies !== "object") {
275     obj.dependencies = {}
276   }
277   Object.keys(obj.dependencies).forEach(function (dep) {
278     findUnmet(obj.dependencies[dep], opts)
279   })
280   Object.keys(obj.dependencies).forEach(function (dep) {
281     if (typeof obj.dependencies[dep] === "object") {
282       resolveInheritance(obj.dependencies[dep], opts)
283     } else {
284       debug("unmet dep! %s %s@%s", obj.name, dep, obj.dependencies[dep])
285     }
286   })
287   findUnmet(obj, opts)
288 }
289
290 // find unmet deps by walking up the tree object.
291 // No I/O
292 function findUnmet (obj, opts) {
293   var findUnmetSeen = opts.findUnmetSeen
294   if (findUnmetSeen.indexOf(obj) !== -1) return
295   findUnmetSeen.push(obj)
296   debug("find unmet parent=%s obj=", obj.parent && obj.parent.name, obj.name || obj)
297   var deps = obj.dependencies = obj.dependencies || {}
298
299   debug(deps)
300   Object.keys(deps)
301     .filter(function (d) { return typeof deps[d] === "string" })
302     .forEach(function (d) {
303       var found = findDep(obj, d)
304       debug("finding dep %j", d, found && found.name || found)
305       // "foo":"http://blah" and "foo":"latest" are always presumed valid
306       if (typeof deps[d] === "string" &&
307           semver.validRange(deps[d], true) &&
308           found &&
309           !semver.satisfies(found.version, deps[d], true)) {
310         // the bad thing will happen
311         opts.log( "unmet dependency"
312                 , obj.path + " requires "+d+"@'"+deps[d]
313                 + "' but will load\n"
314                 + found.path+",\nwhich is version "+found.version )
315         found.invalid = true
316       }
317       if (found) {
318         deps[d] = found
319       }
320     })
321
322   var peerDeps = obj.peerDependencies = obj.peerDependencies || {}
323   Object.keys(peerDeps).forEach(function (d) {
324     var dependency
325
326     if (!obj.parent) {
327       dependency = obj.dependencies[d]
328
329       // read it as a missing dep
330       if (!dependency) {
331         obj.dependencies[d] = peerDeps[d]
332       }
333     } else {
334       var r = obj.parent
335       while (r && !dependency) {
336         dependency = r.dependencies && r.dependencies[d]
337         r = r.link ? null : r.parent
338       }
339     }
340
341     if (!dependency) {
342       // mark as a missing dep!
343       obj.dependencies[d] = peerDeps[d]
344     } else if (!semver.satisfies(dependency.version, peerDeps[d], true)) {
345       dependency.peerInvalid = true
346     }
347   })
348
349   return obj
350 }
351
352 function unmarkExtraneous (obj, opts) {
353   // Mark all non-required deps as extraneous.
354   // start from the root object and mark as non-extraneous all modules
355   // that haven't been previously flagged as extraneous then propagate
356   // to all their dependencies
357
358   obj.extraneous = false
359
360   var deps = obj._dependencies || []
361   if (opts.dev && obj.devDependencies && (obj.root || obj.link)) {
362     Object.keys(obj.devDependencies).forEach(function (k) {
363       deps[k] = obj.devDependencies[k]
364     })
365   }
366
367   if (obj.peerDependencies) {
368     Object.keys(obj.peerDependencies).forEach(function (k) {
369       deps[k] = obj.peerDependencies[k]
370     })
371   }
372
373   debug("not extraneous", obj._id, deps)
374   Object.keys(deps).forEach(function (d) {
375     var dep = findDep(obj, d)
376     if (dep && dep.extraneous) {
377       unmarkExtraneous(dep, opts)
378     }
379   })
380 }
381
382 // Find the one that will actually be loaded by require()
383 // so we can make sure it's valid etc.
384 function findDep (obj, d) {
385   var r = obj
386     , found = null
387   while (r && !found) {
388     // if r is a valid choice, then use that.
389     // kinda weird if a pkg depends on itself, but after the first
390     // iteration of this loop, it indicates a dep cycle.
391     if (typeof r.dependencies[d] === "object") {
392       found = r.dependencies[d]
393     }
394     if (!found && r.realName === d) found = r
395     r = r.link ? null : r.parent
396   }
397   return found
398 }
399
400 function copy (obj) {
401   if (!obj || typeof obj !== 'object') return obj
402   if (Array.isArray(obj)) return obj.map(copy)
403
404   var o = {}
405   for (var i in obj) o[i] = copy(obj[i])
406   return o
407 }