lib_collect-schemas.js

import path from 'path'
import sanitizeSchema from './sanitize-schema.js'

async function handler ({ file }) {
  const { ns, alias } = this
  const { readConfig, eachPlugins } = this.app.bajo
  const { pascalCase } = this.app.lib.aneka
  const { get, isPlainObject, each, find, has, isArray, forOwn, isString, merge } = this.app.lib._
  const { fastGlob } = this.app.lib

  const base = path.basename(file, path.extname(file))
  const defName = pascalCase(`${alias} ${base}`)
  const mod = await readConfig(file, { ns, ignoreError: true })
  if (!isPlainObject(mod)) this.fatal('invalidSchema%s', defName)
  const forcedConn = get(this, `app.${ns}.config.dobo.schemaConnection.${base}`)
  if (forcedConn) mod.connection = forcedConn
  if (!mod.connection) mod.connection = 'default'
  mod.name = mod.name ?? defName
  mod.file = file
  mod.ns = ns
  mod.attachment = mod.attachment ?? true
  mod.feature = mod.feature ?? []
  mod.buildLevel = mod.buildLevel ?? 999
  const feats = []
  if (isArray(mod.feature)) {
    each(mod.feature, f => {
      if (isString(f)) feats.push({ name: f })
      else if (isPlainObject(f)) feats.push(f)
    })
  } else if (isPlainObject(mod.feature)) {
    forOwn(mod.feature, (v, k) => {
      feats.push(merge({}, v, { name: k }))
    })
  }
  mod.feature = feats
  mod.properties = mod.properties ?? []
  // if ((mod.properties ?? []).length === 0) this.fatal('noPropsFoundOnSchema%s', mod.name)
  // schema extender
  await eachPlugins(async function ({ dir }) {
    const { ns } = this
    const glob = `${dir}/extend/dobo/extend/${mod.ns}/schema/${base}.*`
    const files = await fastGlob(glob)
    for (const file of files) {
      const extender = await readConfig(file, { ns, ignoreError: true })
      if (!isPlainObject(extender)) return undefined
      each(extender.properties ?? [], p => {
        if (isString(p) && mod.properties.includes(p)) return undefined
        else if (find(mod.properties, { name: p.name })) return undefined
        mod.properties.push(p)
      })
      const feats = []
      if (isArray(extender.feature)) {
        each(extender.feature, f => {
          if (isString(f)) feats.push({ name: f })
          else if (isPlainObject(f)) feats.push(f)
        })
      } else if (isPlainObject(extender.feature)) {
        forOwn(extender.feature, (v, k) => {
          feats.push(merge({}, v, { name: k }))
        })
      }
      if (feats.length > 0) mod.feature.push(...feats)
      if (ns === this.app.mainNs) {
        each(['connection', 'name'], i => {
          if (has(extender, i)) mod[i] = extender[i]
        })
      }
      mod.extender = mod.extender ?? []
      mod.extender.push(ns)
    }
  })
  return mod
}

/**
 * Collect all database schemas from loaded plugins
 *
 * @name collectSchemas
 * @memberof module:Lib
 * @async
 * @see Dobo#init
 */
async function collectSchemas () {
  const { eachPlugins } = this.app.bajo
  const { isEmpty } = this.app.lib._
  const result = await eachPlugins(handler, { glob: 'schema/*.*', prefix: this.ns })
  if (isEmpty(result)) this.log.warn('notFound%s', this.t('schema'))
  else await sanitizeSchema.call(this, result)
}

export default collectSchemas