UNPKG

modpacksio-common

Version:

Common code for Modpacks.io services

177 lines (169 loc) 5.08 kB
const Schema = require('mongoose').Schema; const id = require('../id'); const SLUG_REGEX = /^[0-9a-zA-Z-]*$/; const SEM_VER_REGEX = /^([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))$|^([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)\.([0-9]|[1-9][0-9]*)$/; const icons = ['https://i.imgur.com/DISt7j6.png', 'https://i.imgur.com/gV5yjzG.png', 'https://i.imgur.com/Ldw4ITJ.png', 'https://i.imgur.com/KDj4QRV.png', 'https://i.imgur.com/Yt5vjBW.png', 'https://i.imgur.com/qhFTgTR.png', 'https://i.imgur.com/tUgdmEV.png', 'https://i.imgur.com/C12dO93.png', 'https://i.imgur.com/HqJ0UuY.png', 'https://i.imgur.com/UMhLly3.png']; // Author const author = new Schema({ id: Number, primary: { type: Boolean, default: false }, role: { type: String, minlength: [ 2, 'Author role must be at least 2 characters long.'], maxlength: [ 16, 'Author role must be a max of 16 characters.'] } }, { _id: false, id: false }); // Image const image = new Schema({ id: Number, name: String, description: String, url: String //todo validation on these fields }, { _id: false, id: false }); // File const file = new Schema({ id: Number, created: { type: Number, default: new Date().getTime() }, approved: { type: Boolean, default: false }, type: { type: String, required: [ true, 'A file must have a type' ], validate: { validator: type => ['fabric', 'forge'].includes(type), message: props => `${props.value} is not a valid type. Must be 'mod' or 'modpack'` } }, pre: { type: Boolean, default: false }, name: { type: String, minlength: [2, 'Summary must be at least 2 characters long.'], maxlength: [50, 'Summary must be a max of 50 characters.'] }, changelog: String, version: { type: String, validate: { validator: slug => SEM_VER_REGEX.test(slug), message: props => `${props.value} must follow semantic versioning format.` } }, gameVersion: [{ type: String, //todo validation }], javaVersion: [{ type: String, //todo validation }], sha1: String, url: String }, { _id: false, id: false }); // Project const project = new Schema({ _id: { alias: 'id', type: Number, default: id.nextId() }, type: { type: String, required: [ true, 'A project must have a type' ], validate: { validator: type => ['mod', 'modpack'].includes(type), message: props => `${props.value} is not a valid type. Must be 'mod' or 'modpack'` } }, approved: { type: Boolean, default: false }, created: { type: Number, default: new Date().getTime() }, updated: { type: Number, default: new Date().getTime() }, name: String, slug: { type: String, validate: { validator: slug => SLUG_REGEX.test(slug), message: props => `${props.value} is not a valid url member.` } }, summary: { type: String, minlength: [ 10, 'Summary must be at least 10 characters long.'], maxlength: [ 100, 'Summary must be a max of 100 characters.'] }, description: String, downloads: { type: Number, default: 0, }, license: { title: { type: String, default: 'All Rights Reserved' }, body: { type: String, default: 'All Rights Reserved unless otherwise explicitly stated.' } }, authors: [author], categories: [Number], icon: { type: String, default: icons[icons.length * Math.random() | 0] }, images: [image], languages: [String], //todo language validation files: [file], _status: { approvedBy: Number, approvedAt: Number } }); project.methods.populate = async function () { // Populate Authors const { User } = require('../database'); const raw = this.toObject({ virtuals: true, versionKey: false }); delete raw._id; for (let i = 0; i < raw.authors.length; i++) { const user = await User.findOne({ _id: raw.authors[i].id }).select('username icon'); if (user == null) throw new Error(`Project contains invalid user! (${raw.authors[i].id})`); const rtn = { ...raw.authors[i], ...user.toObject({ }) }; delete rtn._id; raw.authors[i] = rtn; } // Populate Categories // todo return raw; }; project.methods.toPublic = async function (status = false, shard = false) { const doc = await this.populate(); doc.files = doc.files.filter(file => file.approved); if (!status) delete doc._status; if (!shard) delete doc._shard; delete doc.type; return doc; }; module.exports = { project, file };