-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathindex.js
161 lines (152 loc) · 4.79 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import { ZipArchiveOutputStream, ZipArchiveEntry } from "compress-commons";
import { dateify, sanitizePath } from "./utils.js";
/**
* ZipStream
*
* @ignore
* @license [MIT]{@link https://github.com/archiverjs/node-zip-stream/blob/master/LICENSE}
* @copyright (c) 2014 Chris Talkington, contributors.
*/
export default class ZipStream extends ZipArchiveOutputStream {
/**
* @constructor
* @extends external:ZipArchiveOutputStream
* @param {Object} [options]
* @param {String} [options.comment] Sets the zip archive comment.
* @param {Boolean} [options.forceLocalTime=false] Forces the archive to contain local file times instead of UTC.
* @param {Boolean} [options.forceZip64=false] Forces the archive to contain ZIP64 headers.
* @param {Boolean} [options.store=false] Sets the compression method to STORE.
* @param {Object} [options.zlib] Passed to [zlib]{@link https://nodejs.org/api/zlib.html#zlib_class_options}
* to control compression.
*/
constructor(options) {
options = options || {};
options.zlib = options.zlib || {};
if (typeof options.level === "number" && options.level >= 0) {
options.zlib.level = options.level;
delete options.level;
}
if (
!options.forceZip64 &&
typeof options.zlib.level === "number" &&
options.zlib.level === 0
) {
options.store = true;
}
options.namePrependSlash = options.namePrependSlash || false;
super(options);
if (options.comment && options.comment.length > 0) {
this.setComment(options.comment);
}
}
/**
* Normalizes entry data with fallbacks for key properties.
*
* @private
* @param {Object} data
* @return {Object}
*/
_normalizeFileData(data) {
data = {
type: "file",
name: null,
namePrependSlash: this.options.namePrependSlash,
linkname: null,
date: null,
mode: null,
store: this.options.store,
comment: "",
...data,
};
let isDir = data.type === "directory";
const isSymlink = data.type === "symlink";
if (data.name) {
data.name = sanitizePath(data.name);
if (!isSymlink && data.name.slice(-1) === "/") {
isDir = true;
data.type = "directory";
} else if (isDir) {
data.name += "/";
}
}
if (isDir || isSymlink) {
data.store = true;
}
data.date = dateify(data.date);
return data;
}
/**
* Appends an entry given an input source (text string, buffer, or stream).
*
* @param {(Buffer|Stream|String)} source The input source.
* @param {Object} data
* @param {String} data.name Sets the entry name including internal path.
* @param {String} [data.comment] Sets the entry comment.
* @param {(String|Date)} [data.date=NOW()] Sets the entry date.
* @param {Number} [data.mode=D:0755/F:0644] Sets the entry permissions.
* @param {Boolean} [data.store=options.store] Sets the compression method to STORE.
* @param {String} [data.type=file] Sets the entry type. Defaults to `directory`
* if name ends with trailing slash.
* @param {Function} callback
* @return this
*/
entry(source, data, callback) {
if (typeof callback !== "function") {
callback = this._emitErrorCallback.bind(this);
}
data = this._normalizeFileData(data);
if (
data.type !== "file" &&
data.type !== "directory" &&
data.type !== "symlink"
) {
callback(new Error(data.type + " entries not currently supported"));
return;
}
if (typeof data.name !== "string" || data.name.length === 0) {
callback(new Error("entry name must be a non-empty string value"));
return;
}
if (data.type === "symlink" && typeof data.linkname !== "string") {
callback(
new Error(
"entry linkname must be a non-empty string value when type equals symlink",
),
);
return;
}
const entry = new ZipArchiveEntry(data.name);
entry.setTime(data.date, this.options.forceLocalTime);
if (data.namePrependSlash) {
entry.setName(data.name, true);
}
if (data.store) {
entry.setMethod(0);
}
if (data.comment.length > 0) {
entry.setComment(data.comment);
}
if (data.type === "symlink" && typeof data.mode !== "number") {
data.mode = 40960; // 0120000
}
if (typeof data.mode === "number") {
if (data.type === "symlink") {
data.mode |= 40960;
}
entry.setUnixMode(data.mode);
}
if (data.type === "symlink" && typeof data.linkname === "string") {
source = Buffer.from(data.linkname);
}
return super.entry(entry, source, callback);
}
/**
* Finalizes the instance and prevents further appending to the archive
* structure (queue will continue til drained).
*
* @return void
*/
finalize() {
this.finish();
}
}