@ffflorian/jszip-cli 3.6.3 → 3.6.5
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/dist/BuildService.js +115 -136
- package/dist/ExtractService.js +48 -59
- package/dist/FileService.d.ts +0 -1
- package/dist/FileService.js +45 -62
- package/dist/JSZipCLI.js +19 -30
- package/dist/cli.js +33 -19
- package/package.json +7 -7
package/dist/BuildService.js
CHANGED
|
@@ -22,15 +22,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
27
|
};
|
|
@@ -77,23 +68,21 @@ class BuildService {
|
|
|
77
68
|
});
|
|
78
69
|
return this;
|
|
79
70
|
}
|
|
80
|
-
save() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (this.outputFile) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return this;
|
|
96
|
-
});
|
|
71
|
+
async save() {
|
|
72
|
+
await this.checkOutput();
|
|
73
|
+
await Promise.all(this.entries.map(entry => this.checkEntry(entry)));
|
|
74
|
+
const data = await this.getBuffer();
|
|
75
|
+
if (this.outputFile) {
|
|
76
|
+
if (!this.outputFile.match(/\.\w+$/)) {
|
|
77
|
+
this.outputFile = path_1.default.join(this.outputFile, 'data.zip');
|
|
78
|
+
}
|
|
79
|
+
this.logger.info(`Saving finished zip file to "${this.outputFile}" ...`);
|
|
80
|
+
await this.fileService.writeFile(data, this.outputFile);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
process.stdout.write(data);
|
|
84
|
+
}
|
|
85
|
+
return this;
|
|
97
86
|
}
|
|
98
87
|
/**
|
|
99
88
|
* Note: glob patterns should always use / as a path separator, even on Windows systems,
|
|
@@ -103,119 +92,111 @@ class BuildService {
|
|
|
103
92
|
normalizePaths(rawEntries) {
|
|
104
93
|
return rawEntries.map(entry => entry.replace(/\\/g, '/'));
|
|
105
94
|
}
|
|
106
|
-
addFile(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
95
|
+
async addFile(entry, isLink = false) {
|
|
96
|
+
const { resolvedPath, zipPath } = entry;
|
|
97
|
+
let fileStat;
|
|
98
|
+
let fileData;
|
|
99
|
+
try {
|
|
100
|
+
fileData = isLink ? await fs.readlink(resolvedPath) : await fs.readFile(resolvedPath);
|
|
101
|
+
fileStat = await fs.lstat(resolvedPath);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (!this.options.quiet) {
|
|
105
|
+
this.logger.info(`Can't read file "${entry.resolvedPath}". Ignoring.`);
|
|
106
|
+
}
|
|
107
|
+
this.logger.info(error);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.logger.info(`Adding file "${resolvedPath}" to ZIP file ...`);
|
|
111
|
+
this.jszip.file(zipPath, fileData, {
|
|
112
|
+
createFolders: true,
|
|
113
|
+
date: fileStat.mtime,
|
|
114
|
+
// See https://github.com/Stuk/jszip/issues/550
|
|
115
|
+
// dosPermissions: fileStat.mode,
|
|
116
|
+
unixPermissions: fileStat.mode,
|
|
117
|
+
});
|
|
118
|
+
this.compressedFilesCount++;
|
|
119
|
+
}
|
|
120
|
+
async addLink(entry) {
|
|
121
|
+
const { resolvedPath, zipPath } = entry;
|
|
122
|
+
if (this.options.dereferenceLinks) {
|
|
123
|
+
let realPath;
|
|
111
124
|
try {
|
|
112
|
-
|
|
113
|
-
fileStat = yield fs.lstat(resolvedPath);
|
|
125
|
+
realPath = await fs.realpath(resolvedPath);
|
|
114
126
|
}
|
|
115
127
|
catch (error) {
|
|
116
128
|
if (!this.options.quiet) {
|
|
117
|
-
this.logger.info(`Can't read
|
|
129
|
+
this.logger.info(`Can't read link "${entry.resolvedPath}". Ignoring.`);
|
|
118
130
|
}
|
|
119
131
|
this.logger.info(error);
|
|
120
132
|
return;
|
|
121
133
|
}
|
|
122
|
-
this.logger.info(`
|
|
123
|
-
this.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// See https://github.com/Stuk/jszip/issues/550
|
|
127
|
-
// dosPermissions: fileStat.mode,
|
|
128
|
-
unixPermissions: fileStat.mode,
|
|
134
|
+
this.logger.info(`Found real path "${realPath} for symbolic link".`);
|
|
135
|
+
await this.checkEntry({
|
|
136
|
+
resolvedPath: realPath,
|
|
137
|
+
zipPath,
|
|
129
138
|
});
|
|
130
|
-
|
|
131
|
-
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
await this.addFile(entry, true);
|
|
142
|
+
}
|
|
132
143
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
144
|
+
async checkEntry(entry) {
|
|
145
|
+
let fileStat;
|
|
146
|
+
try {
|
|
147
|
+
fileStat = await fs.lstat(entry.resolvedPath);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (!this.options.quiet) {
|
|
151
|
+
this.logger.info(`Can't read file "${entry.resolvedPath}". Ignoring.`);
|
|
152
|
+
}
|
|
153
|
+
this.logger.info(error);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const ignoreEntries = this.ignoreEntries.filter(ignoreEntry => Boolean(entry.resolvedPath.match(ignoreEntry)));
|
|
157
|
+
if (ignoreEntries.length) {
|
|
158
|
+
this.logger.info(`Found ${entry.resolvedPath}. Not adding since it's on the ignore list:`, ignoreEntries.map(entry => String(entry)));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (fileStat.isDirectory()) {
|
|
162
|
+
this.logger.info(`Found directory "${entry.resolvedPath}".`);
|
|
163
|
+
await this.walkDir(entry);
|
|
164
|
+
}
|
|
165
|
+
else if (fileStat.isFile()) {
|
|
166
|
+
this.logger.info(`Found file "${entry.resolvedPath}".`);
|
|
167
|
+
this.logger.info(`Found file "${entry.resolvedPath}".`);
|
|
168
|
+
await this.addFile(entry);
|
|
169
|
+
}
|
|
170
|
+
else if (fileStat.isSymbolicLink()) {
|
|
171
|
+
this.logger.info(`Found symbolic link "${entry.resolvedPath}".`);
|
|
172
|
+
await this.addLink(entry);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
this.logger.info('Unknown file type.', { fileStat });
|
|
176
|
+
if (!this.options.quiet) {
|
|
177
|
+
this.logger.info(`Can't read file "${entry.resolvedPath}". Ignoring.`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
158
180
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
catch (error) {
|
|
166
|
-
if (!this.options.quiet) {
|
|
167
|
-
this.logger.info(`Can't read file "${entry.resolvedPath}". Ignoring.`);
|
|
181
|
+
async checkOutput() {
|
|
182
|
+
if (this.outputFile) {
|
|
183
|
+
if (this.outputFile.match(/\.\w+$/)) {
|
|
184
|
+
const dirExists = await this.fileService.dirExists(path_1.default.dirname(this.outputFile));
|
|
185
|
+
if (!dirExists) {
|
|
186
|
+
throw new Error(`Directory "${path_1.default.dirname(this.outputFile)}" doesn't exist or is not writable.`);
|
|
168
187
|
}
|
|
169
|
-
this.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const ignoreEntries = this.ignoreEntries.filter(ignoreEntry => Boolean(entry.resolvedPath.match(ignoreEntry)));
|
|
173
|
-
if (ignoreEntries.length) {
|
|
174
|
-
this.logger.info(`Found ${entry.resolvedPath}. Not adding since it's on the ignore list:`, ignoreEntries.map(entry => String(entry)));
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
if (fileStat.isDirectory()) {
|
|
178
|
-
this.logger.info(`Found directory "${entry.resolvedPath}".`);
|
|
179
|
-
yield this.walkDir(entry);
|
|
180
|
-
}
|
|
181
|
-
else if (fileStat.isFile()) {
|
|
182
|
-
this.logger.info(`Found file "${entry.resolvedPath}".`);
|
|
183
|
-
this.logger.info(`Found file "${entry.resolvedPath}".`);
|
|
184
|
-
yield this.addFile(entry);
|
|
185
|
-
}
|
|
186
|
-
else if (fileStat.isSymbolicLink()) {
|
|
187
|
-
this.logger.info(`Found symbolic link "${entry.resolvedPath}".`);
|
|
188
|
-
yield this.addLink(entry);
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
this.logger.info('Unknown file type.', { fileStat });
|
|
192
|
-
if (!this.options.quiet) {
|
|
193
|
-
this.logger.info(`Can't read file "${entry.resolvedPath}". Ignoring.`);
|
|
188
|
+
const fileIsWritable = await this.fileService.fileIsWritable(this.outputFile);
|
|
189
|
+
if (!fileIsWritable) {
|
|
190
|
+
throw new Error(`File "${this.outputFile}" already exists.`);
|
|
194
191
|
}
|
|
195
192
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if (this.outputFile) {
|
|
201
|
-
if (this.outputFile.match(/\.\w+$/)) {
|
|
202
|
-
const dirExists = yield this.fileService.dirExists(path_1.default.dirname(this.outputFile));
|
|
203
|
-
if (!dirExists) {
|
|
204
|
-
throw new Error(`Directory "${path_1.default.dirname(this.outputFile)}" doesn't exist or is not writable.`);
|
|
205
|
-
}
|
|
206
|
-
const fileIsWritable = yield this.fileService.fileIsWritable(this.outputFile);
|
|
207
|
-
if (!fileIsWritable) {
|
|
208
|
-
throw new Error(`File "${this.outputFile}" already exists.`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
const dirExists = yield this.fileService.dirExists(this.outputFile);
|
|
213
|
-
if (!dirExists) {
|
|
214
|
-
throw new Error(`Directory "${this.outputFile}" doesn't exist or is not writable.`);
|
|
215
|
-
}
|
|
193
|
+
else {
|
|
194
|
+
const dirExists = await this.fileService.dirExists(this.outputFile);
|
|
195
|
+
if (!dirExists) {
|
|
196
|
+
throw new Error(`Directory "${this.outputFile}" doesn't exist or is not writable.`);
|
|
216
197
|
}
|
|
217
198
|
}
|
|
218
|
-
}
|
|
199
|
+
}
|
|
219
200
|
}
|
|
220
201
|
getBuffer() {
|
|
221
202
|
const compressionType = this.options.compressionLevel === 0 ? 'STORE' : 'DEFLATE';
|
|
@@ -234,19 +215,17 @@ class BuildService {
|
|
|
234
215
|
}
|
|
235
216
|
});
|
|
236
217
|
}
|
|
237
|
-
walkDir(entry) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
});
|
|
218
|
+
async walkDir(entry) {
|
|
219
|
+
this.logger.info(`Walking directory ${entry.resolvedPath} ...`);
|
|
220
|
+
const dirEntries = await fs.readdir(entry.resolvedPath);
|
|
221
|
+
for (const dirEntry of dirEntries) {
|
|
222
|
+
const newZipPath = entry.zipPath === '.' ? dirEntry : `${entry.zipPath}/${dirEntry}`;
|
|
223
|
+
const newResolvedPath = path_1.default.join(entry.resolvedPath, dirEntry);
|
|
224
|
+
await this.checkEntry({
|
|
225
|
+
resolvedPath: newResolvedPath,
|
|
226
|
+
zipPath: newZipPath,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
250
229
|
}
|
|
251
230
|
}
|
|
252
231
|
exports.BuildService = BuildService;
|
package/dist/ExtractService.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -36,60 +27,58 @@ class ExtractService {
|
|
|
36
27
|
});
|
|
37
28
|
this.extractedFilesCount = 0;
|
|
38
29
|
}
|
|
39
|
-
extract(rawEntries) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
async extract(rawEntries) {
|
|
31
|
+
const isWin32 = os_1.default.platform() === 'win32';
|
|
32
|
+
for (const entry of rawEntries) {
|
|
33
|
+
const jszip = new jszip_1.default();
|
|
34
|
+
if (this.outputDir) {
|
|
35
|
+
await fs_extra_1.default.ensureDir(this.outputDir);
|
|
36
|
+
}
|
|
37
|
+
const resolvedPath = path_1.default.resolve(entry);
|
|
38
|
+
const data = await fs_extra_1.default.readFile(resolvedPath);
|
|
39
|
+
const entries = [];
|
|
40
|
+
await jszip.loadAsync(data, { createFolders: true });
|
|
41
|
+
if (!this.outputDir) {
|
|
42
|
+
await this.printStream(jszip.generateNodeStream());
|
|
43
|
+
return this;
|
|
44
|
+
}
|
|
45
|
+
jszip.forEach((filePath, entry) => {
|
|
46
|
+
if (filePath.includes('..')) {
|
|
47
|
+
this.logger.info(`Skipping bad path "${filePath}"`);
|
|
46
48
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const entries = [];
|
|
50
|
-
yield jszip.loadAsync(data, { createFolders: true });
|
|
51
|
-
if (!this.outputDir) {
|
|
52
|
-
yield this.printStream(jszip.generateNodeStream());
|
|
53
|
-
return this;
|
|
49
|
+
else {
|
|
50
|
+
entries.push([filePath, entry]);
|
|
54
51
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
encoding: 'utf-8',
|
|
73
|
-
});
|
|
74
|
-
this.extractedFilesCount++;
|
|
75
|
-
const diff = Math.floor(index / entries.length) - Math.floor(lastPercent);
|
|
76
|
-
if (diff && !this.options.quiet) {
|
|
77
|
-
this.progressBar.tick(diff);
|
|
78
|
-
lastPercent = Math.floor(index / entries.length);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (isWin32) {
|
|
82
|
-
if (entry.dosPermissions) {
|
|
83
|
-
yield fs_extra_1.default.chmod(resolvedFilePath, entry.dosPermissions);
|
|
84
|
-
}
|
|
52
|
+
});
|
|
53
|
+
let lastPercent = 0;
|
|
54
|
+
await Promise.all(entries.map(async ([filePath, entry], index) => {
|
|
55
|
+
const resolvedFilePath = path_1.default.join(this.outputDir, filePath);
|
|
56
|
+
if (entry.dir) {
|
|
57
|
+
await fs_extra_1.default.ensureDir(resolvedFilePath);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const data = await entry.async('nodebuffer');
|
|
61
|
+
await fs_extra_1.default.writeFile(resolvedFilePath, data, {
|
|
62
|
+
encoding: 'utf-8',
|
|
63
|
+
});
|
|
64
|
+
this.extractedFilesCount++;
|
|
65
|
+
const diff = Math.floor(index / entries.length) - Math.floor(lastPercent);
|
|
66
|
+
if (diff && !this.options.quiet) {
|
|
67
|
+
this.progressBar.tick(diff);
|
|
68
|
+
lastPercent = Math.floor(index / entries.length);
|
|
85
69
|
}
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
}
|
|
71
|
+
if (isWin32) {
|
|
72
|
+
if (entry.dosPermissions) {
|
|
73
|
+
await fs_extra_1.default.chmod(resolvedFilePath, entry.dosPermissions);
|
|
88
74
|
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
}
|
|
76
|
+
else if (entry.unixPermissions) {
|
|
77
|
+
await fs_extra_1.default.chmod(resolvedFilePath, entry.unixPermissions);
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
return this;
|
|
93
82
|
}
|
|
94
83
|
printStream(fileStream) {
|
|
95
84
|
return new Promise((resolve, reject) => {
|
package/dist/FileService.d.ts
CHANGED
package/dist/FileService.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -25,70 +16,62 @@ class FileService {
|
|
|
25
16
|
});
|
|
26
17
|
this.logger.state.isEnabled = this.options.verbose;
|
|
27
18
|
}
|
|
28
|
-
dirExists(dirPath) {
|
|
29
|
-
|
|
19
|
+
async dirExists(dirPath) {
|
|
20
|
+
try {
|
|
21
|
+
await fs_extra_1.default.access(dirPath, fs_extra_1.default.constants.F_OK);
|
|
30
22
|
try {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
yield fs_extra_1.default.access(dirPath, fs_extra_1.default.constants.W_OK);
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
this.logger.info(`Directory "${dirPath}" exists but is not writable.`);
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
23
|
+
await fs_extra_1.default.access(dirPath, fs_extra_1.default.constants.W_OK);
|
|
24
|
+
return true;
|
|
40
25
|
}
|
|
41
26
|
catch (error) {
|
|
42
|
-
this.logger.info(`Directory "${dirPath}"
|
|
43
|
-
if (this.options.force) {
|
|
44
|
-
yield fs_extra_1.default.ensureDir(dirPath);
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
27
|
+
this.logger.info(`Directory "${dirPath}" exists but is not writable.`);
|
|
47
28
|
return false;
|
|
48
29
|
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
yield fs_extra_1.default.access(filePath, fs_extra_1.default.constants.F_OK | fs_extra_1.default.constants.R_OK);
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
this.logger.info(`Directory "${dirPath}" doesn't exist.`, this.options.force ? 'Creating.' : 'Not creating.');
|
|
33
|
+
if (this.options.force) {
|
|
34
|
+
await fs_extra_1.default.ensureDir(dirPath);
|
|
35
|
+
return true;
|
|
62
36
|
}
|
|
63
37
|
return false;
|
|
64
|
-
}
|
|
38
|
+
}
|
|
65
39
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
yield fs_extra_1.default.access(filePath, fs_extra_1.default.constants.F_OK | fs_extra_1.default.constants.R_OK);
|
|
73
|
-
this.logger.info(`File "${filePath}" already exists.`, this.options.force ? 'Forcing overwrite.' : 'Not overwriting.');
|
|
74
|
-
return this.options.force;
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
40
|
+
async fileIsReadable(filePath) {
|
|
41
|
+
const dirExists = await this.dirExists(path_1.default.dirname(filePath));
|
|
42
|
+
if (dirExists) {
|
|
43
|
+
try {
|
|
44
|
+
await fs_extra_1.default.access(filePath, fs_extra_1.default.constants.F_OK | fs_extra_1.default.constants.R_OK);
|
|
45
|
+
return true;
|
|
79
46
|
}
|
|
80
|
-
|
|
81
|
-
|
|
47
|
+
catch (error) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
82
52
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
53
|
+
async fileIsWritable(filePath) {
|
|
54
|
+
const dirName = path_1.default.dirname(filePath);
|
|
55
|
+
const dirExists = await this.dirExists(dirName);
|
|
56
|
+
if (dirExists) {
|
|
57
|
+
try {
|
|
58
|
+
await fs_extra_1.default.access(filePath, fs_extra_1.default.constants.F_OK | fs_extra_1.default.constants.R_OK);
|
|
59
|
+
this.logger.info(`File "${filePath}" already exists.`, this.options.force ? 'Forcing overwrite.' : 'Not overwriting.');
|
|
60
|
+
return this.options.force;
|
|
89
61
|
}
|
|
90
|
-
|
|
91
|
-
|
|
62
|
+
catch (error) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
async writeFile(data, filePath) {
|
|
69
|
+
const fileIsWritable = await this.fileIsWritable(filePath);
|
|
70
|
+
if (fileIsWritable) {
|
|
71
|
+
await fs_extra_1.default.writeFile(filePath, data);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`File "${this.options.outputEntry}" already exists.`);
|
|
92
75
|
}
|
|
93
76
|
}
|
|
94
77
|
exports.FileService = FileService;
|
package/dist/JSZipCLI.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
@@ -35,7 +26,7 @@ class JSZipCLI {
|
|
|
35
26
|
markdown: false,
|
|
36
27
|
});
|
|
37
28
|
this.configExplorer = (0, cosmiconfig_1.cosmiconfigSync)('jszip');
|
|
38
|
-
this.options =
|
|
29
|
+
this.options = { ...defaultOptions, ...this.terminalOptions };
|
|
39
30
|
this.logger.state.isEnabled = this.options.verbose;
|
|
40
31
|
this.logger.info('Merged options', this.options);
|
|
41
32
|
this.checkConfigFile();
|
|
@@ -79,27 +70,25 @@ class JSZipCLI {
|
|
|
79
70
|
* Run in file mode - reads entries and settings from configuration file.
|
|
80
71
|
* Options from the constructor still take precedence.
|
|
81
72
|
*/
|
|
82
|
-
fileMode() {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
console.info(`Done compressing ${compressedFilesCount} files to "${outputFile}".`);
|
|
91
|
-
}
|
|
92
|
-
return this;
|
|
73
|
+
async fileMode() {
|
|
74
|
+
if (!this.options.mode && !this.configFile) {
|
|
75
|
+
throw new Error('No configuration file and no mode specified.');
|
|
76
|
+
}
|
|
77
|
+
if (this.options.mode === 'add') {
|
|
78
|
+
const { outputFile, compressedFilesCount } = await this.add().save();
|
|
79
|
+
if (this.options.outputEntry && !this.options.quiet) {
|
|
80
|
+
console.info(`Done compressing ${compressedFilesCount} files to "${outputFile}".`);
|
|
93
81
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
else if (this.options.mode === 'extract') {
|
|
85
|
+
const { outputDir, extractedFilesCount } = await this.extract();
|
|
86
|
+
if (this.options.outputEntry && !this.options.quiet) {
|
|
87
|
+
console.info(`Done extracting ${extractedFilesCount} files to "${outputDir}".`);
|
|
100
88
|
}
|
|
101
|
-
|
|
102
|
-
}
|
|
89
|
+
return this;
|
|
90
|
+
}
|
|
91
|
+
throw new Error('No or invalid mode in configuration file defined.');
|
|
103
92
|
}
|
|
104
93
|
save() {
|
|
105
94
|
return this.buildService.save();
|
|
@@ -132,7 +121,7 @@ class JSZipCLI {
|
|
|
132
121
|
}
|
|
133
122
|
const configFileData = configResult.config;
|
|
134
123
|
this.logger.info(`Using configuration file ${configResult.filepath}`);
|
|
135
|
-
this.options =
|
|
124
|
+
this.options = { ...defaultOptions, ...configFileData, ...this.terminalOptions };
|
|
136
125
|
this.logger.state.isEnabled = this.options.verbose;
|
|
137
126
|
}
|
|
138
127
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
-
});
|
|
11
|
-
};
|
|
12
3
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
5
|
};
|
|
@@ -53,12 +44,21 @@ commander_1.program
|
|
|
53
44
|
.option('-q, --quiet', "don't log anything excluding errors", false)
|
|
54
45
|
.option('-V, --verbose', 'enable verbose logging', false)
|
|
55
46
|
.arguments('[entries...]')
|
|
56
|
-
.action((entries) =>
|
|
47
|
+
.action(async (entries) => {
|
|
57
48
|
const options = commander_1.program.opts();
|
|
58
49
|
try {
|
|
59
|
-
const jszip = new JSZipCLI_1.JSZipCLI(
|
|
50
|
+
const jszip = new JSZipCLI_1.JSZipCLI({
|
|
51
|
+
...(options.level && { compressionLevel: Number(options.level) }),
|
|
52
|
+
...((options.config && { configFile: options.config }) || (options.noconfig && { configFile: false })),
|
|
53
|
+
...(options.dereference && { dereferenceLinks: options.dereference }),
|
|
54
|
+
...(options.force && { force: options.force }),
|
|
55
|
+
...(options.ignore && { ignoreEntries: [options.ignore] }),
|
|
56
|
+
...(options.output && { outputEntry: options.output }),
|
|
57
|
+
...(options.quiet && { quiet: options.quiet }),
|
|
58
|
+
...(options.verbose && { verbose: options.verbose }),
|
|
59
|
+
});
|
|
60
60
|
jszip.add(entries);
|
|
61
|
-
const { outputFile, compressedFilesCount } =
|
|
61
|
+
const { outputFile, compressedFilesCount } = await jszip.save();
|
|
62
62
|
if (options.output && !options.quiet) {
|
|
63
63
|
console.info(`Done compressing ${compressedFilesCount} files to "${outputFile}".`);
|
|
64
64
|
}
|
|
@@ -67,7 +67,7 @@ commander_1.program
|
|
|
67
67
|
console.error('Error:', error.message);
|
|
68
68
|
process.exit(1);
|
|
69
69
|
}
|
|
70
|
-
})
|
|
70
|
+
});
|
|
71
71
|
commander_1.program
|
|
72
72
|
.command('extract')
|
|
73
73
|
.alias('e')
|
|
@@ -80,10 +80,17 @@ commander_1.program
|
|
|
80
80
|
.option('-V, --verbose', 'enable verbose logging', false)
|
|
81
81
|
.option('-q, --quiet', "don't log anything excluding errors", false)
|
|
82
82
|
.arguments('<archives...>')
|
|
83
|
-
.action((archives) =>
|
|
83
|
+
.action(async (archives) => {
|
|
84
84
|
const options = commander_1.program.opts();
|
|
85
85
|
try {
|
|
86
|
-
const { outputDir, extractedFilesCount } =
|
|
86
|
+
const { outputDir, extractedFilesCount } = await new JSZipCLI_1.JSZipCLI({
|
|
87
|
+
...((options.config && { configFile: options.config }) || (options.noconfig && { configFile: false })),
|
|
88
|
+
...(options.force && { force: options.force }),
|
|
89
|
+
...(options.ignore && { ignoreEntries: [options.ignore] }),
|
|
90
|
+
...(options.output && { outputEntry: options.output }),
|
|
91
|
+
...(options.quiet && { quiet: options.quiet }),
|
|
92
|
+
...(options.verbose && { verbose: options.verbose }),
|
|
93
|
+
}).extract(archives);
|
|
87
94
|
if (options.output && !options.quiet) {
|
|
88
95
|
console.info(`Done extracting ${extractedFilesCount} files to "${outputDir}".`);
|
|
89
96
|
}
|
|
@@ -92,7 +99,7 @@ commander_1.program
|
|
|
92
99
|
console.error('Error:', error.message);
|
|
93
100
|
process.exit(1);
|
|
94
101
|
}
|
|
95
|
-
})
|
|
102
|
+
});
|
|
96
103
|
commander_1.program
|
|
97
104
|
.command('fileMode', { hidden: true, isDefault: true })
|
|
98
105
|
.option('--noconfig', "don't look for a configuration file", false)
|
|
@@ -102,13 +109,20 @@ commander_1.program
|
|
|
102
109
|
.option('-f, --force', 'force overwriting files and directories', false)
|
|
103
110
|
.option('-V, --verbose', 'enable verbose logging', false)
|
|
104
111
|
.option('-q, --quiet', "don't log anything excluding errors", false)
|
|
105
|
-
.action(() =>
|
|
112
|
+
.action(async () => {
|
|
106
113
|
const options = commander_1.program.opts();
|
|
107
114
|
try {
|
|
108
115
|
if (options.noconfig) {
|
|
109
116
|
commander_1.program.outputHelp();
|
|
110
117
|
}
|
|
111
|
-
|
|
118
|
+
await new JSZipCLI_1.JSZipCLI({
|
|
119
|
+
...(options.config && { configFile: options.config }),
|
|
120
|
+
...(options.force && { force: options.force }),
|
|
121
|
+
...(options.ignore && { ignoreEntries: [options.ignore] }),
|
|
122
|
+
...(options.output && { outputEntry: options.output }),
|
|
123
|
+
...(options.quiet && { quiet: options.quiet }),
|
|
124
|
+
...(options.verbose && { verbose: options.verbose }),
|
|
125
|
+
}).fileMode();
|
|
112
126
|
}
|
|
113
127
|
catch (error) {
|
|
114
128
|
if (error.message.includes('ENOENT')) {
|
|
@@ -119,5 +133,5 @@ commander_1.program
|
|
|
119
133
|
}
|
|
120
134
|
process.exit(1);
|
|
121
135
|
}
|
|
122
|
-
})
|
|
136
|
+
});
|
|
123
137
|
commander_1.program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"author": "Florian Imdahl <git@ffflorian.de>",
|
|
3
3
|
"bin": "dist/cli.js",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"commander": "12.
|
|
5
|
+
"commander": "12.1.0",
|
|
6
6
|
"cosmiconfig": "9.0.0",
|
|
7
7
|
"fs-extra": "11.2.0",
|
|
8
|
-
"glob": "10.
|
|
8
|
+
"glob": "10.4.1",
|
|
9
9
|
"jszip": "3.10.1",
|
|
10
10
|
"logdown": "3.3.1",
|
|
11
11
|
"progress": "2.0.3"
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"@types/fs-extra": "11.0.4",
|
|
16
16
|
"@types/progress": "2.0.7",
|
|
17
17
|
"cross-env": "7.0.3",
|
|
18
|
-
"rimraf": "5.0.
|
|
18
|
+
"rimraf": "5.0.7",
|
|
19
19
|
"ts-node": "10.9.2",
|
|
20
|
-
"typescript": "5.
|
|
21
|
-
"vitest": "1.
|
|
20
|
+
"typescript": "5.5.2",
|
|
21
|
+
"vitest": "1.6.0"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">= 10.9"
|
|
@@ -43,6 +43,6 @@
|
|
|
43
43
|
"start": "cross-env NODE_DEBUG=\"jszip-cli/*\" node --loader ts-node/esm src/cli.ts",
|
|
44
44
|
"test": "vitest run"
|
|
45
45
|
},
|
|
46
|
-
"version": "3.6.
|
|
47
|
-
"gitHead": "
|
|
46
|
+
"version": "3.6.5",
|
|
47
|
+
"gitHead": "f7a6a79286e4eb85392b5f2d33942ab166142109"
|
|
48
48
|
}
|