UNPKG

pauls-dat-api

Version:

Library of functions that make working with dat / hyperdrive easier.

131 lines (119 loc) 3.44 kB
const path = require('path') const {maybe, toBeakerError} = require('./common') const { NotFoundError, NotAFileError, NotAFolderError, DestDirectoryNotEmpty, ArchiveNotWritableError } = require('beaker-error-constants') const {stat} = require('./lookup') const {readdir} = require('./read') function unlink (archive, name, cb) { return maybe(cb, async function () { // ensure we have the archive's private key if (archive.key && !archive.writable) { throw new ArchiveNotWritableError() } // ensure the target location is a file var st try { st = await stat(archive, name) } catch (e) {} if (!st) { throw new NotFoundError() } if (!st.isFile()) { throw new NotAFileError('Cannot unlink non-files') } // write return new Promise((resolve, reject) => { archive.unlink(name, err => { if (err) reject(toBeakerError(err, 'unlink')) else resolve() }) }) }) } function rmdir (archive, name, opts, cb) { if (typeof opts === 'function') { cb = opts opts = {} } return maybe(cb, async function () { opts = opts || {} var recursive = opts && opts.recursive // ensure we have the archive's private key if (archive.key && !archive.writable) { throw new ArchiveNotWritableError() } // ensure the target location is a folder var st try { st = await stat(archive, name) } catch (e) {} if (!st) { throw new NotFoundError() } if (!st.isDirectory()) { throw new NotAFolderError('Cannot rmdir non-folders') } if (recursive) { // TODO // fetch and delete all children // var release = await lock(archive) try { return recurseDelete(archive, name, st) } finally { // release() } } else { // delete if there are no children var children = await readdir(archive, name) if (children.length) { throw new DestDirectoryNotEmpty() } return new Promise((resolve, reject) => { archive.rmdir(name, err => { if (err) reject(toBeakerError(err, 'rmdir')) else resolve() }) }) } }) } async function recurseDelete (archive, targetPath, st) { // fetch stat if needed if (!st) { st = await stat(archive, targetPath) } if (st.isFile()) { // delete file return new Promise((resolve, reject) => { archive.unlink(targetPath, (err) => { if (err) reject(toBeakerError(err, 'unlink')) else resolve() }) }) } else if (st.isDirectory()) { // fetch children var children = await readdir(archive, targetPath) // delete children for (var i = 0; i < children.length; i++) { await recurseDelete(archive, path.join(targetPath, children[i])) } // delete self return new Promise((resolve, reject) => { archive.rmdir(targetPath, err => { // FIXME // there's a hyperdrive bug that causes empty dirs to register as NotFound // https://github.com/mafintosh/append-tree/issues/6 // if (err) reject(toBeakerError(err, 'rmdir')) // else resolve() if (err) { console.warn('rmdir issue (append-tree#6)', err) } resolve() }) }) } else { throw new Error('Unexpectedly encountered an entry which is neither a file or directory at', path) } } module.exports = {unlink, rmdir}