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

typeorm / typeorm / 19549987525

20 Nov 2025 08:11PM UTC coverage: 80.769% (+4.3%) from 76.433%
19549987525

push

github

web-flow
ci: run tests on commits to master and next (#11783)

Co-authored-by: Oleg "OSA413" Sokolov <OSA413@users.noreply.github.com>

26500 of 32174 branches covered (82.36%)

Branch coverage included in aggregate %.

91252 of 113615 relevant lines covered (80.32%)

88980.79 hits per line

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

95.3
/src/query-builder/transformer/PlainObjectToDatabaseEntityTransformer.ts
1
import { ObjectLiteral } from "../../common/ObjectLiteral"
26✔
2
import { EntityMetadata } from "../../metadata/EntityMetadata"
26✔
3
import { EntityManager } from "../../entity-manager/EntityManager"
26✔
4
import { RelationMetadata } from "../../metadata/RelationMetadata"
26✔
5

26✔
6
/**
26✔
7
 */
26✔
8
class LoadMapItem {
26✔
9
    entity?: ObjectLiteral
26✔
10
    plainEntity: ObjectLiteral
26✔
11
    metadata: EntityMetadata
26✔
12
    parentLoadMapItem?: LoadMapItem
26✔
13
    relation?: RelationMetadata
26✔
14

26✔
15
    constructor(
26✔
16
        plainEntity: ObjectLiteral,
178✔
17
        metadata: EntityMetadata,
178✔
18
        parentLoadMapItem?: LoadMapItem,
178✔
19
        relation?: RelationMetadata,
178✔
20
    ) {
178✔
21
        this.plainEntity = plainEntity
178✔
22
        this.metadata = metadata
178✔
23
        this.parentLoadMapItem = parentLoadMapItem
178✔
24
        this.relation = relation
178✔
25
    }
178✔
26

26✔
27
    get target(): Function | string {
26✔
28
        return this.metadata.target
792✔
29
    }
792✔
30

26✔
31
    get id(): any {
26✔
32
        return this.metadata.getEntityIdMixedMap(this.plainEntity)
234✔
33
    }
234✔
34
}
26✔
35

26✔
36
class LoadMap {
90✔
37
    loadMapItems: LoadMapItem[] = []
90✔
38

90✔
39
    get mainLoadMapItem(): LoadMapItem | undefined {
90✔
40
        return this.loadMapItems.find(
180✔
41
            (item) => !item.relation && !item.parentLoadMapItem,
180✔
42
        )
180✔
43
    }
180✔
44

90✔
45
    addLoadMap(newLoadMap: LoadMapItem) {
90✔
46
        const item = this.loadMapItems.find(
178✔
47
            (item) =>
178✔
48
                item.target === newLoadMap.target && item.id === newLoadMap.id,
178✔
49
        )
178✔
50
        if (!item) this.loadMapItems.push(newLoadMap)
178✔
51
    }
178✔
52

90✔
53
    fillEntities(target: Function | string, entities: any[]) {
90✔
54
        entities.forEach((entity) => {
150✔
55
            const item = this.loadMapItems.find((loadMapItem) => {
178✔
56
                return (
294✔
57
                    loadMapItem.target === target &&
294✔
58
                    loadMapItem.metadata.compareEntities(
206✔
59
                        entity,
206✔
60
                        loadMapItem.plainEntity,
206✔
61
                    )
294✔
62
                )
294✔
63
            })
178✔
64
            if (item) item.entity = entity
178✔
65
        })
150✔
66
    }
150✔
67

90✔
68
    groupByTargetIds(): { target: Function | string; ids: any[] }[] {
90✔
69
        const groups: { target: Function | string; ids: any[] }[] = []
90✔
70
        this.loadMapItems.forEach((loadMapItem) => {
90✔
71
            let group = groups.find(
178✔
72
                (group) => group.target === loadMapItem.target,
178✔
73
            )
178✔
74
            if (!group) {
178✔
75
                group = { target: loadMapItem.target, ids: [] }
150✔
76
                groups.push(group)
150✔
77
            }
150✔
78

178✔
79
            group.ids.push(loadMapItem.id)
178✔
80
        })
90✔
81
        return groups
90✔
82
    }
90✔
83
}
90✔
84

26✔
85
/**
26✔
86
 * Transforms plain old javascript object
26✔
87
 * Entity is constructed based on its entity metadata.
26✔
88
 */
26✔
89
export class PlainObjectToDatabaseEntityTransformer {
26✔
90
    constructor(private manager: EntityManager) {}
26✔
91

26✔
92
    // -------------------------------------------------------------------------
26✔
93
    // Public Methods
26✔
94
    // -------------------------------------------------------------------------
26✔
95

26✔
96
    async transform(
26✔
97
        plainObject: ObjectLiteral,
90✔
98
        metadata: EntityMetadata,
90✔
99
    ): Promise<ObjectLiteral | undefined> {
90✔
100
        // if plain object does not have id then nothing to load really
90✔
101
        if (!metadata.hasAllPrimaryKeys(plainObject))
90✔
102
            return Promise.reject(
90!
103
                "Given object does not have a primary column, cannot transform it to database entity.",
×
104
            )
×
105

90✔
106
        // create a special load map that will hold all metadata that will be used to operate with entities easily
90✔
107
        const loadMap = new LoadMap()
90✔
108
        const fillLoadMap = (
90✔
109
            entity: ObjectLiteral,
178✔
110
            entityMetadata: EntityMetadata,
178✔
111
            parentLoadMapItem?: LoadMapItem,
178✔
112
            relation?: RelationMetadata,
178✔
113
        ) => {
178✔
114
            const item = new LoadMapItem(
178✔
115
                entity,
178✔
116
                entityMetadata,
178✔
117
                parentLoadMapItem,
178✔
118
                relation,
178✔
119
            )
178✔
120
            loadMap.addLoadMap(item)
178✔
121

178✔
122
            entityMetadata
178✔
123
                .extractRelationValuesFromEntity(entity, metadata.relations)
178✔
124
                .filter((value) => value !== null && value !== undefined)
178✔
125
                .forEach(([relation, value, inverseEntityMetadata]) =>
178✔
126
                    fillLoadMap(value, inverseEntityMetadata, item, relation),
178✔
127
                )
178✔
128
        }
178✔
129
        fillLoadMap(plainObject, metadata)
90✔
130
        // load all entities and store them in the load map
90✔
131
        await Promise.all(
90✔
132
            loadMap.groupByTargetIds().map((targetWithIds) => {
90✔
133
                // todo: fix type hinting
150✔
134
                return this.manager
150✔
135
                    .findByIds<ObjectLiteral>(
150✔
136
                        targetWithIds.target as any,
150✔
137
                        targetWithIds.ids,
150✔
138
                    )
150✔
139
                    .then((entities) =>
150✔
140
                        loadMap.fillEntities(targetWithIds.target, entities),
150✔
141
                    )
150✔
142
            }),
90✔
143
        )
90✔
144

90✔
145
        // go through each item in the load map and set their entity relationship using metadata stored in load map
90✔
146
        loadMap.loadMapItems.forEach((loadMapItem) => {
90✔
147
            if (
178✔
148
                !loadMapItem.relation ||
178!
149
                !loadMapItem.entity ||
178!
150
                !loadMapItem.parentLoadMapItem ||
178!
151
                !loadMapItem.parentLoadMapItem.entity
88✔
152
            )
178✔
153
                return
178✔
154

88!
155
            if (
88✔
156
                loadMapItem.relation.isManyToMany ||
88✔
157
                loadMapItem.relation.isOneToMany
4✔
158
            ) {
178!
159
                if (
84✔
160
                    !loadMapItem.parentLoadMapItem.entity[
84✔
161
                        loadMapItem.relation.propertyName
84✔
162
                    ]
84✔
163
                )
84✔
164
                    loadMapItem.parentLoadMapItem.entity[
84✔
165
                        loadMapItem.relation.propertyName
56✔
166
                    ] = []
56✔
167
                loadMapItem.parentLoadMapItem.entity[
84✔
168
                    loadMapItem.relation.propertyName
84✔
169
                ].push(loadMapItem.entity)
84✔
170
            } else {
176✔
171
                loadMapItem.parentLoadMapItem.entity[
4✔
172
                    loadMapItem.relation.propertyName
4✔
173
                ] = loadMapItem.entity
4✔
174
            }
4✔
175
        })
90✔
176

90✔
177
        return loadMap.mainLoadMapItem
90✔
178
            ? loadMap.mainLoadMapItem.entity
90✔
179
            : undefined
90!
180
    }
90✔
181
}
26✔
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

© 2026 Coveralls, Inc