'use strict'
const { get, set, isEmpty, isArray, merge } = require('lodash')const mongoose = require('mongoose')const TYPES = mongoose.Schema.Typesconst Schema = mongoose.Schemaconst DEFAULT_COLLECTION_NAME = 'historyLogs'mongoose.Promise = global.Promise
module.exports.HistoryLogModel = function (options) { const collectionName = get(options, 'customCollectionName', DEFAULT_COLLECTION_NAME)
if (!(collectionName in mongoose.models)) { return initializeInstanceModel(collectionName, options) } return mongoose.models[collectionName]}
function DefaultSchema () { return { documentNumber: { type: TYPES.String, required: true }, action: { type: TYPES.String, required: true }, method: { type: TYPES.String, required: true }, user: { type: TYPES.Mixed, require: true }, createdAt: { type: TYPES.Date, required: true, default: Date.now }, module: { type: TYPES.String, require: true }, changes: { type: [TYPES.Mixed], required: true } }}
function getOptionsVersionInstance (mongooseInstance) { const version = parseInt(get(mongooseInstance, 'version')) if (version < 5) { return merge({}, { useMongoClient: true }) } return merge({}, { useUnifiedTopology: true, useNewUrlParser: true, useFindAndModify: false, autoIndex: true })}
function initializeInstanceModel (collectionName, options) { const connectionUri = get(options, 'connectionUri')
const schema = initializeDefaultSchema(options)
if (connectionUri) { return otherConnection(collectionName, options) } return getOrAddNewInstanceModel(mongoose, collectionName, schema)}
function getOrAddNewInstanceModel (mongooseInstance, collectionName, schema) { if (mongooseInstance.models[collectionName]) { return mongooseInstance.models[collectionName] } else { return mongooseInstance.model(collectionName, schema, collectionName) }}
function initializeDefaultSchema (options) { const defaultSchema = addNewPathsInSchema(new DefaultSchema(), options) const schema = new Schema(defaultSchema, { id: true, versionKey: false }) ensureIndex(schema, options) return schema}
function otherConnection (collectionName, options) { const connectionUri = get(options, 'connectionUri') const dbOptions = getOptionsVersionInstance(mongoose) const schema = initializeDefaultSchema(options)
const otherConnection = mongoose.createConnection(connectionUri, dbOptions) return getOrAddNewInstanceModel(otherConnection, collectionName, schema)}
function ensureIndex (schema, options) { const indexes = get(options, 'indexes') const addCollectionPaths = get(options, 'addCollectionPaths', [])
schema.index({ module: 1 }) schema.index({ method: 1 }) schema.index({ documentNumber: 1 })
if (!isEmpty(indexes) && isArray(addCollectionPaths)) { indexes.map((idx) => schema.index(idx)) }
return schema}
function addNewPathsInSchema (schema, options) { const addCollectionPaths = get(options, 'addCollectionPaths', [])
if (isEmpty(addCollectionPaths) || !isArray(addCollectionPaths)) { return schema }
addCollectionPaths.map(({ key, value, defaultValue }) => { const newField = {} if (TYPES[value]) { newField.type = TYPES[value] } if (defaultValue !== undefined) { newField.default = defaultValue } set(schema, `${key}`, newField) }) return schema}