• 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

93.0
/src/metadata/EmbeddedMetadata.ts
1
import { ColumnMetadata } from "./ColumnMetadata"
2
import { RelationMetadata } from "./RelationMetadata"
3
import { EntityMetadata } from "./EntityMetadata"
4
import { EmbeddedMetadataArgs } from "../metadata-args/EmbeddedMetadataArgs"
5
import { RelationIdMetadata } from "./RelationIdMetadata"
6
import { RelationCountMetadata } from "./RelationCountMetadata"
7
import { DataSource } from "../data-source/DataSource"
8
import { EntityListenerMetadata } from "./EntityListenerMetadata"
9
import { IndexMetadata } from "./IndexMetadata"
10
import { UniqueMetadata } from "./UniqueMetadata"
11
import { TypeORMError } from "../error"
4✔
12

13
/**
14
 * Contains all information about entity's embedded property.
15
 */
16
export class EmbeddedMetadata {
4✔
17
    // ---------------------------------------------------------------------
18
    // Public Properties
19
    // ---------------------------------------------------------------------
20

21
    /**
22
     * Entity metadata where this embedded is.
23
     */
24
    entityMetadata: EntityMetadata
25

26
    /**
27
     * Parent embedded in the case if this embedded inside other embedded.
28
     */
29
    parentEmbeddedMetadata?: EmbeddedMetadata
30

31
    /**
32
     * Embedded target type.
33
     */
34
    type: Function | string
35

36
    /**
37
     * Property name on which this embedded is attached.
38
     */
39
    propertyName: string
40

41
    /**
42
     * Gets full path to this embedded property (including embedded property name).
43
     * Full path is relevant when embedded is used inside other embeds (one or multiple nested).
44
     * For example it will return "counters.subcounters".
45
     */
46
    propertyPath: string
47

48
    /**
49
     * Columns inside this embed.
50
     */
51
    columns: ColumnMetadata[] = []
438✔
52

53
    /**
54
     * Relations inside this embed.
55
     */
56
    relations: RelationMetadata[] = []
438✔
57

58
    /**
59
     * Entity listeners inside this embed.
60
     */
61
    listeners: EntityListenerMetadata[] = []
438✔
62

63
    /**
64
     * Indices applied to the embed columns.
65
     */
66
    indices: IndexMetadata[] = []
438✔
67

68
    /**
69
     * Uniques applied to the embed columns.
70
     */
71
    uniques: UniqueMetadata[] = []
438✔
72

73
    /**
74
     * Relation ids inside this embed.
75
     */
76
    relationIds: RelationIdMetadata[] = []
438✔
77

78
    /**
79
     * Relation counts inside this embed.
80
     */
81
    relationCounts: RelationCountMetadata[] = []
438✔
82

83
    /**
84
     * Nested embeddable in this embeddable (which has current embedded as parent embedded).
85
     */
86
    embeddeds: EmbeddedMetadata[] = []
438✔
87

88
    /**
89
     * Indicates if the entity should be instantiated using the constructor
90
     * or via allocating a new object via `Object.create()`.
91
     */
92
    isAlwaysUsingConstructor: boolean = true
438✔
93

94
    /**
95
     * Indicates if this embedded is in array mode.
96
     *
97
     * This option works only in mongodb.
98
     */
99
    isArray: boolean = false
438✔
100

101
    /**
102
     * Prefix of the embedded, used instead of propertyName.
103
     * If set to empty string or false, then prefix is not set at all.
104
     */
105
    customPrefix: string | boolean | undefined
106

107
    /**
108
     * Gets the prefix of the columns.
109
     * By default its a property name of the class where this prefix is.
110
     * But if custom prefix is set then it takes its value as a prefix.
111
     * However if custom prefix is set to empty string or false, then prefix to column is not applied at all.
112
     */
113
    prefix: string
114

115
    /**
116
     * Returns array of property names of current embed and all its parent embeds.
117
     *
118
     * example: post[data][information][counters].id where "data", "information" and "counters" are embeds
119
     * we need to get value of "id" column from the post real entity object.
120
     * this method will return ["data", "information", "counters"]
121
     */
122
    parentPropertyNames: string[] = []
438✔
123

124
    /**
125
     * Returns array of prefixes of current embed and all its parent embeds.
126
     */
127
    parentPrefixes: string[] = []
438✔
128

129
    /**
130
     * Returns embed metadatas from all levels of the parent tree.
131
     *
132
     * example: post[data][information][counters].id where "data", "information" and "counters" are embeds
133
     * this method will return [embed metadata of data, embed metadata of information, embed metadata of counters]
134
     */
135
    embeddedMetadataTree: EmbeddedMetadata[] = []
438✔
136

137
    /**
138
     * Embed metadatas from all levels of the parent tree.
139
     *
140
     * example: post[data][information][counters].id where "data", "information" and "counters" are embeds
141
     * this method will return [embed metadata of data, embed metadata of information, embed metadata of counters]
142
     */
143
    columnsFromTree: ColumnMetadata[] = []
438✔
144

145
    /**
146
     * Relations of this embed and all relations from its child embeds.
147
     */
148
    relationsFromTree: RelationMetadata[] = []
438✔
149

150
    /**
151
     * Relations of this embed and all relations from its child embeds.
152
     */
153
    listenersFromTree: EntityListenerMetadata[] = []
438✔
154

155
    /**
156
     * Indices of this embed and all indices from its child embeds.
157
     */
158
    indicesFromTree: IndexMetadata[] = []
438✔
159

160
    /**
161
     * Uniques of this embed and all uniques from its child embeds.
162
     */
163
    uniquesFromTree: UniqueMetadata[] = []
438✔
164

165
    /**
166
     * Relation ids of this embed and all relation ids from its child embeds.
167
     */
168
    relationIdsFromTree: RelationIdMetadata[] = []
438✔
169

170
    /**
171
     * Relation counts of this embed and all relation counts from its child embeds.
172
     */
173
    relationCountsFromTree: RelationCountMetadata[] = []
438✔
174

175
    // ---------------------------------------------------------------------
176
    // Constructor
177
    // ---------------------------------------------------------------------
178

179
    constructor(options: {
180
        entityMetadata: EntityMetadata
181
        args: EmbeddedMetadataArgs
182
    }) {
183
        this.entityMetadata = options.entityMetadata
438✔
184
        this.type = options.args.type()
438✔
185
        this.propertyName = options.args.propertyName
438✔
186
        this.customPrefix = options.args.prefix
438✔
187
        this.isArray = options.args.isArray
438✔
188
    }
189

190
    // ---------------------------------------------------------------------
191
    // Public Methods
192
    // ---------------------------------------------------------------------
193

194
    /**
195
     * Creates a new embedded object.
196
     */
197
    create(options?: { fromDeserializer?: boolean }): any {
198
        if (!(typeof this.type === "function")) {
2,592✔
199
            return {}
8✔
200
        }
201

202
        if (options?.fromDeserializer || !this.isAlwaysUsingConstructor) {
2,584!
203
            return Object.create(this.type.prototype)
×
204
        } else {
205
            return new (this.type as any)()
2,584✔
206
        }
207
    }
208

209
    // ---------------------------------------------------------------------
210
    // Builder Methods
211
    // ---------------------------------------------------------------------
212

213
    build(connection: DataSource): this {
214
        this.embeddeds.forEach((embedded) => embedded.build(connection))
716✔
215
        this.prefix = this.buildPrefix(connection)
716✔
216
        this.parentPropertyNames = this.buildParentPropertyNames()
716✔
217
        this.parentPrefixes = this.buildParentPrefixes()
716✔
218
        this.propertyPath = this.parentPropertyNames.join(".")
716✔
219
        this.embeddedMetadataTree = this.buildEmbeddedMetadataTree()
716✔
220
        this.columnsFromTree = this.buildColumnsFromTree()
716✔
221
        this.relationsFromTree = this.buildRelationsFromTree()
716✔
222
        this.listenersFromTree = this.buildListenersFromTree()
716✔
223
        this.indicesFromTree = this.buildIndicesFromTree()
716✔
224
        this.uniquesFromTree = this.buildUniquesFromTree()
716✔
225
        this.relationIdsFromTree = this.buildRelationIdsFromTree()
716✔
226
        this.relationCountsFromTree = this.buildRelationCountsFromTree()
716✔
227

228
        if (connection.options.entitySkipConstructor) {
716!
229
            this.isAlwaysUsingConstructor =
×
230
                !connection.options.entitySkipConstructor
231
        }
232

233
        return this
716✔
234
    }
235

236
    // ---------------------------------------------------------------------
237
    // Protected Methods
238
    // ---------------------------------------------------------------------
239

240
    protected buildPartialPrefix(): string[] {
241
        // if prefix option was not set or explicitly set to true - default prefix
242
        if (this.customPrefix === undefined || this.customPrefix === true) {
1,964✔
243
            return [this.propertyName]
1,196✔
244
        }
245

246
        // if prefix option was set to empty string or explicity set to false - disable prefix
247
        if (this.customPrefix === "" || this.customPrefix === false) {
768✔
248
            return []
120✔
249
        }
250

251
        // use custom prefix
252
        if (typeof this.customPrefix === "string") {
648✔
253
            return [this.customPrefix]
648✔
254
        }
255

256
        throw new TypeORMError(
×
257
            `Invalid prefix option given for ${this.entityMetadata.targetName}#${this.propertyName}`,
258
        )
259
    }
260

261
    protected buildPrefix(connection: DataSource): string {
262
        if (connection.driver.options.type === "mongodb")
982!
263
            return this.propertyName
×
264

265
        const prefixes: string[] = []
982✔
266
        if (this.parentEmbeddedMetadata)
982✔
267
            prefixes.push(this.parentEmbeddedMetadata.buildPrefix(connection))
266✔
268

269
        prefixes.push(...this.buildPartialPrefix())
982✔
270

271
        return prefixes.join("_") // todo: use naming strategy instead of "_"  !!!
982✔
272
    }
273

274
    protected buildParentPropertyNames(): string[] {
275
        return this.parentEmbeddedMetadata
982✔
276
            ? this.parentEmbeddedMetadata
277
                  .buildParentPropertyNames()
278
                  .concat(this.propertyName)
279
            : [this.propertyName]
280
    }
281

282
    protected buildParentPrefixes(): string[] {
283
        return this.parentEmbeddedMetadata
982✔
284
            ? this.parentEmbeddedMetadata
285
                  .buildParentPrefixes()
286
                  .concat(this.buildPartialPrefix())
287
            : this.buildPartialPrefix()
288
    }
289

290
    protected buildEmbeddedMetadataTree(): EmbeddedMetadata[] {
291
        return this.parentEmbeddedMetadata
982✔
292
            ? this.parentEmbeddedMetadata
293
                  .buildEmbeddedMetadataTree()
294
                  .concat(this)
295
            : [this]
296
    }
297

298
    protected buildColumnsFromTree(): ColumnMetadata[] {
299
        return this.embeddeds.reduce(
982✔
300
            (columns, embedded) =>
301
                columns.concat(embedded.buildColumnsFromTree()),
266✔
302
            this.columns,
303
        )
304
    }
305

306
    protected buildRelationsFromTree(): RelationMetadata[] {
307
        return this.embeddeds.reduce(
982✔
308
            (relations, embedded) =>
309
                relations.concat(embedded.buildRelationsFromTree()),
266✔
310
            this.relations,
311
        )
312
    }
313

314
    protected buildListenersFromTree(): EntityListenerMetadata[] {
315
        return this.embeddeds.reduce(
982✔
316
            (relations, embedded) =>
317
                relations.concat(embedded.buildListenersFromTree()),
266✔
318
            this.listeners,
319
        )
320
    }
321

322
    protected buildIndicesFromTree(): IndexMetadata[] {
323
        return this.embeddeds.reduce(
982✔
324
            (relations, embedded) =>
325
                relations.concat(embedded.buildIndicesFromTree()),
266✔
326
            this.indices,
327
        )
328
    }
329

330
    protected buildUniquesFromTree(): UniqueMetadata[] {
331
        return this.embeddeds.reduce(
982✔
332
            (relations, embedded) =>
333
                relations.concat(embedded.buildUniquesFromTree()),
266✔
334
            this.uniques,
335
        )
336
    }
337

338
    protected buildRelationIdsFromTree(): RelationIdMetadata[] {
339
        return this.embeddeds.reduce(
982✔
340
            (relations, embedded) =>
341
                relations.concat(embedded.buildRelationIdsFromTree()),
266✔
342
            this.relationIds,
343
        )
344
    }
345

346
    protected buildRelationCountsFromTree(): RelationCountMetadata[] {
347
        return this.embeddeds.reduce(
982✔
348
            (relations, embedded) =>
349
                relations.concat(embedded.buildRelationCountsFromTree()),
266✔
350
            this.relationCounts,
351
        )
352
    }
353
}
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