All files / FeatureServer/lib/query filter-and-transform.js

93.87% Statements 46/49
94.28% Branches 33/35
100% Functions 10/10
93.87% Lines 46/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 1147x 7x 7x     64x 64x           64x   64x   64x 8x           56x 45x     11x               64x       64x       64x 10x 2x     10x 2x     10x 1x     10x     64x       64x 64x       64x 64x 64x 64x       64x 53x       11x 1x 10x 7x 3x 3x             11x 20x 3x     17x     11x         11x   11x 1687x       7x  
const _ = require('lodash')
const { query } = require('winnow')
const helpers = require('../helpers')
 
function filterAndTransform (json, requestParams) {
  const { features, type, ...restJson } = json
  const params = FilterAndTransformParams.create(requestParams)
    .removeParamsAlreadyApplied(json.filtersApplied)
    .addToEsri()
    .addInputCrs(json)
    .normalizeObjectIds()
 
  const result = query(json, params)
 
  const { objectIds, outStatistics } = params
 
  if (outStatistics) {
    return {
      statistics: result,
      ...restJson
    }
  }
 
  if (!objectIds) {
    return result
  }
 
  return {
    ...result,
    features: filterByObjectIds(result, objectIds)
  }
}
 
class FilterAndTransformParams {
  static create (requestParams) {
    return new FilterAndTransformParams(requestParams)
  }
 
  constructor (requestParams) {
    Object.assign(this, requestParams)
  }
 
  removeParamsAlreadyApplied (alreadyApplied) {
    for (const key in alreadyApplied) {
      if (key === 'projection') {
        delete this.outSR
      }
 
      if (key === 'offset') {
        delete this.resultOffset
      }
 
      if (key === 'limit') {
        delete this.resultRecordCount
      }
 
      delete this[key]
    }
 
    return this
  }
 
  addToEsri () {
    this.toEsri = this.f !== 'geojson' && !this.returnExtentOnly
    return this
  }
 
  addInputCrs (data = {}) {
    const { metadata = {} } = data
    this.inputCrs = this.inputCrs || this.sourceSR || metadata.crs || helpers.getCollectionCrs(data) || 4326
    delete this.sourceSR
    return this
  }
 
  normalizeObjectIds () {
    if (!this.objectIds) {
      return this
    }
 
    let ids
    if (Array.isArray(this.objectIds)) {
      ids = this.objectIds
    } else if (typeof this.objectIds === 'string') {
      ids = this.objectIds.split(',')
    } else Eif (typeof this.objectIds === 'number') {
      ids = [this.objectIds]
    } else {
      const error = new Error('Invalid "objectIds" parameter.')
      error.code = 400
      throw error
    }
 
    this.objectIds = ids.map(i => {
      if (isNaN(i)) {
        return i
      }
 
      return parseInt(i)
    })
 
    return this
  }
}
 
function filterByObjectIds (data, objectIds) {
  const idField = _.get(data, 'metadata.idField') || 'OBJECTID'
 
  return data.features.filter(({ attributes = {}, properties = {} }) => {
    return objectIds.includes(attributes[idField]) || objectIds.includes(properties[idField])
  })
}
 
module.exports = { filterAndTransform }