blob: 721b48cc2b90b5d4d938ce396011ed424903b27e [file] [log] [blame]
Leo Repp58b9f112021-11-22 11:57:47 +01001'use strict';
2const fileType = require('file-type');
3const isStream = require('is-stream');
4const tarStream = require('tar-stream');
5
6module.exports = () => input => {
7 if (!Buffer.isBuffer(input) && !isStream(input)) {
8 return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`));
9 }
10
11 if (Buffer.isBuffer(input) && (!fileType(input) || fileType(input).ext !== 'tar')) {
12 return Promise.resolve([]);
13 }
14
15 const extract = tarStream.extract();
16 const files = [];
17
18 extract.on('entry', (header, stream, cb) => {
19 const chunk = [];
20
21 stream.on('data', data => chunk.push(data));
22 stream.on('end', () => {
23 const file = {
24 data: Buffer.concat(chunk),
25 mode: header.mode,
26 mtime: header.mtime,
27 path: header.name,
28 type: header.type
29 };
30
31 if (header.type === 'symlink' || header.type === 'link') {
32 file.linkname = header.linkname;
33 }
34
35 files.push(file);
36 cb();
37 });
38 });
39
40 const promise = new Promise((resolve, reject) => {
41 if (!Buffer.isBuffer(input)) {
42 input.on('error', reject);
43 }
44
45 extract.on('finish', () => resolve(files));
46 extract.on('error', reject);
47 });
48
49 extract.then = promise.then.bind(promise);
50 extract.catch = promise.catch.bind(promise);
51
52 if (Buffer.isBuffer(input)) {
53 extract.end(input);
54 } else {
55 input.pipe(extract);
56 }
57
58 return extract;
59};