• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

satanTime / ngrx-entity-relationship / 475a6fe6-862e-42f9-b95e-23a40dfab79b

26 Jan 2024 01:24AM CUT coverage: 100.0%. Remained the same
475a6fe6-862e-42f9-b95e-23a40dfab79b

Pull #2048

circleci

web-flow
chore(deps): update dependency husky to v9
Pull Request #2048: chore(deps): update dependency husky to v9

443 of 443 branches covered (100.0%)

Branch coverage included in aggregate %.

680 of 680 relevant lines covered (100.0%)

33.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/libs/ngrx-entity-relationship/src/lib/childrenEntities.ts
1
import {
2
    CACHE,
3
    CACHE_CHECKS_SET,
4
    FEATURE_SELECTOR,
5
    HANDLER_RELATED_ENTITY,
6
    ID_FILTER_PROPS,
7
    ID_SELECTOR,
8
    ID_TYPES,
9
    isSelectorMeta,
10
    UNKNOWN,
11
    VALUES_FILTER_PROPS,
12
} from './types';
13
import {argsToArray, mergeCache, normalizeSelector, objectValues, verifyCache} from './utils';
14

15
export function childrenEntities<
16
    STORE,
17
    PARENT_ENTITY,
18
    RELATED_ENTITY,
19
    RELATED_KEY_IDS extends ID_FILTER_PROPS<RELATED_ENTITY, ID_TYPES> = ID_FILTER_PROPS<RELATED_ENTITY, ID_TYPES>,
20
    RELATED_KEY_VALUES_ARRAYS extends VALUES_FILTER_PROPS<PARENT_ENTITY, Array<RELATED_ENTITY>> = VALUES_FILTER_PROPS<
21
        PARENT_ENTITY,
22
        Array<RELATED_ENTITY>
23
    >,
24
>(
25
    featureSelector: FEATURE_SELECTOR<STORE, RELATED_ENTITY>,
26
    keyId: RELATED_KEY_IDS,
27
    keyValue: RELATED_KEY_VALUES_ARRAYS,
28
    metaOrRelationship?: SELECTOR_META | HANDLER_RELATED_ENTITY<STORE, RELATED_ENTITY>,
29
    ...relationships: Array<HANDLER_RELATED_ENTITY<STORE, RELATED_ENTITY>>
30
): HANDLER_RELATED_ENTITY<STORE, PARENT_ENTITY>;
31

32
export function childrenEntities<
33
    STORE,
34
    PARENT_ENTITY,
35
    RELATED_ENTITY,
36
    RELATED_KEY_IDS extends ID_FILTER_PROPS<RELATED_ENTITY, ID_TYPES>,
37
    RELATED_KEY_VALUES_ARRAYS extends VALUES_FILTER_PROPS<PARENT_ENTITY, Array<RELATED_ENTITY>>,
38
>(
39
    featureSelector: FEATURE_SELECTOR<STORE, RELATED_ENTITY>,
40
    keyId: RELATED_KEY_IDS,
41
    keyValue: RELATED_KEY_VALUES_ARRAYS,
42
): HANDLER_RELATED_ENTITY<STORE, PARENT_ENTITY> {
43
    let relationships: Array<HANDLER_RELATED_ENTITY<STORE, RELATED_ENTITY>> = argsToArray(arguments);
81✔
44
    relationships = relationships.slice(3);
81✔
45

46
    let meta: SELECTOR_META = {};
81✔
47
    if (isSelectorMeta(relationships[0])) {
81✔
48
        meta = relationships[0];
44✔
49
        relationships = relationships.slice(1);
44✔
50
    }
51

52
    const {collection: collectionSelector, id: idSelector} = normalizeSelector(featureSelector);
81✔
53
    const emptyResult: Map<UNKNOWN, UNKNOWN> = new Map();
81✔
54

55
    const callback = (
81✔
56
        cacheLevel: string,
57
        state: STORE,
58
        cache: CACHE<STORE>,
59
        source: PARENT_ENTITY,
60
        idParentSelector: ID_SELECTOR<PARENT_ENTITY>,
61
    ) => {
62
        const featureState = collectionSelector(state);
18✔
63
        const parentId = idParentSelector(source);
18✔
64

65
        let cacheDataLevel = cache.get(cacheLevel);
18✔
66
        if (!cacheDataLevel) {
18✔
67
            cacheDataLevel = new Map();
14✔
68
            cache.set(cacheLevel, cacheDataLevel);
14✔
69
        }
70

71
        // maybe we don't need to scan the entities.
72
        let [idsChecks, ids]: [CACHE_CHECKS_SET<STORE>, Array<ID_TYPES>] = cacheDataLevel.get(`!${parentId}`) || [
18✔
73
            new Map(),
74
            [],
75
        ];
76
        if (!verifyCache(state, idsChecks)) {
18✔
77
            ids = [];
16✔
78
            for (const entity of objectValues(featureState.entities)) {
16✔
79
                if (
24✔
80
                    !entity ||
48✔
81
                    entity[keyId] !== (parentId as any as RELATED_ENTITY[RELATED_KEY_IDS]) // todo fix any A8
82
                ) {
83
                    continue;
6✔
84
                }
85
                const id = idSelector(entity);
18✔
86
                // istanbul ignore else
87
                if (id) {
18✔
88
                    ids.push(id);
18✔
89
                }
90
            }
91
            idsChecks = new Map();
16✔
92
            const idsChecksEntities = new Map();
16✔
93
            idsChecks.set(collectionSelector, idsChecksEntities);
16✔
94
            idsChecksEntities.set(null, featureState.entities);
16✔
95
            cacheDataLevel.set(`!${parentId}`, [idsChecks, ids]);
16✔
96
        }
97
        if (!ids.length) {
18✔
98
            source[keyValue] = emptyResult.get(parentId);
2✔
99
            // istanbul ignore else
100
            if (!source[keyValue]) {
2✔
101
                source[keyValue] = [] as PARENT_ENTITY[RELATED_KEY_VALUES_ARRAYS];
2✔
102
                emptyResult.set(parentId, source[keyValue]);
2✔
103
            }
104
            return `!${parentId}`;
2✔
105
        }
106

107
        const cacheHash = `#${ids.join(',')}`;
16✔
108
        let [checks, value]: [CACHE_CHECKS_SET<STORE>, UNKNOWN] = cacheDataLevel.get(cacheHash) || [
16✔
109
            new Map(),
110
            undefined,
111
        ];
112
        if (verifyCache(state, checks)) {
16✔
113
            source[keyValue] = value;
2✔
114
            return cacheHash;
2✔
115
        }
116

117
        // building a new value.
118
        value = [];
14✔
119
        checks = new Map();
14✔
120
        const checksEntities = new Map();
14✔
121
        checks.set(collectionSelector, checksEntities);
14✔
122
        checksEntities.set(null, featureState.entities);
14✔
123
        for (const id of ids) {
14✔
124
            checksEntities.set(id, featureState.entities[id]);
18✔
125
        }
126

127
        for (const id of ids) {
14✔
128
            let [entityChecks, entityValue]: [CACHE_CHECKS_SET<STORE>, UNKNOWN] = cacheDataLevel.get(
18✔
129
                `${cacheHash}:${id}`,
130
            ) || [new Map(), undefined];
131
            if (verifyCache(state, entityChecks)) {
18✔
132
                // istanbul ignore else
133
                if (entityValue) {
2✔
134
                    value.push(entityValue);
2✔
135
                }
136
                continue;
2✔
137
            }
138
            // we have to clone it because we are going to update it with relationships.
139
            entityValue = {...featureState.entities[id]} as RELATED_ENTITY;
16✔
140
            entityChecks = new Map();
16✔
141
            const entityChecksEntities = new Map();
16✔
142
            entityChecks.set(collectionSelector, entityChecksEntities);
16✔
143
            entityChecksEntities.set(null, featureState.entities);
16✔
144
            entityChecksEntities.set(id, featureState.entities[id]);
16✔
145

146
            let cacheRelLevelIndex = 0;
16✔
147
            for (const relationship of relationships) {
16✔
148
                const cacheRelLevel = `${cacheLevel}:${cacheRelLevelIndex}`;
6✔
149
                const cacheRelHash = relationship(cacheRelLevel, state, cache, entityValue, idSelector);
6✔
150
                cacheRelLevelIndex += 1;
6✔
151
                if (cacheRelHash) {
6✔
152
                    mergeCache(cache.get(cacheRelLevel)?.get(cacheRelHash)?.[0], checks);
4✔
153
                    mergeCache(cache.get(cacheRelLevel)?.get(cacheRelHash)?.[0], entityChecks);
4✔
154
                }
155
            }
156
            cacheDataLevel.set(`${cacheHash}:${id}`, [entityChecks, entityValue]);
16✔
157
            value.push(entityValue);
16✔
158
        }
159
        cacheDataLevel.set(cacheHash, [checks, value]);
14✔
160
        source[keyValue] = value as PARENT_ENTITY[RELATED_KEY_VALUES_ARRAYS];
14✔
161
        return cacheHash;
14✔
162
    };
163
    callback.ngrxEntityRelationship = 'childrenEntities';
81✔
164
    callback.collectionSelector = collectionSelector;
81✔
165
    callback.meta = meta;
81✔
166
    callback.idSelector = idSelector;
81✔
167
    callback.relationships = relationships;
81✔
168
    callback.keyId = keyId;
81✔
169
    callback.keyValue = keyValue;
81✔
170
    callback.release = () => {
81✔
171
        emptyResult.clear();
1✔
172
        for (const relationship of relationships) {
1✔
173
            relationship.release();
2✔
174
        }
175
    };
176

177
    return callback;
81✔
178
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc