Skip to content

Commit 0592ac3

Browse files
authored
feat: add support for a connection string (#140)
1 parent 1e23bac commit 0592ac3

File tree

4 files changed

+112
-6
lines changed

4 files changed

+112
-6
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,17 @@ let value = connection.escape('Some value to be escaped')
134134
```
135135

136136
## Configuration Options
137+
138+
There are two ways to provide a configuration.
139+
140+
The one way is using a connection string at initialization time.
141+
142+
```javascript
143+
const mysql = require('serverless-mysql')(`mysql://${process.env.USERNAME}:${process.env.PASSWORD}@${process.env.ENDPOINT}:${process.env.PORT}/${process.env.DATABASE}`)
144+
```
145+
146+
The other way is to pass in the options defined in the below table.
147+
137148
Below is a table containing all of the possible configuration options for `serverless-mysql`. Additional details are provided throughout the documentation.
138149

139150
| Property | Type | Description | Default |

index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ declare namespace serverlessMysql {
9797

9898
export type ServerlessMysql = {
9999
connect(wait?: number): Promise<void>
100-
config(config?: MySQL.ConnectionConfig): MySQL.ConnectionConfig
100+
config(config?: string | MySQL.ConnectionConfig): MySQL.ConnectionConfig
101101
query<T>(...args): Promise<T>
102102
end(): Promise<void>
103103
escape(str: string): MySQL.EscapeFunctions
@@ -110,5 +110,5 @@ declare namespace serverlessMysql {
110110
}
111111
}
112112

113-
declare function serverlessMysql (cfg?: serverlessMysql.Config): serverlessMysql.ServerlessMysql
113+
declare function serverlessMysql (cfg?: string | serverlessMysql.Config): serverlessMysql.ServerlessMysql
114114
export = serverlessMysql

index.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict'
22

3+
const NodeURL = require('url')
4+
35
/**
46
* This module manages MySQL connections in serverless applications.
57
* More detail regarding the MySQL module can be found here:
@@ -50,11 +52,43 @@ module.exports = (params) => {
5052
const resetRetries = () => retries = 0
5153
const getErrorCount = () => errors
5254
const getConfig = () => _cfg
53-
const config = (args) => Object.assign(_cfg,args)
55+
const config = (args) => {
56+
if (typeof args === 'string') {
57+
return Object.assign(_cfg,uriToConnectionConfig(args))
58+
}
59+
return Object.assign(_cfg,args)
60+
}
5461
const delay = ms => new PromiseLibrary(res => setTimeout(res, ms))
5562
const randRange = (min,max) => Math.floor(Math.random() * (max - min + 1)) + min
5663
const fullJitter = () => randRange(0, Math.min(cap, base * 2 ** retries))
5764
const decorrelatedJitter = (sleep=0) => Math.min(cap, randRange(base, sleep * 3))
65+
const uriToConnectionConfig = (connectionString) => {
66+
let uri = undefined
67+
68+
try {
69+
uri = new NodeURL.URL(connectionString)
70+
} catch (error) {
71+
throw new Error('Invalid data source URL provided')
72+
}
73+
74+
const extraFields = {}
75+
76+
for (const [name, value] of uri.searchParams) {
77+
extraFields[name] = value
78+
}
79+
80+
const database = uri.pathname && uri.pathname.startsWith('/') ? uri.pathname.slice(1) : undefined
81+
82+
const connectionFields = {
83+
host: uri.hostname ? uri.hostname : undefined,
84+
user: uri.username ? uri.username : undefined,
85+
port: uri.port ? Number(uri.port) : undefined,
86+
password: uri.password ? uri.password : undefined,
87+
database
88+
}
89+
90+
return Object.assign(connectionFields, extraFields)
91+
}
5892

5993

6094
/********************************************************************/
@@ -348,8 +382,7 @@ module.exports = (params) => {
348382
/********************************************************************/
349383
/** INITIALIZATION **/
350384
/********************************************************************/
351-
352-
let cfg = typeof params === 'object' && !Array.isArray(params) ? params : {}
385+
const cfg = typeof params === 'object' && !Array.isArray(params) ? params : {}
353386

354387
MYSQL = cfg.library || require('mysql')
355388
PromiseLibrary = cfg.promise || Promise
@@ -377,7 +410,14 @@ module.exports = (params) => {
377410
onKill = typeof cfg.onKill === 'function' ? cfg.onKill : () => {}
378411
onKillError = typeof cfg.onKillError === 'function' ? cfg.onKillError : () => {}
379412

380-
let connCfg = typeof cfg.config === 'object' && !Array.isArray(cfg.config) ? cfg.config : {}
413+
let connCfg = {}
414+
415+
if (typeof cfg.config === 'object' && !Array.isArray(cfg.config)) {
416+
connCfg = cfg.config
417+
} else if (typeof params === 'string') {
418+
connCfg = params
419+
}
420+
381421
let escape = MYSQL.escape
382422
// Set MySQL configs
383423
config(connCfg)

test/connection-config.spec.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const assert = require("assert");
2+
3+
const mysql = require("../index");
4+
5+
describe("Test a connection config", () => {
6+
it("Should get a valid connection config when a config is passed in", () => {
7+
const configs = [
8+
mysql({
9+
config: {
10+
host: "localhost",
11+
database: "database",
12+
user: "user",
13+
password: "password",
14+
},
15+
}).getConfig(),
16+
mysql().config({
17+
host: "localhost",
18+
database: "database",
19+
user: "user",
20+
password: "password",
21+
}),
22+
];
23+
24+
configs.forEach((config) => {
25+
assert.deepEqual(config, {
26+
host: "localhost",
27+
database: "database",
28+
user: "user",
29+
password: "password",
30+
});
31+
});
32+
});
33+
34+
it("Should get a valid connection config when a connection string is passed in", () => {
35+
const configs = [
36+
mysql("mysql://user:password@localhost:3306/database").getConfig(),
37+
mysql().config("mysql://user:password@localhost:3306/database"),
38+
];
39+
40+
configs.forEach((config) => {
41+
assert.deepEqual(config, {
42+
host: "localhost",
43+
database: "database",
44+
user: "user",
45+
password: "password",
46+
port: "3306",
47+
});
48+
});
49+
});
50+
51+
it("Should throw an exception when an invalid connection string is passed in", () => {
52+
assert.throws(() => mysql("mysql://:3306/database").getConfig());
53+
assert.throws(() => mysql("mysql://:3306").getConfig());
54+
});
55+
});

0 commit comments

Comments
 (0)