directus
1import { isPlainObject, isArray } from 'lodash-es';2
3/**
4* Calculates the depth of a given JSON structure, not counting any _ prefixed properties
5*
6* Used to calculate the field depth in a filter or deep query structure
7*
8* @example
9*
10* ```js
11* const deep = {
12* translations: {
13* _filter: {
14* _and: [
15* {
16* language_id: {
17* name: {
18* _eq: 'English'
19* }
20* }
21* },
22* {
23* status: {
24* _eq: 'Published'
25* }
26* }
27* ]
28* }
29* }
30* };
31*
32* const result = calculateFieldDepth(deep); // => 3
33* ```
34*/
35export function calculateFieldDepth(obj?: Record<string, any> | null, dotNotationKeys: string[] = []): number {36if (!obj) {37return 0;38}39
40let depth = 0;41
42const keys = Object.keys(obj);43
44for (const key of keys) {45const nestedValue = obj[key];46
47if (dotNotationKeys.includes(key) && nestedValue) {48let sortDepth = 0;49
50for (const sortKey of nestedValue) {51if (sortKey) {52sortDepth = Math.max(sortKey.split('.').length, sortDepth);53}54}55
56if (sortDepth > depth) {57depth = sortDepth;58}59} else {60if (!isPlainObject(nestedValue) && !isArray(nestedValue)) continue;61
62let nestedDepth = 0;63
64if (Array.isArray(nestedValue)) {65nestedDepth = Math.max(...nestedValue.map((val) => calculateFieldDepth(val, dotNotationKeys)));66} else {67nestedDepth = calculateFieldDepth(nestedValue, dotNotationKeys);68}69
70if (key.startsWith('_') === false) nestedDepth += 1;71
72if (nestedDepth > depth) {73depth = nestedDepth;74}75}76}77
78return depth;79}
80