libnpmpack 1.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -68
- package/lib/index.js +54 -0
- package/package.json +19 -20
- package/CHANGELOG.md +0 -10
- package/index.js +0 -75
- package/utils/tar.js +0 -121
package/README.md
CHANGED
|
@@ -27,15 +27,12 @@ const pack = require('libnpmpack')
|
|
|
27
27
|
|
|
28
28
|
### API
|
|
29
29
|
|
|
30
|
-
|
|
31
30
|
#### <a name="pack"></a> `> pack(spec, [opts]) -> Promise`
|
|
32
31
|
|
|
33
|
-
Packs a tarball from a local directory or from a registry or github spec and
|
|
32
|
+
Packs a tarball from a local directory or from a registry or github spec and returns a Promise that resolves to the tarball data Buffer, with from, resolved, and integrity fields attached.
|
|
34
33
|
|
|
35
34
|
If no options are passed, the tarball file will be saved on the same directory from which `pack` was called in.
|
|
36
35
|
|
|
37
|
-
If `opts.target` is passed in, it will save the tarball file on the location entered.
|
|
38
|
-
|
|
39
36
|
`libnpmpack` uses [`pacote`](https://npm.im/pacote).
|
|
40
37
|
Most options are passed through directly to that library, so please refer to
|
|
41
38
|
[its own `opts`
|
|
@@ -45,74 +42,15 @@ for options that can be passed in.
|
|
|
45
42
|
##### Examples
|
|
46
43
|
|
|
47
44
|
```javascript
|
|
48
|
-
// packs from
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
id: 'my-cool-pkg@1.0.0',
|
|
54
|
-
name: 'my-cool-pkg',
|
|
55
|
-
version: '1.0.0',
|
|
56
|
-
size: 260,
|
|
57
|
-
unpackedSize: 133,
|
|
58
|
-
shasum: '535bdcc05fd4a1b7f2603c5527a7c63ba5b88cff',
|
|
59
|
-
integrity: ssri.parse(integrity.sha512[0]),
|
|
60
|
-
filename: 'my-cool-pkg-1.0.0.tgz',
|
|
61
|
-
files: [
|
|
62
|
-
{ path: 'index.js', size: 5, mode: 420 },
|
|
63
|
-
{ path: 'node_modules/a/package.json', size: 39, mode: 420 },
|
|
64
|
-
{ path: 'package.json', size: 89, mode: 420 }
|
|
65
|
-
],
|
|
66
|
-
entryCount: 3,
|
|
67
|
-
bundled: ['a']
|
|
68
|
-
}
|
|
69
|
-
*/
|
|
45
|
+
// packs from cwd
|
|
46
|
+
const tarball = await pack()
|
|
47
|
+
|
|
48
|
+
// packs from a local directory
|
|
49
|
+
const localTar = await pack('/Users/claudiahdz/projects/my-cool-pkg')
|
|
70
50
|
|
|
71
51
|
// packs from a registry spec
|
|
72
52
|
const registryTar = await pack('abbrev@1.0.3')
|
|
73
|
-
console.log(registryTar)
|
|
74
|
-
/*
|
|
75
|
-
{
|
|
76
|
-
id: abbrev@1.0.3,
|
|
77
|
-
name: 'abbrev',
|
|
78
|
-
version: '1.0.3',
|
|
79
|
-
size: 1526,
|
|
80
|
-
unpackedSize: 3358,
|
|
81
|
-
shasum: 'aa049c967f999222aa42e14434f0c562ef468241',
|
|
82
|
-
integrity: Integrity { sha512: [ [Hash] ] },
|
|
83
|
-
filename: 'abbrev-1.0.3.tgz',
|
|
84
|
-
files: [
|
|
85
|
-
{ path: 'package.json', size: 277, mode: 420 },
|
|
86
|
-
{ path: 'README.md', size: 499, mode: 420 },
|
|
87
|
-
{ path: 'lib/abbrev.js', size: 2582, mode: 420 }
|
|
88
|
-
],
|
|
89
|
-
entryCount: 3,
|
|
90
|
-
bundled: []
|
|
91
|
-
}
|
|
92
|
-
*/
|
|
93
53
|
|
|
94
54
|
// packs from a github spec
|
|
95
55
|
const githubTar = await pack('isaacs/rimraf#PR-192')
|
|
96
|
-
/*
|
|
97
|
-
{
|
|
98
|
-
id: 'rimraf@2.6.3',
|
|
99
|
-
name: 'rimraf',
|
|
100
|
-
version: '2.6.3',
|
|
101
|
-
size: 5664,
|
|
102
|
-
unpackedSize: 15463,
|
|
103
|
-
shasum: '9f5edf99046b4096d610532f0ec279135a624b15',
|
|
104
|
-
integrity: Integrity { sha512: [ [Hash] ] },
|
|
105
|
-
filename: 'rimraf-2.6.3.tgz',
|
|
106
|
-
files: [
|
|
107
|
-
{ path: 'LICENSE', size: 765, mode: 420 },
|
|
108
|
-
{ path: 'bin.js', size: 1196, mode: 493 },
|
|
109
|
-
{ path: 'rimraf.js', size: 9225, mode: 420 },
|
|
110
|
-
{ path: 'package.json', size: 677, mode: 420 },
|
|
111
|
-
{ path: 'README.md', size: 3600, mode: 420 }
|
|
112
|
-
],
|
|
113
|
-
entryCount: 5,
|
|
114
|
-
bundled: []
|
|
115
|
-
}
|
|
116
|
-
*/
|
|
117
56
|
```
|
|
118
|
-
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const pacote = require('pacote')
|
|
4
|
+
const npa = require('npm-package-arg')
|
|
5
|
+
const runScript = require('@npmcli/run-script')
|
|
6
|
+
|
|
7
|
+
module.exports = pack
|
|
8
|
+
async function pack (spec = 'file:.', opts = {}) {
|
|
9
|
+
// gets spec
|
|
10
|
+
spec = npa(spec)
|
|
11
|
+
|
|
12
|
+
const manifest = await pacote.manifest(spec, opts)
|
|
13
|
+
|
|
14
|
+
// Default to true if no log options passed, set to false if we're in silent
|
|
15
|
+
// mode
|
|
16
|
+
const banner = !opts.log || (opts.log.level !== 'silent')
|
|
17
|
+
|
|
18
|
+
if (spec.type === 'directory') {
|
|
19
|
+
// prepack
|
|
20
|
+
await runScript({
|
|
21
|
+
...opts,
|
|
22
|
+
event: 'prepack',
|
|
23
|
+
path: spec.fetchSpec,
|
|
24
|
+
stdio: 'inherit',
|
|
25
|
+
pkg: manifest,
|
|
26
|
+
banner,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// packs tarball
|
|
31
|
+
const tarball = await pacote.tarball(manifest._resolved, {
|
|
32
|
+
...opts,
|
|
33
|
+
integrity: manifest._integrity,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
if (spec.type === 'directory') {
|
|
37
|
+
// postpack
|
|
38
|
+
await runScript({
|
|
39
|
+
...opts,
|
|
40
|
+
event: 'postpack',
|
|
41
|
+
path: spec.fetchSpec,
|
|
42
|
+
stdio: 'inherit',
|
|
43
|
+
pkg: manifest,
|
|
44
|
+
banner,
|
|
45
|
+
env: {
|
|
46
|
+
npm_package_from: tarball.from,
|
|
47
|
+
npm_package_resolved: tarball.resolved,
|
|
48
|
+
npm_package_integrity: tarball.integrity,
|
|
49
|
+
},
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return tarball
|
|
54
|
+
}
|
package/package.json
CHANGED
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "libnpmpack",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Programmatic API for the bits behind npm pack",
|
|
5
|
-
"author": "
|
|
5
|
+
"author": "GitHub Inc.",
|
|
6
|
+
"main": "lib/index.js",
|
|
6
7
|
"contributors": [
|
|
7
8
|
"Claudia Hernández <claudia@npmjs.com>"
|
|
8
9
|
],
|
|
9
|
-
"main": "index.js",
|
|
10
10
|
"files": [
|
|
11
|
-
"
|
|
12
|
-
"
|
|
11
|
+
"bin",
|
|
12
|
+
"lib"
|
|
13
13
|
],
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"preversion": "npm test",
|
|
17
17
|
"postversion": "npm publish",
|
|
18
18
|
"prepublishOnly": "git push origin --follow-tags",
|
|
19
|
-
"lint": "
|
|
19
|
+
"lint": "eslint '**/*.js'",
|
|
20
20
|
"test": "tap",
|
|
21
|
-
"posttest": "npm run lint"
|
|
21
|
+
"posttest": "npm run lint",
|
|
22
|
+
"postlint": "npm-template-check",
|
|
23
|
+
"lintfix": "npm run lint -- --fix",
|
|
24
|
+
"snap": "tap"
|
|
22
25
|
},
|
|
23
26
|
"tap": {
|
|
24
27
|
"check-coverage": true
|
|
25
28
|
},
|
|
26
29
|
"devDependencies": {
|
|
27
|
-
"nock": "^
|
|
28
|
-
"
|
|
29
|
-
"tap": "^14.10.6"
|
|
30
|
+
"nock": "^13.0.7",
|
|
31
|
+
"tap": "^15.0.0"
|
|
30
32
|
},
|
|
31
33
|
"repository": {
|
|
32
34
|
"type": "git",
|
|
@@ -35,17 +37,14 @@
|
|
|
35
37
|
"bugs": "https://github.com/npm/libnpmpack/issues",
|
|
36
38
|
"homepage": "https://npmjs.com/package/libnpmpack",
|
|
37
39
|
"dependencies": {
|
|
38
|
-
"@npmcli/run-script": "^
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"move-concurrently": "^1.0.1",
|
|
42
|
-
"npm-package-arg": "^8.0.0",
|
|
43
|
-
"pacote": "^11.1.2",
|
|
44
|
-
"rimraf": "^3.0.2",
|
|
45
|
-
"ssri": "^8.0.0",
|
|
46
|
-
"tar": "^6.0.1"
|
|
40
|
+
"@npmcli/run-script": "^2.0.0",
|
|
41
|
+
"npm-package-arg": "^8.1.0",
|
|
42
|
+
"pacote": "^12.0.0"
|
|
47
43
|
},
|
|
48
44
|
"engines": {
|
|
49
|
-
"node": ">=
|
|
45
|
+
"node": "^12.13.0 || ^14.15.0 || >=16"
|
|
46
|
+
},
|
|
47
|
+
"templateOSS": {
|
|
48
|
+
"version": "2.4.1"
|
|
50
49
|
}
|
|
51
50
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
# Change Log
|
|
2
|
-
|
|
3
|
-
<a name="1.0.0"></a>
|
|
4
|
-
# 1.0.0 (2020-03-26)
|
|
5
|
-
|
|
6
|
-
### Features
|
|
7
|
-
|
|
8
|
-
* [`a35c590`](https://github.com/npm/libnpmpack/commit/a35c590) feat: pack tarballs from local dir or registry spec ([@claudiahdz](https://github.com/claudiahdz))
|
|
9
|
-
|
|
10
|
-
* [`6d72149`](https://github.com/npm/libnpmpack/commit/6d72149) feat: sorted tarball contents ([@eridal](https://github.com/eridal))
|
package/index.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const os = require('os')
|
|
4
|
-
const fs = require('fs')
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const util = require('util')
|
|
7
|
-
const pacote = require('pacote')
|
|
8
|
-
const npa = require('npm-package-arg')
|
|
9
|
-
const mv = require('move-concurrently')
|
|
10
|
-
const runScript = require('@npmcli/run-script')
|
|
11
|
-
|
|
12
|
-
const rimraf = util.promisify(require('rimraf'))
|
|
13
|
-
const mkdtemp = util.promisify(fs.mkdtemp)
|
|
14
|
-
|
|
15
|
-
const { getContents, logTar } = require('./utils/tar')
|
|
16
|
-
|
|
17
|
-
async function pack (spec = 'file:.', opts = {}) {
|
|
18
|
-
const { target = null } = opts
|
|
19
|
-
// gets spec
|
|
20
|
-
spec = npa(spec)
|
|
21
|
-
|
|
22
|
-
const manifest = await pacote.manifest(spec, opts)
|
|
23
|
-
const filename = path.basename(`${manifest.name}-${manifest.version}.tgz`)
|
|
24
|
-
const dest = target || `${process.cwd()}/${filename}`
|
|
25
|
-
|
|
26
|
-
if (spec.type === 'directory') {
|
|
27
|
-
// prepack
|
|
28
|
-
await runScript({
|
|
29
|
-
...opts,
|
|
30
|
-
event: 'prepack',
|
|
31
|
-
path: spec.fetchSpec,
|
|
32
|
-
stdio: 'inherit',
|
|
33
|
-
pkg: manifest,
|
|
34
|
-
env: {
|
|
35
|
-
npm_package_target: dest
|
|
36
|
-
}
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const tmpDir = await mkdtemp(path.join(os.tmpdir(), 'libnpmpack-'))
|
|
41
|
-
const tmpTarget = `${tmpDir}/${filename}`
|
|
42
|
-
|
|
43
|
-
// packs tarball on tmp location
|
|
44
|
-
const tarball = await pacote.tarball.file(manifest._resolved, tmpTarget, {
|
|
45
|
-
...opts,
|
|
46
|
-
integrity: manifest._integrity
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
// moves tarball to dest
|
|
50
|
-
await mv(tmpTarget, dest)
|
|
51
|
-
await rimraf(tmpDir)
|
|
52
|
-
|
|
53
|
-
if (spec.type === 'directory') {
|
|
54
|
-
// postpack
|
|
55
|
-
await runScript({
|
|
56
|
-
...opts,
|
|
57
|
-
event: 'postpack',
|
|
58
|
-
path: spec.fetchSpec,
|
|
59
|
-
stdio: 'inherit',
|
|
60
|
-
pkg: manifest,
|
|
61
|
-
env: {
|
|
62
|
-
npm_package_target: dest,
|
|
63
|
-
npm_package_from: tarball.from,
|
|
64
|
-
npm_package_resolved: tarball.resolved,
|
|
65
|
-
npm_package_integrity: tarball.integrity
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const contents = await getContents(manifest, dest)
|
|
71
|
-
return contents
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
pack.logTar = logTar
|
|
75
|
-
module.exports = pack
|
package/utils/tar.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const tar = require('tar')
|
|
5
|
-
const util = require('util')
|
|
6
|
-
const ssri = require('ssri')
|
|
7
|
-
const byteSize = require('byte-size')
|
|
8
|
-
const columnify = require('columnify')
|
|
9
|
-
|
|
10
|
-
const statAsync = util.promisify(require('fs').stat)
|
|
11
|
-
|
|
12
|
-
module.exports.logTar = logTar
|
|
13
|
-
/* istanbul ignore next */
|
|
14
|
-
function logTar (tarball, opts = {}) {
|
|
15
|
-
const { unicode, log = console.log } = opts
|
|
16
|
-
log('')
|
|
17
|
-
log('', `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`)
|
|
18
|
-
log('=== Tarball Contents ===')
|
|
19
|
-
if (tarball.files.length) {
|
|
20
|
-
log('', columnify(tarball.files.map((f) => {
|
|
21
|
-
const bytes = byteSize(f.size)
|
|
22
|
-
return { path: f.path, size: `${bytes.value}${bytes.unit}` }
|
|
23
|
-
}), {
|
|
24
|
-
include: ['size', 'path'],
|
|
25
|
-
showHeaders: false
|
|
26
|
-
}))
|
|
27
|
-
}
|
|
28
|
-
if (tarball.bundled.length) {
|
|
29
|
-
log('=== Bundled Dependencies ===')
|
|
30
|
-
tarball.bundled.forEach((name) => log.notice('', name))
|
|
31
|
-
}
|
|
32
|
-
log('=== Tarball Details ===')
|
|
33
|
-
log('', columnify([
|
|
34
|
-
{ name: 'name:', value: tarball.name },
|
|
35
|
-
{ name: 'version:', value: tarball.version },
|
|
36
|
-
tarball.filename && { name: 'filename:', value: tarball.filename },
|
|
37
|
-
{ name: 'package size:', value: byteSize(tarball.size) },
|
|
38
|
-
{ name: 'unpacked size:', value: byteSize(tarball.unpackedSize) },
|
|
39
|
-
{ name: 'shasum:', value: tarball.shasum },
|
|
40
|
-
{
|
|
41
|
-
name: 'integrity:',
|
|
42
|
-
value: tarball.integrity.toString().substr(0, 20) + '[...]' + tarball.integrity.toString().substr(80)
|
|
43
|
-
},
|
|
44
|
-
tarball.bundled.length && { name: 'bundled deps:', value: tarball.bundled.length },
|
|
45
|
-
tarball.bundled.length && { name: 'bundled files:', value: tarball.entryCount - tarball.files.length },
|
|
46
|
-
tarball.bundled.length && { name: 'own files:', value: tarball.files.length },
|
|
47
|
-
{ name: 'total files:', value: tarball.entryCount }
|
|
48
|
-
].filter((x) => x), {
|
|
49
|
-
include: ['name', 'value'],
|
|
50
|
-
showHeaders: false
|
|
51
|
-
}))
|
|
52
|
-
log('', '')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
module.exports.getContents = getContents
|
|
56
|
-
async function getContents (manifest, target) {
|
|
57
|
-
const files = []
|
|
58
|
-
const bundled = new Set()
|
|
59
|
-
let totalEntries = 0
|
|
60
|
-
let totalEntrySize = 0
|
|
61
|
-
|
|
62
|
-
// reads contents of tarball
|
|
63
|
-
await tar.t({
|
|
64
|
-
file: target,
|
|
65
|
-
onentry (entry) {
|
|
66
|
-
totalEntries++
|
|
67
|
-
totalEntrySize += entry.size
|
|
68
|
-
const p = entry.path
|
|
69
|
-
if (p.startsWith('package/node_modules/')) {
|
|
70
|
-
const name = p.match(/^package\/node_modules\/((?:@[^/]+\/)?[^/]+)/)[1]
|
|
71
|
-
bundled.add(name)
|
|
72
|
-
}
|
|
73
|
-
files.push({
|
|
74
|
-
path: entry.path.replace(/^package\//, ''),
|
|
75
|
-
size: entry.size,
|
|
76
|
-
mode: entry.mode
|
|
77
|
-
})
|
|
78
|
-
},
|
|
79
|
-
strip: 1
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const [stat, integrity] = await Promise.all([
|
|
83
|
-
statAsync(target),
|
|
84
|
-
ssri.fromStream(fs.createReadStream(target), {
|
|
85
|
-
algorithms: ['sha1', 'sha512']
|
|
86
|
-
})
|
|
87
|
-
])
|
|
88
|
-
|
|
89
|
-
const comparator = (a, b) => {
|
|
90
|
-
return a.path.localeCompare(b.path, undefined, {
|
|
91
|
-
sensitivity: 'case',
|
|
92
|
-
numeric: true
|
|
93
|
-
})
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const isUpper = (str) => {
|
|
97
|
-
const ch = str.charAt(0)
|
|
98
|
-
return ch >= 'A' && ch <= 'Z'
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const uppers = files.filter(file => isUpper(file.path))
|
|
102
|
-
const others = files.filter(file => !isUpper(file.path))
|
|
103
|
-
|
|
104
|
-
uppers.sort(comparator)
|
|
105
|
-
others.sort(comparator)
|
|
106
|
-
|
|
107
|
-
const shasum = integrity.sha1[0].hexDigest()
|
|
108
|
-
return {
|
|
109
|
-
id: manifest._id || `${manifest.name}@${manifest.version}`,
|
|
110
|
-
name: manifest.name,
|
|
111
|
-
version: manifest.version,
|
|
112
|
-
size: stat.size,
|
|
113
|
-
unpackedSize: totalEntrySize,
|
|
114
|
-
shasum,
|
|
115
|
-
integrity: ssri.parse(integrity.sha512[0]),
|
|
116
|
-
filename: `${manifest.name}-${manifest.version}.tgz`,
|
|
117
|
-
files: uppers.concat(others),
|
|
118
|
-
entryCount: totalEntries,
|
|
119
|
-
bundled: Array.from(bundled)
|
|
120
|
-
}
|
|
121
|
-
}
|