index.js

import anekaSpatial from 'aneka-spatial/index.js'

/**
 * Plugin factory
 *
 * @param {string} pkgName - NPM package name
 * @returns {class}
 */
async function factory (pkgName) {
  const me = this

  /**
   * BajoSpatial class
   *
   * @class
   */
  class BajoSpatial extends this.app.pluginClass.base {
    static alias = 'spatial'

    constructor () {
      super(pkgName, me.app)
      this.config = {}
      this.app.lib.anekaSpatial = anekaSpatial
    }

    buildBboxQuery = async ({ bbox, query, schema, options = {} } = {}) => {
      const { merge, isEmpty } = this.app.lib._
      const props = schema.properties.map(item => item.name)
      const { bboxLatField = 'lat', bboxLngField = 'lng' } = options
      if (props.includes(bboxLatField) && props.includes(bboxLngField)) {
        const [minx, miny, maxx, maxy] = await this.parseBbox(bbox)
        const q = {}
        q[bboxLngField] = { $gte: minx, $lte: maxx }
        q[bboxLatField] = { $gte: miny, $lte: maxy }
        if (isEmpty(query)) query = q
        else {
          const $or = query.$or
          if ($or) query = merge(q, { $or })
          else merge(query, q)
        }
      }
      return query
    }

    getCountryBbox = async (item) => {
      item = item + ''
      if (item.includes(',')) return
      if (!this.app.bajoCommonDb || !this.app.dobo) return
      const { recordGet } = this.app.dobo
      const country = await recordGet('CdbCountry', item, { thrownNotFound: false })
      if (country) return country.bbox
      throw this.error('Invalid country bbox \'%s\'', item, { statusCode: 400 })
    }

    parseBbox = async (input) => {
      const { isSet } = this.app.lib.aneka
      if (input.length === 2 && !input.includes(',')) return await this.getCountryBbox(input)
      const [minx, miny, maxx, maxy] = input.split(',').map(b => parseFloat(b) || null)
      const valid = (isSet(minx) && isSet(miny) && isSet(maxx) && isSet(maxy)) &&
        (minx >= -180 && maxx <= 180 && miny >= -90 && maxy <= 90)
        // (minx <= maxx && miny <= maxy)
      if (valid) return [minx, miny, maxx, maxy]
      throw this.error('Invalid bbox \'%s\'', input)
    }
  }

  return BajoSpatial
}

export default factory