Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbd975feb6 | ||
|
|
1bd153de5b | ||
|
|
a1838bc153 | ||
|
|
65e8e64079 |
+9
-6
@@ -1,14 +1,17 @@
|
||||
import NodeFileSystemDirectoryHandle from '../dist/NodeFileSystemDirectoryHandle.js'
|
||||
import NodeFileSystemDirectoryHandle from '../src/NodeFileSystemDirectoryHandle.ts'
|
||||
|
||||
const textText="Hello World!"
|
||||
const cwd_directory_handle = new NodeFileSystemDirectoryHandle('.')
|
||||
const test_directory_handle = await cwd_directory_handle.getDirectoryHandle('test', { 'create': true })
|
||||
const file_handle = await test_directory_handle.getFileHandle('test.txt', { 'create': true })
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
const file_handle = await test_directory_handle.getFileHandle(i+'.txt', { 'create': true })
|
||||
const writable = await file_handle.createWritable()
|
||||
writable.write('Hello World!')
|
||||
writable.close()
|
||||
await writable.write('Hello World!')
|
||||
await writable.close()
|
||||
const file = await file_handle.getFile()
|
||||
console.log(file.type)
|
||||
console.log(await file.text())
|
||||
const text = await file.text()
|
||||
if(text!==textText) throw new Error("failed to read back written data")
|
||||
}
|
||||
const result = await cwd_directory_handle.getFileHandle('test/test.txt').catch(error => 'blocked path traversal')
|
||||
if (typeof result === 'string') console.log(result)
|
||||
else console.error('path traversal not blocked')
|
||||
|
||||
@@ -9,7 +9,7 @@ import type {
|
||||
FileSystemGetFileOptions,
|
||||
FileSystemCreateWritableOptions,
|
||||
FileSystemWritableFileStream,
|
||||
File
|
||||
File as WebFile
|
||||
} from '@sugoidogo/importable-types-web'
|
||||
|
||||
export default class NodeFileSystemFileHandle extends NodeFileSystemHandle implements FileSystemFileHandle {
|
||||
@@ -24,13 +24,10 @@ export default class NodeFileSystemFileHandle extends NodeFileSystemHandle imple
|
||||
async createWritable(options: FileSystemCreateWritableOptions = {}): Promise<FileSystemWritableFileStream> {
|
||||
return new NodeFileSystemWritableFileStream(this.path,options)
|
||||
}
|
||||
async getFile(): Promise<File> {
|
||||
async getFile(): Promise<WebFile> {
|
||||
const stats = await asyncfs.stat(this.path)
|
||||
const type = mime.getType(this.name.split('.').pop())
|
||||
return asyncfs.readFile(this.path).then(buffer => Object.assign(new Blob([buffer], { type }), {
|
||||
lastModified: stats.mtimeMs,
|
||||
name: this.path,
|
||||
webkitRelativePath: this.path
|
||||
})) as unknown as File // TODO ArrayBufferView and DataView are incompatible types
|
||||
const buffer = await asyncfs.readFile(this.path)
|
||||
return new File([buffer], this.path, { "lastModified": stats.mtimeMs, "type": type }) as any //TODO Node File and Web File have some incompatibilities
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as fs from 'node:fs'
|
||||
import * as asyncfs from 'node:fs/promises'
|
||||
import * as path from 'node:path'
|
||||
import { Writable } from 'node:stream'
|
||||
import type {
|
||||
@@ -11,34 +10,38 @@ import type {
|
||||
|
||||
export default class NodeFileSystemWritableFileStream extends WritableStream implements FileSystemWritableFileStream {
|
||||
#seek_position = 0
|
||||
#name: string
|
||||
#fd: number
|
||||
constructor(name: string, options: FileSystemCreateWritableOptions = {}) {
|
||||
name = path.normalize(name)
|
||||
super(Writable.toWeb(fs.createWriteStream(name)))
|
||||
this.#name = name
|
||||
if(!options.keepExistingData) this.truncate(0)
|
||||
let flags = 'w'
|
||||
if (!options.keepExistingData) flags = 'r+'
|
||||
const fd = fs.openSync(name, flags)
|
||||
super(Writable.toWeb(fs.createWriteStream(name, { "fd": fd })))
|
||||
this.#fd = fd
|
||||
}
|
||||
async seek(position: number): Promise<void> {
|
||||
if (this.locked) throw new Error("stream is locked")
|
||||
this.#seek_position = position
|
||||
}
|
||||
truncate(size: number): Promise<void> {
|
||||
return asyncfs.truncate(this.#name, size)
|
||||
async truncate(size: number): Promise<void> {
|
||||
if (this.locked) throw new Error("stream is locked")
|
||||
return fs.ftruncateSync(this.#fd, size)
|
||||
}
|
||||
async write(wdata: 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 asyncfs.truncate(this.#name, size)
|
||||
if (type === 'truncate') return this.truncate(size)
|
||||
if (position) this.#seek_position = position
|
||||
if (type === 'seek') return
|
||||
if (size) wsize = size
|
||||
wdata = data
|
||||
}
|
||||
const file = await asyncfs.open(this.#name,'r+')
|
||||
await file.write((wdata as Uint8Array), null, wsize, this.#seek_position)
|
||||
fs.writeSync(this.#fd, (wdata as Uint8Array), null, wsize, this.#seek_position)
|
||||
this.#seek_position = pseek_position
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user