Skip to content

Commit

Permalink
Merge pull request #140 from PermanentOrg/125-throw-meaningful-errors
Browse files Browse the repository at this point in the history
Throw more specific errors
  • Loading branch information
slifty committed Apr 17, 2023
2 parents e78ff76 + 5b4bd8c commit 492c62e
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 19 deletions.
11 changes: 10 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
},
"plugins": [
"@typescript-eslint",
"eslint-plugin-import"
"eslint-plugin-import",
"sort-exports"
],
"extends": [
"plugin:@typescript-eslint/all",
Expand All @@ -21,6 +22,14 @@
"newlines-between": "never"
}]
},
"overrides": [
{
"files": [ "**/index.ts" ],
"rules": {
"sort-exports/sort-exports": ["error", { "sortDir": "asc" }]
}
}
],
"env": {
"es6": true,
"node": true,
Expand Down
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-sort-exports": "^0.8.0",
"jest": "^29.5.0",
"nodemon": "^2.0.19",
"typescript": "^4.5.4"
Expand Down
43 changes: 25 additions & 18 deletions src/classes/PermanentFileSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ import {
getArchiveRecord,
getAuthenticatedAccount,
} from '@permanentorg/sdk';
import {
FileStillProcessingError,
InvalidOperationForPathError,
NotFoundError,
OperationNotAllowedError,
ResourceDoesNotExistError,
} from '../errors';
import {
deduplicateFileEntries,
generateAttributesForArchive,
Expand Down Expand Up @@ -121,7 +128,7 @@ export class PermanentFileSystem {
true,
);
}
throw new Error(`This path does not exist ${itemPath}`);
throw new NotFoundError(`This path does not exist ${itemPath}`);
}

public async getItemAttributes(itemPath: string): Promise<Attributes> {
Expand All @@ -146,7 +153,7 @@ export class PermanentFileSystem {
return generateAttributesForFolder(folder);
}
default:
throw new Error('The specified path is neither a file nor a directory.');
throw new NotFoundError('The specified path is neither a file nor a directory.');
}
}

Expand All @@ -171,13 +178,13 @@ export class PermanentFileSystem {

public async createDirectory(requestedPath: string): Promise<Folder> {
if (isRootPath(requestedPath)) {
throw new Error('You cannot create new root level folders via SFTP.');
throw new InvalidOperationForPathError('You cannot create new root level folders via SFTP.');
}
if (isArchiveCataloguePath(requestedPath)) {
throw new Error('You cannot create new archives via SFTP.');
throw new InvalidOperationForPathError('You cannot create new archives via SFTP.');
}
if (isArchivePath(requestedPath)) {
throw new Error('You cannot create new folders at the root level of an archive via SFTP.');
throw new InvalidOperationForPathError('You cannot create new folders at the root level of an archive via SFTP.');
}
const parentPath = path.dirname(requestedPath);
const childName = path.basename(requestedPath);
Expand All @@ -196,17 +203,17 @@ export class PermanentFileSystem {
this.getClientConfiguration(),
);
if (!account.isSftpDeletionEnabled) {
throw new Error('You must enable SFTP deletion directly in your account settings.');
throw new OperationNotAllowedError('You must enable SFTP deletion directly in your account settings.');
}

if (isRootPath(requestedPath)) {
throw new Error('You cannot delete the root level folder.');
throw new InvalidOperationForPathError('You cannot delete the root level folder.');
}
if (isArchiveCataloguePath(requestedPath)) {
throw new Error('You cannot delete the archive catalogue.');
throw new InvalidOperationForPathError('You cannot delete the archive catalogue.');
}
if (isArchivePath(requestedPath)) {
throw new Error('You cannot delete archives via SFTP.');
throw new InvalidOperationForPathError('You cannot delete archives via SFTP.');
}

const folder = await this.loadFolder(requestedPath);
Expand Down Expand Up @@ -245,11 +252,11 @@ export class PermanentFileSystem {
this.getClientConfiguration(),
);
if (!account.isSftpDeletionEnabled) {
throw new Error('You must enable SFTP deletion directly in your account settings.');
throw new OperationNotAllowedError('You must enable SFTP deletion directly in your account settings.');
}

if (!isItemPath(requestedPath)) {
throw new Error('Invalid file path');
throw new InvalidOperationForPathError('Invalid file path');
}

const archiveRecord = await this.loadArchiveRecord(
Expand All @@ -267,7 +274,7 @@ export class PermanentFileSystem {
overrideCache = false,
): Promise<File> {
if (!isItemPath(requestedPath)) {
throw new Error('Invalid file path');
throw new InvalidOperationForPathError('Invalid file path');
}
await this.waitForPopulatedOriginalFile(requestedPath);
const archiveRecord = await this.loadArchiveRecord(
Expand Down Expand Up @@ -298,7 +305,7 @@ export class PermanentFileSystem {
try {
const originalFile = getOriginalFileForArchiveRecord(archiveRecord);
if (originalFile.downloadUrl === '') {
throw new Error('The original file is incomplete');
throw new FileStillProcessingError('The original file is incomplete');
}
return;
} catch {
Expand Down Expand Up @@ -384,7 +391,7 @@ export class PermanentFileSystem {
const archives = await this.loadArchives();
const archive = archives.find((candidate) => candidate.slug === slug);
if (archive === undefined) {
throw new Error('An archive with that slug could not be found');
throw new ResourceDoesNotExistError('An archive with that slug could not be found');
}
return archive;
}
Expand All @@ -410,7 +417,7 @@ export class PermanentFileSystem {

private async loadArchive(requestedPath: string): Promise<Archive> {
if (!isArchivePath(requestedPath)) {
throw new Error('The requested path is not an archive');
throw new InvalidOperationForPathError('The requested path is not an archive');
}
const archiveSlug = getArchiveSlugFromPath(requestedPath);
return this.loadArchiveByArchiveSlug(archiveSlug);
Expand All @@ -430,7 +437,7 @@ export class PermanentFileSystem {
);

if (overrideParentCache && !targetFolder) {
throw new Error('The specified folder does not exist');
throw new ResourceDoesNotExistError('The specified folder does not exist');
}
return targetFolder ?? this.findFolderInParentDirectory(
parentPath,
Expand All @@ -456,7 +463,7 @@ export class PermanentFileSystem {
return targetArchiveRecord;
}
if (overrideParentCache) {
throw new Error('The specified archive record does not exist');
throw new ResourceDoesNotExistError('The specified archive record does not exist');
}
// At this point we know that the lookup failed but ALSO that we may have been using a cached
// version of the parent directory when checking for the child (`overrideParentCache` is false).
Expand All @@ -479,7 +486,7 @@ export class PermanentFileSystem {
}

if (!isItemPath(requestedPath)) {
throw new Error('The requested path is not a folder');
throw new InvalidOperationForPathError('The requested path is not a folder');
}

const parentPath = path.dirname(requestedPath);
Expand Down
1 change: 1 addition & 0 deletions src/errors/FileStillProcessingError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class FileStillProcessingError extends Error {}
1 change: 1 addition & 0 deletions src/errors/InvalidOperationForPathError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class InvalidOperationForPathError extends Error {}
1 change: 1 addition & 0 deletions src/errors/NotFoundError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class NotFoundError extends Error {}
1 change: 1 addition & 0 deletions src/errors/OperationNotAllowedError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class OperationNotAllowedError extends Error {}
1 change: 1 addition & 0 deletions src/errors/ResourceDoesNotExistError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export class ResourceDoesNotExistError extends Error {}
5 changes: 5 additions & 0 deletions src/errors/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './FileStillProcessingError';
export * from './InvalidOperationForPathError';
export * from './NotFoundError';
export * from './OperationNotAllowedError';
export * from './ResourceDoesNotExistError';

0 comments on commit 492c62e

Please sign in to comment.