123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.NodeFileSystemWritableFileStream = exports.createSwapFile = void 0;
- const buffer_1 = require("../internal/buffer");
- /**
- * When Chrome writes to the file, it creates a copy of the file with extension
- * `.crswap` and then replaces the original file with the copy only when the
- * `close()` method is called. If the `abort()` method is called, the `.crswap`
- * file is deleted.
- *
- * If a file name with with extension `.crswap` is already taken, it
- * creates a new swap file with extension `.1.crswap` and so on.
- */
- const createSwapFile = async (fs, path, keepExistingData) => {
- let handle;
- let swapPath = path + '.crswap';
- try {
- handle = await fs.promises.open(swapPath, 'ax');
- }
- catch (error) {
- if (!error || typeof error !== 'object' || error.code !== 'EEXIST')
- throw error;
- }
- if (!handle) {
- for (let i = 1; i < 1000; i++) {
- try {
- swapPath = `${path}.${i}.crswap`;
- handle = await fs.promises.open(swapPath, 'ax');
- break;
- }
- catch (error) {
- if (!error || typeof error !== 'object' || error.code !== 'EEXIST')
- throw error;
- }
- }
- }
- if (!handle)
- throw new Error(`Could not create a swap file for "${path}".`);
- if (keepExistingData)
- await fs.promises.copyFile(path, swapPath, fs.constants.COPYFILE_FICLONE);
- return [handle, swapPath];
- };
- exports.createSwapFile = createSwapFile;
- /**
- * Is a WritableStream object with additional convenience methods, which
- * operates on a single file on disk. The interface is accessed through the
- * `FileSystemFileHandle.createWritable()` method.
- *
- * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream
- */
- class NodeFileSystemWritableFileStream extends WritableStream {
- constructor(fs, path, keepExistingData) {
- const swap = { handle: undefined, path: '', offset: 0 };
- super({
- async start() {
- const promise = (0, exports.createSwapFile)(fs, path, keepExistingData);
- swap.ready = promise.then(() => undefined);
- const [handle, swapPath] = await promise;
- swap.handle = handle;
- swap.path = swapPath;
- },
- async write(chunk) {
- await swap.ready;
- const handle = swap.handle;
- if (!handle)
- throw new Error('Invalid state');
- const buffer = buffer_1.Buffer.from(typeof chunk === 'string' ? chunk : chunk instanceof Blob ? await chunk.arrayBuffer() : chunk);
- const { bytesWritten } = await handle.write(buffer, 0, buffer.length, swap.offset);
- swap.offset += bytesWritten;
- },
- async close() {
- await swap.ready;
- const handle = swap.handle;
- if (!handle)
- return;
- await handle.close();
- await fs.promises.rename(swap.path, path);
- },
- async abort() {
- await swap.ready;
- const handle = swap.handle;
- if (!handle)
- return;
- await handle.close();
- await fs.promises.unlink(swap.path);
- },
- });
- this.fs = fs;
- this.path = path;
- this.swap = swap;
- }
- /**
- * @sse https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/seek
- * @param position An `unsigned long` describing the byte position from the top
- * (beginning) of the file.
- */
- async seek(position) {
- this.swap.offset = position;
- }
- /**
- * @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream/truncate
- * @param size An `unsigned long` of the amount of bytes to resize the stream to.
- */
- async truncate(size) {
- await this.swap.ready;
- const handle = this.swap.handle;
- if (!handle)
- throw new Error('Invalid state');
- await handle.truncate(size);
- if (this.swap.offset > size)
- this.swap.offset = size;
- }
- async writeBase(chunk) {
- const writer = this.getWriter();
- try {
- await writer.write(chunk);
- }
- finally {
- writer.releaseLock();
- }
- }
- async write(params) {
- if (!params)
- throw new TypeError('Missing required argument: params');
- switch (typeof params) {
- case 'string': {
- return this.writeBase(params);
- }
- case 'object': {
- const constructor = params.constructor;
- switch (constructor) {
- case ArrayBuffer:
- case Blob:
- case DataView:
- return this.writeBase(params);
- default: {
- if (ArrayBuffer.isView(params)) {
- return this.writeBase(params);
- }
- else {
- const options = params;
- switch (options.type) {
- case 'write': {
- if (typeof options.position === 'number')
- await this.seek(options.position);
- return this.writeBase(params.data);
- }
- case 'truncate': {
- if (typeof params.size !== 'number')
- throw new TypeError('Missing required argument: size');
- if (this.swap.offset > params.size)
- this.swap.offset = params.size;
- return this.truncate(params.size);
- }
- case 'seek':
- if (typeof params.position !== 'number')
- throw new TypeError('Missing required argument: position');
- return this.seek(params.position);
- default:
- throw new TypeError('Invalid argument: params');
- }
- }
- }
- }
- }
- default:
- throw new TypeError('Invalid argument: params');
- }
- }
- }
- exports.NodeFileSystemWritableFileStream = NodeFileSystemWritableFileStream;
- //# sourceMappingURL=NodeFileSystemWritableFileStream.js.map
|