<commit_before>import {resolve, join, dirname} from "path"

import camelCase from "camelcase"

import mongoose, {Schema, Model} from "mongoose"

import isEmpty from "lodash/isEmpty"
import isFunction from "lodash/isFunction"
import isPlainObject from "lodash/isPlainObject"

import invariant from "@octetstream/invariant"

import proxy from "core/helper/decorator/proxy"
import apply from "core/helper/proxy/selfInvokingClass"

import objectIterator from "core/helper/iterator/sync/objectIterator"

const Types = (() => {
  const res = {}

  for (const [name, type] of objectIterator.entries(Schema.Types)) {
    res[`T${name}`] = type
  }

  return res
})()

const isPrototypeOf = (parent, child) => (
  Object.prototype.isPrototypeOf.call(parent, child)
)

const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor

const getOwnPropertyNames = Object.getOwnPropertyNames

const DATABASE_ROOT = resolve(__dirname, "..", "..", "database")

/**
 * Get all static values and getters results from given Model
 *
 * @param {Function} Model
 *
 * @return {object}
 *
 * @api private
 */
function getStaticValues(Model) {
  const res = {}

  const names = getOwnPropertyNames(Model)

  for (const name of names) {
    if (/^(length|name|prototype)$/.test(name)) {
      continue
    }

    const descriptor = getOwnPropertyDescriptor(Model, name)

    if (isFunction(descriptor.get)) {
      res[name] = descriptor.get()
    } else if (!isFunction(descriptor.value)) {
      res[name] = descriptor.value
    }
  }

  return res
}

function getSchema(name, values) {
  const path = join(DATABASE_ROOT, "schema", camelCase(name))

  let module = null
  try {
    module = require(path)
  } catch (err) {
    invariant(err.code !== "MODULE_NOT_FOUND", err)

    invariant(
      true, "Can't find a schema for %s model. Expected module %s.js " +
      "at path %s", name, camelCase(name), dirname(path)
    )
  }

  const getModelFields = module.default

  invariant(
    !isFunction(getModelFields), TypeError,
    "Schema module should export a function as default." +
    "Check out the %s.js module exports.", path
  )

  const schemaFields = getModelFields(Types, values)

  invariant(
    !isPlainObject(schemaFields), TypeError,
    "Schema function should return a plain object." +
    "Check out the function %s in %s module.",
    getModelFields.name, path
  )

  const schema = new Schema({...schemaFields})

  return schema
}

function setMiddlewares(name, schema) {
  const path = join(DATABASE_ROOT, "middleware", camelCase(name))

  let middlewares = null
  try {
    middlewares = require(path)
  } catch (err) {
    invariant(err.code !== "MODULE_NOT_FOUND", err)
  }

  if (isEmpty(middlewares)) {
    return schema
  }

  invariant(
    !isPlainObject(middlewares), TypeError,
    "Middlewares module should export a plain object."
  )

  for (const {kind, type, parallel, handler} of objectIterator(middlewares)) {
    schema[kind](type, parallel, handler)
  }

  return schema
}

/**
 * Create a Mongoose model from given class.
 *
 * @param {Function} Target
 *
 * @param {Model} – mongoose model
 *
 * @api public
 */
function createModel(Target) {
  invariant(
    !isPrototypeOf(Model, Target), TypeError,<commit_msg>Fix for Mongoose middleware helper.<commit_after>import {resolve, join, dirname} from "path"

import camelCase from "camelcase"

import mongoose, {Schema, Model} from "mongoose"

import isEmpty from "lodash/isEmpty"
import isFunction from "lodash/isFunction"
import isPlainObject from "lodash/isPlainObject"

import invariant from "@octetstream/invariant"

import proxy from "core/helper/decorator/proxy"
import apply from "core/helper/proxy/selfInvokingClass"

import objectIterator from "core/helper/iterator/sync/objectIterator"

const Types = (() => {
  const res = {}

  for (const [name, type] of objectIterator.entries(Schema.Types)) {
    res[`T${name}`] = type
  }

  return res
})()

const isPrototypeOf = (parent, child) => (
  Object.prototype.isPrototypeOf.call(parent, child)
)

const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor

const getOwnPropertyNames = Object.getOwnPropertyNames

const DATABASE_ROOT = resolve(__dirname, "..", "..", "database")

/**
 * Get all static values and getters results from given Model
 *
 * @param {Function} Model
 *
 * @return {object}
 *
 * @api private
 */
function getStaticValues(Model) {
  const res = {}

  const names = getOwnPropertyNames(Model)

  for (const name of names) {
    if (/^(length|name|prototype)$/.test(name)) {
      continue
    }

    const descriptor = getOwnPropertyDescriptor(Model, name)

    if (isFunction(descriptor.get)) {
      res[name] = descriptor.get()
    } else if (!isFunction(descriptor.value)) {
      res[name] = descriptor.value
    }
  }

  return res
}

function getSchema(name, values) {
  const path = join(DATABASE_ROOT, "schema", camelCase(name))

  let module = null
  try {
    module = require(path)
  } catch (err) {
    invariant(err.code !== "MODULE_NOT_FOUND", err)

    invariant(
      true, "Can't find a schema for %s model. Expected module %s.js " +
      "at path %s", name, camelCase(name), dirname(path)
    )
  }

  const getModelFields = module.default

  invariant(
    !isFunction(getModelFields), TypeError,
    "Schema module should export a function as default." +
    "Check out the %s.js module exports.", path
  )

  const schemaFields = getModelFields(Types, values)

  invariant(
    !isPlainObject(schemaFields), TypeError,
    "Schema function should return a plain object." +
    "Check out the function %s in %s module.",
    getModelFields.name, path
  )

  const schema = new Schema({...schemaFields})

  return schema
}

function setMiddlewares(name, schema) {
  const path = join(DATABASE_ROOT, "middleware", camelCase(name))

  let middlewares = null
  try {
    middlewares = require(path)
  } catch (err) {
    invariant(err.code !== "MODULE_NOT_FOUND", err)
  }

  if (isEmpty(middlewares)) {
    return schema
  }

  invariant(
    !isPlainObject(middlewares), TypeError,
    "Middlewares module should export a plain object."
  )

  for (const {kind, type, parallel, handler} of objectIterator(middlewares)) {
    const args = [type]

    if (kind !== "post") {
      args.push(parallel)
    }

    schema[kind](...args, handler)
  }

  return schema
}

/**
 * Create a Mongoose model from given class.
 *
 * @param {Function} Target
 *
 * @param {Model} – mongoose model
 *
 * @api public
 */
function createModel(Target) {
  invariant(
    !isPrototypeOf(Model, Target), TypeError,
{'fraction_non_alphanumeric': 0.12158054711246201, 'fraction_numerical': 0.0, 'mean_word_length': 3.7619392185238785, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6253290', 'n_tokens_mistral': 2085, 'n_tokens_neox': 2036, 'n_words': 565}