All files / src/functions/query collect.query.fields.ts

100% Statements 35/35
100% Branches 19/19
100% Functions 8/8
100% Lines 27/27

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    8x   8x   46x   8x 16x 8x 8x   8x 5x 1x   7x 7x       8x 74x 25x 13x   61x   57x 60x 60x 48x 44x       8x 37x 37x 37x   8x  
'use strict';
 
import {each, isPlainObject, isString} from 'lodash';
 
const LOGICAL_OPERATORS: string[] = ['$and', '$or', '$nor'];
 
const _rootOf = (path: string): string => path.split('.')[0];
 
const _collectFieldReferences = (value: any, fields: Set<string>): void => {
	if (isString(value)) {
		if (value.startsWith('$') && !value.startsWith('$$') && value.length > 1) fields.add(_rootOf(value.substring(1)));
		return;
	}
	if (Array.isArray(value)) {
		each(value, (entry: any): void => _collectFieldReferences(entry, fields));
		return;
	}
	if (isPlainObject(value)) {
		each(Object.values(value), (entry: any): void => _collectFieldReferences(entry, fields));
	}
};
 
const _collect = (query: any, fields: Set<string>): void => {
	if (Array.isArray(query)) {
		each(query, (entry: any): void => _collect(entry, fields));
		return;
	}
	if (!isPlainObject(query)) return;
 
	each(Object.keys(query), (key: string): void => {
		const value: any = query[key];
		if (LOGICAL_OPERATORS.includes(key)) return _collect(value, fields);
		if (key.startsWith('$')) return _collectFieldReferences(value, fields);
		fields.add(_rootOf(key));
	});
};
 
const collectQueryFields = (query: any): string[] => {
	const fields: Set<string> = new Set<string>();
	_collect(query, fields);
	return [...fields];
};
export default collectQueryFields;