Spaces:
Sleeping
Sleeping
import { statSync, createReadStream, promises as fs } from 'node:fs' | |
import { basename } from 'node:path' | |
import DOMException from 'node-domexception' | |
import File from './file.js' | |
import Blob from './index.js' | |
const { stat } = fs | |
/** | |
* @param {string} path filepath on the disk | |
* @param {string} [type] mimetype to use | |
*/ | |
const blobFromSync = (path, type) => fromBlob(statSync(path), path, type) | |
/** | |
* @param {string} path filepath on the disk | |
* @param {string} [type] mimetype to use | |
* @returns {Promise<Blob>} | |
*/ | |
const blobFrom = (path, type) => stat(path).then(stat => fromBlob(stat, path, type)) | |
/** | |
* @param {string} path filepath on the disk | |
* @param {string} [type] mimetype to use | |
* @returns {Promise<File>} | |
*/ | |
const fileFrom = (path, type) => stat(path).then(stat => fromFile(stat, path, type)) | |
/** | |
* @param {string} path filepath on the disk | |
* @param {string} [type] mimetype to use | |
*/ | |
const fileFromSync = (path, type) => fromFile(statSync(path), path, type) | |
// @ts-ignore | |
const fromBlob = (stat, path, type = '') => new Blob([new BlobDataItem({ | |
path, | |
size: stat.size, | |
lastModified: stat.mtimeMs, | |
start: 0 | |
})], { type }) | |
// @ts-ignore | |
const fromFile = (stat, path, type = '') => new File([new BlobDataItem({ | |
path, | |
size: stat.size, | |
lastModified: stat.mtimeMs, | |
start: 0 | |
})], basename(path), { type, lastModified: stat.mtimeMs }) | |
/** | |
* This is a blob backed up by a file on the disk | |
* with minium requirement. Its wrapped around a Blob as a blobPart | |
* so you have no direct access to this. | |
* | |
* @private | |
*/ | |
class BlobDataItem { | |
#path | |
#start | |
constructor (options) { | |
this.#path = options.path | |
this.#start = options.start | |
this.size = options.size | |
this.lastModified = options.lastModified | |
} | |
/** | |
* Slicing arguments is first validated and formatted | |
* to not be out of range by Blob.prototype.slice | |
*/ | |
slice (start, end) { | |
return new BlobDataItem({ | |
path: this.#path, | |
lastModified: this.lastModified, | |
size: end - start, | |
start: this.#start + start | |
}) | |
} | |
async * stream () { | |
const { mtimeMs } = await stat(this.#path) | |
if (mtimeMs > this.lastModified) { | |
throw new DOMException('The requested file could not be read, typically due to permission problems that have occurred after a reference to a file was acquired.', 'NotReadableError') | |
} | |
yield * createReadStream(this.#path, { | |
start: this.#start, | |
end: this.#start + this.size - 1 | |
}) | |
} | |
get [Symbol.toStringTag] () { | |
return 'Blob' | |
} | |
} | |
export default blobFromSync | |
export { File, Blob, blobFrom, blobFromSync, fileFrom, fileFromSync } | |