• 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

69.13
/src/driver/DriverUtils.ts
1
import { Driver } from "./Driver"
2
import { hash, shorten } from "../util/StringUtils"
1✔
3
import { VersionUtils } from "../util/VersionUtils"
1✔
4

5
/**
6
 * Common driver utility functions.
7
 */
8
export class DriverUtils {
1✔
9
    // -------------------------------------------------------------------------
10
    // Public Static Methods
11
    // -------------------------------------------------------------------------
12

13
    /**
14
     * Returns true if given driver is SQLite-based driver.
15
     */
16
    static isSQLiteFamily(driver: Driver): boolean {
17
        return [
75✔
18
            "sqlite",
19
            "cordova",
20
            "react-native",
21
            "nativescript",
22
            "sqljs",
23
            "expo",
24
            "better-sqlite3",
25
            "capacitor",
26
        ].includes(driver.options.type)
27
    }
28

29
    /**
30
     * Returns true if given driver is MySQL-based driver.
31
     */
32
    static isMySQLFamily(driver: Driver): boolean {
33
        return ["mysql", "mariadb"].includes(driver.options.type)
242✔
34
    }
35

36
    static isReleaseVersionOrGreater(driver: Driver, version: string): boolean {
UNCOV
37
        return VersionUtils.isGreaterOrEqual(driver.version, version)
×
38
    }
39

40
    static isPostgresFamily(driver: Driver): boolean {
UNCOV
41
        return ["postgres", "aurora-postgres", "cockroachdb"].includes(
×
42
            driver.options.type,
43
        )
44
    }
45

46
    /**
47
     * Normalizes and builds a new driver options.
48
     * Extracts settings from connection url and sets to a new options object.
49
     */
50
    static buildDriverOptions(
51
        options: any,
52
        buildOptions?: { useSid: boolean },
53
    ): any {
54
        if (options.url) {
21✔
55
            const urlDriverOptions = this.parseConnectionUrl(options.url) as {
8✔
56
                [key: string]: any
57
            }
58

59
            if (
8!
60
                buildOptions &&
8!
61
                buildOptions.useSid &&
62
                urlDriverOptions.database
63
            ) {
64
                urlDriverOptions.sid = urlDriverOptions.database
×
65
            }
66

67
            for (const key of Object.keys(urlDriverOptions)) {
8✔
68
                if (typeof urlDriverOptions[key] === "undefined") {
48!
69
                    delete urlDriverOptions[key]
×
70
                }
71
            }
72

73
            return Object.assign({}, options, urlDriverOptions)
8✔
74
        }
75
        return Object.assign({}, options)
13✔
76
    }
77

78
    /**
79
     * buildDriverOptions for MongodDB only to support replica set
80
     */
81
    static buildMongoDBDriverOptions(
82
        options: any,
83
        buildOptions?: { useSid: boolean },
84
    ): any {
85
        if (options.url) {
68✔
86
            const urlDriverOptions = this.parseMongoDBConnectionUrl(
14✔
87
                options.url,
88
            ) as { [key: string]: any }
89

90
            if (
14!
91
                buildOptions &&
14!
92
                buildOptions.useSid &&
93
                urlDriverOptions.database
94
            ) {
95
                urlDriverOptions.sid = urlDriverOptions.database
×
96
            }
97

98
            for (const key of Object.keys(urlDriverOptions)) {
14✔
99
                if (typeof urlDriverOptions[key] === "undefined") {
114✔
100
                    delete urlDriverOptions[key]
27✔
101
                }
102
            }
103

104
            return Object.assign({}, options, urlDriverOptions)
14✔
105
        }
106
        return Object.assign({}, options)
54✔
107
    }
108

109
    /**
110
     * Joins and shortens alias if needed.
111
     *
112
     * If the alias length is greater than the limit allowed by the current
113
     * driver, replaces it with a shortend string, if the shortend string
114
     * is still too long, it will then hash the alias.
115
     *
116
     * @param driver Current `Driver`.
117
     * @param buildOptions Optional settings.
118
     * @param alias Alias parts.
119
     *
120
     * @return An alias that is no longer than the divers max alias length.
121
     */
122
    static buildAlias(
123
        { maxAliasLength }: Driver,
124
        buildOptions: { shorten?: boolean; joiner?: string } | undefined,
125
        ...alias: string[]
126
    ): string {
127
        const joiner =
UNCOV
128
            buildOptions && buildOptions.joiner ? buildOptions.joiner : "_"
×
129

UNCOV
130
        const newAlias = alias.length === 1 ? alias[0] : alias.join(joiner)
×
131

UNCOV
132
        if (
×
133
            maxAliasLength &&
×
134
            maxAliasLength > 0 &&
135
            newAlias.length > maxAliasLength
136
        ) {
UNCOV
137
            if (buildOptions && buildOptions.shorten === true) {
×
138
                const shortenedAlias = shorten(newAlias)
×
139
                if (shortenedAlias.length < maxAliasLength) {
×
140
                    return shortenedAlias
×
141
                }
142
            }
143

UNCOV
144
            return hash(newAlias, { length: maxAliasLength })
×
145
        }
146

UNCOV
147
        return newAlias
×
148
    }
149

150
    /**
151
     * @deprecated use `buildAlias` instead.
152
     */
153
    static buildColumnAlias(
154
        { maxAliasLength }: Driver,
155
        buildOptions: { shorten?: boolean; joiner?: string } | string,
156
        ...alias: string[]
157
    ) {
158
        if (typeof buildOptions === "string") {
×
159
            alias.unshift(buildOptions)
×
160
            buildOptions = { shorten: false, joiner: "_" }
×
161
        } else {
162
            buildOptions = Object.assign(
×
163
                { shorten: false, joiner: "_" },
164
                buildOptions,
165
            )
166
        }
167
        return this.buildAlias(
×
168
            { maxAliasLength } as Driver,
169
            buildOptions,
170
            ...alias,
171
        )
172
    }
173

174
    // -------------------------------------------------------------------------
175
    // Private Static Methods
176
    // -------------------------------------------------------------------------
177

178
    /**
179
     * Extracts connection data from the connection url.
180
     */
181
    private static parseConnectionUrl(url: string) {
182
        const type = url.split(":")[0]
8✔
183
        const firstSlashes = url.indexOf("//")
8✔
184
        const preBase = url.substr(firstSlashes + 2)
8✔
185
        const secondSlash = preBase.indexOf("/")
8✔
186
        const base =
187
            secondSlash !== -1 ? preBase.substr(0, secondSlash) : preBase
8!
188
        let afterBase =
189
            secondSlash !== -1 ? preBase.substr(secondSlash + 1) : undefined
8!
190
        // remove mongodb query params
191
        if (afterBase && afterBase.indexOf("?") !== -1) {
8✔
192
            afterBase = afterBase.substr(0, afterBase.indexOf("?"))
1✔
193
        }
194

195
        const lastAtSign = base.lastIndexOf("@")
8✔
196
        const usernameAndPassword = base.substr(0, lastAtSign)
8✔
197
        const hostAndPort = base.substr(lastAtSign + 1)
8✔
198

199
        let username = usernameAndPassword
8✔
200
        let password = ""
8✔
201
        const firstColon = usernameAndPassword.indexOf(":")
8✔
202
        if (firstColon !== -1) {
8✔
203
            username = usernameAndPassword.substr(0, firstColon)
7✔
204
            password = usernameAndPassword.substr(firstColon + 1)
7✔
205
        }
206
        const [host, port] = hostAndPort.split(":")
8✔
207

208
        return {
8✔
209
            type: type,
210
            host: host,
211
            username: decodeURIComponent(username),
212
            password: decodeURIComponent(password),
213
            port: port ? parseInt(port) : undefined,
8!
214
            database: afterBase || undefined,
8!
215
        }
216
    }
217

218
    /**
219
     * Extracts connection data from the connection url for MongoDB to support replica set.
220
     */
221
    private static parseMongoDBConnectionUrl(url: string) {
222
        const type = url.split(":")[0]
14✔
223
        const firstSlashes = url.indexOf("//")
14✔
224
        const preBase = url.substr(firstSlashes + 2)
14✔
225
        const secondSlash = preBase.indexOf("/")
14✔
226
        const base =
227
            secondSlash !== -1 ? preBase.substr(0, secondSlash) : preBase
14✔
228
        let afterBase =
229
            secondSlash !== -1 ? preBase.substr(secondSlash + 1) : undefined
14✔
230
        let afterQuestionMark = ""
14✔
231
        let host = undefined
14✔
232
        let port = undefined
14✔
233
        let hostReplicaSet = undefined
14✔
234
        let replicaSet = undefined
14✔
235

236
        const optionsObject: any = {}
14✔
237

238
        if (afterBase && afterBase.indexOf("?") !== -1) {
14✔
239
            // split params
240
            afterQuestionMark = afterBase.substr(
10✔
241
                afterBase.indexOf("?") + 1,
242
                afterBase.length,
243
            )
244

245
            const optionsList = afterQuestionMark.split("&")
10✔
246
            let optionKey: string
247
            let optionValue: string
248

249
            // create optionsObject for merge with connectionUrl object before return
250
            optionsList.forEach((optionItem) => {
10✔
251
                optionKey = optionItem.split("=")[0]
16✔
252
                optionValue = optionItem.split("=")[1]
16✔
253
                optionsObject[optionKey] = optionValue
16✔
254
            })
255

256
            // specific replicaSet value to set options about hostReplicaSet
257
            replicaSet = optionsObject["replicaSet"]
10✔
258
            afterBase = afterBase.substr(0, afterBase.indexOf("?"))
10✔
259
        }
260

261
        const lastAtSign = base.lastIndexOf("@")
14✔
262
        const usernameAndPassword = base.substr(0, lastAtSign)
14✔
263
        const hostAndPort = base.substr(lastAtSign + 1)
14✔
264

265
        let username = usernameAndPassword
14✔
266
        let password = ""
14✔
267
        const firstColon = usernameAndPassword.indexOf(":")
14✔
268
        if (firstColon !== -1) {
14✔
269
            username = usernameAndPassword.substr(0, firstColon)
10✔
270
            password = usernameAndPassword.substr(firstColon + 1)
10✔
271
        }
272

273
        // If replicaSet have value set It as hostlist, If not set like standalone host
274
        if (replicaSet) {
14✔
275
            hostReplicaSet = hostAndPort
5✔
276
        } else {
277
            ;[host, port] = hostAndPort.split(":")
9✔
278
        }
279

280
        const connectionUrl: any = {
14✔
281
            type: type,
282
            host: host,
283
            hostReplicaSet: hostReplicaSet,
284
            username: decodeURIComponent(username),
285
            password: decodeURIComponent(password),
286
            port: port ? parseInt(port) : undefined,
14✔
287
            database: afterBase || undefined,
18✔
288
        }
289

290
        // Loop to set every options in connectionUrl to object
291
        for (const [key, value] of Object.entries(optionsObject)) {
14✔
292
            connectionUrl[key] = value
16✔
293
        }
294

295
        return connectionUrl
14✔
296
    }
297
}
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