'use strict'; const castFilterPath = require('../query/castFilterPath'); const cleanPositionalOperators = require('../schema/cleanPositionalOperators'); const getPath = require('../schema/getPath'); const updatedPathsByArrayFilter = require('./updatedPathsByArrayFilter'); module.exports = function castArrayFilters(query) { const arrayFilters = query.options.arrayFilters; if (!Array.isArray(arrayFilters)) { return; } const update = query.getUpdate(); const schema = query.schema; const strictQuery = schema.options.strictQuery; const updatedPathsByFilter = updatedPathsByArrayFilter(update); for (const filter of arrayFilters) { if (filter == null) { throw new Error(`Got null array filter in ${arrayFilters}`); } for (const key of Object.keys(filter)) { if (filter[key] == null) { continue; } const dot = key.indexOf('.'); let filterPath = dot === -1 ? updatedPathsByFilter[key] + '.0' : updatedPathsByFilter[key.substr(0, dot)] + '.0' + key.substr(dot); if (filterPath == null) { throw new Error(`Filter path not found for ${key}`); } // If there are multiple array filters in the path being updated, make sure // to replace them so we can get the schema path. filterPath = cleanPositionalOperators(filterPath); const schematype = getPath(schema, filterPath); if (schematype == null) { if (!strictQuery) { return; } // For now, treat `strictQuery = true` and `strictQuery = 'throw'` as // equivalent for casting array filters. `strictQuery = true` doesn't // quite work in this context because we never want to silently strip out // array filters, even if the path isn't in the schema. throw new Error(`Could not find path "${filterPath}" in schema`); } if (typeof filter[key] === 'object') { filter[key] = castFilterPath(query, schematype, filter[key]); } else { filter[key] = schematype.castForQuery(filter[key]); } } } };