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
129 lines
3.2 KiB
3 years ago
|
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
|