Skip to content

Commit dbeada5

Browse files
committed
transformFiles will return file validation errors
1 parent 8699c1b commit dbeada5

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

server/domain-objects/Project.js

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import pick from 'lodash/pick';
22
import Project from '../models/project';
33
import createId from '../utils/createId';
4+
import createApplicationErrorClass from '../utils/createApplicationErrorClass';
5+
6+
export const FileValidationError = createApplicationErrorClass('FileValidationError');
7+
48

59
// objectID().toHexString();
610
/**
@@ -23,10 +27,11 @@ export function toApi(model) {
2327
* - each file/folder gets a generated BSON-ID
2428
* - each folder has a `children` array containing the IDs of it's children
2529
*/
26-
function transformFilesInner(files = {}, parentNode) {
27-
const allFiles = [];
30+
function transformFilesInner(tree = {}, parentNode) {
31+
const files = [];
32+
const errors = [];
2833

29-
Object.entries(files).forEach(([name, params]) => {
34+
Object.entries(tree).forEach(([name, params]) => {
3035
const id = createId();
3136
const isFolder = params.files != null;
3237

@@ -38,11 +43,13 @@ function transformFilesInner(files = {}, parentNode) {
3843
children: [] // Initialise an empty folder
3944
};
4045

41-
allFiles.push(folder);
46+
files.push(folder);
4247

4348
// The recursion will return a list of child files/folders
4449
// It will also push the child's id into `folder.children`
45-
allFiles.push(...transformFilesInner(params.files, folder));
50+
const subFolder = transformFilesInner(params.files, folder);
51+
files.push(...subFolder.files);
52+
errors.push(...subFolder.errors);
4653
} else {
4754
const file = {
4855
_id: id,
@@ -55,10 +62,10 @@ function transformFilesInner(files = {}, parentNode) {
5562
} else if (typeof params.content === 'string') {
5663
file.content = params.content;
5764
} else {
58-
throw new Error('url or params must be supplied');
65+
errors.push({ name, message: 'missing \'url\' or \'content\'' });
5966
}
6067

61-
allFiles.push(file);
68+
files.push(file);
6269
}
6370

6471
// Push this child's ID onto it's parent's list
@@ -68,17 +75,31 @@ function transformFilesInner(files = {}, parentNode) {
6875
}
6976
});
7077

71-
return allFiles;
78+
return { files, errors };
7279
}
7380

74-
export function transformFiles(files = {}) {
81+
export function transformFiles(tree = {}) {
7582
const withRoot = {
7683
root: {
77-
files
84+
files: tree
7885
}
7986
};
8087

81-
return transformFilesInner(withRoot);
88+
const { files, errors } = transformFilesInner(withRoot);
89+
90+
if (errors.length > 0) {
91+
const message = `${errors.length} files failed validation. See error.files for individual errors.
92+
93+
Errors:
94+
${errors.map(e => `* ${e.name}: ${e.message}`).join('\n')}
95+
`;
96+
const error = new FileValidationError(message);
97+
error.files = errors;
98+
99+
throw error;
100+
}
101+
102+
return files;
82103
}
83104

84105
/**

server/domain-objects/__test__/Project.test.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { transformFiles } from '../Project';
1+
import { transformFiles, FileValidationError } from '../Project';
22

33
jest.mock('../../utils/createId');
44

@@ -240,5 +240,33 @@ describe('domain-objects/Project', () => {
240240
}
241241
]);
242242
});
243+
244+
it('validates files', () => {
245+
const tree = {
246+
'index.html': {} // missing `content`
247+
};
248+
249+
expect(() => transformFiles(tree)).toThrowError(FileValidationError);
250+
});
251+
252+
it('collects all file validation errors', () => {
253+
const tree = {
254+
'index.html': {}, // missing `content`
255+
'something.js': {} // also missing `content`
256+
};
257+
258+
try {
259+
transformFiles(tree);
260+
261+
// Should not get here
262+
throw new Error('should have thrown before this point');
263+
} catch (err) {
264+
expect(err).toBeInstanceOf(FileValidationError);
265+
expect(err.files).toEqual([
266+
{ name: 'index.html', message: 'missing \'url\' or \'content\'' },
267+
{ name: 'something.js', message: 'missing \'url\' or \'content\'' }
268+
]);
269+
}
270+
});
243271
});
244272
});

0 commit comments

Comments
 (0)