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.

121 lines
3.5 KiB

const Model = require('flitter-orm/src/model/Model');
const uuid = require('uuid/v4');
class VersionedModel extends Model {
static get schema() {
return {
version_archive: [Object],
version_num: { type: Number, default: 1 },
version_create_date: { type: Date, default: () => new Date },
version_user_id: String,
}
}
__is_version_instantation = false
__version_base = undefined
__version_data = undefined
is_a_version() {
return this.__is_version_instantation
}
version_base() {
return this.__version_base
}
raw_version_data() {
return this.__version_data
}
__initialize_version(base, data = {}) {
this.__is_version_instantation = true
this.__version_base = base
this.__version_data = data
}
async version_save(message = undefined, user_id = undefined) {
await this.new_version(message, user_id)
return this.save()
}
async new_version(message = undefined, user_id = undefined) {
if ( !this.version_num ) this.version_num = 1
if ( !this.version_archive ) this.version_archive = []
this.version_num += 1
this.version_create_date = new Date()
this.version_user_id = user_id
const version_data = await this.cast_to_version_data()
version_data.version_UUID = uuid()
version_data.version_message = message
this.version_archive.push(version_data)
}
async cast_to_version_data() {
const schema = this.constructor.__schema
const shallow_object = {}
for ( const prop in schema.schema ) {
if ( prop in this ) {
shallow_object[prop] = this[prop]
}
}
const data = await this.__scope_limit_save(schema.cast_to_schema(shallow_object))
delete data.version_archive
return data
}
async get_version_data(version_num = undefined) {
if ( typeof version_num === 'undefined' ) {
return await this.cast_to_version_data()
} else {
return this.version_archive.find(data => Number(data.version_num) === Number(version_num))
}
}
has_version(version_num = undefined) {
return !!this.version_archive.find(data => {
return Number(data.version_num) === Number(version_num)
})
}
toJSON() {
const data = {...this}
delete data.__version_data
delete data.__version_base
delete data.__is_version_instantation
delete data.version_archive
if ( this.is_a_version() ) {
data.version_message = this.__version_data.version_message
data.version_user_id = this.__version_data.version_user_id
}
return data
}
async as_version(version_num = undefined) {
const data = await this.get_version_data(version_num)
const inst = new this.constructor(data)
inst.__initialize_version(this, data)
return inst
}
async revert_to_version(version_num, user_id = undefined) {
const inst = await this.as_version(version_num)
inst.version_archive = this.version_archive
inst._id = this._id
inst.__is_version_instantation = false
inst.__version_base = undefined
inst.__version_data = undefined
inst.version_num = this.version_num
await inst.new_version(`Revert to version ${version_num}`, user_id)
await inst.save()
return inst
}
}
module.exports = exports = VersionedModel