• 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.14
/src/connection/ConnectionOptionsReader.ts
1
import appRootPath from "app-root-path"
26✔
2
import path from "path"
26✔
3

26✔
4
import { DataSourceOptions } from "../data-source/DataSourceOptions"
26✔
5
import { TypeORMError } from "../error"
26✔
6
import { PlatformTools } from "../platform/PlatformTools"
26✔
7
import { importOrRequireFile } from "../util/ImportUtils"
26✔
8
import { isAbsolute } from "../util/PathUtils"
26✔
9
import { ConnectionOptionsEnvReader } from "./options-reader/ConnectionOptionsEnvReader"
26✔
10

26✔
11
/**
26✔
12
 * Reads connection options from the ormconfig.
26✔
13
 */
26✔
14
export class ConnectionOptionsReader {
26✔
15
    // -------------------------------------------------------------------------
26✔
16
    // Constructor
26✔
17
    // -------------------------------------------------------------------------
26✔
18

26✔
19
    constructor(
26✔
20
        protected options?: {
286✔
21
            /**
286✔
22
             * Directory where ormconfig should be read from.
286✔
23
             * By default its your application root (where your app package.json is located).
286✔
24
             */
286✔
25
            root?: string
286✔
26

286✔
27
            /**
286✔
28
             * Filename of the ormconfig configuration. By default its equal to "ormconfig".
286✔
29
             */
286✔
30
            configName?: string
286✔
31
        },
286✔
32
    ) {}
286✔
33

26✔
34
    // -------------------------------------------------------------------------
26✔
35
    // Public Methods
26✔
36
    // -------------------------------------------------------------------------
26✔
37

26✔
38
    /**
26✔
39
     * Returns all connection options read from the ormconfig.
26✔
40
     */
26✔
41
    async all(): Promise<DataSourceOptions[]> {
26✔
42
        const options = await this.load()
398✔
43
        if (!options)
398✔
44
            throw new TypeORMError(
398!
45
                `No connection options were found in any orm configuration files.`,
×
46
            )
×
47

398✔
48
        return options
398✔
49
    }
398✔
50

26✔
51
    /**
26✔
52
     * Gets a connection with a given name read from ormconfig.
26✔
53
     * If connection with such name would not be found then it throw error.
26✔
54
     */
26✔
55
    async get(name: string): Promise<DataSourceOptions> {
26✔
56
        const allOptions = await this.all()
294✔
57
        const targetOptions = allOptions.find(
294✔
58
            (options) =>
294✔
59
                options.name === name || (name === "default" && !options.name),
294!
60
        )
294✔
61
        if (!targetOptions)
294✔
62
            throw new TypeORMError(
294!
63
                `Cannot find connection ${name} because its not defined in any orm configuration files.`,
×
64
            )
×
65

294✔
66
        return targetOptions
294✔
67
    }
294✔
68

26✔
69
    /**
26✔
70
     * Checks if there is a TypeORM configuration file.
26✔
71
     */
26✔
72
    async has(name: string): Promise<boolean> {
26✔
73
        const allOptions = await this.load()
×
74
        if (!allOptions) return false
×
75

×
76
        const targetOptions = allOptions.find(
×
77
            (options) =>
×
78
                options.name === name || (name === "default" && !options.name),
×
79
        )
×
80
        return !!targetOptions
×
81
    }
×
82

26✔
83
    // -------------------------------------------------------------------------
26✔
84
    // Protected Methods
26✔
85
    // -------------------------------------------------------------------------
26✔
86

26✔
87
    /**
26✔
88
     * Loads all connection options from a configuration file.
26✔
89
     *
26✔
90
     * todo: get in count NODE_ENV somehow
26✔
91
     */
26✔
92
    protected async load(): Promise<DataSourceOptions[] | undefined> {
26✔
93
        let connectionOptions:
398✔
94
            | DataSourceOptions
398✔
95
            | DataSourceOptions[]
398✔
96
            | undefined = undefined
398✔
97

398✔
98
        const fileFormats = [
398✔
99
            "env",
398✔
100
            "js",
398✔
101
            "mjs",
398✔
102
            "cjs",
398✔
103
            "ts",
398✔
104
            "mts",
398✔
105
            "cts",
398✔
106
            "json",
398✔
107
        ]
398✔
108

398✔
109
        // Detect if baseFilePath contains file extension
398✔
110
        const possibleExtension = this.baseFilePath.substr(
398✔
111
            this.baseFilePath.lastIndexOf("."),
398✔
112
        )
398✔
113
        const fileExtension = fileFormats.find(
398✔
114
            (extension) => `.${extension}` === possibleExtension,
398✔
115
        )
398✔
116

398✔
117
        // try to find any of following configuration formats
398✔
118
        const foundFileFormat =
398✔
119
            fileExtension ||
398✔
120
            fileFormats.find((format) => {
346✔
121
                return PlatformTools.fileExist(this.baseFilePath + "." + format)
1,546✔
122
            })
346✔
123

398✔
124
        // Determine config file name
398✔
125
        const configFile = fileExtension
398✔
126
            ? this.baseFilePath
398✔
127
            : this.baseFilePath + "." + foundFileFormat
398✔
128

398✔
129
        // if .env file found then load all its variables into process.env using dotenv package
398✔
130
        if (foundFileFormat === "env") {
398✔
131
            PlatformTools.dotenv(configFile)
78✔
132
        } else if (PlatformTools.fileExist(this.baseDirectory + "/.env")) {
398!
133
            PlatformTools.dotenv(this.baseDirectory + "/.env")
×
134
        }
×
135

398✔
136
        // try to find connection options from any of available sources of configuration
398✔
137
        if (
398✔
138
            PlatformTools.getEnvVariable("TYPEORM_CONNECTION") ||
398✔
139
            PlatformTools.getEnvVariable("TYPEORM_URL")
320✔
140
        ) {
398✔
141
            connectionOptions = new ConnectionOptionsEnvReader().read()
78✔
142
        } else if (
398✔
143
            foundFileFormat === "js" ||
320✔
144
            foundFileFormat === "mjs" ||
320✔
145
            foundFileFormat === "cjs" ||
320✔
146
            foundFileFormat === "ts" ||
320✔
147
            foundFileFormat === "mts" ||
320✔
148
            foundFileFormat === "cts"
138✔
149
        ) {
320✔
150
            const [importOrRequireResult, moduleSystem] =
182✔
151
                await importOrRequireFile(configFile)
182✔
152
            const configModule = await importOrRequireResult
182✔
153

182✔
154
            if (
182✔
155
                moduleSystem === "esm" ||
182✔
156
                (configModule &&
182✔
157
                    "__esModule" in configModule &&
182✔
158
                    "default" in configModule)
182✔
159
            ) {
182✔
160
                connectionOptions = configModule.default
26✔
161
            } else {
182✔
162
                connectionOptions = configModule
156✔
163
            }
156✔
164
        } else if (foundFileFormat === "json") {
320!
165
            connectionOptions = require(configFile)
138✔
166
        }
138✔
167

398✔
168
        // normalize and return connection options
398✔
169
        if (connectionOptions) {
398✔
170
            return this.normalizeConnectionOptions(connectionOptions)
398✔
171
        }
398✔
172

×
173
        return undefined
×
174
    }
×
175

26✔
176
    /**
26✔
177
     * Normalize connection options.
26✔
178
     */
26✔
179
    protected normalizeConnectionOptions(
26✔
180
        connectionOptions: DataSourceOptions | DataSourceOptions[],
398✔
181
    ): DataSourceOptions[] {
398✔
182
        if (!Array.isArray(connectionOptions))
398✔
183
            connectionOptions = [connectionOptions]
398✔
184

398✔
185
        connectionOptions.forEach((options) => {
398✔
186
            options.baseDirectory = this.baseDirectory
550✔
187
            if (options.entities) {
550✔
188
                const entities = (options.entities as any[]).map((entity) => {
104✔
189
                    if (
26✔
190
                        typeof entity === "string" &&
26!
191
                        entity.substr(0, 1) !== "/"
×
192
                    )
26✔
193
                        return this.baseDirectory + "/" + entity
26!
194

26✔
195
                    return entity
26✔
196
                })
104✔
197
                Object.assign(connectionOptions, { entities: entities })
104✔
198
            }
104✔
199
            if (options.subscribers) {
550✔
200
                const subscribers = (options.subscribers as any[]).map(
78✔
201
                    (subscriber) => {
78✔
202
                        if (
×
203
                            typeof subscriber === "string" &&
×
204
                            subscriber.substr(0, 1) !== "/"
×
205
                        )
×
206
                            return this.baseDirectory + "/" + subscriber
×
207

×
208
                        return subscriber
×
209
                    },
78✔
210
                )
78✔
211
                Object.assign(connectionOptions, { subscribers: subscribers })
78✔
212
            }
78✔
213
            if (options.migrations) {
550✔
214
                const migrations = (options.migrations as any[]).map(
78✔
215
                    (migration) => {
78✔
216
                        if (
×
217
                            typeof migration === "string" &&
×
218
                            migration.substr(0, 1) !== "/"
×
219
                        )
×
220
                            return this.baseDirectory + "/" + migration
×
221

×
222
                        return migration
×
223
                    },
78✔
224
                )
78✔
225
                Object.assign(connectionOptions, { migrations: migrations })
78✔
226
            }
78✔
227

550✔
228
            // make database path file in sqlite relative to package.json
550✔
229
            if (
550✔
230
                options.type === "sqlite" ||
550✔
231
                options.type === "better-sqlite3"
350✔
232
            ) {
550✔
233
                if (
270✔
234
                    typeof options.database === "string" &&
270✔
235
                    !isAbsolute(options.database) &&
270✔
236
                    options.database.substr(0, 1) !== "/" && // unix absolute
270✔
237
                    options.database.substr(1, 2) !== ":\\" && // windows absolute
270✔
238
                    options.database !== ":memory:"
214✔
239
                ) {
270✔
240
                    Object.assign(options, {
110✔
241
                        database: this.baseDirectory + "/" + options.database,
110✔
242
                    })
110✔
243
                }
110✔
244
            }
270✔
245
        })
398✔
246

398✔
247
        return connectionOptions
398✔
248
    }
398✔
249

26✔
250
    /**
26✔
251
     * Gets directory where configuration file should be located and configuration file name.
26✔
252
     */
26✔
253
    protected get baseFilePath(): string {
26✔
254
        return path.resolve(this.baseDirectory, this.baseConfigName)
2,740✔
255
    }
2,740✔
256

26✔
257
    /**
26✔
258
     * Gets directory where configuration file should be located.
26✔
259
     */
26✔
260
    protected get baseDirectory(): string {
26✔
261
        return this.options?.root ?? appRootPath.path
3,720!
262
    }
3,720✔
263

26✔
264
    /**
26✔
265
     * Gets configuration file name.
26✔
266
     */
26✔
267
    protected get baseConfigName(): string {
26✔
268
        return this.options?.configName ?? "ormconfig"
2,740✔
269
    }
2,740✔
270
}
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