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

typeorm / typeorm / 14796576772

02 May 2025 01:52PM UTC coverage: 45.367% (-30.9%) from 76.309%
14796576772

Pull #11434

github

web-flow
Merge ec4ce2d00 into fadad1a74
Pull Request #11434: feat: release PR releases using pkg.pr.new

5216 of 12761 branches covered (40.87%)

Branch coverage included in aggregate %.

11439 of 23951 relevant lines covered (47.76%)

15712.55 hits per line

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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