Skip to content

feat(sqlite)!: drop support for sqlite3 and default to better-sqlite3#11836

Merged
pkuczynski merged 59 commits intomasterfrom
sqlite
Feb 24, 2026
Merged

feat(sqlite)!: drop support for sqlite3 and default to better-sqlite3#11836
pkuczynski merged 59 commits intomasterfrom
sqlite

Conversation

@pkuczynski
Copy link
Copy Markdown
Member

@pkuczynski pkuczynski commented Dec 8, 2025

Fixes #11718

alumni and others added 19 commits September 30, 2025 18:51
BREAKING CHANGE: TypeORM is now compiled for ECMAScript 2023, meaning old versions of Node.js are no longer supported. The minimum supported version of Node.js is 20.
* chore: disable eslint errors for chai assertions

* refactor: make `no-unused-expressions` an error and fix code
* feat: support explicit resource management in QueryRunner

* test: improve tests for explicit resource management

* feat: commit transaction on QueryRunner dispose
# Conflicts:
#	.github/workflows/commit-validation.yml
#	.github/workflows/preview.yml
#	.github/workflows/publish-package.yml
#	README-zh_CN.md
#	README_ko.md
#	docs/docs/query-runner.md
#	eslint.config.mjs
#	package-lock.json
#	package.json
#	src/commands/InitCommand.ts
#	src/driver/sqlserver/MssqlParameter.ts
#	test/utils/xfail.ts
# Conflicts:
#	package-lock.json
#	package.json
# Conflicts:
#	DEVELOPER.md
#	package-lock.json
#	package.json
#	test/github-issues/3387/issue-3387.ts
#	test/github-issues/3837/issue-3387.test.ts
#	test/github-issues/3837/issue-3837.ts
# Conflicts:
#	eslint.config.mjs
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 Security concerns

Sensitive information exposure:
The code contains hardcoded credentials in the template generation (lines 182-184, 192-194, 209-211, 228-230, 237-239). While these are template values for initialization and marked as "test" credentials, they could mislead developers into using weak default passwords in production environments. Consider adding comments warning users to change these credentials before deploying to production.

⚡ Recommended focus areas for review

Uninitialized Variable

The variable dbSettings is declared but not initialized before the switch statement. If the switch statement doesn't match any case (though a default is now added), TypeScript may not catch this at compile time, and it could lead to runtime errors when trying to access an undefined variable at line 263.

let dbSettings: string[]
Fall-through Behavior

The case for "sqlite" now falls through to "better-sqlite3" without an explicit return statement. While this appears intentional to map both to BetterSqlite3Driver, the lack of a break or comment indicating intentional fall-through could be confusing. Consider adding a comment to clarify this is intentional behavior.

case "sqlite":
case "better-sqlite3":
    return new BetterSqlite3Driver(connection)

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects bot commented Dec 8, 2025

PR Code Suggestions ✨

Latest suggestions up to 03d1c05

CategorySuggestion                                                                                                                                    Impact
Security
Parameterize interpolated SQL values

Replace direct string interpolation of relativePath in the SQL query with a
bound parameter to prevent SQL injection vulnerabilities.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts [180-192]

 const [database, tableName] = this.splitTablePath(tablePath)
 const relativePath = database
     ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
-    : undefined
+    : null
+
 const res = await this.query(
-    `SELECT ${
-        relativePath ? `'${relativePath}'` : null
-    } as database, * FROM ${this.escapePath(
+    `SELECT ? as database, * FROM ${this.escapePath(
         `${database ? `${database}.` : ""}sqlite_master`,
     )} WHERE "type" = '${tableOrIndex}' AND "${
         tableOrIndex === "table" ? "name" : "tbl_name"
     }" IN ('${tableName}')`,
+    [relativePath],
 )
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a potential SQL injection vulnerability and provides a secure fix by using query parameterization, which is a critical security best practice.

Medium
Possible issue
Prevent parameter normalization crashes

Add a check to ensure parameters is an array before calling .map() to avoid
runtime errors when it is undefined or not an array.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts [92-95]

-// better-sqlite3 cannot bind booleans, convert to 0/1
-const normalizedParameters = parameters.map((p) =>
-    typeof p === "boolean" ? (p ? 1 : 0) : p,
-)
+const normalizedParameters = Array.isArray(parameters)
+    ? parameters.map((p) => (typeof p === "boolean" ? (p ? 1 : 0) : p))
+    : parameters
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that parameters might not be an array, preventing a potential runtime error by adding a necessary guard clause.

Medium
Initialize config and validate input

Add a check to ensure the database argument is provided and initialize
dbSettings to an empty array to prevent potential runtime errors.

src/commands/InitCommand.ts [183-292]

 protected static getAppDataSourceTemplate(
     isEsm: boolean,
     database: string,
 ): string {
-    let dbSettings: string[]
+    if (!database) {
+        throw new TypeORMError(
+            `Missing required option: --database (e.g. "better-sqlite3")`,
+        )
+    }
+
+    let dbSettings: string[] = []
 
     switch (database) {
         case "mysql":
             dbSettings = [
                 'type: "mysql"',
                 'host: "localhost"',
                 "port: 3306",
                 'username: "test"',
                 'password: "test"',
                 'database: "test"',
             ]
             break
 
         case "mariadb":
             dbSettings = [
                 'type: "mariadb"',
                 'host: "localhost"',
                 "port: 3306",
                 'username: "test"',
                 'password: "test"',
                 'database: "test"',
             ]
             break
 
         case "better-sqlite3":
             dbSettings = [
                 'type: "better-sqlite3"',
                 'database: "database.sqlite"',
             ]
             break
 
         case "postgres":
             dbSettings = [
                 'type: "postgres"',
                 'host: "localhost"',
                 "port: 5432",
                 'username: "test"',
                 'password: "test"',
                 'database: "test"',
             ]
             break
 
         case "cockroachdb":
             dbSettings = [
                 'type: "cockroachdb"',
                 'host: "localhost"',
                 "port: 26257",
                 'username: "root"',
                 'password: ""',
                 'database: "defaultdb"',
             ]
             break
 
         case "mssql":
             dbSettings = [
                 'type: "mssql"',
                 'host: "localhost"',
                 'username: "sa"',
                 'password: "Admin12345"',
                 'database: "tempdb"',
             ]
             break
 
         case "oracle":
             dbSettings = [
                 'type: "oracle"',
                 'host: "localhost"',
                 'username: "system"',
                 'password: "oracle"',
                 "port: 1521",
                 'sid: "xe.oracle.docker"',
             ]
             break
 
         case "mongodb":
             dbSettings = ['type: "mongodb"', 'database: "test"']
             break
 
         case "spanner":
             dbSettings = [
                 'type: "spanner"',
                 'projectId: "test"',
                 'instanceId: "test"',
                 'databaseId: "test"',
             ]
             break
 
         default:
-            throw new Error(`Unknown database "${database}"`)
+            throw new TypeORMError(`Unknown database "${database}"`)
     }
 
     return `import "reflect-metadata"
 import { DataSource } from "typeorm"
 import { User } from "./entities/User${isEsm ? ".js" : ""}"
 
 export const AppDataSource = new DataSource({
 ${dbSettings.map((s) => `    ${s},`).join("\n")}
     synchronize: true,
     logging: false,
     entities: [User],
     migrations: [],
     subscribers: [],
 })
 `
 }

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies that the database argument could be undefined and improves robustness by adding a guard clause and initializing dbSettings.

Low
  • More

Previous suggestions

Suggestions up to commit 9aa2689
CategorySuggestion                                                                                                                                    Impact
Possible issue
Return consistent attached database identifier

In loadHashes, restore the database column to hold the database handle for
consistency, and add the file path in a new databasePath column if needed.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts [176-194]

 protected async loadTableRecords(
     tablePath: string,
     tableOrIndex: "table" | "index",
 ) {
     const [database, tableName] = this.splitTablePath(tablePath)
     const relativePath = database
         ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
         : undefined
+
     const res = await this.query(
         `SELECT ${
+            database ? `'${database}'` : null
+        } as database, ${
             relativePath ? `'${relativePath}'` : null
-        } as database, * FROM ${this.escapePath(
+        } as databasePath, * FROM ${this.escapePath(
             `${database ? `${database}.` : ""}sqlite_master`,
         )} WHERE "type" = '${tableOrIndex}' AND "${
             tableOrIndex === "table" ? "name" : "tbl_name"
         }" IN ('${tableName}')`,
     )
     return res
 }
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that the PR introduces an inconsistency by changing the value of the database column from the database handle to its file path, which could break downstream logic.

Medium
Suggestions up to commit 968bf5e
CategorySuggestion                                                                                                                                    Impact
Possible issue
Handle missing query parameters safely

Add a null check for the parameters variable before calling .map() to prevent
runtime errors when it is undefined.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts [90-95]

 const connection = this.driver.connection
 
+const parametersArray = parameters ?? []
+
 // better-sqlite3 cannot bind booleans, convert to 0/1
-const normalizedParameters = parameters.map((p) =>
+const normalizedParameters = parametersArray.map((p) =>
     typeof p === "boolean" ? (p ? 1 : 0) : p,
 )
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a potential runtime error where .map() would be called on an undefined value, as the parameters argument is optional, and provides a valid fix.

Medium
Align Node engine requirement

Update the engines.node field in package.json to >=20.0.0. This is necessary
because several updated dependencies in the lockfile now require Node.js version
20 or higher.

package.json [0]

+"engines": {
+  "node": ">=20.0.0"
+},
 "pnpm": {
   "onlyBuiltDependencies": [
     "better-sqlite3"
   ],
   "ignoredBuiltDependencies": [
     "@sap/hana-client",
     ...
   ]
 },
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that updated dependencies now require Node.js >= 20, which could break the build on older Node versions, and proposes a valid fix to enforce the new requirement in package.json.

Medium
Suggestions up to commit 032bd31
CategorySuggestion                                                                                                                                    Impact
Possible issue
Restore sqlite-family path normalization

Restore path normalization for all SQLite-family drivers by using
DriverUtils.isSQLiteFamily instead of checking only for better-sqlite3.

src/connection/ConnectionOptionsReader.ts [259-263]

 // make database path file in sqlite relative to package.json
-if (options.type === "better-sqlite3") {
+if (DriverUtils.isSQLiteFamily({ options } as any)) {
     if (
         typeof options.database === "string" &&
         !isAbsolute(options.database) &&
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a significant regression where path normalization for SQLite-family drivers was unintentionally removed, which could break existing configurations for drivers other than better-sqlite3.

Medium
Ensure Node version compatibility

Verify and align the project's supported Node.js version, as some updated
dependencies now require Node.js v20 or higher.

pnpm-lock.yaml [266-268]

+'@aws-sdk/client-rds-data@3.992.0':
+  resolution: {integrity: sha512-Fd5e3a+YItU4Ge1lhoGCZaJMEaRRHFO7wd/5ztBsLrmWHFndL8AD634DklVEfSYwZpKOjxm/fVDEjwDjUWPHQw==}
+  engines: {node: '>=20.0.0'}
 
-
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that updated dependencies now require Node.js v20, which may conflict with the project's supported versions, and advises the user to verify this.

Medium
Initialize template settings safely

Initialize the dbSettings variable to an empty array to prevent potential "used
before assigned" errors in case of future refactoring.

src/commands/InitCommand.ts [187-287]

-let dbSettings: string[]
+let dbSettings: string[] = []
 
 switch (database) {
     case "mysql":
         dbSettings = [
             'type: "mysql"',
             'host: "localhost"',
             "port: 3306",
             'username: "test"',
             'password: "test"',
             'database: "test"',
         ]
         break
     ...
     default:
         throw new Error(`Unknown database "${database}"`)
 }
 
 return `import "reflect-metadata"
 ...
 export const AppDataSource = new DataSource({
 ${dbSettings.map((s) => `    ${s},`).join("\n")}
     synchronize: true,
     logging: false,
     entities: [User],
Suggestion importance[1-10]: 3

__

Why: The suggestion is a good practice for robustness, but the current code is safe because the switch statement's default case throws an error, preventing any path where dbSettings would be used uninitialized.

Low
✅ Suggestions up to commit 3813364
CategorySuggestion                                                                                                                                    Impact
Possible issue
Align runtime with engine requirements

Verify that the project's supported Node.js version is compatible with the new
node: '>=20.0.0' engine requirement from updated dependencies.

pnpm-lock.yaml [266-268]

+'@aws-sdk/client-rds-data@3.992.0':
+  resolution: {integrity: sha512-Fd5e3a+YItU4Ge1lhoGCZaJMEaRRHFO7wd/5ztBsLrmWHFndL8AD634DklVEfSYwZpKOjxm/fVDEjwDjUWPHQw==}
+  engines: {node: '>=20.0.0'}
 
-
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that many updated @aws-sdk packages now require Node.js version 20 or higher, which is a potential breaking change for environments running on Node 18.

Medium
Prevent parameter normalization crashes
Suggestion Impact:The commit introduced `normalizedParameters` derived via `parameters.map(...)` and consistently used it for logging, broadcasting, execution, and error handling. However, it did not add the suggested `Array.isArray(parameters)` guard to prevent `.map()` crashes when `parameters` is not an array.

code diff:

+        // better-sqlite3 cannot bind booleans, convert to 0/1
+        const normalizedParameters = parameters.map((p) =>
+            typeof p === "boolean" ? (p ? 1 : 0) : p,
+        )
+
         const broadcasterResult = new BroadcasterResult()
 
-        this.driver.connection.logger.logQuery(query, parameters, this)
+        this.driver.connection.logger.logQuery(
+            query,
+            normalizedParameters,
+            this,
+        )
         this.broadcaster.broadcastBeforeQueryEvent(
             broadcasterResult,
             query,
-            parameters,
+            normalizedParameters,
         )
         const queryStartTime = Date.now()
 
@@ -102,7 +114,7 @@
             const result = new QueryResult()
 
             if (stmt.reader) {
-                const raw = stmt.all(...parameters)
+                const raw = stmt.all(...normalizedParameters)
 
                 result.raw = raw
 
@@ -110,7 +122,7 @@
                     result.records = raw
                 }
             } else {
-                const raw = stmt.run(...parameters)
+                const raw = stmt.run(...normalizedParameters)
                 result.affected = raw.changes
                 result.raw = raw.lastInsertRowid
             }
@@ -127,14 +139,14 @@
                 connection.logger.logQuerySlow(
                     queryExecutionTime,
                     query,
-                    parameters,
+                    normalizedParameters,
                     this,
                 )
 
             this.broadcaster.broadcastAfterQueryEvent(
                 broadcasterResult,
                 query,
-                parameters,
+                normalizedParameters,
                 true,
                 queryExecutionTime,
                 result.raw,
@@ -147,8 +159,13 @@
 
             return result
         } catch (err) {
-            connection.logger.logQueryError(err, query, parameters, this)
-            throw new QueryFailedError(query, parameters, err)
+            connection.logger.logQueryError(
+                err,
+                query,
+                normalizedParameters,
+                this,
+            )
+            throw new QueryFailedError(query, normalizedParameters, err)
         }

In BetterSqlite3QueryRunner.query, add a check to ensure parameters is an array
before calling .map() to prevent potential runtime errors.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts [104-107]

 // better-sqlite3 cannot bind booleans, convert to 0/1
-const normalizedParameters = parameters.map((p) =>
-    typeof p === "boolean" ? (p ? 1 : 0) : p,
-)
+const params = Array.isArray(parameters) ? parameters : []
+const normalizedParameters = params.some((p) => typeof p === "boolean")
+    ? params.map((p) => (typeof p === "boolean" ? (p ? 1 : 0) : p))
+    : params
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly identifies a potential runtime error if parameters is undefined and offers a robust solution, though the likelihood of this occurring is low given typical usage.

Low
Handle SQLite docker template explicitly
Suggestion Impact:The commit added an explicit "better-sqlite3" case in the switch, but it throws a TypeORMError ("SQLite does not require docker") rather than returning an empty string.

code diff:

+            case "better-sqlite3":
+                throw new TypeORMError(`SQLite does not require docker`)
+

In getDockerComposeTemplate, add an explicit case for better-sqlite3 to return
an empty string, rather than relying on the default case.

src/commands/InitCommand.ts [584-673]

 switch (database) {
     case "mysql":
         return `services:
 ...
 `
     case "cockroachdb":
         return `services:
 ...
 `
+    case "better-sqlite3":
+        return ``
     case "oracle":
         throw new TypeORMError(
             `You must set up the connection to Oracle manually.`
         )
 }
Suggestion importance[1-10]: 2

__

Why: The suggestion to add an explicit case for better-sqlite3 is redundant as the default case already correctly handles it by returning an empty string, making this a minor style improvement.

Low
General
Deduplicate duplicated dependency versions

Deduplicate the @aws-sdk/util-endpoints package by running a lockfile
normalization step to ensure a single, consistent version is used across the
project.

pnpm-lock.yaml [342-348]

-'@aws-sdk/util-endpoints@3.990.0':
-  resolution: {integrity: sha512-kVwtDc9LNI3tQZHEMNbkLIOpeDK8sRSTuT8eMnzGY+O+JImPisfSTjdh+jw9OTznu+MYZjQsv0258sazVKunYg==}
-  engines: {node: '>=20.0.0'}
-
 '@aws-sdk/util-endpoints@3.992.0':
   resolution: {integrity: sha512-FHgdMVbTZ2Lu7hEIoGYfkd5UazNSsAgPcupEnh15vsWKFKhuw6w/6tM1k/yNaa7l1wx0Wt1UuK0m+gQ0BJpuvg==}
   engines: {node: '>=20.0.0'}
Suggestion importance[1-10]: 5

__

Why: The suggestion correctly points out the duplication of the @aws-sdk/util-endpoints package, which is a valid concern for bundle size and consistency, and recommends deduplication.

Low
✅ Suggestions up to commit d4b4db4
CategorySuggestion                                                                                                                                    Impact
High-level
Justify and guide this breaking change
Suggestion Impact:The commit removes remaining references to the "sqlite" driver in DriverFactory (import, switch case, and allowed types), aligning with the suggested code-side cleanup, but it does not add the requested justification or migration guide.

code diff:

-import { SqliteDriver } from "./sqlite/SqliteDriver"
 import { CordovaDriver } from "./cordova/CordovaDriver"
 import { ReactNativeDriver } from "./react-native/ReactNativeDriver"
 import { NativescriptDriver } from "./nativescript/NativescriptDriver"
 import { SqljsDriver } from "./sqljs/SqljsDriver"
 import { MysqlDriver } from "./mysql/MysqlDriver"
 import { PostgresDriver } from "./postgres/PostgresDriver"
-import { ExpoDriverFactory } from "./expo/ExpoDriverFactory"
 import { AuroraMysqlDriver } from "./aurora-mysql/AuroraMysqlDriver"
 import { AuroraPostgresDriver } from "./aurora-postgres/AuroraPostgresDriver"
 import { Driver } from "./Driver"
@@ -19,6 +17,7 @@
 import { BetterSqlite3Driver } from "./better-sqlite3/BetterSqlite3Driver"
 import { CapacitorDriver } from "./capacitor/CapacitorDriver"
 import { SpannerDriver } from "./spanner/SpannerDriver"
+import { ExpoDriver } from "./expo/ExpoDriver"
 
 /**
  * Helps to create drivers.
@@ -26,6 +25,8 @@
 export class DriverFactory {
     /**
      * Creates a new driver depend on a given connection's driver type.
+     * @param connection DataSource instance.
+     * @returns Driver
      */
     create(connection: DataSource): Driver {
         const { type } = connection.options
@@ -40,7 +41,6 @@
                 return new SapDriver(connection)
             case "mariadb":
                 return new MysqlDriver(connection)
-            case "sqlite":
             case "better-sqlite3":
                 return new BetterSqlite3Driver(connection)
             case "cordova":
@@ -58,7 +58,7 @@
             case "mongodb":
                 return new MongoDriver(connection)
             case "expo":
-                return new ExpoDriverFactory(connection).create()
+                return new ExpoDriver(connection)
             case "aurora-mysql":
                 return new AuroraMysqlDriver(connection)
             case "aurora-postgres":
@@ -85,7 +85,6 @@
                     "postgres",
                     "react-native",
                     "sap",
-                    "sqlite",
                     "sqljs",
                     "spanner",
                 ])

The PR removes the sqlite3 driver, which is a significant breaking change. It
should include a justification for this removal and a migration guide for users
transitioning to better-sqlite3.

Examples:

src/driver/DriverFactory.ts [43]
            case "sqlite":
src/driver/sqlite/SqliteDriver.ts [1-230]

Solution Walkthrough:

Before:

// PR Description is empty

// src/driver/DriverFactory.ts
switch (connection.options.type) {
    // ...
    case "sqlite":
        return new SqliteDriver(connection)
    case "better-sqlite3":
        return new BetterSqlite3Driver(connection)
    // ...
}

// src/driver/sqlite/SqliteDriver.ts
// This file and its related files (options, query runner) exist.

After:

/*
PR Description:
# Breaking Change: Remove sqlite3 driver

This PR removes the `sqlite3` driver.

**Reasoning:**
The `better-sqlite3` driver offers superior performance and a simpler synchronous API, making it the recommended choice for new projects. To reduce maintenance overhead and streamline the codebase, we are deprecating and removing the older `sqlite3` driver.

**Migration Guide:**
1. Uninstall `sqlite3` and install `better-sqlite3`.
2. In your DataSource options, change `type: "sqlite"` to `type: "better-sqlite3"`.
*/

// src/driver/DriverFactory.ts
switch (connection.options.type) {
    // ...
    // The "sqlite" case is removed.
    case "better-sqlite3":
        return new BetterSqlite3Driver(connection)
    // ...
}
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a critical process issue: the PR introduces a major breaking change by removing the sqlite3 driver without any justification or migration path for users, which severely impacts the PR's quality.

High
Possible issue
Add missing dependency for sqlite initialization
Suggestion Impact:The sqlite case was removed from the dependency switch so it falls through to the better-sqlite3 case, ensuring better-sqlite3 is added to package.json for sqlite initialization.

code diff:

@@ -720,7 +745,6 @@
                 packageJson.dependencies["pg"] =
                     ourPackageJson.devDependencies.pg
                 break
-            case "sqlite":
             case "better-sqlite3":
                 packageJson.dependencies["better-sqlite3"] =
                     ourPackageJson.devDependencies["better-sqlite3"]

In updatePackageJson, make the sqlite case fall through to the better-sqlite3
case to ensure the correct dependency is added when initializing a project with
sqlite.

src/commands/InitCommand.ts [723-726]

     ... (clipped 101 lines)
                      ourPackageJson.devDependencies.pg
                  break
              case "sqlite":
--                packageJson.dependencies["sqlite3"] =
--                    ourPackageJson.devDependencies.sqlite3
--                break
              case "better-sqlite3":
                  packageJson.dependencies["better-sqlite3"] =
                      ourPackageJson.devDependencies["better-sqlite3"]
  ... (clipped 39 lines)
Suggestion importance[1-10]: 9

__

Why: The PR correctly updates the init command to generate a better-sqlite3 configuration for the sqlite option, but it fails to add the corresponding better-sqlite3 dependency to package.json, which would lead to a broken project.

High

@alumni alumni mentioned this pull request Dec 8, 2025
19 tasks
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
 let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Legacy sqlite error unclear 🐞 Bug ✧ Quality ⭐ New
Description
Existing projects with type: "sqlite" in ormconfig/config code will now fail at runtime, but the
thrown error is generic and doesn’t explicitly tell users that sqlite was removed in favor of
better-sqlite3, increasing upgrade friction and support load.
Code

src/driver/DriverFactory.ts[R41-46]

                return new SapDriver(connection)
            case "mariadb":
                return new MysqlDriver(connection)
-            case "sqlite":
-                return new SqliteDriver(connection)
            case "better-sqlite3":
                return new BetterSqlite3Driver(connection)
            case "cordova":
Evidence
DriverFactory no longer has a case "sqlite", and DatabaseType no longer allows the "sqlite"
literal. When an old config still uses "sqlite", the code falls into the default branch and throws
MissingDriverError, whose message only lists supported drivers without a targeted migration hint.

src/driver/DriverFactory.ts[31-46]
src/driver/types/DatabaseType.ts[4-22]
src/error/MissingDriverError.ts[6-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The PR removes support for `type: "sqlite"`. Existing JS/JSON configs will now throw `MissingDriverError`, but the message does not explicitly tell users what to change (e.g., “use `better-sqlite3` instead”), which makes upgrades noisier than necessary.

### Issue Context
This is a breaking change and it’s fine to fail fast; the improvement here is making the failure actionable and self-explanatory.

### Fix Focus Areas
- src/driver/DriverFactory.ts[31-91]
- src/error/MissingDriverError.ts[6-13]

### Suggested approach
Option A (most direct):
- Add explicit handling in `DriverFactory.create`:
 - `case "sqlite":`
 - `case "sqlite3":`
 - throw a `TypeORMError` (or a dedicated error) with a message like: `Driver "sqlite" was removed. Use "better-sqlite3" instead.`

Option B (centralized):
- Enhance `MissingDriverError` to detect `driverType` values like `sqlite`/`sqlite3` and append a migration hint to the message.

Either option keeps the breaking behavior while making the runtime error immediately actionable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Unescaped filepath in SQL 🐞 Bug ⛨ Security ⭐ New
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

        const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
        const res = await this.query(
            `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
            } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).

## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.

## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

### Suggested approach
- Change the query to use bound parameters for the constant string literal:
 - e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 3. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

…n upgrade guide

The file-open-flags test used sqlite3-specific C-level open flags which
better-sqlite3 does not support. The test was rewritten to test enableWAL
but enable-wal.test.ts already covers this, so remove the duplicate.
Also document the flags option removal in the 1.0 upgrade guide.
Move boolean-to-integer normalization before logQuery and
broadcastBeforeQueryEvent so that logged/emitted parameters
match what better-sqlite3 actually executes.
Add choices constraint to the yargs --db option so unsupported
database values are rejected before handler() runs, preventing
partially-initialized project directories.
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (12) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

      const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
      const res = await this.query(
          `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
          } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (7)
4. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 5. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 7. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

       const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
       const res = await this.query(
           `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
           } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 10. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

11. Init leaves partial project 🐞 Bug ⛯ Reliability ⭐ New
Description
typeorm init --docker --database better-sqlite3 now throws, but only after some files (e.g.,
package.json) have already been written, leaving users with a partially generated project directory.
This makes init non-atomic and can confuse automation/CI scripts.
Code

src/commands/InitCommand.ts[R647-648]

            case "better-sqlite3":
-                return `services:
-`
+                throw new TypeORMError(`SQLite does not require docker`)
Evidence
InitCommand creates files (starting with package.json) before attempting to generate docker-compose;
with this PR, docker-compose generation now throws for better-sqlite3, so the command fails after
side effects have already occurred.

src/commands/InitCommand.ts[63-84]
src/commands/InitCommand.ts[646-652]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`typeorm init` writes `package.json` before generating `docker-compose.yml`. After this PR, `getDockerComposeTemplate("better-sqlite3")` throws, so `typeorm init --docker --database better-sqlite3` can fail after partially creating a project.

## Issue Context
The new behavior is correct to prevent generating a meaningless docker compose for SQLite, but the error should be raised *before* creating files (or the command should gracefully skip docker generation).

## Fix Focus Areas
- src/commands/InitCommand.ts[63-84]
- src/commands/InitCommand.ts[594-652]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. Legacy sqlite error unclear 🐞 Bug ✓ Correctness
Description
Existing projects with type: "sqlite" in ormconfig/config code will now fail at runtime, but the
thrown error is generic and doesn’t explicitly tell users that sqlite was removed in favor of
better-sqlite3, increasing upgrade friction and support load.
Code

src/driver/DriverFactory.ts[R41-46]

               return new SapDriver(connection)
           case "mariadb":
               return new MysqlDriver(connection)
-            case "sqlite":
-                return new SqliteDriver(connection)
           case "better-sqlite3":
               return new BetterSqlite3Driver(connection)
           case "cordova":
Evidence
DriverFactory no longer has a case "sqlite", and DatabaseType no longer allows the "sqlite"
literal. When an old config still uses "sqlite", the code falls into the default branch and throws
MissingDriverError, whose message only lists supported drivers without a targeted migration hint.

src/driver/DriverFactory.ts[31-46]
src/driver/types/DatabaseType.ts[4-22]
src/error/MissingDriverError.ts[6-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The PR removes support for `type: "sqlite"`. Existing JS/JSON configs will now throw `MissingDriverError`, but the message does not explicitly tell users what to change (e.g., “use `better-sqlite3` instead”), which makes upgrades noisier than necessary.
### Issue Context
This is a breaking change and it’s fine to fail fast; the improvement here is making the failure actionable and self-explanatory.
### Fix Focus Areas
- src/driver/DriverFactory.ts[31-91]
- src/error/MissingDriverError.ts[6-13]
### Suggested approach
Option A (most direct):
- Add explicit handling in `DriverFactory.create`:
- `case "sqlite":`
- `case "sqlite3":`
- throw a `TypeORMError` (or a dedicated error) with a message like: `Driver "sqlite" was removed. Use "better-sqlite3" instead.`
Option B (centralized):
- Enhance `MissingDriverError` to detect `driverType` values like `sqlite`/`sqlite3` and append a migration hint to the message.
Either option keeps the breaking behavior while making the runtime error immediately actionable.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Copy link
Copy Markdown
Collaborator

@alumni alumni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! I left a few comments :)

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (33) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 2. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

     const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
     const res = await this.query(
         `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
         } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (27)
4. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 5. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 7. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

      const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
      const res = await this.query(
          `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
          } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 10. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 12. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

    const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
    const res = await this.query(
        `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
        } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


✅ 15. getDockerComposeTemplate missing better-sqlite3 case 🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
[test/functional/sqlite/file-open-flags.test.ts[40-43]](https://github.com/type...

# Conflicts:
#	docs/docs/guides/8-migration-v1.md
#	package.json
#	pnpm-lock.yaml
#	sample/sample33-custom-repository/data-source.ts
#	src/data-source/DataSourceOptions.ts
#	src/driver/DriverFactory.ts
#	src/driver/sqlite/SqliteDataSourceOptions.ts
#	src/driver/sqlite/SqliteDriver.ts
#	src/driver/sqlite/SqliteQueryRunner.ts
#	src/driver/types/DatabaseType.ts
@pkuczynski pkuczynski requested a review from alumni February 23, 2026 23:29
@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

break
case "sqlite":
packageJson.dependencies["sqlite3"] =
ourPackageJson.devDependencies.sqlite3
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Funny thing, loading package.json did not work on certain configurations (e.g. PnP, default in yarn) + now we also don't have devDependencies because they get removed during the build. We'll figure out something, but not right now (or it would be just for a few weeks).

Copy link
Copy Markdown
Collaborator

@alumni alumni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'm happy to get rid of this driver.

There's a duplicate test (that runs even when better-sqlite3 tests are disabled), could you remove it please?

I'll approve now so you can merge faster after that change.

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (50) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Test uses unsupported flags option🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

   const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
   const res = await this.query(
       `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
       } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (42)
4. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

    const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
    const res = await this.query(
        `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
        } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


12. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. Unescaped filepath in SQL 🐞 Bug ⛨ Security
Description
BetterSqlite3QueryRunner interpolates an attached database relative filepath into a SQL string
literal without escaping/binding. A filepath containing a single-quote can break schema loading
queries and could allow SQL manipulation if the attached path is attacker-controlled.
Code

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[R180-187]

  const [database, tableName] = this.splitTablePath(tablePath)
+        const relativePath = database
+            ? this.driver.getAttachedDatabasePathRelativeByHandle(database)
+            : undefined
  const res = await this.query(
      `SELECT ${
-                database ? `'${database}'` : null
+                relativePath ? `'${relativePath}'` : null
      } as database, * FROM ${this.escapePath(
Evidence
The attached database "relativePath" comes from user-supplied metadata/config (the decorated
database argument), is stored unescaped, and is then injected into a SQL string using
'${relativePath}', which will break if it contains ' and is avoidable via parameter binding.

src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`BetterSqlite3QueryRunner.loadTableRecords` currently injects an attached database relative filepath into a SQL string literal via template interpolation (`'${relativePath}'`). Since the attached path ultimately comes from user-supplied metadata/config, a filepath containing `'` will break the query (and could enable SQL manipulation).
## Issue Context
- `BetterSqlite3Driver.buildTableName` stores the decorated `database` string as `attachFilepathRelative`.
- `AbstractSqliteDriver.getAttachedDatabasePathRelativeByHandle` returns that string.
- `BetterSqlite3QueryRunner.loadTableRecords` inserts it directly into a SQL string.
## Fix Focus Areas
- src/driver/better-sqlite3/BetterSqlite3QueryRunner.ts[176-193]
- src/driver/better-sqlite3/BetterSqlite3Driver.ts[81-109]
- src/driver/sqlite-abstract/AbstractSqliteDriver.ts[297-307]
### Suggested approach
- Change the query to use bound parameters for the constant string literal:
- e.g., `SELECT ? as database, * FROM ... WHERE ...` with `[relativePath ?? null]`
- (Optional but recommended) also bind `tableName` instead of interpolating into `IN ('${tableName}')` to avoid similar quoting issues.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3ConnectionOptions`; the test provides neither that option nor any other
mechanism to enable WAL, so the assertion journal_mode = 'wal' will fail.

test/functional/sqlite/file-open-flags.test.ts[9-30]
src/driver/better-sqlite3/BetterSqlite3Driver.ts[127-142]
src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
test/functional/sqlite/file-open-flags.test.ts[40-43]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The test `file-open-flags.test.ts` was migrated from `sqlite3` to `better-sqlite3` but still passes a `flags` option via `driverSpecific`. `better-sqlite3` does not accept a `flags` constructor parameter — it is a `sqlite3`-specific API. The flags are silently ignored. Additionally, the test asserts `journal_mode = 'wal'`, but WAL mode in `better-sqlite3` is only enabled via `enableWAL: true` in the DataSource options, not through C-level open flags. The test will fail.
## Issue Context
- `better-sqlite3` constructor accepts: `readonly`, `fileMustExist`, `timeout`, `verbose`, `nativeBinding` — no `flags`.
- WAL mode is enabled via `enableWAL: true` in `BetterSqlite3ConnectionOptions`.
- The original test was validating that `sqlite3`'s `OPEN_URI | OPEN_SHAREDCACHE | OPEN_READWRITE | OPEN_CREATE` flags worked. This concept does not translate to `better-sqlite3`.
## Fix Focus Areas
- test/functional/sqlite/file-open-flags.test.ts[1-45]
- src/driver/better-sqlite3/BetterSqlite3ConnectionOptions.ts[74-78]
Rewrite the test to use `enableWAL: true` (via `driverSpecific`) on a regular file-based database and assert `journal_mode = 'wal'`, removing the C-level flag constants entirely.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. getDockerComposeTemplate missing better-sqlite3 case🐞 Bug ✓ Correctness
Description
The PR removes the case "sqlite": case "better-sqlite3": block from getDockerComposeTemplate()
without adding a replacement for better-sqlite3. The switch falls through to return "", so
running typeorm init --db better-sqlite3 --docker writes an empty (invalid) docker-compose.yml
file.
Code

src/commands/InitCommand.ts[L601-604]

-            case "sqlite":
-            case "better-sqlite3":
-                return `services:
`
Evidence
The diff removes case "sqlite": case "better-sqlite3": return \services:\n\`` without adding a
replacement case "better-sqlite3": branch. InitCommand.handler() unconditionally calls
getDockerComposeTemplate(database) and writes the result to docker-compose.yml when --docker
is passed. With no matching case, the function returns "" for better-sqlite3, producing an empty
file that is not a valid docker-compose document.

src/commands/InitCommand.ts[68-73]
src/commands/InitCommand.ts[583-676]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `getDockerComposeTemplate()` method in `InitCommand` has no `case "better-sqlite3":` branch after the PR removed the combined `case "sqlite": case "better-sqlite3":` block. The function returns an empty string `""` for `better-sqlite3`, causing `typeorm init --db better-sqlite3 --docker` to write an empty, invalid `docker-compose.yml`.
## Issue Context
- `better-sqlite3` is a file-based database and requires no Docker service, so the correct return value is a minimal `"services:\n"` (valid docker-compose YAML with no services).
- The `getAppDataSourceTemplate()` method correctly added a `default: throw new Error(...)` guard, but `getDockerComposeTemplate()` was not updated consistently.
- `InitCommand.handler()` unconditionally writes the result of `getDockerComposeTemplate()` to disk when `--docker` is passed.
## Fix Focus Areas
- src/commands/InitCommand.ts[583-676]
Add the following case inside the switch statement, before the `case "oracle":` block:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. Test uses unsupported flags option 🐞 Bug ✓ Correctness
Description
The file-open-flags.test.ts was converted from sqlite3 to better-sqlite3 but passes a flags
option that better-sqlite3 does not support. The flags are silently ignored by the driver, and the
test assertion journal_mode = 'wal' will fail because WAL mode in better-sqlite3 requires
enableWAL: true, not C-level open flags.
Code

test/functional/sqlite/file-open-flags.test.ts[R9-17]

+
+// Standard SQLite C API open flag constants (from sqlite3.h)
+const SQLITE_OPEN_READWRITE = 0x00000002
+const SQLITE_OPEN_CREATE = 0x00000004
+const SQLITE_OPEN_URI = 0x00000040
+const SQLITE_OPEN_SHAREDCACHE = 0x00020000
describe("sqlite driver > file open flags", () => {
let connections: DataSource[]
Evidence
1. BetterSqlite3ConnectionOptions has no flags field — only readonly, fileMustExist,
timeout, verbose, nativeBinding, enableWAL, etc. 2.
BetterSqlite3Driver.createDatabaseConnection() explicitly destructures only known options and
never reads flags, so the value is silently dropped. 3. WAL mode is only enabled via `enableWAL:
true in BetterSqlite3Connec...

@pkuczynski pkuczynski merged commit 3100606 into master Feb 24, 2026
68 checks passed
@pkuczynski pkuczynski deleted the sqlite branch February 24, 2026 01:58
@michaelbromley
Copy link
Copy Markdown
Member

Great work @pkuczynski 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

node-sqlite3 maintenance concerns and path forward

5 participants