You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
3.2 KiB

import { BaseProperty, PropertyType } from 'adminjs'
const ID_PROPERTY = '_id'
const VERSION_KEY_PROPERTY = '__v'
class Property extends BaseProperty {
// TODO: Fix typings
public mongoosePath: any;
/**
* Crates an object from mongoose schema path
*
* @param {SchemaString} path
* @param {String[]} path.enumValues
* @param {String} path.regExp
* @param {String} path.path
* @param {String} path.instance
* @param {Object[]} path.validators
* @param {Object[]} path.setters
* @param {Object[]} path.getters
* @param {Object} path.options
* @param {Object} path._index
* @param {number} position
*
* @private
*
* @example
*
* const schema = new mongoose.Schema({
* email: String,
* })
*
* property = new Property(schema.paths.email))
*/
constructor(path, position = 0) {
super({ path: path.path, position })
this.mongoosePath = path
}
instanceToType(mongooseInstance) {
switch (mongooseInstance) {
case 'String':
return 'string'
case 'Boolean':
return 'boolean'
case 'Number':
return 'number'
case 'Date':
return 'datetime'
case 'Embedded':
return 'mixed'
case 'ObjectID':
if (this.reference()) {
return 'reference'
}
return 'id' as PropertyType
case 'Decimal128':
return 'float'
default:
return 'string'
}
}
name() {
return this.mongoosePath.path
}
isEditable() {
return this.name() !== VERSION_KEY_PROPERTY && this.name() !== ID_PROPERTY
}
reference() {
const ref = this.isArray()
? this.mongoosePath.caster.options?.ref
: this.mongoosePath.options?.ref
if (typeof ref === 'function') return ref.modelName
return ref
}
isVisible() {
return this.name() !== VERSION_KEY_PROPERTY
}
isId() {
return this.name() === ID_PROPERTY
}
availableValues() {
return this.mongoosePath.enumValues?.length ? this.mongoosePath.enumValues : null
}
isArray() {
return this.mongoosePath.instance === 'Array'
}
subProperties() {
if (this.type() === 'mixed') {
const subPaths = Object.values(this.mongoosePath.caster.schema.paths)
return subPaths.map(p => new Property(p))
}
return []
}
type() {
if (this.isArray()) {
let { instance } = this.mongoosePath.caster
// For array of embedded schemas mongoose returns null for caster.instance
// That is why we have to check if caster has a schema
if (!instance && this.mongoosePath.caster.schema) {
instance = 'Embedded'
}
return this.instanceToType(instance)
}
return this.instanceToType(this.mongoosePath.instance)
}
isSortable() {
return this.type() !== 'mixed' && !this.isArray()
}
isRequired() {
return !!this.mongoosePath.validators?.find?.(validator => validator.type === 'required')
}
}
export default Property