Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | 3x 3x 40x 40x 40x 52x 52x 52x 23x 23x 23x 23x 23x 29x 29x 1x 28x 23x 5x 29x 52x 35x 40x 17x 17x 17x 4x 5x 4x 4x 4x 13x 14x 11x 11x 11x 8x 5x 8x 3x 6x 6x 6x | import isPlainObject from 'lodash/isPlainObject'; import pick from 'lodash/pick'; import Project from '../models/project'; import createId from '../utils/createId'; import createApplicationErrorClass from '../utils/createApplicationErrorClass'; import createDefaultFiles from './createDefaultFiles'; export const FileValidationError = createApplicationErrorClass('FileValidationError'); export const ProjectValidationError = createApplicationErrorClass('ProjectValidationError'); /** * This converts between a mongoose Project model * and the public API Project object properties * */ export function toApi(model) { return { id: model.id, name: model.name, }; } /** * Transforms a tree of files matching the APIs DirectoryContents * format into the data structure stored in mongodb * * - flattens the tree into an array of file/folders * - each file/folder gets a generated BSON-ID * - each folder has a `children` array containing the IDs of it's children */ function transformFilesInner(tree = {}, parentNode) { const files = []; const errors = []; Object.entries(tree).forEach(([name, params]) => { const id = createId(); const isFolder = params.files != null; if (isFolder) { const folder = { _id: id, name, fileType: 'folder', children: [] // Initialise an empty folder }; files.push(folder); // The recursion will return a list of child files/folders // It will also push the child's id into `folder.children` const subFolder = transformFilesInner(params.files, folder); files.push(...subFolder.files); errors.push(...subFolder.errors); } else { const file = { _id: id, name, fileType: 'file' }; if (typeof params.url === 'string') { file.url = params.url; } else if (typeof params.content === 'string') { file.content = params.content; } else { errors.push({ name, message: 'missing \'url\' or \'content\'' }); } files.push(file); } // Push this child's ID onto it's parent's list // of children if (parentNode != null) { parentNode.children.push(id); } }); return { files, errors }; } export function transformFiles(tree = {}) { const withRoot = { root: { files: tree } }; const { files, errors } = transformFilesInner(withRoot); if (errors.length > 0) { const message = `${errors.length} files failed validation. See error.files for individual errors. Errors: ${errors.map(e => `* ${e.name}: ${e.message}`).join('\n')} `; const error = new FileValidationError(message); error.files = errors; throw error; } return files; } export function containsRootHtmlFile(tree) { return Object.keys(tree).find(name => /\.html$/.test(name)) != null; } /** * This converts between the public API's Project object * properties and a mongoose Project model * */ export function toModel(object) { let files = []; let tree = object.files; if (isPlainObject(tree)) { if (!containsRootHtmlFile(tree)) { tree = Object.assign(createDefaultFiles(), tree); } files = transformFiles(tree); } else { throw new FileValidationError('\'files\' must be an object'); } const projectValues = pick(object, ['user', 'name', 'slug']); projectValues.files = files; return new Project(projectValues); } |