use single fd for all operations
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import * as fs from 'node:fs'
|
import * as fs from 'node:fs'
|
||||||
import * as asyncfs from 'node:fs/promises'
|
|
||||||
import * as path from 'node:path'
|
import * as path from 'node:path'
|
||||||
import { Writable } from 'node:stream'
|
import { Writable } from 'node:stream'
|
||||||
import type {
|
import type {
|
||||||
@@ -11,35 +10,51 @@ import type {
|
|||||||
|
|
||||||
export default class NodeFileSystemWritableFileStream extends WritableStream implements FileSystemWritableFileStream {
|
export default class NodeFileSystemWritableFileStream extends WritableStream implements FileSystemWritableFileStream {
|
||||||
#seek_position = 0
|
#seek_position = 0
|
||||||
#name: string
|
#fd: number
|
||||||
constructor(name: string, options: FileSystemCreateWritableOptions={}) {
|
constructor(name: string, options: FileSystemCreateWritableOptions = {}) {
|
||||||
name = path.normalize(name)
|
name = path.normalize(name)
|
||||||
super(Writable.toWeb(fs.createWriteStream(name)))
|
let flags = 'w'
|
||||||
this.#name = name
|
if (!options.keepExistingData) flags = 'r+'
|
||||||
if(!options.keepExistingData) this.truncate(0)
|
const fd = fs.openSync(name, flags)
|
||||||
|
super(Writable.toWeb(fs.createWriteStream(name, { "fd": fd })))
|
||||||
|
this.#fd = fd
|
||||||
}
|
}
|
||||||
async seek(position: number): Promise<void> {
|
async seek(position: number): Promise<void> {
|
||||||
|
if (this.locked) throw new Error("stream is locked")
|
||||||
this.#seek_position = position
|
this.#seek_position = position
|
||||||
}
|
}
|
||||||
truncate(size: number): Promise<void> {
|
async truncate(size: number): Promise<void> {
|
||||||
return asyncfs.truncate(this.#name, size)
|
if (this.locked) throw new Error("stream is locked")
|
||||||
|
return fs.ftruncateSync(this.#fd, size)
|
||||||
}
|
}
|
||||||
async write(wdata: FileSystemWriteChunkType): Promise<void> {
|
async write(wdata: FileSystemWriteChunkType): Promise<void> {
|
||||||
|
if (this.locked) throw new Error("stream is locked")
|
||||||
if (wdata instanceof Blob) wdata = await wdata.bytes()
|
if (wdata instanceof Blob) wdata = await wdata.bytes()
|
||||||
if (typeof wdata === 'string') wdata = new TextEncoder().encode(wdata)
|
if (typeof wdata === 'string') wdata = new TextEncoder().encode(wdata)
|
||||||
let wsize: number = null
|
let wsize: number = null
|
||||||
let pseek_position = this.#seek_position
|
let pseek_position = this.#seek_position
|
||||||
if ((wdata as WriteParams).type) {
|
if ((wdata as WriteParams).type) {
|
||||||
const { type, position, size, data } = (wdata as WriteParams)
|
const { type, position, size, data } = (wdata as WriteParams)
|
||||||
if (type === 'truncate') return asyncfs.truncate(this.#name, size)
|
if (type === 'truncate') return this.truncate(size)
|
||||||
if (position) this.#seek_position = position
|
if (position) this.#seek_position = position
|
||||||
if (type === 'seek') return
|
if (type === 'seek') return
|
||||||
if (size) wsize = size
|
if (size) wsize = size
|
||||||
wdata = data
|
wdata = data
|
||||||
}
|
}
|
||||||
const file = await asyncfs.open(this.#name,'r+')
|
fs.writeSync(this.#fd, (wdata as Uint8Array), null, wsize, this.#seek_position)
|
||||||
await file.write((wdata as Uint8Array), null, wsize, this.#seek_position)
|
|
||||||
await file.close()
|
|
||||||
this.#seek_position = pseek_position
|
this.#seek_position = pseek_position
|
||||||
}
|
}
|
||||||
|
async #_close() {
|
||||||
|
try {
|
||||||
|
fs.closeSync(this.#fd)
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
async close(): Promise<void> {
|
||||||
|
await super.close()
|
||||||
|
await this.#_close()
|
||||||
|
}
|
||||||
|
async abort(reason?: any): Promise<void> {
|
||||||
|
await super.abort(reason)
|
||||||
|
await this.#_close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user