1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.WriteStream = exports.ReadStream = exports.ReadAfterReleasedError = exports.ReadAfterDestroyedError = void 0;
|
4 | const crypto_1 = require("crypto");
|
5 | const fs_1 = require("fs");
|
6 | const os_1 = require("os");
|
7 | const path_1 = require("path");
|
8 | const stream_1 = require("stream");
|
9 | const events_1 = require("events");
|
10 | class ReadAfterDestroyedError extends Error {
|
11 | }
|
12 | exports.ReadAfterDestroyedError = ReadAfterDestroyedError;
|
13 | class ReadAfterReleasedError extends Error {
|
14 | }
|
15 | exports.ReadAfterReleasedError = ReadAfterReleasedError;
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | const processExitProxy = new events_1.EventEmitter();
|
21 | processExitProxy.setMaxListeners(Infinity);
|
22 | process.once('exit', () => processExitProxy.emit('exit'));
|
23 | class ReadStream extends stream_1.Readable {
|
24 | constructor(writeStream, options) {
|
25 | super({
|
26 | highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark,
|
27 | encoding: options === null || options === void 0 ? void 0 : options.encoding,
|
28 | autoDestroy: true,
|
29 | });
|
30 | this._pos = 0;
|
31 | this._writeStream = writeStream;
|
32 | }
|
33 | _read(n) {
|
34 | if (this.destroyed)
|
35 | return;
|
36 | if (typeof this._writeStream['_fd'] !== 'number') {
|
37 | this._writeStream.once('ready', () => this._read(n));
|
38 | return;
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 | const buf = Buffer.allocUnsafe(n);
|
44 | (0, fs_1.read)(this._writeStream['_fd'], buf, 0, n, this._pos, (error, bytesRead) => {
|
45 | if (error)
|
46 | this.destroy(error);
|
47 |
|
48 | if (bytesRead) {
|
49 | this._pos += bytesRead;
|
50 | this.push(buf.slice(0, bytesRead));
|
51 | return;
|
52 | }
|
53 |
|
54 |
|
55 | if (this._writeStream._writableState.finished) {
|
56 |
|
57 |
|
58 | if (this._pos < this._writeStream._pos)
|
59 | this._read(n);
|
60 | else
|
61 | this.push(null);
|
62 | return;
|
63 | }
|
64 |
|
65 | const retry = () => {
|
66 | this._writeStream.off('finish', retry);
|
67 | this._writeStream.off('write', retry);
|
68 | this._read(n);
|
69 | };
|
70 | this._writeStream.on('finish', retry);
|
71 | this._writeStream.on('write', retry);
|
72 | });
|
73 | }
|
74 | }
|
75 | exports.ReadStream = ReadStream;
|
76 | class WriteStream extends stream_1.Writable {
|
77 | constructor(options) {
|
78 | super({
|
79 | highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark,
|
80 | defaultEncoding: options === null || options === void 0 ? void 0 : options.defaultEncoding,
|
81 | autoDestroy: false,
|
82 | });
|
83 | this._fd = null;
|
84 | this._path = null;
|
85 | this._pos = 0;
|
86 | this._readStreams = new Set();
|
87 | this._released = false;
|
88 | this._cleanup = (callback) => {
|
89 | const fd = this._fd;
|
90 | const path = this._path;
|
91 | if (typeof fd !== 'number' || typeof path !== 'string') {
|
92 | callback(null);
|
93 | return;
|
94 | }
|
95 |
|
96 | (0, fs_1.close)(fd, (closeError) => {
|
97 |
|
98 |
|
99 | (0, fs_1.unlink)(path, (unlinkError) => {
|
100 |
|
101 |
|
102 | this._fd = null;
|
103 |
|
104 |
|
105 | processExitProxy.off('exit', this._cleanupSync);
|
106 | callback(unlinkError !== null && unlinkError !== void 0 ? unlinkError : closeError);
|
107 | });
|
108 | });
|
109 | };
|
110 | this._cleanupSync = () => {
|
111 | processExitProxy.off('exit', this._cleanupSync);
|
112 | if (typeof this._fd === 'number')
|
113 | try {
|
114 | (0, fs_1.closeSync)(this._fd);
|
115 | }
|
116 | catch (error) {
|
117 |
|
118 |
|
119 | }
|
120 | try {
|
121 | if (this._path !== null) {
|
122 | (0, fs_1.unlinkSync)(this._path);
|
123 | }
|
124 | }
|
125 | catch (error) {
|
126 |
|
127 |
|
128 | }
|
129 | };
|
130 |
|
131 | (0, crypto_1.randomBytes)(16, (error, buffer) => {
|
132 | var _a;
|
133 | if (error) {
|
134 | this.destroy(error);
|
135 | return;
|
136 | }
|
137 | this._path = (0, path_1.join)(((_a = options === null || options === void 0 ? void 0 : options.tmpdir) !== null && _a !== void 0 ? _a : os_1.tmpdir)(), `capacitor-${buffer.toString('hex')}.tmp`);
|
138 |
|
139 | (0, fs_1.open)(this._path, 'wx+', 0o600, (error, fd) => {
|
140 | if (error) {
|
141 | this.destroy(error);
|
142 | return;
|
143 | }
|
144 |
|
145 | processExitProxy.once('exit', this._cleanupSync);
|
146 | this._fd = fd;
|
147 | this.emit('ready');
|
148 | });
|
149 | });
|
150 | }
|
151 | _final(callback) {
|
152 | if (typeof this._fd !== 'number') {
|
153 | this.once('ready', () => this._final(callback));
|
154 | return;
|
155 | }
|
156 | callback();
|
157 | }
|
158 | _write(chunk, encoding, callback) {
|
159 | if (typeof this._fd !== 'number') {
|
160 | this.once('ready', () => this._write(chunk, encoding, callback));
|
161 | return;
|
162 | }
|
163 | (0, fs_1.write)(this._fd, chunk, 0, chunk.length, this._pos, (error) => {
|
164 | if (error) {
|
165 | callback(error);
|
166 | return;
|
167 | }
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|
174 |
|
175 | this._pos += chunk.length;
|
176 | this.emit('write');
|
177 | callback();
|
178 | });
|
179 | }
|
180 | release() {
|
181 | this._released = true;
|
182 | if (this._readStreams.size === 0)
|
183 | this.destroy();
|
184 | }
|
185 | _destroy(error, callback) {
|
186 |
|
187 | for (const readStream of this._readStreams) {
|
188 | readStream.destroy(error || undefined);
|
189 | }
|
190 |
|
191 | if (typeof this._fd === 'number' && typeof this._path === 'string') {
|
192 | this._cleanup((cleanupError) => callback(cleanupError !== null && cleanupError !== void 0 ? cleanupError : error));
|
193 | return;
|
194 | }
|
195 |
|
196 |
|
197 | this.once('ready', () => {
|
198 | this._cleanup((cleanupError) => {
|
199 | if (cleanupError) {
|
200 | this.emit('error', cleanupError);
|
201 | }
|
202 | });
|
203 | });
|
204 | callback(error);
|
205 | }
|
206 | createReadStream(options) {
|
207 | if (this.destroyed)
|
208 | throw new ReadAfterDestroyedError('A ReadStream cannot be created from a destroyed WriteStream.');
|
209 | if (this._released)
|
210 | throw new ReadAfterReleasedError('A ReadStream cannot be created from a released WriteStream.');
|
211 | const readStream = new ReadStream(this, options);
|
212 | this._readStreams.add(readStream);
|
213 | readStream.once('close', () => {
|
214 | this._readStreams.delete(readStream);
|
215 | if (this._released && this._readStreams.size === 0) {
|
216 | this.destroy();
|
217 | }
|
218 | });
|
219 | return readStream;
|
220 | }
|
221 | }
|
222 | exports.WriteStream = WriteStream;
|
223 | exports.default = {
|
224 | WriteStream,
|
225 | ReadStream,
|
226 | ReadAfterDestroyedError,
|
227 | ReadAfterReleasedError,
|
228 | };
|
229 |
|
\ | No newline at end of file |