memfs
Version:
In-memory file-system with Node's fs API.
217 lines • 9.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeFileSystemDirectoryHandle = void 0;
const NodeFileSystemHandle_1 = require("./NodeFileSystemHandle");
const util_1 = require("./util");
const NodeFileSystemFileHandle_1 = require("./NodeFileSystemFileHandle");
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle
*/
class NodeFileSystemDirectoryHandle extends NodeFileSystemHandle_1.NodeFileSystemHandle {
constructor(fs, path, ctx = {}) {
const fullCtx = (0, util_1.ctx)(ctx);
super('directory', (0, util_1.basename)(path, fullCtx.separator));
this.fs = fs;
this.ctx = fullCtx;
this.__path = path[path.length - 1] === this.ctx.separator ? path : path + this.ctx.separator;
}
/**
* Returns a new array iterator containing the keys for each item in
* {@link NodeFileSystemDirectoryHandle} object.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/keys
*/
async *keys() {
const list = await this.fs.promises.readdir(this.__path);
for (const name of list)
yield '' + name;
}
/**
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/entries
*/
async *entries() {
const { __path: path, fs, ctx } = this;
const list = await fs.promises.readdir(path, { withFileTypes: true });
for (const d of list) {
const dirent = d;
const name = dirent.name + '';
const newPath = path + name;
if (dirent.isDirectory())
yield [name, new NodeFileSystemDirectoryHandle(fs, newPath, ctx)];
else if (dirent.isFile())
yield [name, new NodeFileSystemFileHandle_1.NodeFileSystemFileHandle(fs, newPath, ctx)];
}
}
/**
* Returns a new array iterator containing the values for each index in the
* {@link FileSystemDirectoryHandle} object.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/values
*/
async *values() {
for await (const [, value] of this.entries())
yield value;
}
/**
* Returns a {@link NodeFileSystemDirectoryHandle} for a subdirectory with the specified
* name within the directory handle on which the method is called.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/getDirectoryHandle
* @param name A string representing the {@link NodeFileSystemHandle} name of
* the subdirectory you wish to retrieve.
* @param options An optional object containing options for the retrieved
* subdirectory.
*/
async getDirectoryHandle(name, options) {
(0, util_1.assertName)(name, 'getDirectoryHandle', 'FileSystemDirectoryHandle');
const filename = this.__path + name;
const { fs } = this;
try {
const stats = await fs.promises.stat(filename);
if (!stats.isDirectory())
throw (0, util_1.newTypeMismatchError)();
return new NodeFileSystemDirectoryHandle(fs, filename, this.ctx);
}
catch (error) {
if (error instanceof DOMException)
throw error;
if (error && typeof error === 'object') {
switch (error.code) {
case 'ENOENT': {
if (options?.create) {
(0, util_1.assertCanWrite)(this.ctx.mode);
try {
await fs.promises.mkdir(filename);
}
catch (mkdirError) {
if (mkdirError && typeof mkdirError === 'object' && mkdirError.code === 'EEXIST') {
const stats = await fs.promises.stat(filename);
if (!stats.isDirectory())
throw (0, util_1.newTypeMismatchError)();
return new NodeFileSystemDirectoryHandle(fs, filename, this.ctx);
}
throw mkdirError;
}
return new NodeFileSystemDirectoryHandle(fs, filename, this.ctx);
}
throw (0, util_1.newNotFoundError)();
}
case 'EPERM':
case 'EACCES':
throw (0, util_1.newNotAllowedError)();
}
}
throw error;
}
}
/**
* Returns a {@link FileSystemFileHandle} for a file with the specified name,
* within the directory the method is called.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/getFileHandle
* @param name A string representing the {@link NodeFileSystemHandle} name of
* the file you wish to retrieve.
* @param options An optional object containing options for the retrieved file.
*/
async getFileHandle(name, options) {
(0, util_1.assertName)(name, 'getFileHandle', 'FileSystemDirectoryHandle');
const filename = this.__path + name;
try {
const stats = await this.fs.promises.stat(filename);
if (!stats.isFile())
throw (0, util_1.newTypeMismatchError)();
return new NodeFileSystemFileHandle_1.NodeFileSystemFileHandle(this.fs, filename, this.ctx);
}
catch (error) {
if (error instanceof DOMException)
throw error;
if (error && typeof error === 'object') {
switch (error.code) {
case 'ENOENT': {
if (options?.create) {
(0, util_1.assertCanWrite)(this.ctx.mode);
await this.fs.promises.writeFile(filename, '');
return new NodeFileSystemFileHandle_1.NodeFileSystemFileHandle(this.fs, filename, this.ctx);
}
throw (0, util_1.newNotFoundError)();
}
case 'EPERM':
case 'EACCES':
throw (0, util_1.newNotAllowedError)();
}
}
throw error;
}
}
/**
* Attempts to remove an entry if the directory handle contains a file or
* directory called the name specified.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/removeEntry
* @param name A string representing the {@link FileSystemHandle} name of the
* entry you wish to remove.
* @param options An optional object containing options.
*/
async removeEntry(name, { recursive = false } = {}) {
(0, util_1.assertCanWrite)(this.ctx.mode);
(0, util_1.assertName)(name, 'removeEntry', 'FileSystemDirectoryHandle');
const filename = this.__path + name;
const promises = this.fs.promises;
try {
const stats = await promises.stat(filename);
if (stats.isFile()) {
await promises.unlink(filename);
}
else if (stats.isDirectory()) {
await promises.rmdir(filename, { recursive });
}
else
throw (0, util_1.newTypeMismatchError)();
}
catch (error) {
if (error instanceof DOMException)
throw error;
if (error && typeof error === 'object') {
switch (error.code) {
case 'ENOENT': {
throw (0, util_1.newNotFoundError)();
}
case 'EPERM':
case 'EACCES':
throw (0, util_1.newNotAllowedError)();
case 'ENOTEMPTY':
throw new DOMException('The object can not be modified in this way.', 'InvalidModificationError');
}
}
throw error;
}
}
/**
* The `resolve()` method of the {@link FileSystemDirectoryHandle} interface
* returns an {@link Array} of directory names from the parent handle to the specified
* child entry, with the name of the child entry as the last array item.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle/resolve
* @param possibleDescendant The {@link IFileSystemHandle} from which
* to return the relative path.
*/
async resolve(possibleDescendant) {
if (possibleDescendant instanceof NodeFileSystemDirectoryHandle ||
possibleDescendant instanceof NodeFileSystemFileHandle_1.NodeFileSystemFileHandle) {
const path = this.__path;
const childPath = possibleDescendant.__path;
if (!childPath.startsWith(path))
return null;
let relative = childPath.slice(path.length);
if (relative === '')
return [];
const separator = this.ctx.separator;
if (relative[0] === separator)
relative = relative.slice(1);
return relative.split(separator);
}
return null;
}
}
exports.NodeFileSystemDirectoryHandle = NodeFileSystemDirectoryHandle;
//# sourceMappingURL=NodeFileSystemDirectoryHandle.js.map