@h3l1os/mp4vault 2.0.0
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/LICENSE +661 -0
- package/README.md +228 -0
- package/dist/index.cjs +1525 -0
- package/dist/index.d.cts +261 -0
- package/dist/index.d.ts +261 -0
- package/dist/index.js +1479 -0
- package/package.json +69 -0
- package/src/AES.ts +134 -0
- package/src/Atom.ts +148 -0
- package/src/Convert.ts +28 -0
- package/src/Embed.ts +243 -0
- package/src/EmbedBinary.ts +204 -0
- package/src/EmbedObject.ts +231 -0
- package/src/MP4.ts +363 -0
- package/src/Pack.ts +11 -0
- package/src/constants.ts +3 -0
- package/src/index.ts +11 -0
- package/src/jspack.d.ts +10 -0
- package/src/jspack.js +319 -0
- package/src/node/Readable.ts +61 -0
- package/src/node/Writable.ts +85 -0
- package/src/types.ts +44 -0
- package/src/utils.ts +6 -0
package/src/jspack.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// https://github.com/AndreasAntener/node-jspack
|
|
3
|
+
/* !
|
|
4
|
+
* Copyright © 2008 Fair Oaks Labs, Inc.
|
|
5
|
+
* All rights reserved.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Utility object: Encode / Decode C-style binary primitives to / from octet arrays
|
|
9
|
+
function JSPack() {
|
|
10
|
+
// Module-level (private) variables
|
|
11
|
+
var el;
|
|
12
|
+
var bBE = false;
|
|
13
|
+
var m = this;
|
|
14
|
+
|
|
15
|
+
// Raw byte arrays
|
|
16
|
+
m._DeArray = function (a, p, l) {
|
|
17
|
+
return [a.slice(p, p + l)];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
m._EnArray = function (a, p, l, v) {
|
|
21
|
+
for (var i = 0; i < l; a[p + i] = v[i] ? v[i] : 0, i++) { }
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// ASCII characters
|
|
25
|
+
m._DeChar = function (a, p) {
|
|
26
|
+
return String.fromCharCode(a[p]);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
m._EnChar = function (a, p, v) {
|
|
30
|
+
a[p] = v.charCodeAt(0);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Little-endian (un)signed N-byte integers
|
|
34
|
+
m._DeInt = function (a, p) {
|
|
35
|
+
var lsb = bBE ? (el.len - 1) : 0;
|
|
36
|
+
var nsb = bBE ? -1 : 1;
|
|
37
|
+
var stop = lsb + nsb * el.len;
|
|
38
|
+
var rv, i, f;
|
|
39
|
+
for (rv = 0, i = lsb, f = 1; i != stop; rv += (a[p + i] * f), i += nsb, f *= 256) { }
|
|
40
|
+
if (el.bSigned && (rv & Math.pow(2, el.len * 8 - 1))) { rv -= Math.pow(2, el.len * 8); }
|
|
41
|
+
return rv;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
m._EnInt = function (a, p, v) {
|
|
45
|
+
var lsb = bBE ? (el.len - 1) : 0;
|
|
46
|
+
var nsb = bBE ? -1 : 1;
|
|
47
|
+
var stop = lsb + nsb * el.len;
|
|
48
|
+
var i;
|
|
49
|
+
v = (v < el.min) ? el.min : (v > el.max) ? el.max : v;
|
|
50
|
+
for (i = lsb; i != stop; a[p + i] = v & 0xff, i += nsb, v >>= 8) { }
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// ASCII character strings
|
|
54
|
+
m._DeString = function (a, p, l) {
|
|
55
|
+
for (var rv = new Array(l), i = 0; i < l; rv[i] = String.fromCharCode(a[p + i]), i++) { }
|
|
56
|
+
return rv.join('');
|
|
57
|
+
};
|
|
58
|
+
m._EnString = function (a, p, l, v) {
|
|
59
|
+
|
|
60
|
+
for (var t, i = 0; i < l; a[p + i] = (t = v.charCodeAt(i)) ? t : 0, i++) { }
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Little-endian N-bit IEEE 754 floating point
|
|
64
|
+
m._De754 = function (a, p) {
|
|
65
|
+
var s, e, m, i, d, nBits, mLen, eLen, eBias, eMax;
|
|
66
|
+
mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
|
|
67
|
+
|
|
68
|
+
i = bBE ? 0 : (el.len - 1); d = bBE ? 1 : -1; s = a[p + i]; i += d; nBits = -7;
|
|
69
|
+
for (e = s & ((1 << (-nBits)) - 1), s >>= (-nBits), nBits += eLen;
|
|
70
|
+
nBits > 0; e = e * 256 + a[p + i], i += d, nBits -= 8) { }
|
|
71
|
+
for (m = e & ((1 << (-nBits)) - 1), e >>= (-nBits), nBits += mLen; nBits > 0;
|
|
72
|
+
m = m * 256 + a[p + i], i += d, nBits -= 8) { }
|
|
73
|
+
|
|
74
|
+
switch (e) {
|
|
75
|
+
|
|
76
|
+
case 0:
|
|
77
|
+
// Zero, or denormalized number
|
|
78
|
+
e = 1 - eBias;
|
|
79
|
+
break;
|
|
80
|
+
case eMax:
|
|
81
|
+
// NaN, or +/-Infinity
|
|
82
|
+
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
|
83
|
+
default:
|
|
84
|
+
// Normalized number
|
|
85
|
+
m = m + Math.pow(2, mLen);
|
|
86
|
+
e = e - eBias;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
|
90
|
+
};
|
|
91
|
+
m._En754 = function (a, p, v) {
|
|
92
|
+
|
|
93
|
+
var s, e, m, i, d, c, mLen, eLen, eBias, eMax;
|
|
94
|
+
mLen = el.mLen, eLen = el.len * 8 - el.mLen - 1, eMax = (1 << eLen) - 1, eBias = eMax >> 1;
|
|
95
|
+
|
|
96
|
+
s = v < 0 ? 1 : 0;
|
|
97
|
+
v = Math.abs(v);
|
|
98
|
+
if (isNaN(v) || (v == Infinity)) {
|
|
99
|
+
|
|
100
|
+
m = isNaN(v) ? 1 : 0;
|
|
101
|
+
e = eMax;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
e = Math.floor(Math.log(v) / Math.LN2); // Calculate log2 of the value
|
|
105
|
+
if (v * (c = Math.pow(2, -e)) < 1) { e--; c *= 2; } // Math.log() isn't 100% reliable
|
|
106
|
+
|
|
107
|
+
// Round by adding 1 / 2 the significand's LSD
|
|
108
|
+
if (e + eBias >= 1) {
|
|
109
|
+
// Normalized: mLen significand digits
|
|
110
|
+
v += el.rt / c;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Denormalized: <= mLen significand digits
|
|
114
|
+
v += el.rt * Math.pow(2, 1 - eBias);
|
|
115
|
+
}
|
|
116
|
+
if (v * c >= 2) {
|
|
117
|
+
// Rounding can increment the exponent
|
|
118
|
+
e++; c /= 2;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (e + eBias >= eMax) {
|
|
122
|
+
// Overflow
|
|
123
|
+
m = 0;
|
|
124
|
+
e = eMax;
|
|
125
|
+
}
|
|
126
|
+
else if (e + eBias >= 1) {
|
|
127
|
+
|
|
128
|
+
// Normalized - term order matters, as Math.pow(2, 52 - e) and v * Math.pow(2, 52) can overflow
|
|
129
|
+
m = (v * c - 1) * Math.pow(2, mLen);
|
|
130
|
+
e = e + eBias;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
|
|
134
|
+
// Denormalized - also catches the '0' case, somewhat by chance
|
|
135
|
+
m = v * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
|
136
|
+
e = 0;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (i = bBE ? (el.len - 1) : 0, d = bBE ? -1 : 1; mLen >= 8; a[p + i] = m & 0xff, i += d, m /= 256, mLen -= 8) { }
|
|
141
|
+
for (e = (e << mLen) | m, eLen += mLen; eLen > 0; a[p + i] = e & 0xff, i += d, e /= 256, eLen -= 8) { }
|
|
142
|
+
a[p + i - d] |= s * 128;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// Convert int64 to array with 3 elements: [lowBits, highBits, unsignedFlag]
|
|
146
|
+
// '>>>' trick to convert signed 32bit int to unsigned int (because << always results in a signed 32bit int)
|
|
147
|
+
m._DeInt64 = function (a, p) {
|
|
148
|
+
var start = bBE ? 0 : 7;
|
|
149
|
+
var nsb = bBE ? 1 : -1;
|
|
150
|
+
var stop = start + nsb * 8;
|
|
151
|
+
var rv = [0, 0, !el.bSigned];
|
|
152
|
+
var i, f, rvi;
|
|
153
|
+
for (i = start, rvi = 1, f = 0;
|
|
154
|
+
i != stop;
|
|
155
|
+
rv[rvi] = (((rv[rvi] << 8) >>> 0) + a[p + i]), i += nsb, f++, rvi = (f < 4 ? 1 : 0)) {}
|
|
156
|
+
|
|
157
|
+
return rv[0] + rv[1]*4294967296;
|
|
158
|
+
// return rv;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
m._EnInt64 = function (a, p, v) {
|
|
162
|
+
if (!Array.isArray(v)) {
|
|
163
|
+
// it's Number, so lets split it to array
|
|
164
|
+
v = [
|
|
165
|
+
v % 4294967296,
|
|
166
|
+
Math.floor(v / 4294967296),
|
|
167
|
+
1];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var start = bBE ? 0 : 7;
|
|
171
|
+
var nsb = bBE ? 1 : -1;
|
|
172
|
+
var stop = start + nsb * 8;
|
|
173
|
+
var i, f, rvi, s;
|
|
174
|
+
for (i = start, rvi = 1, f = 0, s = 24;
|
|
175
|
+
i != stop;
|
|
176
|
+
a[p + i] = v[rvi] >> s & 0xff, i += nsb, f++, rvi = (f < 4 ? 1 : 0), s = 24 - (8 * (f % 4))) { }
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Class data
|
|
180
|
+
m._sPattern = '(\\d+)?([AxcbBhHsfdiIlLqQ])';
|
|
181
|
+
m._lenLut = {'A': 1, 'x': 1, 'c': 1, 'b': 1, 'B': 1, 'h': 2, 'H': 2, 's': 1,
|
|
182
|
+
'f': 4, 'd': 8, 'i': 4, 'I': 4, 'l': 4, 'L': 4, 'q': 8, 'Q': 8
|
|
183
|
+
};
|
|
184
|
+
m._elLut = {'A': {en: m._EnArray, de: m._DeArray},
|
|
185
|
+
's': {en: m._EnString, de: m._DeString},
|
|
186
|
+
'c': {en: m._EnChar, de: m._DeChar},
|
|
187
|
+
'b': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: true, min: -Math.pow(2, 7), max: Math.pow(2, 7) - 1},
|
|
188
|
+
'B': {en: m._EnInt, de: m._DeInt, len: 1, bSigned: false, min: 0, max: Math.pow(2, 8) - 1},
|
|
189
|
+
'h': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: true, min: -Math.pow(2, 15), max: Math.pow(2, 15) - 1},
|
|
190
|
+
'H': {en: m._EnInt, de: m._DeInt, len: 2, bSigned: false, min: 0, max: Math.pow(2, 16) - 1},
|
|
191
|
+
'i': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
|
|
192
|
+
'I': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
|
|
193
|
+
'l': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: true, min: -Math.pow(2, 31), max: Math.pow(2, 31) - 1},
|
|
194
|
+
'L': {en: m._EnInt, de: m._DeInt, len: 4, bSigned: false, min: 0, max: Math.pow(2, 32) - 1},
|
|
195
|
+
'f': {en: m._En754, de: m._De754, len: 4, mLen: 23, rt: Math.pow(2, -24) - Math.pow(2, -77)},
|
|
196
|
+
'd': {en: m._En754, de: m._De754, len: 8, mLen: 52, rt: 0},
|
|
197
|
+
'q': {en: m._EnInt64, de: m._DeInt64, bSigned: true},
|
|
198
|
+
'Q': {en: m._EnInt64, de: m._DeInt64, bSigned: false}};
|
|
199
|
+
|
|
200
|
+
// Unpack a series of n elements of size s from array a at offset p with fxn
|
|
201
|
+
m._UnpackSeries = function (n, s, a, p) {
|
|
202
|
+
for (var fxn = el.de, rv = [], i = 0; i < n; rv.push(fxn(a, p + i * s)), i++) { }
|
|
203
|
+
return rv;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// Pack a series of n elements of size s from array v at offset i to array a at offset p with fxn
|
|
207
|
+
m._PackSeries = function (n, s, a, p, v, i) {
|
|
208
|
+
for (var fxn = el.en, o = 0; o < n; fxn(a, p + o * s, v[i + o]), o++) { }
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Unpack the octet array a, beginning at offset p, according to the fmt string
|
|
212
|
+
m.UnpackTo = function (fmt, a, p, allowLessData = false) {
|
|
213
|
+
// Set the private bBE flag based on the format string - assume big-endianness
|
|
214
|
+
bBE = (fmt.charAt(0) != '<');
|
|
215
|
+
|
|
216
|
+
p = p ? p : 0;
|
|
217
|
+
var re = new RegExp(this._sPattern, 'g');
|
|
218
|
+
var m, n, s;
|
|
219
|
+
var rv = [];
|
|
220
|
+
while (m = re.exec(fmt)) {
|
|
221
|
+
n = ((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1]);
|
|
222
|
+
s = this._lenLut[m[2]];
|
|
223
|
+
if ((p + n * s) > a.length) {
|
|
224
|
+
if (allowLessData) {
|
|
225
|
+
// We stop here and return what we have already,
|
|
226
|
+
// or an empty array if this happens in the first iteration.
|
|
227
|
+
break;
|
|
228
|
+
} else {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
switch (m[2]) {
|
|
233
|
+
case 'A': case 's':
|
|
234
|
+
rv.push(this._elLut[m[2]].de(a, p, n));
|
|
235
|
+
break;
|
|
236
|
+
case 'c': case 'b': case 'B': case 'h': case 'H':
|
|
237
|
+
case 'i': case 'I': case 'l': case 'L': case 'f': case 'd': case 'q': case 'Q':
|
|
238
|
+
el = this._elLut[m[2]];
|
|
239
|
+
if (n > 1) {
|
|
240
|
+
// Field is array, unpack into separate array and push as such
|
|
241
|
+
var arr = [];
|
|
242
|
+
arr.push(this._UnpackSeries(n, s, a, p));
|
|
243
|
+
rv.push(arr);
|
|
244
|
+
} else {
|
|
245
|
+
rv.push(this._UnpackSeries(n, s, a, p));
|
|
246
|
+
}
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
p += n * s;
|
|
250
|
+
}
|
|
251
|
+
return Array.prototype.concat.apply([], rv);
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
|
|
255
|
+
m.PackTo = function (fmt, a, p, values, allowLessData) {
|
|
256
|
+
// Set the private bBE flag based on the format string - assume big-endianness
|
|
257
|
+
bBE = (fmt.charAt(0) != '<');
|
|
258
|
+
|
|
259
|
+
var re = new RegExp(this._sPattern, 'g');
|
|
260
|
+
var m, n, s, j;
|
|
261
|
+
var i = 0;
|
|
262
|
+
while (m = re.exec(fmt)) {
|
|
263
|
+
n = ((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1]);
|
|
264
|
+
s = this._lenLut[m[2]];
|
|
265
|
+
if ((p + n * s) > a.length) {
|
|
266
|
+
// this should not happen unless CalcLength() is broken
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
switch (m[2]) {
|
|
270
|
+
case 'A': case 's':
|
|
271
|
+
if ((i + 1) > values.length) { return allowLessData ? a.slice(0, p) : false; }
|
|
272
|
+
this._elLut[m[2]].en(a, p, n, values[i]);
|
|
273
|
+
i += 1;
|
|
274
|
+
break;
|
|
275
|
+
case 'c': case 'b': case 'B': case 'h': case 'H':
|
|
276
|
+
case 'i': case 'I': case 'l': case 'L': case 'f': case 'd': case 'q': case 'Q':
|
|
277
|
+
el = this._elLut[m[2]];
|
|
278
|
+
if (n > 1 && Array.isArray(values[i])) {
|
|
279
|
+
// Value series is array, iterate through that, only increment by 1
|
|
280
|
+
if ((i + 1) > values.length) { return allowLessData ? a.slice(0, p) : false; }
|
|
281
|
+
this._PackSeries(n, s, a, p, values[i], 0);
|
|
282
|
+
i += 1;
|
|
283
|
+
} else {
|
|
284
|
+
if ((i + n) > values.length) { return allowLessData ? a.slice(0, p) : false; }
|
|
285
|
+
this._PackSeries(n, s, a, p, values, i);
|
|
286
|
+
i += n;
|
|
287
|
+
}
|
|
288
|
+
break;
|
|
289
|
+
case 'x':
|
|
290
|
+
for (j = 0; j < n; j++) { a[p + j] = 0; }
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
293
|
+
p += n * s;
|
|
294
|
+
}
|
|
295
|
+
return a;
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// Pack the supplied values into a new octet array, according to the fmt string
|
|
299
|
+
m.Pack = function (fmt, values, allowLessData = false) {
|
|
300
|
+
return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values, allowLessData);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
m.Unpack = function (fmt, values, allowLessData = false) {
|
|
304
|
+
return this.UnpackTo(fmt, values, 0, allowLessData);
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// Determine the number of bytes represented by the format string
|
|
308
|
+
m.CalcLength = function (fmt) {
|
|
309
|
+
var re = new RegExp(this._sPattern, 'g');
|
|
310
|
+
var sum = 0;
|
|
311
|
+
var m;
|
|
312
|
+
while (m = re.exec(fmt)) {
|
|
313
|
+
sum += (((m[1] == undefined) || (m[1] == '')) ? 1 : parseInt(m[1])) * this._lenLut[m[2]];
|
|
314
|
+
}
|
|
315
|
+
return sum;
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export default new JSPack();
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import type { FileHandle } from 'fs/promises';
|
|
3
|
+
import type { IReadable } from '../types.js';
|
|
4
|
+
|
|
5
|
+
export class Readable implements IReadable {
|
|
6
|
+
private _filename: string | undefined;
|
|
7
|
+
private _prepared = false;
|
|
8
|
+
private _size = 0;
|
|
9
|
+
private _fp: FileHandle | null = null;
|
|
10
|
+
|
|
11
|
+
constructor(params: { filename?: string } = {}) {
|
|
12
|
+
this._filename = params.filename;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
isPrepared(): boolean {
|
|
16
|
+
return this._prepared;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async prepare(): Promise<void> {
|
|
20
|
+
if (this._prepared) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (this._filename) {
|
|
25
|
+
this._fp = await fs.open(this._filename, 'r');
|
|
26
|
+
const stats = await this._fp.stat();
|
|
27
|
+
this._size = stats.size;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this._prepared = true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async close(): Promise<void> {
|
|
34
|
+
if (this._fp) {
|
|
35
|
+
try {
|
|
36
|
+
await this._fp.close();
|
|
37
|
+
} catch {
|
|
38
|
+
// file may already be closed
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
this._fp = null;
|
|
42
|
+
this._prepared = false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getSlice(offset: number, length: number): Promise<Uint8Array> {
|
|
46
|
+
if (!this._prepared) {
|
|
47
|
+
await this.prepare();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const ret = new Uint8Array(length);
|
|
51
|
+
await this._fp!.read(ret, 0, length, offset);
|
|
52
|
+
return ret;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async size(): Promise<number> {
|
|
56
|
+
if (!this._prepared) {
|
|
57
|
+
await this.prepare();
|
|
58
|
+
}
|
|
59
|
+
return this._size;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import { tmpFileSync } from '../utils.js';
|
|
3
|
+
import type { FileHandle } from 'fs/promises';
|
|
4
|
+
import type { IReadable, IWritable } from '../types.js';
|
|
5
|
+
import { Readable } from './Readable.js';
|
|
6
|
+
|
|
7
|
+
export class Writable implements IWritable {
|
|
8
|
+
private _uint8Array: Uint8Array = new Uint8Array([]);
|
|
9
|
+
private _filename: string | undefined;
|
|
10
|
+
private _prepared = false;
|
|
11
|
+
private _bytesWrote = 0;
|
|
12
|
+
private _fp: FileHandle | null = null;
|
|
13
|
+
|
|
14
|
+
constructor(params: { filename?: string } = {}) {
|
|
15
|
+
if (params.filename) {
|
|
16
|
+
this._filename = params.filename;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
size(): number {
|
|
21
|
+
if (this._filename) {
|
|
22
|
+
return this._bytesWrote;
|
|
23
|
+
}
|
|
24
|
+
return this._uint8Array.length;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async prepare(): Promise<void> {
|
|
28
|
+
if (this._prepared) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (this._filename) {
|
|
33
|
+
this._fp = await fs.open(this._filename, 'w');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this._prepared = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async close(): Promise<void> {
|
|
40
|
+
if (this._fp) {
|
|
41
|
+
try {
|
|
42
|
+
await this._fp.close();
|
|
43
|
+
} catch {
|
|
44
|
+
// file may already be closed
|
|
45
|
+
}
|
|
46
|
+
this._fp = null;
|
|
47
|
+
this._prepared = false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async saveToFile(filename: string): Promise<void> {
|
|
52
|
+
await fs.writeFile(filename, this._uint8Array);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async write(append: Uint8Array | number[]): Promise<void> {
|
|
56
|
+
if (!this._prepared) {
|
|
57
|
+
await this.prepare();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const data = append instanceof Uint8Array ? append : Uint8Array.from(append);
|
|
61
|
+
|
|
62
|
+
if (this._fp) {
|
|
63
|
+
await this._fp.write(data, 0, data.length);
|
|
64
|
+
this._bytesWrote += data.length;
|
|
65
|
+
} else {
|
|
66
|
+
const ret = new Uint8Array(this._uint8Array.length + data.length);
|
|
67
|
+
ret.set(this._uint8Array, 0);
|
|
68
|
+
ret.set(data, this._uint8Array.length);
|
|
69
|
+
this._bytesWrote += data.length;
|
|
70
|
+
this._uint8Array = ret;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async toReadable(): Promise<IReadable> {
|
|
75
|
+
if (this._filename) {
|
|
76
|
+
await this.close();
|
|
77
|
+
return new Readable({ filename: this._filename });
|
|
78
|
+
} else {
|
|
79
|
+
const tmpName = tmpFileSync();
|
|
80
|
+
await this.saveToFile(tmpName);
|
|
81
|
+
await this.close();
|
|
82
|
+
return new Readable({ filename: tmpName });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface IReadable {
|
|
2
|
+
isPrepared(): boolean;
|
|
3
|
+
prepare(): Promise<void>;
|
|
4
|
+
close(): Promise<void>;
|
|
5
|
+
getSlice(offset: number, length: number): Promise<Uint8Array>;
|
|
6
|
+
size(): Promise<number>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface IWritable {
|
|
10
|
+
size(): number;
|
|
11
|
+
prepare(): Promise<void>;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
write(data: Uint8Array | number[]): Promise<void>;
|
|
14
|
+
saveToFile(filename: string): Promise<void>;
|
|
15
|
+
toReadable(): Promise<IReadable>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface AtomParams {
|
|
19
|
+
readable?: IReadable;
|
|
20
|
+
name: string;
|
|
21
|
+
start: number;
|
|
22
|
+
size: number;
|
|
23
|
+
header_size: number;
|
|
24
|
+
mother?: Atom | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface FileRecord {
|
|
28
|
+
filename: string;
|
|
29
|
+
size: number;
|
|
30
|
+
meta?: Record<string, unknown>;
|
|
31
|
+
isEncrypted?: boolean;
|
|
32
|
+
offset?: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface EmbedFileParams {
|
|
36
|
+
filename?: string;
|
|
37
|
+
file?: unknown;
|
|
38
|
+
meta?: Record<string, unknown>;
|
|
39
|
+
key?: Buffer | null;
|
|
40
|
+
password?: string | null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Forward declaration to avoid circular imports
|
|
44
|
+
import type { Atom } from './Atom.js';
|