@steadybrew/postgresjs 4.4.1 → 4.5.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.
- package/README.md +271 -20
- package/cf/src/connection.js +62 -19
- package/cf/src/errors.js +2 -2
- package/cf/src/index.js +37 -9
- package/cf/src/query.js +4 -10
- package/cf/src/types.js +7 -2
- package/cjs/src/connection.js +62 -19
- package/cjs/src/errors.js +2 -2
- package/cjs/src/index.js +37 -9
- package/cjs/src/query.js +4 -10
- package/cjs/src/types.js +7 -2
- package/package.json +5 -4
- package/src/connection.js +62 -19
- package/src/errors.js +2 -2
- package/src/index.js +37 -9
- package/src/query.js +4 -10
- package/src/types.js +7 -2
- package/types/index.d.ts +37 -1
- package/types/package.json +1 -1
package/cf/src/index.js
CHANGED
|
@@ -87,7 +87,8 @@ function Postgres(a, b) {
|
|
|
87
87
|
listen,
|
|
88
88
|
begin,
|
|
89
89
|
close,
|
|
90
|
-
end
|
|
90
|
+
end,
|
|
91
|
+
...Symbol.asyncDispose && { [Symbol.asyncDispose]: () => end() }
|
|
91
92
|
})
|
|
92
93
|
|
|
93
94
|
return sql
|
|
@@ -328,10 +329,17 @@ function Postgres(a, b) {
|
|
|
328
329
|
|
|
329
330
|
async function reserve() {
|
|
330
331
|
const l = await lease(false)
|
|
331
|
-
const sql = Sql(
|
|
332
|
+
const sql = Sql(handler)
|
|
332
333
|
sql.release = () => settle(l, Lease.Released)
|
|
334
|
+
Symbol.dispose && (sql[Symbol.dispose] = () => sql.release())
|
|
335
|
+
Symbol.asyncDispose && (sql[Symbol.asyncDispose] = async() => sql.release())
|
|
333
336
|
sql.stats = stats
|
|
334
337
|
return sql
|
|
338
|
+
|
|
339
|
+
// dd-trace starts query spans only inside function declarations named handler
|
|
340
|
+
function handler(q) {
|
|
341
|
+
send(l, q)
|
|
342
|
+
}
|
|
335
343
|
}
|
|
336
344
|
|
|
337
345
|
async function begin(options, fn) {
|
|
@@ -348,7 +356,7 @@ function Postgres(a, b) {
|
|
|
348
356
|
}
|
|
349
357
|
|
|
350
358
|
async function transaction() {
|
|
351
|
-
await Sql(
|
|
359
|
+
await Sql(handler).unsafe('begin ' + options.replace(/[^a-z ]/ig, ''), []).execute().catch(e => {
|
|
352
360
|
e instanceof PostgresError && settle(l, Lease.Released)
|
|
353
361
|
throw e
|
|
354
362
|
})
|
|
@@ -359,7 +367,7 @@ function Postgres(a, b) {
|
|
|
359
367
|
let result
|
|
360
368
|
l.state = Lease.Settling
|
|
361
369
|
try {
|
|
362
|
-
result = await statement(Sql(q =>
|
|
370
|
+
result = await statement(Sql(q => handler(q, Lease.Settling)))
|
|
363
371
|
} catch (e) {
|
|
364
372
|
settle(l, Lease.Discarded)
|
|
365
373
|
throw e
|
|
@@ -369,7 +377,7 @@ function Postgres(a, b) {
|
|
|
369
377
|
}
|
|
370
378
|
|
|
371
379
|
async function scope(fn, name) {
|
|
372
|
-
const sql = Sql(
|
|
380
|
+
const sql = Sql(track)
|
|
373
381
|
sql.savepoint = savepoint
|
|
374
382
|
sql.prepare = x => {
|
|
375
383
|
if (typeof x !== 'string' || !x || x.includes('\0'))
|
|
@@ -423,11 +431,16 @@ function Postgres(a, b) {
|
|
|
423
431
|
return scope(fn, 's' + savepoints++ + (name ? '_' + name : ''))
|
|
424
432
|
}
|
|
425
433
|
|
|
426
|
-
function
|
|
434
|
+
function track(q) {
|
|
427
435
|
q.catch(e => uncaughtError || (uncaughtError = e))
|
|
428
|
-
|
|
436
|
+
handler(q)
|
|
429
437
|
}
|
|
430
438
|
}
|
|
439
|
+
|
|
440
|
+
// dd-trace starts query spans only inside function declarations named handler
|
|
441
|
+
function handler(q, expected) {
|
|
442
|
+
send(l, q, expected)
|
|
443
|
+
}
|
|
431
444
|
}
|
|
432
445
|
|
|
433
446
|
function move(c, queue) {
|
|
@@ -675,6 +688,7 @@ function parseOptions(a, b) {
|
|
|
675
688
|
prepare : true,
|
|
676
689
|
debug : false,
|
|
677
690
|
fetch_types : true,
|
|
691
|
+
parameter_types : 'server',
|
|
678
692
|
publications : 'alltables',
|
|
679
693
|
target_session_attrs: null
|
|
680
694
|
}
|
|
@@ -689,8 +703,8 @@ function parseOptions(a, b) {
|
|
|
689
703
|
...Object.entries(defaults).reduce(
|
|
690
704
|
(acc, [k, d]) => {
|
|
691
705
|
const value = k in o ? o[k] : k in query
|
|
692
|
-
? (query[k]
|
|
693
|
-
: env['PG' + k.toUpperCase()]
|
|
706
|
+
? off(query[k])
|
|
707
|
+
: env['PG' + k.toUpperCase()] ? off(env['PG' + k.toUpperCase()]) : d
|
|
694
708
|
acc[k] = typeof value === 'string' && ints.includes(k)
|
|
695
709
|
? +value
|
|
696
710
|
: value
|
|
@@ -705,11 +719,13 @@ function parseOptions(a, b) {
|
|
|
705
719
|
},
|
|
706
720
|
types : o.types || {},
|
|
707
721
|
target_session_attrs: tsa(o, url, env),
|
|
722
|
+
parameter_types : parameterTypes(o, url, env),
|
|
708
723
|
onnotice : o.onnotice,
|
|
709
724
|
onnotify : o.onnotify,
|
|
710
725
|
onclose : o.onclose,
|
|
711
726
|
onidle : o.onidle,
|
|
712
727
|
onparameter : o.onparameter,
|
|
728
|
+
ontypemismatch : o.ontypemismatch,
|
|
713
729
|
socket : o.socket,
|
|
714
730
|
transform : parseTransform(o.transform || { undefined: undefined }),
|
|
715
731
|
parameters : {},
|
|
@@ -721,6 +737,10 @@ function parseOptions(a, b) {
|
|
|
721
737
|
return options
|
|
722
738
|
}
|
|
723
739
|
|
|
740
|
+
function off(x) {
|
|
741
|
+
return x === 'disable' || x === 'false' ? false : x
|
|
742
|
+
}
|
|
743
|
+
|
|
724
744
|
function tsa(o, url, env) {
|
|
725
745
|
const x = o.target_session_attrs || url.searchParams.get('target_session_attrs') || env.PGTARGETSESSIONATTRS
|
|
726
746
|
if (!x || ['read-write', 'read-only', 'primary', 'standby', 'prefer-standby'].includes(x))
|
|
@@ -729,6 +749,14 @@ function tsa(o, url, env) {
|
|
|
729
749
|
throw new Error('target_session_attrs ' + x + ' is not supported')
|
|
730
750
|
}
|
|
731
751
|
|
|
752
|
+
function parameterTypes(o, url, env) {
|
|
753
|
+
const x = o.parameter_types || url.searchParams.get('parameter_types') || env.PGPARAMETER_TYPES || 'server'
|
|
754
|
+
if (['server', 'client', 'warn'].includes(x))
|
|
755
|
+
return x
|
|
756
|
+
|
|
757
|
+
throw new Error('parameter_types ' + x + ' is not supported')
|
|
758
|
+
}
|
|
759
|
+
|
|
732
760
|
function max_lifetime() {
|
|
733
761
|
return 60 * (30 + Math.random() * 30)
|
|
734
762
|
}
|
package/cf/src/query.js
CHANGED
|
@@ -23,16 +23,9 @@ export class Query extends Promise {
|
|
|
23
23
|
this.state = null
|
|
24
24
|
this.statement = null
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
resolve(x)
|
|
30
|
-
}
|
|
31
|
-
this.reject = x => {
|
|
32
|
-
this.active = false
|
|
33
|
-
this.settled = true
|
|
34
|
-
reject(x)
|
|
35
|
-
}
|
|
26
|
+
// dd-trace's load-time rewrite only accepts single-expression arrows here
|
|
27
|
+
this.resolve = x => (this.active = false, this.settled = true, resolve(x))
|
|
28
|
+
this.reject = x => (this.active = false, this.settled = true, reject(x))
|
|
36
29
|
|
|
37
30
|
this.active = false
|
|
38
31
|
this.settled = false
|
|
@@ -62,6 +55,7 @@ export class Query extends Promise {
|
|
|
62
55
|
if (!this.canceller || this.settled)
|
|
63
56
|
return Promise.resolve()
|
|
64
57
|
|
|
58
|
+
Promise.prototype.then.call(this, undefined, () => undefined)
|
|
65
59
|
const cancelled = this.canceller(this)
|
|
66
60
|
this.canceller = null
|
|
67
61
|
cancelled.catch(() => undefined)
|
package/cf/src/types.js
CHANGED
|
@@ -249,6 +249,11 @@ export const inferType = function inferType(x) {
|
|
|
249
249
|
)
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
+
export function clientSerialize(x) {
|
|
253
|
+
const proto = typeof x === 'object' && Object.getPrototypeOf(x)
|
|
254
|
+
return proto === Object.prototype || proto === null ? JSON.stringify(x) : '' + x
|
|
255
|
+
}
|
|
256
|
+
|
|
252
257
|
const escapeBackslash = /\\/g
|
|
253
258
|
const escapeQuote = /"/g
|
|
254
259
|
|
|
@@ -342,14 +347,14 @@ function arrayParserLoop(s, x, parser, typarray) {
|
|
|
342
347
|
export const toCamel = x => {
|
|
343
348
|
let str = x[0]
|
|
344
349
|
for (let i = 1; i < x.length; i++)
|
|
345
|
-
str += x[i] === '_' ? x[++i].toUpperCase() : x[i]
|
|
350
|
+
str += x[i] === '_' && i + 1 < x.length ? x[++i].toUpperCase() : x[i]
|
|
346
351
|
return str
|
|
347
352
|
}
|
|
348
353
|
|
|
349
354
|
export const toPascal = x => {
|
|
350
355
|
let str = x[0].toUpperCase()
|
|
351
356
|
for (let i = 1; i < x.length; i++)
|
|
352
|
-
str += x[i] === '_' ? x[++i].toUpperCase() : x[i]
|
|
357
|
+
str += x[i] === '_' && i + 1 < x.length ? x[++i].toUpperCase() : x[i]
|
|
353
358
|
return str
|
|
354
359
|
}
|
|
355
360
|
|
package/cjs/src/connection.js
CHANGED
|
@@ -4,7 +4,7 @@ const crypto = require('crypto')
|
|
|
4
4
|
const Stream = require('stream')
|
|
5
5
|
const { performance } = require('perf_hooks')
|
|
6
6
|
|
|
7
|
-
const { stringify, handleValue, addArrayType } = require('./types.js')
|
|
7
|
+
const { stringify, handleValue, addArrayType, clientSerialize } = require('./types.js')
|
|
8
8
|
const { Errors, callback } = require('./errors.js')
|
|
9
9
|
const Result = require('./result.js')
|
|
10
10
|
const Queue = require('./queue.js')
|
|
@@ -104,6 +104,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
104
104
|
, hostIndex = 0
|
|
105
105
|
, length = 0
|
|
106
106
|
, rows = 0
|
|
107
|
+
, copyPaused = false
|
|
107
108
|
, serverSignature = null
|
|
108
109
|
, nextWriteTimer = null
|
|
109
110
|
, incomings = null
|
|
@@ -214,7 +215,10 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
214
215
|
const connection = {
|
|
215
216
|
queue: queues.closed,
|
|
216
217
|
idleTimer,
|
|
217
|
-
connect
|
|
218
|
+
// Sentry's hook wraps connect and reads the connection from this, so it must stay a method
|
|
219
|
+
connect(request) {
|
|
220
|
+
dispatch('acquire', request)
|
|
221
|
+
},
|
|
218
222
|
terminate: () => dispatch('terminate'),
|
|
219
223
|
execute,
|
|
220
224
|
release: () => dispatch('release'),
|
|
@@ -459,6 +463,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
459
463
|
query = results = errorResponse = chunk = nextWriteTimer = barrier = null
|
|
460
464
|
result = new Result()
|
|
461
465
|
rows = 0
|
|
466
|
+
copyPaused = false
|
|
462
467
|
nonce = serverSignature = null
|
|
463
468
|
}
|
|
464
469
|
|
|
@@ -538,7 +543,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
538
543
|
|
|
539
544
|
build(q)
|
|
540
545
|
const written = write(toBuffer(q))
|
|
541
|
-
if (q.describeFirst || q.cursorFn || mayCopy(q))
|
|
546
|
+
if (q.describeFirst || q.cursorFn || mayCopy(q) || (q.prepare && !q.prepared && !q.options.simple && q.parameters.length))
|
|
542
547
|
barrier = q
|
|
543
548
|
return written && accepting()
|
|
544
549
|
} catch (error) {
|
|
@@ -576,7 +581,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
576
581
|
|
|
577
582
|
function prepared(q) {
|
|
578
583
|
return Buffer.concat([
|
|
579
|
-
Bind(q
|
|
584
|
+
Bind(q),
|
|
580
585
|
q.cursorFn
|
|
581
586
|
? Execute('', q.cursorRows)
|
|
582
587
|
: ExecuteUnnamed
|
|
@@ -604,8 +609,11 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
604
609
|
q.signature = q.prepare && types + string
|
|
605
610
|
q.onlyDescribe && (delete statements[q.signature])
|
|
606
611
|
q.parameters = q.parameters || parameters
|
|
612
|
+
q.inferred = options.parameter_types === 'server' ? null : types.slice()
|
|
607
613
|
q.prepared = q.prepare && q.signature in statements
|
|
608
|
-
q.describeFirst = q.onlyDescribe || (
|
|
614
|
+
q.describeFirst = q.onlyDescribe || (!q.prepared && types.some((x, i) =>
|
|
615
|
+
!x && (options.parameter_types !== 'client' || Array.isArray(q.parameters[i]))
|
|
616
|
+
))
|
|
609
617
|
q.statement = q.prepared
|
|
610
618
|
? statements[q.signature]
|
|
611
619
|
: { string, types, name: q.prepare ? statementId + statementCount++ : '' }
|
|
@@ -678,6 +686,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
678
686
|
|
|
679
687
|
function errored(err) {
|
|
680
688
|
stream && (stream.destroy(err), stream = null)
|
|
689
|
+
resumeCopy()
|
|
681
690
|
query && queryError(query, err)
|
|
682
691
|
}
|
|
683
692
|
|
|
@@ -689,7 +698,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
689
698
|
err = new Error(err)
|
|
690
699
|
|
|
691
700
|
'query' in err || 'parameters' in err || Object.defineProperties(err, {
|
|
692
|
-
stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug },
|
|
701
|
+
stack: { value: err.stack + query.origin.replace(/.*\n/, '\n'), enumerable: options.debug, writable: true, configurable: true },
|
|
693
702
|
query: { value: query.string, enumerable: options.debug },
|
|
694
703
|
parameters: { value: query.parameters, enumerable: options.debug },
|
|
695
704
|
args: { value: query.args, enumerable: options.debug },
|
|
@@ -794,7 +803,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
794
803
|
query.prepared && retryRoutines.has(errorResponse.routine) && delete statements[query.signature]
|
|
795
804
|
query.retried
|
|
796
805
|
? errored(query.retried)
|
|
797
|
-
: query.prepared && retryRoutines.has(errorResponse.routine) && query.owner === connection.owner && !barrier
|
|
806
|
+
: query.prepared && retryRoutines.has(errorResponse.routine) && query.owner === connection.owner && !barrier && !query.cancelled
|
|
798
807
|
&& (x[5] !== 69 || endsAbortedState.test(query.string))
|
|
799
808
|
? retry(query, errorResponse)
|
|
800
809
|
: errored(errorResponse)
|
|
@@ -808,6 +817,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
808
817
|
|
|
809
818
|
query = results = errorResponse = null
|
|
810
819
|
result = new Result()
|
|
820
|
+
rows = 0
|
|
811
821
|
|
|
812
822
|
dispatch('ready')
|
|
813
823
|
}
|
|
@@ -1040,8 +1050,9 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1040
1050
|
|
|
1041
1051
|
function mismatchReason(x, xs) {
|
|
1042
1052
|
return (
|
|
1053
|
+
(x === 'read-write' && xs.in_hot_standby === 'on' && 'is a standby') ||
|
|
1043
1054
|
(x === 'read-write' && xs.default_transaction_read_only === 'on' && 'is read-only') ||
|
|
1044
|
-
(x === 'read-only' && xs.default_transaction_read_only === 'off' && 'is read-write') ||
|
|
1055
|
+
(x === 'read-only' && xs.in_hot_standby === 'off' && xs.default_transaction_read_only === 'off' && 'is read-write') ||
|
|
1045
1056
|
(x === 'primary' && xs.in_hot_standby === 'on' && 'is a standby') ||
|
|
1046
1057
|
(x === 'standby' && xs.in_hot_standby === 'off' && 'is a primary') ||
|
|
1047
1058
|
(x === 'prefer-standby' && xs.in_hot_standby === 'off' && standbyPass() && 'is a primary') ||
|
|
@@ -1140,7 +1151,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1140
1151
|
|
|
1141
1152
|
function CopyOutResponse() {
|
|
1142
1153
|
stream = new Stream.Readable({
|
|
1143
|
-
read() { socket.resume() }
|
|
1154
|
+
read() { copyPaused = false; socket.resume() }
|
|
1144
1155
|
})
|
|
1145
1156
|
query.resolve(stream)
|
|
1146
1157
|
connection.owner && connection.owner.next()
|
|
@@ -1150,7 +1161,7 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1150
1161
|
function CopyBothResponse() {
|
|
1151
1162
|
stream = new Stream.Duplex({
|
|
1152
1163
|
autoDestroy: true,
|
|
1153
|
-
read() { socket.resume() },
|
|
1164
|
+
read() { copyPaused = false; socket.resume() },
|
|
1154
1165
|
/* c8 ignore next 11 */
|
|
1155
1166
|
write(chunk, encoding, callback) {
|
|
1156
1167
|
socket.write(b().d().raw(chunk).end(), callback)
|
|
@@ -1170,12 +1181,23 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1170
1181
|
}
|
|
1171
1182
|
|
|
1172
1183
|
function CopyData(x) {
|
|
1173
|
-
stream &&
|
|
1184
|
+
if (stream && !stream.push(x.subarray(5))) {
|
|
1185
|
+
copyPaused = true
|
|
1186
|
+
socket.pause()
|
|
1187
|
+
}
|
|
1174
1188
|
}
|
|
1175
1189
|
|
|
1176
1190
|
function CopyDone() {
|
|
1177
1191
|
stream && stream.push(null)
|
|
1178
1192
|
stream = null
|
|
1193
|
+
resumeCopy()
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
function resumeCopy() {
|
|
1197
|
+
if (copyPaused) {
|
|
1198
|
+
copyPaused = false
|
|
1199
|
+
socket.resume()
|
|
1200
|
+
}
|
|
1179
1201
|
}
|
|
1180
1202
|
|
|
1181
1203
|
function NoticeResponse(x) {
|
|
@@ -1213,20 +1235,21 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1213
1235
|
}
|
|
1214
1236
|
|
|
1215
1237
|
/* Messages */
|
|
1216
|
-
function Bind(
|
|
1238
|
+
function Bind(q) {
|
|
1239
|
+
const differences = []
|
|
1217
1240
|
let prev
|
|
1218
1241
|
, type
|
|
1219
1242
|
|
|
1220
|
-
b().B().str(
|
|
1243
|
+
b().B().str((q.cursorName || '') + b.N).str(q.statement.name + b.N).i16(0).i16(q.parameters.length)
|
|
1221
1244
|
|
|
1222
|
-
parameters.forEach((x, i) => {
|
|
1245
|
+
q.parameters.forEach((x, i) => {
|
|
1223
1246
|
if (x === null)
|
|
1224
1247
|
return b.i32(0xFFFFFFFF)
|
|
1225
1248
|
|
|
1226
|
-
type = types[i]
|
|
1227
|
-
x =
|
|
1228
|
-
?
|
|
1229
|
-
: ''
|
|
1249
|
+
type = q.statement.types[i]
|
|
1250
|
+
x = !q.inferred || q.inferred[i] || Array.isArray(x)
|
|
1251
|
+
? serialize(x, type)
|
|
1252
|
+
: options.parameter_types === 'client' ? clientSerialize(x) : compare(x, type, i, differences)
|
|
1230
1253
|
|
|
1231
1254
|
prev = b.i
|
|
1232
1255
|
b.inc(4).str(x).i32(b.i - prev - 4, prev)
|
|
@@ -1234,7 +1257,27 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
|
|
|
1234
1257
|
|
|
1235
1258
|
b.i16(0)
|
|
1236
1259
|
|
|
1237
|
-
|
|
1260
|
+
const message = b.end()
|
|
1261
|
+
differences.length && callback(options.ontypemismatch || console.warn, { query: q.string, parameters: differences }) // eslint-disable-line
|
|
1262
|
+
return message
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
function serialize(x, type) {
|
|
1266
|
+
return type in options.serializers
|
|
1267
|
+
? options.serializers[type](x)
|
|
1268
|
+
: '' + x
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
function compare(x, type, i, differences) {
|
|
1272
|
+
const serverText = serialize(x, type)
|
|
1273
|
+
let clientText
|
|
1274
|
+
try {
|
|
1275
|
+
clientText = clientSerialize(x)
|
|
1276
|
+
} catch (error) {
|
|
1277
|
+
clientText = error
|
|
1278
|
+
}
|
|
1279
|
+
serverText === clientText || differences.push({ position: i + 1, oid: type, typeof: typeof x, ...options.debug && { serverText, clientText } })
|
|
1280
|
+
return serverText
|
|
1238
1281
|
}
|
|
1239
1282
|
|
|
1240
1283
|
function Parse(str, parameters, types, name = '') {
|
package/cjs/src/errors.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const PostgresError = module.exports.PostgresError = class PostgresError extends Error {
|
|
2
2
|
constructor(x) {
|
|
3
|
-
super(x.message)
|
|
3
|
+
super(typeof x === 'string' ? x : x.message)
|
|
4
4
|
this.name = this.constructor.name
|
|
5
|
-
Object.assign(this, x)
|
|
5
|
+
typeof x === 'string' || Object.assign(this, x)
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
8
|
|
package/cjs/src/index.js
CHANGED
|
@@ -86,7 +86,8 @@ function Postgres(a, b) {
|
|
|
86
86
|
listen,
|
|
87
87
|
begin,
|
|
88
88
|
close,
|
|
89
|
-
end
|
|
89
|
+
end,
|
|
90
|
+
...Symbol.asyncDispose && { [Symbol.asyncDispose]: () => end() }
|
|
90
91
|
})
|
|
91
92
|
|
|
92
93
|
return sql
|
|
@@ -327,10 +328,17 @@ function Postgres(a, b) {
|
|
|
327
328
|
|
|
328
329
|
async function reserve() {
|
|
329
330
|
const l = await lease(false)
|
|
330
|
-
const sql = Sql(
|
|
331
|
+
const sql = Sql(handler)
|
|
331
332
|
sql.release = () => settle(l, Lease.Released)
|
|
333
|
+
Symbol.dispose && (sql[Symbol.dispose] = () => sql.release())
|
|
334
|
+
Symbol.asyncDispose && (sql[Symbol.asyncDispose] = async() => sql.release())
|
|
332
335
|
sql.stats = stats
|
|
333
336
|
return sql
|
|
337
|
+
|
|
338
|
+
// dd-trace starts query spans only inside function declarations named handler
|
|
339
|
+
function handler(q) {
|
|
340
|
+
send(l, q)
|
|
341
|
+
}
|
|
334
342
|
}
|
|
335
343
|
|
|
336
344
|
async function begin(options, fn) {
|
|
@@ -347,7 +355,7 @@ function Postgres(a, b) {
|
|
|
347
355
|
}
|
|
348
356
|
|
|
349
357
|
async function transaction() {
|
|
350
|
-
await Sql(
|
|
358
|
+
await Sql(handler).unsafe('begin ' + options.replace(/[^a-z ]/ig, ''), []).execute().catch(e => {
|
|
351
359
|
e instanceof PostgresError && settle(l, Lease.Released)
|
|
352
360
|
throw e
|
|
353
361
|
})
|
|
@@ -358,7 +366,7 @@ function Postgres(a, b) {
|
|
|
358
366
|
let result
|
|
359
367
|
l.state = Lease.Settling
|
|
360
368
|
try {
|
|
361
|
-
result = await statement(Sql(q =>
|
|
369
|
+
result = await statement(Sql(q => handler(q, Lease.Settling)))
|
|
362
370
|
} catch (e) {
|
|
363
371
|
settle(l, Lease.Discarded)
|
|
364
372
|
throw e
|
|
@@ -368,7 +376,7 @@ function Postgres(a, b) {
|
|
|
368
376
|
}
|
|
369
377
|
|
|
370
378
|
async function scope(fn, name) {
|
|
371
|
-
const sql = Sql(
|
|
379
|
+
const sql = Sql(track)
|
|
372
380
|
sql.savepoint = savepoint
|
|
373
381
|
sql.prepare = x => {
|
|
374
382
|
if (typeof x !== 'string' || !x || x.includes('\0'))
|
|
@@ -422,11 +430,16 @@ function Postgres(a, b) {
|
|
|
422
430
|
return scope(fn, 's' + savepoints++ + (name ? '_' + name : ''))
|
|
423
431
|
}
|
|
424
432
|
|
|
425
|
-
function
|
|
433
|
+
function track(q) {
|
|
426
434
|
q.catch(e => uncaughtError || (uncaughtError = e))
|
|
427
|
-
|
|
435
|
+
handler(q)
|
|
428
436
|
}
|
|
429
437
|
}
|
|
438
|
+
|
|
439
|
+
// dd-trace starts query spans only inside function declarations named handler
|
|
440
|
+
function handler(q, expected) {
|
|
441
|
+
send(l, q, expected)
|
|
442
|
+
}
|
|
430
443
|
}
|
|
431
444
|
|
|
432
445
|
function move(c, queue) {
|
|
@@ -674,6 +687,7 @@ function parseOptions(a, b) {
|
|
|
674
687
|
prepare : true,
|
|
675
688
|
debug : false,
|
|
676
689
|
fetch_types : true,
|
|
690
|
+
parameter_types : 'server',
|
|
677
691
|
publications : 'alltables',
|
|
678
692
|
target_session_attrs: null
|
|
679
693
|
}
|
|
@@ -688,8 +702,8 @@ function parseOptions(a, b) {
|
|
|
688
702
|
...Object.entries(defaults).reduce(
|
|
689
703
|
(acc, [k, d]) => {
|
|
690
704
|
const value = k in o ? o[k] : k in query
|
|
691
|
-
? (query[k]
|
|
692
|
-
: env['PG' + k.toUpperCase()]
|
|
705
|
+
? off(query[k])
|
|
706
|
+
: env['PG' + k.toUpperCase()] ? off(env['PG' + k.toUpperCase()]) : d
|
|
693
707
|
acc[k] = typeof value === 'string' && ints.includes(k)
|
|
694
708
|
? +value
|
|
695
709
|
: value
|
|
@@ -704,11 +718,13 @@ function parseOptions(a, b) {
|
|
|
704
718
|
},
|
|
705
719
|
types : o.types || {},
|
|
706
720
|
target_session_attrs: tsa(o, url, env),
|
|
721
|
+
parameter_types : parameterTypes(o, url, env),
|
|
707
722
|
onnotice : o.onnotice,
|
|
708
723
|
onnotify : o.onnotify,
|
|
709
724
|
onclose : o.onclose,
|
|
710
725
|
onidle : o.onidle,
|
|
711
726
|
onparameter : o.onparameter,
|
|
727
|
+
ontypemismatch : o.ontypemismatch,
|
|
712
728
|
socket : o.socket,
|
|
713
729
|
transform : parseTransform(o.transform || { undefined: undefined }),
|
|
714
730
|
parameters : {},
|
|
@@ -720,6 +736,10 @@ function parseOptions(a, b) {
|
|
|
720
736
|
return options
|
|
721
737
|
}
|
|
722
738
|
|
|
739
|
+
function off(x) {
|
|
740
|
+
return x === 'disable' || x === 'false' ? false : x
|
|
741
|
+
}
|
|
742
|
+
|
|
723
743
|
function tsa(o, url, env) {
|
|
724
744
|
const x = o.target_session_attrs || url.searchParams.get('target_session_attrs') || env.PGTARGETSESSIONATTRS
|
|
725
745
|
if (!x || ['read-write', 'read-only', 'primary', 'standby', 'prefer-standby'].includes(x))
|
|
@@ -728,6 +748,14 @@ function tsa(o, url, env) {
|
|
|
728
748
|
throw new Error('target_session_attrs ' + x + ' is not supported')
|
|
729
749
|
}
|
|
730
750
|
|
|
751
|
+
function parameterTypes(o, url, env) {
|
|
752
|
+
const x = o.parameter_types || url.searchParams.get('parameter_types') || env.PGPARAMETER_TYPES || 'server'
|
|
753
|
+
if (['server', 'client', 'warn'].includes(x))
|
|
754
|
+
return x
|
|
755
|
+
|
|
756
|
+
throw new Error('parameter_types ' + x + ' is not supported')
|
|
757
|
+
}
|
|
758
|
+
|
|
731
759
|
function max_lifetime() {
|
|
732
760
|
return 60 * (30 + Math.random() * 30)
|
|
733
761
|
}
|
package/cjs/src/query.js
CHANGED
|
@@ -23,16 +23,9 @@ const Query = module.exports.Query = class Query extends Promise {
|
|
|
23
23
|
this.state = null
|
|
24
24
|
this.statement = null
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
resolve(x)
|
|
30
|
-
}
|
|
31
|
-
this.reject = x => {
|
|
32
|
-
this.active = false
|
|
33
|
-
this.settled = true
|
|
34
|
-
reject(x)
|
|
35
|
-
}
|
|
26
|
+
// dd-trace's load-time rewrite only accepts single-expression arrows here
|
|
27
|
+
this.resolve = x => (this.active = false, this.settled = true, resolve(x))
|
|
28
|
+
this.reject = x => (this.active = false, this.settled = true, reject(x))
|
|
36
29
|
|
|
37
30
|
this.active = false
|
|
38
31
|
this.settled = false
|
|
@@ -62,6 +55,7 @@ const Query = module.exports.Query = class Query extends Promise {
|
|
|
62
55
|
if (!this.canceller || this.settled)
|
|
63
56
|
return Promise.resolve()
|
|
64
57
|
|
|
58
|
+
Promise.prototype.then.call(this, undefined, () => undefined)
|
|
65
59
|
const cancelled = this.canceller(this)
|
|
66
60
|
this.canceller = null
|
|
67
61
|
cancelled.catch(() => undefined)
|
package/cjs/src/types.js
CHANGED
|
@@ -248,6 +248,11 @@ const inferType = module.exports.inferType = function inferType(x) {
|
|
|
248
248
|
)
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
module.exports.clientSerialize = clientSerialize;function clientSerialize(x) {
|
|
252
|
+
const proto = typeof x === 'object' && Object.getPrototypeOf(x)
|
|
253
|
+
return proto === Object.prototype || proto === null ? JSON.stringify(x) : '' + x
|
|
254
|
+
}
|
|
255
|
+
|
|
251
256
|
const escapeBackslash = /\\/g
|
|
252
257
|
const escapeQuote = /"/g
|
|
253
258
|
|
|
@@ -341,14 +346,14 @@ function arrayParserLoop(s, x, parser, typarray) {
|
|
|
341
346
|
const toCamel = module.exports.toCamel = x => {
|
|
342
347
|
let str = x[0]
|
|
343
348
|
for (let i = 1; i < x.length; i++)
|
|
344
|
-
str += x[i] === '_' ? x[++i].toUpperCase() : x[i]
|
|
349
|
+
str += x[i] === '_' && i + 1 < x.length ? x[++i].toUpperCase() : x[i]
|
|
345
350
|
return str
|
|
346
351
|
}
|
|
347
352
|
|
|
348
353
|
const toPascal = module.exports.toPascal = x => {
|
|
349
354
|
let str = x[0].toUpperCase()
|
|
350
355
|
for (let i = 1; i < x.length; i++)
|
|
351
|
-
str += x[i] === '_' ? x[++i].toUpperCase() : x[i]
|
|
356
|
+
str += x[i] === '_' && i + 1 < x.length ? x[++i].toUpperCase() : x[i]
|
|
352
357
|
return str
|
|
353
358
|
}
|
|
354
359
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@steadybrew/postgresjs",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "PostgreSQL client for Node.js and Deno, independently maintained by Steady Brew",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"types": "types/index.d.ts",
|
|
25
25
|
"typings": "types/index.d.ts",
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=
|
|
27
|
+
"node": ">=22"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"build": "npm run build:cjs && npm run build:deno && npm run build:cf",
|
|
@@ -32,9 +32,10 @@
|
|
|
32
32
|
"build:deno": "node transpile.deno.js",
|
|
33
33
|
"build:cf": "node transpile.cf.js",
|
|
34
34
|
"test": "npm run test:startup && npm run test:esm && npm run test:cjs && npm run test:deno",
|
|
35
|
-
"test:esm": "node tests-startup/run.js --integration && node tests/index.js",
|
|
35
|
+
"test:esm": "node tests-startup/run.js --integration && node tests/index.js && node tests-startup/run.js --reports",
|
|
36
36
|
"test:startup": "node tests-startup/run.js",
|
|
37
|
-
"test:
|
|
37
|
+
"test:tracing": "node tests-tracing/run.js",
|
|
38
|
+
"test:cjs": "npm run build:cjs && node tests-startup/run.js --integration --cjs && cd cjs/tests && node index.js && cd ../../ && node tests-startup/run.js --reports --cjs",
|
|
38
39
|
"test:deno": "npm run test:deno-socket && npm run build:deno && cd deno/tests && deno run --no-lock --allow-all --unsafely-ignore-certificate-errors index.js && cd ../../",
|
|
39
40
|
"lint": "eslint src && eslint tests && eslint tests-startup --ext .js,.mjs",
|
|
40
41
|
"prepare": "npm run build",
|