Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
tar.js110 linesDownload Raw Back to utils
1const tar = require('tar')
2const ssri = require('ssri')
3const { log, output } = require('proc-log')
4const formatBytes = require('./format-bytes.js')
5const localeCompare = require('@isaacs/string-locale-compare')('en', {
6  sensitivity: 'case',
7  numeric: true,
8})
9
10const logTar = (tarball, { unicode = false, json, key } = {}) => {
11  if (json) {
12    output.buffer(key == null ? tarball : { [key]: tarball })
13    return
14  }
15  log.notice('')
16  log.notice('', `${unicode ? '📦 ' : 'package:'} ${tarball.name}@${tarball.version}`)
17  log.notice('Tarball Contents')
18  if (tarball.files.length) {
19    log.notice(
20      '',
21      tarball.files.map(f =>
22        /^node_modules\//.test(f.path) ? null : `${formatBytes(f.size, false)} ${f.path}`
23      ).filter(f => f).join('\n')
24    )
25  }
26  if (tarball.bundled.length) {
27    log.notice('Bundled Dependencies')
28    tarball.bundled.forEach(name => log.notice('', name))
29  }
30  log.notice('Tarball Details')
31  log.notice('', `name: ${tarball.name}`)
32  log.notice('', `version: ${tarball.version}`)
33  if (tarball.filename) {
34    log.notice('', `filename: ${tarball.filename}`)
35  }
36  log.notice('', `package size: ${formatBytes(tarball.size)}`)
37  log.notice('', `unpacked size: ${formatBytes(tarball.unpackedSize)}`)
38  log.notice('', `shasum: ${tarball.shasum}`)
39  log.notice('', `integrity: ${tarball.integrity.toString().slice(0, 20)}[...]${tarball.integrity.toString().slice(80)}`)
40  if (tarball.bundled.length) {
41    log.notice('', `bundled deps: ${tarball.bundled.length}`)
42    log.notice('', `bundled files: ${tarball.entryCount - tarball.files.length}`)
43    log.notice('', `own files: ${tarball.files.length}`)
44  }
45  log.notice('', `total files: ${tarball.entryCount}`)
46  log.notice('', '')
47}
48
49const getContents = async (manifest, tarball) => {
50  const files = []
51  const bundled = new Set()
52  let totalEntries = 0
53  let totalEntrySize = 0
54
55  // reads contents of tarball
56  const stream = tar.t({
57    onentry (entry) {
58      totalEntries++
59      totalEntrySize += entry.size
60      const p = entry.path
61      if (p.startsWith('package/node_modules/') && p !== 'package/node_modules/') {
62        const name = p.match(/^package\/node_modules\/((?:@[^/]+\/)?[^/]+)/)[1]
63        bundled.add(name)
64      }
65      files.push({
66        path: entry.path.replace(/^package\//, ''),
67        size: entry.size,
68        mode: entry.mode,
69      })
70    },
71  })
72  stream.end(tarball)
73
74  const integrity = ssri.fromData(tarball, {
75    algorithms: ['sha1', 'sha512'],
76  })
77
78  const comparator = ({ path: a }, { path: b }) => localeCompare(a, b)
79
80  const isUpper = str => {
81    const ch = str.charAt(0)
82    return ch === ch.toUpperCase()
83  }
84
85  const uppers = files.filter(file => isUpper(file.path))
86  const others = files.filter(file => !isUpper(file.path))
87
88  uppers.sort(comparator)
89  others.sort(comparator)
90
91  const shasum = integrity.sha1[0].hexDigest()
92  return {
93    id: manifest._id || `${manifest.name}@${manifest.version}`,
94    name: manifest.name,
95    version: manifest.version,
96    size: tarball.length,
97    unpackedSize: totalEntrySize,
98    shasum,
99    integrity: ssri.parse(integrity.sha512[0]),
100    // @scope/packagename.tgz => scope-packagename.tgz
101    // we can safely use these global replace rules due to npm package naming rules
102    filename: `${manifest.name.replace('@', '').replace('/', '-')}-${manifest.version}.tgz`,
103    files: uppers.concat(others),
104    entryCount: totalEntries,
105    bundled: Array.from(bundled),
106  }
107}
108
109module.exports = { logTar, getContents }
110 
codekingpro/portable-devtools · Team Ai