|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- 'use strict';
-
- const castFilterPath = require('../query/castFilterPath');
- const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
- const getPath = require('../schema/getPath');
- const modifiedPaths = require('./modifiedPaths');
-
- 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 updatedPaths = modifiedPaths(update);
-
- const updatedPathsByFilter = Object.keys(updatedPaths).reduce((cur, path) => {
- const matches = path.match(/\$\[[^\]]+\]/g);
- if (matches == null) {
- return cur;
- }
- for (const match of matches) {
- const firstMatch = path.indexOf(match);
- if (firstMatch !== path.lastIndexOf(match)) {
- throw new Error(`Path '${path}' contains the same array filter multiple times`);
- }
- cur[match.substring(2, match.length - 1)] = path.
- substr(0, firstMatch - 1).
- replace(/\$\[[^\]]+\]/g, '0');
- }
- return cur;
- }, {});
-
- for (const filter of arrayFilters) {
- if (filter == null) {
- throw new Error(`Got null array filter in ${arrayFilters}`);
- }
- const firstKey = Object.keys(filter)[0];
-
- if (filter[firstKey] == null) {
- continue;
- }
-
- const dot = firstKey.indexOf('.');
- let filterPath = dot === -1 ?
- updatedPathsByFilter[firstKey] + '.0' :
- updatedPathsByFilter[firstKey.substr(0, dot)] + '.0' + firstKey.substr(dot);
-
- if (filterPath == null) {
- throw new Error(`Filter path not found for ${firstKey}`);
- }
-
- // 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[firstKey] === 'object') {
- filter[firstKey] = castFilterPath(query, schematype, filter[firstKey]);
- } else {
- filter[firstKey] = schematype.castForQuery(filter[firstKey]);
- }
- }
- };
|