{"_id":"@benjosivo/mysql","_rev":"7-85a52dc4899f175f6821edff13ba4328","name":"@benjosivo/mysql","dist-tags":{"latest":"1.3.2"},"versions":{"1.0.3":{"name":"@benjosivo/mysql","version":"1.0.3","license":"MIT","_id":"@benjosivo/mysql@1.0.3","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"dist":{"shasum":"e49318fdd3b8bb70376bd6c174e4ed6a458503f1","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.0.3.tgz","fileCount":4,"integrity":"sha512-kVmLc82OtmtBBoCryHnLzh28kqCZsA0kUna4qEhf4VT3+H4t4BxFyOd6jYyn6J0QnJQGpYi7iTJzX9P+m0ehNA==","signatures":[{"sig":"MEUCIQDiTL0AfKERBNsDB+U/22Ba6mpm+c4dScvA337S5qRGUwIgCnKhT3qMCmJMuqhWsAOwE93pxnYi6z3LQJsfA0jwSkQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23737},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"391177f3e5666d393eccbbd099d6a6a1dfeef5d9","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"_npmVersion":"11.14.0","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.0.3_1785845506131_0.22831931942402872","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@benjosivo/mysql","version":"1.0.4","license":"MIT","_id":"@benjosivo/mysql@1.0.4","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"dist":{"shasum":"245543dbe81a498d91df0ff9d97e9cc04db6b434","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.0.4.tgz","fileCount":4,"integrity":"sha512-xJ+0UpZZP34aw+LpwcAovMFOtyXTIS9XdT3ocakhJUxo0gTod+w4mu8BDl6rEvRVJ1v6JikI9X5P0mDK+l6EpA==","signatures":[{"sig":"MEYCIQD35zCY7oHQ/pAe8xUaWaaeFqPgQfiXAGkQ2vPsvYLVCQIhANRxCzNIhwhxTKBkS7afk2FuaqxJvDTmnVC2xjDpINZJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21684},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"1727a67cbfbb25493c690a7405abbf3a87a1c803","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"_npmVersion":"11.14.0","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.0.4_1785846118973_0.6969745462519961","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@benjosivo/mysql","version":"1.2.2","license":"MIT","_id":"@benjosivo/mysql@1.2.2","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"homepage":"https://github.com/benjosivo/mysql#readme","bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"dist":{"shasum":"fc60158734dfe5dc2796c39a0e80e9ce19640e5e","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.2.2.tgz","fileCount":4,"integrity":"sha512-QwrFz2iJrsmYPAkrZvmzO8dn/ku2KI1kAWvhqVjyQd4VSP9FdDLPkMhH0MpmxWYIjTOlV+a8XSFQyUz5PfjUNg==","signatures":[{"sig":"MEQCIBhVx4E9HqWpMGgpLIzlzKpvjpLLVv7Zv2DeYY00sIEqAiA2f1nTn1pa0Ia19zvR6YGJ4vrGYk5cQOi3CPIAtotHtA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26046},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"aece97e02539f1551f6a11e7ced43463ea002dea","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"_npmVersion":"12.0.2","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.2.2_1787832338280_0.4083067125389115","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@benjosivo/mysql","version":"1.2.3","license":"MIT","_id":"@benjosivo/mysql@1.2.3","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"homepage":"https://github.com/benjosivo/mysql#readme","bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"dist":{"shasum":"04773ced7f22853eb8840ccfbce4363d877b5efb","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.2.3.tgz","fileCount":4,"integrity":"sha512-JtZQcVpZzAjcaaTEl9guBOaGRm4ElT+akzSPKVNvXHCFqV4rMivOiuYWOKyuzEteQiGNKcQeqsgTQs88LAufYA==","signatures":[{"sig":"MEUCIQDcvKfHAqEIUnYbPjEjLvkHwSe8UD8rwa+2xn4jEYwbkgIgBzuNHKlAa80+RKQ4OAS0If97gAAPmV8Rh+Ldy8ts0i4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":26046},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"0f4214c1ed588bfcc527570d7c8ec6e1d1571499","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"_npmVersion":"12.0.2","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.2.3_1787833473392_0.7442056897910645","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@benjosivo/mysql","version":"1.3.0","license":"MIT","_id":"@benjosivo/mysql@1.3.0","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"homepage":"https://github.com/benjosivo/mysql#readme","bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"dist":{"shasum":"c589592269a38352f1767914679677063b332f2b","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.3.0.tgz","fileCount":4,"integrity":"sha512-ackgmLXDX3SIcvDalLU4XaMK5tZSW8ZN8WIkGUwB65miFMwDxA9vX8nZUiuOSqyes/2FXb4jTB1GVUO/APRriQ==","signatures":[{"sig":"MEYCIQDwn7WHxnoRTM44AcFEfgeHhZZym7oZpqWN57Mt7MK0BAIhALThjUErSSSsi4gIuoEVOO+27VOkwN+0Aksdkqsnlqdd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45368},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"90d437ebacb686fb6d9ee7451bcc38fb178146cd","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"_npmVersion":"12.0.2","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.3.0_1788420915630_0.4088580116029461","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@benjosivo/mysql","version":"1.3.1","license":"MIT","_id":"@benjosivo/mysql@1.3.1","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"homepage":"https://github.com/benjosivo/mysql#readme","bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"dist":{"shasum":"6e60a78ae366b290e7ef3c1db6cf2ca27079d898","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.3.1.tgz","fileCount":4,"integrity":"sha512-cJjjpoheomfCDtwwkc4HjI145afYhogh3TBgHLNjugh5udm7ud37Fv6L5IgpwWCr3eo/y70YQh5j9frvqX6EFw==","signatures":[{"sig":"MEQCIC3PSCdiaBhFh81v51cBREGOFmtaCNpEmr7QRD584+atAiBPp42OaHpkB9RluDZm7RsvcDNT9OPUdLNyIEO4uMTnrA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQD5qGn5V0EUctnB0jnroyFUIfBQWQlcX1BkO5rt60xQzgIgIrOC6pOi2TAx1jTxtd4PfH8QTSkAsRvv/DbrVNWDsA4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":45407},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"b6b4404e210f102e77744425b93c8ad244b673bf","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"_npmVersion":"12.0.2","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"tmp":"tmp/mysql_1.3.1_1788850921739_0.3713396921967145","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"_id":"@benjosivo/mysql@1.3.2","bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"dist":{"shasum":"268a465852f3acef7c6c42a9431d5fe4d9343ce9","tarball":"https://registry.npmjs.org/@benjosivo/mysql/-/mysql-1.3.2.tgz","fileCount":4,"integrity":"sha512-LP8woNGE0sk5uVaIQiyuG+ec6DfLo7BECLiDy/ooS2iAITuhjWlEk1y2sluyC6TGiotpMVdWkldSwlC7D1XhIw==","signatures":[{"sig":"MEUCIEtMh5uVIYIGGp0lb9FtaPpb1blpkExCz5oQbbY8s3OVAiEAiqLb8cCEqvklw63hXmoC840sMKJJL0IIqKHWSJPIszk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDb6iuc8H5FKOXa4oZrlKSd/FuKeo/GfnFBnqIXq+GY0gIhAI2HtCXM9wzsOKIMQAXiVHOAobWgu/WZWE6ydrZn927u"}],"unpackedSize":45407},"main":"dist/index.js","name":"@benjosivo/mysql","types":"dist/index.d.ts","gitHead":"e21ec822389250d796e7646632cc41acca1eb133","license":"MIT","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"version":"1.3.2","_npmUser":{"name":"benjosivo","email":"macklem75007@gmail.com"},"homepage":"https://github.com/benjosivo/mysql#readme","repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"_npmVersion":"12.0.2","description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","directories":{},"maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"_nodeVersion":"24.15.0","dependencies":{"mysql2":"^3.x","node-sql-parser":"^5.4.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mysql_1.3.2_1788851053135_0.22951084572819758"}}},"time":{"created":"2026-08-04T12:11:45.989Z","modified":"2026-09-08T07:04:13.392Z","1.0.3":"2026-08-04T12:11:46.274Z","1.0.4":"2026-08-04T12:21:59.134Z","1.2.2":"2026-08-27T12:05:38.426Z","1.2.3":"2026-08-27T12:24:33.543Z","1.3.0":"2026-09-03T07:35:15.776Z","1.3.1":"2026-09-08T07:02:01.838Z","1.3.2":"2026-09-08T07:04:13.219Z"},"bugs":{"url":"https://github.com/benjosivo/mysql/issues"},"license":"MIT","homepage":"https://github.com/benjosivo/mysql#readme","repository":{"url":"git+https://github.com/benjosivo/mysql.git","type":"git"},"description":"Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular en","maintainers":[{"name":"benjosivo","email":"macklem75007@gmail.com"}],"readme":"# @benjosivo/mysql\r\n\r\nShared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transaction helpers) for use across multiple projects. Nothing connects until you call `init()` — the package has no side effects at import time and no dependency on any particular env var naming.\r\n\r\n## Install\r\n\r\n```\r\nnpm install @benjosivo/mysql\r\n```\r\n\r\n## Usage\r\n\r\n```ts\r\nimport { init, executeMySQLQuery, closeMySQLConnection } from '@benjosivo/mysql';\r\n\r\nawait init({\r\n    host: process.env.DB_HOST!,\r\n    user: process.env.DB_USER!,\r\n    password: process.env.DB_PASSWORD!,\r\n    database: process.env.DB_NAME!,\r\n    onError: (error, context) => myLogger.error(context, error), // optional, defaults to console.error\r\n});\r\n\r\nconst rows = await executeMySQLQuery('SELECT * FROM users WHERE id = ?', [userId]);\r\n\r\n// on shutdown\r\nawait closeMySQLConnection();\r\n```\r\n\r\nCall `init()` once per process, at startup. Each consuming project supplies its own credentials and (optionally) its own error reporting — this package has no opinion on either.\r\n\r\n### Config\r\n\r\n| Field | Required | Default | Description |\r\n|---|---|---|---|\r\n| `host`, `user`, `password`, `database` | yes | — | MySQL connection details |\r\n| `waitForConnections` | no | `true` | passed through to `mysql2` pool |\r\n| `connectionLimit` | no | `50` | passed through to `mysql2` pool |\r\n| `queueLimit` | no | `0` | passed through to `mysql2` pool |\r\n| `multipleStatements` | no | `true` | passed through to `mysql2` pool |\r\n| `staleTransactionMs` | no | `300000` (5 min) | a transaction with no statement activity for this long is auto rolled back |\r\n| `defaultQueryTimeoutMs` | no | — (off) | default per-statement timeout; overridable per call with `timeoutMs` |\r\n| `onError` | no | `console.error` | called with `(error, context)` whenever the client can't throw the error directly (e.g. background retry loops) |\r\n\r\nCalling `init()` again (e.g. to reconfigure) closes the previous pool first.\r\n\r\n### Queries\r\n\r\n```ts\r\nexecuteMySQLQuery3<T>({ query, values?, connKey?, returnFieldTypes?, returnListTables?, timeoutMs? })\r\n```\r\n\r\n**Preferred for new code.** Always resolves to a wrapper — it never throws and never returns\r\nbare rows, so every result is safe to inspect before use:\r\n\r\n```ts\r\nconst res = await executeMySQLQuery3<User[]>({ query: 'SELECT * FROM users WHERE id = ?', values: [userId] });\r\n\r\nif (!res.ok) {\r\n    // res.error is always a non-empty string\r\n    logger.error(res.error, res.code, res.errno, res.sqlState);\r\n    return;\r\n}\r\n\r\nres.rows[0].email; // narrowed by `ok` — TypeScript knows rows is present\r\n```\r\n\r\n`T` types the rows: `User[]` for a SELECT, `ResultSetHeader` for an INSERT/UPDATE. It defaults to\r\n`any`, so untyped calls keep working.\r\n\r\n| On success | On failure |\r\n|---|---|\r\n| `ok: true` | `ok: false` |\r\n| `rows: T` | `error: string` (never empty), `code?`, `errno?`, `sqlState?`, `cause?` |\r\n| `fieldsType: []` unless `returnFieldTypes` | `stage`: which step failed (`execute`, `transaction-lookup`, `procedure`, …) |\r\n| `tables: []` unless `returnListTables` | `values`: the parameters that were sent |\r\n| `connKey: string \\| null` | `connKey: string \\| null` |\r\n\r\nBecause the union is discriminated on `ok`, TypeScript will not let you read `rows` off a result\r\nyou haven't checked.\r\n\r\n#### Retries\r\n\r\nOnly *transient* failures are retried (up to 5 attempts, with a backoff): deadlocks, lock timeouts,\r\nlost connections, and a server that is out of connections. Deterministic failures — duplicate key,\r\nbad syntax, constraint violations, unknown column, access denied — are returned on the **first**\r\nattempt, since re-sending them can only produce the same error.\r\n\r\n#### Timeouts\r\n\r\n`timeoutMs` (or `defaultQueryTimeoutMs` in the config) bounds a statement, covering both the wait\r\nfor a pooled connection and the query itself. On expiry the statement is aborted server-side with\r\n`KILL QUERY` so it stops consuming resources, and the failure comes back as\r\n`{ ok: false, code: 'ETIMEDOUT' }`. Timed-out statements are never retried — a killed write must\r\nnot be silently re-applied.\r\n\r\n```ts\r\nconst res = await executeMySQLQuery3({ query: 'SELECT ...', values, timeoutMs: 10_000 });\r\n```\r\n\r\n#### Legacy shape\r\n\r\n```ts\r\nexecuteMySQLQuery(query, values?, returnFieldTypes?, connKey?, timeoutMs?)\r\nexecuteMySQLQuery2({ query, values?, connKey?, returnFieldTypes?, returnListTables?, timeoutMs? })\r\n```\r\n\r\nUnchanged: these return the rows directly on success (or `{ rows, fieldsType, connKey, tables }`\r\nwhen a transaction or extra metadata was requested), and `{ error, values, connKey }` on failure\r\ninstead of throwing. Failures now also carry `code`, `errno` and `sqlState` alongside the message.\r\nThey share the retry, timeout and transaction handling described above; `executeMySQLQuery2` is a\r\nthin adapter over `executeMySQLQuery3`.\r\n\r\n### Statements prepared statements can't run\r\n\r\n`executeMySQLQuery` uses `execute()` (MySQL's prepared-statement protocol), and MySQL rejects a\r\nnumber of statements there with *\"This command is not supported in the prepared statement protocol\r\nyet\"* — `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, and so on. For those,\r\nuse `runMySQLQuery`, which goes through `query()` (text protocol) instead:\r\n\r\n```ts\r\nimport { runMySQLQuery } from '@benjosivo/mysql';\r\n\r\nawait runMySQLQuery(\"SET GLOBAL general_log = 'OFF'\");\r\n\r\n// placeholders still work — mysql2 escapes and interpolates them client-side\r\nawait runMySQLQuery('SET GLOBAL general_log = ?', ['OFF']);\r\n\r\n// optionally run inside an existing transaction\r\nawait runMySQLQuery('SELECT * FROM users WHERE id = ?', [userId], connKey);\r\n```\r\n\r\n```ts\r\nrunMySQLQuery(query, values?, connKey?, timeoutMs?)\r\n```\r\n\r\nSame result shape as `executeMySQLQuery`: rows on success, `{ error, values, connKey }` on failure\r\n(with `code`/`errno`/`sqlState` when MySQL supplied them).\r\nIt's deliberately simple — no deadlock/lock-timeout retry — so prefer `executeMySQLQuery` for\r\nregular application queries and keep this one for statements the prepared-statement protocol\r\nrefuses.\r\n\r\n### Transactions\r\n\r\n```ts\r\nconst opened = await executeMySQLQuery3({ query: 'INSERT ...', values, connKey: true });\r\nif (!opened.ok) return opened.error;\r\n\r\nawait executeMySQLQuery3({ query: 'UPDATE ...', values, connKey: opened.connKey }); // same transaction\r\n\r\nawait connectionCommit(opened.connKey!);\r\n// or: await connectionRollback(opened.connKey!);\r\n```\r\n\r\nA transaction is retired as soon as it can no longer be used — MySQL rolled it back after a\r\ndeadlock, its connection was lost, or the background sweep found it idle. Its connection is\r\nreleased immediately, and any later use reports *why*:\r\n\r\n```ts\r\n// Transaction <key> is no longer usable: MySQL rolled it back after a deadlock\r\n```\r\n\r\n`connectionRollback` on a transaction that was already retired succeeds (there is nothing left to\r\nundo); `connectionCommit` reports an error, because the data did not make it. Both always free the\r\nconnection, even if the COMMIT or ROLLBACK itself fails.\r\n\r\n`staleTransactionMs` measures **idle** time: a transaction is swept only when no statement has run\r\non it for that long, so a long-running but active transaction is left alone.\r\n\r\n### Shutdown\r\n\r\n```ts\r\nawait closeMySQLConnection();\r\n```\r\n\r\nRolls back any open transactions, ends the pool, and stops the background sweep. Safe to call even if `init()` was never called.\r\n","readmeFilename":"README.md"}