1 | 'use strict'
|
2 |
|
3 | const deprCheck = require('./utils/depr-check')
|
4 | const path = require('path')
|
5 | const log = require('npmlog')
|
6 | const readPackageTree = require('read-package-tree')
|
7 | const rimraf = require('rimraf')
|
8 | const validate = require('aproba')
|
9 | const npa = require('npm-package-arg')
|
10 | const npm = require('./npm')
|
11 | let npmConfig
|
12 | const npmlog = require('npmlog')
|
13 | const limit = require('call-limit')
|
14 | const tempFilename = require('./utils/temp-filename')
|
15 | const pacote = require('pacote')
|
16 | const isWindows = require('./utils/is-windows.js')
|
17 |
|
18 | function andLogAndFinish (spec, tracker, done) {
|
19 | validate('SOF|SZF|OOF|OZF', [spec, tracker, done])
|
20 | return (er, pkg) => {
|
21 | if (er) {
|
22 | log.silly('fetchPackageMetaData', 'error for ' + String(spec), er.message)
|
23 | if (tracker) tracker.finish()
|
24 | }
|
25 | return done(er, pkg)
|
26 | }
|
27 | }
|
28 |
|
29 | const LRUCache = require('lru-cache')
|
30 | const CACHE = new LRUCache({
|
31 | max: 300 * 1024 * 1024,
|
32 | length: (p) => p._contentLength
|
33 | })
|
34 |
|
35 | module.exports = limit(fetchPackageMetadata, npm.limit.fetch)
|
36 | function fetchPackageMetadata (spec, where, opts, done) {
|
37 | validate('SSOF|SSFZ|OSOF|OSFZ', [spec, where, opts, done])
|
38 |
|
39 | if (!done) {
|
40 | done = opts
|
41 | opts = {}
|
42 | }
|
43 | var tracker = opts.tracker
|
44 | const logAndFinish = andLogAndFinish(spec, tracker, done)
|
45 |
|
46 | if (typeof spec === 'object') {
|
47 | var dep = spec
|
48 | } else {
|
49 | dep = npa(spec)
|
50 | }
|
51 | if (!isWindows && dep.type === 'directory' && /^[a-zA-Z]:/.test(dep.fetchSpec)) {
|
52 | var err = new Error(`Can't install from windows path on a non-windows system: ${dep.fetchSpec.replace(/[/]/g, '\\')}`)
|
53 | err.code = 'EWINDOWSPATH'
|
54 | return logAndFinish(err)
|
55 | }
|
56 | if (!npmConfig) {
|
57 | npmConfig = require('./config/figgy-config.js')
|
58 | }
|
59 | pacote.manifest(dep, npmConfig({
|
60 | annotate: true,
|
61 | fullMetadata: opts.fullMetadata,
|
62 | log: tracker || npmlog,
|
63 | memoize: CACHE,
|
64 | where: where
|
65 | })).then(
|
66 | (pkg) => logAndFinish(null, deprCheck(pkg)),
|
67 | (err) => {
|
68 | if (dep.type !== 'directory') return logAndFinish(err)
|
69 | if (err.code === 'ENOTDIR') {
|
70 | var enolocal = new Error(`Could not install "${path.relative(process.cwd(), dep.fetchSpec)}" as it is not a directory and is not a file with a name ending in .tgz, .tar.gz or .tar`)
|
71 | enolocal.code = 'ENOLOCAL'
|
72 | if (err.stack) enolocal.stack = err.stack
|
73 | return logAndFinish(enolocal)
|
74 | } else if (err.code === 'ENOPACKAGEJSON') {
|
75 | var enopackage = new Error(`Could not install from "${path.relative(process.cwd(), dep.fetchSpec)}" as it does not contain a package.json file.`)
|
76 | enopackage.code = 'ENOLOCAL'
|
77 | if (err.stack) enopackage.stack = err.stack
|
78 | return logAndFinish(enopackage)
|
79 | } else {
|
80 | return logAndFinish(err)
|
81 | }
|
82 | }
|
83 | )
|
84 | }
|
85 |
|
86 | module.exports.addBundled = addBundled
|
87 | function addBundled (pkg, next) {
|
88 | validate('OF', arguments)
|
89 | if (pkg._bundled !== undefined) return next(null, pkg)
|
90 |
|
91 | if (!pkg.bundleDependencies && pkg._requested.type !== 'directory') return next(null, pkg)
|
92 | const requested = pkg._requested || npa(pkg._from)
|
93 | if (requested.type === 'directory') {
|
94 | pkg._bundled = null
|
95 | return readPackageTree(pkg._requested.fetchSpec, function (er, tree) {
|
96 | if (tree) pkg._bundled = tree.children
|
97 | return next(null, pkg)
|
98 | })
|
99 | }
|
100 | pkg._bundled = null
|
101 | const target = tempFilename('unpack')
|
102 | if (!npmConfig) {
|
103 | npmConfig = require('./config/figgy-config.js')
|
104 | }
|
105 | const opts = npmConfig({integrity: pkg._integrity})
|
106 | pacote.extract(pkg._resolved || pkg._requested || npa.resolve(pkg.name, pkg.version), target, opts).then(() => {
|
107 | log.silly('addBundled', 'read tarball')
|
108 | readPackageTree(target, (err, tree) => {
|
109 | if (err) { return next(err) }
|
110 | log.silly('cleanup', 'remove extracted module')
|
111 | rimraf(target, function () {
|
112 | if (tree) {
|
113 | pkg._bundled = tree.children
|
114 | }
|
115 | next(null, pkg)
|
116 | })
|
117 | })
|
118 | }, next)
|
119 | }
|