From 33f7baacf8667dc1f2b77269db3e4baf6b068644 Mon Sep 17 00:00:00 2001 From: Hunter Perrin Date: Mon, 1 Aug 2022 11:15:17 -0700 Subject: [PATCH] feat: delete orphaned config files on folder delete --- src/FileSystemAdapter/Lock.ts | 8 ++++++ src/FileSystemAdapter/Properties.ts | 2 +- src/FileSystemAdapter/Resource.ts | 38 +++++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/FileSystemAdapter/Lock.ts b/src/FileSystemAdapter/Lock.ts index 4d9d27b..c22a807 100644 --- a/src/FileSystemAdapter/Lock.ts +++ b/src/FileSystemAdapter/Lock.ts @@ -8,22 +8,30 @@ export default class Lock implements LockInterface { user: User; date: Date; timeout: number; + guid: string; + depth: '0' | 'infinity'; constructor({ resource, user, date, timeout, + guid, + depth, }: { resource: Resource; user: User; date: Date; timeout: number; + guid: string; + depth: '0' | 'infinity'; }) { this.resource = resource; this.user = user; this.date = date; this.timeout = timeout; + this.guid = guid; + this.depth = depth; } async save() { diff --git a/src/FileSystemAdapter/Properties.ts b/src/FileSystemAdapter/Properties.ts index 92ba439..037d8d7 100644 --- a/src/FileSystemAdapter/Properties.ts +++ b/src/FileSystemAdapter/Properties.ts @@ -58,7 +58,7 @@ export default class Properties implements PropertiesInterface { try { const props = JSON.parse((await fsp.readFile(filepath)).toString()); - if (!(name in props['*'])) { + if (!('*' in props) || !(name in props['*'])) { throw new PropertyNotFoundError( `${name} property doesn't exist on resource.` ); diff --git a/src/FileSystemAdapter/Resource.ts b/src/FileSystemAdapter/Resource.ts index 8451a87..e417a9a 100644 --- a/src/FileSystemAdapter/Resource.ts +++ b/src/FileSystemAdapter/Resource.ts @@ -216,6 +216,7 @@ export default class Resource implements ResourceInterface { } if (await this.isCollection()) { + await this.deleteOrphanedConfigFiles(); await fsp.rmdir(this.absolutePath); } else { await fsp.unlink(this.absolutePath); @@ -293,7 +294,7 @@ export default class Resource implements ResourceInterface { try { const dirname = path.dirname(destinationPath); const basename = path.basename(destinationPath); - propsFilePath = path.join(dirname, `.${basename}.nepheleprops`); + propsFilePath = path.join(dirname, `${basename}.nepheleprops`); try { await fsp.unlink(propsFilePath); } catch (e: any) { @@ -461,7 +462,40 @@ export default class Resource implements ResourceInterface { } else { const dirname = path.dirname(this.absolutePath); const basename = path.basename(this.absolutePath); - return path.join(dirname, `.${basename}.nepheleprops`); + return path.join(dirname, `${basename}.nepheleprops`); + } + } + + async deleteOrphanedConfigFiles() { + if (!(await this.isCollection())) { + throw new MethodNotSupportedError('This is not a collection.'); + } + + const listing = await fsp.readdir(this.absolutePath); + const files: Set = new Set(); + const propsFiles: Set = new Set(); + + for (let name of listing) { + if (name === '.nepheleprops') { + continue; + } + + if (name.endsWith('.nepheleprops')) { + propsFiles.add(name); + } else { + files.add(name); + } + } + + for (let name of files) { + propsFiles.delete(`${name}.nepheleprops`); + } + + const orphans = Array.from(propsFiles); + + for (let name of orphans) { + const orphanPath = path.join(this.absolutePath, name); + await fsp.unlink(orphanPath); } } }