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

typeorm / typeorm / 15219332477

23 May 2025 09:13PM UTC coverage: 17.216% (-59.1%) from 76.346%
15219332477

Pull #11332

github

naorpeled
cr comments - move if block
Pull Request #11332: feat: add new undefined and null behavior flags

1603 of 12759 branches covered (12.56%)

Branch coverage included in aggregate %.

0 of 31 new or added lines in 3 files covered. (0.0%)

14132 existing lines in 166 files now uncovered.

4731 of 24033 relevant lines covered (19.69%)

60.22 hits per line

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

28.99
/src/metadata/UniqueMetadata.ts
1
import { EmbeddedMetadata } from "./EmbeddedMetadata"
2
import { EntityMetadata } from "./EntityMetadata"
3
import { NamingStrategyInterface } from "../naming-strategy/NamingStrategyInterface"
4
import { ColumnMetadata } from "./ColumnMetadata"
5
import { UniqueMetadataArgs } from "../metadata-args/UniqueMetadataArgs"
6
import { TypeORMError } from "../error"
1✔
7
import { DeferrableType } from "./types/DeferrableType"
8

9
/**
10
 * Unique metadata contains all information about table's unique constraints.
11
 */
12
export class UniqueMetadata {
1✔
13
    // ---------------------------------------------------------------------
14
    // Public Properties
15
    // ---------------------------------------------------------------------
16

17
    /**
18
     * Entity metadata of the class to which this unique constraint is applied.
19
     */
20
    entityMetadata: EntityMetadata
21

22
    /**
23
     * Embedded metadata if this unique was applied on embedded.
24
     */
25
    embeddedMetadata?: EmbeddedMetadata
26

27
    /**
28
     * Target class to which metadata is applied.
29
     */
30
    target?: Function | string
31

32
    /**
33
     * Unique columns.
34
     */
35
    columns: ColumnMetadata[] = []
7✔
36

37
    /**
38
     * Indicate if unique constraints can be deferred.
39
     */
40
    deferrable?: DeferrableType
41

42
    /**
43
     * User specified unique constraint name.
44
     */
45
    givenName?: string
46

47
    /**
48
     * User specified column names.
49
     */
50
    givenColumnNames?:
51
        | ((object?: any) => any[] | { [key: string]: number })
52
        | string[]
53

54
    /**
55
     * Final unique constraint name.
56
     * If unique constraint name was given by a user then it stores normalized (by naming strategy) givenName.
57
     * If unique constraint name was not given then its generated.
58
     */
59
    name: string
60

61
    /**
62
     * Map of column names with order set.
63
     * Used only by MongoDB driver.
64
     */
65
    columnNamesWithOrderingMap: { [key: string]: number } = {}
7✔
66

67
    // ---------------------------------------------------------------------
68
    // Constructor
69
    // ---------------------------------------------------------------------
70

71
    constructor(options: {
72
        entityMetadata: EntityMetadata
73
        embeddedMetadata?: EmbeddedMetadata
74
        columns?: ColumnMetadata[]
75
        args?: UniqueMetadataArgs
76
    }) {
77
        this.entityMetadata = options.entityMetadata
7✔
78
        this.embeddedMetadata = options.embeddedMetadata
7✔
79
        if (options.columns) this.columns = options.columns
7✔
80

81
        if (options.args) {
7✔
82
            this.target = options.args.target
7✔
83
            this.givenName = options.args.name
7✔
84
            this.givenColumnNames = options.args.columns
7✔
85
            this.deferrable = options.args.deferrable
7✔
86
        }
87
    }
88

89
    // ---------------------------------------------------------------------
90
    // Public Build Methods
91
    // ---------------------------------------------------------------------
92

93
    /**
94
     * Builds some depend unique constraint properties.
95
     * Must be called after all entity metadata's properties map, columns and relations are built.
96
     */
97
    build(namingStrategy: NamingStrategyInterface): this {
98
        const map: { [key: string]: number } = {}
7✔
99

100
        // if columns already an array of string then simply return it
101
        if (this.givenColumnNames) {
7!
UNCOV
102
            let columnPropertyPaths: string[] = []
×
UNCOV
103
            if (Array.isArray(this.givenColumnNames)) {
×
UNCOV
104
                columnPropertyPaths = this.givenColumnNames.map(
×
105
                    (columnName) => {
UNCOV
106
                        if (this.embeddedMetadata)
×
UNCOV
107
                            return (
×
108
                                this.embeddedMetadata.propertyPath +
109
                                "." +
110
                                columnName
111
                            )
112

UNCOV
113
                        return columnName.trim()
×
114
                    },
115
                )
UNCOV
116
                columnPropertyPaths.forEach(
×
UNCOV
117
                    (propertyPath) => (map[propertyPath] = 1),
×
118
                )
119
            } else {
120
                // if columns is a function that returns array of field names then execute it and get columns names from it
UNCOV
121
                const columnsFnResult = this.givenColumnNames(
×
122
                    this.entityMetadata.propertiesMap,
123
                )
UNCOV
124
                if (Array.isArray(columnsFnResult)) {
×
UNCOV
125
                    columnPropertyPaths = columnsFnResult.map((i: any) =>
×
UNCOV
126
                        String(i),
×
127
                    )
UNCOV
128
                    columnPropertyPaths.forEach((name) => (map[name] = 1))
×
129
                } else {
130
                    columnPropertyPaths = Object.keys(columnsFnResult).map(
×
131
                        (i: any) => String(i),
×
132
                    )
133
                    Object.keys(columnsFnResult).forEach(
×
134
                        (columnName) =>
135
                            (map[columnName] = columnsFnResult[columnName]),
×
136
                    )
137
                }
138
            }
139

UNCOV
140
            this.columns = columnPropertyPaths
×
141
                .map((propertyName) => {
UNCOV
142
                    const columnWithSameName = this.entityMetadata.columns.find(
×
UNCOV
143
                        (column) => column.propertyPath === propertyName,
×
144
                    )
UNCOV
145
                    if (columnWithSameName) {
×
UNCOV
146
                        return [columnWithSameName]
×
147
                    }
148
                    const relationWithSameName =
UNCOV
149
                        this.entityMetadata.relations.find(
×
150
                            (relation) =>
UNCOV
151
                                relation.isWithJoinColumn &&
×
152
                                relation.propertyName === propertyName,
153
                        )
UNCOV
154
                    if (relationWithSameName) {
×
UNCOV
155
                        return relationWithSameName.joinColumns
×
156
                    }
157
                    const indexName = this.givenName
×
158
                        ? '"' + this.givenName + '" '
159
                        : ""
160
                    const entityName = this.entityMetadata.targetName
×
161
                    throw new TypeORMError(
×
162
                        `Unique constraint ${indexName}contains column that is missing in the entity (${entityName}): ` +
163
                            propertyName,
164
                    )
165
                })
UNCOV
166
                .reduce((a, b) => a.concat(b))
×
167
        }
168

169
        this.columnNamesWithOrderingMap = Object.keys(map).reduce(
7✔
170
            (updatedMap, key) => {
UNCOV
171
                const column = this.entityMetadata.columns.find(
×
UNCOV
172
                    (column) => column.propertyPath === key,
×
173
                )
UNCOV
174
                if (column) updatedMap[column.databasePath] = map[key]
×
175

UNCOV
176
                return updatedMap
×
177
            },
178
            {} as { [key: string]: number },
179
        )
180

181
        this.name = this.givenName
7!
182
            ? this.givenName
183
            : namingStrategy.uniqueConstraintName(
184
                  this.entityMetadata.tableName,
UNCOV
185
                  this.columns.map((column) => column.databaseName),
×
186
              )
187
        return this
7✔
188
    }
189
}
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