overleaf/services/web/scripts/fix_malformed_filetree.js

97 lines
2.4 KiB
JavaScript
Raw Normal View History

const { ObjectId } = require('mongodb')
const { db, waitForDb } = require('../app/src/infrastructure/mongodb')
async function main() {
const { projectId, mongoPath } = parseArgs()
await waitForDb()
const pathSegments = mongoPath.split('.')
const lastPathSegment = pathSegments[pathSegments.length - 1]
let modifiedCount
if (mongoPath === 'rootFolder.0') {
modifiedCount = await fixRootFolder(projectId)
} else if (endsWithNumber(mongoPath)) {
modifiedCount = await removeNullFolders(projectId, parentPath(mongoPath))
} else if (['docs', 'folders', 'fileTrees'].includes(lastPathSegment)) {
modifiedCount = await ensureElementIsArray(projectId, mongoPath)
} else {
console.error(`Unexpected mongo path: ${mongoPath}`)
process.exit(1)
}
console.log(`${modifiedCount} project(s) modified`)
process.exit(0)
}
function parseArgs() {
const args = process.argv.slice(2)
if (args.length !== 2) {
console.error('Usage: fix_malformed_filetree.js PROJECT_ID MONGO_PATH')
process.exit(1)
}
const [projectId, mongoPath] = args
return { projectId: ObjectId(projectId), mongoPath }
}
function endsWithNumber(path) {
return /\.\d+$/.test(path)
}
function parentPath(path) {
return path.slice(0, path.lastIndexOf('.'))
}
/**
* If the root folder structure is missing, set it up
*/
async function fixRootFolder(projectId) {
const result = await db.projects.updateOne(
{ _id: projectId, rootFolder: [] },
{
$set: {
rootFolder: [
{
_id: ObjectId(),
name: 'rootFolder',
folders: [],
docs: [],
fileRefs: [],
},
],
},
}
)
return result.modifiedCount
}
/**
* Remove all null entries from the given folders array
*/
async function removeNullFolders(projectId, foldersPath) {
const result = await db.projects.updateOne(
{ _id: projectId, [foldersPath]: { $exists: true } },
{ $pull: { [foldersPath]: null } }
)
return result.modifiedCount
}
/**
* If the element at the given path is not an array, set it to an empty array
*/
async function ensureElementIsArray(projectId, path) {
const result = await db.projects.updateOne(
{ _id: projectId, [path]: { $not: { $type: 'array' } } },
{ $set: { [path]: [] } }
)
return result.modifiedCount
}
main()
.then(() => {
process.exit(0)
})
.catch(err => {
console.error(err)
process.exit(1)
})