Skip to content

Commit 3aa382d

Browse files
authored
fix(types): resolve wrong connection options
1 parent 2e71757 commit 3aa382d

File tree

5 files changed

+186
-46
lines changed

5 files changed

+186
-46
lines changed

index.d.ts

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,118 @@
11
// Type definitions for serverless-mysql
22

3-
import * as MySQL from 'mysql2'
3+
import * as MySQL from "mysql2";
44

55
// https://github.com/microsoft/TypeScript/issues/8335#issuecomment-215194561
66
declare namespace serverlessMysql {
77
export type Config = {
88
/**
99
* Function mysql library
1010
*/
11-
library?: Function
11+
library?: Function;
1212

1313
/**
1414
* Function promise library
1515
*/
16-
promise?: Function
16+
promise?: Function;
1717

1818
/**
1919
* String or Function Backoff algorithm to be used when retrying connections. Possible values are full and decorrelated, or you can also specify your own algorithm. See Connection Backoff for more information. full
2020
*/
21-
backoff?: string | Function
21+
backoff?: string | Function;
2222
/**
2323
* Integer Number of milliseconds added to random backoff values. 2
2424
*/
25-
base?: number
25+
base?: number;
2626
/**
2727
* Integer Maximum number of milliseconds between connection retries. 100
2828
*/
29-
cap?: number
29+
cap?: number;
3030
/**
31-
* Object A mysql configuration object as defined here {}
31+
* Object A mysql configuration object as defined here or a connection string {}
3232
*/
33-
config?: MySQL.ConnectionConfig
33+
config?: MySQL.ConnectionOptions | string;
3434
/**
3535
* Number The percentage of total connections to use when connecting to your MySQL server. A value of 0.75 would use 75% of your total available connections. 0.8
3636
*/
37-
connUtilization?: number
37+
connUtilization?: number;
3838
/**
3939
* Boolean Flag indicating whether or not you want serverless-mysql to manage MySQL connections for you. true
4040
*/
41-
manageConns?: boolean
41+
manageConns?: boolean;
4242
/**
4343
* Integer The number of milliseconds to cache lookups of @@max_connections. 15000
4444
*/
45-
maxConnsFreq?: number
45+
maxConnsFreq?: number;
4646
/**
4747
* Integer Maximum number of times to retry a connection before throwing an error. 50
4848
*/
49-
maxRetries?: number
49+
maxRetries?: number;
5050
/**
5151
* function Event callback when the MySQL connection fires an error.
5252
*/
53-
onError?: Function
53+
onError?: Function;
5454
/**
5555
* function Event callback when MySQL connections are explicitly closed.
5656
*/
57-
onClose?: Function
57+
onClose?: Function;
5858
/**
5959
* function Event callback when connections are succesfully established.
6060
*/
61-
onConnect?: Function
61+
onConnect?: Function;
6262
/**
6363
* function Event callback when connection fails.
6464
*/
65-
onConnectError?: Function
65+
onConnectError?: Function;
6666
/**
6767
* function Event callback when connections are explicitly killed.
6868
*/
69-
onKill?: Function
69+
onKill?: Function;
7070
/**
7171
* function Event callback when a connection cannot be killed.
7272
*/
73-
onKillError?: Function
73+
onKillError?: Function;
7474
/**
7575
* function Event callback when connections are retried.
7676
*/
77-
onRetry?: Function
77+
onRetry?: Function;
7878
/**
7979
* Integer The number of milliseconds to cache lookups of current connection usage. 0
8080
*/
81-
usedConnsFreq?: number
81+
usedConnsFreq?: number;
8282
/**
8383
* Integer The maximum number of seconds that a connection can stay idle before being recycled. 900
8484
*/
85-
zombieMaxTimeout?: number
85+
zombieMaxTimeout?: number;
8686
/**
8787
* Integer The minimum number of seconds that a connection must be idle before the module will recycle it. 3
8888
*/
89-
zombieMinTimeout?: number
90-
}
89+
zombieMinTimeout?: number;
90+
};
9191

9292
class Transaction {
93-
query(...args: any[]): this
94-
rollback(fn: Function): this
95-
commit<T = any>(): Promise<T[]>
93+
query(...args: any[]): this;
94+
rollback(fn: Function): this;
95+
commit<T = any>(): Promise<T[]>;
9696
}
9797

9898
export type ServerlessMysql = {
99-
connect(wait?: number): Promise<void>
100-
config(config?: string | MySQL.ConnectionConfig): MySQL.ConnectionConfig
101-
query<T>(...args: any[]): Promise<T>
102-
end(): Promise<void>
103-
escape: typeof MySQL.escape
104-
escapeId: typeof MySQL.escapeId
105-
format: typeof MySQL.format
106-
quit(): void
107-
transaction(): Transaction
108-
getCounter(): number
109-
getClient(): MySQL.Connection
110-
getConfig(): MySQL.ConnectionConfig
111-
getErrorCount(): number
112-
}
99+
connect(wait?: number): Promise<void>;
100+
config(config?: string | MySQL.ConnectionOptions): MySQL.ConnectionOptions;
101+
query<T>(...args: any[]): Promise<T>;
102+
end(): Promise<void>;
103+
escape: typeof MySQL.escape;
104+
escapeId: typeof MySQL.escapeId;
105+
format: typeof MySQL.format;
106+
quit(): void;
107+
transaction(): Transaction;
108+
getCounter(): number;
109+
getClient(): MySQL.Connection;
110+
getConfig(): MySQL.ConnectionOptions;
111+
getErrorCount(): number;
112+
};
113113
}
114114

115-
declare function serverlessMysql (cfg?: string | serverlessMysql.Config): serverlessMysql.ServerlessMysql
116-
export = serverlessMysql
115+
declare function serverlessMysql(
116+
cfg?: string | serverlessMysql.Config
117+
): serverlessMysql.ServerlessMysql;
118+
export = serverlessMysql;

index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,10 @@ module.exports = (params) => {
411411

412412
let connCfg = {}
413413

414-
if (typeof cfg.config === 'object' && !Array.isArray(cfg.config)) {
414+
const isConfigAnObject = typeof cfg.config === 'object' && !Array.isArray(cfg.config)
415+
const isConfigAString = typeof cfg.config === 'string'
416+
417+
if (isConfigAnObject || isConfigAString) {
415418
connCfg = cfg.config
416419
} else if (typeof params === 'string') {
417420
connCfg = params
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
'use strict';
2+
3+
const { expect } = require('chai');
4+
const mysql = require('../../index');
5+
const { closeConnection, createTestConnection, createTestConnectionString } = require('./helpers/setup');
6+
7+
describe('Connection String Integration Tests', function () {
8+
this.timeout(10000);
9+
10+
let db;
11+
12+
afterEach(async function () {
13+
try {
14+
if (db) {
15+
await db.end({ timeout: 5000 });
16+
await closeConnection(db);
17+
db = null;
18+
}
19+
} catch (err) {
20+
console.error('Error closing connection:', err);
21+
}
22+
});
23+
24+
it('should connect using a valid connection string', async function () {
25+
const connectionString = createTestConnectionString();
26+
db = createTestConnection(connectionString);
27+
28+
try {
29+
const result = await db.query('SELECT 1 AS value');
30+
expect(result).to.be.an('array');
31+
expect(result).to.have.lengthOf(1);
32+
expect(result[0]).to.have.property('value', 1);
33+
} catch (error) {
34+
console.error('Connection error:', error);
35+
throw error;
36+
}
37+
});
38+
39+
it('should connect using a connection string with additional parameters', async function () {
40+
const connectionString = createTestConnectionString({
41+
connectTimeout: 10000,
42+
dateStrings: 'true'
43+
});
44+
45+
db = createTestConnection(connectionString);
46+
47+
try {
48+
const result = await db.query('SELECT 1 AS value');
49+
expect(result).to.be.an('array');
50+
expect(result).to.have.lengthOf(1);
51+
expect(result[0]).to.have.property('value', 1);
52+
} catch (error) {
53+
console.error('Connection error:', error);
54+
throw error;
55+
}
56+
});
57+
58+
it('should connect using a connection string as part of sls-mysql.config property', async function () {
59+
const connectionString = createTestConnectionString();
60+
db = mysql({
61+
config: connectionString
62+
})
63+
64+
try {
65+
const result = await db.query('SELECT 1 AS value');
66+
expect(result).to.be.an('array');
67+
expect(result).to.have.lengthOf(1);
68+
expect(result[0]).to.have.property('value', 1);
69+
} catch (error) {
70+
console.error('Connection error:', error);
71+
throw error;
72+
}
73+
});
74+
});

test/integration/helpers/setup.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ const mysql = require('../../../index');
44

55
/**
66
* Creates a MySQL connection for testing
7-
* @param {Object} options - Additional options for the MySQL connection
7+
* @param {Object|string} options - Additional options for the MySQL connection or a connection string
88
* @returns {Object} The MySQL connection object
99
*/
1010
function createTestConnection(options = {}) {
11+
if (typeof options === 'string') {
12+
return mysql(options);
13+
}
14+
1115
const config = {
1216
host: process.env.MYSQL_HOST || '127.0.0.1',
1317
database: process.env.MYSQL_DATABASE || 'serverless_mysql_test',
@@ -22,6 +26,30 @@ function createTestConnection(options = {}) {
2226
});
2327
}
2428

29+
/**
30+
* Creates a connection string from environment variables or defaults
31+
* @param {Object} additionalParams - Additional URL parameters to include
32+
* @returns {string} The connection string
33+
*/
34+
function createTestConnectionString(additionalParams = {}) {
35+
const host = process.env.MYSQL_HOST || '127.0.0.1';
36+
const database = process.env.MYSQL_DATABASE || 'serverless_mysql_test';
37+
const user = process.env.MYSQL_USER || 'root';
38+
const password = process.env.MYSQL_PASSWORD || 'password';
39+
const port = process.env.MYSQL_PORT || 3306;
40+
41+
let connectionString = `mysql://${user}:${password}@${host}:${port}/${database}`;
42+
43+
if (Object.keys(additionalParams).length > 0) {
44+
connectionString += '?';
45+
connectionString += Object.entries(additionalParams)
46+
.map(([key, value]) => `${key}=${value}`)
47+
.join('&');
48+
}
49+
50+
return connectionString;
51+
}
52+
2553
/**
2654
* Sets up a test table
2755
* @param {Object} db - The MySQL connection
@@ -106,6 +134,7 @@ async function closeConnection(db) {
106134

107135
module.exports = {
108136
createTestConnection,
137+
createTestConnectionString,
109138
setupTestTable,
110139
cleanupTestTable,
111140
closeConnection

test/unit/connection-config.spec.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const assert = require("assert");
2-
32
const mysql = require("../../index");
43

54
describe("Test a connection config", () => {
@@ -43,7 +42,7 @@ describe("Test a connection config", () => {
4342
database: "database",
4443
user: "user",
4544
password: "password",
46-
port: "3306",
45+
port: 3306,
4746
});
4847
});
4948
});
@@ -52,4 +51,37 @@ describe("Test a connection config", () => {
5251
assert.throws(() => mysql("mysql://:3306/database").getConfig());
5352
assert.throws(() => mysql("mysql://:3306").getConfig());
5453
});
54+
55+
it("Should throw an error with an invalid connection string format", () => {
56+
assert.throws(() => {
57+
mysql("invalid-connection-string");
58+
}, /Invalid data source URL provided/);
59+
});
60+
61+
it("Should throw an error with a malformed connection string", () => {
62+
assert.throws(() => {
63+
mysql("mysql://user:password@");
64+
}, /Invalid data source URL provided/);
65+
});
66+
67+
it("Should handle connection string with missing credentials gracefully", () => {
68+
const db = mysql("mysql://localhost:3306/");
69+
const config = db.getConfig();
70+
71+
assert.strictEqual(config.host, "localhost");
72+
assert.strictEqual(config.port, 3306);
73+
});
74+
75+
it("Should parse additional parameters from connection string", () => {
76+
const db = mysql("mysql://user:password@localhost:3306/database?connectTimeout=10000&dateStrings=true");
77+
const config = db.getConfig();
78+
79+
assert.strictEqual(config.host, "localhost");
80+
assert.strictEqual(config.database, "database");
81+
assert.strictEqual(config.user, "user");
82+
assert.strictEqual(config.password, "password");
83+
assert.strictEqual(config.port, 3306);
84+
assert.strictEqual(config.connectTimeout, "10000");
85+
assert.strictEqual(config.dateStrings, "true");
86+
});
5587
});

0 commit comments

Comments
 (0)