Skip to content

Commit 4886809

Browse files
committed
allow user & database to be provided dynamically
1 parent f58cd4f commit 4886809

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -994,9 +994,9 @@ const sql = postgres('postgres://username:password@host:port/database', {
994994

995995
Note that `max_lifetime = 60 * (30 + Math.random() * 30)` by default. This resolves to an interval between 30 and 60 minutes to optimize for the benefits of prepared statements **and** working nicely with Linux's OOM killer.
996996

997-
### Dynamic passwords
997+
### Dynamic credentials
998998

999-
When clients need to use alternative authentication schemes such as access tokens or connections to databases with rotating passwords, provide either a synchronous or asynchronous function that will resolve the dynamic password value at connection time.
999+
When clients need to use alternative authentication schemes such as access tokens or connections to databases with rotating usernames, database names or passwords, provide either a synchronous or asynchronous function that will resolve the dynamic value at connection time.
10001000

10011001
```js
10021002
const sql = postgres(url, {

src/connection.js

+14-12
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,8 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
5353
const {
5454
ssl,
5555
max,
56-
user,
5756
host,
5857
port,
59-
database,
6058
parsers,
6159
transform,
6260
onnotice,
@@ -71,6 +69,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
7169
const sent = Queue()
7270
, id = uid++
7371
, backend = { pid: null, secret: null }
72+
, User = Resolve(options.user)
73+
, Database = Resolve(options.database)
74+
, Pass = Resolve(options.pass)
7475
, idleTimer = timer(end, options.idle_timeout)
7576
, lifeTimer = timer(end, options.max_lifetime)
7677
, connectTimer = timer(connectTimedOut, options.connect_timeout)
@@ -353,7 +354,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
353354
setTimeout(connect, closedDate ? closedDate + delay - performance.now() : 0)
354355
}
355356

356-
function connected() {
357+
async function connected() {
357358
try {
358359
statements = {}
359360
needsTypes = options.fetch_types
@@ -362,7 +363,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
362363
lifeTimer.start()
363364
socket.on('data', data)
364365
keep_alive && socket.setKeepAlive && socket.setKeepAlive(true, 1000 * keep_alive)
365-
const s = StartupMessage()
366+
const s = await StartupMessage()
366367
write(s)
367368
} catch (err) {
368369
error(err)
@@ -665,10 +666,11 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
665666
}
666667

667668
async function AuthenticationMD5Password(x) {
669+
const [pass, user] = await Promise.all([Pass(), User()])
668670
const payload = 'md5' + (
669-
await md5(
671+
md5(
670672
Buffer.concat([
671-
Buffer.from(await md5((await Pass()) + user)),
673+
Buffer.from(md5(pass + user)),
672674
x.subarray(9)
673675
])
674676
)
@@ -720,11 +722,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
720722
socket.destroy()
721723
}
722724

723-
function Pass() {
724-
return Promise.resolve(typeof options.pass === 'function'
725-
? options.pass()
726-
: options.pass
727-
)
725+
function Resolve(opt) {
726+
return async () => typeof opt === 'function'
727+
? opt.apply(options, [options])
728+
: opt
728729
}
729730

730731
function NoData() {
@@ -967,7 +968,8 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
967968
])
968969
}
969970

970-
function StartupMessage() {
971+
async function StartupMessage() {
972+
const [user, database] = await Promise.all([User(), Database()])
971973
return cancelMessage || b().inc(4).i16(3).z(2).str(
972974
Object.entries(Object.assign({
973975
user,

types/index.d.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@ interface BaseOptions<T extends Record<string, postgres.PostgresType>> {
3434
* Name of database to connect to
3535
* @default process.env['PGDATABASE'] || options.user
3636
*/
37-
database: string;
37+
database: Resolver<T, string>;
3838
/**
3939
* Username of database user
4040
* @default process.env['PGUSERNAME'] || process.env['PGUSER'] || require('os').userInfo().username
4141
*/
42-
user: string;
42+
user: Resolver<T, string>;
4343
/**
4444
* How to deal with ssl (can be a tls.connect option object)
4545
* @default false
@@ -125,6 +125,10 @@ interface BaseOptions<T extends Record<string, postgres.PostgresType>> {
125125
}
126126

127127

128+
type Resolver<T extends Record<string, postgres.PostgresType>, U> =
129+
| U
130+
| ((this: postgres.Options<T>, options: postgres.Options<T>) => U)
131+
128132
declare const PRIVATE: unique symbol;
129133

130134
declare class NotAPromise {
@@ -356,7 +360,7 @@ declare namespace postgres {
356360
* Password of database user
357361
* @default process.env['PGPASSWORD']
358362
*/
359-
password?: string | (() => string | Promise<string>) | undefined;
363+
password?: Resolver<T, string> | undefined;
360364
/** Name of database to connect to (an alias for `database`) */
361365
db?: Options<T>['database'] | undefined;
362366
/** Username of database user (an alias for `user`) */

0 commit comments

Comments
 (0)