123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- "use strict";
- var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.WriteStream = exports.ReadStream = exports.ReadAfterReleasedError = exports.ReadAfterDestroyedError = void 0;
- const crypto_1 = __importDefault(require("crypto"));
- const fs_1 = __importDefault(require("fs"));
- const os_1 = __importDefault(require("os"));
- const path_1 = __importDefault(require("path"));
- const stream_1 = require("stream");
- class ReadAfterDestroyedError extends Error {
- }
- exports.ReadAfterDestroyedError = ReadAfterDestroyedError;
- class ReadAfterReleasedError extends Error {
- }
- exports.ReadAfterReleasedError = ReadAfterReleasedError;
- class ReadStream extends stream_1.Readable {
- constructor(writeStream, options) {
- super({
- highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark,
- encoding: options === null || options === void 0 ? void 0 : options.encoding,
- autoDestroy: true,
- });
- this._pos = 0;
- this._writeStream = writeStream;
- }
- _read(n) {
- if (this.destroyed)
- return;
- if (typeof this._writeStream["_fd"] !== "number") {
- this._writeStream.once("ready", () => this._read(n));
- return;
- }
- // Using `allocUnsafe` here is OK because we return a slice the length of
- // `bytesRead`, and discard the rest. This prevents node from having to zero
- // out the entire allocation first.
- const buf = Buffer.allocUnsafe(n);
- fs_1.default.read(this._writeStream["_fd"], buf, 0, n, this._pos, (error, bytesRead) => {
- if (error)
- this.destroy(error);
- // Push any read bytes into the local stream buffer.
- if (bytesRead) {
- this._pos += bytesRead;
- this.push(buf.slice(0, bytesRead));
- return;
- }
- // If there were no more bytes to read and the write stream is finished,
- // than this stream has reached the end.
- if (this._writeStream._writableState.finished) {
- this.push(null);
- return;
- }
- // Otherwise, wait for the write stream to add more data or finish.
- const retry = () => {
- this._writeStream.removeListener("finish", retry);
- this._writeStream.removeListener("write", retry);
- this._read(n);
- };
- this._writeStream.addListener("finish", retry);
- this._writeStream.addListener("write", retry);
- });
- }
- }
- exports.ReadStream = ReadStream;
- class WriteStream extends stream_1.Writable {
- constructor(options) {
- super({
- highWaterMark: options === null || options === void 0 ? void 0 : options.highWaterMark,
- defaultEncoding: options === null || options === void 0 ? void 0 : options.defaultEncoding,
- autoDestroy: false,
- });
- this._fd = null;
- this._path = null;
- this._pos = 0;
- this._readStreams = new Set();
- this._released = false;
- this._cleanupSync = () => {
- process.removeListener("exit", this._cleanupSync);
- if (typeof this._fd === "number")
- try {
- fs_1.default.closeSync(this._fd);
- }
- catch (error) {
- // An error here probably means the fd was already closed, but we can
- // still try to unlink the file.
- }
- try {
- if (this._path)
- fs_1.default.unlinkSync(this._path);
- }
- catch (error) {
- // If we are unable to unlink the file, the operating system will clean
- // up on next restart, since we use store thes in `os.tmpdir()`
- }
- };
- // Generate a random filename.
- crypto_1.default.randomBytes(16, (error, buffer) => {
- if (error) {
- this.destroy(error);
- return;
- }
- this._path = path_1.default.join(os_1.default.tmpdir(), `capacitor-${buffer.toString("hex")}.tmp`);
- // Create a file in the OS's temporary files directory.
- fs_1.default.open(this._path, "wx+", 0o600, (error, fd) => {
- if (error) {
- this.destroy(error);
- return;
- }
- // Cleanup when the process exits or is killed.
- process.addListener("exit", this._cleanupSync);
- this._fd = fd;
- this.emit("ready");
- });
- });
- }
- _final(callback) {
- if (typeof this._fd !== "number") {
- this.once("ready", () => this._final(callback));
- return;
- }
- callback();
- }
- _write(chunk, encoding, callback) {
- if (typeof this._fd !== "number") {
- this.once("ready", () => this._write(chunk, encoding, callback));
- return;
- }
- fs_1.default.write(this._fd, chunk, 0, chunk.length, this._pos, (error) => {
- if (error) {
- callback(error);
- return;
- }
- // It's safe to increment `this._pos` after flushing to the filesystem
- // because node streams ensure that only one `_write()` is active at a
- // time. If this assumption is broken, the behavior of this library is
- // undefined, regardless of where this is incremented. Relocating this
- // to increment syncronously would result in correct file contents, but
- // the out-of-order writes would still open the potential for read streams
- // to scan positions that have not yet been written.
- this._pos += chunk.length;
- this.emit("write");
- callback();
- });
- }
- release() {
- this._released = true;
- if (this._readStreams.size === 0)
- this.destroy();
- }
- _destroy(error, callback) {
- const fd = this._fd;
- const path = this._path;
- if (typeof fd !== "number" || typeof path !== "string") {
- this.once("ready", () => this._destroy(error, callback));
- return;
- }
- // Close the file descriptor.
- fs_1.default.close(fd, (closeError) => {
- // An error here probably means the fd was already closed, but we can
- // still try to unlink the file.
- fs_1.default.unlink(path, (unlinkError) => {
- // If we are unable to unlink the file, the operating system will
- // clean up on next restart, since we use store thes in `os.tmpdir()`
- this._fd = null;
- // We avoid removing this until now in case an exit occurs while
- // asyncronously cleaning up.
- process.removeListener("exit", this._cleanupSync);
- callback(unlinkError || closeError || error);
- });
- });
- // Destroy all attached read streams.
- for (const readStream of this._readStreams)
- readStream.destroy(error || undefined);
- }
- createReadStream(options) {
- if (this.destroyed)
- throw new ReadAfterDestroyedError("A ReadStream cannot be created from a destroyed WriteStream.");
- if (this._released)
- throw new ReadAfterReleasedError("A ReadStream cannot be created from a released WriteStream.");
- const readStream = new ReadStream(this, options);
- this._readStreams.add(readStream);
- const remove = () => {
- readStream.removeListener("close", remove);
- this._readStreams.delete(readStream);
- if (this._released && this._readStreams.size === 0) {
- this.destroy();
- }
- };
- readStream.addListener("close", remove);
- return readStream;
- }
- }
- exports.WriteStream = WriteStream;
- exports.default = {
- WriteStream,
- ReadStream,
- ReadAfterDestroyedError,
- ReadAfterReleasedError,
- };
- //# sourceMappingURL=index.js.map
|