/
getRootCodenamesOfItem.ts
81 lines (66 loc) · 2.56 KB
/
getRootCodenamesOfItem.ts
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
import { ContentItem, Elements } from 'kentico-cloud-delivery';
import { IWebhookContentItem } from '../contracts/kontent';
interface IContext {
readonly visitedItems: string[],
readonly rootItemCodenames: string[],
readonly newItemsToVisit: ContentItem[],
readonly allItems: ContentItem[],
}
export const getRootCodenamesOfItem = (
item: IWebhookContentItem,
allItems: ContentItem[],
rootItemTypes: string[],
): string[] =>
rootItemTypes.includes(item.type)
? [item.codename]
: getRootParents(item.codename, allItems, rootItemTypes);
const getRootParents = (codename: string, allItems: ContentItem[], rootItemTypes: string[]): string[] => {
let itemsToVisit: ContentItem[] = getDirectParents(codename, allItems);
const visitedItems: string[] = [];
const rootItemCodenames: string[] = [];
while (itemsToVisit.length > 0) {
const newItemsToVisit: ContentItem[] = [];
itemsToVisit.forEach((item) => processItem(
item,
rootItemTypes,
{
allItems,
newItemsToVisit,
rootItemCodenames,
visitedItems,
}));
itemsToVisit = newItemsToVisit;
}
return rootItemCodenames;
};
const processItem = (itemToProcess: ContentItem, rootItemTypes: string[], context: IContext): void => {
const itemCodename: string = itemToProcess.system.codename;
if (context.visitedItems.includes(itemCodename)) {
return;
}
context.visitedItems.push(itemCodename);
if (rootItemTypes.includes(itemToProcess.system.type)) {
context.rootItemCodenames.push(itemCodename);
} else {
const parents = getDirectParents(itemCodename, context.allItems);
parents.forEach((item) => context.newItemsToVisit.push(item));
}
};
const getDirectParents = (codename: string, allItems: ContentItem[]): ContentItem[] =>
allItems.filter((item) => isInAnyElement(item, codename));
const isInAnyElement = (
parentItem: ContentItem,
codename: string): boolean =>
Object
.keys(parentItem)
.map((key) => {
const element = parentItem[key];
if (element instanceof Elements.RichTextElement) {
return element.linkedItemCodenames.includes(codename);
}
if (element instanceof Elements.LinkedItemsElement) {
return element.itemCodenames.includes(codename);
}
return false;
})
.reduce((accumulator, current) => current === true ? true : accumulator, false);