@@ -1,48 +1,44 @@
|
||||
import * as fs from 'node:fs'
|
||||
import * as path from 'node:path'
|
||||
import { Writable } from 'node:stream'
|
||||
import type {
|
||||
FileSystemWritableFileStream,
|
||||
FileSystemCreateWritableOptions,
|
||||
FileSystemWriteChunkType,
|
||||
WriteParams
|
||||
} from '@sugoidogo/importable-types-web'
|
||||
import type { FileHandle } from 'node:fs/promises'
|
||||
|
||||
function isWriteParams(data: FileSystemWriteChunkType): data is WriteParams {
|
||||
return ["write", "seek", "truncate"].includes((data as WriteParams).type)
|
||||
}
|
||||
|
||||
export default class NodeFileSystemWritableFileStream extends WritableStream implements FileSystemWritableFileStream {
|
||||
#seek_position = 0
|
||||
#fd: number
|
||||
constructor(name: string, options: FileSystemCreateWritableOptions = {}) {
|
||||
name = path.normalize(name)
|
||||
let flags = 'w'
|
||||
if (options.keepExistingData) flags = 'r+'
|
||||
const fd = fs.openSync(name, flags)
|
||||
if (!options.keepExistingData) fs.ftruncateSync(fd, 0)
|
||||
super(Writable.toWeb(fs.createWriteStream(name, { "fd": fd })))
|
||||
this.#fd = fd
|
||||
#position = 0
|
||||
#fileHandle: FileHandle
|
||||
constructor(fileHandle: FileHandle) {
|
||||
const writeStream = fileHandle.createWriteStream({ "encoding": "binary" })
|
||||
const writeableStream = Writable.toWeb(writeStream)
|
||||
super(writeableStream)
|
||||
this.#fileHandle = fileHandle
|
||||
}
|
||||
async seek(position: number): Promise<void> {
|
||||
if (this.locked) throw new Error("stream is locked")
|
||||
this.#seek_position = position
|
||||
this.#position = position
|
||||
}
|
||||
async truncate(size: number): Promise<void> {
|
||||
if (this.locked) throw new Error("stream is locked")
|
||||
return fs.ftruncateSync(this.#fd, size)
|
||||
return this.#fileHandle.truncate(size)
|
||||
}
|
||||
async write(wdata: FileSystemWriteChunkType): Promise<void> {
|
||||
async write(data: FileSystemWriteChunkType): Promise<void> {
|
||||
if (this.locked) throw new Error("stream is locked")
|
||||
if (wdata instanceof Blob) wdata = await wdata.bytes()
|
||||
if (typeof wdata === 'string') wdata = new TextEncoder().encode(wdata)
|
||||
let wsize: number = null
|
||||
let pseek_position = this.#seek_position
|
||||
if ((wdata as WriteParams).type) {
|
||||
const { type, position, size, data } = (wdata as WriteParams)
|
||||
if (type === 'truncate') return this.truncate(size)
|
||||
if (position) this.#seek_position = position
|
||||
if (type === 'seek') return
|
||||
if (size) wsize = size
|
||||
wdata = data
|
||||
let offset: number, length: number, position=this.#position
|
||||
if (isWriteParams(data)) {
|
||||
if (data.type === "seek") return this.seek(data.position)
|
||||
if (data.type === "truncate") return this.truncate(data.size)
|
||||
if (typeof data.position === "number") position = data.position
|
||||
length = data.size
|
||||
data = data.data
|
||||
}
|
||||
fs.writeSync(this.#fd, (wdata as Uint8Array), null, wsize, this.#seek_position)
|
||||
this.#seek_position = pseek_position
|
||||
if (typeof data === 'string') data = new TextEncoder().encode(data)
|
||||
const { bytesWritten } = await this.#fileHandle.write(data as any, offset, length, position)
|
||||
this.#position=position+bytesWritten
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user