diff --git a/src/core/dir.spec.ts b/src/core/dir.spec.ts index 199f7a3..36459fa 100644 --- a/src/core/dir.spec.ts +++ b/src/core/dir.spec.ts @@ -72,6 +72,46 @@ describe('Test Directory Service', () => { const exists = await dir.exists(); expect(exists).toBeTruthy(); }); + + describe('delete', () => { + + test('create and delete a file non recursive', async () => { + const dir = new Directory(testHelper.getBasePath(), 'to_delete'); + await dir.create(); + expect(await dir.exists()).toBeTruthy(); + await dir.delete(); + expect(await dir.exists()).toBeFalsy(); + }); + + test('delete a non existing file', async () => { + const dir = new Directory(testHelper.getBasePath(), 'to_delete'); + await dir.delete(); + expect(await dir.exists()).toBeFalsy(); + }); + + test('try to delete a non existing file with strict mode', async () => { + const dir = new Directory(testHelper.getBasePath(), 'to_delete'); + dir.strict(); + await expect(dir.delete()).rejects.toThrow(); + }); + + test('delete a non empty directory', async () => { + const dir = new Directory(testHelper.getBasePath(), 'to_delete'); + await dir.create(); + await testHelper.createFile('some content', {path: 'to_delete/test.txt'}); + await expect(dir.delete()).rejects.toThrow(); + await expect(dir.exists()).resolves.toBeTruthy(); + }); + + test('delete a non empty directory recursive', async () => { + const dir = new Directory(testHelper.getBasePath(), 'to_delete'); + await dir.create(); + await testHelper.createFile('some content', {path: 'to_delete/test_some_other'}); + await dir.delete(true); + expect(await dir.exists()).toBeFalsy(); + }); + + }); describe('list method', () => { test('list directory amount', async () => { diff --git a/src/core/dir.ts b/src/core/dir.ts index 4c20f75..1835165 100644 --- a/src/core/dir.ts +++ b/src/core/dir.ts @@ -2,17 +2,22 @@ import * as fs from 'node:fs/promises'; import { join as joinPath, relative as relativePath, resolve as resolvePath} from 'node:path'; import { LoomFile } from './file.js'; import { List } from './list.js'; - - +import { isErrnoException } from './helper/typechecks.js'; export class Directory { protected readonly _path: string; + protected _strict: boolean = false; constructor( - path: string = process.cwd() + path: string = process.cwd(), ...paths: string[] ) { - this._path = resolvePath(path); + this._path = resolvePath(path, ...(paths || [])); + } + + strict(strictMode: boolean = true) { + this._strict = strictMode; + return this; } get path() { @@ -35,17 +40,27 @@ export class Directory { } } - subDir(name: string) { - return new Directory(joinPath(this.path, name)); + async create(): Promise { + await fs.mkdir(this.path, {recursive: true}); } - /** - * @deprecated use subDir - * @param subDir - * @returns - */ - subdir(subDir: string) { - return this.subDir(subDir); + async delete(recursive: boolean = false): Promise { + try { + await fs.rmdir(this.path, {recursive}); + } catch (err) { + if(this._strict){ + throw err; + } + if(isErrnoException(err)) { + if((err as NodeJS.ErrnoException).code !== 'ENOENT' && (err as NodeJS.ErrnoException).errno !== -2) { + throw err; + } + } + } + } + + subDir(name: string) { + return new Directory(joinPath(this.path, name)); } async list(): Promise { diff --git a/src/core/helper/typechecks.ts b/src/core/helper/typechecks.ts new file mode 100644 index 0000000..5414c08 --- /dev/null +++ b/src/core/helper/typechecks.ts @@ -0,0 +1,3 @@ +export function isErrnoException(obj: unknown): obj is NodeJS.ErrnoException { + return obj instanceof Error && 'code' in obj && 'errno' in obj; +} \ No newline at end of file diff --git a/src/core/wrapper/dirent.spec.ts b/src/core/wrapper/dirent.spec.ts new file mode 100644 index 0000000..3c5143e --- /dev/null +++ b/src/core/wrapper/dirent.spec.ts @@ -0,0 +1,60 @@ +import { describe, test, expect, beforeAll } from 'vitest'; +import * as fs from 'fs/promises'; +import type { Dirent } from 'fs'; +import { DirentWrapper } from './dirent.js'; +import { Directory } from '../dir'; +import { TestFilesystemHelper } from '../../../test/helpers/testFilesystemHelper'; + +describe('Test Dirent Service', () => { + + let dir: Directory; + let dirent: Dirent; + + beforeAll(async () => { + const testHelper = TestFilesystemHelper.init(); + (await testHelper).createDir('test'); + dir = new Directory((await testHelper).getBasePath()); + dirent = (await fs.readdir(dir.path, { withFileTypes: true }))[0]; + }); + + test('Create Instance and set path', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper).toBeInstanceOf(DirentWrapper); + }); + + test('isDirectory', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.isDirectory()).toBeTruthy(); + }); + + test('isFile', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.isFile()).toBeFalsy(); + }); + + test('dirent', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.dirent).toBe(dirent); + }); + + test('dir', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.dir).toBe(dir); + }); + + test('name', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.name).toBe('test'); + }); + + test('parentPath', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.parentPath).toBe(dir.path); + }); + + test('path', async () => { + const direntWrapper = new DirentWrapper(dir, dirent); + expect(direntWrapper.path).toBe(`${dir.path}/test`); + }); + +}); \ No newline at end of file