feat(core): Enhanced directory handling and file restoration from trash

This commit is contained in:
Philipp Kunz 2024-11-24 19:56:12 +01:00
parent 8e9041fbbf
commit 154854dc21
5 changed files with 81 additions and 10 deletions

View File

@ -1,5 +1,11 @@
# Changelog
## 2024-11-24 - 3.3.0 - feat(core)
Enhanced directory handling and file restoration from trash
- Refined getSubDirectoryByName to handle file paths treated as directories.
- Introduced file restoration function from trash to original or specified paths.
## 2024-11-24 - 3.2.2 - fix(core)
Refactor Bucket class for improved error handling

View File

@ -30,7 +30,7 @@ tap.test('should clean all contents', async () => {
tap.test('should delete a file into the normally', async () => {
const path = 'trashtest/trashme.txt';
const file = await myBucket.fastPut({
const file = await myBucket.fastPutStrict({
path,
contents: 'I\'m in the trash test content!',
});
@ -44,7 +44,7 @@ tap.test('should delete a file into the normally', async () => {
tap.test('should put a file into the trash', async () => {
const path = 'trashtest/trashme.txt';
const file = await myBucket.fastPut({
const file = await myBucket.fastPutStrict({
path,
contents: 'I\'m in the trash test content!',
});
@ -60,4 +60,19 @@ tap.test('should put a file into the trash', async () => {
});
});
tap.test('should restore a file from trash', async () => {
const baseDirectory = await myBucket.getBaseDirectory();
const file = await baseDirectory.getFileStrict({
path: 'trashtest/trashme.txt',
getFromTrash: true
});
const trashFileMeta = await file.getMetaData();
const data = await trashFileMeta.getCustomMetaData({
key: 'recycle'
});
expect(file).toBeInstanceOf(smartbucket.File);
await file.restore();
});
export default tap.start();

View File

@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartbucket',
version: '3.2.2',
version: '3.3.0',
description: 'A TypeScript library offering simple and cloud-agnostic object storage with advanced features like bucket creation, file and directory management, and data streaming.'
}

View File

@ -10,9 +10,9 @@ export class Directory {
public parentDirectoryRef: Directory;
public name: string;
public tree: string[];
public files: string[];
public folders: string[];
public tree!: string[];
public files!: string[];
public folders!: string[];
constructor(bucketRefArg: Bucket, parentDirectory: Directory, name: string) {
this.bucketRef = bucketRefArg;
@ -192,9 +192,22 @@ export class Directory {
* gets a sub directory by name
*/
public async getSubDirectoryByName(dirNameArg: string, optionsArg: {
/**
* in s3 a directory does not exist if it is empty
* this option returns a directory even if it is empty
*/
getEmptyDirectory?: boolean;
/**
* in s3 a directory does not exist if it is empty
* this option creates a directory even if it is empty using a initializer file
*/
createWithInitializerFile?: boolean;
/**
* if the path is a file path, it will be treated as a file and the parent directory will be returned
*/
couldBeFilePath?: boolean;
} = {}): Promise<Directory | null> {
const dirNameArray = dirNameArg.split('/').filter(str => str.trim() !== "");
optionsArg = {
@ -221,8 +234,19 @@ export class Directory {
return returnDirectory || null;
};
if (optionsArg.couldBeFilePath) {
const baseDirectory = await this.bucketRef.getBaseDirectory();
const existingFile = await baseDirectory.getFile({
path: dirNameArg,
});
if (existingFile) {
const adjustedPath = dirNameArg.substring(0, dirNameArg.lastIndexOf('/'));
return this.getSubDirectoryByName(adjustedPath);
}
}
let wantedDirectory: Directory | null = null;
let counter = 0;
let counter = 0;
for (const dirNameToSearch of dirNameArray) {
counter++;
const directoryToSearchIn = wantedDirectory ? wantedDirectory : this;
@ -336,7 +360,7 @@ export class Directory {
*/
mode?: 'permanent' | 'trash';
}) {
const file = await this.getFile({
const file = await this.getFileStrict({
path: optionsArg.path,
});
await file.delete({

View File

@ -130,6 +130,29 @@ export class File {
await this.parentDirectoryRef.listFiles();
}
/**
* restores
*/
public async restore(optionsArg: {
useOriginalPath?: boolean;
toPath?: string;
overwrite?: boolean;
} = {}) {
optionsArg = {
useOriginalPath: (() => {
return optionsArg.toPath ? false : true;
})(),
overwrite: false,
...optionsArg,
};
const moveToPath = optionsArg.toPath || (await (await this.getMetaData()).getCustomMetaData({
key: 'recycle'
})).originalPath;
await this.move({
path: moveToPath,
})
}
/**
* allows locking the file
* @param optionsArg
@ -154,7 +177,7 @@ export class File {
}) {
const metadata = await this.getMetaData();
await metadata.removeLock({
force: optionsArg?.force,
force: optionsArg?.force || false,
});
}
@ -219,7 +242,10 @@ export class File {
// lets update references of this
const baseDirectory = await this.parentDirectoryRef.bucketRef.getBaseDirectory();
this.parentDirectoryRef = await baseDirectory.getSubDirectoryByNameStrict(
pathDescriptorArg.directory?.getBasePath()!
await helpers.reducePathDescriptorToPath(pathDescriptorArg),
{
couldBeFilePath: true,
}
);
this.name = pathDescriptorArg.path!;
}