forked from Merlin-Taylor/node-pack-zip
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
145 lines (122 loc) · 5.02 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
'use strict';
const archiver = require('archiver');
const console = require('console');
const fs = require('fs');
const globby = require('globby');
const path = require('path');
const Promise = require('bluebird');
const readFile = Promise.promisify(fs.readFile);
const DEFAULT_IGNORE_PATTERNS = [
];
const DEFAULT_INCLUDE_PATTERNS = [
'**/*',
'!node_modules/**'
];
let resolvePathRelativeTo = (() => {
let pcwd = process.cwd();
return cwd => path.resolve.bind(path, cwd || pcwd);
})();
let getFiles = ({ cwd }) => ({ include, ignore }) => globby(include, { cwd: cwd || process.cwd(), ignore, nodir: true });
function getPackageInfo(packageFile) {
return readFile(packageFile, 'utf-8')
.then(content => JSON.parse(content))
.catch(error => {
console.error(`Failed to read ${packageFile}`);
return JSON.parse("{}");
});
}
function getDefaultOuputFilename({ cwd }) {
let at = resolvePathRelativeTo(cwd);
let packageFile = at('package.json');
return getPackageInfo(packageFile)
.then(packageInfo => {
const filename = `${packageInfo.name}.zip`;
const idx = filename.indexOf('/');
return (idx !== -1) ? filename.substring(idx+1) : filename;
});
}
function flatten(arr) {
return arr.reduce(function (flat, toFlatten) {
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
}, []);
}
function getTransitiveDependencies({ cwd }, dependencies, module) {
let at = resolvePathRelativeTo(cwd);
if (!dependencies.find(d => d === module)) {
dependencies.push(module);
return getPackageInfo(at('node_modules/'+module+'/package.json'))
.then(modulePackage => Object.keys(modulePackage.dependencies || {})
.concat(Object.keys(modulePackage._phantomChildren || {})))
.then(deps => {
return Promise.map(deps, (dep) => {
return getTransitiveDependencies({ cwd }, dependencies, dep);
});
})
.then(flatten);
} else {
return Promise.resolve([]);
}
}
function getPackageDependencies({ cwd }) {
let at = resolvePathRelativeTo(cwd);
return getPackageInfo(at('package.json'))
.then(rootPackage => Object.keys(rootPackage.dependencies || {})
.concat(Object.keys(rootPackage._phantomChildren || {}))
.concat(Object.keys(rootPackage.bundledDependencies || {})))
.then(rootDependencies => {
let totalDependencies = [];
return Promise.all(rootDependencies.map(dep => getTransitiveDependencies({ cwd }, totalDependencies, dep)))
.then(() => { return totalDependencies;} );
})
.then(flatten);
}
function getPackageGlobs({cwd}) {
let at = resolvePathRelativeTo(cwd);
return getPackageInfo(at('package.json'))
.then(rootPackage => {
let includes = rootPackage.repackZipConfig ? (rootPackage.repackZipConfig.includes || []) : [];
let excludes = rootPackage.repackZipConfig ? (rootPackage.repackZipConfig.excludes || []) : [];
return { includes: includes, excludes: excludes};
});
}
function getGlobPatterns({ cwd }) {
let at = resolvePathRelativeTo(cwd);
return getPackageGlobs({cwd}).then( ({includes, excludes}) => {
let includePatterns = getPackageDependencies({ cwd })
.then(dependencies => dependencies.map(x => `node_modules/${x}/**`))
.then(includePatterns => DEFAULT_INCLUDE_PATTERNS.concat(includePatterns).concat(includes));
let ignorePatterns = readFile(at('.packignore'), 'utf-8') // For backward compatibility
.then(txt => txt.split('\n').map(line => line.trim()).filter(line => line.length > 0))
.catch(error => error.code === 'ENOENT' ? Promise.resolve([]) : Promise.reject(error))
.then(ignorePatterns => DEFAULT_IGNORE_PATTERNS.concat(ignorePatterns).concat(excludes));
return Promise.all([includePatterns, ignorePatterns])
.then(([include, ignore]) => ({ include, ignore }));
});
}
function zipFiles({ cwd, destination }) {
let at = resolvePathRelativeTo(cwd);
return files => new Promise((resolve, reject) => {
let archive = archiver.create('zip');
archive.on('error', error => reject(error));
archive.pipe(fs.createWriteStream(destination)).on('end', () => resolve());
files
.filter(f => { return f !== destination })
.forEach(file => archive.file(at(file), { name: file }));
archive.finalize();
});
}
function pack({ source, destination }) {
let files = getGlobPatterns({ cwd: source })
.then(getFiles({ cwd: source }));
let outputFilename = destination
? Promise.resolve(destination)
: getDefaultOuputFilename({ cwd: source })
return Promise.all([outputFilename, files])
.then(([destination, files]) => zipFiles({ cwd: source, destination })(files));
}
module.exports = {
getFiles,
getGlobPatterns,
pack,
zipFiles,
}