ipfs storage for images and other nontext items. for use with etica - runs on etica network and currencys
https://collect.etica-stats.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
2.6 KiB
100 lines
2.6 KiB
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 }
|
|
|