• 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

87.15
/src/entity-schema/EntitySchemaTransformer.ts
1
import { EntitySchema } from "./EntitySchema"
26✔
2
import { MetadataArgsStorage } from "../metadata-args/MetadataArgsStorage"
26✔
3
import { TableMetadataArgs } from "../metadata-args/TableMetadataArgs"
26✔
4
import { ColumnMetadataArgs } from "../metadata-args/ColumnMetadataArgs"
26✔
5
import { IndexMetadataArgs } from "../metadata-args/IndexMetadataArgs"
26✔
6
import { RelationMetadataArgs } from "../metadata-args/RelationMetadataArgs"
26✔
7
import { JoinColumnMetadataArgs } from "../metadata-args/JoinColumnMetadataArgs"
26✔
8
import { JoinTableMetadataArgs } from "../metadata-args/JoinTableMetadataArgs"
26✔
9
import { JoinTableOptions } from "../decorator/options/JoinTableOptions"
26✔
10
import { JoinTableMultipleColumnsOptions } from "../decorator/options/JoinTableMultipleColumnsOptions"
26✔
11
import { ColumnMode } from "../metadata-args/types/ColumnMode"
26✔
12
import { GeneratedMetadataArgs } from "../metadata-args/GeneratedMetadataArgs"
26✔
13
import { UniqueMetadataArgs } from "../metadata-args/UniqueMetadataArgs"
26✔
14
import { CheckMetadataArgs } from "../metadata-args/CheckMetadataArgs"
26✔
15
import { ExclusionMetadataArgs } from "../metadata-args/ExclusionMetadataArgs"
26✔
16
import { EntitySchemaColumnOptions } from "./EntitySchemaColumnOptions"
26✔
17
import { EntitySchemaOptions } from "./EntitySchemaOptions"
26✔
18
import { EntitySchemaEmbeddedError } from "./EntitySchemaEmbeddedError"
26✔
19
import { InheritanceMetadataArgs } from "../metadata-args/InheritanceMetadataArgs"
26✔
20
import { RelationIdMetadataArgs } from "../metadata-args/RelationIdMetadataArgs"
26✔
21
import { ForeignKeyMetadataArgs } from "../metadata-args/ForeignKeyMetadataArgs"
26✔
22

26✔
23
/**
26✔
24
 * Transforms entity schema into metadata args storage.
26✔
25
 * The result will be just like entities read from decorators.
26✔
26
 */
26✔
27
export class EntitySchemaTransformer {
26✔
28
    // -------------------------------------------------------------------------
26✔
29
    // Public Methods
26✔
30
    // -------------------------------------------------------------------------
26✔
31

26✔
32
    /**
26✔
33
     * Transforms entity schema into new metadata args storage object.
26✔
34
     */
26✔
35
    transform(schemas: EntitySchema<any>[]): MetadataArgsStorage {
26✔
36
        const metadataArgsStorage = new MetadataArgsStorage()
14,597✔
37

14,597✔
38
        schemas.forEach((entitySchema) => {
14,597✔
39
            const options = entitySchema.options
1,020✔
40

1,020✔
41
            // add table metadata args from the schema
1,020✔
42
            const tableMetadata: TableMetadataArgs = {
1,020✔
43
                target: options.target || options.name,
1,020✔
44
                name: options.tableName,
1,020✔
45
                database: options.database,
1,020✔
46
                schema: options.schema,
1,020✔
47
                type: options.type || "regular",
1,020✔
48
                orderBy: options.orderBy,
1,020✔
49
                synchronize: options.synchronize,
1,020✔
50
                withoutRowid: !!options.withoutRowid,
1,020✔
51
                expression: options.expression,
1,020✔
52
            }
1,020✔
53
            metadataArgsStorage.tables.push(tableMetadata)
1,020✔
54

1,020✔
55
            const { inheritance } = options
1,020✔
56

1,020✔
57
            if (inheritance) {
1,020!
58
                metadataArgsStorage.inheritances.push({
46✔
59
                    target: options.target,
46✔
60
                    pattern: inheritance.pattern ?? "STI",
46!
61
                    column: inheritance.column
46✔
62
                        ? typeof inheritance.column === "string"
46✔
63
                            ? { name: inheritance.column }
46✔
64
                            : inheritance.column
46!
65
                        : undefined,
46!
66
                } as InheritanceMetadataArgs)
46✔
67
            }
46✔
68

1,020✔
69
            const { discriminatorValue } = options
1,020✔
70

1,020✔
71
            if (discriminatorValue) {
1,020!
72
                metadataArgsStorage.discriminatorValues.push({
46✔
73
                    target: options.target || options.name,
46!
74
                    value: discriminatorValue,
46✔
75
                })
46✔
76
            }
46✔
77

1,020✔
78
            this.transformColumnsRecursive(options, metadataArgsStorage)
1,020✔
79
        })
14,597✔
80

14,597✔
81
        return metadataArgsStorage
14,597✔
82
    }
14,597✔
83

26✔
84
    private transformColumnsRecursive(
26✔
85
        options: EntitySchemaOptions<any>,
1,104✔
86
        metadataArgsStorage: MetadataArgsStorage,
1,104✔
87
    ): void {
1,104✔
88
        // add columns metadata args from the schema
1,104✔
89
        Object.keys(options.columns).forEach((columnName) => {
1,104✔
90
            const column = options.columns[columnName]!
3,090✔
91

3,090✔
92
            const regularColumn = column as EntitySchemaColumnOptions
3,090✔
93
            let mode: ColumnMode = "regular"
3,090✔
94
            if (regularColumn.createDate) mode = "createDate"
3,090!
95
            if (regularColumn.updateDate) mode = "updateDate"
3,090!
96
            if (regularColumn.deleteDate) mode = "deleteDate"
3,090!
97
            if (regularColumn.version) mode = "version"
3,090!
98
            if (regularColumn.treeChildrenCount) mode = "treeChildrenCount"
3,090!
99
            if (regularColumn.treeLevel) mode = "treeLevel"
3,090!
100
            if (regularColumn.objectId) mode = "objectId"
3,090!
101
            if (regularColumn.virtualProperty) mode = "virtual-property"
3,090!
102

3,090✔
103
            const columnArgs: ColumnMetadataArgs = {
3,090✔
104
                target: options.target || options.name,
3,090✔
105
                mode: mode,
3,090✔
106
                propertyName: columnName,
3,090✔
107
                options: {
3,090✔
108
                    type: regularColumn.type,
3,090✔
109
                    name: regularColumn.objectId ? "_id" : regularColumn.name,
3,090!
110
                    primaryKeyConstraintName:
3,090✔
111
                        regularColumn.primaryKeyConstraintName,
3,090✔
112
                    length: regularColumn.length,
3,090✔
113
                    width: regularColumn.width,
3,090✔
114
                    nullable: regularColumn.nullable,
3,090✔
115
                    readonly: regularColumn.readonly,
3,090✔
116
                    update: regularColumn.update,
3,090✔
117
                    select: regularColumn.select,
3,090✔
118
                    insert: regularColumn.insert,
3,090✔
119
                    primary: regularColumn.primary,
3,090✔
120
                    unique: regularColumn.unique,
3,090✔
121
                    comment: regularColumn.comment,
3,090✔
122
                    default: regularColumn.default,
3,090✔
123
                    onUpdate: regularColumn.onUpdate,
3,090✔
124
                    precision: regularColumn.precision,
3,090✔
125
                    scale: regularColumn.scale,
3,090✔
126
                    zerofill: regularColumn.zerofill,
3,090✔
127
                    unsigned: regularColumn.unsigned,
3,090✔
128
                    charset: regularColumn.charset,
3,090✔
129
                    collation: regularColumn.collation,
3,090✔
130
                    enum: regularColumn.enum,
3,090✔
131
                    enumName: regularColumn.enumName,
3,090✔
132
                    asExpression: regularColumn.asExpression,
3,090✔
133
                    generatedType: regularColumn.generatedType,
3,090✔
134
                    hstoreType: regularColumn.hstoreType,
3,090✔
135
                    array: regularColumn.array,
3,090✔
136
                    transformer: regularColumn.transformer,
3,090✔
137
                    spatialFeatureType: regularColumn.spatialFeatureType,
3,090✔
138
                    srid: regularColumn.srid,
3,090✔
139
                    query: regularColumn.query,
3,090✔
140
                },
3,090✔
141
            }
3,090✔
142
            metadataArgsStorage.columns.push(columnArgs)
3,090✔
143

3,090✔
144
            if (regularColumn.generated) {
3,090✔
145
                const generationArgs: GeneratedMetadataArgs = {
623✔
146
                    target: options.target || options.name,
623✔
147
                    propertyName: columnName,
623✔
148
                    strategy:
623✔
149
                        typeof regularColumn.generated === "string"
623✔
150
                            ? regularColumn.generated
623✔
151
                            : "increment",
623✔
152
                }
623✔
153
                metadataArgsStorage.generations.push(generationArgs)
623✔
154
            }
623✔
155

3,090✔
156
            if (regularColumn.unique)
3,090✔
157
                metadataArgsStorage.uniques.push({
3,090!
158
                    target: options.target || options.name,
56✔
159
                    columns: [columnName],
56✔
160
                })
56✔
161

3,090✔
162
            if (regularColumn.foreignKey) {
3,090!
163
                const foreignKey = regularColumn.foreignKey
112✔
164

112✔
165
                const foreignKeyArgs: ForeignKeyMetadataArgs = {
112✔
166
                    target: options.target || options.name,
112✔
167
                    type: foreignKey.target,
112✔
168
                    propertyName: columnName,
112✔
169
                    inverseSide: foreignKey.inverseSide,
112✔
170
                    name: foreignKey.name,
112✔
171
                    onDelete: foreignKey.onDelete,
112✔
172
                    onUpdate: foreignKey.onUpdate,
112✔
173
                    deferrable: foreignKey.deferrable,
112✔
174
                }
112✔
175
                metadataArgsStorage.foreignKeys.push(foreignKeyArgs)
112✔
176
            }
112✔
177
        })
1,104✔
178

1,104✔
179
        // add relation metadata args from the schema
1,104✔
180
        if (options.relations) {
1,104✔
181
            Object.keys(options.relations).forEach((relationName) => {
252✔
182
                const relationSchema = options.relations![relationName]!
342✔
183
                const relation: RelationMetadataArgs = {
342✔
184
                    target: options.target || options.name,
342!
185
                    propertyName: relationName,
342✔
186
                    relationType: relationSchema.type,
342✔
187
                    isLazy: relationSchema.lazy || false,
342✔
188
                    type: relationSchema.target,
342✔
189
                    inverseSideProperty: relationSchema.inverseSide,
342✔
190
                    isTreeParent: relationSchema.treeParent,
342✔
191
                    isTreeChildren: relationSchema.treeChildren,
342✔
192
                    options: {
342✔
193
                        eager: relationSchema.eager || false,
342✔
194
                        cascade: relationSchema.cascade,
342✔
195
                        nullable: relationSchema.nullable,
342✔
196
                        onDelete: relationSchema.onDelete,
342✔
197
                        onUpdate: relationSchema.onUpdate,
342✔
198
                        deferrable: relationSchema.deferrable,
342✔
199
                        // primary: relationSchema.primary,
342✔
200
                        createForeignKeyConstraints:
342✔
201
                            relationSchema.createForeignKeyConstraints,
342✔
202
                        persistence: relationSchema.persistence,
342✔
203
                        orphanedRowAction: relationSchema.orphanedRowAction,
342✔
204
                    },
342✔
205
                }
342✔
206

342✔
207
                metadataArgsStorage.relations.push(relation)
342✔
208

342✔
209
                // add join column
342✔
210
                if (relationSchema.joinColumn) {
342✔
211
                    if (typeof relationSchema.joinColumn === "boolean") {
145!
212
                        const joinColumn: JoinColumnMetadataArgs = {
4✔
213
                            target: options.target || options.name,
4✔
214
                            propertyName: relationName,
4✔
215
                        }
4✔
216
                        metadataArgsStorage.joinColumns.push(joinColumn)
4✔
217
                    } else {
145✔
218
                        const joinColumnsOptions = Array.isArray(
141✔
219
                            relationSchema.joinColumn,
141✔
220
                        )
141✔
221
                            ? relationSchema.joinColumn
141✔
222
                            : [relationSchema.joinColumn]
141!
223

141✔
224
                        for (const joinColumnOption of joinColumnsOptions) {
141✔
225
                            const joinColumn: JoinColumnMetadataArgs = {
170✔
226
                                target: options.target || options.name,
170!
227
                                propertyName: relationName,
170✔
228
                                name: joinColumnOption.name,
170✔
229
                                referencedColumnName:
170✔
230
                                    joinColumnOption.referencedColumnName,
170✔
231
                                foreignKeyConstraintName:
170✔
232
                                    joinColumnOption.foreignKeyConstraintName,
170✔
233
                            }
170✔
234
                            metadataArgsStorage.joinColumns.push(joinColumn)
170✔
235
                        }
170✔
236
                    }
141✔
237
                }
145✔
238

342✔
239
                // add join table
342✔
240
                if (relationSchema.joinTable) {
342!
241
                    if (typeof relationSchema.joinTable === "boolean") {
60✔
242
                        const joinTable: JoinTableMetadataArgs = {
28✔
243
                            target: options.target || options.name,
28✔
244
                            propertyName: relationName,
28✔
245
                        }
28✔
246
                        metadataArgsStorage.joinTables.push(joinTable)
28✔
247
                    } else {
36✔
248
                        const joinTable: JoinTableMetadataArgs = {
32✔
249
                            target: options.target || options.name,
32✔
250
                            propertyName: relationName,
32✔
251
                            name: relationSchema.joinTable.name,
32✔
252
                            database: relationSchema.joinTable.database,
32✔
253
                            schema: relationSchema.joinTable.schema,
32✔
254
                            joinColumns: ((
32✔
255
                                relationSchema.joinTable as JoinTableOptions
32✔
256
                            ).joinColumn
32✔
257
                                ? [
32✔
258
                                      (
28✔
259
                                          relationSchema.joinTable as JoinTableOptions
28✔
260
                                      ).joinColumn!,
28✔
261
                                  ]
28✔
262
                                : (
32!
263
                                      relationSchema.joinTable as JoinTableMultipleColumnsOptions
4✔
264
                                  ).joinColumns) as any,
32✔
265
                            inverseJoinColumns: ((
32✔
266
                                relationSchema.joinTable as JoinTableOptions
32✔
267
                            ).inverseJoinColumn
32✔
268
                                ? [
32✔
269
                                      (
28✔
270
                                          relationSchema.joinTable as JoinTableOptions
28✔
271
                                      ).inverseJoinColumn!,
28✔
272
                                  ]
28✔
273
                                : (
32!
274
                                      relationSchema.joinTable as JoinTableMultipleColumnsOptions
4✔
275
                                  ).inverseJoinColumns) as any,
32✔
276
                        }
32✔
277
                        metadataArgsStorage.joinTables.push(joinTable)
32✔
278
                    }
32✔
279
                }
60✔
280
            })
252✔
281
        }
252✔
282

1,104✔
283
        // add relation id metadata args from the schema
1,104✔
284
        if (options.relationIds) {
1,104!
285
            Object.keys(options.relationIds).forEach((relationIdName) => {
×
286
                const relationIdOptions = options.relationIds![relationIdName]!
×
287
                const relationId: RelationIdMetadataArgs = {
×
288
                    propertyName: relationIdName,
×
289
                    relation: relationIdOptions.relationName,
×
290
                    target: options.target || options.name,
×
291
                    alias: relationIdOptions.alias,
×
292
                    queryBuilderFactory: relationIdOptions.queryBuilderFactory,
×
293
                }
×
294
                metadataArgsStorage.relationIds.push(relationId)
×
295
            })
×
296
        }
×
297

1,104✔
298
        // add index metadata args from the schema
1,104✔
299
        if (options.indices) {
1,104✔
300
            options.indices.forEach((index) => {
144✔
301
                const indexArgs: IndexMetadataArgs = {
176✔
302
                    target: options.target || options.name,
176✔
303
                    name: index.name,
176✔
304
                    unique: index.unique === true ? true : false,
176!
305
                    spatial: index.spatial === true ? true : false,
176!
306
                    fulltext: index.fulltext === true ? true : false,
176!
307
                    nullFiltered: index.nullFiltered === true ? true : false,
176!
308
                    parser: index.parser,
176✔
309
                    synchronize: index.synchronize === false ? false : true,
176!
310
                    where: index.where,
176✔
311
                    sparse: index.sparse,
176✔
312
                    columns: index.columns,
176✔
313
                }
176✔
314
                metadataArgsStorage.indices.push(indexArgs)
176✔
315
            })
144✔
316
        }
144✔
317

1,104✔
318
        if (options.foreignKeys) {
1,104✔
319
            options.foreignKeys.forEach((foreignKey) => {
28✔
320
                const foreignKeyArgs: ForeignKeyMetadataArgs = {
28✔
321
                    target: options.target || options.name,
28✔
322
                    type: foreignKey.target,
28✔
323
                    columnNames: foreignKey.columnNames,
28✔
324
                    referencedColumnNames: foreignKey.referencedColumnNames,
28✔
325
                    name: foreignKey.name,
28✔
326
                    onDelete: foreignKey.onDelete,
28✔
327
                    onUpdate: foreignKey.onUpdate,
28✔
328
                    deferrable: foreignKey.deferrable,
28✔
329
                }
28✔
330
                metadataArgsStorage.foreignKeys.push(foreignKeyArgs)
28✔
331
            })
28✔
332
        }
28✔
333

1,104✔
334
        // add unique metadata args from the schema
1,104✔
335
        if (options.uniques) {
1,104✔
336
            options.uniques.forEach((unique) => {
84✔
337
                const uniqueArgs: UniqueMetadataArgs = {
84✔
338
                    target: options.target || options.name,
84✔
339
                    name: unique.name,
84✔
340
                    columns: unique.columns,
84✔
341
                    deferrable: unique.deferrable,
84✔
342
                }
84✔
343
                metadataArgsStorage.uniques.push(uniqueArgs)
84✔
344
            })
84✔
345
        }
84✔
346

1,104✔
347
        // add check metadata args from the schema
1,104✔
348
        if (options.checks) {
1,104!
349
            options.checks.forEach((check) => {
9✔
350
                const checkArgs: CheckMetadataArgs = {
18✔
351
                    target: options.target || options.name,
18✔
352
                    name: check.name,
18✔
353
                    expression: check.expression,
18✔
354
                }
18✔
355
                metadataArgsStorage.checks.push(checkArgs)
18✔
356
            })
9✔
357
        }
9✔
358

1,104✔
359
        // add exclusion metadata args from the schema
1,104✔
360
        if (options.exclusions) {
1,104!
361
            options.exclusions.forEach((exclusion) => {
4✔
362
                const exclusionArgs: ExclusionMetadataArgs = {
4✔
363
                    target: options.target || options.name,
4✔
364
                    name: exclusion.name,
4✔
365
                    expression: exclusion.expression,
4✔
366
                }
4✔
367
                metadataArgsStorage.exclusions.push(exclusionArgs)
4✔
368
            })
4✔
369
        }
4✔
370

1,104✔
371
        if (options.embeddeds) {
1,104✔
372
            Object.keys(options.embeddeds).forEach((columnName) => {
84✔
373
                const embeddedOptions = options.embeddeds![columnName]
84✔
374

84✔
375
                if (!embeddedOptions.schema)
84✔
376
                    throw EntitySchemaEmbeddedError.createEntitySchemaIsRequiredException(
84!
377
                        columnName,
×
378
                    )
×
379

84✔
380
                const embeddedSchema = embeddedOptions.schema.options
84✔
381

84✔
382
                metadataArgsStorage.embeddeds.push({
84✔
383
                    target: options.target || options.name,
84✔
384
                    propertyName: columnName,
84✔
385
                    isArray: embeddedOptions.array === true,
84✔
386
                    prefix:
84✔
387
                        embeddedOptions.prefix !== undefined
84✔
388
                            ? embeddedOptions.prefix
84✔
389
                            : undefined,
84!
390
                    type: () => embeddedSchema?.target || embeddedSchema.name,
84✔
391
                })
84✔
392

84✔
393
                this.transformColumnsRecursive(
84✔
394
                    embeddedSchema,
84✔
395
                    metadataArgsStorage,
84✔
396
                )
84✔
397
            })
84✔
398
        }
84✔
399

1,104✔
400
        if (options.trees) {
1,104!
401
            options.trees.forEach((tree) => {
3✔
402
                metadataArgsStorage.trees.push({
3✔
403
                    target: options.target || options.name,
3✔
404
                    type: tree.type,
3✔
405
                    options: tree.options,
3✔
406
                })
3✔
407
            })
3✔
408
        }
3✔
409
    }
1,104✔
410
}
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