@benjosivo/mysql 1.0.3 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -36
- package/dist/index.d.ts +22 -0
- package/dist/index.js +44 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -4,46 +4,10 @@ Shared MySQL client (pooling, automatic retry on deadlock/lock-timeout, transact
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
This package is published to **GitHub Packages**, not the public npm registry, so every machine needs a one-time setup before `npm install` will work — even though the repo and package are public. GitHub Packages never allows anonymous installs; a valid GitHub token is always required.
|
|
8
|
-
|
|
9
|
-
### One-time setup (per machine)
|
|
10
|
-
|
|
11
|
-
1. **Create a GitHub Personal Access Token.**
|
|
12
|
-
GitHub → click your avatar → **Settings** → **Developer settings** → **Personal access tokens** → **Tokens (classic)** → **Generate new token (classic)**.
|
|
13
|
-
Scope needed: **`read:packages`**. Copy the token — GitHub only shows it once.
|
|
14
|
-
|
|
15
|
-
2. **Add two lines to your global npm config.**
|
|
16
|
-
Find the file path:
|
|
17
|
-
```
|
|
18
|
-
npm config get globalconfig
|
|
19
|
-
```
|
|
20
|
-
It's typically `C:\Users\<you>\AppData\Roaming\npm\etc\npmrc` on Windows. Open that file in a text editor and add:
|
|
21
|
-
```
|
|
22
|
-
@benjosivo:registry=https://npm.pkg.github.com
|
|
23
|
-
//npm.pkg.github.com/:_authToken=YOUR_TOKEN_HERE
|
|
24
|
-
```
|
|
25
|
-
Editing the file directly is more reliable than `npm config set` — on some npm versions, `npm config set @benjosivo:registry=... --global` fails with a cryptic `` `` is not a valid npm option `` error. If you'd rather use the CLI, use the space-separated form instead of `=`:
|
|
26
|
-
```
|
|
27
|
-
npm config set @benjosivo:registry https://npm.pkg.github.com --global
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
3. **Verify both lines took effect:**
|
|
31
|
-
```
|
|
32
|
-
npm config list
|
|
33
|
-
```
|
|
34
|
-
You should see both `@benjosivo:registry = "https://npm.pkg.github.com"` and `//npm.pkg.github.com/:_authToken = (protected)` in the output.
|
|
35
|
-
|
|
36
|
-
### Install
|
|
37
|
-
|
|
38
7
|
```
|
|
39
8
|
npm install @benjosivo/mysql
|
|
40
9
|
```
|
|
41
10
|
|
|
42
|
-
### Troubleshooting
|
|
43
|
-
|
|
44
|
-
- **`404 Not Found - GET https://registry.npmjs.org/@benjosivo%2fmysql`** — npm is checking the default npm registry instead of GitHub Packages. This means the `@benjosivo:registry` line from step 2 above isn't set (check with `npm config get @benjosivo:registry`). Add it and retry.
|
|
45
|
-
- **401/403 or `ENEEDAUTH`** — the auth token is missing, expired, or lacks `read:packages` scope. Regenerate a token and re-add it.
|
|
46
|
-
|
|
47
11
|
## Usage
|
|
48
12
|
|
|
49
13
|
```ts
|
|
@@ -87,6 +51,34 @@ executeMySQLQuery(query, values?, returnFieldTypes?, connKey?)
|
|
|
87
51
|
|
|
88
52
|
Returns the rows directly on success. On failure it returns `{ error, values, connKey }` instead of throwing (matches `mysql2`'s row-result shape so existing call sites don't need try/catch).
|
|
89
53
|
|
|
54
|
+
### Statements prepared statements can't run
|
|
55
|
+
|
|
56
|
+
`executeMySQLQuery` uses `execute()` (MySQL's prepared-statement protocol), and MySQL rejects a
|
|
57
|
+
number of statements there with *"This command is not supported in the prepared statement protocol
|
|
58
|
+
yet"* — `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, and so on. For those,
|
|
59
|
+
use `runMySQLQuery`, which goes through `query()` (text protocol) instead:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { runMySQLQuery } from '@benjosivo/mysql';
|
|
63
|
+
|
|
64
|
+
await runMySQLQuery("SET GLOBAL general_log = 'OFF'");
|
|
65
|
+
|
|
66
|
+
// placeholders still work — mysql2 escapes and interpolates them client-side
|
|
67
|
+
await runMySQLQuery('SET GLOBAL general_log = ?', ['OFF']);
|
|
68
|
+
|
|
69
|
+
// optionally run inside an existing transaction
|
|
70
|
+
await runMySQLQuery('SELECT * FROM users WHERE id = ?', [userId], connKey);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
runMySQLQuery(query, values?, connKey?)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Same result shape as `executeMySQLQuery`: rows on success, `{ error, values, connKey }` on failure.
|
|
78
|
+
It's deliberately simple — no deadlock/lock-timeout retry — so prefer `executeMySQLQuery` for
|
|
79
|
+
regular application queries and keep this one for statements the prepared-statement protocol
|
|
80
|
+
refuses.
|
|
81
|
+
|
|
90
82
|
### Transactions
|
|
91
83
|
|
|
92
84
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import mysql from 'mysql2/promise';
|
|
1
2
|
export interface MySQLClientConfig {
|
|
2
3
|
host: string;
|
|
3
4
|
user: string;
|
|
@@ -24,6 +25,27 @@ export declare function executeMySQLQuery2(opt: {
|
|
|
24
25
|
returnFieldTypes?: boolean;
|
|
25
26
|
returnListTables?: boolean | string;
|
|
26
27
|
}): Promise<any>;
|
|
28
|
+
/**
|
|
29
|
+
* Runs a statement through mysql2's `query()` (text protocol) instead of `execute()`
|
|
30
|
+
* (prepared-statement protocol).
|
|
31
|
+
*
|
|
32
|
+
* MySQL refuses a number of statements in the prepared-statement protocol
|
|
33
|
+
* ("This command is not supported in the prepared statement protocol yet") —
|
|
34
|
+
* `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, etc.
|
|
35
|
+
* Use this for those; keep using `executeMySQLQuery` for everything else, since
|
|
36
|
+
* that one adds deadlock/lock-timeout retries and prepared statements.
|
|
37
|
+
*
|
|
38
|
+
* Values are escaped and interpolated client-side by mysql2 (`?` placeholders),
|
|
39
|
+
* so parameters are still safe to pass.
|
|
40
|
+
*
|
|
41
|
+
* Returns the rows on success, or `{ error, values, connKey }` on failure —
|
|
42
|
+
* same shape as `executeMySQLQuery`.
|
|
43
|
+
*/
|
|
44
|
+
export declare function runMySQLQuery(query: string, values?: any[], connKey?: string): Promise<mysql.RowDataPacket[][] | mysql.OkPacket[] | mysql.ResultSetHeader[] | mysql.RowDataPacket[] | mysql.OkPacket | mysql.ResultSetHeader | {
|
|
45
|
+
error: any;
|
|
46
|
+
values: any[];
|
|
47
|
+
connKey: string | null;
|
|
48
|
+
} | [mysql.RowDataPacket[], mysql.ResultSetHeader]>;
|
|
27
49
|
export declare function connectionCommit(keyConn: string): Promise<{
|
|
28
50
|
error?: unknown;
|
|
29
51
|
}>;
|
package/dist/index.js
CHANGED
|
@@ -42,6 +42,7 @@ exports.loopKillOpenTRX = loopKillOpenTRX;
|
|
|
42
42
|
exports.stopLoopKillOpenTRX = stopLoopKillOpenTRX;
|
|
43
43
|
exports.executeMySQLQuery = executeMySQLQuery;
|
|
44
44
|
exports.executeMySQLQuery2 = executeMySQLQuery2;
|
|
45
|
+
exports.runMySQLQuery = runMySQLQuery;
|
|
45
46
|
exports.connectionCommit = connectionCommit;
|
|
46
47
|
exports.connectionRollback = connectionRollback;
|
|
47
48
|
const crypto_1 = require("crypto");
|
|
@@ -369,6 +370,49 @@ async function executeMySQLQuery2(opt) {
|
|
|
369
370
|
return { error: error?.message ?? error, values, connKey: connKey ?? null };
|
|
370
371
|
}
|
|
371
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Runs a statement through mysql2's `query()` (text protocol) instead of `execute()`
|
|
375
|
+
* (prepared-statement protocol).
|
|
376
|
+
*
|
|
377
|
+
* MySQL refuses a number of statements in the prepared-statement protocol
|
|
378
|
+
* ("This command is not supported in the prepared statement protocol yet") —
|
|
379
|
+
* `SET GLOBAL ...`, `USE ...`, `LOCK TABLES`, several `SHOW` variants, etc.
|
|
380
|
+
* Use this for those; keep using `executeMySQLQuery` for everything else, since
|
|
381
|
+
* that one adds deadlock/lock-timeout retries and prepared statements.
|
|
382
|
+
*
|
|
383
|
+
* Values are escaped and interpolated client-side by mysql2 (`?` placeholders),
|
|
384
|
+
* so parameters are still safe to pass.
|
|
385
|
+
*
|
|
386
|
+
* Returns the rows on success, or `{ error, values, connKey }` on failure —
|
|
387
|
+
* same shape as `executeMySQLQuery`.
|
|
388
|
+
*/
|
|
389
|
+
async function runMySQLQuery(query, values = [], connKey) {
|
|
390
|
+
requireConfig();
|
|
391
|
+
let conn;
|
|
392
|
+
try {
|
|
393
|
+
if (connKey) {
|
|
394
|
+
const tr = listTransaction.get(connKey);
|
|
395
|
+
if (!tr) {
|
|
396
|
+
const msg = `Transaction key not found: ${connKey}`;
|
|
397
|
+
handleError(msg, 'MySQL: runMySQLQuery');
|
|
398
|
+
return { error: msg, values, connKey };
|
|
399
|
+
}
|
|
400
|
+
tr.lastUpdate = Date.now();
|
|
401
|
+
conn = tr.conn;
|
|
402
|
+
}
|
|
403
|
+
else if (lastConnectionCheck + 5 * 60000 <= Date.now()) {
|
|
404
|
+
await ensurePool();
|
|
405
|
+
}
|
|
406
|
+
const [rows] = await (conn ?? requirePool()).query(query, values);
|
|
407
|
+
return rows;
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
const errorMsg = String(error?.message ?? error);
|
|
411
|
+
const queryStr = query.length > 200 ? `${query.substring(0, 200)}...` : query;
|
|
412
|
+
handleError(error, `MySQL${error?.code ? ` [${error.code}]` : ''}${connKey ? ' (using connection)' : ''}\n${errorMsg}\n\nparams: ${values}\n\nquery: ${queryStr}`);
|
|
413
|
+
return { error: error?.message ?? error, values, connKey: connKey ?? null };
|
|
414
|
+
}
|
|
415
|
+
}
|
|
372
416
|
async function createTransaction() {
|
|
373
417
|
const keyConn = (0, crypto_1.randomUUID)();
|
|
374
418
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@benjosivo/mysql",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -18,5 +18,9 @@
|
|
|
18
18
|
"@types/node": "^26.1.2",
|
|
19
19
|
"typescript": "^7.0.2"
|
|
20
20
|
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/benjosivo/mysql.git"
|
|
24
|
+
},
|
|
21
25
|
"license": "MIT"
|
|
22
26
|
}
|