@depup/postgres 3.4.8-depup.0

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.
@@ -0,0 +1,1062 @@
1
+ import net from 'net'
2
+ import tls from 'tls'
3
+ import crypto from 'crypto'
4
+ import Stream from 'stream'
5
+ import { performance } from 'perf_hooks'
6
+
7
+ import { stringify, handleValue, arrayParser, arraySerializer } from './types.js'
8
+ import { Errors } from './errors.js'
9
+ import Result from './result.js'
10
+ import Queue from './queue.js'
11
+ import { Query, CLOSE } from './query.js'
12
+ import b from './bytes.js'
13
+
14
+ export default Connection
15
+
16
+ let uid = 1
17
+
18
+ const Sync = b().S().end()
19
+ , Flush = b().H().end()
20
+ , SSLRequest = b().i32(8).i32(80877103).end(8)
21
+ , ExecuteUnnamed = Buffer.concat([b().E().str(b.N).i32(0).end(), Sync])
22
+ , DescribeUnnamed = b().D().str('S').str(b.N).end()
23
+ , noop = () => { /* noop */ }
24
+
25
+ const retryRoutines = new Set([
26
+ 'FetchPreparedStatement',
27
+ 'RevalidateCachedQuery',
28
+ 'transformAssignedExpr'
29
+ ])
30
+
31
+ const errorFields = {
32
+ 83 : 'severity_local', // S
33
+ 86 : 'severity', // V
34
+ 67 : 'code', // C
35
+ 77 : 'message', // M
36
+ 68 : 'detail', // D
37
+ 72 : 'hint', // H
38
+ 80 : 'position', // P
39
+ 112 : 'internal_position', // p
40
+ 113 : 'internal_query', // q
41
+ 87 : 'where', // W
42
+ 115 : 'schema_name', // s
43
+ 116 : 'table_name', // t
44
+ 99 : 'column_name', // c
45
+ 100 : 'data type_name', // d
46
+ 110 : 'constraint_name', // n
47
+ 70 : 'file', // F
48
+ 76 : 'line', // L
49
+ 82 : 'routine' // R
50
+ }
51
+
52
+ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose = noop } = {}) {
53
+ const {
54
+ sslnegotiation,
55
+ ssl,
56
+ max,
57
+ user,
58
+ host,
59
+ port,
60
+ database,
61
+ parsers,
62
+ transform,
63
+ onnotice,
64
+ onnotify,
65
+ onparameter,
66
+ max_pipeline,
67
+ keep_alive,
68
+ backoff,
69
+ target_session_attrs
70
+ } = options
71
+
72
+ const sent = Queue()
73
+ , id = uid++
74
+ , backend = { pid: null, secret: null }
75
+ , idleTimer = timer(end, options.idle_timeout)
76
+ , lifeTimer = timer(end, options.max_lifetime)
77
+ , connectTimer = timer(connectTimedOut, options.connect_timeout)
78
+
79
+ let socket = null
80
+ , cancelMessage
81
+ , errorResponse = null
82
+ , result = new Result()
83
+ , incoming = Buffer.alloc(0)
84
+ , needsTypes = options.fetch_types
85
+ , backendParameters = {}
86
+ , statements = {}
87
+ , statementId = Math.random().toString(36).slice(2)
88
+ , statementCount = 1
89
+ , closedTime = 0
90
+ , remaining = 0
91
+ , hostIndex = 0
92
+ , retries = 0
93
+ , length = 0
94
+ , delay = 0
95
+ , rows = 0
96
+ , serverSignature = null
97
+ , nextWriteTimer = null
98
+ , terminated = false
99
+ , incomings = null
100
+ , results = null
101
+ , initial = null
102
+ , ending = null
103
+ , stream = null
104
+ , chunk = null
105
+ , ended = null
106
+ , nonce = null
107
+ , query = null
108
+ , final = null
109
+
110
+ const connection = {
111
+ queue: queues.closed,
112
+ idleTimer,
113
+ connect(query) {
114
+ initial = query
115
+ reconnect()
116
+ },
117
+ terminate,
118
+ execute,
119
+ cancel,
120
+ end,
121
+ count: 0,
122
+ id
123
+ }
124
+
125
+ queues.closed && queues.closed.push(connection)
126
+
127
+ return connection
128
+
129
+ async function createSocket() {
130
+ let x
131
+ try {
132
+ x = options.socket
133
+ ? (await Promise.resolve(options.socket(options)))
134
+ : new net.Socket()
135
+ } catch (e) {
136
+ error(e)
137
+ return
138
+ }
139
+ x.on('error', error)
140
+ x.on('close', closed)
141
+ x.on('drain', drain)
142
+ return x
143
+ }
144
+
145
+ async function cancel({ pid, secret }, resolve, reject) {
146
+ try {
147
+ cancelMessage = b().i32(16).i32(80877102).i32(pid).i32(secret).end(16)
148
+ await connect()
149
+ socket.once('error', reject)
150
+ socket.once('close', resolve)
151
+ } catch (error) {
152
+ reject(error)
153
+ }
154
+ }
155
+
156
+ function execute(q) {
157
+ if (terminated)
158
+ return queryError(q, Errors.connection('CONNECTION_DESTROYED', options))
159
+
160
+ if (stream)
161
+ return queryError(q, Errors.generic('COPY_IN_PROGRESS', 'You cannot execute queries during copy'))
162
+
163
+ if (q.cancelled)
164
+ return
165
+
166
+ try {
167
+ q.state = backend
168
+ query
169
+ ? sent.push(q)
170
+ : (query = q, query.active = true)
171
+
172
+ build(q)
173
+ return write(toBuffer(q))
174
+ && !q.describeFirst
175
+ && !q.cursorFn
176
+ && sent.length < max_pipeline
177
+ && (!q.options.onexecute || q.options.onexecute(connection))
178
+ } catch (error) {
179
+ sent.length === 0 && write(Sync)
180
+ errored(error)
181
+ return true
182
+ }
183
+ }
184
+
185
+ function toBuffer(q) {
186
+ if (q.parameters.length >= 65534)
187
+ throw Errors.generic('MAX_PARAMETERS_EXCEEDED', 'Max number of parameters (65534) exceeded')
188
+
189
+ return q.options.simple
190
+ ? b().Q().str(q.statement.string + b.N).end()
191
+ : q.describeFirst
192
+ ? Buffer.concat([describe(q), Flush])
193
+ : q.prepare
194
+ ? q.prepared
195
+ ? prepared(q)
196
+ : Buffer.concat([describe(q), prepared(q)])
197
+ : unnamed(q)
198
+ }
199
+
200
+ function describe(q) {
201
+ return Buffer.concat([
202
+ Parse(q.statement.string, q.parameters, q.statement.types, q.statement.name),
203
+ Describe('S', q.statement.name)
204
+ ])
205
+ }
206
+
207
+ function prepared(q) {
208
+ return Buffer.concat([
209
+ Bind(q.parameters, q.statement.types, q.statement.name, q.cursorName),
210
+ q.cursorFn
211
+ ? Execute('', q.cursorRows)
212
+ : ExecuteUnnamed
213
+ ])
214
+ }
215
+
216
+ function unnamed(q) {
217
+ return Buffer.concat([
218
+ Parse(q.statement.string, q.parameters, q.statement.types),
219
+ DescribeUnnamed,
220
+ prepared(q)
221
+ ])
222
+ }
223
+
224
+ function build(q) {
225
+ const parameters = []
226
+ , types = []
227
+
228
+ const string = stringify(q, q.strings[0], q.args[0], parameters, types, options)
229
+
230
+ !q.tagged && q.args.forEach(x => handleValue(x, parameters, types, options))
231
+
232
+ q.prepare = options.prepare && ('prepare' in q.options ? q.options.prepare : true)
233
+ q.string = string
234
+ q.signature = q.prepare && types + string
235
+ q.onlyDescribe && (delete statements[q.signature])
236
+ q.parameters = q.parameters || parameters
237
+ q.prepared = q.prepare && q.signature in statements
238
+ q.describeFirst = q.onlyDescribe || (parameters.length && !q.prepared)
239
+ q.statement = q.prepared
240
+ ? statements[q.signature]
241
+ : { string, types, name: q.prepare ? statementId + statementCount++ : '' }
242
+
243
+ typeof options.debug === 'function' && options.debug(id, string, parameters, types)
244
+ }
245
+
246
+ function write(x, fn) {
247
+ chunk = chunk ? Buffer.concat([chunk, x]) : Buffer.from(x)
248
+ if (fn || chunk.length >= 1024)
249
+ return nextWrite(fn)
250
+ nextWriteTimer === null && (nextWriteTimer = setImmediate(nextWrite))
251
+ return true
252
+ }
253
+
254
+ function nextWrite(fn) {
255
+ const x = socket.write(chunk, fn)
256
+ nextWriteTimer !== null && clearImmediate(nextWriteTimer)
257
+ chunk = nextWriteTimer = null
258
+ return x
259
+ }
260
+
261
+ function connectTimedOut() {
262
+ errored(Errors.connection('CONNECT_TIMEOUT', options, socket))
263
+ socket.destroy()
264
+ }
265
+
266
+ async function secure() {
267
+ if (sslnegotiation !== 'direct') {
268
+ write(SSLRequest)
269
+ const canSSL = await new Promise(r => socket.once('data', x => r(x[0] === 83))) // S
270
+
271
+ if (!canSSL && ssl === 'prefer')
272
+ return connected()
273
+ }
274
+
275
+ const options = {
276
+ socket,
277
+ servername: net.isIP(socket.host) ? undefined : socket.host
278
+ }
279
+
280
+ if (sslnegotiation === 'direct')
281
+ options.ALPNProtocols = ['postgresql']
282
+
283
+ if (ssl === 'require' || ssl === 'allow' || ssl === 'prefer')
284
+ options.rejectUnauthorized = false
285
+ else if (typeof ssl === 'object')
286
+ Object.assign(options, ssl)
287
+
288
+ socket.removeAllListeners()
289
+ socket = tls.connect(options)
290
+ socket.on('secureConnect', connected)
291
+ socket.on('error', error)
292
+ socket.on('close', closed)
293
+ socket.on('drain', drain)
294
+ }
295
+
296
+ /* c8 ignore next 3 */
297
+ function drain() {
298
+ !query && onopen(connection)
299
+ }
300
+
301
+ function data(x) {
302
+ if (incomings) {
303
+ incomings.push(x)
304
+ remaining -= x.length
305
+ if (remaining > 0)
306
+ return
307
+ }
308
+
309
+ incoming = incomings
310
+ ? Buffer.concat(incomings, length - remaining)
311
+ : incoming.length === 0
312
+ ? x
313
+ : Buffer.concat([incoming, x], incoming.length + x.length)
314
+
315
+ while (incoming.length > 4) {
316
+ length = incoming.readUInt32BE(1)
317
+ if (length >= incoming.length) {
318
+ remaining = length - incoming.length
319
+ incomings = [incoming]
320
+ break
321
+ }
322
+
323
+ try {
324
+ handle(incoming.subarray(0, length + 1))
325
+ } catch (e) {
326
+ query && (query.cursorFn || query.describeFirst) && write(Sync)
327
+ errored(e)
328
+ }
329
+ incoming = incoming.subarray(length + 1)
330
+ remaining = 0
331
+ incomings = null
332
+ }
333
+ }
334
+
335
+ async function connect() {
336
+ terminated = false
337
+ backendParameters = {}
338
+ socket || (socket = await createSocket())
339
+
340
+ if (!socket)
341
+ return
342
+
343
+ connectTimer.start()
344
+
345
+ if (options.socket)
346
+ return ssl ? secure() : connected()
347
+
348
+ socket.on('connect', ssl ? secure : connected)
349
+
350
+ if (options.path)
351
+ return socket.connect(options.path)
352
+
353
+ socket.ssl = ssl
354
+ socket.connect(port[hostIndex], host[hostIndex])
355
+ socket.host = host[hostIndex]
356
+ socket.port = port[hostIndex]
357
+
358
+ hostIndex = (hostIndex + 1) % port.length
359
+ }
360
+
361
+ function reconnect() {
362
+ setTimeout(connect, closedTime ? Math.max(0, closedTime + delay - performance.now()) : 0)
363
+ }
364
+
365
+ function connected() {
366
+ try {
367
+ statements = {}
368
+ needsTypes = options.fetch_types
369
+ statementId = Math.random().toString(36).slice(2)
370
+ statementCount = 1
371
+ lifeTimer.start()
372
+ socket.on('data', data)
373
+ keep_alive && socket.setKeepAlive && socket.setKeepAlive(true, 1000 * keep_alive)
374
+ const s = StartupMessage()
375
+ write(s)
376
+ } catch (err) {
377
+ error(err)
378
+ }
379
+ }
380
+
381
+ function error(err) {
382
+ if (connection.queue === queues.connecting && options.host[retries + 1])
383
+ return
384
+
385
+ errored(err)
386
+ while (sent.length)
387
+ queryError(sent.shift(), err)
388
+ }
389
+
390
+ function errored(err) {
391
+ stream && (stream.destroy(err), stream = null)
392
+ query && queryError(query, err)
393
+ initial && (queryError(initial, err), initial = null)
394
+ }
395
+
396
+ function queryError(query, err) {
397
+ if (query.reserve)
398
+ return query.reject(err)
399
+
400
+ if (!err || typeof err !== 'object')
401
+ err = new Error(err)
402
+
403
+ 'query' in err || 'parameters' in err || Object.defineProperties(err, {
404
+ stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug },
405
+ query: { value: query.string, enumerable: options.debug },
406
+ parameters: { value: query.parameters, enumerable: options.debug },
407
+ args: { value: query.args, enumerable: options.debug },
408
+ types: { value: query.statement && query.statement.types, enumerable: options.debug }
409
+ })
410
+ query.reject(err)
411
+ }
412
+
413
+ function end() {
414
+ return ending || (
415
+ !connection.reserved && onend(connection),
416
+ !connection.reserved && !initial && !query && sent.length === 0
417
+ ? (terminate(), new Promise(r => socket && socket.readyState !== 'closed' ? socket.once('close', r) : r()))
418
+ : ending = new Promise(r => ended = r)
419
+ )
420
+ }
421
+
422
+ function terminate() {
423
+ terminated = true
424
+ if (stream || query || initial || sent.length)
425
+ error(Errors.connection('CONNECTION_DESTROYED', options))
426
+
427
+ clearImmediate(nextWriteTimer)
428
+ if (socket) {
429
+ socket.removeListener('data', data)
430
+ socket.removeListener('connect', connected)
431
+ socket.readyState === 'open' && socket.end(b().X().end())
432
+ }
433
+ ended && (ended(), ending = ended = null)
434
+ }
435
+
436
+ async function closed(hadError) {
437
+ incoming = Buffer.alloc(0)
438
+ remaining = 0
439
+ incomings = null
440
+ clearImmediate(nextWriteTimer)
441
+ socket.removeListener('data', data)
442
+ socket.removeListener('connect', connected)
443
+ idleTimer.cancel()
444
+ lifeTimer.cancel()
445
+ connectTimer.cancel()
446
+
447
+ socket.removeAllListeners()
448
+ socket = null
449
+
450
+ if (initial)
451
+ return reconnect()
452
+
453
+ !hadError && (query || sent.length) && error(Errors.connection('CONNECTION_CLOSED', options, socket))
454
+ closedTime = performance.now()
455
+ hadError && options.shared.retries++
456
+ delay = (typeof backoff === 'function' ? backoff(options.shared.retries) : backoff) * 1000
457
+ onclose(connection, Errors.connection('CONNECTION_CLOSED', options, socket))
458
+ }
459
+
460
+ /* Handlers */
461
+ function handle(xs, x = xs[0]) {
462
+ (
463
+ x === 68 ? DataRow : // D
464
+ x === 100 ? CopyData : // d
465
+ x === 65 ? NotificationResponse : // A
466
+ x === 83 ? ParameterStatus : // S
467
+ x === 90 ? ReadyForQuery : // Z
468
+ x === 67 ? CommandComplete : // C
469
+ x === 50 ? BindComplete : // 2
470
+ x === 49 ? ParseComplete : // 1
471
+ x === 116 ? ParameterDescription : // t
472
+ x === 84 ? RowDescription : // T
473
+ x === 82 ? Authentication : // R
474
+ x === 110 ? NoData : // n
475
+ x === 75 ? BackendKeyData : // K
476
+ x === 69 ? ErrorResponse : // E
477
+ x === 115 ? PortalSuspended : // s
478
+ x === 51 ? CloseComplete : // 3
479
+ x === 71 ? CopyInResponse : // G
480
+ x === 78 ? NoticeResponse : // N
481
+ x === 72 ? CopyOutResponse : // H
482
+ x === 99 ? CopyDone : // c
483
+ x === 73 ? EmptyQueryResponse : // I
484
+ x === 86 ? FunctionCallResponse : // V
485
+ x === 118 ? NegotiateProtocolVersion : // v
486
+ x === 87 ? CopyBothResponse : // W
487
+ /* c8 ignore next */
488
+ UnknownMessage
489
+ )(xs)
490
+ }
491
+
492
+ function DataRow(x) {
493
+ let index = 7
494
+ let length
495
+ let column
496
+ let value
497
+
498
+ const row = query.isRaw ? new Array(query.statement.columns.length) : {}
499
+ for (let i = 0; i < query.statement.columns.length; i++) {
500
+ column = query.statement.columns[i]
501
+ length = x.readInt32BE(index)
502
+ index += 4
503
+
504
+ value = length === -1
505
+ ? null
506
+ : query.isRaw === true
507
+ ? x.subarray(index, index += length)
508
+ : column.parser === undefined
509
+ ? x.toString('utf8', index, index += length)
510
+ : column.parser.array === true
511
+ ? column.parser(x.toString('utf8', index + 1, index += length))
512
+ : column.parser(x.toString('utf8', index, index += length))
513
+
514
+ query.isRaw
515
+ ? (row[i] = query.isRaw === true
516
+ ? value
517
+ : transform.value.from ? transform.value.from(value, column) : value)
518
+ : (row[column.name] = transform.value.from ? transform.value.from(value, column) : value)
519
+ }
520
+
521
+ query.forEachFn
522
+ ? query.forEachFn(transform.row.from ? transform.row.from(row) : row, result)
523
+ : (result[rows++] = transform.row.from ? transform.row.from(row) : row)
524
+ }
525
+
526
+ function ParameterStatus(x) {
527
+ const [k, v] = x.toString('utf8', 5, x.length - 1).split(b.N)
528
+ backendParameters[k] = v
529
+ if (options.parameters[k] !== v) {
530
+ options.parameters[k] = v
531
+ onparameter && onparameter(k, v)
532
+ }
533
+ }
534
+
535
+ function ReadyForQuery(x) {
536
+ if (query) {
537
+ if (errorResponse) {
538
+ query.retried
539
+ ? errored(query.retried)
540
+ : query.prepared && retryRoutines.has(errorResponse.routine)
541
+ ? retry(query, errorResponse)
542
+ : errored(errorResponse)
543
+ } else {
544
+ query.resolve(results || result)
545
+ }
546
+ } else if (errorResponse) {
547
+ errored(errorResponse)
548
+ }
549
+
550
+ query = results = errorResponse = null
551
+ result = new Result()
552
+ connectTimer.cancel()
553
+
554
+ if (initial) {
555
+ if (target_session_attrs) {
556
+ if (!backendParameters.in_hot_standby || !backendParameters.default_transaction_read_only)
557
+ return fetchState()
558
+ else if (tryNext(target_session_attrs, backendParameters))
559
+ return terminate()
560
+ }
561
+
562
+ if (needsTypes) {
563
+ initial.reserve && (initial = null)
564
+ return fetchArrayTypes()
565
+ }
566
+
567
+ initial && !initial.reserve && execute(initial)
568
+ options.shared.retries = retries = 0
569
+ initial = null
570
+ return
571
+ }
572
+
573
+ while (sent.length && (query = sent.shift()) && (query.active = true, query.cancelled))
574
+ Connection(options).cancel(query.state, query.cancelled.resolve, query.cancelled.reject)
575
+
576
+ if (query)
577
+ return // Consider opening if able and sent.length < 50
578
+
579
+ connection.reserved
580
+ ? !connection.reserved.release && x[5] === 73 // I
581
+ ? ending
582
+ ? terminate()
583
+ : (connection.reserved = null, onopen(connection))
584
+ : connection.reserved()
585
+ : ending
586
+ ? terminate()
587
+ : onopen(connection)
588
+ }
589
+
590
+ function CommandComplete(x) {
591
+ rows = 0
592
+
593
+ for (let i = x.length - 1; i > 0; i--) {
594
+ if (x[i] === 32 && x[i + 1] < 58 && result.count === null)
595
+ result.count = +x.toString('utf8', i + 1, x.length - 1)
596
+ if (x[i - 1] >= 65) {
597
+ result.command = x.toString('utf8', 5, i)
598
+ result.state = backend
599
+ break
600
+ }
601
+ }
602
+
603
+ final && (final(), final = null)
604
+
605
+ if (result.command === 'BEGIN' && max !== 1 && !connection.reserved)
606
+ return errored(Errors.generic('UNSAFE_TRANSACTION', 'Only use sql.begin, sql.reserved or max: 1'))
607
+
608
+ if (query.options.simple)
609
+ return BindComplete()
610
+
611
+ if (query.cursorFn) {
612
+ result.count && query.cursorFn(result)
613
+ write(Sync)
614
+ }
615
+ }
616
+
617
+ function ParseComplete() {
618
+ query.parsing = false
619
+ }
620
+
621
+ function BindComplete() {
622
+ !result.statement && (result.statement = query.statement)
623
+ result.columns = query.statement.columns
624
+ }
625
+
626
+ function ParameterDescription(x) {
627
+ const length = x.readUInt16BE(5)
628
+
629
+ for (let i = 0; i < length; ++i)
630
+ !query.statement.types[i] && (query.statement.types[i] = x.readUInt32BE(7 + i * 4))
631
+
632
+ query.prepare && (statements[query.signature] = query.statement)
633
+ query.describeFirst && !query.onlyDescribe && (write(prepared(query)), query.describeFirst = false)
634
+ }
635
+
636
+ function RowDescription(x) {
637
+ if (result.command) {
638
+ results = results || [result]
639
+ results.push(result = new Result())
640
+ result.count = null
641
+ query.statement.columns = null
642
+ }
643
+
644
+ const length = x.readUInt16BE(5)
645
+ let index = 7
646
+ let start
647
+
648
+ query.statement.columns = Array(length)
649
+
650
+ for (let i = 0; i < length; ++i) {
651
+ start = index
652
+ while (x[index++] !== 0);
653
+ const table = x.readUInt32BE(index)
654
+ const number = x.readUInt16BE(index + 4)
655
+ const type = x.readUInt32BE(index + 6)
656
+ query.statement.columns[i] = {
657
+ name: transform.column.from
658
+ ? transform.column.from(x.toString('utf8', start, index - 1))
659
+ : x.toString('utf8', start, index - 1),
660
+ parser: parsers[type],
661
+ table,
662
+ number,
663
+ type
664
+ }
665
+ index += 18
666
+ }
667
+
668
+ result.statement = query.statement
669
+ if (query.onlyDescribe)
670
+ return (query.resolve(query.statement), write(Sync))
671
+ }
672
+
673
+ async function Authentication(x, type = x.readUInt32BE(5)) {
674
+ (
675
+ type === 3 ? AuthenticationCleartextPassword :
676
+ type === 5 ? AuthenticationMD5Password :
677
+ type === 10 ? SASL :
678
+ type === 11 ? SASLContinue :
679
+ type === 12 ? SASLFinal :
680
+ type !== 0 ? UnknownAuth :
681
+ noop
682
+ )(x, type)
683
+ }
684
+
685
+ /* c8 ignore next 5 */
686
+ async function AuthenticationCleartextPassword() {
687
+ const payload = await Pass()
688
+ write(
689
+ b().p().str(payload).z(1).end()
690
+ )
691
+ }
692
+
693
+ async function AuthenticationMD5Password(x) {
694
+ const payload = 'md5' + (
695
+ await md5(
696
+ Buffer.concat([
697
+ Buffer.from(await md5((await Pass()) + user)),
698
+ x.subarray(9)
699
+ ])
700
+ )
701
+ )
702
+ write(
703
+ b().p().str(payload).z(1).end()
704
+ )
705
+ }
706
+
707
+ async function SASL() {
708
+ nonce = (await crypto.randomBytes(18)).toString('base64')
709
+ b().p().str('SCRAM-SHA-256' + b.N)
710
+ const i = b.i
711
+ write(b.inc(4).str('n,,n=*,r=' + nonce).i32(b.i - i - 4, i).end())
712
+ }
713
+
714
+ async function SASLContinue(x) {
715
+ const res = x.toString('utf8', 9).split(',').reduce((acc, x) => (acc[x[0]] = x.slice(2), acc), {})
716
+
717
+ const saltedPassword = await crypto.pbkdf2Sync(
718
+ await Pass(),
719
+ Buffer.from(res.s, 'base64'),
720
+ parseInt(res.i), 32,
721
+ 'sha256'
722
+ )
723
+
724
+ const clientKey = await hmac(saltedPassword, 'Client Key')
725
+
726
+ const auth = 'n=*,r=' + nonce + ','
727
+ + 'r=' + res.r + ',s=' + res.s + ',i=' + res.i
728
+ + ',c=biws,r=' + res.r
729
+
730
+ serverSignature = (await hmac(await hmac(saltedPassword, 'Server Key'), auth)).toString('base64')
731
+
732
+ const payload = 'c=biws,r=' + res.r + ',p=' + xor(
733
+ clientKey, Buffer.from(await hmac(await sha256(clientKey), auth))
734
+ ).toString('base64')
735
+
736
+ write(
737
+ b().p().str(payload).end()
738
+ )
739
+ }
740
+
741
+ function SASLFinal(x) {
742
+ if (x.toString('utf8', 9).split(b.N, 1)[0].slice(2) === serverSignature)
743
+ return
744
+ /* c8 ignore next 5 */
745
+ errored(Errors.generic('SASL_SIGNATURE_MISMATCH', 'The server did not return the correct signature'))
746
+ socket.destroy()
747
+ }
748
+
749
+ function Pass() {
750
+ return Promise.resolve(typeof options.pass === 'function'
751
+ ? options.pass()
752
+ : options.pass
753
+ )
754
+ }
755
+
756
+ function NoData() {
757
+ result.statement = query.statement
758
+ result.statement.columns = []
759
+ if (query.onlyDescribe)
760
+ return (query.resolve(query.statement), write(Sync))
761
+ }
762
+
763
+ function BackendKeyData(x) {
764
+ backend.pid = x.readUInt32BE(5)
765
+ backend.secret = x.readUInt32BE(9)
766
+ }
767
+
768
+ async function fetchArrayTypes() {
769
+ needsTypes = false
770
+ const types = await new Query([`
771
+ select b.oid, b.typarray
772
+ from pg_catalog.pg_type a
773
+ left join pg_catalog.pg_type b on b.oid = a.typelem
774
+ where a.typcategory = 'A'
775
+ group by b.oid, b.typarray
776
+ order by b.oid
777
+ `], [], execute)
778
+ types.forEach(({ oid, typarray }) => addArrayType(oid, typarray))
779
+ }
780
+
781
+ function addArrayType(oid, typarray) {
782
+ if (!!options.parsers[typarray] && !!options.serializers[typarray]) return
783
+ const parser = options.parsers[oid]
784
+ options.shared.typeArrayMap[oid] = typarray
785
+ options.parsers[typarray] = (xs) => arrayParser(xs, parser, typarray)
786
+ options.parsers[typarray].array = true
787
+ options.serializers[typarray] = (xs) => arraySerializer(xs, options.serializers[oid], options, typarray)
788
+ }
789
+
790
+ function tryNext(x, xs) {
791
+ return (
792
+ (x === 'read-write' && xs.default_transaction_read_only === 'on') ||
793
+ (x === 'read-only' && xs.default_transaction_read_only === 'off') ||
794
+ (x === 'primary' && xs.in_hot_standby === 'on') ||
795
+ (x === 'standby' && xs.in_hot_standby === 'off') ||
796
+ (x === 'prefer-standby' && xs.in_hot_standby === 'off' && options.host[retries])
797
+ )
798
+ }
799
+
800
+ function fetchState() {
801
+ const query = new Query([`
802
+ show transaction_read_only;
803
+ select pg_catalog.pg_is_in_recovery()
804
+ `], [], execute, null, { simple: true })
805
+ query.resolve = ([[a], [b]]) => {
806
+ backendParameters.default_transaction_read_only = a.transaction_read_only
807
+ backendParameters.in_hot_standby = b.pg_is_in_recovery ? 'on' : 'off'
808
+ }
809
+ query.execute()
810
+ }
811
+
812
+ function ErrorResponse(x) {
813
+ if (query) {
814
+ (query.cursorFn || query.describeFirst) && write(Sync)
815
+ errorResponse = Errors.postgres(parseError(x))
816
+ } else {
817
+ errored(Errors.postgres(parseError(x)))
818
+ }
819
+ }
820
+
821
+ function retry(q, error) {
822
+ delete statements[q.signature]
823
+ q.retried = error
824
+ execute(q)
825
+ }
826
+
827
+ function NotificationResponse(x) {
828
+ if (!onnotify)
829
+ return
830
+
831
+ let index = 9
832
+ while (x[index++] !== 0);
833
+ onnotify(
834
+ x.toString('utf8', 9, index - 1),
835
+ x.toString('utf8', index, x.length - 1)
836
+ )
837
+ }
838
+
839
+ async function PortalSuspended() {
840
+ try {
841
+ const x = await Promise.resolve(query.cursorFn(result))
842
+ rows = 0
843
+ x === CLOSE
844
+ ? write(Close(query.portal))
845
+ : (result = new Result(), write(Execute('', query.cursorRows)))
846
+ } catch (err) {
847
+ write(Sync)
848
+ query.reject(err)
849
+ }
850
+ }
851
+
852
+ function CloseComplete() {
853
+ result.count && query.cursorFn(result)
854
+ query.resolve(result)
855
+ }
856
+
857
+ function CopyInResponse() {
858
+ stream = new Stream.Writable({
859
+ autoDestroy: true,
860
+ write(chunk, encoding, callback) {
861
+ socket.write(b().d().raw(chunk).end(), callback)
862
+ },
863
+ destroy(error, callback) {
864
+ callback(error)
865
+ socket.write(b().f().str(error + b.N).end())
866
+ stream = null
867
+ },
868
+ final(callback) {
869
+ socket.write(b().c().end())
870
+ final = callback
871
+ stream = null
872
+ }
873
+ })
874
+ query.resolve(stream)
875
+ }
876
+
877
+ function CopyOutResponse() {
878
+ stream = new Stream.Readable({
879
+ read() { socket.resume() }
880
+ })
881
+ query.resolve(stream)
882
+ }
883
+
884
+ /* c8 ignore next 3 */
885
+ function CopyBothResponse() {
886
+ stream = new Stream.Duplex({
887
+ autoDestroy: true,
888
+ read() { socket.resume() },
889
+ /* c8 ignore next 11 */
890
+ write(chunk, encoding, callback) {
891
+ socket.write(b().d().raw(chunk).end(), callback)
892
+ },
893
+ destroy(error, callback) {
894
+ callback(error)
895
+ socket.write(b().f().str(error + b.N).end())
896
+ stream = null
897
+ },
898
+ final(callback) {
899
+ socket.write(b().c().end())
900
+ final = callback
901
+ }
902
+ })
903
+ query.resolve(stream)
904
+ }
905
+
906
+ function CopyData(x) {
907
+ stream && (stream.push(x.subarray(5)) || socket.pause())
908
+ }
909
+
910
+ function CopyDone() {
911
+ stream && stream.push(null)
912
+ stream = null
913
+ }
914
+
915
+ function NoticeResponse(x) {
916
+ onnotice
917
+ ? onnotice(parseError(x))
918
+ : console.log(parseError(x)) // eslint-disable-line
919
+
920
+ }
921
+
922
+ /* c8 ignore next 3 */
923
+ function EmptyQueryResponse() {
924
+ /* noop */
925
+ }
926
+
927
+ /* c8 ignore next 3 */
928
+ function FunctionCallResponse() {
929
+ errored(Errors.notSupported('FunctionCallResponse'))
930
+ }
931
+
932
+ /* c8 ignore next 3 */
933
+ function NegotiateProtocolVersion() {
934
+ errored(Errors.notSupported('NegotiateProtocolVersion'))
935
+ }
936
+
937
+ /* c8 ignore next 3 */
938
+ function UnknownMessage(x) {
939
+ console.error('Postgres.js : Unknown Message:', x[0]) // eslint-disable-line
940
+ }
941
+
942
+ /* c8 ignore next 3 */
943
+ function UnknownAuth(x, type) {
944
+ console.error('Postgres.js : Unknown Auth:', type) // eslint-disable-line
945
+ }
946
+
947
+ /* Messages */
948
+ function Bind(parameters, types, statement = '', portal = '') {
949
+ let prev
950
+ , type
951
+
952
+ b().B().str(portal + b.N).str(statement + b.N).i16(0).i16(parameters.length)
953
+
954
+ parameters.forEach((x, i) => {
955
+ if (x === null)
956
+ return b.i32(0xFFFFFFFF)
957
+
958
+ type = types[i]
959
+ parameters[i] = x = type in options.serializers
960
+ ? options.serializers[type](x)
961
+ : '' + x
962
+
963
+ prev = b.i
964
+ b.inc(4).str(x).i32(b.i - prev - 4, prev)
965
+ })
966
+
967
+ b.i16(0)
968
+
969
+ return b.end()
970
+ }
971
+
972
+ function Parse(str, parameters, types, name = '') {
973
+ b().P().str(name + b.N).str(str + b.N).i16(parameters.length)
974
+ parameters.forEach((x, i) => b.i32(types[i] || 0))
975
+ return b.end()
976
+ }
977
+
978
+ function Describe(x, name = '') {
979
+ return b().D().str(x).str(name + b.N).end()
980
+ }
981
+
982
+ function Execute(portal = '', rows = 0) {
983
+ return Buffer.concat([
984
+ b().E().str(portal + b.N).i32(rows).end(),
985
+ Flush
986
+ ])
987
+ }
988
+
989
+ function Close(portal = '') {
990
+ return Buffer.concat([
991
+ b().C().str('P').str(portal + b.N).end(),
992
+ b().S().end()
993
+ ])
994
+ }
995
+
996
+ function StartupMessage() {
997
+ return cancelMessage || b().inc(4).i16(3).z(2).str(
998
+ Object.entries(Object.assign({
999
+ user,
1000
+ database,
1001
+ client_encoding: 'UTF8'
1002
+ },
1003
+ options.connection
1004
+ )).filter(([, v]) => v).map(([k, v]) => k + b.N + v).join(b.N)
1005
+ ).z(2).end(0)
1006
+ }
1007
+
1008
+ }
1009
+
1010
+ function parseError(x) {
1011
+ const error = {}
1012
+ let start = 5
1013
+ for (let i = 5; i < x.length - 1; i++) {
1014
+ if (x[i] === 0) {
1015
+ error[errorFields[x[start]]] = x.toString('utf8', start + 1, i)
1016
+ start = i + 1
1017
+ }
1018
+ }
1019
+ return error
1020
+ }
1021
+
1022
+ function md5(x) {
1023
+ return crypto.createHash('md5').update(x).digest('hex')
1024
+ }
1025
+
1026
+ function hmac(key, x) {
1027
+ return crypto.createHmac('sha256', key).update(x).digest()
1028
+ }
1029
+
1030
+ function sha256(x) {
1031
+ return crypto.createHash('sha256').update(x).digest()
1032
+ }
1033
+
1034
+ function xor(a, b) {
1035
+ const length = Math.max(a.length, b.length)
1036
+ const buffer = Buffer.allocUnsafe(length)
1037
+ for (let i = 0; i < length; i++)
1038
+ buffer[i] = a[i] ^ b[i]
1039
+ return buffer
1040
+ }
1041
+
1042
+ function timer(fn, seconds) {
1043
+ seconds = typeof seconds === 'function' ? seconds() : seconds
1044
+ if (!seconds)
1045
+ return { cancel: noop, start: noop }
1046
+
1047
+ let timer
1048
+ return {
1049
+ cancel() {
1050
+ timer && (clearTimeout(timer), timer = null)
1051
+ },
1052
+ start() {
1053
+ timer && clearTimeout(timer)
1054
+ timer = setTimeout(done, seconds * 1000, arguments)
1055
+ }
1056
+ }
1057
+
1058
+ function done(args) {
1059
+ fn.apply(null, args)
1060
+ timer = null
1061
+ }
1062
+ }