44 lines
1.8 KiB
TypeScript
44 lines
1.8 KiB
TypeScript
import { Writable } from 'node:stream'
|
|
import type {
|
|
FileSystemWritableFileStream,
|
|
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 {
|
|
#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.#position = position
|
|
}
|
|
async truncate(size: number): Promise<void> {
|
|
if (this.locked) throw new Error("stream is locked")
|
|
return this.#fileHandle.truncate(size)
|
|
}
|
|
async write(data: FileSystemWriteChunkType): Promise<void> {
|
|
if (this.locked) throw new Error("stream is locked")
|
|
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
|
|
}
|
|
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
|
|
}
|
|
} |