• 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

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

5
/**
6
 * Common driver utility functions.
7
 */
8
export class DriverUtils {
4✔
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 [
120,695✔
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)
255,588✔
34
    }
35

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

40
    static isPostgresFamily(driver: Driver): boolean {
41
        return ["postgres", "aurora-postgres", "cockroachdb"].includes(
190,527✔
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) {
2,764✔
55
            const urlDriverOptions = this.parseConnectionUrl(options.url) as {
32✔
56
                [key: string]: any
57
            }
58

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

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

73
            return Object.assign({}, options, urlDriverOptions)
32✔
74
        }
75
        return Object.assign({}, options)
2,732✔
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) {
40✔
86
            const urlDriverOptions = this.parseMongoDBConnectionUrl(
40✔
87
                options.url,
88
            ) as { [key: string]: any }
89

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

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

104
            return Object.assign({}, options, urlDriverOptions)
40✔
105
        }
106
        return Object.assign({}, options)
×
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 =
128
            buildOptions && buildOptions.joiner ? buildOptions.joiner : "_"
1,500,688✔
129

130
        const newAlias = alias.length === 1 ? alias[0] : alias.join(joiner)
1,500,688✔
131

132
        if (
1,500,688✔
133
            maxAliasLength &&
2,201,186✔
134
            maxAliasLength > 0 &&
135
            newAlias.length > maxAliasLength
136
        ) {
137
            if (buildOptions && buildOptions.shorten === true) {
1,072!
138
                const shortenedAlias = shorten(newAlias)
×
139
                if (shortenedAlias.length < maxAliasLength) {
×
140
                    return shortenedAlias
×
141
                }
142
            }
143

144
            return hash(newAlias, { length: maxAliasLength })
1,072✔
145
        }
146

147
        return newAlias
1,499,616✔
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]
32✔
183
        const firstSlashes = url.indexOf("//")
32✔
184
        const preBase = url.substr(firstSlashes + 2)
32✔
185
        const secondSlash = preBase.indexOf("/")
32✔
186
        const base =
187
            secondSlash !== -1 ? preBase.substr(0, secondSlash) : preBase
32!
188
        let afterBase =
189
            secondSlash !== -1 ? preBase.substr(secondSlash + 1) : undefined
32!
190
        // remove mongodb query params
191
        if (afterBase && afterBase.indexOf("?") !== -1) {
32✔
192
            afterBase = afterBase.substr(0, afterBase.indexOf("?"))
4✔
193
        }
194

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

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

208
        return {
32✔
209
            type: type,
210
            host: host,
211
            username: decodeURIComponent(username),
212
            password: decodeURIComponent(password),
213
            port: port ? parseInt(port) : undefined,
32!
214
            database: afterBase || undefined,
32!
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]
40✔
223
        const firstSlashes = url.indexOf("//")
40✔
224
        const preBase = url.substr(firstSlashes + 2)
40✔
225
        const secondSlash = preBase.indexOf("/")
40✔
226
        const base =
227
            secondSlash !== -1 ? preBase.substr(0, secondSlash) : preBase
40!
228
        let afterBase =
229
            secondSlash !== -1 ? preBase.substr(secondSlash + 1) : undefined
40!
230
        let afterQuestionMark = ""
40✔
231
        let host = undefined
40✔
232
        let port = undefined
40✔
233
        let hostReplicaSet = undefined
40✔
234
        let replicaSet = undefined
40✔
235

236
        const optionsObject: any = {}
40✔
237

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

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

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

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

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

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

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

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

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

295
        return connectionUrl
40✔
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